@librechat/agents 3.3.0 → 3.3.1

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 (129) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +116 -2
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/common/enum.cjs +2 -0
  4. package/dist/cjs/common/enum.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +229 -48
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/graphs/MultiAgentGraph.cjs +102 -27
  8. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  9. package/dist/cjs/llm/bedrock/index.cjs +11 -2
  10. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  11. package/dist/cjs/llm/contextOverflowRecovery.cjs +132 -0
  12. package/dist/cjs/llm/contextOverflowRecovery.cjs.map +1 -0
  13. package/dist/cjs/llm/google/index.cjs +1 -1
  14. package/dist/cjs/llm/invoke.cjs +60 -3
  15. package/dist/cjs/llm/invoke.cjs.map +1 -1
  16. package/dist/cjs/main.cjs +20 -7
  17. package/dist/cjs/messages/prune.cjs +16 -5
  18. package/dist/cjs/messages/prune.cjs.map +1 -1
  19. package/dist/cjs/messages/recency.cjs +2 -0
  20. package/dist/cjs/messages/recency.cjs.map +1 -1
  21. package/dist/cjs/run.cjs +15 -2
  22. package/dist/cjs/run.cjs.map +1 -1
  23. package/dist/cjs/stream.cjs +205 -49
  24. package/dist/cjs/stream.cjs.map +1 -1
  25. package/dist/cjs/summarization/node.cjs +55 -7
  26. package/dist/cjs/summarization/node.cjs.map +1 -1
  27. package/dist/cjs/tools/BashExecutor.cjs +2 -2
  28. package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
  29. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +2 -2
  30. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
  31. package/dist/cjs/tools/CodeExecutor.cjs +69 -8
  32. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  33. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +19 -15
  34. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  35. package/dist/cjs/tools/ToolNode.cjs +32 -3
  36. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  37. package/dist/cjs/utils/errors.cjs +317 -52
  38. package/dist/cjs/utils/errors.cjs.map +1 -1
  39. package/dist/esm/agents/AgentContext.mjs +117 -3
  40. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  41. package/dist/esm/common/enum.mjs +2 -0
  42. package/dist/esm/common/enum.mjs.map +1 -1
  43. package/dist/esm/graphs/Graph.mjs +227 -46
  44. package/dist/esm/graphs/Graph.mjs.map +1 -1
  45. package/dist/esm/graphs/MultiAgentGraph.mjs +102 -27
  46. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  47. package/dist/esm/llm/bedrock/index.mjs +11 -2
  48. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  49. package/dist/esm/llm/contextOverflowRecovery.mjs +130 -0
  50. package/dist/esm/llm/contextOverflowRecovery.mjs.map +1 -0
  51. package/dist/esm/llm/google/index.mjs +1 -1
  52. package/dist/esm/llm/invoke.mjs +59 -4
  53. package/dist/esm/llm/invoke.mjs.map +1 -1
  54. package/dist/esm/main.mjs +9 -9
  55. package/dist/esm/messages/prune.mjs +14 -6
  56. package/dist/esm/messages/prune.mjs.map +1 -1
  57. package/dist/esm/messages/recency.mjs +2 -1
  58. package/dist/esm/messages/recency.mjs.map +1 -1
  59. package/dist/esm/run.mjs +15 -2
  60. package/dist/esm/run.mjs.map +1 -1
  61. package/dist/esm/stream.mjs +205 -49
  62. package/dist/esm/stream.mjs.map +1 -1
  63. package/dist/esm/summarization/node.mjs +55 -7
  64. package/dist/esm/summarization/node.mjs.map +1 -1
  65. package/dist/esm/tools/BashExecutor.mjs +3 -3
  66. package/dist/esm/tools/BashExecutor.mjs.map +1 -1
  67. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +3 -3
  68. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
  69. package/dist/esm/tools/CodeExecutor.mjs +62 -9
  70. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  71. package/dist/esm/tools/ProgrammaticToolCalling.mjs +20 -16
  72. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  73. package/dist/esm/tools/ToolNode.mjs +32 -3
  74. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  75. package/dist/esm/utils/errors.mjs +317 -53
  76. package/dist/esm/utils/errors.mjs.map +1 -1
  77. package/dist/types/agents/AgentContext.d.ts +62 -3
  78. package/dist/types/common/enum.d.ts +2 -0
  79. package/dist/types/graphs/Graph.d.ts +16 -2
  80. package/dist/types/graphs/MultiAgentGraph.d.ts +1 -0
  81. package/dist/types/llm/contextOverflowRecovery.d.ts +85 -0
  82. package/dist/types/llm/invoke.d.ts +35 -6
  83. package/dist/types/messages/prune.d.ts +10 -2
  84. package/dist/types/messages/recency.d.ts +1 -0
  85. package/dist/types/run.d.ts +2 -0
  86. package/dist/types/tools/CodeExecutor.d.ts +14 -1
  87. package/dist/types/types/llm.d.ts +7 -4
  88. package/dist/types/types/stream.d.ts +5 -4
  89. package/dist/types/types/summarize.d.ts +22 -0
  90. package/dist/types/utils/__tests__/fixtures/contextOverflowSignatures.d.ts +40 -0
  91. package/dist/types/utils/errors.d.ts +65 -16
  92. package/dist/types/utils/redactSecrets.d.ts +3 -0
  93. package/package.json +7 -8
  94. package/src/agents/AgentContext.ts +188 -7
  95. package/src/agents/__tests__/AgentContext.overflow.test.ts +205 -0
  96. package/src/common/enum.ts +2 -0
  97. package/src/graphs/Graph.ts +389 -58
  98. package/src/graphs/MultiAgentGraph.ts +184 -46
  99. package/src/graphs/__tests__/Graph.contextOverflow.test.ts +631 -0
  100. package/src/llm/__tests__/contextOverflowRecovery.test.ts +401 -0
  101. package/src/llm/__tests__/fallbackOverflow.test.ts +287 -0
  102. package/src/llm/bedrock/index.ts +25 -12
  103. package/src/llm/contextOverflowRecovery.ts +292 -0
  104. package/src/llm/invoke.ts +119 -4
  105. package/src/messages/prune.ts +24 -11
  106. package/src/messages/recency.ts +3 -1
  107. package/src/run.ts +24 -1
  108. package/src/scripts/context-overflow-probe.ts +997 -0
  109. package/src/specs/agent-handoffs.test.ts +903 -1
  110. package/src/specs/context-overflow-recovery.live.test.ts +213 -0
  111. package/src/splitStream.test.ts +882 -0
  112. package/src/stream.ts +315 -51
  113. package/src/summarization/__tests__/aggregator.test.ts +83 -0
  114. package/src/summarization/__tests__/node.test.ts +139 -0
  115. package/src/summarization/node.ts +99 -14
  116. package/src/tools/BashExecutor.ts +4 -2
  117. package/src/tools/BashProgrammaticToolCalling.ts +4 -7
  118. package/src/tools/CodeExecutor.ts +119 -8
  119. package/src/tools/ProgrammaticToolCalling.ts +29 -27
  120. package/src/tools/ToolNode.ts +50 -8
  121. package/src/tools/__tests__/CodeApiAuthHeaders.test.ts +297 -3
  122. package/src/types/llm.ts +8 -1
  123. package/src/types/stream.ts +5 -4
  124. package/src/types/summarize.ts +22 -0
  125. package/src/utils/__tests__/errors.test.ts +270 -0
  126. package/src/utils/__tests__/fixtures/contextOverflowSignatures.ts +336 -0
  127. package/src/utils/__tests__/redactSecrets.test.ts +56 -0
  128. package/src/utils/errors.ts +484 -66
  129. package/src/utils/redactSecrets.ts +61 -0
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Recovery policy for provider context-overflow rejections.
3
+ *
4
+ * Detection (`@/utils/errors`) answers "was this an overflow, and what did
5
+ * the provider disclose?". This module answers the follow-up: "what budget
6
+ * should the retry target?" — deliberately kept as pure functions so the
7
+ * policy can be reasoned about and tested without a graph.
8
+ *
9
+ * On units: `maxContextTokens` is a **provider-space** budget. The pruner
10
+ * converts it into its own raw estimate space by dividing by the
11
+ * `calibrationRatio` it learns from reported usage. A provider-reported
12
+ * ceiling is therefore applied verbatim — converting it here as well would
13
+ * apply the same correction twice and prune toward roughly `limit / ratio²`,
14
+ * silently discarding far more history than the overflow called for.
15
+ *
16
+ * `observedCalibrationRatio` is returned separately so the caller can seed
17
+ * the pruner's conversion without folding the same correction into the
18
+ * provider-space budget.
19
+ */
20
+ import type { ContextOverflowInfo } from '@/utils/errors';
21
+ import type { Providers } from '@/common';
22
+ /** Bound on forced-compaction retries per agent, per run. */
23
+ export declare const DEFAULT_MAX_OVERFLOW_RECOVERIES = 2;
24
+ export interface OverflowRecoveryPlan {
25
+ /** Budget the retry should target, in provider token units when known. */
26
+ budgetTokens?: number;
27
+ /** What the provider disclosed. Carried through for logging. */
28
+ info: ContextOverflowInfo;
29
+ /**
30
+ * Provider-reported message tokens divided by our own message estimate,
31
+ * when both are known. Greater than 1 means we under-count relative to this
32
+ * provider.
33
+ *
34
+ * Returned separately so the graph can seed the pruner's calibration;
35
+ * applying it to this plan's budget as well would double-count. Fixed
36
+ * instruction overhead is removed before deriving it from
37
+ * `info.promptTokens`, never `info.requestedTokens`, since several providers
38
+ * fold the completion allowance into the latter.
39
+ */
40
+ observedCalibrationRatio?: number;
41
+ }
42
+ export interface OverflowRecoveryParams {
43
+ error: unknown;
44
+ provider: Providers;
45
+ /** Budget in force when the rejected prompt was built. */
46
+ maxContextTokens?: number;
47
+ /** Our own estimate of the prompt we actually sent. */
48
+ estimatedPromptTokens?: number;
49
+ /** Provider/local calibration already applied to the prompt estimate. */
50
+ calibrationRatio?: number;
51
+ /**
52
+ * System prompt plus tool schemas — the part of the budget compaction
53
+ * cannot touch. A corrected budget at or below this leaves no room for
54
+ * messages, and the summarize node refuses to run, so recovery is declined
55
+ * rather than entered.
56
+ */
57
+ instructionTokens?: number;
58
+ /** Whether a model-backed summary can compact messages without a pruner. */
59
+ canSummarize?: boolean;
60
+ /**
61
+ * Completion allowance the caller configured. Providers count it against
62
+ * the same ceiling, so it has to come off the top when the error itself did
63
+ * not break the total down.
64
+ */
65
+ configuredCompletionTokens?: number;
66
+ /** Recoveries already attempted for this agent in this run. */
67
+ attemptsSoFar: number;
68
+ maxAttempts?: number;
69
+ }
70
+ /**
71
+ * Converts a provider-space retry budget into the units consumed by a pruner
72
+ * calibrated for another provider while preserving the same raw-token limit.
73
+ */
74
+ export declare function translateRecoveryBudget(budgetTokens: number | undefined, sourceCalibrationRatio: number | undefined, targetCalibrationRatio: number | undefined): number | undefined;
75
+ /** Applies the conservative shrink used when no provider-space ceiling is usable. */
76
+ export declare function getBlindRecoveryBudget(maxContextTokens: number | undefined): number | undefined;
77
+ /**
78
+ * Decides whether a failed model call is a recoverable context overflow and,
79
+ * if so, what budget the retry should be re-pruned against.
80
+ *
81
+ * Returns `null` when the error is something compaction cannot fix, or when
82
+ * the per-run recovery budget is spent — in both cases the caller should let
83
+ * its normal failure handling proceed.
84
+ */
85
+ export declare function planContextOverflowRecovery({ error, provider, maxContextTokens, estimatedPromptTokens, calibrationRatio, instructionTokens, canSummarize, configuredCompletionTokens, attemptsSoFar, maxAttempts, }: OverflowRecoveryParams): OverflowRecoveryPlan | null;
@@ -2,6 +2,7 @@ import { AIMessageChunk } from '@langchain/core/messages';
2
2
  import type { RunnableConfig } from '@langchain/core/runnables';
3
3
  import type { BaseMessage } from '@langchain/core/messages';
4
4
  import type { ToolOutputReferenceRegistry } from '@/tools/toolOutputReferences';
5
+ import type { ContextOverflowContext } from '@/utils/errors';
5
6
  import type * as t from '@/types';
6
7
  import { Providers } from '@/common';
7
8
  import { ChatModelStreamHandler } from '@/stream';
@@ -56,19 +57,47 @@ export declare function attemptInvoke({ model, messages, provider, context, onCh
56
57
  context?: InvokeContext;
57
58
  onChunk?: OnChunk;
58
59
  }, config?: RunnableConfig): Promise<Partial<t.BaseGraphState>>;
60
+ /**
61
+ * Identifies which fallback produced an error, so a caller planning a
62
+ * recovery can reason about the client that actually failed rather than the
63
+ * primary's configuration — their context windows and output allowances
64
+ * differ, which is the whole reason a fallback exists.
65
+ */
66
+ export interface FallbackErrorContext {
67
+ provider: Providers;
68
+ clientOptions?: t.ClientOptions;
69
+ maxContextTokens?: number;
70
+ }
71
+ export interface FallbackOverflowCandidate {
72
+ error: unknown;
73
+ context: FallbackErrorContext;
74
+ }
75
+ /** Reads back the fallback attribution attached by `tryFallbackProviders`. */
76
+ export declare function getFallbackErrorContext(error: unknown): FallbackErrorContext | undefined;
77
+ /** Returns every fallback overflow retained from an exhausted provider chain. */
78
+ export declare function getFallbackOverflowCandidates(error: unknown): FallbackOverflowCandidate[];
59
79
  /**
60
80
  * Attempts each fallback provider in order until one succeeds.
61
- * Throws the last error if all fallbacks fail.
81
+ *
82
+ * When every fallback fails, a context overflow among them is thrown in
83
+ * preference to whichever failure happened to come last. An overflow is the
84
+ * one failure the caller can act on — it compacts and retries — and losing it
85
+ * behind a later unrelated error would surface a dead end instead. Ordinary
86
+ * failures still throw last-error-wins.
62
87
  */
63
- export declare function tryFallbackProviders({ fallbacks, tools, messages, config, primaryError, context, onChunk, }: {
64
- fallbacks: Array<{
65
- provider: Providers;
66
- clientOptions?: t.ClientOptions;
67
- }>;
88
+ export declare function tryFallbackProviders({ fallbacks, tools, messages, config, primaryError, context, onChunk, overflowContext, }: {
89
+ fallbacks: t.FallbackConfig[];
68
90
  tools?: t.GraphTools;
69
91
  messages: BaseMessage[];
70
92
  config?: RunnableConfig;
71
93
  primaryError: unknown;
72
94
  context?: InvokeContext;
73
95
  onChunk?: OnChunk;
96
+ /**
97
+ * Prompt-size corroboration for signatures that are not self-describing.
98
+ * Vertex AI's overflow is a bare `400` with no reason, so without this a
99
+ * fallback that overflows is indistinguishable from any other 400 and would
100
+ * be dropped in favour of whichever failure came last.
101
+ */
102
+ overflowContext?: ContextOverflowContext;
74
103
  }): Promise<Partial<t.BaseGraphState> | undefined>;
@@ -15,6 +15,13 @@ export declare const ORIGINAL_CONTENT_MAX_CHARS = 2000000;
15
15
  * recency carry-over bypasses that cap unless re-applied here.
16
16
  */
17
17
  export declare function enforceOriginalContentCap(map: Map<number, string>): void;
18
+ /** Minimum cumulative calibration ratio — provider can't count fewer tokens
19
+ * than our raw estimate (within reason). Prevents divide-by-zero edge cases. */
20
+ export declare const CALIBRATION_RATIO_MIN = 0.5;
21
+ /** Maximum cumulative calibration ratio — sanity cap for the running ratio. */
22
+ export declare const CALIBRATION_RATIO_MAX = 5;
23
+ /** Keeps provider/local token calibration within the shared safe range. */
24
+ export declare function clampCalibrationRatio(ratio: number): number;
18
25
  export type PruneMessagesFactoryParams = {
19
26
  provider?: Providers;
20
27
  maxTokens: number;
@@ -172,8 +179,8 @@ export declare function maskConsumedToolResults(params: {
172
179
  /** When provided, original (pre-masking) content is stored here keyed by
173
180
  * message index — only for entries that actually get truncated. */
174
181
  originalContentStore?: Map<number, string>;
175
- /** Called after storing content with the char length of the stored entry. */
176
- onContentStored?: (charLength: number) => void;
182
+ /** Called after storing a newly captured entry. */
183
+ onContentStored?: (index: number, content: string) => void;
177
184
  }): number;
178
185
  /**
179
186
  * Pre-flight truncation: truncates oversized ToolMessage content before the
@@ -219,6 +226,7 @@ export declare function createPruneMessages(factoryParams: PruneMessagesFactoryP
219
226
  remainingContextTokens?: number;
220
227
  contextPressure?: number;
221
228
  originalToolContent?: Map<number, string>;
229
+ newOriginalToolContent?: Map<number, string>;
222
230
  calibrationRatio?: number;
223
231
  resolvedInstructionOverhead?: number;
224
232
  /** Usable budget this call: maxTokens minus output reserve */
@@ -1,4 +1,5 @@
1
1
  import type { BaseMessage } from '@langchain/core/messages';
2
+ export declare const DEFAULT_RETAIN_RECENT_TURNS = 2;
2
3
  /**
3
4
  * Configuration for splitting a message list into a head (to be summarized)
4
5
  * and a tail (to be preserved verbatim).
@@ -41,6 +41,8 @@ export declare class Run<_T extends t.BaseGraphState> {
41
41
  private _interrupt;
42
42
  /** Per-run sequence for batch-unique activity-label trace-seed fallbacks. */
43
43
  private activityLabelSeq;
44
+ /** Distinguishes sibling forks started from the same explicit checkpoint. */
45
+ private checkpointForkSeq;
44
46
  private _haltedReason;
45
47
  private constructor();
46
48
  private createLegacyGraph;
@@ -32,8 +32,21 @@ export declare const CodeExecutionToolSchema: {
32
32
  };
33
33
  readonly required: readonly ["lang", "code"];
34
34
  };
35
+ export declare const CODE_API_UNAVAILABLE_ERROR_MESSAGE = "Code execution is temporarily unavailable. Please retry.";
36
+ export declare const CODE_API_AUTHORIZATION_ERROR_MESSAGE = "Code execution is not authorized. Verify access before trying again.";
37
+ export declare const CODE_API_EXECUTION_FAILED_ERROR_MESSAGE = "Code execution failed.";
38
+ export declare const CODE_API_INVALID_REQUEST_ERROR_MESSAGE = "The code execution request was rejected. Please check the tool input and try again.";
39
+ export declare const CODE_API_RATE_LIMITED_ERROR_MESSAGE = "Code execution is temporarily rate-limited. Please retry shortly.";
40
+ export declare class CodeApiRequestError extends Error {
41
+ constructor(message?: string);
42
+ }
43
+ export declare function normalizeCodeApiRequestError(error: unknown): CodeApiRequestError;
44
+ export declare function buildCodeApiExecutionErrorMessage(response: {
45
+ error?: unknown;
46
+ stderr?: unknown;
47
+ }): string;
35
48
  export declare function resolveCodeApiAuthHeaders(authHeaders?: t.CodeApiAuthHeaders): Promise<t.CodeApiAuthHeaderMap>;
36
- export declare function buildCodeApiHttpErrorMessage(method: string, endpoint: string, response: {
49
+ export declare function buildCodeApiHttpErrorMessage(_method: string, _endpoint: string, response: {
37
50
  status: number;
38
51
  text: () => Promise<string>;
39
52
  }): Promise<string>;
@@ -103,12 +103,15 @@ export type SharedLLMConfig = {
103
103
  provider: Providers;
104
104
  _lc_stream_delay?: number;
105
105
  };
106
+ export interface FallbackConfig {
107
+ provider: Providers;
108
+ clientOptions?: ClientOptions;
109
+ /** Context window used to corroborate ambiguous fallback overflow errors. */
110
+ maxContextTokens?: number;
111
+ }
106
112
  export type LLMConfig = SharedLLMConfig & ClientOptions & {
107
113
  /** Optional provider fallbacks in order of attempt */
108
- fallbacks?: Array<{
109
- provider: Providers;
110
- clientOptions?: ClientOptions;
111
- }>;
114
+ fallbacks?: FallbackConfig[];
112
115
  };
113
116
  export type ProviderOptionsMap = {
114
117
  [Providers.AZURE]: AzureClientOptions;
@@ -40,13 +40,14 @@ export type RunStep = {
40
40
  runId?: string;
41
41
  agentId?: string;
42
42
  /**
43
- * Group ID - incrementing number (1, 2, 3...) reflecting execution order.
44
- * Agents with the same groupId run in parallel and should be rendered together.
45
- * undefined means the agent runs sequentially (not part of any parallel group).
43
+ * Opaque positive safe-integer identifier for parallel execution.
44
+ * Agents with the same groupId should be rendered together.
45
+ * Consumers must use content indexes, not groupId ordering, for execution order.
46
+ * undefined means the agent runs sequentially (not part of a parallel group).
46
47
  *
47
48
  * Example for: researcher -> [analyst1, analyst2, analyst3] -> summarizer
48
49
  * - researcher: undefined (sequential)
49
- * - analyst1, analyst2, analyst3: 1 (first parallel group)
50
+ * - analyst1, analyst2, analyst3: the same groupId (parallel group)
50
51
  * - summarizer: undefined (sequential)
51
52
  */
52
53
  groupId?: number;
@@ -54,6 +54,28 @@ export interface SummarizeResult {
54
54
  export interface SummarizationNodeInput {
55
55
  remainingContextTokens: number;
56
56
  agentId: string;
57
+ /**
58
+ * Why the detour was requested.
59
+ *
60
+ * - `trigger` (default): the configured summarization trigger fired during
61
+ * the pre-call budget check.
62
+ * - `overflow`: the provider rejected the prompt as too large and the run
63
+ * is compacting to recover. When summarization is not enabled, this
64
+ * variant performs no model call — the corrected budget alone is what the
65
+ * retry needs.
66
+ */
67
+ reason?: 'trigger' | 'overflow';
68
+ /**
69
+ * Whether an overflow recovery may spend a summarization model call.
70
+ *
71
+ * The first recovery deliberately does not: re-pruning against the
72
+ * corrected budget raises context pressure, which drives the pruner's
73
+ * existing tool-output compression and masking. That is cheaper, needs no
74
+ * model call, and cannot lose message content the way a summary can. Only
75
+ * when deterministic compression proves insufficient does the next attempt
76
+ * allow the summarizer to run.
77
+ */
78
+ allowSummarization?: boolean;
57
79
  }
58
80
  export interface SummarizeStartEvent {
59
81
  agentId: string;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Provider error signatures captured from live over-limit requests.
3
+ *
4
+ * Every entry below was produced by `src/scripts/context-overflow-probe.ts`
5
+ * sending a prompt past the model's context window and recording what came
6
+ * back. Account identifiers and request ids have been replaced with
7
+ * placeholders; the wording, status codes, and nesting are verbatim.
8
+ *
9
+ * Treat these as evidence, not examples: if a provider changes its wording,
10
+ * re-run the probe and update the fixture rather than loosening the matcher.
11
+ */
12
+ import { Providers } from '@/common';
13
+ export interface OverflowSignature {
14
+ provider: Providers;
15
+ model: string;
16
+ /** Class the SDK actually threw, for reference in review. */
17
+ thrownAs: string;
18
+ /**
19
+ * Stand-in for the thrown error carrying exactly the fields the classifier
20
+ * reads. Nested bodies are kept as the strings the SDKs attach.
21
+ */
22
+ error: Record<string, unknown>;
23
+ expected: {
24
+ kind: 'context_window' | 'request_too_large';
25
+ limitTokens?: number;
26
+ requestedTokens?: number;
27
+ };
28
+ /** Set when the signature is only decidable with caller-side corroboration. */
29
+ requiresContextPressure?: boolean;
30
+ }
31
+ export declare const OVERFLOW_SIGNATURES: readonly OverflowSignature[];
32
+ /**
33
+ * Errors that mention limits, sizes, or tokens but are NOT fixed by
34
+ * compaction. The first two were captured live alongside the signatures
35
+ * above; the rest are the adjacent failures a loose matcher would swallow.
36
+ */
37
+ export declare const NON_OVERFLOW_SIGNATURES: readonly {
38
+ label: string;
39
+ error: Record<string, unknown>;
40
+ }[];
@@ -1,28 +1,77 @@
1
+ import type { Providers } from '@/common';
1
2
  /**
2
- * Context overflow error detection utilities.
3
- *
4
- * Identifies provider-specific error messages that indicate the request
5
- * exceeded the model's context window. Used by the overflow recovery loop
6
- * to decide whether to retry with truncation/compaction vs. propagating
7
- * the error.
3
+ * Why the request was rejected. Both kinds are fixed by shrinking the
4
+ * prompt, which is what makes them recoverable; they are distinguished
5
+ * because only `context_window` tells us the model's true window.
6
+ */
7
+ export type ContextOverflowKind =
8
+ /** Input exceeded the model's context window. */
9
+ 'context_window'
10
+ /**
11
+ * A single request exceeded a per-minute token allowance. Waiting cannot
12
+ * help — the request can never fit the bucket — so this is a payload
13
+ * problem wearing a 429, not throttling.
8
14
  */
15
+ | 'request_too_large';
16
+ export interface ContextOverflowInfo {
17
+ kind: ContextOverflowKind;
18
+ /** Ceiling the provider reported, when it named one. */
19
+ limitTokens?: number;
20
+ /**
21
+ * Token count the provider attributed to the whole request. Several
22
+ * providers fold the requested completion allowance into this number, so it
23
+ * is not interchangeable with the prompt size.
24
+ */
25
+ requestedTokens?: number;
26
+ /**
27
+ * The prompt alone, counted by the provider — set only when the provider
28
+ * distinguished input from output, either by reporting an input-only figure
29
+ * or by breaking the total down. Callers comparing provider counts against
30
+ * their own prompt estimate must use this and not `requestedTokens`, whose
31
+ * completion component would inflate the comparison.
32
+ */
33
+ promptTokens?: number;
34
+ /** Which layer produced the verdict. Surfaced in logs and asserted in tests. */
35
+ source: 'langchain' | 'pattern';
36
+ provider?: Providers;
37
+ }
38
+ export interface ContextOverflowContext {
39
+ provider?: Providers;
40
+ /** Our own estimate of the prompt size for the call that failed. */
41
+ estimatedPromptTokens?: number;
42
+ /** The budget we believed applied when we built that prompt. */
43
+ maxContextTokens?: number;
44
+ }
9
45
  /**
10
46
  * Extracts a human-readable error message from an unknown error value.
11
47
  */
12
48
  export declare function extractErrorMessage(error: unknown): string;
13
49
  /**
14
- * Returns true if the error message definitively indicates a context
15
- * overflow / prompt-too-large error from the provider.
50
+ * Classifies a provider error as a recoverable context overflow, returning
51
+ * whatever the provider disclosed about the limit and the request size.
52
+ *
53
+ * Returns `null` for anything that compaction cannot fix — genuine
54
+ * throttling, auth, quota, and output-token-cap errors all mention limits
55
+ * and must not be mistaken for overflow.
56
+ *
57
+ * The reported numbers are the point of the return value: they let the
58
+ * caller retarget the token budget to the provider's real ceiling instead of
59
+ * retrying blindly against a configured value that was evidently wrong.
60
+ */
61
+ export declare function getContextOverflowInfo(error: unknown, context?: ContextOverflowContext): ContextOverflowInfo | null;
62
+ /**
63
+ * Returns true if the error definitively indicates a context overflow.
16
64
  *
17
- * This is the strict check: only matches known, unambiguous phrases.
18
- * Use this when you want high confidence before taking recovery action.
65
+ * Accepts either a raw error or a pre-extracted message; passing the error
66
+ * itself is preferred, since several providers report the decisive detail in
67
+ * a nested body rather than in `message`.
19
68
  */
20
- export declare function isContextOverflowError(errorMessage?: string): boolean;
69
+ export declare function isContextOverflowError(error?: unknown, context?: ContextOverflowContext): boolean;
21
70
  /**
22
- * Returns true if the error message likely indicates a context overflow.
23
- * Uses broader heuristic matching (regex) in addition to exact phrases.
71
+ * Returns true if the error likely indicates a context overflow, adding
72
+ * body-size and token-count heuristics on top of the definitive patterns.
24
73
  *
25
- * May produce false positives for unusual error messages. Use this when
26
- * the cost of a false positive (one extra retry) is acceptable.
74
+ * May produce false positives on unusual messages. Use when the cost of
75
+ * being wrong is one extra compaction pass.
27
76
  */
28
- export declare function isLikelyContextOverflowError(errorMessage?: string): boolean;
77
+ export declare function isLikelyContextOverflowError(error?: unknown, context?: ContextOverflowContext): boolean;
@@ -0,0 +1,3 @@
1
+ export declare function isSecretKey(key: string): boolean;
2
+ /** Recursively removes credentials from structured diagnostic payloads. */
3
+ export declare function redactSecrets(value: unknown, seen?: WeakSet<object>): unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@librechat/agents",
3
- "version": "3.3.0",
3
+ "version": "3.3.1",
4
4
  "main": "./dist/cjs/main.cjs",
5
5
  "module": "./dist/esm/main.mjs",
6
6
  "types": "./dist/types/index.d.ts",
@@ -140,6 +140,7 @@
140
140
  "search": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/search.ts --provider 'bedrock' --name 'Jo' --location 'New York, NY'",
141
141
  "tool_search": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/tool_search.ts",
142
142
  "bench:cache": "node --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/bench-prompt-cache.ts",
143
+ "probe:overflow": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/context-overflow-probe.ts",
143
144
  "subagent": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/multi-agent-subagent.ts",
144
145
  "subagent:events": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/subagent-event-driven-debug.ts",
145
146
  "subagent:tools": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/subagent-tools-debug.ts",
@@ -205,11 +206,9 @@
205
206
  "openai": "$openai"
206
207
  },
207
208
  "uuid": "$uuid",
208
- "fast-xml-parser": "5.7.2",
209
209
  "ajv": "6.14.0",
210
- "minimatch": "3.1.4",
211
210
  "@opentelemetry/core": "^2.9.0",
212
- "js-yaml": "^4.2.0"
211
+ "js-yaml": "^4.3.0"
213
212
  },
214
213
  "dependencies": {
215
214
  "@anthropic-ai/sdk": "^0.103.0",
@@ -235,7 +234,7 @@
235
234
  "@scarf/scarf": "^1.4.0",
236
235
  "@types/diff": "^7.0.2",
237
236
  "ai-tokenizer": "^1.0.6",
238
- "axios": "^1.16.0",
237
+ "axios": "^1.18.1",
239
238
  "cheerio": "^1.0.0",
240
239
  "diff": "^9.0.0",
241
240
  "dotenv": "^16.4.7",
@@ -247,7 +246,7 @@
247
246
  "uuid": "^11.1.1"
248
247
  },
249
248
  "peerDependencies": {
250
- "@anthropic-ai/sandbox-runtime": "^0.0.54"
249
+ "@anthropic-ai/sandbox-runtime": "^0.0.67"
251
250
  },
252
251
  "peerDependenciesMeta": {
253
252
  "@anthropic-ai/sandbox-runtime": {
@@ -259,7 +258,7 @@
259
258
  "~/*": "./*"
260
259
  },
261
260
  "devDependencies": {
262
- "@anthropic-ai/sandbox-runtime": "^0.0.54",
261
+ "@anthropic-ai/sandbox-runtime": "^0.0.67",
263
262
  "@anthropic-ai/vertex-sdk": "^0.12.0",
264
263
  "@eslint/compat": "^1.2.7",
265
264
  "@langchain/langgraph-checkpoint-mongodb": "^1.4.0",
@@ -270,7 +269,7 @@
270
269
  "@types/yargs-parser": "^21.0.3",
271
270
  "@typescript-eslint/eslint-plugin": "^8.24.0",
272
271
  "@typescript-eslint/parser": "^8.24.0",
273
- "eslint": "^9.39.1",
272
+ "eslint": "^9.39.5",
274
273
  "eslint-import-resolver-typescript": "^3.7.0",
275
274
  "eslint-plugin-import": "^2.31.0",
276
275
  "husky": "^9.1.7",