@assemble-dev/providers 0.1.0 → 0.2.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 +361 -71
- package/dist/index.d.cts +94 -15
- package/dist/index.d.ts +94 -15
- package/dist/index.js +356 -71
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -22,12 +22,17 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AnthropicMessagesResponseSchema: () => AnthropicMessagesResponseSchema,
|
|
24
24
|
AnthropicStreamEventSchema: () => AnthropicStreamEventSchema,
|
|
25
|
+
ChatMessageCacheControlSchema: () => ChatMessageCacheControlSchema,
|
|
25
26
|
ChatMessageRoleSchema: () => ChatMessageRoleSchema,
|
|
26
27
|
ChatMessageSchema: () => ChatMessageSchema,
|
|
27
28
|
ChatStopReasonSchema: () => ChatStopReasonSchema,
|
|
28
29
|
MessageContentBlockSchema: () => MessageContentBlockSchema,
|
|
29
30
|
ModelToolCallSchema: () => ModelToolCallSchema,
|
|
30
31
|
anthropic: () => anthropic,
|
|
32
|
+
anthropicBatchJsonOnlySystemInstruction: () => anthropicBatchJsonOnlySystemInstruction,
|
|
33
|
+
anthropicBatchTraceWorkflowName: () => anthropicBatchTraceWorkflowName,
|
|
34
|
+
applyCacheControlToLastContentBlock: () => applyCacheControlToLastContentBlock,
|
|
35
|
+
buildAnthropicCacheControl: () => buildAnthropicCacheControl,
|
|
31
36
|
buildAnthropicRequestBody: () => buildAnthropicRequestBody,
|
|
32
37
|
buildOpenAiRequestBody: () => buildOpenAiRequestBody,
|
|
33
38
|
buildProviderCanceledError: () => buildProviderCanceledError,
|
|
@@ -61,11 +66,14 @@ __export(index_exports, {
|
|
|
61
66
|
mapModelToolChoiceToOpenAiToolChoice: () => mapModelToolChoiceToOpenAiToolChoice,
|
|
62
67
|
mapModelToolDefinitionToOpenAiTool: () => mapModelToolDefinitionToOpenAiTool,
|
|
63
68
|
mapModelToolDefinitionsToAnthropicTools: () => mapModelToolDefinitionsToAnthropicTools,
|
|
69
|
+
mergeProviderRequestExtraBody: () => mergeProviderRequestExtraBody,
|
|
64
70
|
mockModel: () => mockModel,
|
|
65
71
|
normalizeAnthropicStopReason: () => normalizeAnthropicStopReason,
|
|
66
72
|
openai: () => openai,
|
|
73
|
+
parseAnthropicBatchStructuredContent: () => parseAnthropicBatchStructuredContent,
|
|
67
74
|
parseAnthropicStreamEvents: () => parseAnthropicStreamEvents,
|
|
68
75
|
parseAnthropicToolInputJson: () => parseAnthropicToolInputJson,
|
|
76
|
+
resolveAnthropicPromptCachingSettings: () => resolveAnthropicPromptCachingSettings,
|
|
69
77
|
resolveProviderApiKey: () => resolveProviderApiKey,
|
|
70
78
|
streamAnthropicChatCompletion: () => streamAnthropicChatCompletion
|
|
71
79
|
});
|
|
@@ -101,12 +109,16 @@ var ModelToolCallSchema = import_zod.z.object({
|
|
|
101
109
|
toolName: import_zod.z.string(),
|
|
102
110
|
input: import_json.JsonValueSchema
|
|
103
111
|
});
|
|
112
|
+
var ChatMessageCacheControlSchema = import_zod.z.object({
|
|
113
|
+
ttl: import_zod.z.enum(["5m", "1h"]).optional()
|
|
114
|
+
});
|
|
104
115
|
var ChatMessageSchema = import_zod.z.object({
|
|
105
116
|
role: ChatMessageRoleSchema,
|
|
106
117
|
content: import_zod.z.union([import_zod.z.string(), import_zod.z.array(MessageContentBlockSchema)]),
|
|
107
118
|
toolName: import_zod.z.string().optional(),
|
|
108
119
|
toolCallId: import_zod.z.string().optional(),
|
|
109
|
-
toolCalls: import_zod.z.array(ModelToolCallSchema).optional()
|
|
120
|
+
toolCalls: import_zod.z.array(ModelToolCallSchema).optional(),
|
|
121
|
+
cacheControl: ChatMessageCacheControlSchema.optional()
|
|
110
122
|
});
|
|
111
123
|
var ChatStopReasonSchema = import_zod.z.enum([
|
|
112
124
|
"end_turn",
|
|
@@ -336,6 +348,15 @@ async function executeAbortableProviderFetch(providerLabel, performFetch) {
|
|
|
336
348
|
}
|
|
337
349
|
}
|
|
338
350
|
|
|
351
|
+
// src/provider-extra-body.ts
|
|
352
|
+
function mergeProviderRequestExtraBody(requestBody, adapterExtraBody, requestExtraBody) {
|
|
353
|
+
return {
|
|
354
|
+
...requestBody,
|
|
355
|
+
...adapterExtraBody ?? {},
|
|
356
|
+
...requestExtraBody ?? {}
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
|
|
339
360
|
// src/provider-fallback.ts
|
|
340
361
|
var import_errors11 = require("@assemble-dev/shared-utils/errors");
|
|
341
362
|
|
|
@@ -503,7 +524,8 @@ function openai(options) {
|
|
|
503
524
|
requireJsonObjectResponse: false,
|
|
504
525
|
tools: request.tools,
|
|
505
526
|
toolChoice: request.toolChoice,
|
|
506
|
-
abortSignal: request.abortSignal
|
|
527
|
+
abortSignal: request.abortSignal,
|
|
528
|
+
extraBody: request.extraBody
|
|
507
529
|
});
|
|
508
530
|
},
|
|
509
531
|
async generateStructuredOutput(request) {
|
|
@@ -545,7 +567,11 @@ async function requestOpenAiChatCompletion(options, input) {
|
|
|
545
567
|
});
|
|
546
568
|
const fetchImplementation = options.fetchImplementation ?? fetch;
|
|
547
569
|
const baseUrl = options.baseURL ?? defaultOpenAiBaseUrl;
|
|
548
|
-
const requestBody =
|
|
570
|
+
const requestBody = mergeProviderRequestExtraBody(
|
|
571
|
+
buildOpenAiRequestBody(options.model, input),
|
|
572
|
+
options.extraBody,
|
|
573
|
+
input.extraBody
|
|
574
|
+
);
|
|
549
575
|
const startedAt = Date.now();
|
|
550
576
|
const response = await executeAbortableProviderFetch(
|
|
551
577
|
"OpenAI",
|
|
@@ -641,6 +667,36 @@ function mapOpenAiUsageToTokenUsage(response) {
|
|
|
641
667
|
};
|
|
642
668
|
}
|
|
643
669
|
|
|
670
|
+
// src/anthropic-cache-control.ts
|
|
671
|
+
function resolveAnthropicPromptCachingSettings(promptCaching) {
|
|
672
|
+
if (promptCaching === void 0) {
|
|
673
|
+
return { mode: "off" };
|
|
674
|
+
}
|
|
675
|
+
if (typeof promptCaching === "string") {
|
|
676
|
+
return { mode: promptCaching };
|
|
677
|
+
}
|
|
678
|
+
return promptCaching;
|
|
679
|
+
}
|
|
680
|
+
function buildAnthropicCacheControl(ttl) {
|
|
681
|
+
if (ttl === void 0) {
|
|
682
|
+
return { type: "ephemeral" };
|
|
683
|
+
}
|
|
684
|
+
return { type: "ephemeral", ttl };
|
|
685
|
+
}
|
|
686
|
+
function applyCacheControlToLastContentBlock(requestMessage, cacheControl) {
|
|
687
|
+
if (typeof requestMessage.content === "string") {
|
|
688
|
+
if (requestMessage.content.length === 0) {
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
requestMessage.content = [{ type: "text", text: requestMessage.content }];
|
|
692
|
+
}
|
|
693
|
+
const lastContentBlock = requestMessage.content[requestMessage.content.length - 1];
|
|
694
|
+
if (lastContentBlock === void 0) {
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
lastContentBlock.cache_control = cacheControl;
|
|
698
|
+
}
|
|
699
|
+
|
|
644
700
|
// src/anthropic-request-mapping.ts
|
|
645
701
|
function buildAnthropicRequestBody(settings, input) {
|
|
646
702
|
const requestBody = {
|
|
@@ -650,6 +706,7 @@ function buildAnthropicRequestBody(settings, input) {
|
|
|
650
706
|
};
|
|
651
707
|
applyAnthropicSystemField(requestBody, settings, input);
|
|
652
708
|
applyAnthropicToolFields(requestBody, settings, input);
|
|
709
|
+
applyAnthropicMessageCacheBreakpoints(requestBody, settings, input);
|
|
653
710
|
if (input.temperature !== void 0) {
|
|
654
711
|
requestBody.temperature = input.temperature;
|
|
655
712
|
}
|
|
@@ -662,18 +719,46 @@ function buildAnthropicRequestBody(settings, input) {
|
|
|
662
719
|
return requestBody;
|
|
663
720
|
}
|
|
664
721
|
function applyAnthropicSystemField(requestBody, settings, input) {
|
|
722
|
+
const caching = resolveAnthropicPromptCachingSettings(settings.promptCaching);
|
|
665
723
|
const systemText = joinSystemMessageText(input.messages);
|
|
666
724
|
if (systemText.length === 0) {
|
|
667
725
|
return;
|
|
668
726
|
}
|
|
669
|
-
if (
|
|
727
|
+
if (caching.mode === "off") {
|
|
670
728
|
requestBody.system = systemText;
|
|
671
729
|
return;
|
|
672
730
|
}
|
|
673
731
|
requestBody.system = [
|
|
674
|
-
{
|
|
732
|
+
{
|
|
733
|
+
type: "text",
|
|
734
|
+
text: systemText,
|
|
735
|
+
cache_control: buildAnthropicCacheControl(caching.ttl)
|
|
736
|
+
}
|
|
675
737
|
];
|
|
676
738
|
}
|
|
739
|
+
function applyAnthropicMessageCacheBreakpoints(requestBody, settings, input) {
|
|
740
|
+
const caching = resolveAnthropicPromptCachingSettings(settings.promptCaching);
|
|
741
|
+
const finalRequestMessage = requestBody.messages[requestBody.messages.length - 1];
|
|
742
|
+
if (caching.mode === "messages" && finalRequestMessage !== void 0) {
|
|
743
|
+
applyCacheControlToLastContentBlock(
|
|
744
|
+
finalRequestMessage,
|
|
745
|
+
buildAnthropicCacheControl(caching.ttl)
|
|
746
|
+
);
|
|
747
|
+
}
|
|
748
|
+
const nonSystemMessages = input.messages.filter(
|
|
749
|
+
(message) => message.role !== "system"
|
|
750
|
+
);
|
|
751
|
+
nonSystemMessages.forEach((message, messageIndex) => {
|
|
752
|
+
const requestMessage = requestBody.messages[messageIndex];
|
|
753
|
+
if (message.cacheControl === void 0 || requestMessage === void 0) {
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
applyCacheControlToLastContentBlock(
|
|
757
|
+
requestMessage,
|
|
758
|
+
buildAnthropicCacheControl(message.cacheControl.ttl ?? caching.ttl)
|
|
759
|
+
);
|
|
760
|
+
});
|
|
761
|
+
}
|
|
677
762
|
function applyAnthropicToolFields(requestBody, settings, input) {
|
|
678
763
|
if (input.tools !== void 0 && input.tools.length > 0) {
|
|
679
764
|
requestBody.tools = mapModelToolDefinitionsToAnthropicTools(
|
|
@@ -688,14 +773,15 @@ function applyAnthropicToolFields(requestBody, settings, input) {
|
|
|
688
773
|
}
|
|
689
774
|
}
|
|
690
775
|
function mapModelToolDefinitionsToAnthropicTools(tools, promptCaching) {
|
|
776
|
+
const caching = resolveAnthropicPromptCachingSettings(promptCaching);
|
|
691
777
|
return tools.map((tool, toolIndex) => {
|
|
692
778
|
const anthropicTool = {
|
|
693
779
|
name: tool.name,
|
|
694
780
|
description: tool.description,
|
|
695
781
|
input_schema: tool.inputJsonSchema
|
|
696
782
|
};
|
|
697
|
-
if (
|
|
698
|
-
anthropicTool.cache_control =
|
|
783
|
+
if (caching.mode !== "off" && toolIndex === tools.length - 1) {
|
|
784
|
+
anthropicTool.cache_control = buildAnthropicCacheControl(caching.ttl);
|
|
699
785
|
}
|
|
700
786
|
return anthropicTool;
|
|
701
787
|
});
|
|
@@ -1200,7 +1286,8 @@ function buildAnthropicCallInput(options, request) {
|
|
|
1200
1286
|
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
1201
1287
|
tools: request.tools,
|
|
1202
1288
|
toolChoice: request.toolChoice,
|
|
1203
|
-
abortSignal: request.abortSignal
|
|
1289
|
+
abortSignal: request.abortSignal,
|
|
1290
|
+
extraBody: request.extraBody
|
|
1204
1291
|
};
|
|
1205
1292
|
}
|
|
1206
1293
|
async function executeAnthropicAdapterCall(options, input) {
|
|
@@ -1217,9 +1304,10 @@ async function executeAnthropicAdapterCall(options, input) {
|
|
|
1217
1304
|
);
|
|
1218
1305
|
}
|
|
1219
1306
|
async function requestAnthropicMessages(options, input) {
|
|
1220
|
-
const requestBody =
|
|
1221
|
-
buildAnthropicRequestSettings(options),
|
|
1222
|
-
|
|
1307
|
+
const requestBody = mergeProviderRequestExtraBody(
|
|
1308
|
+
buildAnthropicRequestBody(buildAnthropicRequestSettings(options), input),
|
|
1309
|
+
options.extraBody,
|
|
1310
|
+
input.extraBody
|
|
1223
1311
|
);
|
|
1224
1312
|
const startedAt = Date.now();
|
|
1225
1313
|
const response = await executeAbortableProviderFetch(
|
|
@@ -1248,9 +1336,10 @@ async function requestAnthropicMessages(options, input) {
|
|
|
1248
1336
|
}
|
|
1249
1337
|
function buildAnthropicStreamInput(options, request) {
|
|
1250
1338
|
const input = buildAnthropicCallInput(options, request);
|
|
1251
|
-
const requestBody =
|
|
1252
|
-
buildAnthropicRequestSettings(options),
|
|
1253
|
-
|
|
1339
|
+
const requestBody = mergeProviderRequestExtraBody(
|
|
1340
|
+
buildAnthropicRequestBody(buildAnthropicRequestSettings(options), input),
|
|
1341
|
+
options.extraBody,
|
|
1342
|
+
input.extraBody
|
|
1254
1343
|
);
|
|
1255
1344
|
return {
|
|
1256
1345
|
url: `${resolveAnthropicBaseUrl(options)}/v1/messages`,
|
|
@@ -1322,7 +1411,8 @@ function gemini(options) {
|
|
|
1322
1411
|
temperature: request.temperature ?? options.temperature,
|
|
1323
1412
|
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
1324
1413
|
requireJsonResponse: false,
|
|
1325
|
-
abortSignal: request.abortSignal
|
|
1414
|
+
abortSignal: request.abortSignal,
|
|
1415
|
+
extraBody: request.extraBody
|
|
1326
1416
|
});
|
|
1327
1417
|
},
|
|
1328
1418
|
async generateStructuredOutput(request) {
|
|
@@ -1364,7 +1454,11 @@ async function requestGeminiGenerateContent(options, input) {
|
|
|
1364
1454
|
});
|
|
1365
1455
|
const fetchImplementation = options.fetchImplementation ?? fetch;
|
|
1366
1456
|
const baseUrl = options.baseURL ?? defaultGeminiBaseUrl;
|
|
1367
|
-
const requestBody =
|
|
1457
|
+
const requestBody = mergeProviderRequestExtraBody(
|
|
1458
|
+
buildGeminiRequestBody(input),
|
|
1459
|
+
options.extraBody,
|
|
1460
|
+
input.extraBody
|
|
1461
|
+
);
|
|
1368
1462
|
const requestUrl = `${baseUrl}/v1beta/models/${options.model}:generateContent`;
|
|
1369
1463
|
const startedAt = Date.now();
|
|
1370
1464
|
const response = await executeAbortableProviderFetch(
|
|
@@ -1652,9 +1746,209 @@ function calculateModelCallCostUsd(pricing, tokenUsage) {
|
|
|
1652
1746
|
}
|
|
1653
1747
|
|
|
1654
1748
|
// src/anthropic-batch.ts
|
|
1749
|
+
var import_errors26 = require("@assemble-dev/shared-types/errors");
|
|
1750
|
+
var import_json7 = require("@assemble-dev/shared-types/json");
|
|
1751
|
+
var import_errors27 = require("@assemble-dev/shared-utils/errors");
|
|
1752
|
+
|
|
1753
|
+
// src/anthropic-batch-structured.ts
|
|
1655
1754
|
var import_errors24 = require("@assemble-dev/shared-types/errors");
|
|
1656
1755
|
var import_json6 = require("@assemble-dev/shared-types/json");
|
|
1657
1756
|
var import_errors25 = require("@assemble-dev/shared-utils/errors");
|
|
1757
|
+
var anthropicBatchJsonOnlySystemInstruction = "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text.";
|
|
1758
|
+
function parseAnthropicBatchStructuredContent(content, schema) {
|
|
1759
|
+
const jsonValue = parseStructuredJsonText(
|
|
1760
|
+
content,
|
|
1761
|
+
import_json6.JsonValueSchema
|
|
1762
|
+
);
|
|
1763
|
+
const validationResult = schema.safeParse(jsonValue);
|
|
1764
|
+
if (!validationResult.success) {
|
|
1765
|
+
throw new import_errors25.AppError({
|
|
1766
|
+
code: import_errors24.AppErrorCode.ValidationFailed,
|
|
1767
|
+
message: "Anthropic batch structured output did not match the expected schema",
|
|
1768
|
+
statusCode: 422,
|
|
1769
|
+
details: { validationErrorMessage: validationResult.error.message }
|
|
1770
|
+
});
|
|
1771
|
+
}
|
|
1772
|
+
return validationResult.data;
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
// src/anthropic-batch-request.ts
|
|
1776
|
+
function mapBatchMessageRequestToApiBatchRequest(request) {
|
|
1777
|
+
const params = {
|
|
1778
|
+
model: request.model,
|
|
1779
|
+
max_tokens: request.maxOutputTokens ?? defaultAnthropicMaxOutputTokens,
|
|
1780
|
+
messages: request.messages.filter((message) => message.role !== "system").map(mapChatMessageToBatchApiRequestMessage)
|
|
1781
|
+
};
|
|
1782
|
+
applyBatchSystemField(params, request);
|
|
1783
|
+
if (request.temperature !== void 0) {
|
|
1784
|
+
params.temperature = request.temperature;
|
|
1785
|
+
}
|
|
1786
|
+
return { custom_id: request.customId, params };
|
|
1787
|
+
}
|
|
1788
|
+
function applyBatchSystemField(params, request) {
|
|
1789
|
+
const systemText = buildBatchSystemText(request);
|
|
1790
|
+
if (systemText.length === 0) {
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
if (request.promptCaching !== "auto") {
|
|
1794
|
+
params.system = systemText;
|
|
1795
|
+
return;
|
|
1796
|
+
}
|
|
1797
|
+
params.system = [
|
|
1798
|
+
{ type: "text", text: systemText, cache_control: { type: "ephemeral" } }
|
|
1799
|
+
];
|
|
1800
|
+
}
|
|
1801
|
+
function buildBatchSystemText(request) {
|
|
1802
|
+
const joinedSystemText = joinBatchSystemMessageText(request.messages);
|
|
1803
|
+
if (request.requireJsonResponse !== true) {
|
|
1804
|
+
return joinedSystemText;
|
|
1805
|
+
}
|
|
1806
|
+
if (joinedSystemText.length === 0) {
|
|
1807
|
+
return anthropicBatchJsonOnlySystemInstruction;
|
|
1808
|
+
}
|
|
1809
|
+
return `${anthropicBatchJsonOnlySystemInstruction}
|
|
1810
|
+
|
|
1811
|
+
${joinedSystemText}`;
|
|
1812
|
+
}
|
|
1813
|
+
function joinBatchSystemMessageText(messages) {
|
|
1814
|
+
return messages.filter((message) => message.role === "system").map(extractMessageText).join("\n\n");
|
|
1815
|
+
}
|
|
1816
|
+
function mapChatMessageToBatchApiRequestMessage(message) {
|
|
1817
|
+
if (message.role === "assistant") {
|
|
1818
|
+
return { role: "assistant", content: extractMessageText(message) };
|
|
1819
|
+
}
|
|
1820
|
+
if (message.role === "tool") {
|
|
1821
|
+
return { role: "user", content: buildBatchToolResultText(message) };
|
|
1822
|
+
}
|
|
1823
|
+
return { role: "user", content: extractMessageText(message) };
|
|
1824
|
+
}
|
|
1825
|
+
function buildBatchToolResultText(message) {
|
|
1826
|
+
if (message.toolName === void 0) {
|
|
1827
|
+
return `Tool result: ${extractMessageText(message)}`;
|
|
1828
|
+
}
|
|
1829
|
+
return `Tool result (${message.toolName}): ${extractMessageText(message)}`;
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
// src/anthropic-batch-trace-events.ts
|
|
1833
|
+
var import_ids = require("@assemble-dev/shared-utils/ids");
|
|
1834
|
+
var anthropicBatchTraceWorkflowName = "anthropic-message-batch";
|
|
1835
|
+
function createAnthropicBatchTraceEmitter(input) {
|
|
1836
|
+
if (input.onTraceEvent === void 0) {
|
|
1837
|
+
return createNoopAnthropicBatchTraceEmitter();
|
|
1838
|
+
}
|
|
1839
|
+
const onTraceEvent = input.onTraceEvent;
|
|
1840
|
+
const runId = (0, import_ids.generateRunId)();
|
|
1841
|
+
const completedBatchIds = /* @__PURE__ */ new Set();
|
|
1842
|
+
const submittedEventIdByBatchId = /* @__PURE__ */ new Map();
|
|
1843
|
+
const modelByBatchScopedCustomId = /* @__PURE__ */ new Map();
|
|
1844
|
+
function buildBatchTraceEventBase(parentEventId) {
|
|
1845
|
+
return {
|
|
1846
|
+
id: (0, import_ids.generateTraceEventId)(),
|
|
1847
|
+
runId,
|
|
1848
|
+
workflowName: anthropicBatchTraceWorkflowName,
|
|
1849
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1850
|
+
parentEventId,
|
|
1851
|
+
redacted: false
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1854
|
+
function stampMetadataOntoEvent(event) {
|
|
1855
|
+
if (input.metadata === void 0) {
|
|
1856
|
+
return event;
|
|
1857
|
+
}
|
|
1858
|
+
return { ...event, metadata: input.metadata };
|
|
1859
|
+
}
|
|
1860
|
+
function emitBatchSubmittedEvent(batch, requestSummaries) {
|
|
1861
|
+
const submittedEvent = {
|
|
1862
|
+
...buildBatchTraceEventBase(null),
|
|
1863
|
+
type: "batch.submitted",
|
|
1864
|
+
batchId: batch.id,
|
|
1865
|
+
requestCount: requestSummaries.length,
|
|
1866
|
+
models: requestSummaries.map((requestSummary) => requestSummary.model)
|
|
1867
|
+
};
|
|
1868
|
+
submittedEventIdByBatchId.set(batch.id, submittedEvent.id);
|
|
1869
|
+
for (const requestSummary of requestSummaries) {
|
|
1870
|
+
modelByBatchScopedCustomId.set(
|
|
1871
|
+
buildBatchScopedCustomIdKey(batch.id, requestSummary.customId),
|
|
1872
|
+
requestSummary.model
|
|
1873
|
+
);
|
|
1874
|
+
}
|
|
1875
|
+
onTraceEvent(stampMetadataOntoEvent(submittedEvent));
|
|
1876
|
+
}
|
|
1877
|
+
function emitBatchCompletedEventOnce(batch) {
|
|
1878
|
+
if (batch.processingStatus !== "ended" || completedBatchIds.has(batch.id)) {
|
|
1879
|
+
return;
|
|
1880
|
+
}
|
|
1881
|
+
completedBatchIds.add(batch.id);
|
|
1882
|
+
const completedEvent = {
|
|
1883
|
+
...buildBatchTraceEventBase(
|
|
1884
|
+
submittedEventIdByBatchId.get(batch.id) ?? null
|
|
1885
|
+
),
|
|
1886
|
+
type: "batch.completed",
|
|
1887
|
+
batchId: batch.id,
|
|
1888
|
+
requestCounts: batch.requestCounts,
|
|
1889
|
+
latencyMs: calculateBatchLatencyMs(batch)
|
|
1890
|
+
};
|
|
1891
|
+
onTraceEvent(stampMetadataOntoEvent(completedEvent));
|
|
1892
|
+
}
|
|
1893
|
+
function emitBatchResultEvent(batchId, result) {
|
|
1894
|
+
const resultEvent = buildBatchResultEvent(
|
|
1895
|
+
buildBatchTraceEventBase(submittedEventIdByBatchId.get(batchId) ?? null),
|
|
1896
|
+
batchId,
|
|
1897
|
+
result,
|
|
1898
|
+
modelByBatchScopedCustomId.get(
|
|
1899
|
+
buildBatchScopedCustomIdKey(batchId, result.customId)
|
|
1900
|
+
)
|
|
1901
|
+
);
|
|
1902
|
+
onTraceEvent(stampMetadataOntoEvent(resultEvent));
|
|
1903
|
+
}
|
|
1904
|
+
return {
|
|
1905
|
+
emitBatchSubmittedEvent,
|
|
1906
|
+
emitBatchCompletedEventOnce,
|
|
1907
|
+
emitBatchResultEvent
|
|
1908
|
+
};
|
|
1909
|
+
}
|
|
1910
|
+
function createNoopAnthropicBatchTraceEmitter() {
|
|
1911
|
+
return {
|
|
1912
|
+
emitBatchSubmittedEvent() {
|
|
1913
|
+
},
|
|
1914
|
+
emitBatchCompletedEventOnce() {
|
|
1915
|
+
},
|
|
1916
|
+
emitBatchResultEvent() {
|
|
1917
|
+
}
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1920
|
+
function buildBatchScopedCustomIdKey(batchId, customId) {
|
|
1921
|
+
return `${batchId}:${customId}`;
|
|
1922
|
+
}
|
|
1923
|
+
function calculateBatchLatencyMs(batch) {
|
|
1924
|
+
const createdAtMs = Date.parse(batch.createdAt);
|
|
1925
|
+
const endedAtMs = batch.endedAt === null ? Date.now() : Date.parse(batch.endedAt);
|
|
1926
|
+
if (Number.isNaN(createdAtMs) || Number.isNaN(endedAtMs)) {
|
|
1927
|
+
return 0;
|
|
1928
|
+
}
|
|
1929
|
+
return Math.max(0, endedAtMs - createdAtMs);
|
|
1930
|
+
}
|
|
1931
|
+
function buildBatchResultEvent(eventBase, batchId, result, modelName) {
|
|
1932
|
+
if (result.outcome.type !== "succeeded") {
|
|
1933
|
+
return {
|
|
1934
|
+
...eventBase,
|
|
1935
|
+
type: "batch.result",
|
|
1936
|
+
batchId,
|
|
1937
|
+
customId: result.customId,
|
|
1938
|
+
outcomeType: result.outcome.type,
|
|
1939
|
+
costUsd: null
|
|
1940
|
+
};
|
|
1941
|
+
}
|
|
1942
|
+
return {
|
|
1943
|
+
...eventBase,
|
|
1944
|
+
type: "batch.result",
|
|
1945
|
+
batchId,
|
|
1946
|
+
customId: result.customId,
|
|
1947
|
+
outcomeType: "succeeded",
|
|
1948
|
+
tokenUsage: result.outcome.tokenUsage,
|
|
1949
|
+
costUsd: modelName === void 0 ? null : estimateModelCallCostUsd(modelName, result.outcome.tokenUsage)
|
|
1950
|
+
};
|
|
1951
|
+
}
|
|
1658
1952
|
|
|
1659
1953
|
// src/anthropic-batch-types.ts
|
|
1660
1954
|
var import_zod7 = require("zod");
|
|
@@ -1759,19 +2053,26 @@ var defaultAnthropicBatchPollIntervalMs = 5e3;
|
|
|
1759
2053
|
var defaultAnthropicBatchTimeoutMs = 36e5;
|
|
1760
2054
|
var anthropicBatchApiVersion = "2023-06-01";
|
|
1761
2055
|
function createAnthropicBatchClient(options) {
|
|
2056
|
+
const clientContext = {
|
|
2057
|
+
options,
|
|
2058
|
+
traceEmitter: createAnthropicBatchTraceEmitter({
|
|
2059
|
+
onTraceEvent: options.onTraceEvent,
|
|
2060
|
+
metadata: options.metadata
|
|
2061
|
+
})
|
|
2062
|
+
};
|
|
1762
2063
|
return {
|
|
1763
2064
|
async submitMessageBatch(requests) {
|
|
1764
|
-
return await submitAnthropicMessageBatch(
|
|
2065
|
+
return await submitAnthropicMessageBatch(clientContext, requests);
|
|
1765
2066
|
},
|
|
1766
2067
|
async fetchMessageBatch(batchId) {
|
|
1767
|
-
return await fetchAnthropicMessageBatch(
|
|
2068
|
+
return await fetchAnthropicMessageBatch(clientContext, batchId);
|
|
1768
2069
|
},
|
|
1769
2070
|
async listMessageBatchResults(batchId) {
|
|
1770
|
-
return await listAnthropicMessageBatchResults(
|
|
2071
|
+
return await listAnthropicMessageBatchResults(clientContext, batchId);
|
|
1771
2072
|
},
|
|
1772
2073
|
async waitForMessageBatchCompletion(batchId, waitOptions) {
|
|
1773
2074
|
return await waitForAnthropicMessageBatchCompletion(
|
|
1774
|
-
|
|
2075
|
+
clientContext,
|
|
1775
2076
|
batchId,
|
|
1776
2077
|
waitOptions
|
|
1777
2078
|
);
|
|
@@ -1798,8 +2099,8 @@ function buildAnthropicBatchRequestHeaders(apiKey) {
|
|
|
1798
2099
|
"anthropic-version": anthropicBatchApiVersion
|
|
1799
2100
|
};
|
|
1800
2101
|
}
|
|
1801
|
-
async function submitAnthropicMessageBatch(
|
|
1802
|
-
const context = resolveAnthropicBatchRequestContext(options);
|
|
2102
|
+
async function submitAnthropicMessageBatch(clientContext, requests) {
|
|
2103
|
+
const context = resolveAnthropicBatchRequestContext(clientContext.options);
|
|
1803
2104
|
const response = await context.fetchImplementation(
|
|
1804
2105
|
`${context.baseUrl}/v1/messages/batches`,
|
|
1805
2106
|
{
|
|
@@ -1810,10 +2111,18 @@ async function submitAnthropicMessageBatch(options, requests) {
|
|
|
1810
2111
|
})
|
|
1811
2112
|
}
|
|
1812
2113
|
);
|
|
1813
|
-
|
|
2114
|
+
const batch = await parseAnthropicMessageBatchHttpResponse(response);
|
|
2115
|
+
clientContext.traceEmitter.emitBatchSubmittedEvent(
|
|
2116
|
+
batch,
|
|
2117
|
+
requests.map((request) => ({
|
|
2118
|
+
customId: request.customId,
|
|
2119
|
+
model: request.model
|
|
2120
|
+
}))
|
|
2121
|
+
);
|
|
2122
|
+
return batch;
|
|
1814
2123
|
}
|
|
1815
|
-
async function fetchAnthropicMessageBatch(
|
|
1816
|
-
const context = resolveAnthropicBatchRequestContext(options);
|
|
2124
|
+
async function fetchAnthropicMessageBatch(clientContext, batchId) {
|
|
2125
|
+
const context = resolveAnthropicBatchRequestContext(clientContext.options);
|
|
1817
2126
|
const response = await context.fetchImplementation(
|
|
1818
2127
|
`${context.baseUrl}/v1/messages/batches/${batchId}`,
|
|
1819
2128
|
{
|
|
@@ -1821,7 +2130,9 @@ async function fetchAnthropicMessageBatch(options, batchId) {
|
|
|
1821
2130
|
headers: buildAnthropicBatchRequestHeaders(context.apiKey)
|
|
1822
2131
|
}
|
|
1823
2132
|
);
|
|
1824
|
-
|
|
2133
|
+
const batch = await parseAnthropicMessageBatchHttpResponse(response);
|
|
2134
|
+
clientContext.traceEmitter.emitBatchCompletedEventOnce(batch);
|
|
2135
|
+
return batch;
|
|
1825
2136
|
}
|
|
1826
2137
|
async function parseAnthropicMessageBatchHttpResponse(response) {
|
|
1827
2138
|
if (!response.ok) {
|
|
@@ -1835,17 +2146,17 @@ async function parseAnthropicMessageBatchHttpResponse(response) {
|
|
|
1835
2146
|
}
|
|
1836
2147
|
return mapAnthropicMessageBatchResponseToMessageBatch(parseResult.data);
|
|
1837
2148
|
}
|
|
1838
|
-
async function listAnthropicMessageBatchResults(
|
|
1839
|
-
const batch = await fetchAnthropicMessageBatch(
|
|
2149
|
+
async function listAnthropicMessageBatchResults(clientContext, batchId) {
|
|
2150
|
+
const batch = await fetchAnthropicMessageBatch(clientContext, batchId);
|
|
1840
2151
|
if (batch.resultsUrl === null) {
|
|
1841
|
-
throw new
|
|
1842
|
-
code:
|
|
2152
|
+
throw new import_errors27.AppError({
|
|
2153
|
+
code: import_errors26.AppErrorCode.Conflict,
|
|
1843
2154
|
message: `Anthropic message batch ${batchId} has no results because processing has not ended`,
|
|
1844
2155
|
statusCode: 409,
|
|
1845
2156
|
details: { batchId, processingStatus: batch.processingStatus }
|
|
1846
2157
|
});
|
|
1847
2158
|
}
|
|
1848
|
-
const context = resolveAnthropicBatchRequestContext(options);
|
|
2159
|
+
const context = resolveAnthropicBatchRequestContext(clientContext.options);
|
|
1849
2160
|
const response = await context.fetchImplementation(batch.resultsUrl, {
|
|
1850
2161
|
method: "GET",
|
|
1851
2162
|
headers: buildAnthropicBatchRequestHeaders(context.apiKey)
|
|
@@ -1853,7 +2164,11 @@ async function listAnthropicMessageBatchResults(options, batchId) {
|
|
|
1853
2164
|
if (!response.ok) {
|
|
1854
2165
|
throw buildProviderStatusError("Anthropic", response.status);
|
|
1855
2166
|
}
|
|
1856
|
-
|
|
2167
|
+
const results = parseAnthropicBatchResultsJsonl(await response.text());
|
|
2168
|
+
for (const result of results) {
|
|
2169
|
+
clientContext.traceEmitter.emitBatchResultEvent(batchId, result);
|
|
2170
|
+
}
|
|
2171
|
+
return results;
|
|
1857
2172
|
}
|
|
1858
2173
|
function parseAnthropicBatchResultsJsonl(jsonlText) {
|
|
1859
2174
|
return jsonlText.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map(parseAnthropicBatchResultLine);
|
|
@@ -1872,7 +2187,7 @@ function parseAnthropicBatchResultLine(line) {
|
|
|
1872
2187
|
}
|
|
1873
2188
|
function parseAnthropicBatchResultLineJson(line) {
|
|
1874
2189
|
try {
|
|
1875
|
-
return
|
|
2190
|
+
return import_json7.JsonValueSchema.parse(JSON.parse(line));
|
|
1876
2191
|
} catch {
|
|
1877
2192
|
throw buildProviderInvalidResponseError(
|
|
1878
2193
|
"Anthropic",
|
|
@@ -1880,72 +2195,44 @@ function parseAnthropicBatchResultLineJson(line) {
|
|
|
1880
2195
|
);
|
|
1881
2196
|
}
|
|
1882
2197
|
}
|
|
1883
|
-
async function waitForAnthropicMessageBatchCompletion(
|
|
2198
|
+
async function waitForAnthropicMessageBatchCompletion(clientContext, batchId, waitOptions) {
|
|
1884
2199
|
const pollIntervalMs = waitOptions?.pollIntervalMs ?? defaultAnthropicBatchPollIntervalMs;
|
|
1885
2200
|
const timeoutMs = waitOptions?.timeoutMs ?? defaultAnthropicBatchTimeoutMs;
|
|
1886
2201
|
const waitFor = waitOptions?.waitFor ?? waitForMilliseconds;
|
|
1887
2202
|
const startedAt = Date.now();
|
|
1888
|
-
let batch = await fetchAnthropicMessageBatch(
|
|
2203
|
+
let batch = await fetchAnthropicMessageBatch(clientContext, batchId);
|
|
1889
2204
|
while (batch.processingStatus !== "ended") {
|
|
1890
2205
|
if (Date.now() - startedAt >= timeoutMs) {
|
|
1891
2206
|
throw buildAnthropicBatchTimeoutError(batchId, timeoutMs);
|
|
1892
2207
|
}
|
|
1893
2208
|
await waitFor(pollIntervalMs);
|
|
1894
|
-
batch = await fetchAnthropicMessageBatch(
|
|
2209
|
+
batch = await fetchAnthropicMessageBatch(clientContext, batchId);
|
|
1895
2210
|
}
|
|
1896
2211
|
return batch;
|
|
1897
2212
|
}
|
|
1898
2213
|
function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
|
|
1899
|
-
return new
|
|
1900
|
-
code:
|
|
2214
|
+
return new import_errors27.AppError({
|
|
2215
|
+
code: import_errors26.AppErrorCode.ServiceUnavailable,
|
|
1901
2216
|
message: `Anthropic message batch ${batchId} did not complete within ${String(timeoutMs)}ms`,
|
|
1902
2217
|
statusCode: 504,
|
|
1903
2218
|
details: { batchId, timeoutMs }
|
|
1904
2219
|
});
|
|
1905
2220
|
}
|
|
1906
|
-
function mapBatchMessageRequestToApiBatchRequest(request) {
|
|
1907
|
-
const params = {
|
|
1908
|
-
model: request.model,
|
|
1909
|
-
max_tokens: request.maxOutputTokens ?? defaultAnthropicMaxOutputTokens,
|
|
1910
|
-
messages: request.messages.filter((message) => message.role !== "system").map(mapChatMessageToBatchApiRequestMessage)
|
|
1911
|
-
};
|
|
1912
|
-
const systemText = joinBatchSystemMessageText(request.messages);
|
|
1913
|
-
if (systemText.length > 0) {
|
|
1914
|
-
params.system = systemText;
|
|
1915
|
-
}
|
|
1916
|
-
if (request.temperature !== void 0) {
|
|
1917
|
-
params.temperature = request.temperature;
|
|
1918
|
-
}
|
|
1919
|
-
return { custom_id: request.customId, params };
|
|
1920
|
-
}
|
|
1921
|
-
function joinBatchSystemMessageText(messages) {
|
|
1922
|
-
return messages.filter((message) => message.role === "system").map(extractMessageText).join("\n\n");
|
|
1923
|
-
}
|
|
1924
|
-
function mapChatMessageToBatchApiRequestMessage(message) {
|
|
1925
|
-
if (message.role === "assistant") {
|
|
1926
|
-
return { role: "assistant", content: extractMessageText(message) };
|
|
1927
|
-
}
|
|
1928
|
-
if (message.role === "tool") {
|
|
1929
|
-
return { role: "user", content: buildBatchToolResultText(message) };
|
|
1930
|
-
}
|
|
1931
|
-
return { role: "user", content: extractMessageText(message) };
|
|
1932
|
-
}
|
|
1933
|
-
function buildBatchToolResultText(message) {
|
|
1934
|
-
if (message.toolName === void 0) {
|
|
1935
|
-
return `Tool result: ${extractMessageText(message)}`;
|
|
1936
|
-
}
|
|
1937
|
-
return `Tool result (${message.toolName}): ${extractMessageText(message)}`;
|
|
1938
|
-
}
|
|
1939
2221
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1940
2222
|
0 && (module.exports = {
|
|
1941
2223
|
AnthropicMessagesResponseSchema,
|
|
1942
2224
|
AnthropicStreamEventSchema,
|
|
2225
|
+
ChatMessageCacheControlSchema,
|
|
1943
2226
|
ChatMessageRoleSchema,
|
|
1944
2227
|
ChatMessageSchema,
|
|
1945
2228
|
ChatStopReasonSchema,
|
|
1946
2229
|
MessageContentBlockSchema,
|
|
1947
2230
|
ModelToolCallSchema,
|
|
1948
2231
|
anthropic,
|
|
2232
|
+
anthropicBatchJsonOnlySystemInstruction,
|
|
2233
|
+
anthropicBatchTraceWorkflowName,
|
|
2234
|
+
applyCacheControlToLastContentBlock,
|
|
2235
|
+
buildAnthropicCacheControl,
|
|
1949
2236
|
buildAnthropicRequestBody,
|
|
1950
2237
|
buildOpenAiRequestBody,
|
|
1951
2238
|
buildProviderCanceledError,
|
|
@@ -1979,11 +2266,14 @@ function buildBatchToolResultText(message) {
|
|
|
1979
2266
|
mapModelToolChoiceToOpenAiToolChoice,
|
|
1980
2267
|
mapModelToolDefinitionToOpenAiTool,
|
|
1981
2268
|
mapModelToolDefinitionsToAnthropicTools,
|
|
2269
|
+
mergeProviderRequestExtraBody,
|
|
1982
2270
|
mockModel,
|
|
1983
2271
|
normalizeAnthropicStopReason,
|
|
1984
2272
|
openai,
|
|
2273
|
+
parseAnthropicBatchStructuredContent,
|
|
1985
2274
|
parseAnthropicStreamEvents,
|
|
1986
2275
|
parseAnthropicToolInputJson,
|
|
2276
|
+
resolveAnthropicPromptCachingSettings,
|
|
1987
2277
|
resolveProviderApiKey,
|
|
1988
2278
|
streamAnthropicChatCompletion
|
|
1989
2279
|
});
|