@librechat/agents 3.2.63 → 3.2.65

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.
Files changed (67) hide show
  1. package/dist/cjs/graphs/Graph.cjs +3 -0
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/llm/anthropic/index.cjs +73 -9
  4. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  5. package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
  6. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +41 -9
  7. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  8. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +3 -1
  9. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
  10. package/dist/cjs/llm/anthropic/utils/stream_events.cjs +337 -0
  11. package/dist/cjs/llm/anthropic/utils/stream_events.cjs.map +1 -0
  12. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +82 -34
  13. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
  14. package/dist/cjs/tools/search/crw-scraper.cjs +165 -0
  15. package/dist/cjs/tools/search/crw-scraper.cjs.map +1 -0
  16. package/dist/cjs/tools/search/crw-search.cjs +105 -0
  17. package/dist/cjs/tools/search/crw-search.cjs.map +1 -0
  18. package/dist/cjs/tools/search/search.cjs +4 -2
  19. package/dist/cjs/tools/search/search.cjs.map +1 -1
  20. package/dist/cjs/tools/search/tool.cjs +15 -3
  21. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  22. package/dist/esm/graphs/Graph.mjs +3 -0
  23. package/dist/esm/graphs/Graph.mjs.map +1 -1
  24. package/dist/esm/llm/anthropic/index.mjs +73 -9
  25. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  26. package/dist/esm/llm/anthropic/types.mjs.map +1 -1
  27. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +41 -9
  28. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  29. package/dist/esm/llm/anthropic/utils/message_outputs.mjs +3 -2
  30. package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
  31. package/dist/esm/llm/anthropic/utils/stream_events.mjs +337 -0
  32. package/dist/esm/llm/anthropic/utils/stream_events.mjs.map +1 -0
  33. package/dist/esm/llm/bedrock/utils/message_inputs.mjs +82 -34
  34. package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
  35. package/dist/esm/tools/search/crw-scraper.mjs +163 -0
  36. package/dist/esm/tools/search/crw-scraper.mjs.map +1 -0
  37. package/dist/esm/tools/search/crw-search.mjs +103 -0
  38. package/dist/esm/tools/search/crw-search.mjs.map +1 -0
  39. package/dist/esm/tools/search/search.mjs +4 -2
  40. package/dist/esm/tools/search/search.mjs.map +1 -1
  41. package/dist/esm/tools/search/tool.mjs +15 -3
  42. package/dist/esm/tools/search/tool.mjs.map +1 -1
  43. package/dist/types/llm/anthropic/index.d.ts +2 -0
  44. package/dist/types/llm/anthropic/types.d.ts +2 -0
  45. package/dist/types/llm/anthropic/utils/message_outputs.d.ts +1 -2
  46. package/dist/types/llm/anthropic/utils/stream_events.d.ts +25 -0
  47. package/dist/types/tools/search/crw-scraper.d.ts +41 -0
  48. package/dist/types/tools/search/crw-search.d.ts +4 -0
  49. package/dist/types/tools/search/types.d.ts +88 -3
  50. package/package.json +1 -1
  51. package/src/graphs/Graph.ts +15 -0
  52. package/src/llm/anthropic/index.ts +134 -10
  53. package/src/llm/anthropic/inherited-content-utils.spec.ts +10 -5
  54. package/src/llm/anthropic/inherited-stream-events.spec.ts +513 -9
  55. package/src/llm/anthropic/llm.spec.ts +100 -16
  56. package/src/llm/anthropic/types.ts +3 -0
  57. package/src/llm/anthropic/utils/message_inputs.ts +60 -3
  58. package/src/llm/anthropic/utils/message_outputs.ts +10 -2
  59. package/src/llm/anthropic/utils/stream_events.ts +471 -0
  60. package/src/llm/bedrock/utils/message_inputs.test.ts +276 -1
  61. package/src/llm/bedrock/utils/message_inputs.ts +121 -73
  62. package/src/tools/search/crw-scraper.ts +244 -0
  63. package/src/tools/search/crw-search.ts +167 -0
  64. package/src/tools/search/crw.test.ts +836 -0
  65. package/src/tools/search/search.ts +7 -1
  66. package/src/tools/search/tool.ts +23 -3
  67. package/src/tools/search/types.ts +103 -3
@@ -961,7 +961,7 @@ class RecordingStreamingAnthropic extends ChatAnthropic {
961
961
  }
962
962
  }
963
963
 
964
- test('Anthropic message_delta usage emits only output token totals', () => {
964
+ test('Anthropic message_delta usage preserves cumulative input totals', () => {
965
965
  const event: AnthropicStreamEvent = {
966
966
  type: 'message_delta',
967
967
  context_management: null,
@@ -978,6 +978,7 @@ test('Anthropic message_delta usage emits only output token totals', () => {
978
978
  cache_read_input_tokens: 13,
979
979
  server_tool_use: null,
980
980
  iterations: null,
981
+ output_tokens_details: null,
981
982
  },
982
983
  };
983
984
 
@@ -987,9 +988,13 @@ test('Anthropic message_delta usage emits only output token totals', () => {
987
988
  });
988
989
 
989
990
  expect(result?.chunk.usage_metadata).toEqual({
990
- input_tokens: 0,
991
+ input_tokens: 267,
991
992
  output_tokens: 375,
992
- total_tokens: 375,
993
+ total_tokens: 642,
994
+ input_token_details: {
995
+ cache_creation: 11,
996
+ cache_read: 13,
997
+ },
993
998
  });
994
999
  });
995
1000
 
@@ -1002,6 +1007,7 @@ test('Anthropic stream usage does not double-count cumulative input tokens', asy
1002
1007
  container: null,
1003
1008
  context_management: null,
1004
1009
  content: [],
1010
+ diagnostics: null,
1005
1011
  model: modelName,
1006
1012
  role: 'assistant',
1007
1013
  stop_details: null,
@@ -1010,15 +1016,16 @@ test('Anthropic stream usage does not double-count cumulative input tokens', asy
1010
1016
  type: 'message',
1011
1017
  usage: {
1012
1018
  cache_creation: null,
1013
- cache_creation_input_tokens: 0,
1014
- cache_read_input_tokens: 0,
1019
+ cache_creation_input_tokens: 20,
1020
+ cache_read_input_tokens: 30,
1015
1021
  inference_geo: null,
1016
1022
  input_tokens: 243,
1017
1023
  iterations: null,
1018
- output_tokens: 0,
1024
+ output_tokens: 7,
1019
1025
  server_tool_use: null,
1020
1026
  service_tier: null,
1021
1027
  speed: null,
1028
+ output_tokens_details: null,
1022
1029
  },
1023
1030
  },
1024
1031
  },
@@ -1034,10 +1041,11 @@ test('Anthropic stream usage does not double-count cumulative input tokens', asy
1034
1041
  usage: {
1035
1042
  input_tokens: 243,
1036
1043
  output_tokens: 375,
1037
- cache_creation_input_tokens: 0,
1038
- cache_read_input_tokens: 0,
1044
+ cache_creation_input_tokens: 20,
1045
+ cache_read_input_tokens: 30,
1039
1046
  server_tool_use: null,
1040
1047
  iterations: null,
1048
+ output_tokens_details: null,
1041
1049
  },
1042
1050
  },
1043
1051
  { type: 'message_stop' },
@@ -1050,12 +1058,83 @@ test('Anthropic stream usage does not double-count cumulative input tokens', asy
1050
1058
  }
1051
1059
 
1052
1060
  expect(full?.usage_metadata).toEqual({
1053
- input_tokens: 243,
1061
+ input_tokens: 293,
1054
1062
  output_tokens: 375,
1055
- total_tokens: 618,
1063
+ total_tokens: 668,
1056
1064
  input_token_details: {
1057
- cache_creation: 0,
1058
- cache_read: 0,
1065
+ cache_creation: 20,
1066
+ cache_read: 30,
1067
+ },
1068
+ output_token_details: {},
1069
+ });
1070
+ });
1071
+
1072
+ test('Anthropic stream usage accepts input first reported at message_delta', async () => {
1073
+ const events: AnthropicStreamEvent[] = [
1074
+ {
1075
+ type: 'message_start',
1076
+ message: {
1077
+ id: 'msg_late_input_usage',
1078
+ container: null,
1079
+ context_management: null,
1080
+ content: [],
1081
+ diagnostics: null,
1082
+ model: modelName,
1083
+ role: 'assistant',
1084
+ stop_details: null,
1085
+ stop_reason: null,
1086
+ stop_sequence: null,
1087
+ type: 'message',
1088
+ usage: {
1089
+ cache_creation: null,
1090
+ cache_creation_input_tokens: 0,
1091
+ cache_read_input_tokens: 0,
1092
+ inference_geo: null,
1093
+ input_tokens: 0,
1094
+ iterations: null,
1095
+ output_tokens: 0,
1096
+ server_tool_use: null,
1097
+ service_tier: null,
1098
+ speed: null,
1099
+ output_tokens_details: null,
1100
+ },
1101
+ },
1102
+ },
1103
+ {
1104
+ type: 'message_delta',
1105
+ context_management: null,
1106
+ delta: {
1107
+ container: null,
1108
+ stop_details: null,
1109
+ stop_reason: 'end_turn',
1110
+ stop_sequence: null,
1111
+ },
1112
+ usage: {
1113
+ input_tokens: 100,
1114
+ output_tokens: 42,
1115
+ cache_creation_input_tokens: 500,
1116
+ cache_read_input_tokens: 200,
1117
+ server_tool_use: null,
1118
+ iterations: null,
1119
+ output_tokens_details: null,
1120
+ },
1121
+ },
1122
+ { type: 'message_stop' },
1123
+ ];
1124
+ const model = new MockStreamingAnthropic(events);
1125
+
1126
+ let full: AIMessageChunk | undefined;
1127
+ for await (const chunk of await model.stream('hello')) {
1128
+ full = !full ? chunk : concat(full, chunk);
1129
+ }
1130
+
1131
+ expect(full?.usage_metadata).toEqual({
1132
+ input_tokens: 800,
1133
+ output_tokens: 42,
1134
+ total_tokens: 842,
1135
+ input_token_details: {
1136
+ cache_creation: 500,
1137
+ cache_read: 200,
1059
1138
  },
1060
1139
  output_token_details: {},
1061
1140
  });
@@ -1070,6 +1149,7 @@ test('Anthropic stream usage handles multiple cumulative message_delta events',
1070
1149
  container: null,
1071
1150
  context_management: null,
1072
1151
  content: [],
1152
+ diagnostics: null,
1073
1153
  model: modelName,
1074
1154
  role: 'assistant',
1075
1155
  stop_details: null,
@@ -1083,10 +1163,11 @@ test('Anthropic stream usage handles multiple cumulative message_delta events',
1083
1163
  inference_geo: null,
1084
1164
  input_tokens: 243,
1085
1165
  iterations: null,
1086
- output_tokens: 0,
1166
+ output_tokens: 7,
1087
1167
  server_tool_use: null,
1088
1168
  service_tier: null,
1089
1169
  speed: null,
1170
+ output_tokens_details: null,
1090
1171
  },
1091
1172
  },
1092
1173
  },
@@ -1106,6 +1187,7 @@ test('Anthropic stream usage handles multiple cumulative message_delta events',
1106
1187
  cache_read_input_tokens: 0,
1107
1188
  server_tool_use: null,
1108
1189
  iterations: null,
1190
+ output_tokens_details: null,
1109
1191
  },
1110
1192
  },
1111
1193
  {
@@ -1124,6 +1206,7 @@ test('Anthropic stream usage handles multiple cumulative message_delta events',
1124
1206
  cache_read_input_tokens: 0,
1125
1207
  server_tool_use: null,
1126
1208
  iterations: null,
1209
+ output_tokens_details: null,
1127
1210
  },
1128
1211
  },
1129
1212
  { type: 'message_stop' },
@@ -1230,9 +1313,10 @@ test('Anthropic live stream usage matches raw cumulative output snapshots', asyn
1230
1313
  expect(model.messageDeltaOutputTokens.length).toBeGreaterThan(0);
1231
1314
  const rawOutputTokens =
1232
1315
  model.messageDeltaOutputTokens[model.messageDeltaOutputTokens.length - 1];
1233
- expect(full?.usage_metadata?.output_tokens).toBe(
1234
- model.messageStartOutputTokens + rawOutputTokens
1316
+ expect(rawOutputTokens).toBeGreaterThanOrEqual(
1317
+ model.messageStartOutputTokens
1235
1318
  );
1319
+ expect(full?.usage_metadata?.output_tokens).toBe(rawOutputTokens);
1236
1320
  expect(full?.usage_metadata?.total_tokens).toBe(
1237
1321
  (full?.usage_metadata?.input_tokens ?? 0) +
1238
1322
  (full?.usage_metadata?.output_tokens ?? 0)
@@ -1244,7 +1328,7 @@ test('Anthropic live stream usage matches raw cumulative output snapshots', asyn
1244
1328
  0
1245
1329
  );
1246
1330
  expect(full?.usage_metadata?.output_tokens).toBeLessThan(
1247
- model.messageStartOutputTokens + summedOutputTokens
1331
+ summedOutputTokens
1248
1332
  );
1249
1333
  }
1250
1334
  });
@@ -61,6 +61,9 @@ export type AnthropicSearchResultBlockParam =
61
61
  Anthropic.Beta.BetaSearchResultBlockParam;
62
62
  export type AnthropicCompactionBlockParam =
63
63
  Anthropic.Beta.BetaCompactionBlockParam;
64
+ export type AnthropicCompactionBlock = Anthropic.Beta.BetaCompactionBlock;
65
+ export type AnthropicCompactionContentBlockDelta =
66
+ Anthropic.Beta.BetaCompactionContentBlockDelta;
64
67
  export type AnthropicOutputConfig = Anthropic.Messages.OutputConfig;
65
68
  export type ChatAnthropicOutputFormat = Anthropic.Messages.JSONOutputFormat;
66
69
 
@@ -482,8 +482,8 @@ function _formatContent(message: BaseMessage) {
482
482
  const contentBlocks = contentParts.map((contentPart) => {
483
483
  /**
484
484
  * Normalize server_tool_use blocks into a clean shape the API accepts.
485
- * These blocks may arrive with the correct type (server_tool_use) or mislabeled
486
- * as text/tool_use after chunk concatenation or state serialization.
485
+ * These blocks may arrive with the correct type (server_tool_use), as a
486
+ * standardized server_tool_call, or mislabeled after state serialization.
487
487
  * Regardless of current type, if the id starts with 'srvtoolu_' we rebuild
488
488
  * a clean block with only the properties the API expects.
489
489
  */
@@ -496,7 +496,7 @@ function _formatContent(message: BaseMessage) {
496
496
  'name' in contentPart
497
497
  ) {
498
498
  const rawPart = contentPart as Record<string, unknown>;
499
- let input = rawPart.input;
499
+ let input = rawPart.input ?? rawPart.args;
500
500
  if (typeof input === 'string') {
501
501
  try {
502
502
  input = JSON.parse(input);
@@ -549,6 +549,60 @@ function _formatContent(message: BaseMessage) {
549
549
  return null;
550
550
  }
551
551
 
552
+ /**
553
+ * Native ChatModelStream output standardizes client tool uses as
554
+ * `tool_call` blocks. Convert those blocks back to Anthropic's wire shape
555
+ * before the generic content formatter sees them.
556
+ */
557
+ if (
558
+ contentPart.type === 'tool_call' &&
559
+ 'id' in contentPart &&
560
+ typeof contentPart.id === 'string' &&
561
+ 'name' in contentPart &&
562
+ typeof contentPart.name === 'string' &&
563
+ 'args' in contentPart
564
+ ) {
565
+ let args = contentPart.args;
566
+ if (typeof args === 'string') {
567
+ try {
568
+ args = JSON.parse(args);
569
+ } catch {
570
+ args = {};
571
+ }
572
+ }
573
+ if (args == null || typeof args !== 'object' || Array.isArray(args)) {
574
+ args = {};
575
+ }
576
+ return _convertLangChainToolCallToAnthropic({
577
+ id: contentPart.id,
578
+ name: contentPart.name,
579
+ args: args as Record<string, unknown>,
580
+ });
581
+ }
582
+
583
+ /**
584
+ * Native Anthropic thinking is exposed through the standard reasoning
585
+ * stream, but its signature makes it safe and necessary to round-trip.
586
+ * Keep unsigned or cross-provider reasoning on the existing drop path.
587
+ */
588
+ if (
589
+ contentPart.type === 'reasoning' &&
590
+ isAIMessage(message) &&
591
+ message.response_metadata.model_provider === 'anthropic' &&
592
+ 'reasoning' in contentPart &&
593
+ typeof contentPart.reasoning === 'string' &&
594
+ 'signature' in contentPart &&
595
+ typeof contentPart.signature === 'string' &&
596
+ contentPart.signature !== ''
597
+ ) {
598
+ const block: AnthropicThinkingBlockParam = {
599
+ type: 'thinking',
600
+ thinking: contentPart.reasoning,
601
+ signature: contentPart.signature,
602
+ };
603
+ return block;
604
+ }
605
+
552
606
  /**
553
607
  * Skip non-server malformed blocks that have tool fields mixed with text type.
554
608
  */
@@ -665,6 +719,9 @@ function _formatContent(message: BaseMessage) {
665
719
  const block: AnthropicCompactionBlockParam = {
666
720
  type: 'compaction' as const,
667
721
  content: compactionPart.content,
722
+ ...('encrypted_content' in compactionPart
723
+ ? { encrypted_content: compactionPart.encrypted_content }
724
+ : {}),
668
725
  ...(cacheControl != null ? { cache_control: cacheControl } : {}),
669
726
  };
670
727
  return block;
@@ -9,7 +9,7 @@ import type { MessageContentComplex } from '@/types';
9
9
  import { toLangChainContent } from '@/messages/langchain';
10
10
  import { extractToolCalls } from './output_parsers';
11
11
 
12
- interface AnthropicUsageData {
12
+ export interface AnthropicUsageData {
13
13
  input_tokens?: number | null;
14
14
  output_tokens?: number | null;
15
15
  cache_creation_input_tokens?: number | null;
@@ -92,7 +92,15 @@ export function _makeMessageChunkFromAnthropicEvent(
92
92
  context_management: data.delta.context_management,
93
93
  });
94
94
  }
95
- const usageMetadata: UsageMetadata = {
95
+ const deltaUsage: AnthropicUsageData = data.usage;
96
+ const hasInputUsage =
97
+ deltaUsage.input_tokens != null ||
98
+ deltaUsage.cache_creation_input_tokens != null ||
99
+ deltaUsage.cache_read_input_tokens != null;
100
+ const cumulativeUsageMetadata = hasInputUsage
101
+ ? getAnthropicUsageMetadata(deltaUsage)
102
+ : undefined;
103
+ const usageMetadata: UsageMetadata = cumulativeUsageMetadata ?? {
96
104
  input_tokens: 0,
97
105
  output_tokens: data.usage.output_tokens,
98
106
  total_tokens: data.usage.output_tokens,