@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 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 = buildOpenAiRequestBody(options.model, input);
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 (settings.promptCaching !== "auto") {
727
+ if (caching.mode === "off") {
670
728
  requestBody.system = systemText;
671
729
  return;
672
730
  }
673
731
  requestBody.system = [
674
- { type: "text", text: systemText, cache_control: { type: "ephemeral" } }
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 (promptCaching === "auto" && toolIndex === tools.length - 1) {
698
- anthropicTool.cache_control = { type: "ephemeral" };
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 = buildAnthropicRequestBody(
1221
- buildAnthropicRequestSettings(options),
1222
- input
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 = buildAnthropicRequestBody(
1252
- buildAnthropicRequestSettings(options),
1253
- input
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 = buildGeminiRequestBody(input);
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(options, requests);
2065
+ return await submitAnthropicMessageBatch(clientContext, requests);
1765
2066
  },
1766
2067
  async fetchMessageBatch(batchId) {
1767
- return await fetchAnthropicMessageBatch(options, batchId);
2068
+ return await fetchAnthropicMessageBatch(clientContext, batchId);
1768
2069
  },
1769
2070
  async listMessageBatchResults(batchId) {
1770
- return await listAnthropicMessageBatchResults(options, batchId);
2071
+ return await listAnthropicMessageBatchResults(clientContext, batchId);
1771
2072
  },
1772
2073
  async waitForMessageBatchCompletion(batchId, waitOptions) {
1773
2074
  return await waitForAnthropicMessageBatchCompletion(
1774
- options,
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(options, requests) {
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
- return await parseAnthropicMessageBatchHttpResponse(response);
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(options, batchId) {
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
- return await parseAnthropicMessageBatchHttpResponse(response);
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(options, batchId) {
1839
- const batch = await fetchAnthropicMessageBatch(options, batchId);
2149
+ async function listAnthropicMessageBatchResults(clientContext, batchId) {
2150
+ const batch = await fetchAnthropicMessageBatch(clientContext, batchId);
1840
2151
  if (batch.resultsUrl === null) {
1841
- throw new import_errors25.AppError({
1842
- code: import_errors24.AppErrorCode.Conflict,
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
- return parseAnthropicBatchResultsJsonl(await response.text());
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 import_json6.JsonValueSchema.parse(JSON.parse(line));
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(options, batchId, waitOptions) {
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(options, batchId);
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(options, batchId);
2209
+ batch = await fetchAnthropicMessageBatch(clientContext, batchId);
1895
2210
  }
1896
2211
  return batch;
1897
2212
  }
1898
2213
  function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
1899
- return new import_errors25.AppError({
1900
- code: import_errors24.AppErrorCode.ServiceUnavailable,
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
  });