@ai-sdk/anthropic 2.0.98 → 2.0.100

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.mjs CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  } from "@ai-sdk/provider-utils";
12
12
 
13
13
  // src/version.ts
14
- var VERSION = true ? "2.0.98" : "0.0.0-test";
14
+ var VERSION = true ? "2.0.100" : "0.0.0-test";
15
15
 
16
16
  // src/anthropic-messages-language-model.ts
17
17
  import {
@@ -702,7 +702,7 @@ var anthropicProviderOptions = z3.object({
702
702
  * Determines how structured outputs are generated.
703
703
  *
704
704
  * - `outputFormat`: Use the `output_format` parameter to specify the structured output format.
705
- * - `jsonTool`: Use a special 'json' tool to specify the structured output format (default).
705
+ * - `jsonTool`: Use a special JSON response tool to specify the structured output format (default).
706
706
  * - `auto`: Use 'outputFormat' when supported, otherwise use 'jsonTool'.
707
707
  */
708
708
  structuredOutputMode: z3.enum(["outputFormat", "jsonTool", "auto"]).optional(),
@@ -2020,7 +2020,10 @@ async function convertToAnthropicMessagesPrompt({
2020
2020
  }
2021
2021
  }
2022
2022
  }
2023
- messages.push({ role: "assistant", content: anthropicContent });
2023
+ messages.push({
2024
+ role: "assistant",
2025
+ content: moveToolUseBlocksToEnd(anthropicContent)
2026
+ });
2024
2027
  break;
2025
2028
  }
2026
2029
  default: {
@@ -2080,6 +2083,27 @@ function groupIntoBlocks(prompt) {
2080
2083
  }
2081
2084
  return blocks;
2082
2085
  }
2086
+ function moveToolUseBlocksToEnd(content) {
2087
+ const result = [];
2088
+ let segment = [];
2089
+ function flushSegment() {
2090
+ result.push(
2091
+ ...segment.filter((part) => part.type !== "tool_use"),
2092
+ ...segment.filter((part) => part.type === "tool_use")
2093
+ );
2094
+ segment = [];
2095
+ }
2096
+ for (const part of content) {
2097
+ if (part.type === "thinking" || part.type === "redacted_thinking") {
2098
+ flushSegment();
2099
+ result.push(part);
2100
+ } else {
2101
+ segment.push(part);
2102
+ }
2103
+ }
2104
+ flushSegment();
2105
+ return result;
2106
+ }
2083
2107
 
2084
2108
  // src/map-anthropic-stop-reason.ts
2085
2109
  function mapAnthropicStopReason({
@@ -2251,6 +2275,15 @@ function isPlainObject(value) {
2251
2275
  }
2252
2276
 
2253
2277
  // src/anthropic-messages-language-model.ts
2278
+ function getJsonResponseToolName(tools) {
2279
+ const toolNames = new Set(tools == null ? void 0 : tools.map((tool) => tool.name));
2280
+ let name = "json";
2281
+ let suffix = 1;
2282
+ while (toolNames.has(name)) {
2283
+ name = `json_${suffix++}`;
2284
+ }
2285
+ return name;
2286
+ }
2254
2287
  function createCitationSource(citation, citationDocuments, generateId3) {
2255
2288
  var _a;
2256
2289
  if (citation.type !== "page_location" && citation.type !== "char_location") {
@@ -2356,12 +2389,6 @@ var AnthropicMessagesLanguageModel = class {
2356
2389
  setting: "responseFormat",
2357
2390
  details: "JSON response format requires a schema. The response format is ignored."
2358
2391
  });
2359
- } else if (tools != null) {
2360
- warnings.push({
2361
- type: "unsupported-setting",
2362
- setting: "tools",
2363
- details: "JSON response format does not support tools. The provided tools are ignored."
2364
- });
2365
2392
  }
2366
2393
  }
2367
2394
  const anthropicOptions = await parseProviderOptions2({
@@ -2411,9 +2438,10 @@ var AnthropicMessagesLanguageModel = class {
2411
2438
  const isAnthropicModel = isKnownModel || this.modelId.includes("claude-");
2412
2439
  const structureOutputMode = (_a = anthropicOptions == null ? void 0 : anthropicOptions.structuredOutputMode) != null ? _a : "jsonTool";
2413
2440
  const useStructuredOutput = structureOutputMode === "outputFormat" || structureOutputMode === "auto" && supportsStructuredOutput;
2441
+ const jsonResponseToolName = getJsonResponseToolName(tools);
2414
2442
  const jsonResponseTool = (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && !useStructuredOutput ? {
2415
2443
  type: "function",
2416
- name: "json",
2444
+ name: jsonResponseToolName,
2417
2445
  description: "Respond with a JSON object.",
2418
2446
  inputSchema: responseFormat.schema
2419
2447
  } : void 0;
@@ -2656,8 +2684,8 @@ var AnthropicMessagesLanguageModel = class {
2656
2684
  betas: toolsBetas
2657
2685
  } = await prepareTools(
2658
2686
  jsonResponseTool != null ? {
2659
- tools: [jsonResponseTool],
2660
- toolChoice: { type: "tool", toolName: jsonResponseTool.name },
2687
+ tools: [...tools != null ? tools : [], jsonResponseTool],
2688
+ toolChoice: tools != null && tools.length > 0 ? { type: "required" } : { type: "tool", toolName: jsonResponseTool.name },
2661
2689
  disableParallelToolUse: true,
2662
2690
  cacheControlValidator
2663
2691
  } : {
@@ -2681,7 +2709,7 @@ var AnthropicMessagesLanguageModel = class {
2681
2709
  ...userSuppliedBetas,
2682
2710
  ...(_i = anthropicOptions == null ? void 0 : anthropicOptions.anthropicBeta) != null ? _i : []
2683
2711
  ]),
2684
- usesJsonResponseTool: jsonResponseTool != null
2712
+ jsonResponseToolName: jsonResponseTool != null ? jsonResponseToolName : void 0
2685
2713
  };
2686
2714
  }
2687
2715
  async getHeaders({
@@ -2739,7 +2767,7 @@ var AnthropicMessagesLanguageModel = class {
2739
2767
  }
2740
2768
  async doGenerate(options) {
2741
2769
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2742
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
2770
+ const { args, warnings, betas, jsonResponseToolName } = await this.getArgs({
2743
2771
  ...options,
2744
2772
  userSuppliedBetas: await this.getBetasFromHeaders(options.headers)
2745
2773
  });
@@ -2760,10 +2788,11 @@ var AnthropicMessagesLanguageModel = class {
2760
2788
  fetch: this.config.fetch
2761
2789
  });
2762
2790
  const content = [];
2791
+ let isJsonResponseFromTool = false;
2763
2792
  for (const part of response.content) {
2764
2793
  switch (part.type) {
2765
2794
  case "text": {
2766
- if (!usesJsonResponseTool) {
2795
+ if (jsonResponseToolName == null) {
2767
2796
  const webSearchCitations = (_a = part.citations) == null ? void 0 : _a.filter(
2768
2797
  (citation) => citation.type === "web_search_result_location"
2769
2798
  );
@@ -2830,18 +2859,21 @@ var AnthropicMessagesLanguageModel = class {
2830
2859
  break;
2831
2860
  }
2832
2861
  case "tool_use": {
2833
- content.push(
2834
- // when a json response tool is used, the tool call becomes the text:
2835
- usesJsonResponseTool ? {
2862
+ const isJsonResponseTool = part.name === jsonResponseToolName;
2863
+ if (isJsonResponseTool) {
2864
+ isJsonResponseFromTool = true;
2865
+ content.push({
2836
2866
  type: "text",
2837
2867
  text: JSON.stringify(part.input)
2838
- } : {
2868
+ });
2869
+ } else {
2870
+ content.push({
2839
2871
  type: "tool-call",
2840
2872
  toolCallId: part.id,
2841
2873
  toolName: part.name,
2842
2874
  input: JSON.stringify(part.input)
2843
- }
2844
- );
2875
+ });
2876
+ }
2845
2877
  break;
2846
2878
  }
2847
2879
  case "server_tool_use": {
@@ -3023,7 +3055,7 @@ var AnthropicMessagesLanguageModel = class {
3023
3055
  content,
3024
3056
  finishReason: mapAnthropicStopReason({
3025
3057
  finishReason: response.stop_reason,
3026
- isJsonResponseFromTool: usesJsonResponseTool
3058
+ isJsonResponseFromTool
3027
3059
  }),
3028
3060
  usage: {
3029
3061
  inputTokens,
@@ -3091,7 +3123,7 @@ var AnthropicMessagesLanguageModel = class {
3091
3123
  }
3092
3124
  async doStream(options) {
3093
3125
  var _a, _b;
3094
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
3126
+ const { args, warnings, betas, jsonResponseToolName } = await this.getArgs({
3095
3127
  ...options,
3096
3128
  userSuppliedBetas: await this.getBetasFromHeaders(options.headers)
3097
3129
  });
@@ -3123,6 +3155,7 @@ var AnthropicMessagesLanguageModel = class {
3123
3155
  let container = null;
3124
3156
  let iterations = null;
3125
3157
  let contextManagement = null;
3158
+ let isJsonResponseFromTool = false;
3126
3159
  let isMessageOpen = false;
3127
3160
  let activeMessageId;
3128
3161
  let hasInvalidMessageSequence = false;
@@ -3206,20 +3239,31 @@ var AnthropicMessagesLanguageModel = class {
3206
3239
  return;
3207
3240
  }
3208
3241
  case "tool_use": {
3209
- contentBlocks[value.index] = usesJsonResponseTool ? { type: "text", citations: [] } : {
3210
- type: "tool-call",
3211
- toolCallId: value.content_block.id,
3212
- toolName: value.content_block.name,
3213
- input: "",
3214
- firstDelta: true
3215
- };
3216
- controller.enqueue(
3217
- usesJsonResponseTool ? { type: "text-start", id: String(value.index) } : {
3242
+ const isJsonResponseTool = value.content_block.name === jsonResponseToolName;
3243
+ if (isJsonResponseTool) {
3244
+ isJsonResponseFromTool = true;
3245
+ contentBlocks[value.index] = {
3246
+ type: "text",
3247
+ citations: []
3248
+ };
3249
+ controller.enqueue({
3250
+ type: "text-start",
3251
+ id: String(value.index)
3252
+ });
3253
+ } else {
3254
+ contentBlocks[value.index] = {
3255
+ type: "tool-call",
3256
+ toolCallId: value.content_block.id,
3257
+ toolName: value.content_block.name,
3258
+ input: "",
3259
+ firstDelta: true
3260
+ };
3261
+ controller.enqueue({
3218
3262
  type: "tool-input-start",
3219
3263
  id: value.content_block.id,
3220
3264
  toolName: value.content_block.name
3221
- }
3222
- );
3265
+ });
3266
+ }
3223
3267
  return;
3224
3268
  }
3225
3269
  case "server_tool_use": {
@@ -3415,22 +3459,21 @@ var AnthropicMessagesLanguageModel = class {
3415
3459
  });
3416
3460
  break;
3417
3461
  }
3418
- case "tool-call":
3419
- if (!usesJsonResponseTool) {
3420
- controller.enqueue({
3421
- type: "tool-input-end",
3422
- id: contentBlock.toolCallId
3423
- });
3424
- const toolName = contentBlock.toolName === "text_editor_code_execution" || contentBlock.toolName === "bash_code_execution" ? "code_execution" : contentBlock.toolName;
3425
- controller.enqueue({
3426
- type: "tool-call",
3427
- toolCallId: contentBlock.toolCallId,
3428
- toolName,
3429
- input: contentBlock.input === "" ? "{}" : contentBlock.input,
3430
- providerExecuted: contentBlock.providerExecuted
3431
- });
3432
- }
3462
+ case "tool-call": {
3463
+ controller.enqueue({
3464
+ type: "tool-input-end",
3465
+ id: contentBlock.toolCallId
3466
+ });
3467
+ const toolName = contentBlock.toolName === "text_editor_code_execution" || contentBlock.toolName === "bash_code_execution" ? "code_execution" : contentBlock.toolName;
3468
+ controller.enqueue({
3469
+ type: "tool-call",
3470
+ toolCallId: contentBlock.toolCallId,
3471
+ toolName,
3472
+ input: contentBlock.input === "" ? "{}" : contentBlock.input,
3473
+ providerExecuted: contentBlock.providerExecuted
3474
+ });
3433
3475
  break;
3476
+ }
3434
3477
  }
3435
3478
  delete contentBlocks[value.index];
3436
3479
  }
@@ -3441,7 +3484,7 @@ var AnthropicMessagesLanguageModel = class {
3441
3484
  const deltaType = value.delta.type;
3442
3485
  switch (deltaType) {
3443
3486
  case "text_delta": {
3444
- if (usesJsonResponseTool) {
3487
+ if (jsonResponseToolName != null) {
3445
3488
  return;
3446
3489
  }
3447
3490
  controller.enqueue({
@@ -3490,10 +3533,7 @@ var AnthropicMessagesLanguageModel = class {
3490
3533
  if (delta.length === 0) {
3491
3534
  return;
3492
3535
  }
3493
- if (usesJsonResponseTool) {
3494
- if ((contentBlock == null ? void 0 : contentBlock.type) !== "text") {
3495
- return;
3496
- }
3536
+ if ((contentBlock == null ? void 0 : contentBlock.type) === "text") {
3497
3537
  controller.enqueue({
3498
3538
  type: "text-delta",
3499
3539
  id: String(value.index),
@@ -3602,7 +3642,7 @@ var AnthropicMessagesLanguageModel = class {
3602
3642
  usage.totalTokens = ((_g = usage.inputTokens) != null ? _g : 0) + ((_h = usage.outputTokens) != null ? _h : 0);
3603
3643
  finishReason = mapAnthropicStopReason({
3604
3644
  finishReason: value.delta.stop_reason,
3605
- isJsonResponseFromTool: usesJsonResponseTool
3645
+ isJsonResponseFromTool
3606
3646
  });
3607
3647
  stopDetails = mapAnthropicStopDetails(value.delta.stop_details);
3608
3648
  stopSequence = (_i = value.delta.stop_sequence) != null ? _i : null;