@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.
@@ -698,7 +698,7 @@ var anthropicProviderOptions = import_v43.z.object({
698
698
  * Determines how structured outputs are generated.
699
699
  *
700
700
  * - `outputFormat`: Use the `output_format` parameter to specify the structured output format.
701
- * - `jsonTool`: Use a special 'json' tool to specify the structured output format (default).
701
+ * - `jsonTool`: Use a special JSON response tool to specify the structured output format (default).
702
702
  * - `auto`: Use 'outputFormat' when supported, otherwise use 'jsonTool'.
703
703
  */
704
704
  structuredOutputMode: import_v43.z.enum(["outputFormat", "jsonTool", "auto"]).optional(),
@@ -1988,7 +1988,10 @@ async function convertToAnthropicMessagesPrompt({
1988
1988
  }
1989
1989
  }
1990
1990
  }
1991
- messages.push({ role: "assistant", content: anthropicContent });
1991
+ messages.push({
1992
+ role: "assistant",
1993
+ content: moveToolUseBlocksToEnd(anthropicContent)
1994
+ });
1992
1995
  break;
1993
1996
  }
1994
1997
  default: {
@@ -2048,6 +2051,27 @@ function groupIntoBlocks(prompt) {
2048
2051
  }
2049
2052
  return blocks;
2050
2053
  }
2054
+ function moveToolUseBlocksToEnd(content) {
2055
+ const result = [];
2056
+ let segment = [];
2057
+ function flushSegment() {
2058
+ result.push(
2059
+ ...segment.filter((part) => part.type !== "tool_use"),
2060
+ ...segment.filter((part) => part.type === "tool_use")
2061
+ );
2062
+ segment = [];
2063
+ }
2064
+ for (const part of content) {
2065
+ if (part.type === "thinking" || part.type === "redacted_thinking") {
2066
+ flushSegment();
2067
+ result.push(part);
2068
+ } else {
2069
+ segment.push(part);
2070
+ }
2071
+ }
2072
+ flushSegment();
2073
+ return result;
2074
+ }
2051
2075
 
2052
2076
  // src/map-anthropic-stop-reason.ts
2053
2077
  function mapAnthropicStopReason({
@@ -2219,6 +2243,15 @@ function isPlainObject(value) {
2219
2243
  }
2220
2244
 
2221
2245
  // src/anthropic-messages-language-model.ts
2246
+ function getJsonResponseToolName(tools) {
2247
+ const toolNames = new Set(tools == null ? void 0 : tools.map((tool) => tool.name));
2248
+ let name = "json";
2249
+ let suffix = 1;
2250
+ while (toolNames.has(name)) {
2251
+ name = `json_${suffix++}`;
2252
+ }
2253
+ return name;
2254
+ }
2222
2255
  function createCitationSource(citation, citationDocuments, generateId2) {
2223
2256
  var _a;
2224
2257
  if (citation.type !== "page_location" && citation.type !== "char_location") {
@@ -2324,12 +2357,6 @@ var AnthropicMessagesLanguageModel = class {
2324
2357
  setting: "responseFormat",
2325
2358
  details: "JSON response format requires a schema. The response format is ignored."
2326
2359
  });
2327
- } else if (tools != null) {
2328
- warnings.push({
2329
- type: "unsupported-setting",
2330
- setting: "tools",
2331
- details: "JSON response format does not support tools. The provided tools are ignored."
2332
- });
2333
2360
  }
2334
2361
  }
2335
2362
  const anthropicOptions = await (0, import_provider_utils10.parseProviderOptions)({
@@ -2379,9 +2406,10 @@ var AnthropicMessagesLanguageModel = class {
2379
2406
  const isAnthropicModel = isKnownModel || this.modelId.includes("claude-");
2380
2407
  const structureOutputMode = (_a = anthropicOptions == null ? void 0 : anthropicOptions.structuredOutputMode) != null ? _a : "jsonTool";
2381
2408
  const useStructuredOutput = structureOutputMode === "outputFormat" || structureOutputMode === "auto" && supportsStructuredOutput;
2409
+ const jsonResponseToolName = getJsonResponseToolName(tools);
2382
2410
  const jsonResponseTool = (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && !useStructuredOutput ? {
2383
2411
  type: "function",
2384
- name: "json",
2412
+ name: jsonResponseToolName,
2385
2413
  description: "Respond with a JSON object.",
2386
2414
  inputSchema: responseFormat.schema
2387
2415
  } : void 0;
@@ -2624,8 +2652,8 @@ var AnthropicMessagesLanguageModel = class {
2624
2652
  betas: toolsBetas
2625
2653
  } = await prepareTools(
2626
2654
  jsonResponseTool != null ? {
2627
- tools: [jsonResponseTool],
2628
- toolChoice: { type: "tool", toolName: jsonResponseTool.name },
2655
+ tools: [...tools != null ? tools : [], jsonResponseTool],
2656
+ toolChoice: tools != null && tools.length > 0 ? { type: "required" } : { type: "tool", toolName: jsonResponseTool.name },
2629
2657
  disableParallelToolUse: true,
2630
2658
  cacheControlValidator
2631
2659
  } : {
@@ -2649,7 +2677,7 @@ var AnthropicMessagesLanguageModel = class {
2649
2677
  ...userSuppliedBetas,
2650
2678
  ...(_i = anthropicOptions == null ? void 0 : anthropicOptions.anthropicBeta) != null ? _i : []
2651
2679
  ]),
2652
- usesJsonResponseTool: jsonResponseTool != null
2680
+ jsonResponseToolName: jsonResponseTool != null ? jsonResponseToolName : void 0
2653
2681
  };
2654
2682
  }
2655
2683
  async getHeaders({
@@ -2707,7 +2735,7 @@ var AnthropicMessagesLanguageModel = class {
2707
2735
  }
2708
2736
  async doGenerate(options) {
2709
2737
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2710
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
2738
+ const { args, warnings, betas, jsonResponseToolName } = await this.getArgs({
2711
2739
  ...options,
2712
2740
  userSuppliedBetas: await this.getBetasFromHeaders(options.headers)
2713
2741
  });
@@ -2728,10 +2756,11 @@ var AnthropicMessagesLanguageModel = class {
2728
2756
  fetch: this.config.fetch
2729
2757
  });
2730
2758
  const content = [];
2759
+ let isJsonResponseFromTool = false;
2731
2760
  for (const part of response.content) {
2732
2761
  switch (part.type) {
2733
2762
  case "text": {
2734
- if (!usesJsonResponseTool) {
2763
+ if (jsonResponseToolName == null) {
2735
2764
  const webSearchCitations = (_a = part.citations) == null ? void 0 : _a.filter(
2736
2765
  (citation) => citation.type === "web_search_result_location"
2737
2766
  );
@@ -2798,18 +2827,21 @@ var AnthropicMessagesLanguageModel = class {
2798
2827
  break;
2799
2828
  }
2800
2829
  case "tool_use": {
2801
- content.push(
2802
- // when a json response tool is used, the tool call becomes the text:
2803
- usesJsonResponseTool ? {
2830
+ const isJsonResponseTool = part.name === jsonResponseToolName;
2831
+ if (isJsonResponseTool) {
2832
+ isJsonResponseFromTool = true;
2833
+ content.push({
2804
2834
  type: "text",
2805
2835
  text: JSON.stringify(part.input)
2806
- } : {
2836
+ });
2837
+ } else {
2838
+ content.push({
2807
2839
  type: "tool-call",
2808
2840
  toolCallId: part.id,
2809
2841
  toolName: part.name,
2810
2842
  input: JSON.stringify(part.input)
2811
- }
2812
- );
2843
+ });
2844
+ }
2813
2845
  break;
2814
2846
  }
2815
2847
  case "server_tool_use": {
@@ -2991,7 +3023,7 @@ var AnthropicMessagesLanguageModel = class {
2991
3023
  content,
2992
3024
  finishReason: mapAnthropicStopReason({
2993
3025
  finishReason: response.stop_reason,
2994
- isJsonResponseFromTool: usesJsonResponseTool
3026
+ isJsonResponseFromTool
2995
3027
  }),
2996
3028
  usage: {
2997
3029
  inputTokens,
@@ -3059,7 +3091,7 @@ var AnthropicMessagesLanguageModel = class {
3059
3091
  }
3060
3092
  async doStream(options) {
3061
3093
  var _a, _b;
3062
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
3094
+ const { args, warnings, betas, jsonResponseToolName } = await this.getArgs({
3063
3095
  ...options,
3064
3096
  userSuppliedBetas: await this.getBetasFromHeaders(options.headers)
3065
3097
  });
@@ -3091,6 +3123,7 @@ var AnthropicMessagesLanguageModel = class {
3091
3123
  let container = null;
3092
3124
  let iterations = null;
3093
3125
  let contextManagement = null;
3126
+ let isJsonResponseFromTool = false;
3094
3127
  let isMessageOpen = false;
3095
3128
  let activeMessageId;
3096
3129
  let hasInvalidMessageSequence = false;
@@ -3174,20 +3207,31 @@ var AnthropicMessagesLanguageModel = class {
3174
3207
  return;
3175
3208
  }
3176
3209
  case "tool_use": {
3177
- contentBlocks[value.index] = usesJsonResponseTool ? { type: "text", citations: [] } : {
3178
- type: "tool-call",
3179
- toolCallId: value.content_block.id,
3180
- toolName: value.content_block.name,
3181
- input: "",
3182
- firstDelta: true
3183
- };
3184
- controller.enqueue(
3185
- usesJsonResponseTool ? { type: "text-start", id: String(value.index) } : {
3210
+ const isJsonResponseTool = value.content_block.name === jsonResponseToolName;
3211
+ if (isJsonResponseTool) {
3212
+ isJsonResponseFromTool = true;
3213
+ contentBlocks[value.index] = {
3214
+ type: "text",
3215
+ citations: []
3216
+ };
3217
+ controller.enqueue({
3218
+ type: "text-start",
3219
+ id: String(value.index)
3220
+ });
3221
+ } else {
3222
+ contentBlocks[value.index] = {
3223
+ type: "tool-call",
3224
+ toolCallId: value.content_block.id,
3225
+ toolName: value.content_block.name,
3226
+ input: "",
3227
+ firstDelta: true
3228
+ };
3229
+ controller.enqueue({
3186
3230
  type: "tool-input-start",
3187
3231
  id: value.content_block.id,
3188
3232
  toolName: value.content_block.name
3189
- }
3190
- );
3233
+ });
3234
+ }
3191
3235
  return;
3192
3236
  }
3193
3237
  case "server_tool_use": {
@@ -3383,22 +3427,21 @@ var AnthropicMessagesLanguageModel = class {
3383
3427
  });
3384
3428
  break;
3385
3429
  }
3386
- case "tool-call":
3387
- if (!usesJsonResponseTool) {
3388
- controller.enqueue({
3389
- type: "tool-input-end",
3390
- id: contentBlock.toolCallId
3391
- });
3392
- const toolName = contentBlock.toolName === "text_editor_code_execution" || contentBlock.toolName === "bash_code_execution" ? "code_execution" : contentBlock.toolName;
3393
- controller.enqueue({
3394
- type: "tool-call",
3395
- toolCallId: contentBlock.toolCallId,
3396
- toolName,
3397
- input: contentBlock.input === "" ? "{}" : contentBlock.input,
3398
- providerExecuted: contentBlock.providerExecuted
3399
- });
3400
- }
3430
+ case "tool-call": {
3431
+ controller.enqueue({
3432
+ type: "tool-input-end",
3433
+ id: contentBlock.toolCallId
3434
+ });
3435
+ const toolName = contentBlock.toolName === "text_editor_code_execution" || contentBlock.toolName === "bash_code_execution" ? "code_execution" : contentBlock.toolName;
3436
+ controller.enqueue({
3437
+ type: "tool-call",
3438
+ toolCallId: contentBlock.toolCallId,
3439
+ toolName,
3440
+ input: contentBlock.input === "" ? "{}" : contentBlock.input,
3441
+ providerExecuted: contentBlock.providerExecuted
3442
+ });
3401
3443
  break;
3444
+ }
3402
3445
  }
3403
3446
  delete contentBlocks[value.index];
3404
3447
  }
@@ -3409,7 +3452,7 @@ var AnthropicMessagesLanguageModel = class {
3409
3452
  const deltaType = value.delta.type;
3410
3453
  switch (deltaType) {
3411
3454
  case "text_delta": {
3412
- if (usesJsonResponseTool) {
3455
+ if (jsonResponseToolName != null) {
3413
3456
  return;
3414
3457
  }
3415
3458
  controller.enqueue({
@@ -3458,10 +3501,7 @@ var AnthropicMessagesLanguageModel = class {
3458
3501
  if (delta.length === 0) {
3459
3502
  return;
3460
3503
  }
3461
- if (usesJsonResponseTool) {
3462
- if ((contentBlock == null ? void 0 : contentBlock.type) !== "text") {
3463
- return;
3464
- }
3504
+ if ((contentBlock == null ? void 0 : contentBlock.type) === "text") {
3465
3505
  controller.enqueue({
3466
3506
  type: "text-delta",
3467
3507
  id: String(value.index),
@@ -3570,7 +3610,7 @@ var AnthropicMessagesLanguageModel = class {
3570
3610
  usage.totalTokens = ((_g = usage.inputTokens) != null ? _g : 0) + ((_h = usage.outputTokens) != null ? _h : 0);
3571
3611
  finishReason = mapAnthropicStopReason({
3572
3612
  finishReason: value.delta.stop_reason,
3573
- isJsonResponseFromTool: usesJsonResponseTool
3613
+ isJsonResponseFromTool
3574
3614
  });
3575
3615
  stopDetails = mapAnthropicStopDetails(value.delta.stop_details);
3576
3616
  stopSequence = (_i = value.delta.stop_sequence) != null ? _i : null;