@yourgpt/llm-sdk 2.6.0-beta.3 → 2.6.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.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +46 -10
  3. package/dist/adapters/index.d.mts +11 -13
  4. package/dist/adapters/index.d.ts +11 -13
  5. package/dist/adapters/index.js +327 -100
  6. package/dist/adapters/index.mjs +327 -100
  7. package/dist/audio-K-Z3-Bce.d.mts +191 -0
  8. package/dist/audio-K-Z3-Bce.d.ts +191 -0
  9. package/dist/{base-BICaQaRS.d.mts → base-6LzczuCg.d.ts} +8 -1
  10. package/dist/{base-CpRPB8u8.d.ts → base-DySbTP8C.d.mts} +8 -1
  11. package/dist/decisions-CJzOt87t.d.mts +137 -0
  12. package/dist/decisions-CJzOt87t.d.ts +137 -0
  13. package/dist/fallback/index.d.mts +4 -4
  14. package/dist/fallback/index.d.ts +4 -4
  15. package/dist/http-BQxUT5A9.d.mts +9 -0
  16. package/dist/http-BQxUT5A9.d.ts +9 -0
  17. package/dist/index.d.mts +14 -8
  18. package/dist/index.d.ts +14 -8
  19. package/dist/index.js +599 -195
  20. package/dist/index.mjs +596 -196
  21. package/dist/providers/anthropic/index.d.mts +7 -4
  22. package/dist/providers/anthropic/index.d.ts +7 -4
  23. package/dist/providers/anthropic/index.js +383 -102
  24. package/dist/providers/anthropic/index.mjs +383 -102
  25. package/dist/providers/azure/index.d.mts +3 -3
  26. package/dist/providers/azure/index.d.ts +3 -3
  27. package/dist/providers/cloudflare/index.d.mts +11 -0
  28. package/dist/providers/cloudflare/index.d.ts +11 -0
  29. package/dist/providers/cloudflare/index.js +743 -0
  30. package/dist/providers/cloudflare/index.mjs +741 -0
  31. package/dist/providers/fireworks/index.d.mts +3 -3
  32. package/dist/providers/fireworks/index.d.ts +3 -3
  33. package/dist/providers/fireworks/index.js +108 -59
  34. package/dist/providers/fireworks/index.mjs +108 -59
  35. package/dist/providers/google/index.d.mts +3 -3
  36. package/dist/providers/google/index.d.ts +3 -3
  37. package/dist/providers/google/index.js +108 -59
  38. package/dist/providers/google/index.mjs +108 -59
  39. package/dist/providers/ollama/index.d.mts +4 -4
  40. package/dist/providers/ollama/index.d.ts +4 -4
  41. package/dist/providers/openai/index.d.mts +38 -6
  42. package/dist/providers/openai/index.d.ts +38 -6
  43. package/dist/providers/openai/index.js +1378 -84
  44. package/dist/providers/openai/index.mjs +1376 -85
  45. package/dist/providers/openrouter/index.d.mts +21 -4
  46. package/dist/providers/openrouter/index.d.ts +21 -4
  47. package/dist/providers/openrouter/index.js +967 -130
  48. package/dist/providers/openrouter/index.mjs +967 -131
  49. package/dist/providers/togetherai/index.d.mts +3 -3
  50. package/dist/providers/togetherai/index.d.ts +3 -3
  51. package/dist/providers/togetherai/index.js +108 -59
  52. package/dist/providers/togetherai/index.mjs +108 -59
  53. package/dist/providers/typesafe/index.d.mts +8 -0
  54. package/dist/providers/typesafe/index.d.ts +8 -0
  55. package/dist/providers/typesafe/index.js +735 -0
  56. package/dist/providers/typesafe/index.mjs +733 -0
  57. package/dist/providers/xai/index.d.mts +3 -3
  58. package/dist/providers/xai/index.d.ts +3 -3
  59. package/dist/providers/xai/index.js +108 -59
  60. package/dist/providers/xai/index.mjs +108 -59
  61. package/dist/{types-DCFqkJAy.d.ts → types-B0y6VZSQ.d.ts} +1 -1
  62. package/dist/{types-DHQEMFHA.d.mts → types-BXQMtaCX.d.ts} +17 -3
  63. package/dist/{types-C3RgRbEC.d.mts → types-BY6BVhFg.d.mts} +1 -1
  64. package/dist/{types-Dikj3En4.d.ts → types-C7_qVSSd.d.mts} +17 -3
  65. package/dist/{types-Dg1Bcg1k.d.mts → types-D7lzMMLu.d.mts} +13 -1
  66. package/dist/{types-Dg1Bcg1k.d.ts → types-D7lzMMLu.d.ts} +13 -1
  67. package/dist/yourgpt/index.d.mts +1 -1
  68. package/dist/yourgpt/index.d.ts +1 -1
  69. package/docs/decisions.md +174 -0
  70. package/docs/media.md +201 -0
  71. package/docs/multimodal-and-audio.md +9 -2
  72. package/package.json +34 -12
  73. package/dist/audio-BBSwnjo8.d.mts +0 -92
  74. package/dist/audio-BBSwnjo8.d.ts +0 -92
@@ -103,6 +103,63 @@ function textToolOutput(value, fallback) {
103
103
  return toolOutputForProvider(value, "unsupported").map((part) => part.text).join("\n");
104
104
  }
105
105
 
106
+ // src/core/anthropic-replay.ts
107
+ function anthropicReplay(content) {
108
+ if (!Array.isArray(content) || !content.some(
109
+ (b) => b?.type === "thinking" || b?.type === "redacted_thinking"
110
+ ))
111
+ return void 0;
112
+ const blocks = content.flatMap((block) => {
113
+ if (block?.type === "thinking" && typeof block.thinking === "string" && typeof block.signature === "string")
114
+ return [
115
+ {
116
+ type: "thinking",
117
+ thinking: block.thinking,
118
+ signature: block.signature
119
+ }
120
+ ];
121
+ if (block?.type === "redacted_thinking" && typeof block.data === "string")
122
+ return [{ type: "redacted_thinking", data: block.data }];
123
+ if (block?.type === "text" && typeof block.text === "string")
124
+ return [{ type: "text", text: block.text }];
125
+ if (block?.type === "tool_use" && typeof block.id === "string" && typeof block.name === "string")
126
+ return [
127
+ {
128
+ type: "tool_use",
129
+ id: block.id,
130
+ name: block.name,
131
+ input: block.input
132
+ }
133
+ ];
134
+ return [];
135
+ });
136
+ return { anthropic: { content: blocks } };
137
+ }
138
+ function anthropicReplayContent(metadata) {
139
+ const state = metadata?.anthropic;
140
+ return anthropicReplay(state?.content)?.anthropic?.content;
141
+ }
142
+ function collectAnthropicContent(blocks, event) {
143
+ if (event.type === "content_block_start")
144
+ blocks[event.index] = { ...event.content_block };
145
+ const block = blocks[event.index];
146
+ if (event.type !== "content_block_delta" || !block) return;
147
+ const delta = event.delta;
148
+ if (delta.type === "thinking_delta")
149
+ block.thinking = (block.thinking ?? "") + delta.thinking;
150
+ else if (delta.type === "signature_delta")
151
+ block.signature = (block.signature ?? "") + delta.signature;
152
+ else if (delta.type === "text_delta")
153
+ block.text = (block.text ?? "") + delta.text;
154
+ else if (delta.type === "input_json_delta") {
155
+ block.partialInput = (block.partialInput ?? "") + delta.partial_json;
156
+ try {
157
+ block.input = JSON.parse(block.partialInput);
158
+ } catch {
159
+ }
160
+ }
161
+ }
162
+
106
163
  // src/core/openai-parameters.ts
107
164
  function capabilities(model) {
108
165
  const gpt = /^gpt-(\d+)(?:\.(\d+))?(?:-(.+))?$/i.exec(model);
@@ -113,6 +170,19 @@ function capabilities(model) {
113
170
  const supportsNone = major === 5 && minor >= 1 && !chat || /^gpt-6-(?:sol|luna)(?:-\d{4}-\d{2}-\d{2})?$/i.test(model);
114
171
  return { major, minor, reasoning, supportsNone };
115
172
  }
173
+ function filterOpenAIResponseInclude(model, include, options = {}) {
174
+ const c = capabilities(model);
175
+ let result = include;
176
+ if (options.parameterPolicy !== "passthrough" && c.reasoning && !(options.reasoningEffort === "none" && c.supportsNone) && include.includes("message.output_text.logprobs")) {
177
+ result = include.filter(
178
+ (value) => value !== "message.output_text.logprobs"
179
+ );
180
+ (options.onWarning ?? console.warn)(
181
+ `[llm-sdk] ${model}: omitted message.output_text.logprobs because reasoning is enabled.`
182
+ );
183
+ }
184
+ return result.length ? result : void 0;
185
+ }
116
186
  function requiresOpenAIResponses(model, baseUrl, options = {}) {
117
187
  if (options.parameterPolicy === "passthrough") return false;
118
188
  const c = capabilities(model);
@@ -284,7 +354,22 @@ function stripSchemaKeys(schema, keysToDrop, options = {}) {
284
354
  )) {
285
355
  if (keysToDrop.has(key)) continue;
286
356
  const renamed = options.renameKeys?.[key] ?? key;
287
- out[renamed] = stripSchemaKeys(value, keysToDrop, options);
357
+ if ([
358
+ "properties",
359
+ "$defs",
360
+ "definitions",
361
+ "patternProperties",
362
+ "dependentSchemas"
363
+ ].includes(key) && value && typeof value === "object" && !Array.isArray(value)) {
364
+ out[renamed] = Object.fromEntries(
365
+ Object.entries(value).map(([name, child]) => [
366
+ name,
367
+ stripSchemaKeys(child, keysToDrop, options)
368
+ ])
369
+ );
370
+ } else if (["enum", "const", "default", "examples"].includes(key)) {
371
+ out[renamed] = value;
372
+ } else out[renamed] = stripSchemaKeys(value, keysToDrop, options);
288
373
  }
289
374
  if (options.forceAdditionalPropertiesFalse && out.type === "object") {
290
375
  out.additionalProperties = false;
@@ -305,6 +390,7 @@ function toOpenAIResponseFormat(rf) {
305
390
  };
306
391
  }
307
392
  function toOpenAIResponsesTextFormat(rf) {
393
+ if (rf?.type === "json_object") return { type: "json_object" };
308
394
  if (!rf || rf.type !== "json_schema") return void 0;
309
395
  return {
310
396
  type: "json_schema",
@@ -544,6 +630,14 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
544
630
  const msg = messages[i];
545
631
  if (msg.role === "system") continue;
546
632
  if (msg.role === "assistant") {
633
+ const replay = anthropicReplayContent(msg.providerMetadata);
634
+ if (replay) {
635
+ formatted.push({
636
+ role: "assistant",
637
+ content: replay
638
+ });
639
+ continue;
640
+ }
547
641
  const content = [];
548
642
  if (msg.content) {
549
643
  content.push({ type: "text", text: msg.content });
@@ -634,6 +728,63 @@ function formatMessagesForOpenAI(messages, systemPrompt, preserveProviderMetadat
634
728
  return formatted;
635
729
  }
636
730
 
731
+ // src/core/provider-error.ts
732
+ function invalidProviderResponse(message) {
733
+ return Object.assign(new Error(message), {
734
+ name: "InvalidProviderResponseError",
735
+ status: 502,
736
+ code: "INVALID_PROVIDER_RESPONSE"
737
+ });
738
+ }
739
+ function providerErrorEvent(error, code) {
740
+ const details = error ?? {};
741
+ const event = {
742
+ type: "error",
743
+ message: error instanceof Error ? error.message : String(error),
744
+ code,
745
+ ...typeof details.status === "number" ? { status: details.status } : {},
746
+ ...typeof details.code === "string" ? { providerCode: details.code } : {},
747
+ ...typeof details.param === "string" ? { param: details.param } : {},
748
+ ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
749
+ };
750
+ Object.defineProperty(event, "cause", { value: error, enumerable: false });
751
+ return event;
752
+ }
753
+ function throwIfAborted(signal) {
754
+ if (!signal?.aborted) return;
755
+ const error = new Error("The operation was aborted");
756
+ error.name = "AbortError";
757
+ throw error;
758
+ }
759
+
760
+ // src/core/tool-validation.ts
761
+ function parseToolArguments(value) {
762
+ let args = value;
763
+ if (typeof value === "string") {
764
+ try {
765
+ args = JSON.parse(value || "{}");
766
+ } catch {
767
+ throw invalidProviderResponse("Tool arguments are not valid JSON");
768
+ }
769
+ }
770
+ if (args === null || typeof args !== "object" || Array.isArray(args))
771
+ throw invalidProviderResponse("Tool arguments must be a JSON object");
772
+ return args;
773
+ }
774
+ function validateToolCalls(calls) {
775
+ const ids = /* @__PURE__ */ new Set();
776
+ for (const call of calls) {
777
+ if (!call || typeof call.id !== "string" || !call.id || typeof call.name !== "string" || !call.name || ids.has(call.id))
778
+ throw invalidProviderResponse(
779
+ "Tool calls have missing or duplicate identities"
780
+ );
781
+ ids.add(call.id);
782
+ if (typeof call.args === "string")
783
+ throw invalidProviderResponse("Parsed tool arguments must be an object");
784
+ parseToolArguments(call.args);
785
+ }
786
+ }
787
+
637
788
  // src/core/openai-responses.ts
638
789
  function resolveOpenAITransport(defaults, overrides) {
639
790
  return {
@@ -740,35 +891,6 @@ function getResponseReplay(metadata) {
740
891
  return responseReplayMetadata(metadata)?.openai?.response?.output;
741
892
  }
742
893
 
743
- // src/core/provider-error.ts
744
- function invalidProviderResponse(message) {
745
- return Object.assign(new Error(message), {
746
- name: "InvalidProviderResponseError",
747
- status: 502,
748
- code: "INVALID_PROVIDER_RESPONSE"
749
- });
750
- }
751
- function providerErrorEvent(error, code) {
752
- const details = error ?? {};
753
- const event = {
754
- type: "error",
755
- message: error instanceof Error ? error.message : String(error),
756
- code,
757
- ...typeof details.status === "number" ? { status: details.status } : {},
758
- ...typeof details.code === "string" ? { providerCode: details.code } : {},
759
- ...typeof details.param === "string" ? { param: details.param } : {},
760
- ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
761
- };
762
- Object.defineProperty(event, "cause", { value: error, enumerable: false });
763
- return event;
764
- }
765
- function throwIfAborted(signal) {
766
- if (!signal?.aborted) return;
767
- const error = new Error("The operation was aborted");
768
- error.name = "AbortError";
769
- throw error;
770
- }
771
-
772
894
  // src/core/utils.ts
773
895
  function generateId(prefix = "id") {
774
896
  return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
@@ -802,6 +924,8 @@ var OpenAIAdapter = class _OpenAIAdapter {
802
924
  apiKey: this.config.apiKey,
803
925
  baseURL: this.config.baseUrl,
804
926
  organization: this.config.organization,
927
+ project: this.config.project,
928
+ timeout: this.config.timeout,
805
929
  defaultHeaders: this.config.headers
806
930
  });
807
931
  }
@@ -1083,6 +1207,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
1083
1207
  request.config?.responseFormat
1084
1208
  );
1085
1209
  const modelIdForPayload = request.config?.model || this.model;
1210
+ const include = filterOpenAIResponseInclude(
1211
+ modelIdForPayload,
1212
+ [
1213
+ .../* @__PURE__ */ new Set([
1214
+ ...options?.include ?? [],
1215
+ ...options?.store === false ? ["reasoning.encrypted_content"] : []
1216
+ ])
1217
+ ],
1218
+ this.parameterOptions(request)
1219
+ );
1086
1220
  const payload = {
1087
1221
  model: modelIdForPayload,
1088
1222
  instructions: request.systemPrompt,
@@ -1106,14 +1240,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
1106
1240
  ...options?.promptCacheKey !== void 0 ? { prompt_cache_key: options.promptCacheKey } : {},
1107
1241
  ...options?.promptCacheOptions !== void 0 ? { prompt_cache_options: options.promptCacheOptions } : {},
1108
1242
  ...options?.promptCacheRetention !== void 0 ? { prompt_cache_retention: options.promptCacheRetention } : {},
1109
- ...options?.store === false || options?.include ? {
1110
- include: [
1111
- .../* @__PURE__ */ new Set([
1112
- ...options?.include ?? [],
1113
- ...options?.store === false ? ["reasoning.encrypted_content"] : []
1114
- ])
1115
- ]
1116
- } : {},
1243
+ ...include ? { include } : {},
1117
1244
  ...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
1118
1245
  stream
1119
1246
  };
@@ -1484,15 +1611,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1484
1611
  }
1485
1612
  throwIfAborted(request.signal);
1486
1613
  if (!finishReason)
1487
- throw new Error("OpenAI stream ended without a finish reason");
1614
+ throw invalidProviderResponse(
1615
+ "OpenAI stream ended without a finish reason"
1616
+ );
1488
1617
  if (toolCalls.size && !["tool_calls", "function_call"].includes(finishReason)) {
1489
- throw new Error("OpenAI stream ended with incomplete tool calls");
1490
- }
1491
- for (const call of toolCalls.values()) {
1492
- if (!call.id || !call.name)
1493
- throw new Error("OpenAI stream contains an incomplete tool call");
1494
- JSON.parse(call.arguments || "{}");
1618
+ throw invalidProviderResponse(
1619
+ "OpenAI stream ended with incomplete tool calls"
1620
+ );
1495
1621
  }
1622
+ validateToolCalls(
1623
+ [...toolCalls.values()].map((call) => ({
1624
+ ...call,
1625
+ args: parseToolArguments(call.arguments)
1626
+ }))
1627
+ );
1496
1628
  for (const call of toolCalls.values()) {
1497
1629
  yield {
1498
1630
  type: "action:start",
@@ -1576,20 +1708,20 @@ var OpenAIAdapter = class _OpenAIAdapter {
1576
1708
  logProviderPayload("openai", "response payload", response, request.debug);
1577
1709
  const choice = response.choices?.[0];
1578
1710
  const message = choice?.message;
1711
+ const toolCalls = (message?.tool_calls ?? []).map((toolCall) => ({
1712
+ id: toolCall.id,
1713
+ name: toolCall.function?.name,
1714
+ args: parseToolArguments(toolCall.function?.arguments ?? "{}"),
1715
+ ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1716
+ }));
1717
+ validateToolCalls(toolCalls);
1718
+ if (toolCalls.length && choice?.finish_reason && !["tool_calls", "function_call"].includes(choice.finish_reason))
1719
+ throw invalidProviderResponse(
1720
+ "OpenAI response ended with incomplete tool calls"
1721
+ );
1579
1722
  return {
1580
1723
  content: message?.content ?? "",
1581
- toolCalls: message?.tool_calls?.map((toolCall) => ({
1582
- id: toolCall.id ?? generateToolCallId(),
1583
- name: toolCall.function?.name ?? "",
1584
- args: (() => {
1585
- try {
1586
- return JSON.parse(toolCall.function?.arguments ?? "{}");
1587
- } catch {
1588
- return {};
1589
- }
1590
- })(),
1591
- ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1592
- })) ?? [],
1724
+ toolCalls,
1593
1725
  usage: response.usage ? {
1594
1726
  promptTokens: response.usage.prompt_tokens,
1595
1727
  completionTokens: response.usage.completion_tokens,
@@ -1622,6 +1754,52 @@ function createOpenAIAdapter(config) {
1622
1754
  return new OpenAIAdapter(config);
1623
1755
  }
1624
1756
 
1757
+ // src/core/anthropic-parameters.ts
1758
+ function anthropicMaxTokens(maxTokens, thinking) {
1759
+ return maxTokens ?? Math.max(4096, Number(thinking?.budget_tokens ?? 0) + 1);
1760
+ }
1761
+ function anthropicModelRules(model) {
1762
+ const match = /^claude-(opus|sonnet|haiku)-(\d+)(?:-(\d{1,2})(?=-|$))?(?:-|$)/i.exec(
1763
+ model
1764
+ );
1765
+ const family = match?.[1]?.toLowerCase();
1766
+ const major = Number(match?.[2] ?? 0);
1767
+ const minor = Number(match?.[3] ?? 0);
1768
+ const adaptive = major >= 5 || major === 4 && minor >= 6;
1769
+ return {
1770
+ structured: major >= 5 || major === 4 && minor >= 5,
1771
+ thinking: major >= 4 || /^claude-3-7-/.test(model),
1772
+ adaptive,
1773
+ rejectsSampling: major >= 5 || family === "opus" && major === 4 && minor >= 7
1774
+ };
1775
+ }
1776
+ function anthropicInputTokens(usage) {
1777
+ return (usage?.input_tokens ?? 0) + (usage?.cache_creation_input_tokens ?? 0) + (usage?.cache_read_input_tokens ?? 0);
1778
+ }
1779
+ function anthropicThinking(model, thinking) {
1780
+ if (!thinking) return void 0;
1781
+ if (thinking.type === "enabled") {
1782
+ if (anthropicModelRules(model).adaptive) {
1783
+ console.warn(
1784
+ `[llm-sdk] ${model}: using adaptive thinking instead of a legacy token budget.`
1785
+ );
1786
+ return { type: "adaptive" };
1787
+ }
1788
+ return { type: "enabled", budget_tokens: thinking.budgetTokens ?? 1e4 };
1789
+ }
1790
+ return { ...thinking };
1791
+ }
1792
+ function anthropicTemperature(model, temperature, thinking = false) {
1793
+ if (temperature === void 0) return {};
1794
+ if (thinking || anthropicModelRules(model).rejectsSampling) {
1795
+ console.warn(
1796
+ `[llm-sdk] ${model}: omitted temperature because this model or thinking mode does not support it.`
1797
+ );
1798
+ return {};
1799
+ }
1800
+ return { temperature };
1801
+ }
1802
+
1625
1803
  // src/adapters/anthropic.ts
1626
1804
  var AnthropicAdapter = class {
1627
1805
  constructor(config) {
@@ -1633,7 +1811,10 @@ var AnthropicAdapter = class {
1633
1811
  if (!this.client) {
1634
1812
  const { default: Anthropic } = await import('@anthropic-ai/sdk');
1635
1813
  this.client = new Anthropic({
1636
- apiKey: this.config.apiKey
1814
+ apiKey: this.config.apiKey,
1815
+ baseURL: this.config.baseUrl,
1816
+ timeout: this.config.timeout,
1817
+ defaultHeaders: this.config.headers
1637
1818
  });
1638
1819
  }
1639
1820
  return this.client;
@@ -1670,6 +1851,15 @@ var AnthropicAdapter = class {
1670
1851
  lastToolCallIds = [];
1671
1852
  toolResultIndex = 0;
1672
1853
  }
1854
+ const replay = anthropicReplayContent(
1855
+ msg.providerMetadata
1856
+ );
1857
+ if (replay) {
1858
+ messages.push({ role: "assistant", content: replay });
1859
+ lastToolCallIds = replay.filter((b) => b.type === "tool_use").map((b) => b.id);
1860
+ toolResultIndex = 0;
1861
+ continue;
1862
+ }
1673
1863
  const content = [];
1674
1864
  if (msg.content && typeof msg.content === "string" && msg.content.trim()) {
1675
1865
  content.push({ type: "text", text: msg.content });
@@ -1845,7 +2035,7 @@ var AnthropicAdapter = class {
1845
2035
  */
1846
2036
  buildRequestOptions(request) {
1847
2037
  const responseFormat = request.config?.responseFormat;
1848
- const jsonObjectSuffix = responseFormat?.type === "json_object" ? "\n\nRespond with a single JSON object and no other text." : "";
2038
+ const jsonObjectSuffix = responseFormat?.type === "json_object" ? "\n\nRespond with a single JSON object and no other text. Do not include Markdown code fences." : "";
1849
2039
  let systemMessage;
1850
2040
  let messages;
1851
2041
  if (request.rawMessages && request.rawMessages.length > 0) {
@@ -1867,7 +2057,17 @@ var AnthropicAdapter = class {
1867
2057
  const tools = anthropicNativeSearch?.enabled ? this.buildNativeSearchTools(
1868
2058
  request.toolDefinitions ?? [],
1869
2059
  anthropicNativeSearch.variant
1870
- ) : request.actions?.map((action) => ({
2060
+ ) : request.toolDefinitions?.length ? request.toolDefinitions.filter((tool) => tool.available !== false).map((tool) => ({
2061
+ name: tool.name,
2062
+ description: tool.description,
2063
+ // Keep the original schema. Legacy ActionParameter conversion
2064
+ // cannot represent unions, null, or nested required constraints.
2065
+ input_schema: tool.inputSchema ?? {
2066
+ type: "object",
2067
+ properties: {},
2068
+ required: []
2069
+ }
2070
+ })) : request.actions?.map((action) => ({
1871
2071
  name: action.name,
1872
2072
  description: action.description,
1873
2073
  input_schema: {
@@ -1909,12 +2109,25 @@ var AnthropicAdapter = class {
1909
2109
  };
1910
2110
  }
1911
2111
  }
2112
+ const thinking = anthropicThinking(
2113
+ request.config?.model || this.model,
2114
+ this.config.thinking
2115
+ );
1912
2116
  const options = {
1913
2117
  model: request.config?.model || this.model,
1914
- max_tokens: request.config?.maxTokens || this.config.maxTokens || 4096,
2118
+ max_tokens: anthropicMaxTokens(
2119
+ request.config?.maxTokens ?? this.config.maxTokens,
2120
+ thinking
2121
+ ),
1915
2122
  system: systemMessage,
1916
2123
  messages,
1917
- tools: tools.length ? tools : void 0
2124
+ tools: tools.length ? tools : void 0,
2125
+ ...this.config.cacheControl ? { cache_control: { type: "ephemeral" } } : {},
2126
+ ...anthropicTemperature(
2127
+ request.config?.model || this.model,
2128
+ request.config?.temperature ?? this.config.temperature,
2129
+ !!this.config.thinking && this.config.thinking.type !== "disabled"
2130
+ )
1918
2131
  };
1919
2132
  const anthropicToolOptions = request.providerToolOptions?.anthropic;
1920
2133
  if (tools.length > 0 && anthropicToolOptions) {
@@ -1933,15 +2146,13 @@ var AnthropicAdapter = class {
1933
2146
  options.server_tool_configuration = serverToolConfiguration;
1934
2147
  }
1935
2148
  const outputConfig = toAnthropicOutputConfig(responseFormat);
1936
- if (outputConfig) {
1937
- options.output_config = outputConfig;
1938
- }
1939
- if (this.config.thinking?.type === "enabled") {
1940
- options.thinking = {
1941
- type: "enabled",
1942
- budget_tokens: this.config.thinking.budgetTokens || 1e4
2149
+ if (outputConfig || this.config.effort) {
2150
+ options.output_config = {
2151
+ ...outputConfig,
2152
+ ...this.config.effort ? { effort: this.config.effort } : {}
1943
2153
  };
1944
2154
  }
2155
+ if (thinking) options.thinking = thinking;
1945
2156
  return { options, messages };
1946
2157
  }
1947
2158
  /**
@@ -1961,7 +2172,9 @@ var AnthropicAdapter = class {
1961
2172
  nonStreamingOptions,
1962
2173
  request.debug
1963
2174
  );
1964
- const response = await client.messages.create(nonStreamingOptions);
2175
+ const response = await client.messages.create(nonStreamingOptions, {
2176
+ signal: request.signal
2177
+ });
1965
2178
  logProviderPayload(
1966
2179
  "anthropic",
1967
2180
  "response payload",
@@ -1984,14 +2197,20 @@ var AnthropicAdapter = class {
1984
2197
  });
1985
2198
  }
1986
2199
  }
2200
+ validateToolCalls(toolCalls);
2201
+ if (toolCalls.length && response.stop_reason !== "tool_use")
2202
+ throw invalidProviderResponse(
2203
+ "Anthropic response ended with incomplete tool calls"
2204
+ );
1987
2205
  return {
1988
2206
  content,
2207
+ providerMetadata: anthropicReplay(response.content),
1989
2208
  toolCalls,
1990
2209
  thinking: thinking || void 0,
1991
2210
  usage: response.usage ? {
1992
- promptTokens: response.usage.input_tokens ?? 0,
2211
+ promptTokens: anthropicInputTokens(response.usage),
1993
2212
  completionTokens: response.usage.output_tokens ?? 0,
1994
- totalTokens: (response.usage.input_tokens ?? 0) + (response.usage.output_tokens ?? 0)
2213
+ totalTokens: anthropicInputTokens(response.usage) + (response.usage.output_tokens ?? 0)
1995
2214
  } : void 0,
1996
2215
  rawResponse: response
1997
2216
  };
@@ -2011,28 +2230,33 @@ var AnthropicAdapter = class {
2011
2230
  options,
2012
2231
  request.debug
2013
2232
  );
2014
- const stream = await client.messages.stream(options);
2233
+ const stream = await client.messages.stream(options, {
2234
+ signal: request.signal
2235
+ });
2015
2236
  let currentToolUse = null;
2016
2237
  let isInThinkingBlock = false;
2238
+ const content = [];
2239
+ const toolCalls = [];
2240
+ let stopReason;
2017
2241
  const collectedCitations = [];
2018
2242
  let citationIndex = 0;
2019
2243
  let usage;
2020
2244
  for await (const event of stream) {
2245
+ collectAnthropicContent(content, event);
2021
2246
  logProviderPayload("anthropic", "stream event", event, request.debug);
2022
- if (request.signal?.aborted) {
2023
- break;
2024
- }
2247
+ throwIfAborted(request.signal);
2025
2248
  switch (event.type) {
2026
2249
  case "message_start":
2027
2250
  if (event.message?.usage) {
2028
2251
  usage = {
2029
- prompt_tokens: event.message.usage.input_tokens,
2252
+ prompt_tokens: anthropicInputTokens(event.message.usage),
2030
2253
  completion_tokens: 0,
2031
- total_tokens: event.message.usage.input_tokens
2254
+ total_tokens: anthropicInputTokens(event.message.usage)
2032
2255
  };
2033
2256
  }
2034
2257
  break;
2035
2258
  case "message_delta":
2259
+ if (event.delta?.stop_reason) stopReason = event.delta.stop_reason;
2036
2260
  if (event.usage && usage) {
2037
2261
  usage.completion_tokens = event.usage.output_tokens;
2038
2262
  usage.total_tokens = usage.prompt_tokens + event.usage.output_tokens;
@@ -2045,13 +2269,6 @@ var AnthropicAdapter = class {
2045
2269
  name: event.content_block.name,
2046
2270
  input: ""
2047
2271
  };
2048
- if (currentToolUse.name !== "web_search") {
2049
- yield {
2050
- type: "action:start",
2051
- id: currentToolUse.id,
2052
- name: currentToolUse.name
2053
- };
2054
- }
2055
2272
  } else if (event.content_block.type === "web_search_tool_result") {
2056
2273
  const webSearchResult = event.content_block;
2057
2274
  if (webSearchResult.content && Array.isArray(webSearchResult.content)) {
@@ -2100,16 +2317,11 @@ var AnthropicAdapter = class {
2100
2317
  case "content_block_stop":
2101
2318
  if (currentToolUse) {
2102
2319
  if (currentToolUse.name !== "web_search") {
2103
- yield {
2104
- type: "action:args",
2105
- id: currentToolUse.id,
2106
- args: currentToolUse.input
2107
- };
2108
- yield {
2109
- type: "action:end",
2320
+ toolCalls.push({
2110
2321
  id: currentToolUse.id,
2111
- name: currentToolUse.name
2112
- };
2322
+ name: currentToolUse.name,
2323
+ args: parseToolArguments(currentToolUse.input)
2324
+ });
2113
2325
  }
2114
2326
  currentToolUse = null;
2115
2327
  }
@@ -2122,18 +2334,33 @@ var AnthropicAdapter = class {
2122
2334
  break;
2123
2335
  }
2124
2336
  }
2337
+ throwIfAborted(request.signal);
2338
+ if (!stopReason || currentToolUse)
2339
+ throw invalidProviderResponse(
2340
+ "Anthropic stream ended before its turn completed"
2341
+ );
2342
+ validateToolCalls(toolCalls);
2343
+ if (toolCalls.length && stopReason !== "tool_use")
2344
+ throw invalidProviderResponse(
2345
+ "Anthropic stream ended with incomplete tool calls"
2346
+ );
2347
+ for (const call of toolCalls) {
2348
+ yield { type: "action:start", id: call.id, name: call.name };
2349
+ yield {
2350
+ type: "action:args",
2351
+ id: call.id,
2352
+ args: JSON.stringify(call.args)
2353
+ };
2354
+ yield { type: "action:end", id: call.id, name: call.name };
2355
+ }
2125
2356
  if (collectedCitations.length > 0) {
2126
2357
  const uniqueCitations = deduplicateCitations2(collectedCitations);
2127
2358
  yield { type: "citation", citations: uniqueCitations };
2128
2359
  }
2129
2360
  yield { type: "message:end" };
2130
- yield { type: "done", usage };
2361
+ yield { type: "done", usage, providerMetadata: anthropicReplay(content) };
2131
2362
  } catch (error) {
2132
- yield {
2133
- type: "error",
2134
- message: error instanceof Error ? error.message : "Unknown error",
2135
- code: "ANTHROPIC_ERROR"
2136
- };
2363
+ yield providerErrorEvent(error, "ANTHROPIC_ERROR");
2137
2364
  }
2138
2365
  }
2139
2366
  };