@ai-sdk/anthropic 3.0.0-beta.43 → 3.0.0-beta.45

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
+ ## 3.0.0-beta.45
4
+
5
+ ### Patch Changes
6
+
7
+ - f4e4a95: feat(provider/anthropic): enable fine grained tool streaming by default
8
+
9
+ ## 3.0.0-beta.44
10
+
11
+ ### Patch Changes
12
+
13
+ - cf4e2a9: Add support for tool calling with structured output
14
+
3
15
  ## 3.0.0-beta.43
4
16
 
5
17
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -72,6 +72,7 @@ declare const anthropicProviderOptions: z.ZodObject<{
72
72
  version: z.ZodOptional<z.ZodString>;
73
73
  }, z.core.$strip>>>;
74
74
  }, z.core.$strip>>;
75
+ toolStreaming: z.ZodOptional<z.ZodBoolean>;
75
76
  }, z.core.$strip>;
76
77
  type AnthropicProviderOptions = z.infer<typeof anthropicProviderOptions>;
77
78
 
package/dist/index.d.ts CHANGED
@@ -72,6 +72,7 @@ declare const anthropicProviderOptions: z.ZodObject<{
72
72
  version: z.ZodOptional<z.ZodString>;
73
73
  }, z.core.$strip>>>;
74
74
  }, z.core.$strip>>;
75
+ toolStreaming: z.ZodOptional<z.ZodBoolean>;
75
76
  }, z.core.$strip>;
76
77
  type AnthropicProviderOptions = z.infer<typeof anthropicProviderOptions>;
77
78
 
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 ? "3.0.0-beta.43" : "0.0.0-test";
34
+ var VERSION = true ? "3.0.0-beta.45" : "0.0.0-test";
35
35
 
36
36
  // src/anthropic-messages-language-model.ts
37
37
  var import_provider3 = require("@ai-sdk/provider");
@@ -631,7 +631,16 @@ var anthropicProviderOptions = import_v43.z.object({
631
631
  version: import_v43.z.string().optional()
632
632
  })
633
633
  ).optional()
634
- }).optional()
634
+ }).optional(),
635
+ /**
636
+ * Whether to enable tool streaming (and structured output streaming).
637
+ *
638
+ * When set to false, the model will return all tool calls and results
639
+ * at once after a delay.
640
+ *
641
+ * @default true
642
+ */
643
+ toolStreaming: import_v43.z.boolean().optional()
635
644
  });
636
645
 
637
646
  // src/anthropic-prepare-tools.ts
@@ -1880,9 +1889,10 @@ var AnthropicMessagesLanguageModel = class {
1880
1889
  seed,
1881
1890
  tools,
1882
1891
  toolChoice,
1883
- providerOptions
1892
+ providerOptions,
1893
+ stream
1884
1894
  }) {
1885
- var _a, _b, _c, _d;
1895
+ var _a, _b, _c, _d, _e;
1886
1896
  const warnings = [];
1887
1897
  if (frequencyPenalty != null) {
1888
1898
  warnings.push({
@@ -1909,12 +1919,6 @@ var AnthropicMessagesLanguageModel = class {
1909
1919
  setting: "responseFormat",
1910
1920
  details: "JSON response format requires a schema. The response format is ignored."
1911
1921
  });
1912
- } else if (tools != null) {
1913
- warnings.push({
1914
- type: "unsupported-setting",
1915
- setting: "tools",
1916
- details: "JSON response format does not support tools. The provided tools are ignored."
1917
- });
1918
1922
  }
1919
1923
  }
1920
1924
  const jsonResponseTool = (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null ? {
@@ -2038,6 +2042,9 @@ var AnthropicMessagesLanguageModel = class {
2038
2042
  });
2039
2043
  }
2040
2044
  }
2045
+ if (stream && ((_e = anthropicOptions == null ? void 0 : anthropicOptions.toolStreaming) != null ? _e : true)) {
2046
+ betas.add("fine-grained-tool-streaming-2025-05-14");
2047
+ }
2041
2048
  const {
2042
2049
  tools: anthropicTools2,
2043
2050
  toolChoice: anthropicToolChoice,
@@ -2045,8 +2052,8 @@ var AnthropicMessagesLanguageModel = class {
2045
2052
  betas: toolsBetas
2046
2053
  } = await prepareTools(
2047
2054
  jsonResponseTool != null ? {
2048
- tools: [jsonResponseTool],
2049
- toolChoice: { type: "tool", toolName: jsonResponseTool.name },
2055
+ tools: [...tools != null ? tools : [], jsonResponseTool],
2056
+ toolChoice: { type: "required" },
2050
2057
  disableParallelToolUse: true,
2051
2058
  cacheControlValidator
2052
2059
  } : {
@@ -2061,7 +2068,9 @@ var AnthropicMessagesLanguageModel = class {
2061
2068
  args: {
2062
2069
  ...baseArgs,
2063
2070
  tools: anthropicTools2,
2064
- tool_choice: anthropicToolChoice
2071
+ tool_choice: anthropicToolChoice,
2072
+ stream: stream === true ? true : void 0
2073
+ // do not send when not streaming
2065
2074
  },
2066
2075
  warnings: [...warnings, ...toolWarnings, ...cacheWarnings],
2067
2076
  betas: /* @__PURE__ */ new Set([...betas, ...toolsBetas]),
@@ -2111,7 +2120,10 @@ var AnthropicMessagesLanguageModel = class {
2111
2120
  }
2112
2121
  async doGenerate(options) {
2113
2122
  var _a, _b, _c, _d, _e, _f, _g, _h;
2114
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs(options);
2123
+ const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
2124
+ ...options,
2125
+ stream: false
2126
+ });
2115
2127
  const citationDocuments = this.extractCitationDocuments(options.prompt);
2116
2128
  const {
2117
2129
  responseHeaders,
@@ -2130,6 +2142,7 @@ var AnthropicMessagesLanguageModel = class {
2130
2142
  });
2131
2143
  const content = [];
2132
2144
  const mcpToolCalls = {};
2145
+ let isJsonResponseFromTool = false;
2133
2146
  for (const part of response.content) {
2134
2147
  switch (part.type) {
2135
2148
  case "text": {
@@ -2175,18 +2188,21 @@ var AnthropicMessagesLanguageModel = class {
2175
2188
  break;
2176
2189
  }
2177
2190
  case "tool_use": {
2178
- content.push(
2179
- // when a json response tool is used, the tool call becomes the text:
2180
- usesJsonResponseTool ? {
2191
+ const isJsonResponseTool = usesJsonResponseTool && part.name === "json";
2192
+ if (isJsonResponseTool) {
2193
+ isJsonResponseFromTool = true;
2194
+ content.push({
2181
2195
  type: "text",
2182
2196
  text: JSON.stringify(part.input)
2183
- } : {
2197
+ });
2198
+ } else {
2199
+ content.push({
2184
2200
  type: "tool-call",
2185
2201
  toolCallId: part.id,
2186
2202
  toolName: part.name,
2187
2203
  input: JSON.stringify(part.input)
2188
- }
2189
- );
2204
+ });
2205
+ }
2190
2206
  break;
2191
2207
  }
2192
2208
  case "server_tool_use": {
@@ -2373,7 +2389,7 @@ var AnthropicMessagesLanguageModel = class {
2373
2389
  content,
2374
2390
  finishReason: mapAnthropicStopReason({
2375
2391
  finishReason: response.stop_reason,
2376
- isJsonResponseFromTool: usesJsonResponseTool
2392
+ isJsonResponseFromTool
2377
2393
  }),
2378
2394
  usage: {
2379
2395
  inputTokens: response.usage.input_tokens,
@@ -2408,9 +2424,16 @@ var AnthropicMessagesLanguageModel = class {
2408
2424
  };
2409
2425
  }
2410
2426
  async doStream(options) {
2411
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs(options);
2427
+ const {
2428
+ args: body,
2429
+ warnings,
2430
+ betas,
2431
+ usesJsonResponseTool
2432
+ } = await this.getArgs({
2433
+ ...options,
2434
+ stream: true
2435
+ });
2412
2436
  const citationDocuments = this.extractCitationDocuments(options.prompt);
2413
- const body = { ...args, stream: true };
2414
2437
  const { responseHeaders, value: response } = await (0, import_provider_utils11.postJsonToApi)({
2415
2438
  url: this.buildRequestUrl(true),
2416
2439
  headers: await this.getHeaders({ betas, headers: options.headers }),
@@ -2434,6 +2457,7 @@ var AnthropicMessagesLanguageModel = class {
2434
2457
  let cacheCreationInputTokens = null;
2435
2458
  let stopSequence = null;
2436
2459
  let container = null;
2460
+ let isJsonResponseFromTool = false;
2437
2461
  let blockType = void 0;
2438
2462
  const generateId3 = this.generateId;
2439
2463
  return {
@@ -2462,6 +2486,9 @@ var AnthropicMessagesLanguageModel = class {
2462
2486
  blockType = contentBlockType;
2463
2487
  switch (contentBlockType) {
2464
2488
  case "text": {
2489
+ if (usesJsonResponseTool) {
2490
+ return;
2491
+ }
2465
2492
  contentBlocks[value.index] = { type: "text" };
2466
2493
  controller.enqueue({
2467
2494
  type: "text-start",
@@ -2491,20 +2518,28 @@ var AnthropicMessagesLanguageModel = class {
2491
2518
  return;
2492
2519
  }
2493
2520
  case "tool_use": {
2494
- contentBlocks[value.index] = usesJsonResponseTool ? { type: "text" } : {
2495
- type: "tool-call",
2496
- toolCallId: part.id,
2497
- toolName: part.name,
2498
- input: "",
2499
- firstDelta: true
2500
- };
2501
- controller.enqueue(
2502
- usesJsonResponseTool ? { type: "text-start", id: String(value.index) } : {
2521
+ const isJsonResponseTool = usesJsonResponseTool && part.name === "json";
2522
+ if (isJsonResponseTool) {
2523
+ isJsonResponseFromTool = true;
2524
+ contentBlocks[value.index] = { type: "text" };
2525
+ controller.enqueue({
2526
+ type: "text-start",
2527
+ id: String(value.index)
2528
+ });
2529
+ } else {
2530
+ contentBlocks[value.index] = {
2531
+ type: "tool-call",
2532
+ toolCallId: part.id,
2533
+ toolName: part.name,
2534
+ input: "",
2535
+ firstDelta: true
2536
+ };
2537
+ controller.enqueue({
2503
2538
  type: "tool-input-start",
2504
2539
  id: part.id,
2505
2540
  toolName: part.name
2506
- }
2507
- );
2541
+ });
2542
+ }
2508
2543
  return;
2509
2544
  }
2510
2545
  case "server_tool_use": {
@@ -2720,7 +2755,8 @@ var AnthropicMessagesLanguageModel = class {
2720
2755
  break;
2721
2756
  }
2722
2757
  case "tool-call":
2723
- if (!usesJsonResponseTool) {
2758
+ const isJsonResponseTool = usesJsonResponseTool && contentBlock.toolName === "json";
2759
+ if (!isJsonResponseTool) {
2724
2760
  controller.enqueue({
2725
2761
  type: "tool-input-end",
2726
2762
  id: contentBlock.toolCallId
@@ -2784,7 +2820,7 @@ var AnthropicMessagesLanguageModel = class {
2784
2820
  if (delta.length === 0) {
2785
2821
  return;
2786
2822
  }
2787
- if (usesJsonResponseTool) {
2823
+ if (isJsonResponseFromTool) {
2788
2824
  if ((contentBlock == null ? void 0 : contentBlock.type) !== "text") {
2789
2825
  return;
2790
2826
  }
@@ -2849,7 +2885,7 @@ var AnthropicMessagesLanguageModel = class {
2849
2885
  usage.totalTokens = ((_f = usage.inputTokens) != null ? _f : 0) + ((_g = value.usage.output_tokens) != null ? _g : 0);
2850
2886
  finishReason = mapAnthropicStopReason({
2851
2887
  finishReason: value.delta.stop_reason,
2852
- isJsonResponseFromTool: usesJsonResponseTool
2888
+ isJsonResponseFromTool
2853
2889
  });
2854
2890
  stopSequence = (_h = value.delta.stop_sequence) != null ? _h : null;
2855
2891
  container = value.delta.container != null ? {