@librechat/agents 3.6.15 → 3.7.0

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 (180) hide show
  1. package/README.md +41 -0
  2. package/dist/cjs/_virtual/_rolldown/runtime.cjs +10 -0
  3. package/dist/cjs/agents/AgentContext.cjs +1 -1
  4. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +13 -13
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/lazyRequire.cjs +33 -0
  8. package/dist/cjs/lazyRequire.cjs.map +1 -0
  9. package/dist/cjs/llm/anthropic/index.cjs +13 -0
  10. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  11. package/dist/cjs/llm/bedrock/index.cjs +10 -1
  12. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  13. package/dist/cjs/llm/bedrock/toolCache.cjs +3 -2
  14. package/dist/cjs/llm/bedrock/toolCache.cjs.map +1 -1
  15. package/dist/cjs/llm/google/index.cjs +10 -1
  16. package/dist/cjs/llm/google/index.cjs.map +1 -1
  17. package/dist/cjs/llm/init.cjs +7 -4
  18. package/dist/cjs/llm/init.cjs.map +1 -1
  19. package/dist/cjs/llm/invoke.cjs +9 -2
  20. package/dist/cjs/llm/invoke.cjs.map +1 -1
  21. package/dist/cjs/llm/mistral/index.cjs +9 -0
  22. package/dist/cjs/llm/mistral/index.cjs.map +1 -1
  23. package/dist/cjs/llm/openai/index.cjs +41 -1
  24. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  25. package/dist/cjs/llm/openrouter/index.cjs +12 -3
  26. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  27. package/dist/cjs/llm/openrouter/toolCache.cjs +3 -2
  28. package/dist/cjs/llm/openrouter/toolCache.cjs.map +1 -1
  29. package/dist/cjs/llm/prepareProviderRequest.cjs +6 -3
  30. package/dist/cjs/llm/prepareProviderRequest.cjs.map +1 -1
  31. package/dist/cjs/llm/providerRegistry.cjs +81 -0
  32. package/dist/cjs/llm/providerRegistry.cjs.map +1 -0
  33. package/dist/cjs/llm/providers.cjs +37 -28
  34. package/dist/cjs/llm/providers.cjs.map +1 -1
  35. package/dist/cjs/llm/providers.eager.cjs +21 -0
  36. package/dist/cjs/llm/providers.eager.cjs.map +1 -0
  37. package/dist/cjs/llm/request.cjs +6 -4
  38. package/dist/cjs/llm/request.cjs.map +1 -1
  39. package/dist/cjs/llm/truncation.cjs +2 -1
  40. package/dist/cjs/llm/truncation.cjs.map +1 -1
  41. package/dist/cjs/llm/vertexai/index.cjs +17 -0
  42. package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
  43. package/dist/cjs/main.cjs +19 -18
  44. package/dist/cjs/messages/core.cjs +9 -4
  45. package/dist/cjs/messages/core.cjs.map +1 -1
  46. package/dist/cjs/messages/format.cjs.map +1 -1
  47. package/dist/cjs/messages/prune.cjs +50 -12
  48. package/dist/cjs/messages/prune.cjs.map +1 -1
  49. package/dist/cjs/provider-registration.cjs +4 -0
  50. package/dist/cjs/run.cjs +9 -4
  51. package/dist/cjs/run.cjs.map +1 -1
  52. package/dist/cjs/stream.cjs +1 -1
  53. package/dist/cjs/stream.cjs.map +1 -1
  54. package/dist/cjs/summarization/node.cjs +2 -2
  55. package/dist/cjs/summarization/node.cjs.map +1 -1
  56. package/dist/cjs/tools/Calculator.cjs +7 -4
  57. package/dist/cjs/tools/Calculator.cjs.map +1 -1
  58. package/dist/cjs/tools/CodeExecutor.cjs +1 -1
  59. package/dist/cjs/utils/llm.cjs +22 -4
  60. package/dist/cjs/utils/llm.cjs.map +1 -1
  61. package/dist/esm/_virtual/_rolldown/runtime.mjs +14 -0
  62. package/dist/esm/agents/AgentContext.mjs +1 -1
  63. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  64. package/dist/esm/graphs/Graph.mjs +13 -13
  65. package/dist/esm/graphs/Graph.mjs.map +1 -1
  66. package/dist/esm/lazyRequire.mjs +30 -0
  67. package/dist/esm/lazyRequire.mjs.map +1 -0
  68. package/dist/esm/llm/anthropic/index.mjs +6 -1
  69. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  70. package/dist/esm/llm/bedrock/index.mjs +4 -2
  71. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  72. package/dist/esm/llm/bedrock/toolCache.mjs +3 -2
  73. package/dist/esm/llm/bedrock/toolCache.mjs.map +1 -1
  74. package/dist/esm/llm/google/index.mjs +4 -2
  75. package/dist/esm/llm/google/index.mjs.map +1 -1
  76. package/dist/esm/llm/init.mjs +8 -5
  77. package/dist/esm/llm/init.mjs.map +1 -1
  78. package/dist/esm/llm/invoke.mjs +9 -2
  79. package/dist/esm/llm/invoke.mjs.map +1 -1
  80. package/dist/esm/llm/mistral/index.mjs +3 -1
  81. package/dist/esm/llm/mistral/index.mjs.map +1 -1
  82. package/dist/esm/llm/openai/index.mjs +31 -9
  83. package/dist/esm/llm/openai/index.mjs.map +1 -1
  84. package/dist/esm/llm/openrouter/index.mjs +3 -1
  85. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  86. package/dist/esm/llm/openrouter/toolCache.mjs +3 -2
  87. package/dist/esm/llm/openrouter/toolCache.mjs.map +1 -1
  88. package/dist/esm/llm/prepareProviderRequest.mjs +7 -4
  89. package/dist/esm/llm/prepareProviderRequest.mjs.map +1 -1
  90. package/dist/esm/llm/providerRegistry.mjs +76 -0
  91. package/dist/esm/llm/providerRegistry.mjs.map +1 -0
  92. package/dist/esm/llm/providers.eager.mjs +22 -0
  93. package/dist/esm/llm/providers.eager.mjs.map +1 -0
  94. package/dist/esm/llm/providers.mjs +38 -28
  95. package/dist/esm/llm/providers.mjs.map +1 -1
  96. package/dist/esm/llm/request.mjs +6 -4
  97. package/dist/esm/llm/request.mjs.map +1 -1
  98. package/dist/esm/llm/truncation.mjs +2 -1
  99. package/dist/esm/llm/truncation.mjs.map +1 -1
  100. package/dist/esm/llm/vertexai/index.mjs +8 -1
  101. package/dist/esm/llm/vertexai/index.mjs.map +1 -1
  102. package/dist/esm/main.mjs +12 -13
  103. package/dist/esm/messages/core.mjs +9 -5
  104. package/dist/esm/messages/core.mjs.map +1 -1
  105. package/dist/esm/messages/format.mjs.map +1 -1
  106. package/dist/esm/messages/prune.mjs +50 -13
  107. package/dist/esm/messages/prune.mjs.map +1 -1
  108. package/dist/esm/provider-registration.mjs +3 -0
  109. package/dist/esm/run.mjs +10 -5
  110. package/dist/esm/run.mjs.map +1 -1
  111. package/dist/esm/stream.mjs +1 -1
  112. package/dist/esm/stream.mjs.map +1 -1
  113. package/dist/esm/summarization/node.mjs +2 -2
  114. package/dist/esm/summarization/node.mjs.map +1 -1
  115. package/dist/esm/tools/Calculator.mjs +7 -2
  116. package/dist/esm/tools/Calculator.mjs.map +1 -1
  117. package/dist/esm/tools/CodeExecutor.mjs +1 -1
  118. package/dist/esm/utils/llm.mjs +21 -5
  119. package/dist/esm/utils/llm.mjs.map +1 -1
  120. package/dist/types/agents/AgentContext.d.ts +5 -5
  121. package/dist/types/index.d.ts +5 -3
  122. package/dist/types/lazyRequire.d.ts +8 -0
  123. package/dist/types/llm/contextOverflowRecovery.d.ts +2 -2
  124. package/dist/types/llm/init.d.ts +21 -14
  125. package/dist/types/llm/invoke.d.ts +5 -6
  126. package/dist/types/llm/prepareProviderRequest.d.ts +5 -6
  127. package/dist/types/llm/providerRegistry.d.ts +22 -0
  128. package/dist/types/llm/providers.d.ts +4 -5
  129. package/dist/types/llm/providers.eager.d.ts +1 -0
  130. package/dist/types/llm/request.d.ts +2 -3
  131. package/dist/types/llm/truncation.d.ts +2 -2
  132. package/dist/types/messages/core.d.ts +3 -2
  133. package/dist/types/messages/format.d.ts +3 -3
  134. package/dist/types/messages/prune.d.ts +8 -6
  135. package/dist/types/provider-registration.d.ts +15 -0
  136. package/dist/types/stream.d.ts +1 -2
  137. package/dist/types/summarization/node.d.ts +1 -2
  138. package/dist/types/types/activityLabel.d.ts +3 -4
  139. package/dist/types/types/graph.d.ts +4 -5
  140. package/dist/types/types/llm.d.ts +54 -13
  141. package/dist/types/types/reasoningLabel.d.ts +2 -3
  142. package/dist/types/types/run.d.ts +3 -3
  143. package/dist/types/types/summarize.d.ts +2 -2
  144. package/dist/types/utils/errors.d.ts +3 -3
  145. package/dist/types/utils/llm.d.ts +14 -4
  146. package/dist/types/utils/llmConfig.d.ts +2 -2
  147. package/package.json +66 -1
  148. package/src/agents/AgentContext.ts +27 -26
  149. package/src/graphs/Graph.ts +16 -22
  150. package/src/index.ts +8 -3
  151. package/src/lazyRequire.ts +67 -0
  152. package/src/llm/bedrock/toolCache.ts +6 -2
  153. package/src/llm/contextOverflowRecovery.ts +2 -2
  154. package/src/llm/init.ts +55 -25
  155. package/src/llm/invoke.ts +36 -21
  156. package/src/llm/openrouter/toolCache.ts +8 -2
  157. package/src/llm/prepareProviderRequest.ts +19 -18
  158. package/src/llm/providerRegistry.ts +174 -0
  159. package/src/llm/providers.eager.ts +24 -0
  160. package/src/llm/providers.ts +99 -42
  161. package/src/llm/request.ts +10 -6
  162. package/src/llm/truncation.ts +9 -3
  163. package/src/messages/core.ts +18 -13
  164. package/src/messages/format.ts +14 -16
  165. package/src/messages/prune.ts +108 -28
  166. package/src/provider-registration.ts +29 -0
  167. package/src/run.ts +15 -7
  168. package/src/session/AgentSession.ts +1 -1
  169. package/src/stream.ts +7 -8
  170. package/src/summarization/node.ts +7 -7
  171. package/src/tools/Calculator.ts +9 -2
  172. package/src/types/activityLabel.ts +3 -4
  173. package/src/types/graph.ts +5 -5
  174. package/src/types/llm.ts +95 -13
  175. package/src/types/reasoningLabel.ts +2 -3
  176. package/src/types/run.ts +3 -3
  177. package/src/types/summarize.ts +2 -2
  178. package/src/utils/errors.ts +3 -3
  179. package/src/utils/llm.ts +61 -15
  180. package/src/utils/llmConfig.ts +4 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@librechat/agents",
3
- "version": "3.6.15",
3
+ "version": "3.7.0",
4
4
  "reova": {
5
5
  "enabled": true,
6
6
  "endpoint": "https://telemetry.reo.dev/data"
@@ -14,6 +14,11 @@
14
14
  "import": "./dist/esm/main.mjs",
15
15
  "require": "./dist/cjs/main.cjs"
16
16
  },
17
+ "./provider-registration": {
18
+ "types": "./dist/types/provider-registration.d.ts",
19
+ "import": "./dist/esm/provider-registration.mjs",
20
+ "require": "./dist/cjs/provider-registration.cjs"
21
+ },
17
22
  "./openai": {
18
23
  "types": "./dist/types/openai/index.d.ts",
19
24
  "import": "./dist/esm/openai/index.mjs",
@@ -73,10 +78,48 @@
73
78
  "types": "./dist/types/langchain/utils/env.d.ts",
74
79
  "import": "./dist/esm/langchain/utils/env.mjs",
75
80
  "require": "./dist/cjs/langchain/utils/env.cjs"
81
+ },
82
+ "./llm/openai": {
83
+ "types": "./dist/types/llm/openai/index.d.ts",
84
+ "import": "./dist/esm/llm/openai/index.mjs",
85
+ "require": "./dist/cjs/llm/openai/index.cjs"
86
+ },
87
+ "./llm/mistral": {
88
+ "types": "./dist/types/llm/mistral/index.d.ts",
89
+ "import": "./dist/esm/llm/mistral/index.mjs",
90
+ "require": "./dist/cjs/llm/mistral/index.cjs"
91
+ },
92
+ "./llm/anthropic": {
93
+ "types": "./dist/types/llm/anthropic/index.d.ts",
94
+ "import": "./dist/esm/llm/anthropic/index.mjs",
95
+ "require": "./dist/cjs/llm/anthropic/index.cjs"
96
+ },
97
+ "./llm/google": {
98
+ "types": "./dist/types/llm/google/index.d.ts",
99
+ "import": "./dist/esm/llm/google/index.mjs",
100
+ "require": "./dist/cjs/llm/google/index.cjs"
101
+ },
102
+ "./llm/bedrock": {
103
+ "types": "./dist/types/llm/bedrock/index.d.ts",
104
+ "import": "./dist/esm/llm/bedrock/index.mjs",
105
+ "require": "./dist/cjs/llm/bedrock/index.cjs"
106
+ },
107
+ "./llm/vertexai": {
108
+ "types": "./dist/types/llm/vertexai/index.d.ts",
109
+ "import": "./dist/esm/llm/vertexai/index.mjs",
110
+ "require": "./dist/cjs/llm/vertexai/index.cjs"
111
+ },
112
+ "./llm/openrouter": {
113
+ "types": "./dist/types/llm/openrouter/index.d.ts",
114
+ "import": "./dist/esm/llm/openrouter/index.mjs",
115
+ "require": "./dist/cjs/llm/openrouter/index.cjs"
76
116
  }
77
117
  },
78
118
  "typesVersions": {
79
119
  "*": {
120
+ "provider-registration": [
121
+ "dist/types/provider-registration.d.ts"
122
+ ],
80
123
  "langchain": [
81
124
  "dist/types/langchain/index.d.ts"
82
125
  ],
@@ -88,6 +131,27 @@
88
131
  ],
89
132
  "responses": [
90
133
  "dist/types/responses/index.d.ts"
134
+ ],
135
+ "llm/openai": [
136
+ "./dist/types/llm/openai/index.d.ts"
137
+ ],
138
+ "llm/mistral": [
139
+ "./dist/types/llm/mistral/index.d.ts"
140
+ ],
141
+ "llm/anthropic": [
142
+ "./dist/types/llm/anthropic/index.d.ts"
143
+ ],
144
+ "llm/google": [
145
+ "./dist/types/llm/google/index.d.ts"
146
+ ],
147
+ "llm/bedrock": [
148
+ "./dist/types/llm/bedrock/index.d.ts"
149
+ ],
150
+ "llm/vertexai": [
151
+ "./dist/types/llm/vertexai/index.d.ts"
152
+ ],
153
+ "llm/openrouter": [
154
+ "./dist/types/llm/openrouter/index.d.ts"
91
155
  ]
92
156
  }
93
157
  },
@@ -154,6 +218,7 @@
154
218
  "tool_search": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/tool_search.ts",
155
219
  "bench:cache": "node --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/bench-prompt-cache.ts",
156
220
  "bench:context-pressure": "node --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/bench-context-pressure-cache.ts",
221
+ "bench:provider-derivation": "node --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/bench-provider-derivation.ts",
157
222
  "bench:execution-world": "node --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/bench-execution-world.ts",
158
223
  "probe:overflow": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/context-overflow-probe.ts",
159
224
  "subagent": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/multi-agent-subagent.ts",
@@ -7,8 +7,18 @@ import type {
7
7
  BaseMessageFields,
8
8
  } from '@langchain/core/messages';
9
9
  import type { RunnableConfig, Runnable } from '@langchain/core/runnables';
10
- import type * as t from '@/types';
11
10
  import type { ExactTokenCountCache } from '@/llm/contextPressureMeter';
11
+ import type * as t from '@/types';
12
+ import {
13
+ type CallerCapabilityProjection,
14
+ allowsToolCaller,
15
+ applyCallerCapabilityDefinitionOverrides,
16
+ createCallerCapabilityProjectionSnapshot,
17
+ isToolDefinitionActive,
18
+ isProgrammaticControlTool,
19
+ mergeCallerCapabilityDefinitions,
20
+ resolveCallerCapabilityProjection,
21
+ } from '@/tools/CallerCapabilities';
12
22
  import {
13
23
  addTailCacheControl,
14
24
  addCacheControlToStablePrefixMessages,
@@ -19,6 +29,12 @@ import {
19
29
  cloneMessage,
20
30
  type PromptCacheTtl,
21
31
  } from '@/messages/cache';
32
+ import {
33
+ isProgrammaticRunnerAutoBound,
34
+ isProgrammaticRunnerResolvedDirectly,
35
+ resolveLocalImplementationNames,
36
+ resolveLocalToolRegistry,
37
+ } from '@/tools/local/resolveLocalExecutionTools';
22
38
  import {
23
39
  DEFAULT_RESERVE_RATIO,
24
40
  ORIGINAL_CONTENT_MAX_CHARS,
@@ -33,27 +49,11 @@ import {
33
49
  Constants,
34
50
  Providers,
35
51
  } from '@/common';
36
- import {
37
- isProgrammaticRunnerAutoBound,
38
- isProgrammaticRunnerResolvedDirectly,
39
- resolveLocalImplementationNames,
40
- resolveLocalToolRegistry,
41
- } from '@/tools/local/resolveLocalExecutionTools';
42
- import {
43
- type CallerCapabilityProjection,
44
- allowsToolCaller,
45
- applyCallerCapabilityDefinitionOverrides,
46
- createCallerCapabilityProjectionSnapshot,
47
- isToolDefinitionActive,
48
- isProgrammaticControlTool,
49
- mergeCallerCapabilityDefinitions,
50
- resolveCallerCapabilityProjection,
51
- } from '@/tools/CallerCapabilities';
52
+ import { isTokenCounterCacheCompatible } from '@/llm/tokenCounterCacheCompatibility';
53
+ import { createExactTokenCountCache } from '@/llm/contextPressureMeter';
52
54
  import { createSchemaOnlyTools } from '@/tools/schema';
53
55
  import { apportionTokenCounts } from '@/utils/tokens';
54
56
  import { isThinkingEnabled } from '@/llm/request';
55
- import { createExactTokenCountCache } from '@/llm/contextPressureMeter';
56
- import { isTokenCounterCacheCompatible } from '@/llm/tokenCounterCacheCompatibility';
57
57
  import { toJsonSchema } from '@/utils/schema';
58
58
 
59
59
  type AgentSystemTextBlock = {
@@ -201,7 +201,7 @@ export class AgentContext {
201
201
  /** Human-readable name for this agent (used in handoff context). Falls back to agentId if not provided. */
202
202
  name?: string;
203
203
  /** Provider for this specific agent */
204
- provider: Providers;
204
+ provider: t.ProviderName;
205
205
  /** Client options for this agent */
206
206
  clientOptions?: t.ClientOptions;
207
207
  /** Per-agent Langfuse tracing configuration. */
@@ -433,7 +433,7 @@ export class AgentContext {
433
433
  agentId: string;
434
434
  codeSessionKey?: string;
435
435
  name?: string;
436
- provider: Providers;
436
+ provider: t.ProviderName;
437
437
  clientOptions?: t.ClientOptions;
438
438
  langfuse?: t.LangfuseConfig;
439
439
  maxContextTokens?: number;
@@ -570,7 +570,9 @@ export class AgentContext {
570
570
  directOnlyToolNames.length > 0
571
571
  ? `\nCall these tools directly; never list them in the \`tool_manifest\` or reference them inside ${programmaticRunnerNames}: ${directOnlyToolNames
572
572
  .map((name) => `\`${name}\``)
573
- .join(', ')}. Every ${programmaticRunnerNames} call must include a \`tool_manifest\` containing the exact registered names used by its code; the manifest is validated before execution starts.`
573
+ .join(
574
+ ', '
575
+ )}. Every ${programmaticRunnerNames} call must include a \`tool_manifest\` containing the exact registered names used by its code; the manifest is validated before execution starts.`
574
576
  : '';
575
577
  const boundary =
576
578
  '\n\n' +
@@ -658,9 +660,8 @@ export class AgentContext {
658
660
  this.toolExecution,
659
661
  this.toolDefinitions?.some((toolDef) => toolDef.name === name) === true
660
662
  ) ||
661
- this.graphTools?.some(
662
- (tool) => 'name' in tool && tool.name === name
663
- ) === true
663
+ this.graphTools?.some((tool) => 'name' in tool && tool.name === name) ===
664
+ true
664
665
  );
665
666
  }
666
667
 
@@ -1618,7 +1619,7 @@ export class AgentContext {
1618
1619
 
1619
1620
  /** Applies token calibration only when the observation came from this provider. */
1620
1621
  applyObservedOverflowCalibration(
1621
- provider: Providers | undefined,
1622
+ provider: t.ProviderName | undefined,
1622
1623
  observedCalibrationRatio: number | undefined
1623
1624
  ): void {
1624
1625
  if (
@@ -53,9 +53,8 @@ import {
53
53
  cloneMessage,
54
54
  CALIBRATION_RATIO_MAX,
55
55
  createPruneMessages,
56
- projectToolCallInputs,
56
+ projectToolMessagesForProvider,
57
57
  calculateMaxToolCallInputChars,
58
- projectToolStreamContentForProvider,
59
58
  syncBudgetDerivedFields,
60
59
  addTailCacheControl,
61
60
  resolvePromptCacheTtl,
@@ -72,7 +71,6 @@ import {
72
71
  splitAtRecencyBoundary,
73
72
  convertInjectedMessages,
74
73
  coalesceAdjacentUserTurns,
75
- strictAlternationProviders,
76
74
  appendPredecessorHandoffCue,
77
75
  stampSyntheticProviderMessage,
78
76
  } from '@/messages';
@@ -98,14 +96,6 @@ import {
98
96
  joinKeys,
99
97
  sleep,
100
98
  } from '@/utils';
101
- import {
102
- attemptInvoke,
103
- tryFallbackProviders,
104
- getFallbackErrorContext,
105
- getFallbackOverflowCandidates,
106
- } from '@/llm/invoke';
107
- import { prepareProviderRequest } from '@/llm/prepareProviderRequest';
108
- import { createContextPressureMeter } from '@/llm/contextPressureMeter';
109
99
  import {
110
100
  resolveStreamLimits,
111
101
  StreamLimitExceededError,
@@ -130,6 +120,12 @@ import {
130
120
  planContextOverflowRecovery,
131
121
  translateRecoveryBudget,
132
122
  } from '@/llm/contextOverflowRecovery';
123
+ import {
124
+ attemptInvoke,
125
+ tryFallbackProviders,
126
+ getFallbackErrorContext,
127
+ getFallbackOverflowCandidates,
128
+ } from '@/llm/invoke';
133
129
  import {
134
130
  hasToolOutputTracingConfig,
135
131
  resolveLangfuseConfig,
@@ -159,8 +155,11 @@ import { createLocalCodingToolBundle } from '@/tools/local/LocalCodingTools';
159
155
  import { SUBAGENT_REPLAY_CONTROLLER } from '@/tools/subagent/SubagentReplay';
160
156
  import { applyGraphRuntimeConfig } from '@/graphs/applyGraphRuntimeConfig';
161
157
  import { partitionAndMarkBedrockToolCache } from '@/llm/bedrock/toolCache';
158
+ import { createContextPressureMeter } from '@/llm/contextPressureMeter';
162
159
  import { safeDispatchCustomEvent, emitAgentLog } from '@/utils/events';
160
+ import { prepareProviderRequest } from '@/llm/prepareProviderRequest';
163
161
  import { createCloudflareCodingToolBundle } from '@/tools/cloudflare';
162
+ import { providerRequiresStrictAlternation } from '@/llm/providers';
164
163
  import { buildSubagentToolParams } from '@/tools/SubagentTool';
165
164
  import { initializeLangfuseTracing } from '@/instrumentation';
166
165
  import { shouldTriggerSummarization } from '@/summarization';
@@ -324,7 +323,7 @@ function isGoogleServerSideToolMessageContentPart(
324
323
  }
325
324
 
326
325
  function hasGoogleServerSideToolDeltaContent(
327
- provider: Providers | undefined,
326
+ provider: t.ProviderName | undefined,
328
327
  content: t.MessageDelta['content']
329
328
  ): content is t.MessageContentComplex[] {
330
329
  return (
@@ -337,7 +336,7 @@ function hasGoogleServerSideToolDeltaContent(
337
336
  }
338
337
 
339
338
  function getMessageDeltaContent(
340
- provider: Providers | undefined,
339
+ provider: t.ProviderName | undefined,
341
340
  content: MessageContent | undefined
342
341
  ): t.MessageDelta['content'] | undefined {
343
342
  if (content == null) {
@@ -550,7 +549,7 @@ async function dispatchTextMessageContent({
550
549
  }: {
551
550
  graph: Graph<t.BaseGraphState>;
552
551
  stepKey: string;
553
- provider?: Providers;
552
+ provider?: t.ProviderName;
554
553
  content: t.MessageDelta['content'];
555
554
  metadata: Record<string, unknown>;
556
555
  }): Promise<boolean> {
@@ -3178,15 +3177,10 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
3178
3177
  const maxProviderToolResultChars =
3179
3178
  agentContext.maxToolResultChars ??
3180
3179
  calculateMaxToolResultChars(agentContext.maxContextTokens);
3181
- const beforeToolStreamProjection = finalMessages;
3182
- finalMessages = trackProviderMessageOrigins(
3183
- beforeToolStreamProjection,
3184
- projectToolStreamContentForProvider(beforeToolStreamProjection)
3185
- );
3186
3180
  const beforeToolInputProjection = finalMessages;
3187
3181
  finalMessages = trackProviderMessageOrigins(
3188
3182
  beforeToolInputProjection,
3189
- projectToolCallInputs(
3183
+ projectToolMessagesForProvider(
3190
3184
  beforeToolInputProjection,
3191
3185
  calculateMaxToolCallInputChars(agentContext.maxContextTokens)
3192
3186
  )
@@ -3237,7 +3231,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
3237
3231
  info,
3238
3232
  }: {
3239
3233
  projection: ReturnType<typeof measureProviderPayload>;
3240
- provider?: Providers;
3234
+ provider?: t.ProviderName;
3241
3235
  info: string;
3242
3236
  }): ContextOverflowError => {
3243
3237
  const error = new ContextOverflowError(
@@ -3508,7 +3502,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
3508
3502
  * drop messages, so coalescing has to see its output, and it is the
3509
3503
  * last shaping step before the cache breakpoint is chosen.
3510
3504
  */
3511
- if (strictAlternationProviders.has(agentContext.provider)) {
3505
+ if (providerRequiresStrictAlternation(agentContext.provider)) {
3512
3506
  /**
3513
3507
  * Wrapped like every other provider transform: the merged message is
3514
3508
  * a NEW object, and without re-attachment the final pre-invoke
package/src/index.ts CHANGED
@@ -70,15 +70,20 @@ export type { Interrupt } from '@langchain/langgraph';
70
70
 
71
71
  /* LLM */
72
72
  export { markTokenCounterCacheCompatible } from './llm/tokenCounterCacheCompatibility';
73
- export { CustomOpenAIClient } from './llm/openai';
74
- export { ChatOpenRouter } from './llm/openrouter';
73
+ /** Provider chat-model classes moved off the root barrel: importing any of them here
74
+ * forced every host to pay that provider SDK's module init at boot. They remain
75
+ * available from their own entries, e.g. `@librechat/agents/llm/openai`. */
75
76
  export type {
76
77
  OpenRouterReasoning,
77
78
  OpenRouterReasoningEffort,
78
79
  ChatOpenRouterCallOptions,
79
80
  } from './llm/openrouter';
80
81
  export { getChatModelClass } from './llm/providers';
81
- export { CustomChatMistralAI } from './llm/mistral';
82
+ export { registerProvider } from './provider-registration';
83
+ export type {
84
+ ProviderFamily,
85
+ ProviderRegistrationOptions,
86
+ } from './provider-registration';
82
87
  export {
83
88
  smoothStream,
84
89
  resolveStreamDelay,
@@ -0,0 +1,67 @@
1
+ import { createRequire } from 'node:module';
2
+
3
+ /**
4
+ * Synchronous on-demand module loading: provider SDKs and other heavy dependencies
5
+ * load with their first request instead of at import time. This is the only module
6
+ * that touches `import.meta`; jest maps it to `test/stubs/lazyRequire.ts` so suites
7
+ * resolve source modules through their own resolver (the same precedent as the
8
+ * `@langchain/mistralai` stub).
9
+ *
10
+ * Internal modules load as format-matched siblings — `.cjs` neighbors from the CJS
11
+ * build and `.mjs` neighbors from the ESM build (Node's `require(esm)`, safe on the
12
+ * declared `>=24` engine) — so a lazily resolved provider shares one LangChain class
13
+ * graph with the code that requested it. Under a source-mode runner such as `tsx`,
14
+ * the seam resolves the TypeScript source directly through the active loader.
15
+ */
16
+ const moduleUrl = import.meta.url;
17
+ const requireModule = createRequire(moduleUrl);
18
+
19
+ function detectBuildExtension(url: string): '.cjs' | '.mjs' | null {
20
+ if (url.endsWith('.mjs')) {
21
+ return '.mjs';
22
+ }
23
+ if (url.endsWith('.cjs')) {
24
+ return '.cjs';
25
+ }
26
+ return null;
27
+ }
28
+
29
+ const buildExtension = detectBuildExtension(moduleUrl);
30
+
31
+ /** False when the package runs from TypeScript source, where dist siblings do
32
+ * not exist and lazily loadable modules must be registered up front. */
33
+ export function isBuiltRuntime(): boolean {
34
+ return buildExtension != null;
35
+ }
36
+
37
+ /** Source-mode commands run the TypeScript through an ESM loader that a synchronous
38
+ * CJS `require` can neither reach nor share module identity with, so lazily loadable
39
+ * modules are provided up front instead: `@/llm/providers.eager` imports them through
40
+ * the active loader and registers them here. */
41
+ const sourceModeModules = new Map<string, unknown>();
42
+
43
+ export function registerSourceModeModules(modules: Record<string, unknown>): void {
44
+ for (const [relativePath, moduleExports] of Object.entries(modules)) {
45
+ sourceModeModules.set(relativePath, moduleExports);
46
+ }
47
+ }
48
+
49
+ /** Loads a module of this package by its src-relative path, e.g. `llm/openai/index`. */
50
+ export function requireInternalModule<T>(relativePath: string): T {
51
+ if (buildExtension != null) {
52
+ return requireModule(`./${relativePath}${buildExtension}`) as T;
53
+ }
54
+ const provided = sourceModeModules.get(relativePath);
55
+ if (provided == null) {
56
+ throw new Error(
57
+ `Lazily loaded module "${relativePath}" is unavailable when running from source; ` +
58
+ 'import \'@/llm/providers.eager\' at the entrypoint before any model is used.'
59
+ );
60
+ }
61
+ return provided as T;
62
+ }
63
+
64
+ /** Loads a third-party package on first use; identity-sensitive callers must not use this. */
65
+ export function requireLazyModule<T>(specifier: string): T {
66
+ return requireModule(specifier) as T;
67
+ }
@@ -4,7 +4,11 @@ import type { OpenAIClient } from '@langchain/openai';
4
4
  import type { DocumentType } from '@smithy/types';
5
5
  import type { GraphTools } from '@/types';
6
6
  import { buildBedrockCachePoint, type PromptCacheTtl } from '@/messages/cache';
7
- import { _convertToOpenAITool } from '@/llm/openai';
7
+ import { requireInternalModule } from '@/lazyRequire';
8
+
9
+ /** Loads with the first Bedrock request rather than alongside every graph. */
10
+ const convertToOpenAITool: typeof import('@/llm/openai')._convertToOpenAITool = (...args) =>
11
+ requireInternalModule<typeof import('@/llm/openai')>('llm/openai/index')._convertToOpenAITool(...args);
8
12
 
9
13
  const BEDROCK_TOOL_CACHE_MARKER = '__lc_bedrock_cache_point_after';
10
14
  const BEDROCK_TOOL_CACHE_DISABLED_MARKER = '__lc_bedrock_skip_tool_cache';
@@ -77,7 +81,7 @@ function toBedrockTool(tool: unknown): BedrockToolWithCacheMarker {
77
81
  }
78
82
 
79
83
  return openAIToBedrockTool(
80
- _convertToOpenAITool(tool as BindToolsInput) as OpenAIFunctionTool
84
+ convertToOpenAITool(tool as BindToolsInput) as OpenAIFunctionTool
81
85
  ) as BedrockToolWithCacheMarker;
82
86
  }
83
87
 
@@ -18,7 +18,7 @@
18
18
  * provider-space budget.
19
19
  */
20
20
  import type { ContextOverflowInfo } from '@/utils/errors';
21
- import type { Providers } from '@/common';
21
+ import type { ProviderName } from '@/types';
22
22
  import { getContextOverflowInfo } from '@/utils/errors';
23
23
 
24
24
  /** Fraction of the previous budget used when the provider named no ceiling. */
@@ -66,7 +66,7 @@ export interface OverflowRecoveryPlan {
66
66
 
67
67
  export interface OverflowRecoveryParams {
68
68
  error: unknown;
69
- provider: Providers;
69
+ provider: ProviderName;
70
70
  /** Budget in force when the rejected prompt was built. */
71
71
  maxContextTokens?: number;
72
72
  /** Our own estimate of the prompt we actually sent. */
package/src/llm/init.ts CHANGED
@@ -1,39 +1,63 @@
1
- import { ChatVertexAI } from '@langchain/google-vertexai';
2
1
  import type { Runnable } from '@langchain/core/runnables';
3
2
  import type * as t from '@/types';
4
- import { ChatOpenAI, AzureChatOpenAI } from '@/llm/openai';
5
3
  import { getChatModelClass } from '@/llm/providers';
6
- import { isOpenAILike } from '@/utils';
4
+ import { isOpenAILike, isLibreChatOpenAIModel, constructorChainHasLcName } from '@/utils';
7
5
  import { Providers } from '@/common';
8
6
 
7
+ type InitializeModelParams<P extends t.ProviderName> = {
8
+ provider: P;
9
+ tools?: t.GraphTools;
10
+ } & (
11
+ | {
12
+ override: t.ChatModelInstance;
13
+ clientOptions?: t.ProviderOptionsFor<P>;
14
+ }
15
+ | ([P] extends [keyof t.ProviderOptionsMap]
16
+ ? {
17
+ override?: t.ChatModelInstance;
18
+ clientOptions?: t.ProviderOptionsFor<P>;
19
+ }
20
+ : object extends t.ProviderOptionsFor<P>
21
+ ? {
22
+ override?: t.ChatModelInstance;
23
+ clientOptions?: t.ProviderOptionsFor<P>;
24
+ }
25
+ : {
26
+ override?: undefined;
27
+ clientOptions: t.ProviderOptionsFor<P>;
28
+ })
29
+ );
30
+
31
+ const VERTEX_LC_NAMES: ReadonlySet<string> = new Set(['ChatVertexAI']);
32
+
33
+ /** Structural stand-in for `instanceof ChatVertexAI`: matches both builds of
34
+ * `@langchain/google-vertexai`, while this package's own vertex class reports
35
+ * `LibreChatVertexAI` and keeps failing this guard exactly as it did under
36
+ * `instanceof`. */
37
+ function isLangchainVertexModel(
38
+ model: unknown
39
+ ): model is import('@langchain/google-vertexai').ChatVertexAI {
40
+ return constructorChainHasLcName(model, VERTEX_LC_NAMES);
41
+ }
42
+
9
43
  /**
10
- * Creates a chat model instance for a given provider, applies provider-specific
11
- * field assignments, and optionally binds tools.
12
- *
13
- * This is the single entry point for model creation across the codebase — used
14
- * by both the agent graph (main LLM) and the summarization node (compaction LLM).
15
- * An optional `override` model can be passed to skip construction entirely
16
- * (useful for cached/reused model instances or test fakes).
44
+ * Creates a chat model instance for a given built-in or host-registered
45
+ * provider, applies provider-specific field assignments, and optionally binds
46
+ * tools.
17
47
  */
18
- export function initializeModel({
48
+ export function initializeModel<P extends t.ProviderName>({
19
49
  provider,
20
50
  clientOptions,
21
51
  tools,
22
52
  override,
23
- }: {
24
- provider: Providers;
25
- clientOptions?: t.ClientOptions;
26
- tools?: t.GraphTools;
27
- override?: t.ChatModelInstance;
28
- }): Runnable {
53
+ }: InitializeModelParams<P>): Runnable {
29
54
  const model =
30
55
  override ??
31
- new (getChatModelClass(provider))(clientOptions ?? ({} as never));
56
+ new (getChatModelClass(provider))(
57
+ (clientOptions ?? {}) as t.ProviderOptionsFor<P>
58
+ );
32
59
 
33
- if (
34
- isOpenAILike(provider) &&
35
- (model instanceof ChatOpenAI || model instanceof AzureChatOpenAI)
36
- ) {
60
+ if (isOpenAILike(provider) && isLibreChatOpenAIModel(model)) {
37
61
  const opts = clientOptions as t.OpenAIClientOptions | undefined;
38
62
  if (opts) {
39
63
  model.temperature = opts.temperature as number;
@@ -42,7 +66,7 @@ export function initializeModel({
42
66
  model.presencePenalty = opts.presencePenalty as number;
43
67
  model.n = opts.n as number;
44
68
  }
45
- } else if (provider === Providers.VERTEXAI && model instanceof ChatVertexAI) {
69
+ } else if (provider === Providers.VERTEXAI && isLangchainVertexModel(model)) {
46
70
  const opts = clientOptions as t.VertexAIClientOptions | undefined;
47
71
  if (opts) {
48
72
  model.temperature = opts.temperature as number;
@@ -56,8 +80,14 @@ export function initializeModel({
56
80
  }
57
81
 
58
82
  if (!tools || tools.length === 0) {
59
- return model as unknown as Runnable;
83
+ return model;
84
+ }
85
+
86
+ if (!('bindTools' in model) || typeof model.bindTools !== 'function') {
87
+ throw new TypeError(
88
+ `LLM provider does not support tool binding: ${provider}`
89
+ );
60
90
  }
61
91
 
62
- return (model as t.ModelWithTools).bindTools(tools);
92
+ return model.bindTools(tools);
63
93
  }