@librechat/agents 3.7.15 → 3.7.16

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 (120) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +91 -0
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/agents/projection.cjs +2 -1
  4. package/dist/cjs/agents/projection.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +47 -6
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/graphs/MultiAgentGraph.cjs +20 -7
  8. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  9. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +1 -1
  10. package/dist/cjs/llm/openai/utils/index.cjs +1 -1
  11. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  12. package/dist/cjs/llm/preempt.cjs +1 -10
  13. package/dist/cjs/llm/preempt.cjs.map +1 -1
  14. package/dist/cjs/main.cjs +23 -3
  15. package/dist/cjs/messages/contextPruning.cjs +1 -1
  16. package/dist/cjs/messages/contextPruning.cjs.map +1 -1
  17. package/dist/cjs/messages/core.cjs +29 -1
  18. package/dist/cjs/messages/core.cjs.map +1 -1
  19. package/dist/cjs/messages/fading.cjs +122 -0
  20. package/dist/cjs/messages/fading.cjs.map +1 -0
  21. package/dist/cjs/messages/format.cjs +1 -1
  22. package/dist/cjs/messages/index.cjs +1 -0
  23. package/dist/cjs/messages/prune.cjs +364 -236
  24. package/dist/cjs/messages/prune.cjs.map +1 -1
  25. package/dist/cjs/run.cjs +27 -0
  26. package/dist/cjs/run.cjs.map +1 -1
  27. package/dist/cjs/session/AgentSession.cjs +213 -8
  28. package/dist/cjs/session/AgentSession.cjs.map +1 -1
  29. package/dist/cjs/session/JsonlSessionStore.cjs +41 -0
  30. package/dist/cjs/session/JsonlSessionStore.cjs.map +1 -1
  31. package/dist/cjs/session/index.cjs +1 -1
  32. package/dist/cjs/stream.cjs +1 -1
  33. package/dist/cjs/summarization/node.cjs +1 -1
  34. package/dist/cjs/tools/ToolNode.cjs +1 -1
  35. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +2 -0
  36. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  37. package/dist/cjs/tools/subagent/SubagentReplay.cjs +2 -1
  38. package/dist/cjs/tools/subagent/SubagentReplay.cjs.map +1 -1
  39. package/dist/cjs/utils/index.cjs +1 -1
  40. package/dist/cjs/utils/truncation.cjs +9 -0
  41. package/dist/cjs/utils/truncation.cjs.map +1 -1
  42. package/dist/esm/agents/AgentContext.mjs +92 -1
  43. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  44. package/dist/esm/agents/projection.mjs +2 -1
  45. package/dist/esm/agents/projection.mjs.map +1 -1
  46. package/dist/esm/graphs/Graph.mjs +47 -6
  47. package/dist/esm/graphs/Graph.mjs.map +1 -1
  48. package/dist/esm/graphs/MultiAgentGraph.mjs +20 -7
  49. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  50. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +1 -1
  51. package/dist/esm/llm/openai/utils/index.mjs +2 -2
  52. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  53. package/dist/esm/llm/preempt.mjs +1 -10
  54. package/dist/esm/llm/preempt.mjs.map +1 -1
  55. package/dist/esm/main.mjs +6 -5
  56. package/dist/esm/messages/contextPruning.mjs +1 -1
  57. package/dist/esm/messages/contextPruning.mjs.map +1 -1
  58. package/dist/esm/messages/core.mjs +29 -2
  59. package/dist/esm/messages/core.mjs.map +1 -1
  60. package/dist/esm/messages/fading.mjs +108 -0
  61. package/dist/esm/messages/fading.mjs.map +1 -0
  62. package/dist/esm/messages/format.mjs +1 -1
  63. package/dist/esm/messages/index.mjs +1 -0
  64. package/dist/esm/messages/prune.mjs +363 -235
  65. package/dist/esm/messages/prune.mjs.map +1 -1
  66. package/dist/esm/run.mjs +27 -0
  67. package/dist/esm/run.mjs.map +1 -1
  68. package/dist/esm/session/AgentSession.mjs +213 -8
  69. package/dist/esm/session/AgentSession.mjs.map +1 -1
  70. package/dist/esm/session/JsonlSessionStore.mjs +41 -0
  71. package/dist/esm/session/JsonlSessionStore.mjs.map +1 -1
  72. package/dist/esm/session/index.mjs +1 -1
  73. package/dist/esm/stream.mjs +1 -1
  74. package/dist/esm/summarization/node.mjs +1 -1
  75. package/dist/esm/tools/ToolNode.mjs +1 -1
  76. package/dist/esm/tools/subagent/SubagentExecutor.mjs +2 -0
  77. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  78. package/dist/esm/tools/subagent/SubagentReplay.mjs +2 -1
  79. package/dist/esm/tools/subagent/SubagentReplay.mjs.map +1 -1
  80. package/dist/esm/utils/index.mjs +1 -1
  81. package/dist/esm/utils/truncation.mjs +7 -1
  82. package/dist/esm/utils/truncation.mjs.map +1 -1
  83. package/dist/types/agents/AgentContext.d.ts +32 -1
  84. package/dist/types/agents/projection.d.ts +3 -1
  85. package/dist/types/graphs/Graph.d.ts +14 -1
  86. package/dist/types/graphs/MultiAgentGraph.d.ts +7 -0
  87. package/dist/types/messages/contextPruning.d.ts +2 -0
  88. package/dist/types/messages/core.d.ts +2 -0
  89. package/dist/types/messages/fading.d.ts +81 -0
  90. package/dist/types/messages/index.d.ts +1 -0
  91. package/dist/types/messages/prune.d.ts +71 -24
  92. package/dist/types/run.d.ts +16 -0
  93. package/dist/types/session/AgentSession.d.ts +15 -0
  94. package/dist/types/session/JsonlSessionStore.d.ts +4 -1
  95. package/dist/types/session/types.d.ts +9 -0
  96. package/dist/types/tools/subagent/SubagentReplay.d.ts +3 -1
  97. package/dist/types/types/graph.d.ts +23 -0
  98. package/dist/types/types/run.d.ts +10 -0
  99. package/dist/types/utils/truncation.d.ts +9 -0
  100. package/package.json +1 -1
  101. package/src/agents/AgentContext.ts +175 -1
  102. package/src/agents/projection.ts +4 -0
  103. package/src/graphs/Graph.ts +97 -11
  104. package/src/graphs/MultiAgentGraph.ts +54 -6
  105. package/src/llm/openai/utils/index.ts +3 -1
  106. package/src/llm/preempt.ts +4 -17
  107. package/src/messages/contextPruning.ts +7 -1
  108. package/src/messages/core.ts +52 -0
  109. package/src/messages/fading.ts +301 -0
  110. package/src/messages/index.ts +1 -0
  111. package/src/messages/prune.ts +719 -507
  112. package/src/run.ts +52 -0
  113. package/src/session/AgentSession.ts +397 -8
  114. package/src/session/JsonlSessionStore.ts +71 -0
  115. package/src/session/types.ts +10 -0
  116. package/src/tools/subagent/SubagentExecutor.ts +6 -0
  117. package/src/tools/subagent/SubagentReplay.ts +15 -2
  118. package/src/types/graph.ts +25 -0
  119. package/src/types/run.ts +10 -0
  120. package/src/utils/truncation.ts +25 -0
@@ -26,6 +26,7 @@ import type {
26
26
  SessionRunEventEntry,
27
27
  SessionSummaryEntry,
28
28
  SessionStateEntry,
29
+ SessionFadingState,
29
30
  SessionTreeNode,
30
31
  } from './types';
31
32
  import {
@@ -82,6 +83,16 @@ function parseLine(line: string): SessionHeader | SessionEntry | undefined {
82
83
  }
83
84
  }
84
85
 
86
+ /** A `session_state` line may carry `data: null`; only an object can hold fading state. */
87
+ function hasFadingStateField(entry: SessionStateEntry): boolean {
88
+ const data: unknown = entry.data;
89
+ return (
90
+ data != null &&
91
+ typeof data === 'object' &&
92
+ Object.prototype.hasOwnProperty.call(data, 'fadingState')
93
+ );
94
+ }
95
+
85
96
  function createHeader(options: CreateSessionFileOptions): SessionHeader {
86
97
  return {
87
98
  type: 'session',
@@ -374,6 +385,66 @@ export class JsonlSessionStore {
374
385
  });
375
386
  }
376
387
 
388
+ getFadingStates(
389
+ mainThreadId?: string,
390
+ maxAlternateStates = Number.POSITIVE_INFINITY
391
+ ): SessionFadingState[] {
392
+ const states = new Map<string, SessionFadingState>();
393
+ const alternateLimit = Number.isFinite(maxAlternateStates)
394
+ ? Math.max(0, Math.floor(maxAlternateStates))
395
+ : Number.POSITIVE_INFINITY;
396
+ let alternateCount = 0;
397
+ let mainFound = mainThreadId == null;
398
+ for (let i = this.entries.length - 1; i >= 0; i--) {
399
+ const entry = this.entries[i];
400
+ if (entry.type !== 'session_state' || !hasFadingStateField(entry)) {
401
+ continue;
402
+ }
403
+ if (entry.data.fadingState == null) {
404
+ break;
405
+ }
406
+ const state = entry.data.fadingState;
407
+ const scopeKey = JSON.stringify([
408
+ state.threadId,
409
+ state.checkpointNs ?? '',
410
+ ]);
411
+ if (states.has(scopeKey)) {
412
+ continue;
413
+ }
414
+ if (
415
+ state.threadId === mainThreadId &&
416
+ (state.checkpointNs ?? '') === ''
417
+ ) {
418
+ states.set(scopeKey, state);
419
+ mainFound = true;
420
+ } else if (alternateCount < alternateLimit) {
421
+ states.set(scopeKey, state);
422
+ alternateCount += 1;
423
+ }
424
+ if (mainFound && alternateCount >= alternateLimit) {
425
+ break;
426
+ }
427
+ }
428
+ return [...states.values()];
429
+ }
430
+
431
+ hasFadingState(): boolean {
432
+ return this.entries.some(
433
+ (entry) => entry.type === 'session_state' && hasFadingStateField(entry)
434
+ );
435
+ }
436
+
437
+ async appendFadingState(
438
+ fadingState: SessionStateEntry['data']['fadingState']
439
+ ): Promise<SessionStateEntry> {
440
+ const leafId = this.getLeafEntry()?.id ?? null;
441
+ return this.appendEntry<SessionStateEntry>({
442
+ type: 'session_state',
443
+ parentId: leafId,
444
+ data: { leafId, fadingState },
445
+ });
446
+ }
447
+
377
448
  async appendEntryForCompaction(params: {
378
449
  text: string;
379
450
  tokenCount?: number;
@@ -116,10 +116,20 @@ export type SessionRunEventEntry = SessionEntryBase<
116
116
  }
117
117
  >;
118
118
 
119
+ export interface SessionFadingState {
120
+ threadId: string;
121
+ /** LangGraph checkpoint namespace within `threadId`; empty when omitted. */
122
+ checkpointNs?: string;
123
+ fadingTier?: t.FadingTier;
124
+ fadingTiers?: t.FadingTiers;
125
+ }
126
+
119
127
  export type SessionStateEntry = SessionEntryBase<
120
128
  'session_state',
121
129
  {
122
130
  leafId: string | null;
131
+ /** Latest compact fading state for one checkpoint thread; null clears all. */
132
+ fadingState?: SessionFadingState | null;
123
133
  }
124
134
  >;
125
135
 
@@ -2457,6 +2457,12 @@ export class SubagentExecutor {
2457
2457
  streamLimits: this.streamLimits,
2458
2458
  subagentScope: true,
2459
2459
  subagentExecutionContext: childExecutionContext,
2460
+ ...(resumeExecution?.graphState.fadingTier == null
2461
+ ? {}
2462
+ : { fadingTier: resumeExecution.graphState.fadingTier }),
2463
+ ...(resumeExecution?.graphState.fadingTiers == null
2464
+ ? {}
2465
+ : { fadingTiers: resumeExecution.graphState.fadingTiers }),
2460
2466
  /**
2461
2467
  * Forwarded so the child graph's own `SubagentExecutor` (created in
2462
2468
  * its `createAgentNode` when `allowNested` keeps subagentConfigs)
@@ -2,7 +2,13 @@ import type { ToolCall, ToolMessage } from '@langchain/core/messages/tool';
2
2
  import type { RunnableConfig } from '@langchain/core/runnables';
3
3
  import type { ToolOutputReferenceState } from '@/tools/toolOutputReferences';
4
4
  import type { ToolApprovalReplaySnapshot } from '@/hooks';
5
- import type { RunStepResumeState, ToolSessionContext } from '@/types';
5
+ import type {
6
+ FadingTier,
7
+ FadingTiers,
8
+ RunStepResumeState,
9
+ ToolSessionContext,
10
+ } from '@/types';
11
+ import { isFadingTier } from '@/messages/fading';
6
12
  import {
7
13
  attachRunStepResumeState,
8
14
  getRunStepResumeState,
@@ -65,6 +71,8 @@ export interface SubagentGraphResumeState {
65
71
  eagerToolSuppressions: string[];
66
72
  runStepState?: RunStepResumeState;
67
73
  toolOutputReferences?: ToolOutputReferenceState;
74
+ fadingTier?: FadingTier;
75
+ fadingTiers?: FadingTiers;
68
76
  }
69
77
 
70
78
  /** Private checkpoint payload linking a parent pause to an exact child state. */
@@ -301,7 +309,12 @@ function isGraphResumeState(value: unknown): value is SubagentGraphResumeState {
301
309
  (state.runStepState != null &&
302
310
  !isRunStepResumeState(state.runStepState)) ||
303
311
  (state.toolOutputReferences != null &&
304
- !isToolOutputReferenceState(state.toolOutputReferences))
312
+ !isToolOutputReferenceState(state.toolOutputReferences)) ||
313
+ (state.fadingTier != null && !isFadingTier(state.fadingTier)) ||
314
+ (state.fadingTiers != null &&
315
+ (typeof state.fadingTiers !== 'object' ||
316
+ Array.isArray(state.fadingTiers) ||
317
+ !Object.values(state.fadingTiers).every(isFadingTier)))
305
318
  ) {
306
319
  return false;
307
320
  }
@@ -132,6 +132,27 @@ export interface ContextUsageEvent {
132
132
  calibrationRatio?: number;
133
133
  }
134
134
 
135
+ /**
136
+ * Latched context-fading tier. Caps for historical tool results derive from
137
+ * `(budgetTokens, masked)` only, so carrying the tier across runs keeps their
138
+ * truncated bytes stable for prefix-based provider prompt caches. Hosts
139
+ * persist it beside `calibrationRatio` and pass it back via
140
+ * `RunConfig.fadingTiers[agentId]`.
141
+ */
142
+ export interface FadingTier {
143
+ v: 1;
144
+ /** Token budget the caps derive from, in raw token space. Never grows;
145
+ * clamped to the current context window when seeded. */
146
+ budgetTokens: number;
147
+ /** Whether observation masking has activated. Never deactivates. */
148
+ masked: boolean;
149
+ /** Whether this tier was reduced, masked, or restored from host state. */
150
+ latched?: true;
151
+ }
152
+
153
+ /** Latched fading tiers keyed by agent ID. */
154
+ export type FadingTiers = Record<string, FadingTier>;
155
+
135
156
  export interface EventHandler {
136
157
  handle(
137
158
  event: string,
@@ -346,6 +367,10 @@ export type StandardGraphInput = {
346
367
  tokenCounter?: TokenCounter;
347
368
  indexTokenCountMap?: Record<string, number>;
348
369
  calibrationRatio?: number;
370
+ /** Persisted default-agent tier retained for single-agent compatibility. */
371
+ fadingTier?: FadingTier | null;
372
+ /** Persisted fading tiers keyed by agent ID. */
373
+ fadingTiers?: FadingTiers | null;
349
374
  /**
350
375
  * Receives a {@link SubagentUsageEvent} for every model call that reports
351
376
  * usage metadata inside a subagent child run spawned from this graph
package/src/types/run.ts CHANGED
@@ -338,6 +338,16 @@ export type RunConfig = {
338
338
  * conversation. Without this, the EMA resets to 1 on every new Run instance.
339
339
  */
340
340
  calibrationRatio?: number;
341
+ /**
342
+ * Default-agent fading tier retained for single-agent compatibility. New
343
+ * multi-agent integrations should use `fadingTiers`.
344
+ */
345
+ fadingTier?: g.FadingTier | null;
346
+ /**
347
+ * Context-fading tiers keyed by agent ID. Multi-agent hosts should persist
348
+ * the value returned by `Run.getFadingTiers()` and pass it back here.
349
+ */
350
+ fadingTiers?: g.FadingTiers | null;
341
351
  /** Skip post-stream cleanup (clearHeavyState) — useful for tests that inspect graph state after processStream */
342
352
  skipCleanup?: boolean;
343
353
  /**
@@ -152,3 +152,28 @@ export function truncateToolResultContent(
152
152
 
153
153
  return content.slice(0, headEnd) + indicator + content.slice(tailStart);
154
154
  }
155
+
156
+ /** Absolute hard cap on a single tool-call input (characters). */
157
+ export const HARD_MAX_TOOL_CALL_INPUT_CHARS = 200_000;
158
+
159
+ /** Smallest JSON value a truncated tool-call input can shrink to. */
160
+ export const MIN_JSON_VALUE_CHARS = 4;
161
+
162
+ /**
163
+ * Computes the max tool-call input size for a context window: 15 % of the
164
+ * window in estimated characters (~4 chars/token), capped at 200K.
165
+ */
166
+ export function calculateMaxToolCallInputChars(
167
+ maxContextTokens?: number
168
+ ): number {
169
+ if (maxContextTokens == null || maxContextTokens <= 0) {
170
+ return HARD_MAX_TOOL_CALL_INPUT_CHARS;
171
+ }
172
+ return Math.max(
173
+ MIN_JSON_VALUE_CHARS,
174
+ Math.min(
175
+ Math.floor(maxContextTokens * 0.15) * 4,
176
+ HARD_MAX_TOOL_CALL_INPUT_CHARS
177
+ )
178
+ );
179
+ }