@ai-sdk/anthropic 4.0.93 → 4.0.95

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/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @ai-sdk/anthropic
2
2
 
3
+ ## 4.0.95
4
+
5
+ ### Patch Changes
6
+
7
+ - 2cd0a97: Enable native structured output and strict tools for supported Claude 5 models on Bedrock. In automatic mode, Bedrock and Anthropic now fall back for schemas that native structured output cannot represent: recursive references, open objects, or more than ten optional properties. Anthropic uses the JSON response tool; Bedrock Converse uses the JSON tool or JSON instructions for models that reject forced tool use. The JSON-tool fallback excludes disabled and unselected application tools. Explicit `outputFormat` selection remains unchanged.
8
+ - 4ae6986: fix(anthropic): parse valid JSON string tool input and safely serialize BigInt and cycles in tool results
9
+ - Updated dependencies [51ca5b7]
10
+ - Updated dependencies [dc6f1c3]
11
+ - Updated dependencies [4ae6986]
12
+ - @ai-sdk/provider-utils@5.0.73
13
+
14
+ ## 4.0.94
15
+
16
+ ### Patch Changes
17
+
18
+ - f4c5f1e: fix(anthropic): use native structured outputs for Claude models that reject forced tool use (Sonnet 5.5, Opus 5.5, Fable 5.1) even when the provider disables them by default, as Amazon Bedrock and Google Vertex do. Self-referencing schemas keep the JSON response tool. Also keep `definitions` and `$defs` next to a top-level `$ref` when sanitizing structured output schemas, so the reference still resolves.
19
+ - e10aebb: fix(anthropic): when the JSON response tool is in use but the model answers in text without calling it (for example with manual thinking, where the forced tool choice is downgraded to `auto`), return the final answer text instead of dropping it. Text before a tool call, result, or message continuation is still dropped.
20
+ - b0d51fe: fix(anthropic): keep the JSON response tool for schemas that native structured outputs cannot represent when upgrading models that reject forced tool use. Schemas with open objects (maps, free-form objects) would otherwise come back as `{}`, and schemas with more than 10 optional properties can be rejected as too complex.
21
+
3
22
  ## 4.0.93
4
23
 
5
24
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { APICallError, InvalidArgumentError, InvalidResponseDataError, NoSuchModelError, UnsupportedFunctionalityError } from "@ai-sdk/provider";
2
- import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertInlineFileDataToUint8Array, convertToBase64, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonLinesResponseHandler, createJsonResponseHandler, createProviderDefinedToolFactory, createProviderExecutedToolFactory, createProviderStreamError, createToolNameMapping, encodePathSegment, experimental_toolCaller, generateId, getFromApi, getTopLevelMediaType, isCustomReasoning, isNonNullable, isProviderStreamError, isRecord, lazySchema, loadApiKey, loadOptionalSetting, mapReasoningToProviderBudget, mapReasoningToProviderEffort, normalizeBatchRequestCounts, normalizeHeaders, parseProviderOptions, postFormDataToApi, postJsonToApi, resolve, resolveFullMediaType, resolveProviderReference, safeValidateTypes, secureJsonParse, serializeModelOptions, validateBaseURL, validateTypes, withUserAgentSuffix, withoutTrailingSlash, zodSchema } from "@ai-sdk/provider-utils";
2
+ import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertInlineFileDataToUint8Array, convertToBase64, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonLinesResponseHandler, createJsonResponseHandler, createProviderDefinedToolFactory, createProviderExecutedToolFactory, createProviderStreamError, createToolNameMapping, encodePathSegment, experimental_toolCaller, generateId, getFromApi, getTopLevelMediaType, isCustomReasoning, isNonNullable, isProviderStreamError, isRecord, lazySchema, loadApiKey, loadOptionalSetting, mapReasoningToProviderBudget, mapReasoningToProviderEffort, normalizeBatchRequestCounts, normalizeHeaders, parseProviderOptions, postFormDataToApi, postJsonToApi, resolve, resolveFullMediaType, resolveProviderReference, safeValidateTypes, secureJsonParse, serializeModelOptions, stringifyWithBigIntAndCycles, validateBaseURL, validateTypes, withUserAgentSuffix, withoutTrailingSlash, zodSchema } from "@ai-sdk/provider-utils";
3
3
  import { Experimental_DecisionLanguageModel } from "@ai-sdk/provider-utils/experimental-decision";
4
4
  import { z } from "zod/v4";
5
5
  //#region src/anthropic-error.ts
@@ -2963,7 +2963,7 @@ async function convertToAnthropicPrompt({ prompt, sendReasoning, warnings, cache
2963
2963
  case "execution-denied":
2964
2964
  contentValue = output.reason ?? "Tool call execution denied.";
2965
2965
  break;
2966
- default: contentValue = JSON.stringify(output.value);
2966
+ default: contentValue = stringifyWithBigIntAndCycles(output.value);
2967
2967
  }
2968
2968
  const toolsetName = getAnthropicToolsetName({
2969
2969
  toolName: part.toolName,
@@ -3634,6 +3634,10 @@ function getAnthropicCaller(providerOptions) {
3634
3634
  return caller?.type === "direct" ? { type: "direct" } : void 0;
3635
3635
  }
3636
3636
  function toAnthropicToolInput(input) {
3637
+ if (typeof input === "string") try {
3638
+ const parsed = secureJsonParse(input);
3639
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) return parsed;
3640
+ } catch {}
3637
3641
  return typeof input === "object" && input !== null && !Array.isArray(input) ? input : { rawInvalidInput: input };
3638
3642
  }
3639
3643
  //#endregion
@@ -3700,8 +3704,10 @@ function sanitizeDefinition(definition) {
3700
3704
  }
3701
3705
  function sanitizeSchema(schema) {
3702
3706
  const result = {};
3703
- const schemaWithDefs = schema;
3704
- if (schema.$ref != null) return { $ref: schema.$ref };
3707
+ if (schema.$ref != null) return {
3708
+ $ref: schema.$ref,
3709
+ ...sanitizeSchemaDefinitions(schema)
3710
+ };
3705
3711
  if (schema.$schema != null) result.$schema = schema.$schema;
3706
3712
  if (schema.$id != null) result.$id = schema.$id;
3707
3713
  if (schema.title != null) result.title = schema.title;
@@ -3713,11 +3719,7 @@ function sanitizeSchema(schema) {
3713
3719
  if (schema.anyOf != null) result.anyOf = schema.anyOf.map(sanitizeDefinition);
3714
3720
  else if (schema.oneOf != null) result.anyOf = schema.oneOf.map(sanitizeDefinition);
3715
3721
  if (schema.allOf != null) result.allOf = schema.allOf.map(sanitizeDefinition);
3716
- if (schema.definitions != null) result.definitions = Object.fromEntries(Object.entries(schema.definitions).map(([name, definition]) => [name, sanitizeDefinition(definition)]));
3717
- if (schemaWithDefs.$defs != null) {
3718
- const resultWithDefs = result;
3719
- resultWithDefs.$defs = Object.fromEntries(Object.entries(schemaWithDefs.$defs).map(([name, definition]) => [name, sanitizeDefinition(definition)]));
3720
- }
3722
+ Object.assign(result, sanitizeSchemaDefinitions(schema));
3721
3723
  if (schema.type === "object" || schema.properties != null) {
3722
3724
  if (schema.properties != null) result.properties = Object.fromEntries(Object.entries(schema.properties).map(([name, definition]) => [name, sanitizeDefinition(definition)]));
3723
3725
  result.additionalProperties = false;
@@ -3729,6 +3731,14 @@ function sanitizeSchema(schema) {
3729
3731
  if (constraintDescription != null) result.description = result.description == null ? constraintDescription : `${result.description}\n${constraintDescription}`;
3730
3732
  return result;
3731
3733
  }
3734
+ function sanitizeSchemaDefinitions(schema) {
3735
+ const { $defs } = schema;
3736
+ const sanitizeAll = (definitions) => Object.fromEntries(Object.entries(definitions).map(([name, definition]) => [name, sanitizeDefinition(definition)]));
3737
+ return {
3738
+ ...schema.definitions != null && { definitions: sanitizeAll(schema.definitions) },
3739
+ ...$defs != null && { $defs: sanitizeAll($defs) }
3740
+ };
3741
+ }
3732
3742
  function getConstraintDescription(schema) {
3733
3743
  const descriptions = DESCRIPTION_CONSTRAINT_KEYS.flatMap((key) => {
3734
3744
  const value = schema[key];
@@ -3746,6 +3756,155 @@ function formatConstraintValue(value) {
3746
3756
  return JSON.stringify(value);
3747
3757
  }
3748
3758
  //#endregion
3759
+ //#region src/has-circular-schema-reference.ts
3760
+ const SCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set([
3761
+ "dependentSchemas",
3762
+ "patternProperties",
3763
+ "properties"
3764
+ ]);
3765
+ const DATA_KEYWORDS = /* @__PURE__ */ new Set([
3766
+ "const",
3767
+ "default",
3768
+ "enum",
3769
+ "examples"
3770
+ ]);
3771
+ /**
3772
+ * Whether a JSON schema contains a cycle of local `$ref`s, e.g. a tree node
3773
+ * whose children reference the node itself.
3774
+ *
3775
+ * Anthropic's native structured outputs reject such schemas, while the JSON
3776
+ * response tool accepts them.
3777
+ */
3778
+ function hasCircularSchemaReference(schema) {
3779
+ const visiting = /* @__PURE__ */ new Set();
3780
+ const visited = /* @__PURE__ */ new Set();
3781
+ const visit = (pointer) => {
3782
+ if (visiting.has(pointer)) return true;
3783
+ if (visited.has(pointer)) return false;
3784
+ const target = resolveSchemaPointer(schema, pointer);
3785
+ if (target === void 0) return false;
3786
+ visiting.add(pointer);
3787
+ const isCircular = collectLocalRefs(target).some(visit);
3788
+ visiting.delete(pointer);
3789
+ visited.add(pointer);
3790
+ return isCircular;
3791
+ };
3792
+ return visit("#");
3793
+ }
3794
+ function collectLocalRefs(node, refs = []) {
3795
+ if (Array.isArray(node)) {
3796
+ for (const item of node) collectLocalRefs(item, refs);
3797
+ return refs;
3798
+ }
3799
+ if (!isRecord(node)) return refs;
3800
+ for (const [key, value] of Object.entries(node)) if (key === "$ref") {
3801
+ if (typeof value === "string" && value.startsWith("#")) refs.push(value);
3802
+ } else if (SCHEMA_MAP_KEYWORDS.has(key) && isRecord(value)) for (const subschema of Object.values(value)) collectLocalRefs(subschema, refs);
3803
+ else if (key !== "$defs" && key !== "definitions" && !DATA_KEYWORDS.has(key)) collectLocalRefs(value, refs);
3804
+ return refs;
3805
+ }
3806
+ function resolveSchemaPointer(schema, pointer) {
3807
+ if (pointer === "#") return schema;
3808
+ if (!pointer.startsWith("#/")) return;
3809
+ let decodedPointer;
3810
+ try {
3811
+ decodedPointer = decodeURIComponent(pointer.slice(2));
3812
+ } catch {
3813
+ return;
3814
+ }
3815
+ let current = schema;
3816
+ for (const rawSegment of decodedPointer.split("/")) {
3817
+ const segment = rawSegment.replace(/~1/g, "/").replace(/~0/g, "~");
3818
+ if (Array.isArray(current)) current = current[Number(segment)];
3819
+ else if (isRecord(current)) current = current[segment];
3820
+ else return;
3821
+ }
3822
+ return current;
3823
+ }
3824
+ //#endregion
3825
+ //#region src/supports-native-structured-output-schema.ts
3826
+ const MAX_OPTIONAL_PROPERTIES = 10;
3827
+ const SUBSCHEMA_KEYWORDS = [
3828
+ "additionalProperties",
3829
+ "contains",
3830
+ "else",
3831
+ "if",
3832
+ "items",
3833
+ "not",
3834
+ "then"
3835
+ ];
3836
+ const SUBSCHEMA_LIST_KEYWORDS = [
3837
+ "allOf",
3838
+ "anyOf",
3839
+ "oneOf",
3840
+ "prefixItems"
3841
+ ];
3842
+ const SUBSCHEMA_MAP_KEYWORDS = [
3843
+ "dependentSchemas",
3844
+ "patternProperties",
3845
+ "properties"
3846
+ ];
3847
+ /**
3848
+ * Whether Anthropic's native structured outputs (`output_config.format`) can
3849
+ * represent a schema without rejecting it or losing data.
3850
+ *
3851
+ * Rejected: self-referencing schemas, and schemas with too many optional
3852
+ * properties. Lossy: open objects (maps, free-form objects), which native
3853
+ * structured outputs close with `additionalProperties: false`, so the model
3854
+ * can only return `{}` for them.
3855
+ */
3856
+ function supportsNativeStructuredOutputSchema(schema) {
3857
+ if (hasCircularSchemaReference(schema)) return false;
3858
+ const { optionalProperties, hasOpenObject } = getSchemaStats(schema, schema, /* @__PURE__ */ new Map());
3859
+ return !hasOpenObject && optionalProperties <= MAX_OPTIONAL_PROPERTIES;
3860
+ }
3861
+ function getSchemaStats(node, root, refStats) {
3862
+ const stats = {
3863
+ optionalProperties: 0,
3864
+ hasOpenObject: false
3865
+ };
3866
+ if (!isRecord(node)) return stats;
3867
+ const add = (child) => {
3868
+ const childStats = getSchemaStats(child, root, refStats);
3869
+ stats.optionalProperties += childStats.optionalProperties;
3870
+ stats.hasOpenObject ||= childStats.hasOpenObject;
3871
+ };
3872
+ if (typeof node.$ref === "string" && node.$ref.startsWith("#")) {
3873
+ let resolved = refStats.get(node.$ref);
3874
+ if (resolved == null) {
3875
+ resolved = getSchemaStats(resolveSchemaPointer(root, node.$ref), root, refStats);
3876
+ refStats.set(node.$ref, resolved);
3877
+ }
3878
+ stats.optionalProperties += resolved.optionalProperties;
3879
+ stats.hasOpenObject ||= resolved.hasOpenObject;
3880
+ }
3881
+ if (isOpenObject(node)) stats.hasOpenObject = true;
3882
+ if (isRecord(node.properties)) {
3883
+ const required = new Set(Array.isArray(node.required) ? node.required : []);
3884
+ stats.optionalProperties += Object.keys(node.properties).filter((name) => !required.has(name)).length;
3885
+ }
3886
+ for (const keyword of SUBSCHEMA_KEYWORDS) {
3887
+ const value = node[keyword];
3888
+ if (Array.isArray(value)) value.forEach(add);
3889
+ else add(value);
3890
+ }
3891
+ for (const keyword of SUBSCHEMA_LIST_KEYWORDS) {
3892
+ const value = node[keyword];
3893
+ if (Array.isArray(value)) value.forEach(add);
3894
+ }
3895
+ for (const keyword of SUBSCHEMA_MAP_KEYWORDS) {
3896
+ const value = node[keyword];
3897
+ if (isRecord(value)) Object.values(value).forEach(add);
3898
+ }
3899
+ return stats;
3900
+ }
3901
+ function isOpenObject(node) {
3902
+ const { additionalProperties, patternProperties, properties, type } = node;
3903
+ if (additionalProperties === true || isRecord(additionalProperties)) return true;
3904
+ if (isRecord(patternProperties) && Object.keys(patternProperties).length > 0) return true;
3905
+ return (type === "object" || Array.isArray(type) && type.includes("object")) && properties == null && additionalProperties !== false;
3906
+ }
3907
+ //#endregion
3749
3908
  //#region src/anthropic-language-model.ts
3750
3909
  function createAnthropicStreamError(error) {
3751
3910
  const inferredMetadata = getAnthropicStreamErrorMetadata(error.type);
@@ -3864,6 +4023,28 @@ function getProviderOptionsName(provider) {
3864
4023
  const dotIndex = provider.indexOf(".");
3865
4024
  return dotIndex === -1 ? provider : provider.substring(0, dotIndex);
3866
4025
  }
4026
+ const TEXT_OR_THINKING_BLOCK_TYPES = /* @__PURE__ */ new Set([
4027
+ "redacted_thinking",
4028
+ "text",
4029
+ "thinking"
4030
+ ]);
4031
+ function isContinuationStopReason(stopReason) {
4032
+ return stopReason === "pause_turn" || stopReason === "tool_use";
4033
+ }
4034
+ /**
4035
+ * Text parts to return when the JSON response tool is in use: the text after
4036
+ * the last tool call or result, and only if the tool was never called.
4037
+ */
4038
+ function getJsonResponseToolFallbackText(content, stopReason) {
4039
+ const text = /* @__PURE__ */ new Set();
4040
+ if (isContinuationStopReason(stopReason)) return text;
4041
+ for (const part of content) {
4042
+ if (part.type === "tool_use" && part.name === "json") return /* @__PURE__ */ new Set();
4043
+ if (part.type === "text") text.add(part);
4044
+ else if (!TEXT_OR_THINKING_BLOCK_TYPES.has(part.type)) text.clear();
4045
+ }
4046
+ return text;
4047
+ }
3867
4048
  var AnthropicLanguageModel = class AnthropicLanguageModel {
3868
4049
  static [WORKFLOW_SERIALIZE](model) {
3869
4050
  return serializeModelOptions({
@@ -3974,10 +4155,11 @@ var AnthropicLanguageModel = class AnthropicLanguageModel {
3974
4155
  }
3975
4156
  const isAnthropicModel = isKnownModel || modelId.includes("claude-");
3976
4157
  const supportsStructuredOutput = (config.supportsNativeStructuredOutput ?? true) && modelSupportsStructuredOutput;
4158
+ const supportsResponseSchema = responseFormat?.type !== "json" || responseFormat.schema == null || supportsNativeStructuredOutputSchema(responseFormat.schema);
3977
4159
  const supportsStrictTools = (config.supportsStrictTools ?? true) && modelSupportsStructuredOutput;
3978
4160
  const structureOutputMode = anthropicOptions?.structuredOutputMode ?? "auto";
3979
- let useStructuredOutput = structureOutputMode === "outputFormat" || structureOutputMode === "auto" && supportsStructuredOutput;
3980
- if (!useStructuredOutput && rejectsForcedToolUse && supportsStructuredOutput && responseFormat?.type === "json" && responseFormat.schema != null) {
4161
+ let useStructuredOutput = structureOutputMode === "outputFormat" || structureOutputMode === "auto" && supportsStructuredOutput && supportsResponseSchema;
4162
+ if (!useStructuredOutput && rejectsForcedToolUse && modelSupportsStructuredOutput && responseFormat?.type === "json" && responseFormat.schema != null && supportsNativeStructuredOutputSchema(responseFormat.schema)) {
3981
4163
  warnings.push({
3982
4164
  type: "unsupported",
3983
4165
  feature: "providerOptions.anthropic.structuredOutputMode",
@@ -4276,7 +4458,7 @@ var AnthropicLanguageModel = class AnthropicLanguageModel {
4276
4458
  else if (anthropicOptions?.fallbacks && anthropicOptions.fallbacks.length > 0) betas.add("server-side-fallback-2026-06-01");
4277
4459
  const defaultEagerInputStreaming = stream && (anthropicOptions?.toolStreaming ?? true);
4278
4460
  const { tools: anthropicTools, toolChoice: anthropicToolChoice, toolWarnings, betas: toolsBetas } = await prepareTools(jsonResponseTool != null ? {
4279
- tools: [...tools ?? [], jsonResponseTool],
4461
+ tools: [...(tools ?? []).filter((tool) => toolChoice?.type !== "none" && (toolChoice?.type !== "tool" || tool.name === toolChoice.toolName)), jsonResponseTool],
4280
4462
  toolChoice: { type: "required" },
4281
4463
  disableParallelToolUse: true,
4282
4464
  cacheControlValidator,
@@ -4384,9 +4566,10 @@ var AnthropicLanguageModel = class AnthropicLanguageModel {
4384
4566
  const serverToolCalls = {};
4385
4567
  let isJsonResponseFromTool = false;
4386
4568
  const hasWebSearchResults = response.content.some((part) => part.type === "web_search_tool_result" && Array.isArray(part.content) && part.content.length > 0);
4569
+ const jsonResponseToolFallbackText = usesJsonResponseTool ? getJsonResponseToolFallbackText(response.content, response.stop_reason) : void 0;
4387
4570
  for (const part of response.content) switch (part.type) {
4388
4571
  case "text":
4389
- if (!usesJsonResponseTool) {
4572
+ if (jsonResponseToolFallbackText == null || jsonResponseToolFallbackText.has(part)) {
4390
4573
  const citations = part.citations ?? [];
4391
4574
  content.push({
4392
4575
  type: "text",
@@ -4824,6 +5007,16 @@ var AnthropicLanguageModel = class AnthropicLanguageModel {
4824
5007
  let safeguardResults;
4825
5008
  let container = null;
4826
5009
  let isJsonResponseFromTool = false;
5010
+ const heldBackText = [];
5011
+ const heldBackTextByIndex = /* @__PURE__ */ new Map();
5012
+ const createTextEnd = (id, citations) => ({
5013
+ type: "text-end",
5014
+ id,
5015
+ ...citations.length > 0 && {
5016
+ citations: citations.map((citation) => mapAnthropicCitation(citation, citationDocuments)),
5017
+ providerMetadata: { anthropic: { citations } }
5018
+ }
5019
+ });
4827
5020
  let hasWebSearchResults = false;
4828
5021
  const fallbackWebCitations = [];
4829
5022
  let isMessageOpen = false;
@@ -4870,9 +5063,19 @@ var AnthropicLanguageModel = class AnthropicLanguageModel {
4870
5063
  return;
4871
5064
  }
4872
5065
  blockType = contentBlockType;
5066
+ if (!TEXT_OR_THINKING_BLOCK_TYPES.has(contentBlockType)) heldBackText.length = 0;
4873
5067
  switch (contentBlockType) {
4874
5068
  case "text":
4875
- if (usesJsonResponseTool) return;
5069
+ if (usesJsonResponseTool) {
5070
+ const entry = {
5071
+ id: String(value.index),
5072
+ text: "",
5073
+ citations: []
5074
+ };
5075
+ heldBackText.push(entry);
5076
+ heldBackTextByIndex.set(value.index, entry);
5077
+ return;
5078
+ }
4876
5079
  contentBlocks[value.index] = {
4877
5080
  type: "text",
4878
5081
  citations: []
@@ -5258,14 +5461,7 @@ var AnthropicLanguageModel = class AnthropicLanguageModel {
5258
5461
  const contentBlock = contentBlocks[value.index];
5259
5462
  switch (contentBlock.type) {
5260
5463
  case "text":
5261
- controller.enqueue({
5262
- type: "text-end",
5263
- id: String(value.index),
5264
- ...contentBlock.citations.length > 0 && {
5265
- citations: contentBlock.citations.map((citation) => mapAnthropicCitation(citation, citationDocuments)),
5266
- providerMetadata: { anthropic: { citations: contentBlock.citations } }
5267
- }
5268
- });
5464
+ controller.enqueue(createTextEnd(String(value.index), contentBlock.citations));
5269
5465
  break;
5270
5466
  case "reasoning":
5271
5467
  controller.enqueue({
@@ -5325,7 +5521,11 @@ var AnthropicLanguageModel = class AnthropicLanguageModel {
5325
5521
  const deltaType = value.delta.type;
5326
5522
  switch (deltaType) {
5327
5523
  case "text_delta":
5328
- if (usesJsonResponseTool) return;
5524
+ if (usesJsonResponseTool) {
5525
+ const entry = heldBackTextByIndex.get(value.index);
5526
+ if (entry != null) entry.text += value.delta.text;
5527
+ return;
5528
+ }
5329
5529
  controller.enqueue({
5330
5530
  type: "text-delta",
5331
5531
  id: String(value.index),
@@ -5386,6 +5586,7 @@ var AnthropicLanguageModel = class AnthropicLanguageModel {
5386
5586
  const citation = value.delta.citation;
5387
5587
  const contentBlock = contentBlocks[value.index];
5388
5588
  if (contentBlock?.type === "text") contentBlock.citations.push(citation);
5589
+ heldBackTextByIndex.get(value.index)?.citations.push(citation);
5389
5590
  if (citation.type === "web_search_result_location") fallbackWebCitations.push(citation);
5390
5591
  else {
5391
5592
  const source = createCitationSource(citation, citationDocuments, generateId);
@@ -5411,6 +5612,7 @@ var AnthropicLanguageModel = class AnthropicLanguageModel {
5411
5612
  }
5412
5613
  isMessageOpen = true;
5413
5614
  activeMessageId = value.message.id;
5615
+ heldBackTextByIndex.clear();
5414
5616
  usage.input_tokens = value.message.usage.input_tokens;
5415
5617
  usage.cache_read_input_tokens = value.message.usage.cache_read_input_tokens ?? 0;
5416
5618
  usage.cache_creation_input_tokens = value.message.usage.cache_creation_input_tokens ?? 0;
@@ -5531,6 +5733,20 @@ var AnthropicLanguageModel = class AnthropicLanguageModel {
5531
5733
  if (source) controller.enqueue(source);
5532
5734
  }
5533
5735
  fallbackWebCitations.length = 0;
5736
+ if (!isJsonResponseFromTool && !isContinuationStopReason(finishReason.raw)) for (const { id, text, citations } of heldBackText) {
5737
+ if (text.length === 0) continue;
5738
+ controller.enqueue({
5739
+ type: "text-start",
5740
+ id
5741
+ });
5742
+ controller.enqueue({
5743
+ type: "text-delta",
5744
+ id,
5745
+ delta: text
5746
+ });
5747
+ controller.enqueue(createTextEnd(id, citations));
5748
+ }
5749
+ heldBackText.length = 0;
5534
5750
  controller.enqueue({
5535
5751
  type: "finish",
5536
5752
  finishReason,
@@ -7133,7 +7349,7 @@ var AnthropicSkills = class {
7133
7349
  };
7134
7350
  //#endregion
7135
7351
  //#region src/version.ts
7136
- const VERSION = "4.0.93";
7352
+ const VERSION = "4.0.95";
7137
7353
  //#endregion
7138
7354
  //#region src/anthropic-provider.ts
7139
7355
  const ANTHROPIC_API_URL = "https://api.anthropic.com";