@ai-sdk/anthropic 3.0.136 → 3.0.137

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.
@@ -3579,9 +3579,8 @@ function sanitizeDefinition(definition) {
3579
3579
  }
3580
3580
  function sanitizeSchema(schema) {
3581
3581
  const result = {};
3582
- const schemaWithDefs = schema;
3583
3582
  if (schema.$ref != null) {
3584
- return { $ref: schema.$ref };
3583
+ return { $ref: schema.$ref, ...sanitizeSchemaDefinitions(schema) };
3585
3584
  }
3586
3585
  if (schema.$schema != null) {
3587
3586
  result.$schema = schema.$schema;
@@ -3615,23 +3614,7 @@ function sanitizeSchema(schema) {
3615
3614
  if (schema.allOf != null) {
3616
3615
  result.allOf = schema.allOf.map(sanitizeDefinition);
3617
3616
  }
3618
- if (schema.definitions != null) {
3619
- result.definitions = Object.fromEntries(
3620
- Object.entries(schema.definitions).map(([name, definition]) => [
3621
- name,
3622
- sanitizeDefinition(definition)
3623
- ])
3624
- );
3625
- }
3626
- if (schemaWithDefs.$defs != null) {
3627
- const resultWithDefs = result;
3628
- resultWithDefs.$defs = Object.fromEntries(
3629
- Object.entries(schemaWithDefs.$defs).map(([name, definition]) => [
3630
- name,
3631
- sanitizeDefinition(definition)
3632
- ])
3633
- );
3634
- }
3617
+ Object.assign(result, sanitizeSchemaDefinitions(schema));
3635
3618
  if (schema.type === "object" || schema.properties != null) {
3636
3619
  if (schema.properties != null) {
3637
3620
  result.properties = Object.fromEntries(
@@ -3659,6 +3642,21 @@ ${constraintDescription}`;
3659
3642
  }
3660
3643
  return result;
3661
3644
  }
3645
+ function sanitizeSchemaDefinitions(schema) {
3646
+ const { $defs } = schema;
3647
+ const sanitizeAll = (definitions) => Object.fromEntries(
3648
+ Object.entries(definitions).map(([name, definition]) => [
3649
+ name,
3650
+ sanitizeDefinition(definition)
3651
+ ])
3652
+ );
3653
+ return {
3654
+ ...schema.definitions != null && {
3655
+ definitions: sanitizeAll(schema.definitions)
3656
+ },
3657
+ ...$defs != null && { $defs: sanitizeAll($defs) }
3658
+ };
3659
+ }
3662
3660
  function getConstraintDescription(schema) {
3663
3661
  const descriptions = DESCRIPTION_CONSTRAINT_KEYS.flatMap((key) => {
3664
3662
  const value = schema[key];
@@ -3685,6 +3683,187 @@ function isPlainObject(value) {
3685
3683
  return typeof value === "object" && value !== null && !Array.isArray(value);
3686
3684
  }
3687
3685
 
3686
+ // src/has-circular-schema-reference.ts
3687
+ var SCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set([
3688
+ "dependentSchemas",
3689
+ "patternProperties",
3690
+ "properties"
3691
+ ]);
3692
+ var DATA_KEYWORDS = /* @__PURE__ */ new Set(["const", "default", "enum", "examples"]);
3693
+ function hasCircularSchemaReference(schema) {
3694
+ const visiting = /* @__PURE__ */ new Set();
3695
+ const visited = /* @__PURE__ */ new Set();
3696
+ const visit = (pointer) => {
3697
+ if (visiting.has(pointer)) {
3698
+ return true;
3699
+ }
3700
+ if (visited.has(pointer)) {
3701
+ return false;
3702
+ }
3703
+ const target = resolveSchemaPointer(schema, pointer);
3704
+ if (target === void 0) {
3705
+ return false;
3706
+ }
3707
+ visiting.add(pointer);
3708
+ const isCircular = collectLocalRefs(target).some(visit);
3709
+ visiting.delete(pointer);
3710
+ visited.add(pointer);
3711
+ return isCircular;
3712
+ };
3713
+ return visit("#");
3714
+ }
3715
+ function collectLocalRefs(node, refs = []) {
3716
+ if (Array.isArray(node)) {
3717
+ for (const item of node) {
3718
+ collectLocalRefs(item, refs);
3719
+ }
3720
+ return refs;
3721
+ }
3722
+ if (!isRecord(node)) {
3723
+ return refs;
3724
+ }
3725
+ for (const [key, value] of Object.entries(node)) {
3726
+ if (key === "$ref") {
3727
+ if (typeof value === "string" && value.startsWith("#")) {
3728
+ refs.push(value);
3729
+ }
3730
+ } else if (SCHEMA_MAP_KEYWORDS.has(key) && isRecord(value)) {
3731
+ for (const subschema of Object.values(value)) {
3732
+ collectLocalRefs(subschema, refs);
3733
+ }
3734
+ } else if (
3735
+ // definitions are only reached through a `$ref`:
3736
+ key !== "$defs" && key !== "definitions" && !DATA_KEYWORDS.has(key)
3737
+ ) {
3738
+ collectLocalRefs(value, refs);
3739
+ }
3740
+ }
3741
+ return refs;
3742
+ }
3743
+ function resolveSchemaPointer(schema, pointer) {
3744
+ if (pointer === "#") {
3745
+ return schema;
3746
+ }
3747
+ if (!pointer.startsWith("#/")) {
3748
+ return void 0;
3749
+ }
3750
+ let decodedPointer;
3751
+ try {
3752
+ decodedPointer = decodeURIComponent(pointer.slice(2));
3753
+ } catch (e) {
3754
+ return void 0;
3755
+ }
3756
+ let current = schema;
3757
+ for (const rawSegment of decodedPointer.split("/")) {
3758
+ const segment = rawSegment.replace(/~1/g, "/").replace(/~0/g, "~");
3759
+ if (Array.isArray(current)) {
3760
+ current = current[Number(segment)];
3761
+ } else if (isRecord(current)) {
3762
+ current = current[segment];
3763
+ } else {
3764
+ return void 0;
3765
+ }
3766
+ }
3767
+ return current;
3768
+ }
3769
+ function isRecord(value) {
3770
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3771
+ }
3772
+
3773
+ // src/supports-native-structured-output-schema.ts
3774
+ var MAX_OPTIONAL_PROPERTIES = 10;
3775
+ var SUBSCHEMA_KEYWORDS = [
3776
+ "additionalProperties",
3777
+ "contains",
3778
+ "else",
3779
+ "if",
3780
+ "items",
3781
+ "not",
3782
+ "then"
3783
+ ];
3784
+ var SUBSCHEMA_LIST_KEYWORDS = ["allOf", "anyOf", "oneOf", "prefixItems"];
3785
+ var SUBSCHEMA_MAP_KEYWORDS = [
3786
+ "dependentSchemas",
3787
+ "patternProperties",
3788
+ "properties"
3789
+ ];
3790
+ function supportsNativeStructuredOutputSchema(schema) {
3791
+ if (hasCircularSchemaReference(schema)) {
3792
+ return false;
3793
+ }
3794
+ const { optionalProperties, hasOpenObject } = getSchemaStats(
3795
+ schema,
3796
+ schema,
3797
+ /* @__PURE__ */ new Map()
3798
+ );
3799
+ return !hasOpenObject && optionalProperties <= MAX_OPTIONAL_PROPERTIES;
3800
+ }
3801
+ function getSchemaStats(node, root, refStats) {
3802
+ const stats = { optionalProperties: 0, hasOpenObject: false };
3803
+ if (!isRecord(node)) {
3804
+ return stats;
3805
+ }
3806
+ const add = (child) => {
3807
+ const childStats = getSchemaStats(child, root, refStats);
3808
+ stats.optionalProperties += childStats.optionalProperties;
3809
+ stats.hasOpenObject || (stats.hasOpenObject = childStats.hasOpenObject);
3810
+ };
3811
+ if (typeof node.$ref === "string" && node.$ref.startsWith("#")) {
3812
+ let resolved = refStats.get(node.$ref);
3813
+ if (resolved == null) {
3814
+ resolved = getSchemaStats(
3815
+ resolveSchemaPointer(root, node.$ref),
3816
+ root,
3817
+ refStats
3818
+ );
3819
+ refStats.set(node.$ref, resolved);
3820
+ }
3821
+ stats.optionalProperties += resolved.optionalProperties;
3822
+ stats.hasOpenObject || (stats.hasOpenObject = resolved.hasOpenObject);
3823
+ }
3824
+ if (isOpenObject(node)) {
3825
+ stats.hasOpenObject = true;
3826
+ }
3827
+ if (isRecord(node.properties)) {
3828
+ const required = new Set(Array.isArray(node.required) ? node.required : []);
3829
+ stats.optionalProperties += Object.keys(node.properties).filter(
3830
+ (name) => !required.has(name)
3831
+ ).length;
3832
+ }
3833
+ for (const keyword of SUBSCHEMA_KEYWORDS) {
3834
+ const value = node[keyword];
3835
+ if (Array.isArray(value)) {
3836
+ value.forEach(add);
3837
+ } else {
3838
+ add(value);
3839
+ }
3840
+ }
3841
+ for (const keyword of SUBSCHEMA_LIST_KEYWORDS) {
3842
+ const value = node[keyword];
3843
+ if (Array.isArray(value)) {
3844
+ value.forEach(add);
3845
+ }
3846
+ }
3847
+ for (const keyword of SUBSCHEMA_MAP_KEYWORDS) {
3848
+ const value = node[keyword];
3849
+ if (isRecord(value)) {
3850
+ Object.values(value).forEach(add);
3851
+ }
3852
+ }
3853
+ return stats;
3854
+ }
3855
+ function isOpenObject(node) {
3856
+ const { additionalProperties, patternProperties, properties, type } = node;
3857
+ if (additionalProperties === true || isRecord(additionalProperties)) {
3858
+ return true;
3859
+ }
3860
+ if (isRecord(patternProperties) && Object.keys(patternProperties).length > 0) {
3861
+ return true;
3862
+ }
3863
+ const isObjectType = type === "object" || Array.isArray(type) && type.includes("object");
3864
+ return isObjectType && properties == null && additionalProperties !== false;
3865
+ }
3866
+
3688
3867
  // src/anthropic-messages-language-model.ts
3689
3868
  function createCitationSource(citation, citationDocuments, generateId2) {
3690
3869
  var _a;
@@ -3758,6 +3937,31 @@ function toToolsetMemberInput({
3758
3937
  ...typeof input === "object" && input !== null && !Array.isArray(input) ? input : {}
3759
3938
  };
3760
3939
  }
3940
+ var TEXT_OR_THINKING_BLOCK_TYPES = /* @__PURE__ */ new Set([
3941
+ "redacted_thinking",
3942
+ "text",
3943
+ "thinking"
3944
+ ]);
3945
+ function isContinuationStopReason(stopReason) {
3946
+ return stopReason === "pause_turn" || stopReason === "tool_use";
3947
+ }
3948
+ function getJsonResponseToolFallbackText(content, stopReason) {
3949
+ const text = /* @__PURE__ */ new Set();
3950
+ if (isContinuationStopReason(stopReason)) {
3951
+ return text;
3952
+ }
3953
+ for (const part of content) {
3954
+ if (part.type === "tool_use" && part.name === "json") {
3955
+ return /* @__PURE__ */ new Set();
3956
+ }
3957
+ if (part.type === "text") {
3958
+ text.add(part);
3959
+ } else if (!TEXT_OR_THINKING_BLOCK_TYPES.has(part.type)) {
3960
+ text.clear();
3961
+ }
3962
+ }
3963
+ return text;
3964
+ }
3761
3965
  var AnthropicMessagesLanguageModel = class {
3762
3966
  constructor(modelId, config) {
3763
3967
  this.specificationVersion = "v3";
@@ -3905,7 +4109,7 @@ var AnthropicMessagesLanguageModel = class {
3905
4109
  const supportsStrictTools = ((_c = this.config.supportsStrictTools) != null ? _c : true) && modelSupportsStructuredOutput;
3906
4110
  const structureOutputMode = (_d = anthropicOptions == null ? void 0 : anthropicOptions.structuredOutputMode) != null ? _d : "auto";
3907
4111
  let useStructuredOutput = structureOutputMode === "outputFormat" || structureOutputMode === "auto" && supportsStructuredOutput;
3908
- if (!useStructuredOutput && rejectsForcedToolUse && supportsStructuredOutput && (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null) {
4112
+ if (!useStructuredOutput && rejectsForcedToolUse && modelSupportsStructuredOutput && (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && supportsNativeStructuredOutputSchema(responseFormat.schema)) {
3909
4113
  warnings.push({
3910
4114
  type: "unsupported",
3911
4115
  feature: "providerOptions.anthropic.structuredOutputMode",
@@ -4411,10 +4615,11 @@ var AnthropicMessagesLanguageModel = class {
4411
4615
  const mcpToolCalls = {};
4412
4616
  const serverToolCalls = {};
4413
4617
  let isJsonResponseFromTool = false;
4618
+ const jsonResponseToolFallbackText = usesJsonResponseTool ? getJsonResponseToolFallbackText(response.content, response.stop_reason) : void 0;
4414
4619
  for (const part of response.content) {
4415
4620
  switch (part.type) {
4416
4621
  case "text": {
4417
- if (!usesJsonResponseTool) {
4622
+ if (jsonResponseToolFallbackText == null || jsonResponseToolFallbackText.has(part)) {
4418
4623
  const webSearchCitations = (_a = part.citations) == null ? void 0 : _a.filter(
4419
4624
  (citation) => citation.type === "web_search_result_location"
4420
4625
  );
@@ -4950,6 +5155,15 @@ var AnthropicMessagesLanguageModel = class {
4950
5155
  let safeguardResults;
4951
5156
  let container = null;
4952
5157
  let isJsonResponseFromTool = false;
5158
+ const heldBackText = [];
5159
+ const heldBackTextByIndex = /* @__PURE__ */ new Map();
5160
+ const createTextEnd = (id, citations) => ({
5161
+ type: "text-end",
5162
+ id,
5163
+ ...citations.length > 0 && {
5164
+ providerMetadata: { anthropic: { citations } }
5165
+ }
5166
+ });
4953
5167
  let isMessageOpen = false;
4954
5168
  let activeMessageId;
4955
5169
  let hasInvalidMessageSequence = false;
@@ -4961,7 +5175,7 @@ var AnthropicMessagesLanguageModel = class {
4961
5175
  controller.enqueue({ type: "stream-start", warnings });
4962
5176
  },
4963
5177
  transform(chunk, controller) {
4964
- var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
5178
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
4965
5179
  if (hasInvalidMessageSequence) {
4966
5180
  return;
4967
5181
  }
@@ -4984,9 +5198,19 @@ var AnthropicMessagesLanguageModel = class {
4984
5198
  return;
4985
5199
  }
4986
5200
  blockType = contentBlockType;
5201
+ if (!TEXT_OR_THINKING_BLOCK_TYPES.has(contentBlockType)) {
5202
+ heldBackText.length = 0;
5203
+ }
4987
5204
  switch (contentBlockType) {
4988
5205
  case "text": {
4989
5206
  if (usesJsonResponseTool) {
5207
+ const entry = {
5208
+ id: String(value.index),
5209
+ text: "",
5210
+ citations: []
5211
+ };
5212
+ heldBackText.push(entry);
5213
+ heldBackTextByIndex.set(value.index, entry);
4990
5214
  return;
4991
5215
  }
4992
5216
  contentBlocks[value.index] = {
@@ -5441,17 +5665,12 @@ var AnthropicMessagesLanguageModel = class {
5441
5665
  const contentBlock = contentBlocks[value.index];
5442
5666
  switch (contentBlock.type) {
5443
5667
  case "text": {
5444
- controller.enqueue({
5445
- type: "text-end",
5446
- id: String(value.index),
5447
- ...contentBlock.citations.length > 0 && {
5448
- providerMetadata: {
5449
- anthropic: {
5450
- citations: contentBlock.citations
5451
- }
5452
- }
5453
- }
5454
- });
5668
+ controller.enqueue(
5669
+ createTextEnd(
5670
+ String(value.index),
5671
+ contentBlock.citations
5672
+ )
5673
+ );
5455
5674
  break;
5456
5675
  }
5457
5676
  case "reasoning": {
@@ -5537,6 +5756,10 @@ var AnthropicMessagesLanguageModel = class {
5537
5756
  switch (deltaType) {
5538
5757
  case "text_delta": {
5539
5758
  if (usesJsonResponseTool) {
5759
+ const entry = heldBackTextByIndex.get(value.index);
5760
+ if (entry != null) {
5761
+ entry.text += value.delta.text;
5762
+ }
5540
5763
  return;
5541
5764
  }
5542
5765
  controller.enqueue({
@@ -5618,8 +5841,11 @@ var AnthropicMessagesLanguageModel = class {
5618
5841
  case "citations_delta": {
5619
5842
  const citation = value.delta.citation;
5620
5843
  const contentBlock = contentBlocks[value.index];
5621
- if ((contentBlock == null ? void 0 : contentBlock.type) === "text" && citation.type === "web_search_result_location") {
5622
- contentBlock.citations.push(citation);
5844
+ if (citation.type === "web_search_result_location") {
5845
+ if ((contentBlock == null ? void 0 : contentBlock.type) === "text") {
5846
+ contentBlock.citations.push(citation);
5847
+ }
5848
+ (_e = heldBackTextByIndex.get(value.index)) == null ? void 0 : _e.citations.push(citation);
5623
5849
  }
5624
5850
  const source = createCitationSource(
5625
5851
  citation,
@@ -5656,13 +5882,14 @@ var AnthropicMessagesLanguageModel = class {
5656
5882
  }
5657
5883
  isMessageOpen = true;
5658
5884
  activeMessageId = value.message.id;
5885
+ heldBackTextByIndex.clear();
5659
5886
  usage.input_tokens = value.message.usage.input_tokens;
5660
- usage.cache_read_input_tokens = (_e = value.message.usage.cache_read_input_tokens) != null ? _e : 0;
5661
- usage.cache_creation_input_tokens = (_f = value.message.usage.cache_creation_input_tokens) != null ? _f : 0;
5887
+ usage.cache_read_input_tokens = (_f = value.message.usage.cache_read_input_tokens) != null ? _f : 0;
5888
+ usage.cache_creation_input_tokens = (_g = value.message.usage.cache_creation_input_tokens) != null ? _g : 0;
5662
5889
  rawUsage = {
5663
5890
  ...value.message.usage
5664
5891
  };
5665
- cacheCreationInputTokens = (_g = value.message.usage.cache_creation_input_tokens) != null ? _g : null;
5892
+ cacheCreationInputTokens = (_h = value.message.usage.cache_creation_input_tokens) != null ? _h : null;
5666
5893
  if (value.message.input_transformations != null) {
5667
5894
  inputTransformations = value.message.input_transformations;
5668
5895
  }
@@ -5684,8 +5911,8 @@ var AnthropicMessagesLanguageModel = class {
5684
5911
  }
5685
5912
  controller.enqueue({
5686
5913
  type: "response-metadata",
5687
- id: (_h = value.message.id) != null ? _h : void 0,
5688
- modelId: (_i = value.message.model) != null ? _i : void 0
5914
+ id: (_i = value.message.id) != null ? _i : void 0,
5915
+ modelId: (_j = value.message.model) != null ? _j : void 0
5689
5916
  });
5690
5917
  if (value.message.content != null) {
5691
5918
  for (let contentIndex = 0; contentIndex < value.message.content.length; contentIndex++) {
@@ -5697,7 +5924,7 @@ var AnthropicMessagesLanguageModel = class {
5697
5924
  id: part.id,
5698
5925
  toolName: part.name
5699
5926
  });
5700
- const inputStr = JSON.stringify((_j = part.input) != null ? _j : {});
5927
+ const inputStr = JSON.stringify((_k = part.input) != null ? _k : {});
5701
5928
  controller.enqueue({
5702
5929
  type: "tool-input-delta",
5703
5930
  id: part.id,
@@ -5748,18 +5975,18 @@ var AnthropicMessagesLanguageModel = class {
5748
5975
  finishReason: value.delta.stop_reason,
5749
5976
  isJsonResponseFromTool
5750
5977
  }),
5751
- raw: (_k = value.delta.stop_reason) != null ? _k : void 0
5978
+ raw: (_l = value.delta.stop_reason) != null ? _l : void 0
5752
5979
  };
5753
- stopSequence = (_l = value.delta.stop_sequence) != null ? _l : null;
5980
+ stopSequence = (_m = value.delta.stop_sequence) != null ? _m : null;
5754
5981
  stopDetails = mapAnthropicStopDetails(value.delta.stop_details);
5755
5982
  container = value.delta.container != null ? {
5756
5983
  expiresAt: value.delta.container.expires_at,
5757
5984
  id: value.delta.container.id,
5758
- skills: (_n = (_m = value.delta.container.skills) == null ? void 0 : _m.map((skill) => ({
5985
+ skills: (_o = (_n = value.delta.container.skills) == null ? void 0 : _n.map((skill) => ({
5759
5986
  type: skill.type,
5760
5987
  skillId: skill.skill_id,
5761
5988
  version: skill.version
5762
- }))) != null ? _n : null
5989
+ }))) != null ? _o : null
5763
5990
  } : null;
5764
5991
  if (value.context_management) {
5765
5992
  contextManagement = mapAnthropicResponseContextManagement(
@@ -5811,6 +6038,15 @@ var AnthropicMessagesLanguageModel = class {
5811
6038
  if (usedCustomProviderKey && providerOptionsName !== "anthropic") {
5812
6039
  providerMetadata[providerOptionsName] = anthropicMetadata;
5813
6040
  }
6041
+ if (!isJsonResponseFromTool && !isContinuationStopReason(finishReason.raw)) {
6042
+ for (const { id, text, citations } of heldBackText) {
6043
+ if (text.length === 0) continue;
6044
+ controller.enqueue({ type: "text-start", id });
6045
+ controller.enqueue({ type: "text-delta", id, delta: text });
6046
+ controller.enqueue(createTextEnd(id, citations));
6047
+ }
6048
+ }
6049
+ heldBackText.length = 0;
5814
6050
  controller.enqueue({
5815
6051
  type: "finish",
5816
6052
  finishReason,