@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.
@@ -3628,9 +3628,8 @@ function sanitizeDefinition(definition) {
3628
3628
  }
3629
3629
  function sanitizeSchema(schema) {
3630
3630
  const result = {};
3631
- const schemaWithDefs = schema;
3632
3631
  if (schema.$ref != null) {
3633
- return { $ref: schema.$ref };
3632
+ return { $ref: schema.$ref, ...sanitizeSchemaDefinitions(schema) };
3634
3633
  }
3635
3634
  if (schema.$schema != null) {
3636
3635
  result.$schema = schema.$schema;
@@ -3664,23 +3663,7 @@ function sanitizeSchema(schema) {
3664
3663
  if (schema.allOf != null) {
3665
3664
  result.allOf = schema.allOf.map(sanitizeDefinition);
3666
3665
  }
3667
- if (schema.definitions != null) {
3668
- result.definitions = Object.fromEntries(
3669
- Object.entries(schema.definitions).map(([name, definition]) => [
3670
- name,
3671
- sanitizeDefinition(definition)
3672
- ])
3673
- );
3674
- }
3675
- if (schemaWithDefs.$defs != null) {
3676
- const resultWithDefs = result;
3677
- resultWithDefs.$defs = Object.fromEntries(
3678
- Object.entries(schemaWithDefs.$defs).map(([name, definition]) => [
3679
- name,
3680
- sanitizeDefinition(definition)
3681
- ])
3682
- );
3683
- }
3666
+ Object.assign(result, sanitizeSchemaDefinitions(schema));
3684
3667
  if (schema.type === "object" || schema.properties != null) {
3685
3668
  if (schema.properties != null) {
3686
3669
  result.properties = Object.fromEntries(
@@ -3708,6 +3691,21 @@ ${constraintDescription}`;
3708
3691
  }
3709
3692
  return result;
3710
3693
  }
3694
+ function sanitizeSchemaDefinitions(schema) {
3695
+ const { $defs } = schema;
3696
+ const sanitizeAll = (definitions) => Object.fromEntries(
3697
+ Object.entries(definitions).map(([name, definition]) => [
3698
+ name,
3699
+ sanitizeDefinition(definition)
3700
+ ])
3701
+ );
3702
+ return {
3703
+ ...schema.definitions != null && {
3704
+ definitions: sanitizeAll(schema.definitions)
3705
+ },
3706
+ ...$defs != null && { $defs: sanitizeAll($defs) }
3707
+ };
3708
+ }
3711
3709
  function getConstraintDescription(schema) {
3712
3710
  const descriptions = DESCRIPTION_CONSTRAINT_KEYS.flatMap((key) => {
3713
3711
  const value = schema[key];
@@ -3734,6 +3732,187 @@ function isPlainObject(value) {
3734
3732
  return typeof value === "object" && value !== null && !Array.isArray(value);
3735
3733
  }
3736
3734
 
3735
+ // src/has-circular-schema-reference.ts
3736
+ var SCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set([
3737
+ "dependentSchemas",
3738
+ "patternProperties",
3739
+ "properties"
3740
+ ]);
3741
+ var DATA_KEYWORDS = /* @__PURE__ */ new Set(["const", "default", "enum", "examples"]);
3742
+ function hasCircularSchemaReference(schema) {
3743
+ const visiting = /* @__PURE__ */ new Set();
3744
+ const visited = /* @__PURE__ */ new Set();
3745
+ const visit = (pointer) => {
3746
+ if (visiting.has(pointer)) {
3747
+ return true;
3748
+ }
3749
+ if (visited.has(pointer)) {
3750
+ return false;
3751
+ }
3752
+ const target = resolveSchemaPointer(schema, pointer);
3753
+ if (target === void 0) {
3754
+ return false;
3755
+ }
3756
+ visiting.add(pointer);
3757
+ const isCircular = collectLocalRefs(target).some(visit);
3758
+ visiting.delete(pointer);
3759
+ visited.add(pointer);
3760
+ return isCircular;
3761
+ };
3762
+ return visit("#");
3763
+ }
3764
+ function collectLocalRefs(node, refs = []) {
3765
+ if (Array.isArray(node)) {
3766
+ for (const item of node) {
3767
+ collectLocalRefs(item, refs);
3768
+ }
3769
+ return refs;
3770
+ }
3771
+ if (!isRecord(node)) {
3772
+ return refs;
3773
+ }
3774
+ for (const [key, value] of Object.entries(node)) {
3775
+ if (key === "$ref") {
3776
+ if (typeof value === "string" && value.startsWith("#")) {
3777
+ refs.push(value);
3778
+ }
3779
+ } else if (SCHEMA_MAP_KEYWORDS.has(key) && isRecord(value)) {
3780
+ for (const subschema of Object.values(value)) {
3781
+ collectLocalRefs(subschema, refs);
3782
+ }
3783
+ } else if (
3784
+ // definitions are only reached through a `$ref`:
3785
+ key !== "$defs" && key !== "definitions" && !DATA_KEYWORDS.has(key)
3786
+ ) {
3787
+ collectLocalRefs(value, refs);
3788
+ }
3789
+ }
3790
+ return refs;
3791
+ }
3792
+ function resolveSchemaPointer(schema, pointer) {
3793
+ if (pointer === "#") {
3794
+ return schema;
3795
+ }
3796
+ if (!pointer.startsWith("#/")) {
3797
+ return void 0;
3798
+ }
3799
+ let decodedPointer;
3800
+ try {
3801
+ decodedPointer = decodeURIComponent(pointer.slice(2));
3802
+ } catch (e) {
3803
+ return void 0;
3804
+ }
3805
+ let current = schema;
3806
+ for (const rawSegment of decodedPointer.split("/")) {
3807
+ const segment = rawSegment.replace(/~1/g, "/").replace(/~0/g, "~");
3808
+ if (Array.isArray(current)) {
3809
+ current = current[Number(segment)];
3810
+ } else if (isRecord(current)) {
3811
+ current = current[segment];
3812
+ } else {
3813
+ return void 0;
3814
+ }
3815
+ }
3816
+ return current;
3817
+ }
3818
+ function isRecord(value) {
3819
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3820
+ }
3821
+
3822
+ // src/supports-native-structured-output-schema.ts
3823
+ var MAX_OPTIONAL_PROPERTIES = 10;
3824
+ var SUBSCHEMA_KEYWORDS = [
3825
+ "additionalProperties",
3826
+ "contains",
3827
+ "else",
3828
+ "if",
3829
+ "items",
3830
+ "not",
3831
+ "then"
3832
+ ];
3833
+ var SUBSCHEMA_LIST_KEYWORDS = ["allOf", "anyOf", "oneOf", "prefixItems"];
3834
+ var SUBSCHEMA_MAP_KEYWORDS = [
3835
+ "dependentSchemas",
3836
+ "patternProperties",
3837
+ "properties"
3838
+ ];
3839
+ function supportsNativeStructuredOutputSchema(schema) {
3840
+ if (hasCircularSchemaReference(schema)) {
3841
+ return false;
3842
+ }
3843
+ const { optionalProperties, hasOpenObject } = getSchemaStats(
3844
+ schema,
3845
+ schema,
3846
+ /* @__PURE__ */ new Map()
3847
+ );
3848
+ return !hasOpenObject && optionalProperties <= MAX_OPTIONAL_PROPERTIES;
3849
+ }
3850
+ function getSchemaStats(node, root, refStats) {
3851
+ const stats = { optionalProperties: 0, hasOpenObject: false };
3852
+ if (!isRecord(node)) {
3853
+ return stats;
3854
+ }
3855
+ const add = (child) => {
3856
+ const childStats = getSchemaStats(child, root, refStats);
3857
+ stats.optionalProperties += childStats.optionalProperties;
3858
+ stats.hasOpenObject || (stats.hasOpenObject = childStats.hasOpenObject);
3859
+ };
3860
+ if (typeof node.$ref === "string" && node.$ref.startsWith("#")) {
3861
+ let resolved = refStats.get(node.$ref);
3862
+ if (resolved == null) {
3863
+ resolved = getSchemaStats(
3864
+ resolveSchemaPointer(root, node.$ref),
3865
+ root,
3866
+ refStats
3867
+ );
3868
+ refStats.set(node.$ref, resolved);
3869
+ }
3870
+ stats.optionalProperties += resolved.optionalProperties;
3871
+ stats.hasOpenObject || (stats.hasOpenObject = resolved.hasOpenObject);
3872
+ }
3873
+ if (isOpenObject(node)) {
3874
+ stats.hasOpenObject = true;
3875
+ }
3876
+ if (isRecord(node.properties)) {
3877
+ const required = new Set(Array.isArray(node.required) ? node.required : []);
3878
+ stats.optionalProperties += Object.keys(node.properties).filter(
3879
+ (name) => !required.has(name)
3880
+ ).length;
3881
+ }
3882
+ for (const keyword of SUBSCHEMA_KEYWORDS) {
3883
+ const value = node[keyword];
3884
+ if (Array.isArray(value)) {
3885
+ value.forEach(add);
3886
+ } else {
3887
+ add(value);
3888
+ }
3889
+ }
3890
+ for (const keyword of SUBSCHEMA_LIST_KEYWORDS) {
3891
+ const value = node[keyword];
3892
+ if (Array.isArray(value)) {
3893
+ value.forEach(add);
3894
+ }
3895
+ }
3896
+ for (const keyword of SUBSCHEMA_MAP_KEYWORDS) {
3897
+ const value = node[keyword];
3898
+ if (isRecord(value)) {
3899
+ Object.values(value).forEach(add);
3900
+ }
3901
+ }
3902
+ return stats;
3903
+ }
3904
+ function isOpenObject(node) {
3905
+ const { additionalProperties, patternProperties, properties, type } = node;
3906
+ if (additionalProperties === true || isRecord(additionalProperties)) {
3907
+ return true;
3908
+ }
3909
+ if (isRecord(patternProperties) && Object.keys(patternProperties).length > 0) {
3910
+ return true;
3911
+ }
3912
+ const isObjectType = type === "object" || Array.isArray(type) && type.includes("object");
3913
+ return isObjectType && properties == null && additionalProperties !== false;
3914
+ }
3915
+
3737
3916
  // src/anthropic-messages-language-model.ts
3738
3917
  function createCitationSource(citation, citationDocuments, generateId2) {
3739
3918
  var _a;
@@ -3807,6 +3986,31 @@ function toToolsetMemberInput({
3807
3986
  ...typeof input === "object" && input !== null && !Array.isArray(input) ? input : {}
3808
3987
  };
3809
3988
  }
3989
+ var TEXT_OR_THINKING_BLOCK_TYPES = /* @__PURE__ */ new Set([
3990
+ "redacted_thinking",
3991
+ "text",
3992
+ "thinking"
3993
+ ]);
3994
+ function isContinuationStopReason(stopReason) {
3995
+ return stopReason === "pause_turn" || stopReason === "tool_use";
3996
+ }
3997
+ function getJsonResponseToolFallbackText(content, stopReason) {
3998
+ const text = /* @__PURE__ */ new Set();
3999
+ if (isContinuationStopReason(stopReason)) {
4000
+ return text;
4001
+ }
4002
+ for (const part of content) {
4003
+ if (part.type === "tool_use" && part.name === "json") {
4004
+ return /* @__PURE__ */ new Set();
4005
+ }
4006
+ if (part.type === "text") {
4007
+ text.add(part);
4008
+ } else if (!TEXT_OR_THINKING_BLOCK_TYPES.has(part.type)) {
4009
+ text.clear();
4010
+ }
4011
+ }
4012
+ return text;
4013
+ }
3810
4014
  var AnthropicMessagesLanguageModel = class {
3811
4015
  constructor(modelId, config) {
3812
4016
  this.specificationVersion = "v3";
@@ -3954,7 +4158,7 @@ var AnthropicMessagesLanguageModel = class {
3954
4158
  const supportsStrictTools = ((_c = this.config.supportsStrictTools) != null ? _c : true) && modelSupportsStructuredOutput;
3955
4159
  const structureOutputMode = (_d = anthropicOptions == null ? void 0 : anthropicOptions.structuredOutputMode) != null ? _d : "auto";
3956
4160
  let useStructuredOutput = structureOutputMode === "outputFormat" || structureOutputMode === "auto" && supportsStructuredOutput;
3957
- if (!useStructuredOutput && rejectsForcedToolUse && supportsStructuredOutput && (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null) {
4161
+ if (!useStructuredOutput && rejectsForcedToolUse && modelSupportsStructuredOutput && (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && supportsNativeStructuredOutputSchema(responseFormat.schema)) {
3958
4162
  warnings.push({
3959
4163
  type: "unsupported",
3960
4164
  feature: "providerOptions.anthropic.structuredOutputMode",
@@ -4460,10 +4664,11 @@ var AnthropicMessagesLanguageModel = class {
4460
4664
  const mcpToolCalls = {};
4461
4665
  const serverToolCalls = {};
4462
4666
  let isJsonResponseFromTool = false;
4667
+ const jsonResponseToolFallbackText = usesJsonResponseTool ? getJsonResponseToolFallbackText(response.content, response.stop_reason) : void 0;
4463
4668
  for (const part of response.content) {
4464
4669
  switch (part.type) {
4465
4670
  case "text": {
4466
- if (!usesJsonResponseTool) {
4671
+ if (jsonResponseToolFallbackText == null || jsonResponseToolFallbackText.has(part)) {
4467
4672
  const webSearchCitations = (_a = part.citations) == null ? void 0 : _a.filter(
4468
4673
  (citation) => citation.type === "web_search_result_location"
4469
4674
  );
@@ -4999,6 +5204,15 @@ var AnthropicMessagesLanguageModel = class {
4999
5204
  let safeguardResults;
5000
5205
  let container = null;
5001
5206
  let isJsonResponseFromTool = false;
5207
+ const heldBackText = [];
5208
+ const heldBackTextByIndex = /* @__PURE__ */ new Map();
5209
+ const createTextEnd = (id, citations) => ({
5210
+ type: "text-end",
5211
+ id,
5212
+ ...citations.length > 0 && {
5213
+ providerMetadata: { anthropic: { citations } }
5214
+ }
5215
+ });
5002
5216
  let isMessageOpen = false;
5003
5217
  let activeMessageId;
5004
5218
  let hasInvalidMessageSequence = false;
@@ -5010,7 +5224,7 @@ var AnthropicMessagesLanguageModel = class {
5010
5224
  controller.enqueue({ type: "stream-start", warnings });
5011
5225
  },
5012
5226
  transform(chunk, controller) {
5013
- var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
5227
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
5014
5228
  if (hasInvalidMessageSequence) {
5015
5229
  return;
5016
5230
  }
@@ -5033,9 +5247,19 @@ var AnthropicMessagesLanguageModel = class {
5033
5247
  return;
5034
5248
  }
5035
5249
  blockType = contentBlockType;
5250
+ if (!TEXT_OR_THINKING_BLOCK_TYPES.has(contentBlockType)) {
5251
+ heldBackText.length = 0;
5252
+ }
5036
5253
  switch (contentBlockType) {
5037
5254
  case "text": {
5038
5255
  if (usesJsonResponseTool) {
5256
+ const entry = {
5257
+ id: String(value.index),
5258
+ text: "",
5259
+ citations: []
5260
+ };
5261
+ heldBackText.push(entry);
5262
+ heldBackTextByIndex.set(value.index, entry);
5039
5263
  return;
5040
5264
  }
5041
5265
  contentBlocks[value.index] = {
@@ -5490,17 +5714,12 @@ var AnthropicMessagesLanguageModel = class {
5490
5714
  const contentBlock = contentBlocks[value.index];
5491
5715
  switch (contentBlock.type) {
5492
5716
  case "text": {
5493
- controller.enqueue({
5494
- type: "text-end",
5495
- id: String(value.index),
5496
- ...contentBlock.citations.length > 0 && {
5497
- providerMetadata: {
5498
- anthropic: {
5499
- citations: contentBlock.citations
5500
- }
5501
- }
5502
- }
5503
- });
5717
+ controller.enqueue(
5718
+ createTextEnd(
5719
+ String(value.index),
5720
+ contentBlock.citations
5721
+ )
5722
+ );
5504
5723
  break;
5505
5724
  }
5506
5725
  case "reasoning": {
@@ -5586,6 +5805,10 @@ var AnthropicMessagesLanguageModel = class {
5586
5805
  switch (deltaType) {
5587
5806
  case "text_delta": {
5588
5807
  if (usesJsonResponseTool) {
5808
+ const entry = heldBackTextByIndex.get(value.index);
5809
+ if (entry != null) {
5810
+ entry.text += value.delta.text;
5811
+ }
5589
5812
  return;
5590
5813
  }
5591
5814
  controller.enqueue({
@@ -5667,8 +5890,11 @@ var AnthropicMessagesLanguageModel = class {
5667
5890
  case "citations_delta": {
5668
5891
  const citation = value.delta.citation;
5669
5892
  const contentBlock = contentBlocks[value.index];
5670
- if ((contentBlock == null ? void 0 : contentBlock.type) === "text" && citation.type === "web_search_result_location") {
5671
- contentBlock.citations.push(citation);
5893
+ if (citation.type === "web_search_result_location") {
5894
+ if ((contentBlock == null ? void 0 : contentBlock.type) === "text") {
5895
+ contentBlock.citations.push(citation);
5896
+ }
5897
+ (_e = heldBackTextByIndex.get(value.index)) == null ? void 0 : _e.citations.push(citation);
5672
5898
  }
5673
5899
  const source = createCitationSource(
5674
5900
  citation,
@@ -5705,13 +5931,14 @@ var AnthropicMessagesLanguageModel = class {
5705
5931
  }
5706
5932
  isMessageOpen = true;
5707
5933
  activeMessageId = value.message.id;
5934
+ heldBackTextByIndex.clear();
5708
5935
  usage.input_tokens = value.message.usage.input_tokens;
5709
- usage.cache_read_input_tokens = (_e = value.message.usage.cache_read_input_tokens) != null ? _e : 0;
5710
- usage.cache_creation_input_tokens = (_f = value.message.usage.cache_creation_input_tokens) != null ? _f : 0;
5936
+ usage.cache_read_input_tokens = (_f = value.message.usage.cache_read_input_tokens) != null ? _f : 0;
5937
+ usage.cache_creation_input_tokens = (_g = value.message.usage.cache_creation_input_tokens) != null ? _g : 0;
5711
5938
  rawUsage = {
5712
5939
  ...value.message.usage
5713
5940
  };
5714
- cacheCreationInputTokens = (_g = value.message.usage.cache_creation_input_tokens) != null ? _g : null;
5941
+ cacheCreationInputTokens = (_h = value.message.usage.cache_creation_input_tokens) != null ? _h : null;
5715
5942
  if (value.message.input_transformations != null) {
5716
5943
  inputTransformations = value.message.input_transformations;
5717
5944
  }
@@ -5733,8 +5960,8 @@ var AnthropicMessagesLanguageModel = class {
5733
5960
  }
5734
5961
  controller.enqueue({
5735
5962
  type: "response-metadata",
5736
- id: (_h = value.message.id) != null ? _h : void 0,
5737
- modelId: (_i = value.message.model) != null ? _i : void 0
5963
+ id: (_i = value.message.id) != null ? _i : void 0,
5964
+ modelId: (_j = value.message.model) != null ? _j : void 0
5738
5965
  });
5739
5966
  if (value.message.content != null) {
5740
5967
  for (let contentIndex = 0; contentIndex < value.message.content.length; contentIndex++) {
@@ -5746,7 +5973,7 @@ var AnthropicMessagesLanguageModel = class {
5746
5973
  id: part.id,
5747
5974
  toolName: part.name
5748
5975
  });
5749
- const inputStr = JSON.stringify((_j = part.input) != null ? _j : {});
5976
+ const inputStr = JSON.stringify((_k = part.input) != null ? _k : {});
5750
5977
  controller.enqueue({
5751
5978
  type: "tool-input-delta",
5752
5979
  id: part.id,
@@ -5797,18 +6024,18 @@ var AnthropicMessagesLanguageModel = class {
5797
6024
  finishReason: value.delta.stop_reason,
5798
6025
  isJsonResponseFromTool
5799
6026
  }),
5800
- raw: (_k = value.delta.stop_reason) != null ? _k : void 0
6027
+ raw: (_l = value.delta.stop_reason) != null ? _l : void 0
5801
6028
  };
5802
- stopSequence = (_l = value.delta.stop_sequence) != null ? _l : null;
6029
+ stopSequence = (_m = value.delta.stop_sequence) != null ? _m : null;
5803
6030
  stopDetails = mapAnthropicStopDetails(value.delta.stop_details);
5804
6031
  container = value.delta.container != null ? {
5805
6032
  expiresAt: value.delta.container.expires_at,
5806
6033
  id: value.delta.container.id,
5807
- skills: (_n = (_m = value.delta.container.skills) == null ? void 0 : _m.map((skill) => ({
6034
+ skills: (_o = (_n = value.delta.container.skills) == null ? void 0 : _n.map((skill) => ({
5808
6035
  type: skill.type,
5809
6036
  skillId: skill.skill_id,
5810
6037
  version: skill.version
5811
- }))) != null ? _n : null
6038
+ }))) != null ? _o : null
5812
6039
  } : null;
5813
6040
  if (value.context_management) {
5814
6041
  contextManagement = mapAnthropicResponseContextManagement(
@@ -5860,6 +6087,15 @@ var AnthropicMessagesLanguageModel = class {
5860
6087
  if (usedCustomProviderKey && providerOptionsName !== "anthropic") {
5861
6088
  providerMetadata[providerOptionsName] = anthropicMetadata;
5862
6089
  }
6090
+ if (!isJsonResponseFromTool && !isContinuationStopReason(finishReason.raw)) {
6091
+ for (const { id, text, citations } of heldBackText) {
6092
+ if (text.length === 0) continue;
6093
+ controller.enqueue({ type: "text-start", id });
6094
+ controller.enqueue({ type: "text-delta", id, delta: text });
6095
+ controller.enqueue(createTextEnd(id, citations));
6096
+ }
6097
+ }
6098
+ heldBackText.length = 0;
5863
6099
  controller.enqueue({
5864
6100
  type: "finish",
5865
6101
  finishReason,