@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.
@@ -687,7 +687,7 @@ var anthropicProviderOptions = z3.object({
687
687
  * Determines how structured outputs are generated.
688
688
  *
689
689
  * - `outputFormat`: Use the `output_format` parameter to specify the structured output format.
690
- * - `jsonTool`: Use a special 'json' tool to specify the structured output format (default).
690
+ * - `jsonTool`: Use a special JSON response tool to specify the structured output format (default).
691
691
  * - `auto`: Use 'outputFormat' when supported, otherwise use 'jsonTool'.
692
692
  */
693
693
  structuredOutputMode: z3.enum(["outputFormat", "jsonTool", "auto"]).optional(),
@@ -2260,6 +2260,15 @@ function isPlainObject(value) {
2260
2260
  }
2261
2261
 
2262
2262
  // src/anthropic-messages-language-model.ts
2263
+ function getJsonResponseToolName(tools) {
2264
+ const toolNames = new Set(tools == null ? void 0 : tools.map((tool) => tool.name));
2265
+ let name = "json";
2266
+ let suffix = 1;
2267
+ while (toolNames.has(name)) {
2268
+ name = `json_${suffix++}`;
2269
+ }
2270
+ return name;
2271
+ }
2263
2272
  function createCitationSource(citation, citationDocuments, generateId2) {
2264
2273
  var _a;
2265
2274
  if (citation.type !== "page_location" && citation.type !== "char_location") {
@@ -2365,12 +2374,6 @@ var AnthropicMessagesLanguageModel = class {
2365
2374
  setting: "responseFormat",
2366
2375
  details: "JSON response format requires a schema. The response format is ignored."
2367
2376
  });
2368
- } else if (tools != null) {
2369
- warnings.push({
2370
- type: "unsupported-setting",
2371
- setting: "tools",
2372
- details: "JSON response format does not support tools. The provided tools are ignored."
2373
- });
2374
2377
  }
2375
2378
  }
2376
2379
  const anthropicOptions = await parseProviderOptions2({
@@ -2420,9 +2423,10 @@ var AnthropicMessagesLanguageModel = class {
2420
2423
  const isAnthropicModel = isKnownModel || this.modelId.includes("claude-");
2421
2424
  const structureOutputMode = (_a = anthropicOptions == null ? void 0 : anthropicOptions.structuredOutputMode) != null ? _a : "jsonTool";
2422
2425
  const useStructuredOutput = structureOutputMode === "outputFormat" || structureOutputMode === "auto" && supportsStructuredOutput;
2426
+ const jsonResponseToolName = getJsonResponseToolName(tools);
2423
2427
  const jsonResponseTool = (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && !useStructuredOutput ? {
2424
2428
  type: "function",
2425
- name: "json",
2429
+ name: jsonResponseToolName,
2426
2430
  description: "Respond with a JSON object.",
2427
2431
  inputSchema: responseFormat.schema
2428
2432
  } : void 0;
@@ -2665,8 +2669,8 @@ var AnthropicMessagesLanguageModel = class {
2665
2669
  betas: toolsBetas
2666
2670
  } = await prepareTools(
2667
2671
  jsonResponseTool != null ? {
2668
- tools: [jsonResponseTool],
2669
- toolChoice: { type: "tool", toolName: jsonResponseTool.name },
2672
+ tools: [...tools != null ? tools : [], jsonResponseTool],
2673
+ toolChoice: tools != null && tools.length > 0 ? { type: "required" } : { type: "tool", toolName: jsonResponseTool.name },
2670
2674
  disableParallelToolUse: true,
2671
2675
  cacheControlValidator
2672
2676
  } : {
@@ -2690,7 +2694,7 @@ var AnthropicMessagesLanguageModel = class {
2690
2694
  ...userSuppliedBetas,
2691
2695
  ...(_i = anthropicOptions == null ? void 0 : anthropicOptions.anthropicBeta) != null ? _i : []
2692
2696
  ]),
2693
- usesJsonResponseTool: jsonResponseTool != null
2697
+ jsonResponseToolName: jsonResponseTool != null ? jsonResponseToolName : void 0
2694
2698
  };
2695
2699
  }
2696
2700
  async getHeaders({
@@ -2748,7 +2752,7 @@ var AnthropicMessagesLanguageModel = class {
2748
2752
  }
2749
2753
  async doGenerate(options) {
2750
2754
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2751
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
2755
+ const { args, warnings, betas, jsonResponseToolName } = await this.getArgs({
2752
2756
  ...options,
2753
2757
  userSuppliedBetas: await this.getBetasFromHeaders(options.headers)
2754
2758
  });
@@ -2769,10 +2773,11 @@ var AnthropicMessagesLanguageModel = class {
2769
2773
  fetch: this.config.fetch
2770
2774
  });
2771
2775
  const content = [];
2776
+ let isJsonResponseFromTool = false;
2772
2777
  for (const part of response.content) {
2773
2778
  switch (part.type) {
2774
2779
  case "text": {
2775
- if (!usesJsonResponseTool) {
2780
+ if (jsonResponseToolName == null) {
2776
2781
  const webSearchCitations = (_a = part.citations) == null ? void 0 : _a.filter(
2777
2782
  (citation) => citation.type === "web_search_result_location"
2778
2783
  );
@@ -2839,18 +2844,21 @@ var AnthropicMessagesLanguageModel = class {
2839
2844
  break;
2840
2845
  }
2841
2846
  case "tool_use": {
2842
- content.push(
2843
- // when a json response tool is used, the tool call becomes the text:
2844
- usesJsonResponseTool ? {
2847
+ const isJsonResponseTool = part.name === jsonResponseToolName;
2848
+ if (isJsonResponseTool) {
2849
+ isJsonResponseFromTool = true;
2850
+ content.push({
2845
2851
  type: "text",
2846
2852
  text: JSON.stringify(part.input)
2847
- } : {
2853
+ });
2854
+ } else {
2855
+ content.push({
2848
2856
  type: "tool-call",
2849
2857
  toolCallId: part.id,
2850
2858
  toolName: part.name,
2851
2859
  input: JSON.stringify(part.input)
2852
- }
2853
- );
2860
+ });
2861
+ }
2854
2862
  break;
2855
2863
  }
2856
2864
  case "server_tool_use": {
@@ -3032,7 +3040,7 @@ var AnthropicMessagesLanguageModel = class {
3032
3040
  content,
3033
3041
  finishReason: mapAnthropicStopReason({
3034
3042
  finishReason: response.stop_reason,
3035
- isJsonResponseFromTool: usesJsonResponseTool
3043
+ isJsonResponseFromTool
3036
3044
  }),
3037
3045
  usage: {
3038
3046
  inputTokens,
@@ -3100,7 +3108,7 @@ var AnthropicMessagesLanguageModel = class {
3100
3108
  }
3101
3109
  async doStream(options) {
3102
3110
  var _a, _b;
3103
- const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
3111
+ const { args, warnings, betas, jsonResponseToolName } = await this.getArgs({
3104
3112
  ...options,
3105
3113
  userSuppliedBetas: await this.getBetasFromHeaders(options.headers)
3106
3114
  });
@@ -3132,6 +3140,7 @@ var AnthropicMessagesLanguageModel = class {
3132
3140
  let container = null;
3133
3141
  let iterations = null;
3134
3142
  let contextManagement = null;
3143
+ let isJsonResponseFromTool = false;
3135
3144
  let isMessageOpen = false;
3136
3145
  let activeMessageId;
3137
3146
  let hasInvalidMessageSequence = false;
@@ -3215,20 +3224,31 @@ var AnthropicMessagesLanguageModel = class {
3215
3224
  return;
3216
3225
  }
3217
3226
  case "tool_use": {
3218
- contentBlocks[value.index] = usesJsonResponseTool ? { type: "text", citations: [] } : {
3219
- type: "tool-call",
3220
- toolCallId: value.content_block.id,
3221
- toolName: value.content_block.name,
3222
- input: "",
3223
- firstDelta: true
3224
- };
3225
- controller.enqueue(
3226
- usesJsonResponseTool ? { type: "text-start", id: String(value.index) } : {
3227
+ const isJsonResponseTool = value.content_block.name === jsonResponseToolName;
3228
+ if (isJsonResponseTool) {
3229
+ isJsonResponseFromTool = true;
3230
+ contentBlocks[value.index] = {
3231
+ type: "text",
3232
+ citations: []
3233
+ };
3234
+ controller.enqueue({
3235
+ type: "text-start",
3236
+ id: String(value.index)
3237
+ });
3238
+ } else {
3239
+ contentBlocks[value.index] = {
3240
+ type: "tool-call",
3241
+ toolCallId: value.content_block.id,
3242
+ toolName: value.content_block.name,
3243
+ input: "",
3244
+ firstDelta: true
3245
+ };
3246
+ controller.enqueue({
3227
3247
  type: "tool-input-start",
3228
3248
  id: value.content_block.id,
3229
3249
  toolName: value.content_block.name
3230
- }
3231
- );
3250
+ });
3251
+ }
3232
3252
  return;
3233
3253
  }
3234
3254
  case "server_tool_use": {
@@ -3424,22 +3444,21 @@ var AnthropicMessagesLanguageModel = class {
3424
3444
  });
3425
3445
  break;
3426
3446
  }
3427
- case "tool-call":
3428
- if (!usesJsonResponseTool) {
3429
- controller.enqueue({
3430
- type: "tool-input-end",
3431
- id: contentBlock.toolCallId
3432
- });
3433
- const toolName = contentBlock.toolName === "text_editor_code_execution" || contentBlock.toolName === "bash_code_execution" ? "code_execution" : contentBlock.toolName;
3434
- controller.enqueue({
3435
- type: "tool-call",
3436
- toolCallId: contentBlock.toolCallId,
3437
- toolName,
3438
- input: contentBlock.input === "" ? "{}" : contentBlock.input,
3439
- providerExecuted: contentBlock.providerExecuted
3440
- });
3441
- }
3447
+ case "tool-call": {
3448
+ controller.enqueue({
3449
+ type: "tool-input-end",
3450
+ id: contentBlock.toolCallId
3451
+ });
3452
+ const toolName = contentBlock.toolName === "text_editor_code_execution" || contentBlock.toolName === "bash_code_execution" ? "code_execution" : contentBlock.toolName;
3453
+ controller.enqueue({
3454
+ type: "tool-call",
3455
+ toolCallId: contentBlock.toolCallId,
3456
+ toolName,
3457
+ input: contentBlock.input === "" ? "{}" : contentBlock.input,
3458
+ providerExecuted: contentBlock.providerExecuted
3459
+ });
3442
3460
  break;
3461
+ }
3443
3462
  }
3444
3463
  delete contentBlocks[value.index];
3445
3464
  }
@@ -3450,7 +3469,7 @@ var AnthropicMessagesLanguageModel = class {
3450
3469
  const deltaType = value.delta.type;
3451
3470
  switch (deltaType) {
3452
3471
  case "text_delta": {
3453
- if (usesJsonResponseTool) {
3472
+ if (jsonResponseToolName != null) {
3454
3473
  return;
3455
3474
  }
3456
3475
  controller.enqueue({
@@ -3499,10 +3518,7 @@ var AnthropicMessagesLanguageModel = class {
3499
3518
  if (delta.length === 0) {
3500
3519
  return;
3501
3520
  }
3502
- if (usesJsonResponseTool) {
3503
- if ((contentBlock == null ? void 0 : contentBlock.type) !== "text") {
3504
- return;
3505
- }
3521
+ if ((contentBlock == null ? void 0 : contentBlock.type) === "text") {
3506
3522
  controller.enqueue({
3507
3523
  type: "text-delta",
3508
3524
  id: String(value.index),
@@ -3611,7 +3627,7 @@ var AnthropicMessagesLanguageModel = class {
3611
3627
  usage.totalTokens = ((_g = usage.inputTokens) != null ? _g : 0) + ((_h = usage.outputTokens) != null ? _h : 0);
3612
3628
  finishReason = mapAnthropicStopReason({
3613
3629
  finishReason: value.delta.stop_reason,
3614
- isJsonResponseFromTool: usesJsonResponseTool
3630
+ isJsonResponseFromTool
3615
3631
  });
3616
3632
  stopDetails = mapAnthropicStopDetails(value.delta.stop_details);
3617
3633
  stopSequence = (_i = value.delta.stop_sequence) != null ? _i : null;