@assemble-dev/providers 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1400 -241
- package/dist/index.d.cts +159 -6
- package/dist/index.d.ts +159 -6
- package/dist/index.js +1360 -229
- package/package.json +3 -3
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,6 +67,7 @@ __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,
|
|
@@ -60,6 +76,8 @@ __export(index_exports, {
|
|
|
60
76
|
joinSystemMessageText: () => joinSystemMessageText,
|
|
61
77
|
mapAnthropicResponseToChatCompletionResult: () => mapAnthropicResponseToChatCompletionResult,
|
|
62
78
|
mapAnthropicUsageToTokenUsage: () => mapAnthropicUsageToTokenUsage,
|
|
79
|
+
mapAzureOpenAiResponseToChatCompletionResult: () => mapAzureOpenAiResponseToChatCompletionResult,
|
|
80
|
+
mapAzureOpenAiUsageToTokenUsage: () => mapAzureOpenAiUsageToTokenUsage,
|
|
63
81
|
mapChatMessageToAnthropicRequestMessage: () => mapChatMessageToAnthropicRequestMessage,
|
|
64
82
|
mapChatMessageToOpenAiRequestMessage: () => mapChatMessageToOpenAiRequestMessage,
|
|
65
83
|
mapModelToolChoiceToAnthropicToolChoice: () => mapModelToolChoiceToAnthropicToolChoice,
|
|
@@ -69,13 +87,23 @@ __export(index_exports, {
|
|
|
69
87
|
mergeProviderRequestExtraBody: () => mergeProviderRequestExtraBody,
|
|
70
88
|
mockModel: () => mockModel,
|
|
71
89
|
normalizeAnthropicStopReason: () => normalizeAnthropicStopReason,
|
|
90
|
+
normalizeAzureOpenAiFinishReason: () => normalizeAzureOpenAiFinishReason,
|
|
91
|
+
openAiStructuredOutputSchemaName: () => openAiStructuredOutputSchemaName,
|
|
72
92
|
openai: () => openai,
|
|
73
93
|
parseAnthropicBatchStructuredContent: () => parseAnthropicBatchStructuredContent,
|
|
74
94
|
parseAnthropicStreamEvents: () => parseAnthropicStreamEvents,
|
|
75
95
|
parseAnthropicToolInputJson: () => parseAnthropicToolInputJson,
|
|
96
|
+
parseAzureOpenAiStreamEvents: () => parseAzureOpenAiStreamEvents,
|
|
97
|
+
parseAzureOpenAiToolArgumentsJson: () => parseAzureOpenAiToolArgumentsJson,
|
|
76
98
|
resolveAnthropicPromptCachingSettings: () => resolveAnthropicPromptCachingSettings,
|
|
99
|
+
resolveBedrockCredentials: () => resolveBedrockCredentials,
|
|
77
100
|
resolveProviderApiKey: () => resolveProviderApiKey,
|
|
78
|
-
|
|
101
|
+
sanitizeJsonSchemaForAnthropicStructuredOutput: () => sanitizeJsonSchemaForAnthropicStructuredOutput,
|
|
102
|
+
sanitizeJsonSchemaForGeminiResponseSchema: () => sanitizeJsonSchemaForGeminiResponseSchema,
|
|
103
|
+
sanitizeJsonSchemaForOpenAiStructuredOutput: () => sanitizeJsonSchemaForOpenAiStructuredOutput,
|
|
104
|
+
signAwsRequestWithSigV4: () => signAwsRequestWithSigV4,
|
|
105
|
+
streamAnthropicChatCompletion: () => streamAnthropicChatCompletion,
|
|
106
|
+
streamAzureOpenAiChatCompletion: () => streamAzureOpenAiChatCompletion
|
|
79
107
|
});
|
|
80
108
|
module.exports = __toCommonJS(index_exports);
|
|
81
109
|
|
|
@@ -134,14 +162,222 @@ function extractMessageText(message) {
|
|
|
134
162
|
}
|
|
135
163
|
|
|
136
164
|
// src/openai-adapter.ts
|
|
137
|
-
var
|
|
138
|
-
var
|
|
139
|
-
var
|
|
140
|
-
var
|
|
165
|
+
var import_zod4 = require("zod");
|
|
166
|
+
var import_errors16 = require("@assemble-dev/shared-types/errors");
|
|
167
|
+
var import_json4 = require("@assemble-dev/shared-types/json");
|
|
168
|
+
var import_errors17 = require("@assemble-dev/shared-utils/errors");
|
|
141
169
|
|
|
142
170
|
// src/openai-request-mapping.ts
|
|
171
|
+
var import_errors3 = require("@assemble-dev/shared-types/errors");
|
|
172
|
+
var import_errors4 = require("@assemble-dev/shared-utils/errors");
|
|
173
|
+
|
|
174
|
+
// src/structured-output-json-schema.ts
|
|
175
|
+
var import_zod2 = require("zod");
|
|
143
176
|
var import_errors = require("@assemble-dev/shared-types/errors");
|
|
177
|
+
var import_json2 = require("@assemble-dev/shared-types/json");
|
|
144
178
|
var import_errors2 = require("@assemble-dev/shared-utils/errors");
|
|
179
|
+
|
|
180
|
+
// src/json-schema-tree.ts
|
|
181
|
+
var schemaMapKeywords = ["properties", "$defs"];
|
|
182
|
+
var schemaListKeywords = ["anyOf", "oneOf", "allOf", "prefixItems"];
|
|
183
|
+
var schemaValueKeywords = [
|
|
184
|
+
"items",
|
|
185
|
+
"additionalProperties",
|
|
186
|
+
"not",
|
|
187
|
+
"if",
|
|
188
|
+
"then",
|
|
189
|
+
"else",
|
|
190
|
+
"contains",
|
|
191
|
+
"propertyNames"
|
|
192
|
+
];
|
|
193
|
+
function isJsonObject(value) {
|
|
194
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
195
|
+
}
|
|
196
|
+
function transformJsonSchemaNode(node, transformNode) {
|
|
197
|
+
const result = { ...transformNode({ ...node }) };
|
|
198
|
+
for (const keyword of schemaMapKeywords) {
|
|
199
|
+
const mapValue = result[keyword];
|
|
200
|
+
if (mapValue !== void 0 && isJsonObject(mapValue)) {
|
|
201
|
+
result[keyword] = transformJsonSchemaMap(mapValue, transformNode);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
for (const keyword of schemaListKeywords) {
|
|
205
|
+
const listValue = result[keyword];
|
|
206
|
+
if (Array.isArray(listValue)) {
|
|
207
|
+
result[keyword] = listValue.map(
|
|
208
|
+
(entry) => isJsonObject(entry) ? transformJsonSchemaNode(entry, transformNode) : entry
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
for (const keyword of schemaValueKeywords) {
|
|
213
|
+
const schemaValue = result[keyword];
|
|
214
|
+
if (schemaValue !== void 0 && isJsonObject(schemaValue)) {
|
|
215
|
+
result[keyword] = transformJsonSchemaNode(schemaValue, transformNode);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
function transformJsonSchemaMap(schemaMap, transformNode) {
|
|
221
|
+
const result = {};
|
|
222
|
+
for (const [schemaName, schemaValue] of Object.entries(schemaMap)) {
|
|
223
|
+
result[schemaName] = isJsonObject(schemaValue) ? transformJsonSchemaNode(schemaValue, transformNode) : schemaValue;
|
|
224
|
+
}
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
function inlineJsonSchemaReferences(root) {
|
|
228
|
+
const rootDefinitions = root["$defs"];
|
|
229
|
+
const definitions = rootDefinitions !== void 0 && isJsonObject(rootDefinitions) ? rootDefinitions : {};
|
|
230
|
+
const resolvedRoot = resolveJsonSchemaReferences(
|
|
231
|
+
root,
|
|
232
|
+
definitions,
|
|
233
|
+
/* @__PURE__ */ new Set()
|
|
234
|
+
);
|
|
235
|
+
return isJsonObject(resolvedRoot) ? resolvedRoot : {};
|
|
236
|
+
}
|
|
237
|
+
function resolveJsonSchemaReferences(value, definitions, activeReferences) {
|
|
238
|
+
if (Array.isArray(value)) {
|
|
239
|
+
return value.map(
|
|
240
|
+
(entry) => resolveJsonSchemaReferences(entry, definitions, activeReferences)
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
if (!isJsonObject(value)) {
|
|
244
|
+
return value;
|
|
245
|
+
}
|
|
246
|
+
const referenceTarget = value["$ref"];
|
|
247
|
+
if (typeof referenceTarget === "string") {
|
|
248
|
+
return resolveJsonSchemaReferenceTarget(
|
|
249
|
+
referenceTarget,
|
|
250
|
+
definitions,
|
|
251
|
+
activeReferences
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
const result = {};
|
|
255
|
+
for (const [key, entryValue] of Object.entries(value)) {
|
|
256
|
+
if (key !== "$defs") {
|
|
257
|
+
result[key] = resolveJsonSchemaReferences(
|
|
258
|
+
entryValue,
|
|
259
|
+
definitions,
|
|
260
|
+
activeReferences
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
266
|
+
function resolveJsonSchemaReferenceTarget(referenceTarget, definitions, activeReferences) {
|
|
267
|
+
if (activeReferences.has(referenceTarget)) {
|
|
268
|
+
return {};
|
|
269
|
+
}
|
|
270
|
+
const definitionsPrefix = "#/$defs/";
|
|
271
|
+
if (!referenceTarget.startsWith(definitionsPrefix)) {
|
|
272
|
+
return {};
|
|
273
|
+
}
|
|
274
|
+
const definition = definitions[referenceTarget.slice(definitionsPrefix.length)];
|
|
275
|
+
if (definition === void 0 || !isJsonObject(definition)) {
|
|
276
|
+
return {};
|
|
277
|
+
}
|
|
278
|
+
return resolveJsonSchemaReferences(
|
|
279
|
+
definition,
|
|
280
|
+
definitions,
|
|
281
|
+
/* @__PURE__ */ new Set([...activeReferences, referenceTarget])
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
function removeJsonSchemaKeywords(node, keywords) {
|
|
285
|
+
const result = {};
|
|
286
|
+
for (const [key, value] of Object.entries(node)) {
|
|
287
|
+
if (!keywords.includes(key)) {
|
|
288
|
+
result[key] = value;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// src/structured-output-json-schema.ts
|
|
295
|
+
var openAiStructuredOutputSchemaName = "structured_output";
|
|
296
|
+
var schemaMetadataKeywords = ["$schema", "$id"];
|
|
297
|
+
var anthropicUnsupportedSchemaKeywords = [
|
|
298
|
+
...schemaMetadataKeywords,
|
|
299
|
+
"minimum",
|
|
300
|
+
"maximum",
|
|
301
|
+
"exclusiveMinimum",
|
|
302
|
+
"exclusiveMaximum",
|
|
303
|
+
"minLength",
|
|
304
|
+
"maxLength",
|
|
305
|
+
"multipleOf"
|
|
306
|
+
];
|
|
307
|
+
var openAiUnsupportedSchemaKeywords = [
|
|
308
|
+
...anthropicUnsupportedSchemaKeywords,
|
|
309
|
+
"pattern",
|
|
310
|
+
"format",
|
|
311
|
+
"minItems",
|
|
312
|
+
"maxItems",
|
|
313
|
+
"uniqueItems",
|
|
314
|
+
"default"
|
|
315
|
+
];
|
|
316
|
+
function convertZodSchemaToJsonSchema(schema) {
|
|
317
|
+
try {
|
|
318
|
+
return import_json2.JsonObjectSchema.parse(import_zod2.z.toJSONSchema(schema, { io: "input" }));
|
|
319
|
+
} catch (error) {
|
|
320
|
+
throw new import_errors2.AppError({
|
|
321
|
+
code: import_errors.AppErrorCode.BadRequest,
|
|
322
|
+
message: "Structured output schema could not be converted to JSON Schema",
|
|
323
|
+
statusCode: 400,
|
|
324
|
+
cause: error instanceof Error ? error : void 0
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
function buildAnthropicStructuredOutputJsonSchema(schema) {
|
|
329
|
+
return sanitizeJsonSchemaForAnthropicStructuredOutput(
|
|
330
|
+
convertZodSchemaToJsonSchema(schema)
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
function sanitizeJsonSchemaForAnthropicStructuredOutput(jsonSchema) {
|
|
334
|
+
return transformJsonSchemaNode(
|
|
335
|
+
inlineJsonSchemaReferences(jsonSchema),
|
|
336
|
+
sanitizeAnthropicSchemaNode
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
function buildOpenAiStructuredOutputJsonSchema(schema) {
|
|
340
|
+
return sanitizeJsonSchemaForOpenAiStructuredOutput(
|
|
341
|
+
convertZodSchemaToJsonSchema(schema)
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
function sanitizeJsonSchemaForOpenAiStructuredOutput(jsonSchema) {
|
|
345
|
+
return transformJsonSchemaNode(jsonSchema, sanitizeOpenAiSchemaNode);
|
|
346
|
+
}
|
|
347
|
+
function sanitizeAnthropicSchemaNode(node) {
|
|
348
|
+
const sanitized = removeJsonSchemaKeywords(
|
|
349
|
+
node,
|
|
350
|
+
anthropicUnsupportedSchemaKeywords
|
|
351
|
+
);
|
|
352
|
+
if (sanitized["type"] === "object") {
|
|
353
|
+
sanitized["additionalProperties"] = false;
|
|
354
|
+
}
|
|
355
|
+
return sanitized;
|
|
356
|
+
}
|
|
357
|
+
function sanitizeOpenAiSchemaNode(node) {
|
|
358
|
+
const sanitized = removeJsonSchemaKeywords(
|
|
359
|
+
node,
|
|
360
|
+
openAiUnsupportedSchemaKeywords
|
|
361
|
+
);
|
|
362
|
+
if (sanitized["type"] !== "object") {
|
|
363
|
+
return sanitized;
|
|
364
|
+
}
|
|
365
|
+
sanitized["additionalProperties"] = false;
|
|
366
|
+
const propertyNames = listSchemaPropertyNames(sanitized);
|
|
367
|
+
if (propertyNames.length > 0) {
|
|
368
|
+
sanitized["required"] = propertyNames;
|
|
369
|
+
}
|
|
370
|
+
return sanitized;
|
|
371
|
+
}
|
|
372
|
+
function listSchemaPropertyNames(node) {
|
|
373
|
+
const properties = node["properties"];
|
|
374
|
+
if (properties === void 0 || !isJsonObject(properties)) {
|
|
375
|
+
return [];
|
|
376
|
+
}
|
|
377
|
+
return Object.keys(properties);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// src/openai-request-mapping.ts
|
|
145
381
|
function buildOpenAiRequestBody(model, input) {
|
|
146
382
|
const requestBody = {
|
|
147
383
|
model,
|
|
@@ -153,7 +389,16 @@ function buildOpenAiRequestBody(model, input) {
|
|
|
153
389
|
if (input.maxOutputTokens !== void 0) {
|
|
154
390
|
requestBody.max_tokens = input.maxOutputTokens;
|
|
155
391
|
}
|
|
156
|
-
if (input.
|
|
392
|
+
if (input.structuredOutputJsonSchema !== void 0) {
|
|
393
|
+
requestBody.response_format = {
|
|
394
|
+
type: "json_schema",
|
|
395
|
+
json_schema: {
|
|
396
|
+
name: openAiStructuredOutputSchemaName,
|
|
397
|
+
strict: true,
|
|
398
|
+
schema: input.structuredOutputJsonSchema
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
} else if (input.requireJsonObjectResponse === true) {
|
|
157
402
|
requestBody.response_format = { type: "json_object" };
|
|
158
403
|
}
|
|
159
404
|
if (input.tools !== void 0 && input.tools.length > 0) {
|
|
@@ -239,17 +484,17 @@ function mapMessageContentBlockToOpenAiContentPart(contentBlock) {
|
|
|
239
484
|
}
|
|
240
485
|
};
|
|
241
486
|
}
|
|
242
|
-
throw new
|
|
243
|
-
code:
|
|
487
|
+
throw new import_errors4.AppError({
|
|
488
|
+
code: import_errors3.AppErrorCode.ValidationFailed,
|
|
244
489
|
message: "OpenAI adapter does not support document content blocks in chat messages",
|
|
245
490
|
statusCode: 400
|
|
246
491
|
});
|
|
247
492
|
}
|
|
248
493
|
|
|
249
494
|
// src/parse-structured-json.ts
|
|
250
|
-
var
|
|
251
|
-
var
|
|
252
|
-
var
|
|
495
|
+
var import_errors5 = require("@assemble-dev/shared-types/errors");
|
|
496
|
+
var import_json3 = require("@assemble-dev/shared-types/json");
|
|
497
|
+
var import_errors6 = require("@assemble-dev/shared-utils/errors");
|
|
253
498
|
var markdownCodeFencePattern = /^```[A-Za-z]*\s*\n?([\s\S]*?)\n?```$/;
|
|
254
499
|
function parseStructuredJsonText(text, schema) {
|
|
255
500
|
return schema.parse(parseJsonText(stripMarkdownCodeFences(text)));
|
|
@@ -264,10 +509,10 @@ function stripMarkdownCodeFences(text) {
|
|
|
264
509
|
}
|
|
265
510
|
function parseJsonText(text) {
|
|
266
511
|
try {
|
|
267
|
-
return
|
|
512
|
+
return import_json3.JsonValueSchema.parse(JSON.parse(text));
|
|
268
513
|
} catch (error) {
|
|
269
|
-
throw new
|
|
270
|
-
code:
|
|
514
|
+
throw new import_errors6.AppError({
|
|
515
|
+
code: import_errors5.AppErrorCode.ValidationFailed,
|
|
271
516
|
message: "Structured output was not valid JSON",
|
|
272
517
|
statusCode: 422,
|
|
273
518
|
cause: error instanceof Error ? error : void 0
|
|
@@ -276,9 +521,9 @@ function parseJsonText(text) {
|
|
|
276
521
|
}
|
|
277
522
|
|
|
278
523
|
// src/provider-api-key.ts
|
|
279
|
-
var
|
|
280
|
-
var
|
|
281
|
-
var
|
|
524
|
+
var import_zod3 = require("zod");
|
|
525
|
+
var import_errors7 = require("@assemble-dev/shared-types/errors");
|
|
526
|
+
var import_errors8 = require("@assemble-dev/shared-utils/errors");
|
|
282
527
|
var import_provider_keys = require("@assemble-dev/shared-utils/provider-keys");
|
|
283
528
|
function resolveProviderApiKey(input) {
|
|
284
529
|
if (input.apiKey !== void 0 && input.apiKey.length > 0) {
|
|
@@ -291,8 +536,8 @@ function resolveProviderApiKey(input) {
|
|
|
291
536
|
}
|
|
292
537
|
function resolveNamedProviderApiKeyFromEnv(input, apiKeyName) {
|
|
293
538
|
if (!(0, import_provider_keys.validateProviderApiKeyName)(apiKeyName)) {
|
|
294
|
-
throw new
|
|
295
|
-
code:
|
|
539
|
+
throw new import_errors8.AppError({
|
|
540
|
+
code: import_errors7.AppErrorCode.BadRequest,
|
|
296
541
|
message: `Invalid ${input.providerLabel} apiKeyName "${apiKeyName}". Expected ${import_provider_keys.expectedProviderApiKeyNameFormat}.`,
|
|
297
542
|
statusCode: 400
|
|
298
543
|
});
|
|
@@ -300,8 +545,8 @@ function resolveNamedProviderApiKeyFromEnv(input, apiKeyName) {
|
|
|
300
545
|
const envVarName = (0, import_provider_keys.buildNamedApiKeyEnvVarName)(input.baseEnvVarName, apiKeyName);
|
|
301
546
|
const envApiKey = readEnvironmentVariable(envVarName);
|
|
302
547
|
if (envApiKey === void 0 || envApiKey.length === 0) {
|
|
303
|
-
throw new
|
|
304
|
-
code:
|
|
548
|
+
throw new import_errors8.AppError({
|
|
549
|
+
code: import_errors7.AppErrorCode.Unauthorized,
|
|
305
550
|
message: `${input.providerLabel} API key named "${apiKeyName}" is missing. Set the ${envVarName} environment variable or pass apiKey to ${input.adapterFunctionName}.`,
|
|
306
551
|
statusCode: 401
|
|
307
552
|
});
|
|
@@ -311,8 +556,8 @@ function resolveNamedProviderApiKeyFromEnv(input, apiKeyName) {
|
|
|
311
556
|
function resolveBaseProviderApiKeyFromEnv(input) {
|
|
312
557
|
const envApiKey = readEnvironmentVariable(input.baseEnvVarName);
|
|
313
558
|
if (envApiKey === void 0 || envApiKey.length === 0) {
|
|
314
|
-
throw new
|
|
315
|
-
code:
|
|
559
|
+
throw new import_errors8.AppError({
|
|
560
|
+
code: import_errors7.AppErrorCode.Unauthorized,
|
|
316
561
|
message: `${input.providerLabel} API key is missing. Pass apiKey to ${input.adapterFunctionName} or set the ${input.baseEnvVarName} environment variable.`,
|
|
317
562
|
statusCode: 401
|
|
318
563
|
});
|
|
@@ -320,19 +565,19 @@ function resolveBaseProviderApiKeyFromEnv(input) {
|
|
|
320
565
|
return envApiKey;
|
|
321
566
|
}
|
|
322
567
|
function readEnvironmentVariable(envVarName) {
|
|
323
|
-
const parsedEnv =
|
|
568
|
+
const parsedEnv = import_zod3.z.object({ [envVarName]: import_zod3.z.string().optional() }).parse(process.env);
|
|
324
569
|
return parsedEnv[envVarName];
|
|
325
570
|
}
|
|
326
571
|
|
|
327
572
|
// src/provider-cancellation.ts
|
|
328
|
-
var
|
|
329
|
-
var
|
|
573
|
+
var import_errors9 = require("@assemble-dev/shared-types/errors");
|
|
574
|
+
var import_errors10 = require("@assemble-dev/shared-utils/errors");
|
|
330
575
|
function isAbortError(error) {
|
|
331
576
|
return error.name === "AbortError";
|
|
332
577
|
}
|
|
333
578
|
function buildProviderCanceledError(providerLabel) {
|
|
334
|
-
return new
|
|
335
|
-
code:
|
|
579
|
+
return new import_errors10.AppError({
|
|
580
|
+
code: import_errors9.AppErrorCode.Canceled,
|
|
336
581
|
message: `${providerLabel} request was canceled`,
|
|
337
582
|
statusCode: 499
|
|
338
583
|
});
|
|
@@ -358,18 +603,18 @@ function mergeProviderRequestExtraBody(requestBody, adapterExtraBody, requestExt
|
|
|
358
603
|
}
|
|
359
604
|
|
|
360
605
|
// src/provider-fallback.ts
|
|
361
|
-
var
|
|
606
|
+
var import_errors13 = require("@assemble-dev/shared-utils/errors");
|
|
362
607
|
|
|
363
608
|
// src/provider-retry.ts
|
|
364
|
-
var
|
|
365
|
-
var
|
|
609
|
+
var import_errors11 = require("@assemble-dev/shared-types/errors");
|
|
610
|
+
var import_errors12 = require("@assemble-dev/shared-utils/errors");
|
|
366
611
|
var defaultProviderRetryMaxAttempts = 3;
|
|
367
612
|
var defaultProviderRetryInitialDelayMs = 500;
|
|
368
613
|
var defaultProviderRetryMaxDelayMs = 8e3;
|
|
369
614
|
var retryableAppErrorCodes = /* @__PURE__ */ new Set([
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
615
|
+
import_errors11.AppErrorCode.RateLimited,
|
|
616
|
+
import_errors11.AppErrorCode.ServiceUnavailable,
|
|
617
|
+
import_errors11.AppErrorCode.InternalServerError
|
|
373
618
|
]);
|
|
374
619
|
function isRetryableProviderAppError(appError) {
|
|
375
620
|
return retryableAppErrorCodes.has(appError.code);
|
|
@@ -384,7 +629,7 @@ async function executeProviderCallWithRetry(retryOptions, executeCall, waitFor)
|
|
|
384
629
|
try {
|
|
385
630
|
return await executeCall();
|
|
386
631
|
} catch (error) {
|
|
387
|
-
if (error instanceof
|
|
632
|
+
if (error instanceof import_errors12.AppError && !isRetryableProviderAppError(error)) {
|
|
388
633
|
throw error;
|
|
389
634
|
}
|
|
390
635
|
if (error instanceof Error && isAbortError(error)) {
|
|
@@ -418,7 +663,7 @@ async function executeProviderCallWithModelFallback(fallbackModel, executePrimar
|
|
|
418
663
|
if (fallbackModel === void 0) {
|
|
419
664
|
throw error;
|
|
420
665
|
}
|
|
421
|
-
if (error instanceof
|
|
666
|
+
if (error instanceof import_errors13.AppError && !isRetryableProviderAppError(error)) {
|
|
422
667
|
throw error;
|
|
423
668
|
}
|
|
424
669
|
if (error instanceof Error && isAbortError(error)) {
|
|
@@ -429,11 +674,11 @@ async function executeProviderCallWithModelFallback(fallbackModel, executePrimar
|
|
|
429
674
|
}
|
|
430
675
|
|
|
431
676
|
// src/provider-status-error.ts
|
|
432
|
-
var
|
|
433
|
-
var
|
|
677
|
+
var import_errors14 = require("@assemble-dev/shared-types/errors");
|
|
678
|
+
var import_errors15 = require("@assemble-dev/shared-utils/errors");
|
|
434
679
|
function buildProviderStatusError(providerLabel, providerStatus) {
|
|
435
680
|
const code = mapProviderStatusToAppErrorCode(providerStatus);
|
|
436
|
-
return new
|
|
681
|
+
return new import_errors15.AppError({
|
|
437
682
|
code,
|
|
438
683
|
message: `${providerLabel} request failed with status ${String(providerStatus)}`,
|
|
439
684
|
statusCode: mapAppErrorCodeToStatusCode(code),
|
|
@@ -441,44 +686,44 @@ function buildProviderStatusError(providerLabel, providerStatus) {
|
|
|
441
686
|
});
|
|
442
687
|
}
|
|
443
688
|
function buildProviderInvalidResponseError(providerLabel, expectedShapeDescription) {
|
|
444
|
-
return new
|
|
445
|
-
code:
|
|
689
|
+
return new import_errors15.AppError({
|
|
690
|
+
code: import_errors14.AppErrorCode.ValidationFailed,
|
|
446
691
|
message: `${providerLabel} response did not match the expected ${expectedShapeDescription} shape`,
|
|
447
692
|
statusCode: 502
|
|
448
693
|
});
|
|
449
694
|
}
|
|
450
695
|
function mapProviderStatusToAppErrorCode(providerStatus) {
|
|
451
696
|
if (providerStatus === 400) {
|
|
452
|
-
return
|
|
697
|
+
return import_errors14.AppErrorCode.BadRequest;
|
|
453
698
|
}
|
|
454
699
|
if (providerStatus === 401) {
|
|
455
|
-
return
|
|
700
|
+
return import_errors14.AppErrorCode.Unauthorized;
|
|
456
701
|
}
|
|
457
702
|
if (providerStatus === 403) {
|
|
458
|
-
return
|
|
703
|
+
return import_errors14.AppErrorCode.Forbidden;
|
|
459
704
|
}
|
|
460
705
|
if (providerStatus === 404) {
|
|
461
|
-
return
|
|
706
|
+
return import_errors14.AppErrorCode.NotFound;
|
|
462
707
|
}
|
|
463
708
|
if (providerStatus === 429) {
|
|
464
|
-
return
|
|
709
|
+
return import_errors14.AppErrorCode.RateLimited;
|
|
465
710
|
}
|
|
466
|
-
return
|
|
711
|
+
return import_errors14.AppErrorCode.InternalServerError;
|
|
467
712
|
}
|
|
468
713
|
function mapAppErrorCodeToStatusCode(code) {
|
|
469
|
-
if (code ===
|
|
714
|
+
if (code === import_errors14.AppErrorCode.BadRequest) {
|
|
470
715
|
return 400;
|
|
471
716
|
}
|
|
472
|
-
if (code ===
|
|
717
|
+
if (code === import_errors14.AppErrorCode.Unauthorized) {
|
|
473
718
|
return 401;
|
|
474
719
|
}
|
|
475
|
-
if (code ===
|
|
720
|
+
if (code === import_errors14.AppErrorCode.Forbidden) {
|
|
476
721
|
return 403;
|
|
477
722
|
}
|
|
478
|
-
if (code ===
|
|
723
|
+
if (code === import_errors14.AppErrorCode.NotFound) {
|
|
479
724
|
return 404;
|
|
480
725
|
}
|
|
481
|
-
if (code ===
|
|
726
|
+
if (code === import_errors14.AppErrorCode.RateLimited) {
|
|
482
727
|
return 429;
|
|
483
728
|
}
|
|
484
729
|
return 500;
|
|
@@ -486,33 +731,29 @@ function mapAppErrorCodeToStatusCode(code) {
|
|
|
486
731
|
|
|
487
732
|
// src/openai-adapter.ts
|
|
488
733
|
var defaultOpenAiBaseUrl = "https://api.openai.com/v1";
|
|
489
|
-
var OpenAiResponseToolCallSchema =
|
|
490
|
-
id:
|
|
491
|
-
function:
|
|
492
|
-
name:
|
|
493
|
-
arguments:
|
|
734
|
+
var OpenAiResponseToolCallSchema = import_zod4.z.object({
|
|
735
|
+
id: import_zod4.z.string(),
|
|
736
|
+
function: import_zod4.z.object({
|
|
737
|
+
name: import_zod4.z.string(),
|
|
738
|
+
arguments: import_zod4.z.string()
|
|
494
739
|
})
|
|
495
740
|
});
|
|
496
|
-
var OpenAiChatCompletionResponseSchema =
|
|
497
|
-
choices:
|
|
498
|
-
|
|
499
|
-
message:
|
|
500
|
-
content:
|
|
501
|
-
tool_calls:
|
|
741
|
+
var OpenAiChatCompletionResponseSchema = import_zod4.z.object({
|
|
742
|
+
choices: import_zod4.z.array(
|
|
743
|
+
import_zod4.z.object({
|
|
744
|
+
message: import_zod4.z.object({
|
|
745
|
+
content: import_zod4.z.string().nullable(),
|
|
746
|
+
tool_calls: import_zod4.z.array(OpenAiResponseToolCallSchema).optional()
|
|
502
747
|
}),
|
|
503
|
-
finish_reason:
|
|
748
|
+
finish_reason: import_zod4.z.string().nullable().optional()
|
|
504
749
|
})
|
|
505
750
|
).min(1),
|
|
506
|
-
usage:
|
|
507
|
-
prompt_tokens:
|
|
508
|
-
completion_tokens:
|
|
509
|
-
total_tokens:
|
|
751
|
+
usage: import_zod4.z.object({
|
|
752
|
+
prompt_tokens: import_zod4.z.number().int().nonnegative(),
|
|
753
|
+
completion_tokens: import_zod4.z.number().int().nonnegative(),
|
|
754
|
+
total_tokens: import_zod4.z.number().int().nonnegative()
|
|
510
755
|
})
|
|
511
756
|
});
|
|
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
757
|
function openai(options) {
|
|
517
758
|
return {
|
|
518
759
|
name: `openai:${options.model}`,
|
|
@@ -521,7 +762,6 @@ function openai(options) {
|
|
|
521
762
|
messages: request.messages,
|
|
522
763
|
temperature: request.temperature ?? options.temperature,
|
|
523
764
|
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
524
|
-
requireJsonObjectResponse: false,
|
|
525
765
|
tools: request.tools,
|
|
526
766
|
toolChoice: request.toolChoice,
|
|
527
767
|
abortSignal: request.abortSignal,
|
|
@@ -530,10 +770,12 @@ function openai(options) {
|
|
|
530
770
|
},
|
|
531
771
|
async generateStructuredOutput(request) {
|
|
532
772
|
const completion = await executeOpenAiAdapterCall(options, {
|
|
533
|
-
messages:
|
|
773
|
+
messages: request.messages,
|
|
534
774
|
temperature: request.temperature ?? options.temperature,
|
|
535
775
|
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
536
|
-
|
|
776
|
+
structuredOutputJsonSchema: buildOpenAiStructuredOutputJsonSchema(
|
|
777
|
+
request.schema
|
|
778
|
+
),
|
|
537
779
|
abortSignal: request.abortSignal
|
|
538
780
|
});
|
|
539
781
|
return {
|
|
@@ -626,10 +868,10 @@ function parseOpenAiToolArgumentsJson(argumentsJsonText) {
|
|
|
626
868
|
return {};
|
|
627
869
|
}
|
|
628
870
|
try {
|
|
629
|
-
return
|
|
871
|
+
return import_json4.JsonValueSchema.parse(JSON.parse(argumentsJsonText));
|
|
630
872
|
} catch (error) {
|
|
631
|
-
throw new
|
|
632
|
-
code:
|
|
873
|
+
throw new import_errors17.AppError({
|
|
874
|
+
code: import_errors16.AppErrorCode.ValidationFailed,
|
|
633
875
|
message: "OpenAI tool call arguments were not valid JSON",
|
|
634
876
|
statusCode: 502,
|
|
635
877
|
cause: error instanceof Error ? error : void 0
|
|
@@ -651,8 +893,8 @@ function extractOpenAiMessageContent(response, allowEmptyContent) {
|
|
|
651
893
|
if (allowEmptyContent) {
|
|
652
894
|
return "";
|
|
653
895
|
}
|
|
654
|
-
throw new
|
|
655
|
-
code:
|
|
896
|
+
throw new import_errors17.AppError({
|
|
897
|
+
code: import_errors16.AppErrorCode.ValidationFailed,
|
|
656
898
|
message: "OpenAI response contained no message content",
|
|
657
899
|
statusCode: 502
|
|
658
900
|
});
|
|
@@ -716,6 +958,11 @@ function buildAnthropicRequestBody(settings, input) {
|
|
|
716
958
|
budget_tokens: settings.thinking.budgetTokens
|
|
717
959
|
};
|
|
718
960
|
}
|
|
961
|
+
if (input.structuredOutputJsonSchema !== void 0) {
|
|
962
|
+
requestBody.output_config = {
|
|
963
|
+
format: { type: "json_schema", schema: input.structuredOutputJsonSchema }
|
|
964
|
+
};
|
|
965
|
+
}
|
|
719
966
|
return requestBody;
|
|
720
967
|
}
|
|
721
968
|
function applyAnthropicSystemField(requestBody, settings, input) {
|
|
@@ -872,44 +1119,45 @@ function mapMessageContentBlockToAnthropic(contentBlock) {
|
|
|
872
1119
|
}
|
|
873
1120
|
|
|
874
1121
|
// src/anthropic-response-parsing.ts
|
|
875
|
-
var
|
|
876
|
-
var
|
|
877
|
-
var
|
|
878
|
-
var
|
|
879
|
-
var AnthropicUsageSchema =
|
|
880
|
-
input_tokens:
|
|
881
|
-
output_tokens:
|
|
882
|
-
cache_creation_input_tokens:
|
|
883
|
-
cache_read_input_tokens:
|
|
1122
|
+
var import_zod5 = require("zod");
|
|
1123
|
+
var import_errors18 = require("@assemble-dev/shared-types/errors");
|
|
1124
|
+
var import_json5 = require("@assemble-dev/shared-types/json");
|
|
1125
|
+
var import_errors19 = require("@assemble-dev/shared-utils/errors");
|
|
1126
|
+
var AnthropicUsageSchema = import_zod5.z.object({
|
|
1127
|
+
input_tokens: import_zod5.z.number().int().nonnegative(),
|
|
1128
|
+
output_tokens: import_zod5.z.number().int().nonnegative(),
|
|
1129
|
+
cache_creation_input_tokens: import_zod5.z.number().int().nonnegative().optional(),
|
|
1130
|
+
cache_read_input_tokens: import_zod5.z.number().int().nonnegative().optional()
|
|
884
1131
|
});
|
|
885
|
-
var AnthropicContentBlockSchema =
|
|
886
|
-
|
|
887
|
-
type:
|
|
888
|
-
text:
|
|
1132
|
+
var AnthropicContentBlockSchema = import_zod5.z.discriminatedUnion("type", [
|
|
1133
|
+
import_zod5.z.object({
|
|
1134
|
+
type: import_zod5.z.literal("text"),
|
|
1135
|
+
text: import_zod5.z.string()
|
|
889
1136
|
}),
|
|
890
|
-
|
|
891
|
-
type:
|
|
892
|
-
id:
|
|
893
|
-
name:
|
|
894
|
-
input:
|
|
1137
|
+
import_zod5.z.object({
|
|
1138
|
+
type: import_zod5.z.literal("tool_use"),
|
|
1139
|
+
id: import_zod5.z.string(),
|
|
1140
|
+
name: import_zod5.z.string(),
|
|
1141
|
+
input: import_json5.JsonValueSchema
|
|
895
1142
|
}),
|
|
896
|
-
|
|
897
|
-
type:
|
|
898
|
-
thinking:
|
|
899
|
-
signature:
|
|
1143
|
+
import_zod5.z.object({
|
|
1144
|
+
type: import_zod5.z.literal("thinking"),
|
|
1145
|
+
thinking: import_zod5.z.string().optional(),
|
|
1146
|
+
signature: import_zod5.z.string().optional()
|
|
900
1147
|
}),
|
|
901
|
-
|
|
902
|
-
type:
|
|
903
|
-
data:
|
|
1148
|
+
import_zod5.z.object({
|
|
1149
|
+
type: import_zod5.z.literal("redacted_thinking"),
|
|
1150
|
+
data: import_zod5.z.string().optional()
|
|
904
1151
|
})
|
|
905
1152
|
]);
|
|
906
|
-
var AnthropicMessagesResponseSchema =
|
|
907
|
-
content:
|
|
908
|
-
stop_reason:
|
|
1153
|
+
var AnthropicMessagesResponseSchema = import_zod5.z.object({
|
|
1154
|
+
content: import_zod5.z.array(AnthropicContentBlockSchema),
|
|
1155
|
+
stop_reason: import_zod5.z.string().nullable().optional(),
|
|
909
1156
|
usage: AnthropicUsageSchema
|
|
910
1157
|
});
|
|
911
1158
|
function mapAnthropicResponseToChatCompletionResult(response, latencyMs) {
|
|
912
1159
|
const toolCalls = extractAnthropicToolCalls(response);
|
|
1160
|
+
const thinkingText = extractAnthropicThinkingText(response);
|
|
913
1161
|
const result = {
|
|
914
1162
|
content: extractAnthropicTextContent(response, toolCalls.length > 0),
|
|
915
1163
|
tokenUsage: mapAnthropicUsageToTokenUsage(response.usage),
|
|
@@ -918,6 +1166,9 @@ function mapAnthropicResponseToChatCompletionResult(response, latencyMs) {
|
|
|
918
1166
|
if (toolCalls.length > 0) {
|
|
919
1167
|
result.toolCalls = toolCalls;
|
|
920
1168
|
}
|
|
1169
|
+
if (thinkingText.length > 0) {
|
|
1170
|
+
result.thinkingText = thinkingText;
|
|
1171
|
+
}
|
|
921
1172
|
if (response.stop_reason !== null && response.stop_reason !== void 0) {
|
|
922
1173
|
result.stopReason = normalizeAnthropicStopReason(response.stop_reason);
|
|
923
1174
|
}
|
|
@@ -930,13 +1181,16 @@ function extractAnthropicToolCalls(response) {
|
|
|
930
1181
|
input: contentBlock.input
|
|
931
1182
|
}));
|
|
932
1183
|
}
|
|
1184
|
+
function extractAnthropicThinkingText(response) {
|
|
1185
|
+
return response.content.filter((contentBlock) => contentBlock.type === "thinking").map((contentBlock) => contentBlock.thinking ?? "").join("");
|
|
1186
|
+
}
|
|
933
1187
|
function extractAnthropicTextContent(response, allowEmptyText) {
|
|
934
1188
|
const textBlocks = response.content.filter(
|
|
935
1189
|
(contentBlock) => contentBlock.type === "text"
|
|
936
1190
|
);
|
|
937
1191
|
if (textBlocks.length === 0 && !allowEmptyText) {
|
|
938
|
-
throw new
|
|
939
|
-
code:
|
|
1192
|
+
throw new import_errors19.AppError({
|
|
1193
|
+
code: import_errors18.AppErrorCode.ValidationFailed,
|
|
940
1194
|
message: "Anthropic response contained no text content",
|
|
941
1195
|
statusCode: 502
|
|
942
1196
|
});
|
|
@@ -973,58 +1227,68 @@ function mapAnthropicUsageToTokenUsage(usage) {
|
|
|
973
1227
|
}
|
|
974
1228
|
|
|
975
1229
|
// src/anthropic-stream.ts
|
|
976
|
-
var
|
|
977
|
-
var
|
|
978
|
-
var
|
|
1230
|
+
var import_errors20 = require("@assemble-dev/shared-types/errors");
|
|
1231
|
+
var import_json6 = require("@assemble-dev/shared-types/json");
|
|
1232
|
+
var import_errors21 = require("@assemble-dev/shared-utils/errors");
|
|
979
1233
|
|
|
980
1234
|
// src/anthropic-stream-events.ts
|
|
981
|
-
var
|
|
982
|
-
var AnthropicStreamEventSchema =
|
|
983
|
-
|
|
984
|
-
type:
|
|
985
|
-
message:
|
|
986
|
-
usage:
|
|
987
|
-
input_tokens:
|
|
988
|
-
output_tokens:
|
|
989
|
-
cache_creation_input_tokens:
|
|
990
|
-
cache_read_input_tokens:
|
|
1235
|
+
var import_zod6 = require("zod");
|
|
1236
|
+
var AnthropicStreamEventSchema = import_zod6.z.discriminatedUnion("type", [
|
|
1237
|
+
import_zod6.z.object({
|
|
1238
|
+
type: import_zod6.z.literal("message_start"),
|
|
1239
|
+
message: import_zod6.z.object({
|
|
1240
|
+
usage: import_zod6.z.object({
|
|
1241
|
+
input_tokens: import_zod6.z.number().int().nonnegative(),
|
|
1242
|
+
output_tokens: import_zod6.z.number().int().nonnegative().optional(),
|
|
1243
|
+
cache_creation_input_tokens: import_zod6.z.number().int().nonnegative().optional(),
|
|
1244
|
+
cache_read_input_tokens: import_zod6.z.number().int().nonnegative().optional()
|
|
991
1245
|
})
|
|
992
1246
|
})
|
|
993
1247
|
}),
|
|
994
|
-
|
|
995
|
-
type:
|
|
996
|
-
index:
|
|
997
|
-
content_block:
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
type:
|
|
1001
|
-
|
|
1002
|
-
|
|
1248
|
+
import_zod6.z.object({
|
|
1249
|
+
type: import_zod6.z.literal("content_block_start"),
|
|
1250
|
+
index: import_zod6.z.number().int().nonnegative(),
|
|
1251
|
+
content_block: import_zod6.z.discriminatedUnion("type", [
|
|
1252
|
+
import_zod6.z.object({ type: import_zod6.z.literal("text"), text: import_zod6.z.string().optional() }),
|
|
1253
|
+
import_zod6.z.object({
|
|
1254
|
+
type: import_zod6.z.literal("thinking"),
|
|
1255
|
+
thinking: import_zod6.z.string().optional()
|
|
1256
|
+
}),
|
|
1257
|
+
import_zod6.z.object({
|
|
1258
|
+
type: import_zod6.z.literal("redacted_thinking"),
|
|
1259
|
+
data: import_zod6.z.string().optional()
|
|
1260
|
+
}),
|
|
1261
|
+
import_zod6.z.object({
|
|
1262
|
+
type: import_zod6.z.literal("tool_use"),
|
|
1263
|
+
id: import_zod6.z.string(),
|
|
1264
|
+
name: import_zod6.z.string()
|
|
1003
1265
|
})
|
|
1004
1266
|
])
|
|
1005
1267
|
}),
|
|
1006
|
-
|
|
1007
|
-
type:
|
|
1008
|
-
index:
|
|
1009
|
-
delta:
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1268
|
+
import_zod6.z.object({
|
|
1269
|
+
type: import_zod6.z.literal("content_block_delta"),
|
|
1270
|
+
index: import_zod6.z.number().int().nonnegative(),
|
|
1271
|
+
delta: import_zod6.z.discriminatedUnion("type", [
|
|
1272
|
+
import_zod6.z.object({ type: import_zod6.z.literal("text_delta"), text: import_zod6.z.string() }),
|
|
1273
|
+
import_zod6.z.object({ type: import_zod6.z.literal("thinking_delta"), thinking: import_zod6.z.string() }),
|
|
1274
|
+
import_zod6.z.object({ type: import_zod6.z.literal("signature_delta"), signature: import_zod6.z.string() }),
|
|
1275
|
+
import_zod6.z.object({
|
|
1276
|
+
type: import_zod6.z.literal("input_json_delta"),
|
|
1277
|
+
partial_json: import_zod6.z.string()
|
|
1014
1278
|
})
|
|
1015
1279
|
])
|
|
1016
1280
|
}),
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
type:
|
|
1020
|
-
delta:
|
|
1021
|
-
usage:
|
|
1281
|
+
import_zod6.z.object({ type: import_zod6.z.literal("content_block_stop") }),
|
|
1282
|
+
import_zod6.z.object({
|
|
1283
|
+
type: import_zod6.z.literal("message_delta"),
|
|
1284
|
+
delta: import_zod6.z.object({ stop_reason: import_zod6.z.string().nullable().optional() }),
|
|
1285
|
+
usage: import_zod6.z.object({ output_tokens: import_zod6.z.number().int().nonnegative() }).optional()
|
|
1022
1286
|
}),
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
type:
|
|
1027
|
-
error:
|
|
1287
|
+
import_zod6.z.object({ type: import_zod6.z.literal("message_stop") }),
|
|
1288
|
+
import_zod6.z.object({ type: import_zod6.z.literal("ping") }),
|
|
1289
|
+
import_zod6.z.object({
|
|
1290
|
+
type: import_zod6.z.literal("error"),
|
|
1291
|
+
error: import_zod6.z.object({ message: import_zod6.z.string() })
|
|
1028
1292
|
})
|
|
1029
1293
|
]);
|
|
1030
1294
|
|
|
@@ -1110,6 +1374,7 @@ async function* readServerSentEventDataLines(body, abortSignal) {
|
|
|
1110
1374
|
function createAnthropicStreamAccumulator() {
|
|
1111
1375
|
return {
|
|
1112
1376
|
contentText: "",
|
|
1377
|
+
thinkingText: "",
|
|
1113
1378
|
toolCallsByBlockIndex: /* @__PURE__ */ new Map(),
|
|
1114
1379
|
inputTokens: 0,
|
|
1115
1380
|
outputTokens: 0
|
|
@@ -1117,8 +1382,8 @@ function createAnthropicStreamAccumulator() {
|
|
|
1117
1382
|
}
|
|
1118
1383
|
function* applyAnthropicStreamEvent(event, accumulator) {
|
|
1119
1384
|
if (event.type === "error") {
|
|
1120
|
-
throw new
|
|
1121
|
-
code:
|
|
1385
|
+
throw new import_errors21.AppError({
|
|
1386
|
+
code: import_errors20.AppErrorCode.InternalServerError,
|
|
1122
1387
|
message: `Anthropic stream reported an error: ${event.error.message}`,
|
|
1123
1388
|
statusCode: 502
|
|
1124
1389
|
});
|
|
@@ -1154,6 +1419,17 @@ function* applyAnthropicContentBlockStart(event, accumulator) {
|
|
|
1154
1419
|
}
|
|
1155
1420
|
return;
|
|
1156
1421
|
}
|
|
1422
|
+
if (event.content_block.type === "thinking") {
|
|
1423
|
+
const initialThinkingText = event.content_block.thinking ?? "";
|
|
1424
|
+
if (initialThinkingText.length > 0) {
|
|
1425
|
+
accumulator.thinkingText += initialThinkingText;
|
|
1426
|
+
yield { type: "thinking_delta", text: initialThinkingText };
|
|
1427
|
+
}
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
if (event.content_block.type === "redacted_thinking") {
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1157
1433
|
accumulator.toolCallsByBlockIndex.set(event.index, {
|
|
1158
1434
|
id: event.content_block.id,
|
|
1159
1435
|
toolName: event.content_block.name,
|
|
@@ -1171,6 +1447,14 @@ function* applyAnthropicContentBlockDelta(event, accumulator) {
|
|
|
1171
1447
|
yield { type: "text_delta", text: event.delta.text };
|
|
1172
1448
|
return;
|
|
1173
1449
|
}
|
|
1450
|
+
if (event.delta.type === "thinking_delta") {
|
|
1451
|
+
accumulator.thinkingText += event.delta.thinking;
|
|
1452
|
+
yield { type: "thinking_delta", text: event.delta.thinking };
|
|
1453
|
+
return;
|
|
1454
|
+
}
|
|
1455
|
+
if (event.delta.type === "signature_delta") {
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1174
1458
|
const toolCallAccumulation = accumulator.toolCallsByBlockIndex.get(
|
|
1175
1459
|
event.index
|
|
1176
1460
|
);
|
|
@@ -1217,6 +1501,9 @@ function buildAnthropicStreamResult(accumulator, latencyMs) {
|
|
|
1217
1501
|
if (accumulator.stopReason !== void 0) {
|
|
1218
1502
|
result.stopReason = accumulator.stopReason;
|
|
1219
1503
|
}
|
|
1504
|
+
if (accumulator.thinkingText.length > 0) {
|
|
1505
|
+
result.thinkingText = accumulator.thinkingText;
|
|
1506
|
+
}
|
|
1220
1507
|
return result;
|
|
1221
1508
|
}
|
|
1222
1509
|
function mapAccumulatedToolCallToModelToolCall(toolCallAccumulation) {
|
|
@@ -1231,10 +1518,10 @@ function parseAnthropicToolInputJson(inputJsonText) {
|
|
|
1231
1518
|
return {};
|
|
1232
1519
|
}
|
|
1233
1520
|
try {
|
|
1234
|
-
return
|
|
1521
|
+
return import_json6.JsonValueSchema.parse(JSON.parse(inputJsonText));
|
|
1235
1522
|
} catch (error) {
|
|
1236
|
-
throw new
|
|
1237
|
-
code:
|
|
1523
|
+
throw new import_errors21.AppError({
|
|
1524
|
+
code: import_errors20.AppErrorCode.ValidationFailed,
|
|
1238
1525
|
message: "Anthropic tool input was not valid JSON",
|
|
1239
1526
|
statusCode: 502,
|
|
1240
1527
|
cause: error instanceof Error ? error : void 0
|
|
@@ -1246,10 +1533,6 @@ function parseAnthropicToolInputJson(inputJsonText) {
|
|
|
1246
1533
|
var defaultAnthropicBaseUrl = "https://api.anthropic.com";
|
|
1247
1534
|
var defaultAnthropicMaxOutputTokens = 1024;
|
|
1248
1535
|
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
1536
|
function anthropic(options) {
|
|
1254
1537
|
return {
|
|
1255
1538
|
name: `anthropic:${options.model}`,
|
|
@@ -1261,9 +1544,12 @@ function anthropic(options) {
|
|
|
1261
1544
|
},
|
|
1262
1545
|
async generateStructuredOutput(request) {
|
|
1263
1546
|
const completion = await executeAnthropicAdapterCall(options, {
|
|
1264
|
-
messages:
|
|
1547
|
+
messages: request.messages,
|
|
1265
1548
|
temperature: request.temperature ?? options.temperature,
|
|
1266
1549
|
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
1550
|
+
structuredOutputJsonSchema: buildAnthropicStructuredOutputJsonSchema(
|
|
1551
|
+
request.schema
|
|
1552
|
+
),
|
|
1267
1553
|
abortSignal: request.abortSignal
|
|
1268
1554
|
});
|
|
1269
1555
|
return {
|
|
@@ -1379,28 +1665,116 @@ function resolveAnthropicFetch(options) {
|
|
|
1379
1665
|
}
|
|
1380
1666
|
|
|
1381
1667
|
// src/gemini-adapter.ts
|
|
1382
|
-
var
|
|
1383
|
-
var
|
|
1384
|
-
var
|
|
1668
|
+
var import_zod7 = require("zod");
|
|
1669
|
+
var import_errors22 = require("@assemble-dev/shared-types/errors");
|
|
1670
|
+
var import_errors23 = require("@assemble-dev/shared-utils/errors");
|
|
1671
|
+
|
|
1672
|
+
// src/gemini-response-schema.ts
|
|
1673
|
+
var geminiAllowedSchemaKeywords = [
|
|
1674
|
+
"type",
|
|
1675
|
+
"format",
|
|
1676
|
+
"description",
|
|
1677
|
+
"nullable",
|
|
1678
|
+
"enum",
|
|
1679
|
+
"properties",
|
|
1680
|
+
"required",
|
|
1681
|
+
"items",
|
|
1682
|
+
"minItems",
|
|
1683
|
+
"maxItems",
|
|
1684
|
+
"anyOf"
|
|
1685
|
+
];
|
|
1686
|
+
var geminiAllowedFormats = [
|
|
1687
|
+
"date-time",
|
|
1688
|
+
"int32",
|
|
1689
|
+
"int64",
|
|
1690
|
+
"float",
|
|
1691
|
+
"double"
|
|
1692
|
+
];
|
|
1693
|
+
function buildGeminiResponseSchema(schema) {
|
|
1694
|
+
return sanitizeJsonSchemaForGeminiResponseSchema(
|
|
1695
|
+
convertZodSchemaToJsonSchema(schema)
|
|
1696
|
+
);
|
|
1697
|
+
}
|
|
1698
|
+
function sanitizeJsonSchemaForGeminiResponseSchema(jsonSchema) {
|
|
1699
|
+
return transformJsonSchemaNode(
|
|
1700
|
+
inlineJsonSchemaReferences(jsonSchema),
|
|
1701
|
+
sanitizeGeminiSchemaNode
|
|
1702
|
+
);
|
|
1703
|
+
}
|
|
1704
|
+
function sanitizeGeminiSchemaNode(node) {
|
|
1705
|
+
const normalized = normalizeGeminiNullableType(
|
|
1706
|
+
mergeNullUnionIntoNullableNode(node)
|
|
1707
|
+
);
|
|
1708
|
+
const sanitized = {};
|
|
1709
|
+
for (const [key, value] of Object.entries(normalized)) {
|
|
1710
|
+
if (geminiAllowedSchemaKeywords.includes(key)) {
|
|
1711
|
+
sanitized[key] = value;
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
return removeUnsupportedGeminiFormat(sanitized);
|
|
1715
|
+
}
|
|
1716
|
+
function mergeNullUnionIntoNullableNode(node) {
|
|
1717
|
+
const unionKeyword = Array.isArray(node["anyOf"]) ? "anyOf" : "oneOf";
|
|
1718
|
+
const unionMembers = node[unionKeyword];
|
|
1719
|
+
if (!Array.isArray(unionMembers)) {
|
|
1720
|
+
return node;
|
|
1721
|
+
}
|
|
1722
|
+
const nonNullMembers = unionMembers.filter(
|
|
1723
|
+
(member) => !isNullTypeSchemaNode(member)
|
|
1724
|
+
);
|
|
1725
|
+
if (nonNullMembers.length === unionMembers.length) {
|
|
1726
|
+
return node;
|
|
1727
|
+
}
|
|
1728
|
+
const merged = { ...node };
|
|
1729
|
+
delete merged[unionKeyword];
|
|
1730
|
+
const singleMember = nonNullMembers.length === 1 ? nonNullMembers[0] : void 0;
|
|
1731
|
+
if (singleMember !== void 0 && isJsonObject(singleMember)) {
|
|
1732
|
+
return { ...merged, ...singleMember, nullable: true };
|
|
1733
|
+
}
|
|
1734
|
+
return { ...merged, anyOf: nonNullMembers, nullable: true };
|
|
1735
|
+
}
|
|
1736
|
+
function normalizeGeminiNullableType(node) {
|
|
1737
|
+
const typeValue = node["type"];
|
|
1738
|
+
if (!Array.isArray(typeValue)) {
|
|
1739
|
+
return node;
|
|
1740
|
+
}
|
|
1741
|
+
const nonNullTypes = typeValue.filter((typeName) => typeName !== "null");
|
|
1742
|
+
const normalized = { ...node };
|
|
1743
|
+
if (nonNullTypes.length < typeValue.length) {
|
|
1744
|
+
normalized["nullable"] = true;
|
|
1745
|
+
}
|
|
1746
|
+
normalized["type"] = nonNullTypes[0] ?? "string";
|
|
1747
|
+
return normalized;
|
|
1748
|
+
}
|
|
1749
|
+
function removeUnsupportedGeminiFormat(node) {
|
|
1750
|
+
const formatValue = node["format"];
|
|
1751
|
+
if (typeof formatValue === "string" && !geminiAllowedFormats.includes(formatValue)) {
|
|
1752
|
+
const withoutFormat = { ...node };
|
|
1753
|
+
delete withoutFormat["format"];
|
|
1754
|
+
return withoutFormat;
|
|
1755
|
+
}
|
|
1756
|
+
return node;
|
|
1757
|
+
}
|
|
1758
|
+
function isNullTypeSchemaNode(value) {
|
|
1759
|
+
return isJsonObject(value) && value["type"] === "null";
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
// src/gemini-adapter.ts
|
|
1385
1763
|
var defaultGeminiBaseUrl = "https://generativelanguage.googleapis.com";
|
|
1386
|
-
var GeminiGenerateContentResponseSchema =
|
|
1387
|
-
candidates:
|
|
1388
|
-
|
|
1389
|
-
content:
|
|
1390
|
-
parts:
|
|
1764
|
+
var GeminiGenerateContentResponseSchema = import_zod7.z.object({
|
|
1765
|
+
candidates: import_zod7.z.array(
|
|
1766
|
+
import_zod7.z.object({
|
|
1767
|
+
content: import_zod7.z.object({
|
|
1768
|
+
parts: import_zod7.z.array(import_zod7.z.object({ text: import_zod7.z.string() }))
|
|
1391
1769
|
})
|
|
1392
1770
|
})
|
|
1393
1771
|
).optional(),
|
|
1394
|
-
usageMetadata:
|
|
1395
|
-
promptTokenCount:
|
|
1396
|
-
candidatesTokenCount:
|
|
1397
|
-
totalTokenCount:
|
|
1772
|
+
usageMetadata: import_zod7.z.object({
|
|
1773
|
+
promptTokenCount: import_zod7.z.number().int().nonnegative().optional(),
|
|
1774
|
+
candidatesTokenCount: import_zod7.z.number().int().nonnegative().optional(),
|
|
1775
|
+
totalTokenCount: import_zod7.z.number().int().nonnegative().optional()
|
|
1398
1776
|
}).optional()
|
|
1399
1777
|
});
|
|
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
1778
|
function gemini(options) {
|
|
1405
1779
|
return {
|
|
1406
1780
|
name: `gemini:${options.model}`,
|
|
@@ -1410,17 +1784,16 @@ function gemini(options) {
|
|
|
1410
1784
|
messages: request.messages,
|
|
1411
1785
|
temperature: request.temperature ?? options.temperature,
|
|
1412
1786
|
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
1413
|
-
requireJsonResponse: false,
|
|
1414
1787
|
abortSignal: request.abortSignal,
|
|
1415
1788
|
extraBody: request.extraBody
|
|
1416
1789
|
});
|
|
1417
1790
|
},
|
|
1418
1791
|
async generateStructuredOutput(request) {
|
|
1419
1792
|
const completion = await executeGeminiAdapterCall(options, {
|
|
1420
|
-
messages:
|
|
1793
|
+
messages: request.messages,
|
|
1421
1794
|
temperature: request.temperature ?? options.temperature,
|
|
1422
1795
|
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
1423
|
-
|
|
1796
|
+
responseSchema: buildGeminiResponseSchema(request.schema),
|
|
1424
1797
|
abortSignal: request.abortSignal
|
|
1425
1798
|
});
|
|
1426
1799
|
return {
|
|
@@ -1507,8 +1880,8 @@ function ensureGeminiRequestHasNoTools(request) {
|
|
|
1507
1880
|
if (request.tools === void 0 || request.tools.length === 0) {
|
|
1508
1881
|
return;
|
|
1509
1882
|
}
|
|
1510
|
-
throw new
|
|
1511
|
-
code:
|
|
1883
|
+
throw new import_errors23.AppError({
|
|
1884
|
+
code: import_errors22.AppErrorCode.ValidationFailed,
|
|
1512
1885
|
message: "gemini adapter does not support model-driven tool use; remove tools from the request or use another adapter",
|
|
1513
1886
|
statusCode: 400
|
|
1514
1887
|
});
|
|
@@ -1545,8 +1918,9 @@ function buildGeminiGenerationConfig(input) {
|
|
|
1545
1918
|
if (input.maxOutputTokens !== void 0) {
|
|
1546
1919
|
generationConfig.maxOutputTokens = input.maxOutputTokens;
|
|
1547
1920
|
}
|
|
1548
|
-
if (input.
|
|
1921
|
+
if (input.responseSchema !== void 0) {
|
|
1549
1922
|
generationConfig.responseMimeType = "application/json";
|
|
1923
|
+
generationConfig.responseSchema = input.responseSchema;
|
|
1550
1924
|
}
|
|
1551
1925
|
if (Object.keys(generationConfig).length === 0) {
|
|
1552
1926
|
return void 0;
|
|
@@ -1556,8 +1930,8 @@ function buildGeminiGenerationConfig(input) {
|
|
|
1556
1930
|
function extractGeminiCandidateText(response) {
|
|
1557
1931
|
const firstCandidate = response.candidates?.[0];
|
|
1558
1932
|
if (firstCandidate === void 0) {
|
|
1559
|
-
throw new
|
|
1560
|
-
code:
|
|
1933
|
+
throw new import_errors23.AppError({
|
|
1934
|
+
code: import_errors22.AppErrorCode.ValidationFailed,
|
|
1561
1935
|
message: "Gemini response contained no candidates",
|
|
1562
1936
|
statusCode: 502
|
|
1563
1937
|
});
|
|
@@ -1576,8 +1950,8 @@ function mapGeminiUsageToTokenUsage(response) {
|
|
|
1576
1950
|
}
|
|
1577
1951
|
|
|
1578
1952
|
// src/mock-adapter.ts
|
|
1579
|
-
var
|
|
1580
|
-
var
|
|
1953
|
+
var import_errors24 = require("@assemble-dev/shared-types/errors");
|
|
1954
|
+
var import_errors25 = require("@assemble-dev/shared-utils/errors");
|
|
1581
1955
|
var mockStreamChunkCount = 3;
|
|
1582
1956
|
function mockModel(options = {}) {
|
|
1583
1957
|
const remainingScriptedResponses = [...options.scriptedResponses ?? []];
|
|
@@ -1657,8 +2031,8 @@ function resolveNextMockResponseText(request, remainingScriptedResponses, respon
|
|
|
1657
2031
|
if (respond !== void 0) {
|
|
1658
2032
|
return respond(request);
|
|
1659
2033
|
}
|
|
1660
|
-
throw new
|
|
1661
|
-
code:
|
|
2034
|
+
throw new import_errors25.AppError({
|
|
2035
|
+
code: import_errors24.AppErrorCode.BadRequest,
|
|
1662
2036
|
message: "Mock model has no scripted responses left and no respond function was provided",
|
|
1663
2037
|
statusCode: 400
|
|
1664
2038
|
});
|
|
@@ -1746,24 +2120,24 @@ function calculateModelCallCostUsd(pricing, tokenUsage) {
|
|
|
1746
2120
|
}
|
|
1747
2121
|
|
|
1748
2122
|
// src/anthropic-batch.ts
|
|
2123
|
+
var import_errors28 = require("@assemble-dev/shared-types/errors");
|
|
2124
|
+
var import_json8 = require("@assemble-dev/shared-types/json");
|
|
2125
|
+
var import_errors29 = require("@assemble-dev/shared-utils/errors");
|
|
2126
|
+
|
|
2127
|
+
// src/anthropic-batch-structured.ts
|
|
1749
2128
|
var import_errors26 = require("@assemble-dev/shared-types/errors");
|
|
1750
2129
|
var import_json7 = require("@assemble-dev/shared-types/json");
|
|
1751
2130
|
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
2131
|
var anthropicBatchJsonOnlySystemInstruction = "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text.";
|
|
1758
2132
|
function parseAnthropicBatchStructuredContent(content, schema) {
|
|
1759
2133
|
const jsonValue = parseStructuredJsonText(
|
|
1760
2134
|
content,
|
|
1761
|
-
|
|
2135
|
+
import_json7.JsonValueSchema
|
|
1762
2136
|
);
|
|
1763
2137
|
const validationResult = schema.safeParse(jsonValue);
|
|
1764
2138
|
if (!validationResult.success) {
|
|
1765
|
-
throw new
|
|
1766
|
-
code:
|
|
2139
|
+
throw new import_errors27.AppError({
|
|
2140
|
+
code: import_errors26.AppErrorCode.ValidationFailed,
|
|
1767
2141
|
message: "Anthropic batch structured output did not match the expected schema",
|
|
1768
2142
|
statusCode: 422,
|
|
1769
2143
|
details: { validationErrorMessage: validationResult.error.message }
|
|
@@ -1780,11 +2154,25 @@ function mapBatchMessageRequestToApiBatchRequest(request) {
|
|
|
1780
2154
|
messages: request.messages.filter((message) => message.role !== "system").map(mapChatMessageToBatchApiRequestMessage)
|
|
1781
2155
|
};
|
|
1782
2156
|
applyBatchSystemField(params, request);
|
|
2157
|
+
applyBatchStructuredOutputConfig(params, request);
|
|
1783
2158
|
if (request.temperature !== void 0) {
|
|
1784
2159
|
params.temperature = request.temperature;
|
|
1785
2160
|
}
|
|
1786
2161
|
return { custom_id: request.customId, params };
|
|
1787
2162
|
}
|
|
2163
|
+
function applyBatchStructuredOutputConfig(params, request) {
|
|
2164
|
+
if (request.structuredOutputJsonSchema === void 0) {
|
|
2165
|
+
return;
|
|
2166
|
+
}
|
|
2167
|
+
params.output_config = {
|
|
2168
|
+
format: {
|
|
2169
|
+
type: "json_schema",
|
|
2170
|
+
schema: sanitizeJsonSchemaForAnthropicStructuredOutput(
|
|
2171
|
+
request.structuredOutputJsonSchema
|
|
2172
|
+
)
|
|
2173
|
+
}
|
|
2174
|
+
};
|
|
2175
|
+
}
|
|
1788
2176
|
function applyBatchSystemField(params, request) {
|
|
1789
2177
|
const systemText = buildBatchSystemText(request);
|
|
1790
2178
|
if (systemText.length === 0) {
|
|
@@ -1800,7 +2188,7 @@ function applyBatchSystemField(params, request) {
|
|
|
1800
2188
|
}
|
|
1801
2189
|
function buildBatchSystemText(request) {
|
|
1802
2190
|
const joinedSystemText = joinBatchSystemMessageText(request.messages);
|
|
1803
|
-
if (request.requireJsonResponse !== true) {
|
|
2191
|
+
if (request.requireJsonResponse !== true || request.structuredOutputJsonSchema !== void 0) {
|
|
1804
2192
|
return joinedSystemText;
|
|
1805
2193
|
}
|
|
1806
2194
|
if (joinedSystemText.length === 0) {
|
|
@@ -1951,55 +2339,55 @@ function buildBatchResultEvent(eventBase, batchId, result, modelName) {
|
|
|
1951
2339
|
}
|
|
1952
2340
|
|
|
1953
2341
|
// src/anthropic-batch-types.ts
|
|
1954
|
-
var
|
|
1955
|
-
var AnthropicMessageBatchResponseSchema =
|
|
1956
|
-
id:
|
|
1957
|
-
processing_status:
|
|
1958
|
-
request_counts:
|
|
1959
|
-
processing:
|
|
1960
|
-
succeeded:
|
|
1961
|
-
errored:
|
|
1962
|
-
canceled:
|
|
1963
|
-
expired:
|
|
2342
|
+
var import_zod8 = require("zod");
|
|
2343
|
+
var AnthropicMessageBatchResponseSchema = import_zod8.z.object({
|
|
2344
|
+
id: import_zod8.z.string(),
|
|
2345
|
+
processing_status: import_zod8.z.enum(["in_progress", "canceling", "ended"]),
|
|
2346
|
+
request_counts: import_zod8.z.object({
|
|
2347
|
+
processing: import_zod8.z.number().int().nonnegative(),
|
|
2348
|
+
succeeded: import_zod8.z.number().int().nonnegative(),
|
|
2349
|
+
errored: import_zod8.z.number().int().nonnegative(),
|
|
2350
|
+
canceled: import_zod8.z.number().int().nonnegative(),
|
|
2351
|
+
expired: import_zod8.z.number().int().nonnegative()
|
|
1964
2352
|
}),
|
|
1965
|
-
results_url:
|
|
1966
|
-
created_at:
|
|
1967
|
-
ended_at:
|
|
2353
|
+
results_url: import_zod8.z.string().nullable(),
|
|
2354
|
+
created_at: import_zod8.z.string(),
|
|
2355
|
+
ended_at: import_zod8.z.string().nullable()
|
|
1968
2356
|
});
|
|
1969
|
-
var AnthropicBatchContentBlockSchema =
|
|
1970
|
-
|
|
1971
|
-
type:
|
|
1972
|
-
text:
|
|
2357
|
+
var AnthropicBatchContentBlockSchema = import_zod8.z.discriminatedUnion("type", [
|
|
2358
|
+
import_zod8.z.object({
|
|
2359
|
+
type: import_zod8.z.literal("text"),
|
|
2360
|
+
text: import_zod8.z.string()
|
|
1973
2361
|
}),
|
|
1974
|
-
|
|
1975
|
-
type:
|
|
1976
|
-
thinking:
|
|
1977
|
-
signature:
|
|
2362
|
+
import_zod8.z.object({
|
|
2363
|
+
type: import_zod8.z.literal("thinking"),
|
|
2364
|
+
thinking: import_zod8.z.string().optional(),
|
|
2365
|
+
signature: import_zod8.z.string().optional()
|
|
1978
2366
|
}),
|
|
1979
|
-
|
|
1980
|
-
type:
|
|
1981
|
-
data:
|
|
2367
|
+
import_zod8.z.object({
|
|
2368
|
+
type: import_zod8.z.literal("redacted_thinking"),
|
|
2369
|
+
data: import_zod8.z.string().optional()
|
|
1982
2370
|
})
|
|
1983
2371
|
]);
|
|
1984
|
-
var AnthropicBatchResultLineSchema =
|
|
1985
|
-
custom_id:
|
|
1986
|
-
result:
|
|
1987
|
-
|
|
1988
|
-
type:
|
|
1989
|
-
message:
|
|
1990
|
-
content:
|
|
2372
|
+
var AnthropicBatchResultLineSchema = import_zod8.z.object({
|
|
2373
|
+
custom_id: import_zod8.z.string(),
|
|
2374
|
+
result: import_zod8.z.discriminatedUnion("type", [
|
|
2375
|
+
import_zod8.z.object({
|
|
2376
|
+
type: import_zod8.z.literal("succeeded"),
|
|
2377
|
+
message: import_zod8.z.object({
|
|
2378
|
+
content: import_zod8.z.array(AnthropicBatchContentBlockSchema),
|
|
1991
2379
|
usage: AnthropicUsageSchema
|
|
1992
2380
|
})
|
|
1993
2381
|
}),
|
|
1994
|
-
|
|
1995
|
-
type:
|
|
1996
|
-
error:
|
|
1997
|
-
type:
|
|
1998
|
-
message:
|
|
2382
|
+
import_zod8.z.object({
|
|
2383
|
+
type: import_zod8.z.literal("errored"),
|
|
2384
|
+
error: import_zod8.z.object({
|
|
2385
|
+
type: import_zod8.z.string(),
|
|
2386
|
+
message: import_zod8.z.string()
|
|
1999
2387
|
})
|
|
2000
2388
|
}),
|
|
2001
|
-
|
|
2002
|
-
|
|
2389
|
+
import_zod8.z.object({ type: import_zod8.z.literal("canceled") }),
|
|
2390
|
+
import_zod8.z.object({ type: import_zod8.z.literal("expired") })
|
|
2003
2391
|
])
|
|
2004
2392
|
});
|
|
2005
2393
|
function mapAnthropicMessageBatchResponseToMessageBatch(response) {
|
|
@@ -2149,8 +2537,8 @@ async function parseAnthropicMessageBatchHttpResponse(response) {
|
|
|
2149
2537
|
async function listAnthropicMessageBatchResults(clientContext, batchId) {
|
|
2150
2538
|
const batch = await fetchAnthropicMessageBatch(clientContext, batchId);
|
|
2151
2539
|
if (batch.resultsUrl === null) {
|
|
2152
|
-
throw new
|
|
2153
|
-
code:
|
|
2540
|
+
throw new import_errors29.AppError({
|
|
2541
|
+
code: import_errors28.AppErrorCode.Conflict,
|
|
2154
2542
|
message: `Anthropic message batch ${batchId} has no results because processing has not ended`,
|
|
2155
2543
|
statusCode: 409,
|
|
2156
2544
|
details: { batchId, processingStatus: batch.processingStatus }
|
|
@@ -2187,7 +2575,7 @@ function parseAnthropicBatchResultLine(line) {
|
|
|
2187
2575
|
}
|
|
2188
2576
|
function parseAnthropicBatchResultLineJson(line) {
|
|
2189
2577
|
try {
|
|
2190
|
-
return
|
|
2578
|
+
return import_json8.JsonValueSchema.parse(JSON.parse(line));
|
|
2191
2579
|
} catch {
|
|
2192
2580
|
throw buildProviderInvalidResponseError(
|
|
2193
2581
|
"Anthropic",
|
|
@@ -2211,17 +2599,761 @@ async function waitForAnthropicMessageBatchCompletion(clientContext, batchId, wa
|
|
|
2211
2599
|
return batch;
|
|
2212
2600
|
}
|
|
2213
2601
|
function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
|
|
2214
|
-
return new
|
|
2215
|
-
code:
|
|
2602
|
+
return new import_errors29.AppError({
|
|
2603
|
+
code: import_errors28.AppErrorCode.ServiceUnavailable,
|
|
2216
2604
|
message: `Anthropic message batch ${batchId} did not complete within ${String(timeoutMs)}ms`,
|
|
2217
2605
|
statusCode: 504,
|
|
2218
2606
|
details: { batchId, timeoutMs }
|
|
2219
2607
|
});
|
|
2220
2608
|
}
|
|
2609
|
+
|
|
2610
|
+
// src/azure-openai-adapter.ts
|
|
2611
|
+
var import_errors32 = require("@assemble-dev/shared-types/errors");
|
|
2612
|
+
var import_errors33 = require("@assemble-dev/shared-utils/errors");
|
|
2613
|
+
|
|
2614
|
+
// src/azure-openai-response-parsing.ts
|
|
2615
|
+
var import_zod9 = require("zod");
|
|
2616
|
+
var import_errors30 = require("@assemble-dev/shared-types/errors");
|
|
2617
|
+
var import_json9 = require("@assemble-dev/shared-types/json");
|
|
2618
|
+
var import_errors31 = require("@assemble-dev/shared-utils/errors");
|
|
2619
|
+
var AzureOpenAiUsageSchema = import_zod9.z.object({
|
|
2620
|
+
prompt_tokens: import_zod9.z.number().int().nonnegative(),
|
|
2621
|
+
completion_tokens: import_zod9.z.number().int().nonnegative(),
|
|
2622
|
+
total_tokens: import_zod9.z.number().int().nonnegative()
|
|
2623
|
+
});
|
|
2624
|
+
var AzureOpenAiResponseToolCallSchema = import_zod9.z.object({
|
|
2625
|
+
id: import_zod9.z.string(),
|
|
2626
|
+
function: import_zod9.z.object({
|
|
2627
|
+
name: import_zod9.z.string(),
|
|
2628
|
+
arguments: import_zod9.z.string()
|
|
2629
|
+
})
|
|
2630
|
+
});
|
|
2631
|
+
var AzureOpenAiChatCompletionResponseSchema = import_zod9.z.object({
|
|
2632
|
+
choices: import_zod9.z.array(
|
|
2633
|
+
import_zod9.z.object({
|
|
2634
|
+
message: import_zod9.z.object({
|
|
2635
|
+
content: import_zod9.z.string().nullable(),
|
|
2636
|
+
tool_calls: import_zod9.z.array(AzureOpenAiResponseToolCallSchema).optional()
|
|
2637
|
+
}),
|
|
2638
|
+
finish_reason: import_zod9.z.string().nullable().optional()
|
|
2639
|
+
})
|
|
2640
|
+
).min(1),
|
|
2641
|
+
usage: AzureOpenAiUsageSchema
|
|
2642
|
+
});
|
|
2643
|
+
function mapAzureOpenAiResponseToChatCompletionResult(response, latencyMs) {
|
|
2644
|
+
const toolCalls = extractAzureOpenAiToolCalls(response);
|
|
2645
|
+
const result = {
|
|
2646
|
+
content: extractAzureOpenAiMessageContent(response, toolCalls.length > 0),
|
|
2647
|
+
tokenUsage: mapAzureOpenAiUsageToTokenUsage(response.usage),
|
|
2648
|
+
latencyMs
|
|
2649
|
+
};
|
|
2650
|
+
const finishReason = response.choices[0]?.finish_reason;
|
|
2651
|
+
if (toolCalls.length > 0) {
|
|
2652
|
+
result.toolCalls = toolCalls;
|
|
2653
|
+
}
|
|
2654
|
+
if (finishReason !== null && finishReason !== void 0) {
|
|
2655
|
+
result.stopReason = normalizeAzureOpenAiFinishReason(finishReason);
|
|
2656
|
+
}
|
|
2657
|
+
return result;
|
|
2658
|
+
}
|
|
2659
|
+
function extractAzureOpenAiToolCalls(response) {
|
|
2660
|
+
const responseToolCalls = response.choices[0]?.message.tool_calls ?? [];
|
|
2661
|
+
return responseToolCalls.map((responseToolCall) => ({
|
|
2662
|
+
id: responseToolCall.id,
|
|
2663
|
+
toolName: responseToolCall.function.name,
|
|
2664
|
+
input: parseAzureOpenAiToolArgumentsJson(responseToolCall.function.arguments)
|
|
2665
|
+
}));
|
|
2666
|
+
}
|
|
2667
|
+
function parseAzureOpenAiToolArgumentsJson(argumentsJsonText) {
|
|
2668
|
+
if (argumentsJsonText.trim().length === 0) {
|
|
2669
|
+
return {};
|
|
2670
|
+
}
|
|
2671
|
+
try {
|
|
2672
|
+
return import_json9.JsonValueSchema.parse(JSON.parse(argumentsJsonText));
|
|
2673
|
+
} catch (error) {
|
|
2674
|
+
throw new import_errors31.AppError({
|
|
2675
|
+
code: import_errors30.AppErrorCode.ValidationFailed,
|
|
2676
|
+
message: "Azure OpenAI tool call arguments were not valid JSON",
|
|
2677
|
+
statusCode: 502,
|
|
2678
|
+
cause: error instanceof Error ? error : void 0
|
|
2679
|
+
});
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
function normalizeAzureOpenAiFinishReason(finishReason) {
|
|
2683
|
+
if (finishReason === "tool_calls") {
|
|
2684
|
+
return "tool_use";
|
|
2685
|
+
}
|
|
2686
|
+
if (finishReason === "length") {
|
|
2687
|
+
return "max_tokens";
|
|
2688
|
+
}
|
|
2689
|
+
return "end_turn";
|
|
2690
|
+
}
|
|
2691
|
+
function extractAzureOpenAiMessageContent(response, allowEmptyContent) {
|
|
2692
|
+
const content = response.choices[0]?.message.content;
|
|
2693
|
+
if (content === void 0 || content === null) {
|
|
2694
|
+
if (allowEmptyContent) {
|
|
2695
|
+
return "";
|
|
2696
|
+
}
|
|
2697
|
+
throw new import_errors31.AppError({
|
|
2698
|
+
code: import_errors30.AppErrorCode.ValidationFailed,
|
|
2699
|
+
message: "Azure OpenAI response contained no message content",
|
|
2700
|
+
statusCode: 502
|
|
2701
|
+
});
|
|
2702
|
+
}
|
|
2703
|
+
return content;
|
|
2704
|
+
}
|
|
2705
|
+
function mapAzureOpenAiUsageToTokenUsage(usage) {
|
|
2706
|
+
return {
|
|
2707
|
+
inputTokens: usage.prompt_tokens,
|
|
2708
|
+
outputTokens: usage.completion_tokens,
|
|
2709
|
+
totalTokens: usage.total_tokens
|
|
2710
|
+
};
|
|
2711
|
+
}
|
|
2712
|
+
|
|
2713
|
+
// src/azure-openai-stream.ts
|
|
2714
|
+
var import_zod10 = require("zod");
|
|
2715
|
+
var AzureOpenAiStreamToolCallDeltaSchema = import_zod10.z.object({
|
|
2716
|
+
index: import_zod10.z.number().int().nonnegative(),
|
|
2717
|
+
id: import_zod10.z.string().optional(),
|
|
2718
|
+
function: import_zod10.z.object({
|
|
2719
|
+
name: import_zod10.z.string().optional(),
|
|
2720
|
+
arguments: import_zod10.z.string().optional()
|
|
2721
|
+
}).optional()
|
|
2722
|
+
});
|
|
2723
|
+
var AzureOpenAiStreamChunkSchema = import_zod10.z.object({
|
|
2724
|
+
choices: import_zod10.z.array(
|
|
2725
|
+
import_zod10.z.object({
|
|
2726
|
+
delta: import_zod10.z.object({
|
|
2727
|
+
content: import_zod10.z.string().nullable().optional(),
|
|
2728
|
+
tool_calls: import_zod10.z.array(AzureOpenAiStreamToolCallDeltaSchema).optional()
|
|
2729
|
+
}).optional(),
|
|
2730
|
+
finish_reason: import_zod10.z.string().nullable().optional()
|
|
2731
|
+
})
|
|
2732
|
+
).optional(),
|
|
2733
|
+
usage: AzureOpenAiUsageSchema.nullable().optional()
|
|
2734
|
+
});
|
|
2735
|
+
async function* streamAzureOpenAiChatCompletion(input) {
|
|
2736
|
+
const startedAt = Date.now();
|
|
2737
|
+
const response = await establishAzureOpenAiStreamResponse(input);
|
|
2738
|
+
if (response.body === null) {
|
|
2739
|
+
throw buildProviderInvalidResponseError("Azure OpenAI", "stream body");
|
|
2740
|
+
}
|
|
2741
|
+
yield* parseAzureOpenAiStreamEvents(
|
|
2742
|
+
response.body,
|
|
2743
|
+
startedAt,
|
|
2744
|
+
input.abortSignal
|
|
2745
|
+
);
|
|
2746
|
+
}
|
|
2747
|
+
async function establishAzureOpenAiStreamResponse(input) {
|
|
2748
|
+
return await executeProviderCallWithRetry(input.retry, async () => {
|
|
2749
|
+
const response = await executeAbortableProviderFetch(
|
|
2750
|
+
"Azure OpenAI",
|
|
2751
|
+
async () => await input.fetchImplementation(input.url, {
|
|
2752
|
+
method: "POST",
|
|
2753
|
+
headers: input.headers,
|
|
2754
|
+
body: JSON.stringify(input.body),
|
|
2755
|
+
signal: input.abortSignal
|
|
2756
|
+
})
|
|
2757
|
+
);
|
|
2758
|
+
if (!response.ok) {
|
|
2759
|
+
throw buildProviderStatusError("Azure OpenAI", response.status);
|
|
2760
|
+
}
|
|
2761
|
+
return response;
|
|
2762
|
+
});
|
|
2763
|
+
}
|
|
2764
|
+
async function* parseAzureOpenAiStreamEvents(body, startedAt, abortSignal) {
|
|
2765
|
+
const accumulator = createAzureOpenAiStreamAccumulator();
|
|
2766
|
+
for await (const dataText of readServerSentEventDataLines2(body, abortSignal)) {
|
|
2767
|
+
if (dataText === "[DONE]") {
|
|
2768
|
+
yield {
|
|
2769
|
+
type: "completed",
|
|
2770
|
+
result: buildAzureOpenAiStreamResult(
|
|
2771
|
+
accumulator,
|
|
2772
|
+
Date.now() - startedAt
|
|
2773
|
+
)
|
|
2774
|
+
};
|
|
2775
|
+
return;
|
|
2776
|
+
}
|
|
2777
|
+
const parsedChunk = AzureOpenAiStreamChunkSchema.safeParse(
|
|
2778
|
+
JSON.parse(dataText)
|
|
2779
|
+
);
|
|
2780
|
+
if (!parsedChunk.success) {
|
|
2781
|
+
continue;
|
|
2782
|
+
}
|
|
2783
|
+
yield* applyAzureOpenAiStreamChunk(parsedChunk.data, accumulator);
|
|
2784
|
+
}
|
|
2785
|
+
throw buildProviderInvalidResponseError("Azure OpenAI", "stream termination");
|
|
2786
|
+
}
|
|
2787
|
+
async function* readServerSentEventDataLines2(body, abortSignal) {
|
|
2788
|
+
const reader = body.getReader();
|
|
2789
|
+
const decoder = new TextDecoder();
|
|
2790
|
+
let bufferedText = "";
|
|
2791
|
+
try {
|
|
2792
|
+
for (; ; ) {
|
|
2793
|
+
if (abortSignal?.aborted === true) {
|
|
2794
|
+
await reader.cancel();
|
|
2795
|
+
throw buildProviderCanceledError("Azure OpenAI");
|
|
2796
|
+
}
|
|
2797
|
+
const readResult = await reader.read();
|
|
2798
|
+
if (readResult.done) {
|
|
2799
|
+
return;
|
|
2800
|
+
}
|
|
2801
|
+
bufferedText += decoder.decode(readResult.value, { stream: true });
|
|
2802
|
+
const lines = bufferedText.split("\n");
|
|
2803
|
+
bufferedText = lines.pop() ?? "";
|
|
2804
|
+
for (const line of lines) {
|
|
2805
|
+
if (line.startsWith("data:")) {
|
|
2806
|
+
const dataText = line.slice("data:".length).trim();
|
|
2807
|
+
if (dataText.length > 0) {
|
|
2808
|
+
yield dataText;
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
}
|
|
2813
|
+
} catch (error) {
|
|
2814
|
+
if (error instanceof Error && isAbortError(error)) {
|
|
2815
|
+
throw buildProviderCanceledError("Azure OpenAI");
|
|
2816
|
+
}
|
|
2817
|
+
throw error;
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2820
|
+
function createAzureOpenAiStreamAccumulator() {
|
|
2821
|
+
return {
|
|
2822
|
+
contentText: "",
|
|
2823
|
+
toolCallsByIndex: /* @__PURE__ */ new Map()
|
|
2824
|
+
};
|
|
2825
|
+
}
|
|
2826
|
+
function* applyAzureOpenAiStreamChunk(chunk, accumulator) {
|
|
2827
|
+
if (chunk.usage !== null && chunk.usage !== void 0) {
|
|
2828
|
+
accumulator.usage = chunk.usage;
|
|
2829
|
+
}
|
|
2830
|
+
const choice = chunk.choices?.[0];
|
|
2831
|
+
if (choice === void 0) {
|
|
2832
|
+
return;
|
|
2833
|
+
}
|
|
2834
|
+
if (choice.finish_reason !== null && choice.finish_reason !== void 0) {
|
|
2835
|
+
accumulator.finishReason = choice.finish_reason;
|
|
2836
|
+
}
|
|
2837
|
+
if (choice.delta === void 0) {
|
|
2838
|
+
return;
|
|
2839
|
+
}
|
|
2840
|
+
const contentDelta = choice.delta.content;
|
|
2841
|
+
if (contentDelta !== null && contentDelta !== void 0 && contentDelta.length > 0) {
|
|
2842
|
+
accumulator.contentText += contentDelta;
|
|
2843
|
+
yield { type: "text_delta", text: contentDelta };
|
|
2844
|
+
}
|
|
2845
|
+
for (const toolCallDelta of choice.delta.tool_calls ?? []) {
|
|
2846
|
+
yield* applyAzureOpenAiToolCallDelta(toolCallDelta, accumulator);
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
function* applyAzureOpenAiToolCallDelta(toolCallDelta, accumulator) {
|
|
2850
|
+
const existingToolCall = accumulator.toolCallsByIndex.get(toolCallDelta.index);
|
|
2851
|
+
if (existingToolCall === void 0) {
|
|
2852
|
+
yield* startAzureOpenAiToolCallAccumulation(toolCallDelta, accumulator);
|
|
2853
|
+
return;
|
|
2854
|
+
}
|
|
2855
|
+
const argumentsDelta = toolCallDelta.function?.arguments;
|
|
2856
|
+
if (argumentsDelta !== void 0 && argumentsDelta.length > 0) {
|
|
2857
|
+
existingToolCall.argumentsJsonText += argumentsDelta;
|
|
2858
|
+
yield {
|
|
2859
|
+
type: "tool_call_input_delta",
|
|
2860
|
+
id: existingToolCall.id,
|
|
2861
|
+
inputJsonText: argumentsDelta
|
|
2862
|
+
};
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
function* startAzureOpenAiToolCallAccumulation(toolCallDelta, accumulator) {
|
|
2866
|
+
const toolName = toolCallDelta.function?.name;
|
|
2867
|
+
if (toolCallDelta.id === void 0 || toolName === void 0) {
|
|
2868
|
+
throw buildProviderInvalidResponseError(
|
|
2869
|
+
"Azure OpenAI",
|
|
2870
|
+
"stream tool call start"
|
|
2871
|
+
);
|
|
2872
|
+
}
|
|
2873
|
+
const startedToolCall = {
|
|
2874
|
+
id: toolCallDelta.id,
|
|
2875
|
+
toolName,
|
|
2876
|
+
argumentsJsonText: toolCallDelta.function?.arguments ?? ""
|
|
2877
|
+
};
|
|
2878
|
+
accumulator.toolCallsByIndex.set(toolCallDelta.index, startedToolCall);
|
|
2879
|
+
yield {
|
|
2880
|
+
type: "tool_call_started",
|
|
2881
|
+
id: startedToolCall.id,
|
|
2882
|
+
toolName: startedToolCall.toolName
|
|
2883
|
+
};
|
|
2884
|
+
if (startedToolCall.argumentsJsonText.length > 0) {
|
|
2885
|
+
yield {
|
|
2886
|
+
type: "tool_call_input_delta",
|
|
2887
|
+
id: startedToolCall.id,
|
|
2888
|
+
inputJsonText: startedToolCall.argumentsJsonText
|
|
2889
|
+
};
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
function buildAzureOpenAiStreamResult(accumulator, latencyMs) {
|
|
2893
|
+
const result = {
|
|
2894
|
+
content: accumulator.contentText,
|
|
2895
|
+
tokenUsage: mapAzureOpenAiUsageToTokenUsage(
|
|
2896
|
+
accumulator.usage ?? {
|
|
2897
|
+
prompt_tokens: 0,
|
|
2898
|
+
completion_tokens: 0,
|
|
2899
|
+
total_tokens: 0
|
|
2900
|
+
}
|
|
2901
|
+
),
|
|
2902
|
+
latencyMs
|
|
2903
|
+
};
|
|
2904
|
+
const toolCalls = [...accumulator.toolCallsByIndex.values()].map(
|
|
2905
|
+
mapAccumulatedToolCallToModelToolCall2
|
|
2906
|
+
);
|
|
2907
|
+
if (toolCalls.length > 0) {
|
|
2908
|
+
result.toolCalls = toolCalls;
|
|
2909
|
+
}
|
|
2910
|
+
if (accumulator.finishReason !== void 0) {
|
|
2911
|
+
result.stopReason = normalizeAzureOpenAiFinishReason(
|
|
2912
|
+
accumulator.finishReason
|
|
2913
|
+
);
|
|
2914
|
+
}
|
|
2915
|
+
return result;
|
|
2916
|
+
}
|
|
2917
|
+
function mapAccumulatedToolCallToModelToolCall2(toolCallAccumulation) {
|
|
2918
|
+
return {
|
|
2919
|
+
id: toolCallAccumulation.id,
|
|
2920
|
+
toolName: toolCallAccumulation.toolName,
|
|
2921
|
+
input: parseAzureOpenAiToolArgumentsJson(
|
|
2922
|
+
toolCallAccumulation.argumentsJsonText
|
|
2923
|
+
)
|
|
2924
|
+
};
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2927
|
+
// src/azure-openai-adapter.ts
|
|
2928
|
+
var defaultAzureOpenAiApiVersion = "2024-10-21";
|
|
2929
|
+
var azureDeploymentModelPlaceholder = "azure-deployment";
|
|
2930
|
+
function azureOpenai(options) {
|
|
2931
|
+
return {
|
|
2932
|
+
name: `azure-openai:${options.deployment}`,
|
|
2933
|
+
async generateChatCompletion(request) {
|
|
2934
|
+
return await executeAzureOpenAiAdapterCall(options, {
|
|
2935
|
+
messages: request.messages,
|
|
2936
|
+
temperature: request.temperature ?? options.temperature,
|
|
2937
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
2938
|
+
tools: request.tools,
|
|
2939
|
+
toolChoice: request.toolChoice,
|
|
2940
|
+
abortSignal: request.abortSignal,
|
|
2941
|
+
extraBody: request.extraBody
|
|
2942
|
+
});
|
|
2943
|
+
},
|
|
2944
|
+
async generateStructuredOutput(request) {
|
|
2945
|
+
const completion = await executeAzureOpenAiAdapterCall(options, {
|
|
2946
|
+
messages: request.messages,
|
|
2947
|
+
temperature: request.temperature ?? options.temperature,
|
|
2948
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
2949
|
+
structuredOutputJsonSchema: buildOpenAiStructuredOutputJsonSchema(
|
|
2950
|
+
request.schema
|
|
2951
|
+
),
|
|
2952
|
+
abortSignal: request.abortSignal
|
|
2953
|
+
});
|
|
2954
|
+
return {
|
|
2955
|
+
value: parseStructuredJsonText(completion.content, request.schema),
|
|
2956
|
+
tokenUsage: completion.tokenUsage,
|
|
2957
|
+
latencyMs: completion.latencyMs
|
|
2958
|
+
};
|
|
2959
|
+
},
|
|
2960
|
+
streamChatCompletion(request) {
|
|
2961
|
+
return streamAzureOpenAiChatCompletion(
|
|
2962
|
+
buildAzureOpenAiStreamInput(options, request)
|
|
2963
|
+
);
|
|
2964
|
+
}
|
|
2965
|
+
};
|
|
2966
|
+
}
|
|
2967
|
+
function buildAzureOpenAiChatCompletionsUrl(options) {
|
|
2968
|
+
const endpoint = resolveAzureOpenAiEndpoint(options);
|
|
2969
|
+
const apiVersion = options.apiVersion ?? defaultAzureOpenAiApiVersion;
|
|
2970
|
+
return `${endpoint}/openai/deployments/${encodeURIComponent(options.deployment)}/chat/completions?api-version=${encodeURIComponent(apiVersion)}`;
|
|
2971
|
+
}
|
|
2972
|
+
function resolveAzureOpenAiEndpoint(options) {
|
|
2973
|
+
if (options.baseURL !== void 0 && options.baseURL.length > 0) {
|
|
2974
|
+
return options.baseURL.replace(/\/+$/, "");
|
|
2975
|
+
}
|
|
2976
|
+
if (options.resourceName !== void 0 && options.resourceName.length > 0) {
|
|
2977
|
+
return `https://${options.resourceName}.openai.azure.com`;
|
|
2978
|
+
}
|
|
2979
|
+
throw new import_errors33.AppError({
|
|
2980
|
+
code: import_errors32.AppErrorCode.BadRequest,
|
|
2981
|
+
message: "Azure OpenAI endpoint is missing. Pass resourceName or baseURL to azureOpenai().",
|
|
2982
|
+
statusCode: 400
|
|
2983
|
+
});
|
|
2984
|
+
}
|
|
2985
|
+
function buildAzureOpenAiRequestHeaders(options) {
|
|
2986
|
+
return {
|
|
2987
|
+
"content-type": "application/json",
|
|
2988
|
+
"api-key": resolveProviderApiKey({
|
|
2989
|
+
providerLabel: "Azure OpenAI",
|
|
2990
|
+
adapterFunctionName: "azureOpenai()",
|
|
2991
|
+
baseEnvVarName: "AZURE_OPENAI_API_KEY",
|
|
2992
|
+
apiKey: options.apiKey,
|
|
2993
|
+
apiKeyName: options.apiKeyName
|
|
2994
|
+
})
|
|
2995
|
+
};
|
|
2996
|
+
}
|
|
2997
|
+
function buildAzureOpenAiChatRequestBody(input) {
|
|
2998
|
+
const requestBody = buildOpenAiRequestBody(
|
|
2999
|
+
azureDeploymentModelPlaceholder,
|
|
3000
|
+
input
|
|
3001
|
+
);
|
|
3002
|
+
const { model: ignoredModel, ...requestBodyWithoutModel } = requestBody;
|
|
3003
|
+
void ignoredModel;
|
|
3004
|
+
return requestBodyWithoutModel;
|
|
3005
|
+
}
|
|
3006
|
+
async function executeAzureOpenAiAdapterCall(options, input) {
|
|
3007
|
+
return await executeProviderCallWithRetry(
|
|
3008
|
+
options.retry,
|
|
3009
|
+
async () => await requestAzureOpenAiChatCompletion(options, input)
|
|
3010
|
+
);
|
|
3011
|
+
}
|
|
3012
|
+
async function requestAzureOpenAiChatCompletion(options, input) {
|
|
3013
|
+
const fetchImplementation = options.fetchImplementation ?? fetch;
|
|
3014
|
+
const requestBody = mergeProviderRequestExtraBody(
|
|
3015
|
+
buildAzureOpenAiChatRequestBody(input),
|
|
3016
|
+
options.extraBody,
|
|
3017
|
+
input.extraBody
|
|
3018
|
+
);
|
|
3019
|
+
const startedAt = Date.now();
|
|
3020
|
+
const response = await executeAbortableProviderFetch(
|
|
3021
|
+
"Azure OpenAI",
|
|
3022
|
+
async () => await fetchImplementation(buildAzureOpenAiChatCompletionsUrl(options), {
|
|
3023
|
+
method: "POST",
|
|
3024
|
+
headers: buildAzureOpenAiRequestHeaders(options),
|
|
3025
|
+
body: JSON.stringify(requestBody),
|
|
3026
|
+
signal: input.abortSignal
|
|
3027
|
+
})
|
|
3028
|
+
);
|
|
3029
|
+
const latencyMs = Date.now() - startedAt;
|
|
3030
|
+
if (!response.ok) {
|
|
3031
|
+
throw buildProviderStatusError("Azure OpenAI", response.status);
|
|
3032
|
+
}
|
|
3033
|
+
const parseResult = AzureOpenAiChatCompletionResponseSchema.safeParse(
|
|
3034
|
+
await response.json()
|
|
3035
|
+
);
|
|
3036
|
+
if (!parseResult.success) {
|
|
3037
|
+
throw buildProviderInvalidResponseError("Azure OpenAI", "chat completion");
|
|
3038
|
+
}
|
|
3039
|
+
return mapAzureOpenAiResponseToChatCompletionResult(
|
|
3040
|
+
parseResult.data,
|
|
3041
|
+
latencyMs
|
|
3042
|
+
);
|
|
3043
|
+
}
|
|
3044
|
+
function buildAzureOpenAiStreamInput(options, request) {
|
|
3045
|
+
const requestBody = mergeProviderRequestExtraBody(
|
|
3046
|
+
buildAzureOpenAiChatRequestBody({
|
|
3047
|
+
messages: request.messages,
|
|
3048
|
+
temperature: request.temperature ?? options.temperature,
|
|
3049
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
3050
|
+
tools: request.tools,
|
|
3051
|
+
toolChoice: request.toolChoice,
|
|
3052
|
+
abortSignal: request.abortSignal,
|
|
3053
|
+
extraBody: request.extraBody
|
|
3054
|
+
}),
|
|
3055
|
+
options.extraBody,
|
|
3056
|
+
request.extraBody
|
|
3057
|
+
);
|
|
3058
|
+
return {
|
|
3059
|
+
url: buildAzureOpenAiChatCompletionsUrl(options),
|
|
3060
|
+
headers: buildAzureOpenAiRequestHeaders(options),
|
|
3061
|
+
body: {
|
|
3062
|
+
...requestBody,
|
|
3063
|
+
stream: true,
|
|
3064
|
+
stream_options: { include_usage: true }
|
|
3065
|
+
},
|
|
3066
|
+
fetchImplementation: options.fetchImplementation ?? fetch,
|
|
3067
|
+
retry: options.retry,
|
|
3068
|
+
abortSignal: request.abortSignal
|
|
3069
|
+
};
|
|
3070
|
+
}
|
|
3071
|
+
|
|
3072
|
+
// src/bedrock-adapter.ts
|
|
3073
|
+
var import_zod11 = require("zod");
|
|
3074
|
+
var import_errors34 = require("@assemble-dev/shared-types/errors");
|
|
3075
|
+
var import_errors35 = require("@assemble-dev/shared-utils/errors");
|
|
3076
|
+
|
|
3077
|
+
// src/bedrock-sigv4.ts
|
|
3078
|
+
var awsSigV4Algorithm = "AWS4-HMAC-SHA256";
|
|
3079
|
+
async function signAwsRequestWithSigV4(input) {
|
|
3080
|
+
const amzDate = formatAmzDateTime(input.signingDate ?? /* @__PURE__ */ new Date());
|
|
3081
|
+
const dateStamp = amzDate.slice(0, 8);
|
|
3082
|
+
const headersToSign = buildHeadersToSign(input, amzDate);
|
|
3083
|
+
const canonicalHeaderEntries = buildCanonicalHeaderEntries(headersToSign);
|
|
3084
|
+
const signedHeaderNames = canonicalHeaderEntries.map(([headerName]) => headerName).join(";");
|
|
3085
|
+
const credentialScope = `${dateStamp}/${input.region}/${input.service}/aws4_request`;
|
|
3086
|
+
const signatureHex = await computeAwsSigV4Signature(
|
|
3087
|
+
input,
|
|
3088
|
+
amzDate,
|
|
3089
|
+
credentialScope,
|
|
3090
|
+
canonicalHeaderEntries,
|
|
3091
|
+
signedHeaderNames
|
|
3092
|
+
);
|
|
3093
|
+
return {
|
|
3094
|
+
...headersToSign,
|
|
3095
|
+
authorization: `${awsSigV4Algorithm} Credential=${input.credentials.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaderNames}, Signature=${signatureHex}`
|
|
3096
|
+
};
|
|
3097
|
+
}
|
|
3098
|
+
async function computeAwsSigV4Signature(input, amzDate, credentialScope, canonicalHeaderEntries, signedHeaderNames) {
|
|
3099
|
+
const canonicalRequest = await buildCanonicalRequest(
|
|
3100
|
+
input,
|
|
3101
|
+
canonicalHeaderEntries,
|
|
3102
|
+
signedHeaderNames
|
|
3103
|
+
);
|
|
3104
|
+
const stringToSign = [
|
|
3105
|
+
awsSigV4Algorithm,
|
|
3106
|
+
amzDate,
|
|
3107
|
+
credentialScope,
|
|
3108
|
+
await hashSha256Hex(canonicalRequest)
|
|
3109
|
+
].join("\n");
|
|
3110
|
+
const signingKey = await deriveAwsSigningKey(
|
|
3111
|
+
input.credentials.secretAccessKey,
|
|
3112
|
+
amzDate.slice(0, 8),
|
|
3113
|
+
input.region,
|
|
3114
|
+
input.service
|
|
3115
|
+
);
|
|
3116
|
+
return bytesToHex(await computeHmacSha256(signingKey, stringToSign));
|
|
3117
|
+
}
|
|
3118
|
+
function buildHeadersToSign(input, amzDate) {
|
|
3119
|
+
const headersToSign = {};
|
|
3120
|
+
for (const [headerName, headerValue] of Object.entries(input.headers)) {
|
|
3121
|
+
headersToSign[headerName.toLowerCase()] = headerValue;
|
|
3122
|
+
}
|
|
3123
|
+
headersToSign.host = input.url.host;
|
|
3124
|
+
headersToSign["x-amz-date"] = amzDate;
|
|
3125
|
+
if (input.credentials.sessionToken !== void 0) {
|
|
3126
|
+
headersToSign["x-amz-security-token"] = input.credentials.sessionToken;
|
|
3127
|
+
}
|
|
3128
|
+
return headersToSign;
|
|
3129
|
+
}
|
|
3130
|
+
function buildCanonicalHeaderEntries(headersToSign) {
|
|
3131
|
+
return Object.entries(headersToSign).map(([headerName, headerValue]) => [
|
|
3132
|
+
headerName.toLowerCase(),
|
|
3133
|
+
headerValue.trim().replace(/\s+/g, " ")
|
|
3134
|
+
]).sort(([leftName], [rightName]) => leftName.localeCompare(rightName));
|
|
3135
|
+
}
|
|
3136
|
+
async function buildCanonicalRequest(input, canonicalHeaderEntries, signedHeaderNames) {
|
|
3137
|
+
const canonicalHeadersText = canonicalHeaderEntries.map(([headerName, headerValue]) => `${headerName}:${headerValue}`).join("\n");
|
|
3138
|
+
return [
|
|
3139
|
+
input.method.toUpperCase(),
|
|
3140
|
+
buildCanonicalUri(input.url.pathname),
|
|
3141
|
+
buildCanonicalQueryString(input.url.searchParams),
|
|
3142
|
+
`${canonicalHeadersText}
|
|
3143
|
+
`,
|
|
3144
|
+
signedHeaderNames,
|
|
3145
|
+
await hashSha256Hex(input.bodyText)
|
|
3146
|
+
].join("\n");
|
|
3147
|
+
}
|
|
3148
|
+
function buildCanonicalUri(pathname) {
|
|
3149
|
+
if (pathname.length === 0) {
|
|
3150
|
+
return "/";
|
|
3151
|
+
}
|
|
3152
|
+
return pathname.split("/").map(encodeRfc3986UriComponent).join("/");
|
|
3153
|
+
}
|
|
3154
|
+
function buildCanonicalQueryString(searchParams) {
|
|
3155
|
+
const encodedEntries = [];
|
|
3156
|
+
searchParams.forEach((parameterValue, parameterName) => {
|
|
3157
|
+
encodedEntries.push([
|
|
3158
|
+
encodeRfc3986UriComponent(parameterName),
|
|
3159
|
+
encodeRfc3986UriComponent(parameterValue)
|
|
3160
|
+
]);
|
|
3161
|
+
});
|
|
3162
|
+
return encodedEntries.sort(
|
|
3163
|
+
([leftName, leftValue], [rightName, rightValue]) => leftName.localeCompare(rightName) || leftValue.localeCompare(rightValue)
|
|
3164
|
+
).map(([parameterName, parameterValue]) => `${parameterName}=${parameterValue}`).join("&");
|
|
3165
|
+
}
|
|
3166
|
+
function encodeRfc3986UriComponent(value) {
|
|
3167
|
+
return encodeURIComponent(value).replace(
|
|
3168
|
+
/[!'()*]/g,
|
|
3169
|
+
(character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`
|
|
3170
|
+
);
|
|
3171
|
+
}
|
|
3172
|
+
function formatAmzDateTime(date) {
|
|
3173
|
+
return date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
|
|
3174
|
+
}
|
|
3175
|
+
async function deriveAwsSigningKey(secretAccessKey, dateStamp, region, service) {
|
|
3176
|
+
const dateKey = await computeHmacSha256(
|
|
3177
|
+
new TextEncoder().encode(`AWS4${secretAccessKey}`),
|
|
3178
|
+
dateStamp
|
|
3179
|
+
);
|
|
3180
|
+
const regionKey = await computeHmacSha256(dateKey, region);
|
|
3181
|
+
const serviceKey = await computeHmacSha256(regionKey, service);
|
|
3182
|
+
return await computeHmacSha256(serviceKey, "aws4_request");
|
|
3183
|
+
}
|
|
3184
|
+
async function hashSha256Hex(text) {
|
|
3185
|
+
const digest = await crypto.subtle.digest(
|
|
3186
|
+
"SHA-256",
|
|
3187
|
+
new TextEncoder().encode(text)
|
|
3188
|
+
);
|
|
3189
|
+
return bytesToHex(new Uint8Array(digest));
|
|
3190
|
+
}
|
|
3191
|
+
async function computeHmacSha256(keyBytes, text) {
|
|
3192
|
+
const hmacKey = await crypto.subtle.importKey(
|
|
3193
|
+
"raw",
|
|
3194
|
+
keyBytes,
|
|
3195
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
3196
|
+
false,
|
|
3197
|
+
["sign"]
|
|
3198
|
+
);
|
|
3199
|
+
const signature = await crypto.subtle.sign(
|
|
3200
|
+
"HMAC",
|
|
3201
|
+
hmacKey,
|
|
3202
|
+
new TextEncoder().encode(text)
|
|
3203
|
+
);
|
|
3204
|
+
return new Uint8Array(signature);
|
|
3205
|
+
}
|
|
3206
|
+
function bytesToHex(bytes) {
|
|
3207
|
+
return Array.from(bytes).map((byteValue) => byteValue.toString(16).padStart(2, "0")).join("");
|
|
3208
|
+
}
|
|
3209
|
+
|
|
3210
|
+
// src/bedrock-adapter.ts
|
|
3211
|
+
var bedrockAnthropicVersion = "bedrock-2023-05-31";
|
|
3212
|
+
var defaultBedrockMaxOutputTokens = 1024;
|
|
3213
|
+
var bedrockSigningServiceName = "bedrock";
|
|
3214
|
+
var bedrockModelPlaceholder = "bedrock-invoke-model";
|
|
3215
|
+
var BedrockEnvCredentialsSchema = import_zod11.z.object({
|
|
3216
|
+
AWS_ACCESS_KEY_ID: import_zod11.z.string().optional(),
|
|
3217
|
+
AWS_SECRET_ACCESS_KEY: import_zod11.z.string().optional(),
|
|
3218
|
+
AWS_SESSION_TOKEN: import_zod11.z.string().optional()
|
|
3219
|
+
});
|
|
3220
|
+
function bedrock(options) {
|
|
3221
|
+
return {
|
|
3222
|
+
name: `bedrock:${options.modelId}`,
|
|
3223
|
+
async generateChatCompletion(request) {
|
|
3224
|
+
return await executeBedrockAdapterCall(options, {
|
|
3225
|
+
messages: request.messages,
|
|
3226
|
+
temperature: request.temperature ?? options.temperature,
|
|
3227
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
3228
|
+
tools: request.tools,
|
|
3229
|
+
toolChoice: request.toolChoice,
|
|
3230
|
+
abortSignal: request.abortSignal,
|
|
3231
|
+
extraBody: request.extraBody
|
|
3232
|
+
});
|
|
3233
|
+
},
|
|
3234
|
+
async generateStructuredOutput(request) {
|
|
3235
|
+
const completion = await executeBedrockAdapterCall(options, {
|
|
3236
|
+
messages: [
|
|
3237
|
+
buildBedrockStructuredOutputSystemMessage(request.schema),
|
|
3238
|
+
...request.messages
|
|
3239
|
+
],
|
|
3240
|
+
temperature: request.temperature ?? options.temperature,
|
|
3241
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
3242
|
+
abortSignal: request.abortSignal
|
|
3243
|
+
});
|
|
3244
|
+
return {
|
|
3245
|
+
value: parseStructuredJsonText(completion.content, request.schema),
|
|
3246
|
+
tokenUsage: completion.tokenUsage,
|
|
3247
|
+
latencyMs: completion.latencyMs
|
|
3248
|
+
};
|
|
3249
|
+
}
|
|
3250
|
+
};
|
|
3251
|
+
}
|
|
3252
|
+
function buildBedrockInvokeModelUrl(region, modelId) {
|
|
3253
|
+
return `https://bedrock-runtime.${region}.amazonaws.com/model/${encodeURIComponent(modelId)}/invoke`;
|
|
3254
|
+
}
|
|
3255
|
+
function resolveBedrockCredentials(options) {
|
|
3256
|
+
if (options.credentials !== void 0) {
|
|
3257
|
+
return options.credentials;
|
|
3258
|
+
}
|
|
3259
|
+
const parsedEnv = BedrockEnvCredentialsSchema.parse(process.env);
|
|
3260
|
+
const accessKeyId = parsedEnv.AWS_ACCESS_KEY_ID;
|
|
3261
|
+
const secretAccessKey = parsedEnv.AWS_SECRET_ACCESS_KEY;
|
|
3262
|
+
if (accessKeyId === void 0 || accessKeyId.length === 0 || secretAccessKey === void 0 || secretAccessKey.length === 0) {
|
|
3263
|
+
throw new import_errors35.AppError({
|
|
3264
|
+
code: import_errors34.AppErrorCode.Unauthorized,
|
|
3265
|
+
message: "AWS credentials are missing. Pass credentials to bedrock() or set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables.",
|
|
3266
|
+
statusCode: 401
|
|
3267
|
+
});
|
|
3268
|
+
}
|
|
3269
|
+
const credentials = { accessKeyId, secretAccessKey };
|
|
3270
|
+
const sessionToken = parsedEnv.AWS_SESSION_TOKEN;
|
|
3271
|
+
if (sessionToken !== void 0 && sessionToken.length > 0) {
|
|
3272
|
+
credentials.sessionToken = sessionToken;
|
|
3273
|
+
}
|
|
3274
|
+
return credentials;
|
|
3275
|
+
}
|
|
3276
|
+
async function executeBedrockAdapterCall(options, input) {
|
|
3277
|
+
return await executeProviderCallWithRetry(
|
|
3278
|
+
options.retry,
|
|
3279
|
+
async () => await requestBedrockInvokeModel(options, input)
|
|
3280
|
+
);
|
|
3281
|
+
}
|
|
3282
|
+
async function requestBedrockInvokeModel(options, input) {
|
|
3283
|
+
const credentials = resolveBedrockCredentials(options);
|
|
3284
|
+
const fetchImplementation = options.fetchImplementation ?? fetch;
|
|
3285
|
+
const requestBody = mergeProviderRequestExtraBody(
|
|
3286
|
+
buildBedrockInvokeModelRequestBody(input),
|
|
3287
|
+
options.extraBody,
|
|
3288
|
+
input.extraBody
|
|
3289
|
+
);
|
|
3290
|
+
const bodyText = JSON.stringify(requestBody);
|
|
3291
|
+
const url = new URL(buildBedrockInvokeModelUrl(options.region, options.modelId));
|
|
3292
|
+
const signedHeaders = await signAwsRequestWithSigV4({
|
|
3293
|
+
method: "POST",
|
|
3294
|
+
url,
|
|
3295
|
+
headers: { "content-type": "application/json" },
|
|
3296
|
+
bodyText,
|
|
3297
|
+
region: options.region,
|
|
3298
|
+
service: bedrockSigningServiceName,
|
|
3299
|
+
credentials
|
|
3300
|
+
});
|
|
3301
|
+
const startedAt = Date.now();
|
|
3302
|
+
const response = await executeAbortableProviderFetch(
|
|
3303
|
+
"Bedrock",
|
|
3304
|
+
async () => await fetchImplementation(url.toString(), {
|
|
3305
|
+
method: "POST",
|
|
3306
|
+
headers: signedHeaders,
|
|
3307
|
+
body: bodyText,
|
|
3308
|
+
signal: input.abortSignal
|
|
3309
|
+
})
|
|
3310
|
+
);
|
|
3311
|
+
const latencyMs = Date.now() - startedAt;
|
|
3312
|
+
if (!response.ok) {
|
|
3313
|
+
throw buildProviderStatusError("Bedrock", response.status);
|
|
3314
|
+
}
|
|
3315
|
+
const parseResult = AnthropicMessagesResponseSchema.safeParse(
|
|
3316
|
+
await response.json()
|
|
3317
|
+
);
|
|
3318
|
+
if (!parseResult.success) {
|
|
3319
|
+
throw buildProviderInvalidResponseError("Bedrock", "invoke model");
|
|
3320
|
+
}
|
|
3321
|
+
return mapAnthropicResponseToChatCompletionResult(parseResult.data, latencyMs);
|
|
3322
|
+
}
|
|
3323
|
+
function buildBedrockInvokeModelRequestBody(input) {
|
|
3324
|
+
const anthropicRequestBody = buildAnthropicRequestBody(
|
|
3325
|
+
{
|
|
3326
|
+
model: bedrockModelPlaceholder,
|
|
3327
|
+
defaultMaxOutputTokens: defaultBedrockMaxOutputTokens
|
|
3328
|
+
},
|
|
3329
|
+
input
|
|
3330
|
+
);
|
|
3331
|
+
const {
|
|
3332
|
+
model: ignoredModel,
|
|
3333
|
+
stream: ignoredStream,
|
|
3334
|
+
...requestBodyWithoutModel
|
|
3335
|
+
} = anthropicRequestBody;
|
|
3336
|
+
void ignoredModel;
|
|
3337
|
+
void ignoredStream;
|
|
3338
|
+
return {
|
|
3339
|
+
...requestBodyWithoutModel,
|
|
3340
|
+
anthropic_version: bedrockAnthropicVersion
|
|
3341
|
+
};
|
|
3342
|
+
}
|
|
3343
|
+
function buildBedrockStructuredOutputSystemMessage(schema) {
|
|
3344
|
+
return {
|
|
3345
|
+
role: "system",
|
|
3346
|
+
content: `Respond with a single JSON object that satisfies the following JSON Schema. Output only valid JSON with no surrounding text.
|
|
3347
|
+
|
|
3348
|
+
JSON Schema:
|
|
3349
|
+
${JSON.stringify(convertZodSchemaToJsonSchema(schema))}`
|
|
3350
|
+
};
|
|
3351
|
+
}
|
|
2221
3352
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2222
3353
|
0 && (module.exports = {
|
|
2223
3354
|
AnthropicMessagesResponseSchema,
|
|
2224
3355
|
AnthropicStreamEventSchema,
|
|
3356
|
+
AzureOpenAiChatCompletionResponseSchema,
|
|
2225
3357
|
ChatMessageCacheControlSchema,
|
|
2226
3358
|
ChatMessageRoleSchema,
|
|
2227
3359
|
ChatMessageSchema,
|
|
@@ -2232,16 +3364,30 @@ function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
|
|
|
2232
3364
|
anthropicBatchJsonOnlySystemInstruction,
|
|
2233
3365
|
anthropicBatchTraceWorkflowName,
|
|
2234
3366
|
applyCacheControlToLastContentBlock,
|
|
3367
|
+
awsSigV4Algorithm,
|
|
3368
|
+
azureOpenai,
|
|
3369
|
+
bedrock,
|
|
3370
|
+
bedrockAnthropicVersion,
|
|
2235
3371
|
buildAnthropicCacheControl,
|
|
2236
3372
|
buildAnthropicRequestBody,
|
|
3373
|
+
buildAnthropicStructuredOutputJsonSchema,
|
|
3374
|
+
buildAzureOpenAiChatCompletionsUrl,
|
|
3375
|
+
buildAzureOpenAiChatRequestBody,
|
|
3376
|
+
buildBedrockInvokeModelRequestBody,
|
|
3377
|
+
buildBedrockInvokeModelUrl,
|
|
3378
|
+
buildGeminiResponseSchema,
|
|
2237
3379
|
buildOpenAiRequestBody,
|
|
3380
|
+
buildOpenAiStructuredOutputJsonSchema,
|
|
2238
3381
|
buildProviderCanceledError,
|
|
2239
3382
|
calculateProviderRetryDelayMs,
|
|
3383
|
+
convertZodSchemaToJsonSchema,
|
|
2240
3384
|
createAnthropicBatchClient,
|
|
2241
3385
|
defaultAnthropicBaseUrl,
|
|
2242
3386
|
defaultAnthropicBatchPollIntervalMs,
|
|
2243
3387
|
defaultAnthropicBatchTimeoutMs,
|
|
2244
3388
|
defaultAnthropicMaxOutputTokens,
|
|
3389
|
+
defaultAzureOpenAiApiVersion,
|
|
3390
|
+
defaultBedrockMaxOutputTokens,
|
|
2245
3391
|
defaultGeminiBaseUrl,
|
|
2246
3392
|
defaultOpenAiBaseUrl,
|
|
2247
3393
|
defaultProviderRetryInitialDelayMs,
|
|
@@ -2252,6 +3398,7 @@ function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
|
|
|
2252
3398
|
executeProviderCallWithModelFallback,
|
|
2253
3399
|
executeProviderCallWithRetry,
|
|
2254
3400
|
extractAnthropicTextContent,
|
|
3401
|
+
extractAnthropicThinkingText,
|
|
2255
3402
|
extractAnthropicToolCalls,
|
|
2256
3403
|
extractMessageText,
|
|
2257
3404
|
gemini,
|
|
@@ -2260,6 +3407,8 @@ function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
|
|
|
2260
3407
|
joinSystemMessageText,
|
|
2261
3408
|
mapAnthropicResponseToChatCompletionResult,
|
|
2262
3409
|
mapAnthropicUsageToTokenUsage,
|
|
3410
|
+
mapAzureOpenAiResponseToChatCompletionResult,
|
|
3411
|
+
mapAzureOpenAiUsageToTokenUsage,
|
|
2263
3412
|
mapChatMessageToAnthropicRequestMessage,
|
|
2264
3413
|
mapChatMessageToOpenAiRequestMessage,
|
|
2265
3414
|
mapModelToolChoiceToAnthropicToolChoice,
|
|
@@ -2269,11 +3418,21 @@ function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
|
|
|
2269
3418
|
mergeProviderRequestExtraBody,
|
|
2270
3419
|
mockModel,
|
|
2271
3420
|
normalizeAnthropicStopReason,
|
|
3421
|
+
normalizeAzureOpenAiFinishReason,
|
|
3422
|
+
openAiStructuredOutputSchemaName,
|
|
2272
3423
|
openai,
|
|
2273
3424
|
parseAnthropicBatchStructuredContent,
|
|
2274
3425
|
parseAnthropicStreamEvents,
|
|
2275
3426
|
parseAnthropicToolInputJson,
|
|
3427
|
+
parseAzureOpenAiStreamEvents,
|
|
3428
|
+
parseAzureOpenAiToolArgumentsJson,
|
|
2276
3429
|
resolveAnthropicPromptCachingSettings,
|
|
3430
|
+
resolveBedrockCredentials,
|
|
2277
3431
|
resolveProviderApiKey,
|
|
2278
|
-
|
|
3432
|
+
sanitizeJsonSchemaForAnthropicStructuredOutput,
|
|
3433
|
+
sanitizeJsonSchemaForGeminiResponseSchema,
|
|
3434
|
+
sanitizeJsonSchemaForOpenAiStructuredOutput,
|
|
3435
|
+
signAwsRequestWithSigV4,
|
|
3436
|
+
streamAnthropicChatCompletion,
|
|
3437
|
+
streamAzureOpenAiChatCompletion
|
|
2279
3438
|
});
|