@ai-sdk/anthropic 2.0.47 → 2.0.49

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @ai-sdk/anthropic
2
2
 
3
+ ## 2.0.49
4
+
5
+ ### Patch Changes
6
+
7
+ - dcdfeb7: Retain user-supplied betas.
8
+
9
+ ## 2.0.48
10
+
11
+ ### Patch Changes
12
+
13
+ - f2c6cbd: feat(provider/anthropic): Anthropic-native structured outputs
14
+
3
15
  ## 2.0.47
4
16
 
5
17
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -45,6 +45,11 @@ interface AnthropicMessageMetadata {
45
45
  type AnthropicMessagesModelId = 'claude-3-5-haiku-20241022' | 'claude-3-5-haiku-latest' | 'claude-3-7-sonnet-20250219' | 'claude-3-7-sonnet-latest' | 'claude-3-haiku-20240307' | 'claude-haiku-4-5-20251001' | 'claude-haiku-4-5' | 'claude-opus-4-0' | 'claude-opus-4-1-20250805' | 'claude-opus-4-1' | 'claude-opus-4-20250514' | 'claude-opus-4-5' | 'claude-opus-4-5-20251101' | 'claude-sonnet-4-0' | 'claude-sonnet-4-20250514' | 'claude-sonnet-4-5-20250929' | 'claude-sonnet-4-5' | (string & {});
46
46
  declare const anthropicProviderOptions: z.ZodObject<{
47
47
  sendReasoning: z.ZodOptional<z.ZodBoolean>;
48
+ structuredOutputMode: z.ZodOptional<z.ZodEnum<{
49
+ outputFormat: "outputFormat";
50
+ jsonTool: "jsonTool";
51
+ auto: "auto";
52
+ }>>;
48
53
  thinking: z.ZodOptional<z.ZodObject<{
49
54
  type: z.ZodUnion<readonly [z.ZodLiteral<"enabled">, z.ZodLiteral<"disabled">]>;
50
55
  budgetTokens: z.ZodOptional<z.ZodNumber>;
package/dist/index.d.ts CHANGED
@@ -45,6 +45,11 @@ interface AnthropicMessageMetadata {
45
45
  type AnthropicMessagesModelId = 'claude-3-5-haiku-20241022' | 'claude-3-5-haiku-latest' | 'claude-3-7-sonnet-20250219' | 'claude-3-7-sonnet-latest' | 'claude-3-haiku-20240307' | 'claude-haiku-4-5-20251001' | 'claude-haiku-4-5' | 'claude-opus-4-0' | 'claude-opus-4-1-20250805' | 'claude-opus-4-1' | 'claude-opus-4-20250514' | 'claude-opus-4-5' | 'claude-opus-4-5-20251101' | 'claude-sonnet-4-0' | 'claude-sonnet-4-20250514' | 'claude-sonnet-4-5-20250929' | 'claude-sonnet-4-5' | (string & {});
46
46
  declare const anthropicProviderOptions: z.ZodObject<{
47
47
  sendReasoning: z.ZodOptional<z.ZodBoolean>;
48
+ structuredOutputMode: z.ZodOptional<z.ZodEnum<{
49
+ outputFormat: "outputFormat";
50
+ jsonTool: "jsonTool";
51
+ auto: "auto";
52
+ }>>;
48
53
  thinking: z.ZodOptional<z.ZodObject<{
49
54
  type: z.ZodUnion<readonly [z.ZodLiteral<"enabled">, z.ZodLiteral<"disabled">]>;
50
55
  budgetTokens: z.ZodOptional<z.ZodNumber>;
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ var import_provider4 = require("@ai-sdk/provider");
31
31
  var import_provider_utils20 = require("@ai-sdk/provider-utils");
32
32
 
33
33
  // src/version.ts
34
- var VERSION = true ? "2.0.47" : "0.0.0-test";
34
+ var VERSION = true ? "2.0.49" : "0.0.0-test";
35
35
 
36
36
  // src/anthropic-messages-language-model.ts
37
37
  var import_provider3 = require("@ai-sdk/provider");
@@ -552,6 +552,20 @@ var anthropicFilePartProviderOptions = import_v43.z.object({
552
552
  });
553
553
  var anthropicProviderOptions = import_v43.z.object({
554
554
  sendReasoning: import_v43.z.boolean().optional(),
555
+ /**
556
+ * Determines how structured outputs are generated.
557
+ *
558
+ * - `outputFormat`: Use the `output_format` parameter to specify the structured output format.
559
+ * - `jsonTool`: Use a special 'json' tool to specify the structured output format (default).
560
+ * - `auto`: Use 'outputFormat' when supported, otherwise use 'jsonTool'.
561
+ */
562
+ structuredOutputMode: import_v43.z.enum(["outputFormat", "jsonTool", "auto"]).optional(),
563
+ /**
564
+ * Configuration for enabling Claude's extended thinking.
565
+ *
566
+ * When enabled, responses include thinking content blocks showing Claude's thinking process before the final answer.
567
+ * Requires a minimum budget of 1,024 tokens and counts towards the `max_tokens` limit.
568
+ */
555
569
  thinking: import_v43.z.object({
556
570
  type: import_v43.z.union([import_v43.z.literal("enabled"), import_v43.z.literal("disabled")]),
557
571
  budgetTokens: import_v43.z.number().optional()
@@ -1755,6 +1769,7 @@ var AnthropicMessagesLanguageModel = class {
1755
1769
  return (_c = (_b = (_a = this.config).supportedUrls) == null ? void 0 : _b.call(_a)) != null ? _c : {};
1756
1770
  }
1757
1771
  async getArgs({
1772
+ userSuppliedBetas,
1758
1773
  prompt,
1759
1774
  maxOutputTokens,
1760
1775
  temperature,
@@ -1769,7 +1784,7 @@ var AnthropicMessagesLanguageModel = class {
1769
1784
  toolChoice,
1770
1785
  providerOptions
1771
1786
  }) {
1772
- var _a, _b, _c, _d;
1787
+ var _a, _b, _c, _d, _e;
1773
1788
  const warnings = [];
1774
1789
  if (frequencyPenalty != null) {
1775
1790
  warnings.push({
@@ -1819,27 +1834,33 @@ var AnthropicMessagesLanguageModel = class {
1819
1834
  });
1820
1835
  }
1821
1836
  }
1822
- const jsonResponseTool = (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null ? {
1823
- type: "function",
1824
- name: "json",
1825
- description: "Respond with a JSON object.",
1826
- inputSchema: responseFormat.schema
1827
- } : void 0;
1828
1837
  const anthropicOptions = await (0, import_provider_utils11.parseProviderOptions)({
1829
1838
  provider: "anthropic",
1830
1839
  providerOptions,
1831
1840
  schema: anthropicProviderOptions
1832
1841
  });
1842
+ const {
1843
+ maxOutputTokens: maxOutputTokensForModel,
1844
+ supportsStructuredOutput,
1845
+ isKnownModel
1846
+ } = getModelCapabilities(this.modelId);
1847
+ const structureOutputMode = (_a = anthropicOptions == null ? void 0 : anthropicOptions.structuredOutputMode) != null ? _a : "jsonTool";
1848
+ const useStructuredOutput = structureOutputMode === "outputFormat" || structureOutputMode === "auto" && supportsStructuredOutput;
1849
+ const jsonResponseTool = (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && !useStructuredOutput ? {
1850
+ type: "function",
1851
+ name: "json",
1852
+ description: "Respond with a JSON object.",
1853
+ inputSchema: responseFormat.schema
1854
+ } : void 0;
1833
1855
  const cacheControlValidator = new CacheControlValidator();
1834
1856
  const { prompt: messagesPrompt, betas } = await convertToAnthropicMessagesPrompt({
1835
1857
  prompt,
1836
- sendReasoning: (_a = anthropicOptions == null ? void 0 : anthropicOptions.sendReasoning) != null ? _a : true,
1858
+ sendReasoning: (_b = anthropicOptions == null ? void 0 : anthropicOptions.sendReasoning) != null ? _b : true,
1837
1859
  warnings,
1838
1860
  cacheControlValidator
1839
1861
  });
1840
- const isThinking = ((_b = anthropicOptions == null ? void 0 : anthropicOptions.thinking) == null ? void 0 : _b.type) === "enabled";
1841
- const thinkingBudget = (_c = anthropicOptions == null ? void 0 : anthropicOptions.thinking) == null ? void 0 : _c.budgetTokens;
1842
- const { maxOutputTokens: maxOutputTokensForModel, knownModel } = getMaxOutputTokensForModel(this.modelId);
1862
+ const isThinking = ((_c = anthropicOptions == null ? void 0 : anthropicOptions.thinking) == null ? void 0 : _c.type) === "enabled";
1863
+ const thinkingBudget = (_d = anthropicOptions == null ? void 0 : anthropicOptions.thinking) == null ? void 0 : _d.budgetTokens;
1843
1864
  const maxTokens = maxOutputTokens != null ? maxOutputTokens : maxOutputTokensForModel;
1844
1865
  const baseArgs = {
1845
1866
  // model id:
@@ -1857,11 +1878,18 @@ var AnthropicMessagesLanguageModel = class {
1857
1878
  ...(anthropicOptions == null ? void 0 : anthropicOptions.effort) && {
1858
1879
  output_config: { effort: anthropicOptions.effort }
1859
1880
  },
1881
+ // structured output:
1882
+ ...useStructuredOutput && (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && {
1883
+ output_format: {
1884
+ type: "json_schema",
1885
+ schema: responseFormat.schema
1886
+ }
1887
+ },
1860
1888
  // container with agent skills:
1861
1889
  ...(anthropicOptions == null ? void 0 : anthropicOptions.container) && {
1862
1890
  container: {
1863
1891
  id: anthropicOptions.container.id,
1864
- skills: (_d = anthropicOptions.container.skills) == null ? void 0 : _d.map((skill) => ({
1892
+ skills: (_e = anthropicOptions.container.skills) == null ? void 0 : _e.map((skill) => ({
1865
1893
  type: skill.type,
1866
1894
  skill_id: skill.skillId,
1867
1895
  version: skill.version
@@ -1904,7 +1932,7 @@ var AnthropicMessagesLanguageModel = class {
1904
1932
  }
1905
1933
  baseArgs.max_tokens = maxTokens + thinkingBudget;
1906
1934
  }
1907
- if (knownModel && baseArgs.max_tokens > maxOutputTokensForModel) {
1935
+ if (isKnownModel && baseArgs.max_tokens > maxOutputTokensForModel) {
1908
1936
  if (maxOutputTokens != null) {
1909
1937
  warnings.push({
1910
1938
  type: "unsupported-setting",
@@ -1930,6 +1958,9 @@ var AnthropicMessagesLanguageModel = class {
1930
1958
  if (anthropicOptions == null ? void 0 : anthropicOptions.effort) {
1931
1959
  betas.add("effort-2025-11-24");
1932
1960
  }
1961
+ if (useStructuredOutput) {
1962
+ betas.add("structured-outputs-2025-11-13");
1963
+ }
1933
1964
  const {
1934
1965
  tools: anthropicTools2,
1935
1966
  toolChoice: anthropicToolChoice,
@@ -1956,7 +1987,7 @@ var AnthropicMessagesLanguageModel = class {
1956
1987
  tool_choice: anthropicToolChoice
1957
1988
  },
1958
1989
  warnings: [...warnings, ...toolWarnings, ...cacheWarnings],
1959
- betas: /* @__PURE__ */ new Set([...betas, ...toolsBetas]),
1990
+ betas: /* @__PURE__ */ new Set([...betas, ...toolsBetas, ...userSuppliedBetas]),
1960
1991
  usesJsonResponseTool: jsonResponseTool != null
1961
1992
  };
1962
1993
  }
@@ -1966,8 +1997,20 @@ var AnthropicMessagesLanguageModel = class {
1966
1997
  }) {
1967
1998
  return (0, import_provider_utils11.combineHeaders)(
1968
1999
  await (0, import_provider_utils11.resolve)(this.config.headers),
1969
- betas.size > 0 ? { "anthropic-beta": Array.from(betas).join(",") } : {},
1970
- headers
2000
+ headers,
2001
+ betas.size > 0 ? { "anthropic-beta": Array.from(betas).join(",") } : {}
2002
+ );
2003
+ }
2004
+ async getBetasFromHeaders(requestHeaders) {
2005
+ var _a, _b;
2006
+ const configHeaders = await (0, import_provider_utils11.resolve)(this.config.headers);
2007
+ const configBetaHeader = (_a = configHeaders["anthropic-beta"]) != null ? _a : "";
2008
+ const requestBetaHeader = (_b = requestHeaders == null ? void 0 : requestHeaders["anthropic-beta"]) != null ? _b : "";
2009
+ return new Set(
2010
+ [
2011
+ ...configBetaHeader.toLowerCase().split(","),
2012
+ ...requestBetaHeader.toLowerCase().split(",")
2013
+ ].map((beta) => beta.trim()).filter((beta) => beta !== "")
1971
2014
  );
1972
2015
  }
1973
2016
  buildRequestUrl(isStreaming) {
@@ -2003,7 +2046,10 @@ var AnthropicMessagesLanguageModel = class {
2003
2046
  }
2004
2047
  async doGenerate(options) {
2005
2048
  var _a, _b, _c, _d, _e, _f, _g, _h;
2006
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs(options);
2049
+ const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
2050
+ ...options,
2051
+ userSuppliedBetas: await this.getBetasFromHeaders(options.headers)
2052
+ });
2007
2053
  const citationDocuments = this.extractCitationDocuments(options.prompt);
2008
2054
  const {
2009
2055
  responseHeaders,
@@ -2268,7 +2314,10 @@ var AnthropicMessagesLanguageModel = class {
2268
2314
  };
2269
2315
  }
2270
2316
  async doStream(options) {
2271
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs(options);
2317
+ const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
2318
+ ...options,
2319
+ userSuppliedBetas: await this.getBetasFromHeaders(options.headers)
2320
+ });
2272
2321
  const citationDocuments = this.extractCitationDocuments(options.prompt);
2273
2322
  const body = { ...args, stream: true };
2274
2323
  const { responseHeaders, value: response } = await (0, import_provider_utils11.postJsonToApi)({
@@ -2732,27 +2781,49 @@ var AnthropicMessagesLanguageModel = class {
2732
2781
  };
2733
2782
  }
2734
2783
  };
2735
- function getMaxOutputTokensForModel(modelId) {
2784
+ function getModelCapabilities(modelId) {
2736
2785
  if (modelId.includes("claude-sonnet-4-5") || modelId.includes("claude-opus-4-5")) {
2737
2786
  return {
2738
2787
  maxOutputTokens: 64e3,
2739
- knownModel: true
2788
+ supportsStructuredOutput: true,
2789
+ isKnownModel: true
2740
2790
  };
2741
2791
  } else if (modelId.includes("claude-opus-4-1")) {
2742
2792
  return {
2743
2793
  maxOutputTokens: 32e3,
2744
- knownModel: true
2794
+ supportsStructuredOutput: true,
2795
+ isKnownModel: true
2745
2796
  };
2746
2797
  } else if (modelId.includes("claude-sonnet-4-") || modelId.includes("claude-3-7-sonnet") || modelId.includes("claude-haiku-4-5")) {
2747
- return { maxOutputTokens: 64e3, knownModel: true };
2798
+ return {
2799
+ maxOutputTokens: 64e3,
2800
+ supportsStructuredOutput: false,
2801
+ isKnownModel: true
2802
+ };
2748
2803
  } else if (modelId.includes("claude-opus-4-")) {
2749
- return { maxOutputTokens: 32e3, knownModel: true };
2804
+ return {
2805
+ maxOutputTokens: 32e3,
2806
+ supportsStructuredOutput: false,
2807
+ isKnownModel: true
2808
+ };
2750
2809
  } else if (modelId.includes("claude-3-5-haiku")) {
2751
- return { maxOutputTokens: 8192, knownModel: true };
2810
+ return {
2811
+ maxOutputTokens: 8192,
2812
+ supportsStructuredOutput: false,
2813
+ isKnownModel: true
2814
+ };
2752
2815
  } else if (modelId.includes("claude-3-haiku")) {
2753
- return { maxOutputTokens: 4096, knownModel: true };
2816
+ return {
2817
+ maxOutputTokens: 4096,
2818
+ supportsStructuredOutput: false,
2819
+ isKnownModel: true
2820
+ };
2754
2821
  } else {
2755
- return { maxOutputTokens: 4096, knownModel: false };
2822
+ return {
2823
+ maxOutputTokens: 4096,
2824
+ supportsStructuredOutput: false,
2825
+ isKnownModel: false
2826
+ };
2756
2827
  }
2757
2828
  }
2758
2829