@ai-sdk/anthropic 2.0.47 → 2.0.48

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,11 @@
1
1
  # @ai-sdk/anthropic
2
2
 
3
+ ## 2.0.48
4
+
5
+ ### Patch Changes
6
+
7
+ - f2c6cbd: feat(provider/anthropic): Anthropic-native structured outputs
8
+
3
9
  ## 2.0.47
4
10
 
5
11
  ### 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.48" : "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()
@@ -1769,7 +1783,7 @@ var AnthropicMessagesLanguageModel = class {
1769
1783
  toolChoice,
1770
1784
  providerOptions
1771
1785
  }) {
1772
- var _a, _b, _c, _d;
1786
+ var _a, _b, _c, _d, _e;
1773
1787
  const warnings = [];
1774
1788
  if (frequencyPenalty != null) {
1775
1789
  warnings.push({
@@ -1819,27 +1833,33 @@ var AnthropicMessagesLanguageModel = class {
1819
1833
  });
1820
1834
  }
1821
1835
  }
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
1836
  const anthropicOptions = await (0, import_provider_utils11.parseProviderOptions)({
1829
1837
  provider: "anthropic",
1830
1838
  providerOptions,
1831
1839
  schema: anthropicProviderOptions
1832
1840
  });
1841
+ const {
1842
+ maxOutputTokens: maxOutputTokensForModel,
1843
+ supportsStructuredOutput,
1844
+ isKnownModel
1845
+ } = getModelCapabilities(this.modelId);
1846
+ const structureOutputMode = (_a = anthropicOptions == null ? void 0 : anthropicOptions.structuredOutputMode) != null ? _a : "jsonTool";
1847
+ const useStructuredOutput = structureOutputMode === "outputFormat" || structureOutputMode === "auto" && supportsStructuredOutput;
1848
+ const jsonResponseTool = (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && !useStructuredOutput ? {
1849
+ type: "function",
1850
+ name: "json",
1851
+ description: "Respond with a JSON object.",
1852
+ inputSchema: responseFormat.schema
1853
+ } : void 0;
1833
1854
  const cacheControlValidator = new CacheControlValidator();
1834
1855
  const { prompt: messagesPrompt, betas } = await convertToAnthropicMessagesPrompt({
1835
1856
  prompt,
1836
- sendReasoning: (_a = anthropicOptions == null ? void 0 : anthropicOptions.sendReasoning) != null ? _a : true,
1857
+ sendReasoning: (_b = anthropicOptions == null ? void 0 : anthropicOptions.sendReasoning) != null ? _b : true,
1837
1858
  warnings,
1838
1859
  cacheControlValidator
1839
1860
  });
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);
1861
+ const isThinking = ((_c = anthropicOptions == null ? void 0 : anthropicOptions.thinking) == null ? void 0 : _c.type) === "enabled";
1862
+ const thinkingBudget = (_d = anthropicOptions == null ? void 0 : anthropicOptions.thinking) == null ? void 0 : _d.budgetTokens;
1843
1863
  const maxTokens = maxOutputTokens != null ? maxOutputTokens : maxOutputTokensForModel;
1844
1864
  const baseArgs = {
1845
1865
  // model id:
@@ -1857,11 +1877,18 @@ var AnthropicMessagesLanguageModel = class {
1857
1877
  ...(anthropicOptions == null ? void 0 : anthropicOptions.effort) && {
1858
1878
  output_config: { effort: anthropicOptions.effort }
1859
1879
  },
1880
+ // structured output:
1881
+ ...useStructuredOutput && (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && {
1882
+ output_format: {
1883
+ type: "json_schema",
1884
+ schema: responseFormat.schema
1885
+ }
1886
+ },
1860
1887
  // container with agent skills:
1861
1888
  ...(anthropicOptions == null ? void 0 : anthropicOptions.container) && {
1862
1889
  container: {
1863
1890
  id: anthropicOptions.container.id,
1864
- skills: (_d = anthropicOptions.container.skills) == null ? void 0 : _d.map((skill) => ({
1891
+ skills: (_e = anthropicOptions.container.skills) == null ? void 0 : _e.map((skill) => ({
1865
1892
  type: skill.type,
1866
1893
  skill_id: skill.skillId,
1867
1894
  version: skill.version
@@ -1904,7 +1931,7 @@ var AnthropicMessagesLanguageModel = class {
1904
1931
  }
1905
1932
  baseArgs.max_tokens = maxTokens + thinkingBudget;
1906
1933
  }
1907
- if (knownModel && baseArgs.max_tokens > maxOutputTokensForModel) {
1934
+ if (isKnownModel && baseArgs.max_tokens > maxOutputTokensForModel) {
1908
1935
  if (maxOutputTokens != null) {
1909
1936
  warnings.push({
1910
1937
  type: "unsupported-setting",
@@ -1930,6 +1957,9 @@ var AnthropicMessagesLanguageModel = class {
1930
1957
  if (anthropicOptions == null ? void 0 : anthropicOptions.effort) {
1931
1958
  betas.add("effort-2025-11-24");
1932
1959
  }
1960
+ if (useStructuredOutput) {
1961
+ betas.add("structured-outputs-2025-11-13");
1962
+ }
1933
1963
  const {
1934
1964
  tools: anthropicTools2,
1935
1965
  toolChoice: anthropicToolChoice,
@@ -2732,27 +2762,49 @@ var AnthropicMessagesLanguageModel = class {
2732
2762
  };
2733
2763
  }
2734
2764
  };
2735
- function getMaxOutputTokensForModel(modelId) {
2765
+ function getModelCapabilities(modelId) {
2736
2766
  if (modelId.includes("claude-sonnet-4-5") || modelId.includes("claude-opus-4-5")) {
2737
2767
  return {
2738
2768
  maxOutputTokens: 64e3,
2739
- knownModel: true
2769
+ supportsStructuredOutput: true,
2770
+ isKnownModel: true
2740
2771
  };
2741
2772
  } else if (modelId.includes("claude-opus-4-1")) {
2742
2773
  return {
2743
2774
  maxOutputTokens: 32e3,
2744
- knownModel: true
2775
+ supportsStructuredOutput: true,
2776
+ isKnownModel: true
2745
2777
  };
2746
2778
  } 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 };
2779
+ return {
2780
+ maxOutputTokens: 64e3,
2781
+ supportsStructuredOutput: false,
2782
+ isKnownModel: true
2783
+ };
2748
2784
  } else if (modelId.includes("claude-opus-4-")) {
2749
- return { maxOutputTokens: 32e3, knownModel: true };
2785
+ return {
2786
+ maxOutputTokens: 32e3,
2787
+ supportsStructuredOutput: false,
2788
+ isKnownModel: true
2789
+ };
2750
2790
  } else if (modelId.includes("claude-3-5-haiku")) {
2751
- return { maxOutputTokens: 8192, knownModel: true };
2791
+ return {
2792
+ maxOutputTokens: 8192,
2793
+ supportsStructuredOutput: false,
2794
+ isKnownModel: true
2795
+ };
2752
2796
  } else if (modelId.includes("claude-3-haiku")) {
2753
- return { maxOutputTokens: 4096, knownModel: true };
2797
+ return {
2798
+ maxOutputTokens: 4096,
2799
+ supportsStructuredOutput: false,
2800
+ isKnownModel: true
2801
+ };
2754
2802
  } else {
2755
- return { maxOutputTokens: 4096, knownModel: false };
2803
+ return {
2804
+ maxOutputTokens: 4096,
2805
+ supportsStructuredOutput: false,
2806
+ isKnownModel: false
2807
+ };
2756
2808
  }
2757
2809
  }
2758
2810