@ai-sdk/anthropic 2.0.111 → 2.0.112

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.111" : "0.0.0-test";
14
+ var VERSION = true ? "2.0.112" : "0.0.0-test";
15
15
 
16
16
  // src/anthropic-messages-language-model.ts
17
17
  import {
@@ -1546,6 +1546,8 @@ import {
1546
1546
  UnsupportedFunctionalityError as UnsupportedFunctionalityError2
1547
1547
  } from "@ai-sdk/provider";
1548
1548
  import {
1549
+ stringifyWithBigIntAndCycles,
1550
+ secureJsonParse,
1549
1551
  convertToBase64,
1550
1552
  parseProviderOptions,
1551
1553
  validateTypes as validateTypes2
@@ -1970,7 +1972,7 @@ async function convertToAnthropicMessagesPrompt({
1970
1972
  case "json":
1971
1973
  case "error-json":
1972
1974
  default:
1973
- contentValue = JSON.stringify(output.value);
1975
+ contentValue = stringifyWithBigIntAndCycles(output.value);
1974
1976
  break;
1975
1977
  }
1976
1978
  const toolsetName = getAnthropicToolsetName({
@@ -2144,7 +2146,7 @@ async function convertToAnthropicMessagesPrompt({
2144
2146
  type: "tool_use",
2145
2147
  id: part.toolCallId,
2146
2148
  name: part.toolName,
2147
- input: part.input,
2149
+ input: parseToolCallInput(part.input),
2148
2150
  cache_control: cacheControl
2149
2151
  });
2150
2152
  break;
@@ -2379,6 +2381,18 @@ function getAnthropicToolsetName({
2379
2381
  const fromMetadata = (_a = providerOptions == null ? void 0 : providerOptions.anthropic) == null ? void 0 : _a.toolsetName;
2380
2382
  return typeof fromMetadata === "string" ? fromMetadata : void 0;
2381
2383
  }
2384
+ function parseToolCallInput(input) {
2385
+ if (typeof input === "string") {
2386
+ try {
2387
+ const parsed = secureJsonParse(input);
2388
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
2389
+ return parsed;
2390
+ }
2391
+ } catch (e) {
2392
+ }
2393
+ }
2394
+ return input;
2395
+ }
2382
2396
 
2383
2397
  // src/map-anthropic-stop-reason.ts
2384
2398
  function mapAnthropicStopReason({
@@ -2549,6 +2563,187 @@ function isPlainObject(value) {
2549
2563
  return typeof value === "object" && value !== null && !Array.isArray(value);
2550
2564
  }
2551
2565
 
2566
+ // src/has-circular-schema-reference.ts
2567
+ var SCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set([
2568
+ "dependentSchemas",
2569
+ "patternProperties",
2570
+ "properties"
2571
+ ]);
2572
+ var DATA_KEYWORDS = /* @__PURE__ */ new Set(["const", "default", "enum", "examples"]);
2573
+ function hasCircularSchemaReference(schema) {
2574
+ const visiting = /* @__PURE__ */ new Set();
2575
+ const visited = /* @__PURE__ */ new Set();
2576
+ const visit = (pointer) => {
2577
+ if (visiting.has(pointer)) {
2578
+ return true;
2579
+ }
2580
+ if (visited.has(pointer)) {
2581
+ return false;
2582
+ }
2583
+ const target = resolveSchemaPointer(schema, pointer);
2584
+ if (target === void 0) {
2585
+ return false;
2586
+ }
2587
+ visiting.add(pointer);
2588
+ const isCircular = collectLocalRefs(target).some(visit);
2589
+ visiting.delete(pointer);
2590
+ visited.add(pointer);
2591
+ return isCircular;
2592
+ };
2593
+ return visit("#");
2594
+ }
2595
+ function collectLocalRefs(node, refs = []) {
2596
+ if (Array.isArray(node)) {
2597
+ for (const item of node) {
2598
+ collectLocalRefs(item, refs);
2599
+ }
2600
+ return refs;
2601
+ }
2602
+ if (!isRecord(node)) {
2603
+ return refs;
2604
+ }
2605
+ for (const [key, value] of Object.entries(node)) {
2606
+ if (key === "$ref") {
2607
+ if (typeof value === "string" && value.startsWith("#")) {
2608
+ refs.push(value);
2609
+ }
2610
+ } else if (SCHEMA_MAP_KEYWORDS.has(key) && isRecord(value)) {
2611
+ for (const subschema of Object.values(value)) {
2612
+ collectLocalRefs(subschema, refs);
2613
+ }
2614
+ } else if (
2615
+ // definitions are only reached through a `$ref`:
2616
+ key !== "$defs" && key !== "definitions" && !DATA_KEYWORDS.has(key)
2617
+ ) {
2618
+ collectLocalRefs(value, refs);
2619
+ }
2620
+ }
2621
+ return refs;
2622
+ }
2623
+ function resolveSchemaPointer(schema, pointer) {
2624
+ if (pointer === "#") {
2625
+ return schema;
2626
+ }
2627
+ if (!pointer.startsWith("#/")) {
2628
+ return void 0;
2629
+ }
2630
+ let decodedPointer;
2631
+ try {
2632
+ decodedPointer = decodeURIComponent(pointer.slice(2));
2633
+ } catch (e) {
2634
+ return void 0;
2635
+ }
2636
+ let current = schema;
2637
+ for (const rawSegment of decodedPointer.split("/")) {
2638
+ const segment = rawSegment.replace(/~1/g, "/").replace(/~0/g, "~");
2639
+ if (Array.isArray(current)) {
2640
+ current = current[Number(segment)];
2641
+ } else if (isRecord(current)) {
2642
+ current = current[segment];
2643
+ } else {
2644
+ return void 0;
2645
+ }
2646
+ }
2647
+ return current;
2648
+ }
2649
+ function isRecord(value) {
2650
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2651
+ }
2652
+
2653
+ // src/supports-native-structured-output-schema.ts
2654
+ var MAX_OPTIONAL_PROPERTIES = 10;
2655
+ var SUBSCHEMA_KEYWORDS = [
2656
+ "additionalProperties",
2657
+ "contains",
2658
+ "else",
2659
+ "if",
2660
+ "items",
2661
+ "not",
2662
+ "then"
2663
+ ];
2664
+ var SUBSCHEMA_LIST_KEYWORDS = ["allOf", "anyOf", "oneOf", "prefixItems"];
2665
+ var SUBSCHEMA_MAP_KEYWORDS = [
2666
+ "dependentSchemas",
2667
+ "patternProperties",
2668
+ "properties"
2669
+ ];
2670
+ function supportsNativeStructuredOutputSchema(schema) {
2671
+ if (schema.$ref != null || hasCircularSchemaReference(schema)) {
2672
+ return false;
2673
+ }
2674
+ const { optionalProperties, hasOpenObject } = getSchemaStats(
2675
+ schema,
2676
+ schema,
2677
+ /* @__PURE__ */ new Map()
2678
+ );
2679
+ return !hasOpenObject && optionalProperties <= MAX_OPTIONAL_PROPERTIES;
2680
+ }
2681
+ function getSchemaStats(node, root, refStats) {
2682
+ const stats = { optionalProperties: 0, hasOpenObject: false };
2683
+ if (!isRecord(node)) {
2684
+ return stats;
2685
+ }
2686
+ const add = (child) => {
2687
+ const childStats = getSchemaStats(child, root, refStats);
2688
+ stats.optionalProperties += childStats.optionalProperties;
2689
+ stats.hasOpenObject || (stats.hasOpenObject = childStats.hasOpenObject);
2690
+ };
2691
+ if (typeof node.$ref === "string" && node.$ref.startsWith("#")) {
2692
+ let resolved = refStats.get(node.$ref);
2693
+ if (resolved == null) {
2694
+ resolved = getSchemaStats(
2695
+ resolveSchemaPointer(root, node.$ref),
2696
+ root,
2697
+ refStats
2698
+ );
2699
+ refStats.set(node.$ref, resolved);
2700
+ }
2701
+ stats.optionalProperties += resolved.optionalProperties;
2702
+ stats.hasOpenObject || (stats.hasOpenObject = resolved.hasOpenObject);
2703
+ }
2704
+ if (isOpenObject(node)) {
2705
+ stats.hasOpenObject = true;
2706
+ }
2707
+ if (isRecord(node.properties)) {
2708
+ const required = new Set(Array.isArray(node.required) ? node.required : []);
2709
+ stats.optionalProperties += Object.keys(node.properties).filter(
2710
+ (name) => !required.has(name)
2711
+ ).length;
2712
+ }
2713
+ for (const keyword of SUBSCHEMA_KEYWORDS) {
2714
+ const value = node[keyword];
2715
+ if (Array.isArray(value)) {
2716
+ value.forEach(add);
2717
+ } else {
2718
+ add(value);
2719
+ }
2720
+ }
2721
+ for (const keyword of SUBSCHEMA_LIST_KEYWORDS) {
2722
+ const value = node[keyword];
2723
+ if (Array.isArray(value)) {
2724
+ value.forEach(add);
2725
+ }
2726
+ }
2727
+ for (const keyword of SUBSCHEMA_MAP_KEYWORDS) {
2728
+ const value = node[keyword];
2729
+ if (isRecord(value)) {
2730
+ Object.values(value).forEach(add);
2731
+ }
2732
+ }
2733
+ return stats;
2734
+ }
2735
+ function isOpenObject(node) {
2736
+ const { additionalProperties, patternProperties, properties, type } = node;
2737
+ if (additionalProperties === true || isRecord(additionalProperties)) {
2738
+ return true;
2739
+ }
2740
+ if (isRecord(patternProperties) && Object.keys(patternProperties).length > 0) {
2741
+ return true;
2742
+ }
2743
+ const isObjectType = type === "object" || Array.isArray(type) && type.includes("object");
2744
+ return isObjectType && properties == null && additionalProperties !== false;
2745
+ }
2746
+
2552
2747
  // src/anthropic-messages-language-model.ts
2553
2748
  function getAnthropicToolsetNames(tools) {
2554
2749
  const toolsetNames = {};
@@ -2606,6 +2801,31 @@ function createCitationSource(citation, citationDocuments, generateId3) {
2606
2801
  }
2607
2802
  };
2608
2803
  }
2804
+ var TEXT_OR_THINKING_BLOCK_TYPES = /* @__PURE__ */ new Set([
2805
+ "redacted_thinking",
2806
+ "text",
2807
+ "thinking"
2808
+ ]);
2809
+ function isContinuationStopReason(stopReason) {
2810
+ return stopReason === "pause_turn" || stopReason === "tool_use";
2811
+ }
2812
+ function getJsonResponseToolFallbackText(content, stopReason, jsonResponseToolName) {
2813
+ const text = /* @__PURE__ */ new Set();
2814
+ if (isContinuationStopReason(stopReason)) {
2815
+ return text;
2816
+ }
2817
+ for (const part of content) {
2818
+ if (part.type === "tool_use" && part.name === jsonResponseToolName) {
2819
+ return /* @__PURE__ */ new Set();
2820
+ }
2821
+ if (part.type === "text") {
2822
+ text.add(part);
2823
+ } else if (!TEXT_OR_THINKING_BLOCK_TYPES.has(part.type)) {
2824
+ text.clear();
2825
+ }
2826
+ }
2827
+ return text;
2828
+ }
2609
2829
  var AnthropicMessagesLanguageModel = class {
2610
2830
  constructor(modelId, config) {
2611
2831
  this.specificationVersion = "v2";
@@ -2733,9 +2953,10 @@ var AnthropicMessagesLanguageModel = class {
2733
2953
  }
2734
2954
  }
2735
2955
  const isAnthropicModel = isKnownModel || this.modelId.includes("claude-");
2956
+ const supportsResponseSchema = (responseFormat == null ? void 0 : responseFormat.type) !== "json" || responseFormat.schema == null || supportsNativeStructuredOutputSchema(responseFormat.schema);
2736
2957
  const structureOutputMode = (_a = anthropicOptions == null ? void 0 : anthropicOptions.structuredOutputMode) != null ? _a : this.modelId.includes("claude-fable-5-1") || this.modelId.includes("claude-opus-5-5") || this.modelId.includes("claude-sonnet-5-5") ? "auto" : "jsonTool";
2737
- let useStructuredOutput = structureOutputMode === "outputFormat" || structureOutputMode === "auto" && supportsStructuredOutput;
2738
- if (!useStructuredOutput && rejectsForcedToolUse && supportsStructuredOutput && (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null) {
2958
+ let useStructuredOutput = structureOutputMode === "outputFormat" || structureOutputMode === "auto" && supportsStructuredOutput && supportsResponseSchema;
2959
+ if (!useStructuredOutput && rejectsForcedToolUse && supportsStructuredOutput && (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && supportsResponseSchema) {
2739
2960
  warnings.push({
2740
2961
  type: "unsupported-setting",
2741
2962
  setting: "providerOptions.anthropic.structuredOutputMode",
@@ -3044,8 +3265,13 @@ var AnthropicMessagesLanguageModel = class {
3044
3265
  betas: toolsBetas
3045
3266
  } = await prepareTools(
3046
3267
  jsonResponseTool != null ? {
3047
- tools: [...tools != null ? tools : [], jsonResponseTool],
3048
- toolChoice: tools != null && tools.length > 0 ? { type: "required" } : { type: "tool", toolName: jsonResponseTool.name },
3268
+ tools: [
3269
+ ...(tools != null ? tools : []).filter(
3270
+ (tool) => (toolChoice == null ? void 0 : toolChoice.type) !== "none" && ((toolChoice == null ? void 0 : toolChoice.type) !== "tool" || tool.name === toolChoice.toolName)
3271
+ ),
3272
+ jsonResponseTool
3273
+ ],
3274
+ toolChoice: rejectsForcedToolUse ? { type: "auto" } : tools != null && tools.length > 0 ? { type: "required" } : { type: "tool", toolName: jsonResponseTool.name },
3049
3275
  disableParallelToolUse: true,
3050
3276
  cacheControlValidator,
3051
3277
  rejectsForcedToolUse
@@ -3151,10 +3377,15 @@ var AnthropicMessagesLanguageModel = class {
3151
3377
  });
3152
3378
  const content = [];
3153
3379
  let isJsonResponseFromTool = false;
3380
+ const jsonResponseToolFallbackText = jsonResponseToolName != null ? getJsonResponseToolFallbackText(
3381
+ response.content,
3382
+ response.stop_reason,
3383
+ jsonResponseToolName
3384
+ ) : void 0;
3154
3385
  for (const part of response.content) {
3155
3386
  switch (part.type) {
3156
3387
  case "text": {
3157
- if (jsonResponseToolName == null) {
3388
+ if (jsonResponseToolFallbackText == null || jsonResponseToolFallbackText.has(part)) {
3158
3389
  const webSearchCitations = (_a = part.citations) == null ? void 0 : _a.filter(
3159
3390
  (citation) => citation.type === "web_search_result_location"
3160
3391
  );
@@ -3533,6 +3764,16 @@ var AnthropicMessagesLanguageModel = class {
3533
3764
  let iterations = null;
3534
3765
  let contextManagement = null;
3535
3766
  let isJsonResponseFromTool = false;
3767
+ let rawStopReason;
3768
+ const heldBackText = [];
3769
+ const heldBackTextByIndex = /* @__PURE__ */ new Map();
3770
+ const createTextEnd = (id, citations) => ({
3771
+ type: "text-end",
3772
+ id,
3773
+ ...citations.length > 0 && {
3774
+ providerMetadata: { anthropic: { citations } }
3775
+ }
3776
+ });
3536
3777
  let isMessageOpen = false;
3537
3778
  let activeMessageId;
3538
3779
  let hasInvalidMessageSequence = false;
@@ -3544,7 +3785,7 @@ var AnthropicMessagesLanguageModel = class {
3544
3785
  controller.enqueue({ type: "stream-start", warnings });
3545
3786
  },
3546
3787
  transform(chunk, controller) {
3547
- var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k;
3788
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
3548
3789
  if (hasInvalidMessageSequence) {
3549
3790
  return;
3550
3791
  }
@@ -3566,8 +3807,21 @@ var AnthropicMessagesLanguageModel = class {
3566
3807
  return;
3567
3808
  }
3568
3809
  blockType = contentBlockType;
3810
+ if (!TEXT_OR_THINKING_BLOCK_TYPES.has(contentBlockType)) {
3811
+ heldBackText.length = 0;
3812
+ }
3569
3813
  switch (contentBlockType) {
3570
3814
  case "text": {
3815
+ if (jsonResponseToolName != null) {
3816
+ const entry = {
3817
+ id: String(value.index),
3818
+ text: "",
3819
+ citations: []
3820
+ };
3821
+ heldBackText.push(entry);
3822
+ heldBackTextByIndex.set(value.index, entry);
3823
+ return;
3824
+ }
3571
3825
  contentBlocks[value.index] = {
3572
3826
  type: "text",
3573
3827
  citations: []
@@ -3903,6 +4157,8 @@ var AnthropicMessagesLanguageModel = class {
3903
4157
  switch (deltaType) {
3904
4158
  case "text_delta": {
3905
4159
  if (jsonResponseToolName != null) {
4160
+ const entry = heldBackTextByIndex.get(value.index);
4161
+ if (entry != null) entry.text += value.delta.text;
3906
4162
  return;
3907
4163
  }
3908
4164
  controller.enqueue({
@@ -3981,8 +4237,10 @@ var AnthropicMessagesLanguageModel = class {
3981
4237
  case "citations_delta": {
3982
4238
  const citation = value.delta.citation;
3983
4239
  const contentBlock = contentBlocks[value.index];
3984
- if ((contentBlock == null ? void 0 : contentBlock.type) === "text" && citation.type === "web_search_result_location") {
3985
- contentBlock.citations.push(citation);
4240
+ if (citation.type === "web_search_result_location") {
4241
+ if ((contentBlock == null ? void 0 : contentBlock.type) === "text")
4242
+ contentBlock.citations.push(citation);
4243
+ (_b2 = heldBackTextByIndex.get(value.index)) == null ? void 0 : _b2.citations.push(citation);
3986
4244
  }
3987
4245
  const source = createCitationSource(
3988
4246
  citation,
@@ -4019,16 +4277,17 @@ var AnthropicMessagesLanguageModel = class {
4019
4277
  }
4020
4278
  isMessageOpen = true;
4021
4279
  activeMessageId = value.message.id;
4280
+ heldBackTextByIndex.clear();
4022
4281
  usage.inputTokens = value.message.usage.input_tokens;
4023
- usage.cachedInputTokens = (_b2 = value.message.usage.cache_read_input_tokens) != null ? _b2 : void 0;
4282
+ usage.cachedInputTokens = (_c = value.message.usage.cache_read_input_tokens) != null ? _c : void 0;
4024
4283
  rawUsage = {
4025
4284
  ...value.message.usage
4026
4285
  };
4027
- cacheCreationInputTokens = (_c = value.message.usage.cache_creation_input_tokens) != null ? _c : null;
4286
+ cacheCreationInputTokens = (_d = value.message.usage.cache_creation_input_tokens) != null ? _d : null;
4028
4287
  controller.enqueue({
4029
4288
  type: "response-metadata",
4030
- id: (_d = value.message.id) != null ? _d : void 0,
4031
- modelId: (_e = value.message.model) != null ? _e : void 0
4289
+ id: (_e = value.message.id) != null ? _e : void 0,
4290
+ modelId: (_f = value.message.model) != null ? _f : void 0
4032
4291
  });
4033
4292
  return;
4034
4293
  }
@@ -4042,7 +4301,7 @@ var AnthropicMessagesLanguageModel = class {
4042
4301
  if (value.usage.iterations != null) {
4043
4302
  iterations = value.usage.iterations;
4044
4303
  }
4045
- const servedByFallback = (_f = value.usage.iterations) == null ? void 0 : _f.some(
4304
+ const servedByFallback = (_g = value.usage.iterations) == null ? void 0 : _g.some(
4046
4305
  (iter) => iter.type === "fallback_message"
4047
4306
  );
4048
4307
  if (value.usage.iterations && value.usage.iterations.length > 0 && !servedByFallback) {
@@ -4061,21 +4320,22 @@ var AnthropicMessagesLanguageModel = class {
4061
4320
  }
4062
4321
  usage.outputTokens = value.usage.output_tokens;
4063
4322
  }
4064
- usage.totalTokens = ((_g = usage.inputTokens) != null ? _g : 0) + ((_h = usage.outputTokens) != null ? _h : 0);
4323
+ usage.totalTokens = ((_h = usage.inputTokens) != null ? _h : 0) + ((_i = usage.outputTokens) != null ? _i : 0);
4324
+ rawStopReason = value.delta.stop_reason;
4065
4325
  finishReason = mapAnthropicStopReason({
4066
4326
  finishReason: value.delta.stop_reason,
4067
4327
  isJsonResponseFromTool
4068
4328
  });
4069
4329
  stopDetails = mapAnthropicStopDetails(value.delta.stop_details);
4070
- stopSequence = (_i = value.delta.stop_sequence) != null ? _i : null;
4330
+ stopSequence = (_j = value.delta.stop_sequence) != null ? _j : null;
4071
4331
  container = value.delta.container != null ? {
4072
4332
  expiresAt: value.delta.container.expires_at,
4073
4333
  id: value.delta.container.id,
4074
- skills: (_k = (_j = value.delta.container.skills) == null ? void 0 : _j.map((skill) => ({
4334
+ skills: (_l = (_k = value.delta.container.skills) == null ? void 0 : _k.map((skill) => ({
4075
4335
  type: skill.type,
4076
4336
  skillId: skill.skill_id,
4077
4337
  version: skill.version
4078
- }))) != null ? _k : null
4338
+ }))) != null ? _l : null
4079
4339
  } : null;
4080
4340
  if (value.context_management != null) {
4081
4341
  contextManagement = {
@@ -4113,6 +4373,15 @@ var AnthropicMessagesLanguageModel = class {
4113
4373
  case "message_stop": {
4114
4374
  isMessageOpen = false;
4115
4375
  activeMessageId = void 0;
4376
+ if (!isJsonResponseFromTool && !isContinuationStopReason(rawStopReason)) {
4377
+ for (const { id, text, citations } of heldBackText) {
4378
+ if (text.length === 0) continue;
4379
+ controller.enqueue({ type: "text-start", id });
4380
+ controller.enqueue({ type: "text-delta", id, delta: text });
4381
+ controller.enqueue(createTextEnd(id, citations));
4382
+ }
4383
+ }
4384
+ heldBackText.length = 0;
4116
4385
  controller.enqueue({
4117
4386
  type: "finish",
4118
4387
  finishReason,