@librechat/agents 3.7.8 → 3.7.10

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 (161) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +3 -2
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/common/constants.cjs +2 -0
  4. package/dist/cjs/common/constants.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +40 -6
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/graphs/MultiAgentGraph.cjs +1 -1
  8. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  9. package/dist/cjs/hooks/executeHooks.cjs +8 -0
  10. package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
  11. package/dist/cjs/hooks/index.cjs +2 -0
  12. package/dist/cjs/hooks/index.cjs.map +1 -1
  13. package/dist/cjs/hooks/types.cjs +1 -0
  14. package/dist/cjs/hooks/types.cjs.map +1 -1
  15. package/dist/cjs/langfuse.cjs +43 -3
  16. package/dist/cjs/langfuse.cjs.map +1 -1
  17. package/dist/cjs/llm/invoke.cjs +2 -6
  18. package/dist/cjs/llm/invoke.cjs.map +1 -1
  19. package/dist/cjs/llm/request.cjs +6 -0
  20. package/dist/cjs/llm/request.cjs.map +1 -1
  21. package/dist/cjs/main.cjs +19 -11
  22. package/dist/cjs/messages/format.cjs +95 -18
  23. package/dist/cjs/messages/format.cjs.map +1 -1
  24. package/dist/cjs/messages/index.cjs +1 -1
  25. package/dist/cjs/run.cjs +201 -46
  26. package/dist/cjs/run.cjs.map +1 -1
  27. package/dist/cjs/session/AgentSession.cjs +1 -1
  28. package/dist/cjs/session/JsonlSessionStore.cjs +1 -1
  29. package/dist/cjs/summarization/index.cjs +1 -0
  30. package/dist/cjs/summarization/index.cjs.map +1 -1
  31. package/dist/cjs/summarization/node.cjs +24 -85
  32. package/dist/cjs/summarization/node.cjs.map +1 -1
  33. package/dist/cjs/summarization/semanticIndex.cjs +7 -3
  34. package/dist/cjs/summarization/semanticIndex.cjs.map +1 -1
  35. package/dist/cjs/summarization/shared.cjs +83 -0
  36. package/dist/cjs/summarization/shared.cjs.map +1 -0
  37. package/dist/cjs/tools/ToolNode.cjs +5 -5
  38. package/dist/cjs/tools/local/CompileCheckTool.cjs +1 -1
  39. package/dist/cjs/tools/local/LocalCodingTools.cjs +1 -1
  40. package/dist/cjs/tools/local/LocalExecutionEngine.cjs +1 -1
  41. package/dist/cjs/tools/runStepResume.cjs +1 -1
  42. package/dist/cjs/tools/runStepResume.cjs.map +1 -1
  43. package/dist/cjs/tools/search/metrics.cjs +234 -0
  44. package/dist/cjs/tools/search/metrics.cjs.map +1 -0
  45. package/dist/cjs/tools/search/rerankers.cjs +80 -68
  46. package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
  47. package/dist/cjs/tools/search/search.cjs +95 -45
  48. package/dist/cjs/tools/search/search.cjs.map +1 -1
  49. package/dist/cjs/tools/search/tool.cjs +77 -49
  50. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  51. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  52. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +8 -12
  53. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  54. package/dist/cjs/utils/tokens.cjs +8 -1
  55. package/dist/cjs/utils/tokens.cjs.map +1 -1
  56. package/dist/esm/agents/AgentContext.mjs +3 -2
  57. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  58. package/dist/esm/common/constants.mjs +2 -1
  59. package/dist/esm/common/constants.mjs.map +1 -1
  60. package/dist/esm/graphs/Graph.mjs +40 -6
  61. package/dist/esm/graphs/Graph.mjs.map +1 -1
  62. package/dist/esm/graphs/MultiAgentGraph.mjs +1 -1
  63. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  64. package/dist/esm/hooks/executeHooks.mjs +8 -1
  65. package/dist/esm/hooks/executeHooks.mjs.map +1 -1
  66. package/dist/esm/hooks/index.mjs +2 -1
  67. package/dist/esm/hooks/index.mjs.map +1 -1
  68. package/dist/esm/hooks/types.mjs +1 -0
  69. package/dist/esm/hooks/types.mjs.map +1 -1
  70. package/dist/esm/langfuse.mjs +43 -3
  71. package/dist/esm/langfuse.mjs.map +1 -1
  72. package/dist/esm/llm/invoke.mjs +2 -6
  73. package/dist/esm/llm/invoke.mjs.map +1 -1
  74. package/dist/esm/llm/request.mjs +6 -1
  75. package/dist/esm/llm/request.mjs.map +1 -1
  76. package/dist/esm/main.mjs +13 -12
  77. package/dist/esm/messages/format.mjs +96 -19
  78. package/dist/esm/messages/format.mjs.map +1 -1
  79. package/dist/esm/messages/index.mjs +1 -1
  80. package/dist/esm/run.mjs +201 -46
  81. package/dist/esm/run.mjs.map +1 -1
  82. package/dist/esm/session/AgentSession.mjs +1 -1
  83. package/dist/esm/session/JsonlSessionStore.mjs +1 -1
  84. package/dist/esm/summarization/index.mjs +1 -0
  85. package/dist/esm/summarization/index.mjs.map +1 -1
  86. package/dist/esm/summarization/node.mjs +21 -82
  87. package/dist/esm/summarization/node.mjs.map +1 -1
  88. package/dist/esm/summarization/semanticIndex.mjs +7 -4
  89. package/dist/esm/summarization/semanticIndex.mjs.map +1 -1
  90. package/dist/esm/summarization/shared.mjs +79 -0
  91. package/dist/esm/summarization/shared.mjs.map +1 -0
  92. package/dist/esm/tools/ToolNode.mjs +5 -5
  93. package/dist/esm/tools/local/CompileCheckTool.mjs +1 -1
  94. package/dist/esm/tools/local/LocalCodingTools.mjs +1 -1
  95. package/dist/esm/tools/local/LocalExecutionEngine.mjs +1 -1
  96. package/dist/esm/tools/runStepResume.mjs +1 -1
  97. package/dist/esm/tools/runStepResume.mjs.map +1 -1
  98. package/dist/esm/tools/search/metrics.mjs +234 -0
  99. package/dist/esm/tools/search/metrics.mjs.map +1 -0
  100. package/dist/esm/tools/search/rerankers.mjs +80 -68
  101. package/dist/esm/tools/search/rerankers.mjs.map +1 -1
  102. package/dist/esm/tools/search/search.mjs +96 -46
  103. package/dist/esm/tools/search/search.mjs.map +1 -1
  104. package/dist/esm/tools/search/tool.mjs +77 -49
  105. package/dist/esm/tools/search/tool.mjs.map +1 -1
  106. package/dist/esm/tools/search/utils.mjs.map +1 -1
  107. package/dist/esm/tools/subagent/SubagentExecutor.mjs +8 -12
  108. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  109. package/dist/esm/utils/tokens.mjs +8 -2
  110. package/dist/esm/utils/tokens.mjs.map +1 -1
  111. package/dist/types/common/constants.d.ts +7 -0
  112. package/dist/types/graphs/Graph.d.ts +9 -0
  113. package/dist/types/hooks/executeHooks.d.ts +5 -2
  114. package/dist/types/hooks/index.d.ts +7 -2
  115. package/dist/types/hooks/types.d.ts +45 -7
  116. package/dist/types/langfuse.d.ts +3 -1
  117. package/dist/types/llm/request.d.ts +10 -0
  118. package/dist/types/messages/format.d.ts +8 -2
  119. package/dist/types/run.d.ts +2 -1
  120. package/dist/types/summarization/index.d.ts +6 -0
  121. package/dist/types/summarization/node.d.ts +0 -4
  122. package/dist/types/summarization/semanticIndex.d.ts +2 -0
  123. package/dist/types/summarization/shared.d.ts +25 -0
  124. package/dist/types/tools/search/metrics.d.ts +15 -0
  125. package/dist/types/tools/search/rerankers.d.ts +30 -5
  126. package/dist/types/tools/search/tool.d.ts +7 -1
  127. package/dist/types/tools/search/types.d.ts +88 -4
  128. package/dist/types/tools/search/utils.d.ts +2 -10
  129. package/dist/types/types/run.d.ts +8 -0
  130. package/dist/types/types/stream.d.ts +6 -0
  131. package/dist/types/types/summarize.d.ts +6 -0
  132. package/dist/types/utils/tokens.d.ts +9 -0
  133. package/package.json +1 -1
  134. package/src/agents/AgentContext.ts +2 -5
  135. package/src/common/constants.ts +8 -0
  136. package/src/graphs/Graph.ts +45 -0
  137. package/src/hooks/HookRegistry.ts +3 -1
  138. package/src/hooks/executeHooks.ts +20 -2
  139. package/src/hooks/index.ts +12 -1
  140. package/src/hooks/types.ts +47 -4
  141. package/src/langfuse.ts +70 -0
  142. package/src/llm/invoke.ts +13 -29
  143. package/src/llm/request.ts +24 -0
  144. package/src/messages/format.ts +213 -27
  145. package/src/run.ts +366 -186
  146. package/src/summarization/index.ts +11 -0
  147. package/src/summarization/node.ts +117 -130
  148. package/src/summarization/semanticIndex.ts +16 -7
  149. package/src/summarization/shared.ts +130 -0
  150. package/src/tools/runStepResume.ts +9 -0
  151. package/src/tools/search/metrics.ts +400 -0
  152. package/src/tools/search/rerankers.ts +160 -97
  153. package/src/tools/search/search.ts +139 -56
  154. package/src/tools/search/tool.ts +126 -62
  155. package/src/tools/search/types.ts +104 -4
  156. package/src/tools/search/utils.ts +2 -10
  157. package/src/tools/subagent/SubagentExecutor.ts +4 -27
  158. package/src/types/run.ts +8 -0
  159. package/src/types/stream.ts +6 -0
  160. package/src/types/summarize.ts +7 -0
  161. package/src/utils/tokens.ts +31 -8
@@ -344,7 +344,9 @@ export interface JinaRerankerResult {
344
344
 
345
345
  export interface JinaRerankerResponse {
346
346
  model: string;
347
- usage: {
347
+ /** Telemetry only, and absent from some Jina-compatible endpoints — never
348
+ * dereference it on a path that would discard a usable ranking. */
349
+ usage?: {
348
350
  total_tokens: number;
349
351
  };
350
352
  results: JinaRerankerResult[];
@@ -358,12 +360,13 @@ export interface CohereRerankerResult {
358
360
  export interface CohereRerankerResponse {
359
361
  results: CohereRerankerResult[];
360
362
  id: string;
361
- meta: {
362
- api_version: {
363
+ /** Telemetry only; see {@link JinaRerankerResponse.usage}. */
364
+ meta?: {
365
+ api_version?: {
363
366
  version: string;
364
367
  is_experimental: boolean;
365
368
  };
366
- billed_units: {
369
+ billed_units?: {
367
370
  search_units: number;
368
371
  };
369
372
  };
@@ -407,6 +410,96 @@ export interface RagApiRerankResponse {
407
410
  export type SafeSearchLevel = 0 | 1 | 2;
408
411
 
409
412
  export type Logger = WinstonLogger;
413
+
414
+ /** Compact, redacted view of a thrown error, safe to hand to a logger. */
415
+ export interface SafeErrorLog {
416
+ message: string;
417
+ name?: string;
418
+ code?: string;
419
+ status?: number;
420
+ method?: string;
421
+ url?: string;
422
+ responseDataSummary?: string;
423
+ value?: string;
424
+ }
425
+
426
+ /** Why a rerank returned the candidates' original order instead of a ranking. */
427
+ export type RerankFallback =
428
+ | 'no_api_key'
429
+ | 'no_base_url'
430
+ | 'no_token_supplier'
431
+ | 'bad_response'
432
+ | 'invalid_results'
433
+ | 'chunk_error'
434
+ | 'placeholder'
435
+ | 'error';
436
+
437
+ /** One provider query. `results` is the row count that query contributed. */
438
+ export interface SearchObservation {
439
+ provider: string;
440
+ type: string;
441
+ results: number;
442
+ durationMs: number;
443
+ error?: string;
444
+ /** The query rejected rather than reporting failure in its response. Those
445
+ * were logged at error level before they were aggregated, so the summary
446
+ * has to carry the distinction to keep that severity. */
447
+ thrown?: boolean;
448
+ }
449
+
450
+ /** One scraped link. A failure carries `error`; a success carries the sizes
451
+ * the scrape produced, so the summary can report both without a second pass. */
452
+ export interface ScrapeObservation {
453
+ url: string;
454
+ chars?: number;
455
+ highlights?: number;
456
+ error?: string;
457
+ }
458
+
459
+ /** One reranker round trip. A search reranks once per scraped source, so
460
+ * these fold into a single summary rather than logging per source. */
461
+ export interface RerankObservation {
462
+ provider: string;
463
+ chunks: number;
464
+ results: number;
465
+ durationMs: number;
466
+ model?: string;
467
+ /** Provider-reported usage: Jina tokens, Cohere billed search units. */
468
+ units?: number;
469
+ /** Chunks a provider candidate cap dropped before submission. */
470
+ dropped?: number;
471
+ /** Set only when a provider cap reduced the requested result count, so a
472
+ * search returning fewer highlights than configured says why. */
473
+ topK?: number;
474
+ topKLimit?: number;
475
+ reason?: RerankFallback;
476
+ error?: SafeErrorLog;
477
+ }
478
+
479
+ /** Per-rerank state threaded from the start of a call to whichever exit it
480
+ * takes, so every path records exactly one observation. */
481
+ export interface RerankRun {
482
+ metrics: SearchMetrics;
483
+ documents: string[];
484
+ topK: number;
485
+ startedAt: number;
486
+ model?: string;
487
+ units?: number;
488
+ dropped?: number;
489
+ topKLimit?: number;
490
+ }
491
+
492
+ /**
493
+ * Fold-as-you-go counters for one `web_search` call. Recording is O(1) and
494
+ * allocation-free past a bounded reason map; {@link SearchMetrics.flush}
495
+ * emits at most one line per phase that actually ran.
496
+ */
497
+ export interface SearchMetrics {
498
+ recordSearch(observation: SearchObservation): void;
499
+ recordScrape(observation: ScrapeObservation): void;
500
+ recordRerank(observation: RerankObservation): void;
501
+ flush(): void;
502
+ }
410
503
  export interface SearchToolConfig
411
504
  extends SearchConfig,
412
505
  ProcessSourcesConfig,
@@ -702,6 +795,10 @@ export interface FirecrawlScraperConfig extends BaseSearchProviderConfig {
702
795
  changeTrackingOptions?: object;
703
796
  }
704
797
 
798
+ /** Result kind a parallel sub-search covers; `web` is the untyped main
799
+ * search, which every provider serves without a `type` parameter. */
800
+ export type SubSearchType = 'web' | 'images' | 'videos' | 'news';
801
+
705
802
  export type GetSourcesParams = {
706
803
  query: string;
707
804
  date?: DATE_RANGE;
@@ -1038,6 +1135,9 @@ export type ProcessSourcesFields = {
1038
1135
  news: boolean;
1039
1136
  proMode: boolean;
1040
1137
  onGetHighlights: SearchToolConfig['onGetHighlights'];
1138
+ /** Collector owned by the caller; when omitted, one is created and flushed
1139
+ * for this call so a direct `processSources` still summarizes itself. */
1140
+ metrics?: SearchMetrics;
1041
1141
  };
1042
1142
 
1043
1143
  export interface SearchToolSchema {
@@ -2,21 +2,13 @@
2
2
 
3
3
  import { isAxiosError } from 'axios';
4
4
 
5
+ import type { SafeErrorLog } from './types';
5
6
  import type { AxiosError } from 'axios';
6
7
  import type * as t from './types';
7
8
 
8
9
  const LOG_VALUE_MAX_LENGTH = 2048;
9
10
 
10
- export interface SafeErrorLog {
11
- message: string;
12
- name?: string;
13
- code?: string;
14
- status?: number;
15
- method?: string;
16
- url?: string;
17
- responseDataSummary?: string;
18
- value?: string;
19
- }
11
+ export type { SafeErrorLog } from './types';
20
12
 
21
13
  /**
22
14
  * Singleton instance of the default logger
@@ -131,6 +131,7 @@ import { stripRunStepResumeState } from '@/tools/runStepResume';
131
131
  import { seedAgentInitialSessions } from '@/utils/toolSessions';
132
132
  import { stableStringify } from '@/tools/eagerEventExecution';
133
133
  import { convertInjectedMessages } from '@/messages/injected';
134
+ import { resolveClientOptionsModel } from '@/llm/request';
134
135
  import { composeAbortSignals } from '@/utils/misc';
135
136
  import { HandlerRegistry } from '@/events';
136
137
 
@@ -1091,8 +1092,7 @@ export class SubagentExecutor {
1091
1092
  return JSON.stringify({
1092
1093
  status: 'rejected',
1093
1094
  tool: Constants.SUBAGENT,
1094
- message:
1095
- 'Child-thread continuation is not enabled by this host.',
1095
+ message: 'Child-thread continuation is not enabled by this host.',
1096
1096
  });
1097
1097
  }
1098
1098
  const detachedHandlers = new HandlerRegistry();
@@ -2261,9 +2261,7 @@ export class SubagentExecutor {
2261
2261
  }
2262
2262
  if (this.maxDepth <= 0) {
2263
2263
  return Promise.resolve(
2264
- createSubagentFailure(
2265
- 'Error: Maximum subagent nesting depth exceeded.'
2266
- )
2264
+ createSubagentFailure('Error: Maximum subagent nesting depth exceeded.')
2267
2265
  );
2268
2266
  }
2269
2267
  if (
@@ -3300,7 +3298,7 @@ function createUsageCaptureHandler(args: {
3300
3298
  defaultMember?.[1];
3301
3299
  const model =
3302
3300
  callInfo?.model ??
3303
- (memberInput == null ? undefined : extractConfiguredModel(memberInput));
3301
+ resolveClientOptionsModel(memberInput?.clientOptions);
3304
3302
  const callProvider = callInfo?.provider ?? memberInput?.provider;
3305
3303
  for (const generationGroup of output.generations) {
3306
3304
  /**
@@ -3423,27 +3421,6 @@ function getGraphEventMemberAgentId({
3423
3421
  : undefined;
3424
3422
  }
3425
3423
 
3426
- /**
3427
- * Best-effort read of the configured model from a subagent's client
3428
- * options. Providers disagree on the key (`model` vs `modelName`), and the
3429
- * value is only a fallback for calls that carry no `ls_model_name`.
3430
- */
3431
- function extractConfiguredModel(agentInputs: AgentInputs): string | undefined {
3432
- const clientOptions = agentInputs.clientOptions as
3433
- | { model?: unknown; modelName?: unknown }
3434
- | undefined;
3435
- if (typeof clientOptions?.model === 'string' && clientOptions.model !== '') {
3436
- return clientOptions.model;
3437
- }
3438
- if (
3439
- typeof clientOptions?.modelName === 'string' &&
3440
- clientOptions.modelName !== ''
3441
- ) {
3442
- return clientOptions.modelName;
3443
- }
3444
- return undefined;
3445
- }
3446
-
3447
3424
  function sanitizeResolverConfigurable(
3448
3425
  parentConfigurable: Record<string, unknown>
3449
3426
  ): SubagentResolveConfigurable | undefined {
package/src/types/run.ts CHANGED
@@ -252,6 +252,14 @@ export type RunConfig = {
252
252
  * block to prevent leaks.
253
253
  */
254
254
  hooks?: HookRegistry;
255
+ /**
256
+ * Maximum number of times a `Stop` hook may keep this Run warm by returning
257
+ * `decision: 'block'` with messages to inject. Defaults to
258
+ * `DEFAULT_MAX_STOP_CONTINUATIONS`; non-finite values use the default and
259
+ * values at or below zero disable terminal continuation while preserving the
260
+ * final Stop notification.
261
+ */
262
+ maxStopContinuations?: number;
255
263
  /**
256
264
  * Opt-in cooperative preemption for this run. Requires a `hooks` registry
257
265
  * with a `PreemptBoundary` matcher — the seal only stops the stream, the
@@ -116,6 +116,12 @@ export interface RunStepResumeState {
116
116
  version: 1;
117
117
  revision: number;
118
118
  nextIndex: number;
119
+ /** Warm terminal continuations already admitted for this execution. */
120
+ stopContinuationCount?: number;
121
+ /** Identifies the fresh execution that owns this continuation lifecycle. */
122
+ stopContinuationExecutionId?: string;
123
+ /** Distinguishes LangGraph event keys when a warm continuation restarts steps. */
124
+ streamSegment?: number;
119
125
  toolCallSteps: Array<{ toolCallId: string; stepId: string }>;
120
126
  steps: RunStepResumeEntry[];
121
127
  }
@@ -82,6 +82,13 @@ export type CompactionSemanticIndexEntry =
82
82
 
83
83
  export type CompactionSemanticIndex = readonly CompactionSemanticIndexEntry[];
84
84
 
85
+ /** Serializable continuation state for a bounded compaction semantic index. */
86
+ export type CompactionSemanticIndexSnapshot = {
87
+ entries: CompactionSemanticIndex;
88
+ /** Cumulative entries supplied before validation and bounded retention. */
89
+ providedEntryCount: number;
90
+ };
91
+
85
92
  export type SummarizationConfig = {
86
93
  provider?: ProviderName;
87
94
  model?: string;
@@ -6,8 +6,8 @@ import {
6
6
  isAtomicToolContentBlock,
7
7
  serializeStructuredValueBounded,
8
8
  } from './toolContent';
9
- import { ContentTypes } from '@/common/enum';
10
9
  import { markTokenCounterCacheCompatible } from '@/llm/tokenCounterCacheCompatibility';
10
+ import { ContentTypes } from '@/common/enum';
11
11
 
12
12
  export type EncodingName = 'o200k_base' | 'claude';
13
13
 
@@ -1257,6 +1257,25 @@ export function apportionTokenCounts(
1257
1257
  */
1258
1258
  const CLAUDE_TOKEN_CORRECTION = 1.1;
1259
1259
 
1260
+ const tokenCounterEncodings = new WeakMap<
1261
+ (message: BaseMessage) => number,
1262
+ EncodingName
1263
+ >();
1264
+
1265
+ /**
1266
+ * Encoding a counter measures in, for counters built here.
1267
+ *
1268
+ * `undefined` for a counter the host supplied itself: unknown, not wrong. A
1269
+ * caller that needs a count in a specific encoding can therefore tell "counts
1270
+ * in the encoding I need" from "counts in a different one" without treating
1271
+ * every foreign counter as suspect.
1272
+ */
1273
+ export function encodingOfTokenCounter(
1274
+ tokenCounter: (message: BaseMessage) => number
1275
+ ): EncodingName | undefined {
1276
+ return tokenCounterEncodings.get(tokenCounter);
1277
+ }
1278
+
1260
1279
  /**
1261
1280
  * Creates a token counter function using the specified encoding.
1262
1281
  * Lazily loads the encoding data on first use via dynamic import.
@@ -1267,13 +1286,17 @@ export const createTokenCounter = async (
1267
1286
  const tok = await getTokenizer(encoding);
1268
1287
  const countTokens = (text: string): number => tok.count(text);
1269
1288
  const isClaude = encoding === 'claude';
1270
- return markTokenCounterCacheCompatible((message: BaseMessage): number => {
1271
- const count = getTokenCountForMessage(message, countTokens, encoding);
1272
- const correctedCount = isClaude
1273
- ? Math.ceil(count * CLAUDE_TOKEN_CORRECTION)
1274
- : count;
1275
- return ensureSafeTokenMeasurement(correctedCount, 'message');
1276
- });
1289
+ const counter = markTokenCounterCacheCompatible(
1290
+ (message: BaseMessage): number => {
1291
+ const count = getTokenCountForMessage(message, countTokens, encoding);
1292
+ const correctedCount = isClaude
1293
+ ? Math.ceil(count * CLAUDE_TOKEN_CORRECTION)
1294
+ : count;
1295
+ return ensureSafeTokenMeasurement(correctedCount, 'message');
1296
+ }
1297
+ );
1298
+ tokenCounterEncodings.set(counter, encoding);
1299
+ return counter;
1277
1300
  };
1278
1301
 
1279
1302
  /** Utility to manage the token encoder lifecycle explicitly. */