@ai-sdk/anthropic 2.0.99 → 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(),
@@ -2243,6 +2243,15 @@ function isPlainObject(value) {
2243
2243
  }
2244
2244
 
2245
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
+ }
2246
2255
  function createCitationSource(citation, citationDocuments, generateId2) {
2247
2256
  var _a;
2248
2257
  if (citation.type !== "page_location" && citation.type !== "char_location") {
@@ -2348,12 +2357,6 @@ var AnthropicMessagesLanguageModel = class {
2348
2357
  setting: "responseFormat",
2349
2358
  details: "JSON response format requires a schema. The response format is ignored."
2350
2359
  });
2351
- } else if (tools != null) {
2352
- warnings.push({
2353
- type: "unsupported-setting",
2354
- setting: "tools",
2355
- details: "JSON response format does not support tools. The provided tools are ignored."
2356
- });
2357
2360
  }
2358
2361
  }
2359
2362
  const anthropicOptions = await (0, import_provider_utils10.parseProviderOptions)({
@@ -2403,9 +2406,10 @@ var AnthropicMessagesLanguageModel = class {
2403
2406
  const isAnthropicModel = isKnownModel || this.modelId.includes("claude-");
2404
2407
  const structureOutputMode = (_a = anthropicOptions == null ? void 0 : anthropicOptions.structuredOutputMode) != null ? _a : "jsonTool";
2405
2408
  const useStructuredOutput = structureOutputMode === "outputFormat" || structureOutputMode === "auto" && supportsStructuredOutput;
2409
+ const jsonResponseToolName = getJsonResponseToolName(tools);
2406
2410
  const jsonResponseTool = (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && !useStructuredOutput ? {
2407
2411
  type: "function",
2408
- name: "json",
2412
+ name: jsonResponseToolName,
2409
2413
  description: "Respond with a JSON object.",
2410
2414
  inputSchema: responseFormat.schema
2411
2415
  } : void 0;
@@ -2648,8 +2652,8 @@ var AnthropicMessagesLanguageModel = class {
2648
2652
  betas: toolsBetas
2649
2653
  } = await prepareTools(
2650
2654
  jsonResponseTool != null ? {
2651
- tools: [jsonResponseTool],
2652
- 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 },
2653
2657
  disableParallelToolUse: true,
2654
2658
  cacheControlValidator
2655
2659
  } : {
@@ -2673,7 +2677,7 @@ var AnthropicMessagesLanguageModel = class {
2673
2677
  ...userSuppliedBetas,
2674
2678
  ...(_i = anthropicOptions == null ? void 0 : anthropicOptions.anthropicBeta) != null ? _i : []
2675
2679
  ]),
2676
- usesJsonResponseTool: jsonResponseTool != null
2680
+ jsonResponseToolName: jsonResponseTool != null ? jsonResponseToolName : void 0
2677
2681
  };
2678
2682
  }
2679
2683
  async getHeaders({
@@ -2731,7 +2735,7 @@ var AnthropicMessagesLanguageModel = class {
2731
2735
  }
2732
2736
  async doGenerate(options) {
2733
2737
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2734
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
2738
+ const { args, warnings, betas, jsonResponseToolName } = await this.getArgs({
2735
2739
  ...options,
2736
2740
  userSuppliedBetas: await this.getBetasFromHeaders(options.headers)
2737
2741
  });
@@ -2752,10 +2756,11 @@ var AnthropicMessagesLanguageModel = class {
2752
2756
  fetch: this.config.fetch
2753
2757
  });
2754
2758
  const content = [];
2759
+ let isJsonResponseFromTool = false;
2755
2760
  for (const part of response.content) {
2756
2761
  switch (part.type) {
2757
2762
  case "text": {
2758
- if (!usesJsonResponseTool) {
2763
+ if (jsonResponseToolName == null) {
2759
2764
  const webSearchCitations = (_a = part.citations) == null ? void 0 : _a.filter(
2760
2765
  (citation) => citation.type === "web_search_result_location"
2761
2766
  );
@@ -2822,18 +2827,21 @@ var AnthropicMessagesLanguageModel = class {
2822
2827
  break;
2823
2828
  }
2824
2829
  case "tool_use": {
2825
- content.push(
2826
- // when a json response tool is used, the tool call becomes the text:
2827
- usesJsonResponseTool ? {
2830
+ const isJsonResponseTool = part.name === jsonResponseToolName;
2831
+ if (isJsonResponseTool) {
2832
+ isJsonResponseFromTool = true;
2833
+ content.push({
2828
2834
  type: "text",
2829
2835
  text: JSON.stringify(part.input)
2830
- } : {
2836
+ });
2837
+ } else {
2838
+ content.push({
2831
2839
  type: "tool-call",
2832
2840
  toolCallId: part.id,
2833
2841
  toolName: part.name,
2834
2842
  input: JSON.stringify(part.input)
2835
- }
2836
- );
2843
+ });
2844
+ }
2837
2845
  break;
2838
2846
  }
2839
2847
  case "server_tool_use": {
@@ -3015,7 +3023,7 @@ var AnthropicMessagesLanguageModel = class {
3015
3023
  content,
3016
3024
  finishReason: mapAnthropicStopReason({
3017
3025
  finishReason: response.stop_reason,
3018
- isJsonResponseFromTool: usesJsonResponseTool
3026
+ isJsonResponseFromTool
3019
3027
  }),
3020
3028
  usage: {
3021
3029
  inputTokens,
@@ -3083,7 +3091,7 @@ var AnthropicMessagesLanguageModel = class {
3083
3091
  }
3084
3092
  async doStream(options) {
3085
3093
  var _a, _b;
3086
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
3094
+ const { args, warnings, betas, jsonResponseToolName } = await this.getArgs({
3087
3095
  ...options,
3088
3096
  userSuppliedBetas: await this.getBetasFromHeaders(options.headers)
3089
3097
  });
@@ -3115,6 +3123,7 @@ var AnthropicMessagesLanguageModel = class {
3115
3123
  let container = null;
3116
3124
  let iterations = null;
3117
3125
  let contextManagement = null;
3126
+ let isJsonResponseFromTool = false;
3118
3127
  let isMessageOpen = false;
3119
3128
  let activeMessageId;
3120
3129
  let hasInvalidMessageSequence = false;
@@ -3198,20 +3207,31 @@ var AnthropicMessagesLanguageModel = class {
3198
3207
  return;
3199
3208
  }
3200
3209
  case "tool_use": {
3201
- contentBlocks[value.index] = usesJsonResponseTool ? { type: "text", citations: [] } : {
3202
- type: "tool-call",
3203
- toolCallId: value.content_block.id,
3204
- toolName: value.content_block.name,
3205
- input: "",
3206
- firstDelta: true
3207
- };
3208
- controller.enqueue(
3209
- 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({
3210
3230
  type: "tool-input-start",
3211
3231
  id: value.content_block.id,
3212
3232
  toolName: value.content_block.name
3213
- }
3214
- );
3233
+ });
3234
+ }
3215
3235
  return;
3216
3236
  }
3217
3237
  case "server_tool_use": {
@@ -3407,22 +3427,21 @@ var AnthropicMessagesLanguageModel = class {
3407
3427
  });
3408
3428
  break;
3409
3429
  }
3410
- case "tool-call":
3411
- if (!usesJsonResponseTool) {
3412
- controller.enqueue({
3413
- type: "tool-input-end",
3414
- id: contentBlock.toolCallId
3415
- });
3416
- const toolName = contentBlock.toolName === "text_editor_code_execution" || contentBlock.toolName === "bash_code_execution" ? "code_execution" : contentBlock.toolName;
3417
- controller.enqueue({
3418
- type: "tool-call",
3419
- toolCallId: contentBlock.toolCallId,
3420
- toolName,
3421
- input: contentBlock.input === "" ? "{}" : contentBlock.input,
3422
- providerExecuted: contentBlock.providerExecuted
3423
- });
3424
- }
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
+ });
3425
3443
  break;
3444
+ }
3426
3445
  }
3427
3446
  delete contentBlocks[value.index];
3428
3447
  }
@@ -3433,7 +3452,7 @@ var AnthropicMessagesLanguageModel = class {
3433
3452
  const deltaType = value.delta.type;
3434
3453
  switch (deltaType) {
3435
3454
  case "text_delta": {
3436
- if (usesJsonResponseTool) {
3455
+ if (jsonResponseToolName != null) {
3437
3456
  return;
3438
3457
  }
3439
3458
  controller.enqueue({
@@ -3482,10 +3501,7 @@ var AnthropicMessagesLanguageModel = class {
3482
3501
  if (delta.length === 0) {
3483
3502
  return;
3484
3503
  }
3485
- if (usesJsonResponseTool) {
3486
- if ((contentBlock == null ? void 0 : contentBlock.type) !== "text") {
3487
- return;
3488
- }
3504
+ if ((contentBlock == null ? void 0 : contentBlock.type) === "text") {
3489
3505
  controller.enqueue({
3490
3506
  type: "text-delta",
3491
3507
  id: String(value.index),
@@ -3594,7 +3610,7 @@ var AnthropicMessagesLanguageModel = class {
3594
3610
  usage.totalTokens = ((_g = usage.inputTokens) != null ? _g : 0) + ((_h = usage.outputTokens) != null ? _h : 0);
3595
3611
  finishReason = mapAnthropicStopReason({
3596
3612
  finishReason: value.delta.stop_reason,
3597
- isJsonResponseFromTool: usesJsonResponseTool
3613
+ isJsonResponseFromTool
3598
3614
  });
3599
3615
  stopDetails = mapAnthropicStopDetails(value.delta.stop_details);
3600
3616
  stopSequence = (_i = value.delta.stop_sequence) != null ? _i : null;