langchain 1.5.7 → 1.5.9
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.
- package/CHANGELOG.md +23 -0
- package/dist/agents/middleware/constants.cjs +3 -2
- package/dist/agents/middleware/constants.cjs.map +1 -1
- package/dist/agents/middleware/constants.js +3 -2
- package/dist/agents/middleware/constants.js.map +1 -1
- package/dist/agents/middleware/modelRetry.cjs +9 -2
- package/dist/agents/middleware/modelRetry.cjs.map +1 -1
- package/dist/agents/middleware/modelRetry.d.cts.map +1 -1
- package/dist/agents/middleware/modelRetry.d.ts.map +1 -1
- package/dist/agents/middleware/modelRetry.js +10 -3
- package/dist/agents/middleware/modelRetry.js.map +1 -1
- package/dist/agents/middleware/toolRetry.cjs +1 -1
- package/dist/agents/middleware/toolRetry.cjs.map +1 -1
- package/dist/agents/middleware/toolRetry.d.cts.map +1 -1
- package/dist/agents/middleware/toolRetry.d.ts.map +1 -1
- package/dist/agents/middleware/toolRetry.js +2 -2
- package/dist/agents/middleware/toolRetry.js.map +1 -1
- package/dist/agents/middleware/utils.cjs +10 -2
- package/dist/agents/middleware/utils.cjs.map +1 -1
- package/dist/agents/middleware/utils.js +10 -3
- package/dist/agents/middleware/utils.js.map +1 -1
- package/dist/chat_models/universal.cjs +2 -2
- package/dist/chat_models/universal.cjs.map +1 -1
- package/dist/chat_models/universal.d.cts.map +1 -1
- package/dist/chat_models/universal.d.ts.map +1 -1
- package/dist/chat_models/universal.js +2 -2
- package/dist/chat_models/universal.js.map +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# langchain
|
|
2
2
|
|
|
3
|
+
## 1.5.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#11369](https://github.com/langchain-ai/langchainjs/pull/11369) [`d6ad973`](https://github.com/langchain-ai/langchainjs/commit/d6ad9735640a6c729f81ef79361acc5e83c526f1) Thanks [@hntrl](https://github.com/hntrl)! - fix(langchain): use unified endpoint for gateway
|
|
8
|
+
|
|
9
|
+
- [#11342](https://github.com/langchain-ai/langchainjs/pull/11342) [`3b0e4c4`](https://github.com/langchain-ai/langchainjs/commit/3b0e4c48a31811031a460c4d95519a7c1163dc41) Thanks [@thushanth-bengre-langchain](https://github.com/thushanth-bengre-langchain)! - feat(core): mark errors as retryable or not, and stop retrying the ones that aren't
|
|
10
|
+
|
|
11
|
+
Retry middleware retried every failure up to `maxRetries`, including deterministic ones like a bad API key or an unknown model. Retries also nest, so a single such failure could cost dozens of API calls.
|
|
12
|
+
|
|
13
|
+
`@langchain/core/errors` adds `stampRetryable(error, retryable)` and `getRetryable(error)`. Marking an error leaves its class and shape untouched, so a provider SDK error can be classified without breaking `instanceof`. `getRetryable` returns `undefined` for errors nobody classified, and both are exported so tool authors can mark their own failures.
|
|
14
|
+
|
|
15
|
+
`modelRetryMiddleware` and `toolRetryMiddleware` now respect the mark by default, and retries stop as soon as one is found rather than each layer spending its own budget. Aborted calls, context overflow, and oversized payloads are marked non-retryable out of the box.
|
|
16
|
+
Models accept a per-call `maxRetries` so a surrounding retry loop can take over.
|
|
17
|
+
|
|
18
|
+
**Behavior change:** errors marked non-retryable now fail on the first attempt. Unclassified errors — including any from third-party integrations or custom tools — retry exactly as before. Pass `retryOn: () => true` to restore the old default. A custom `onFailedAttempt` replaces the built-in handler and opts out of marking.
|
|
19
|
+
|
|
20
|
+
## 1.5.8
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- [#11366](https://github.com/langchain-ai/langchainjs/pull/11366) [`c068bbf`](https://github.com/langchain-ai/langchainjs/commit/c068bbf8c113132bf16ac7a8add44e486a147b41) Thanks [@hntrl](https://github.com/hntrl)! - fix(core,langchain): patch and release core, update peer dependencies
|
|
25
|
+
|
|
3
26
|
## 1.5.7
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
let zod_v3 = require("zod/v3");
|
|
2
|
+
let _langchain_core_errors = require("@langchain/core/errors");
|
|
2
3
|
//#region src/agents/middleware/constants.ts
|
|
3
4
|
/** LangGraph's messages handlers skip runs tagged with this, keeping middleware-internal model calls out of the messages stream. */
|
|
4
5
|
const INTERNAL_CALL_TAG = "nostream";
|
|
@@ -11,9 +12,9 @@ const RetrySchema = zod_v3.z.object({
|
|
|
11
12
|
/**
|
|
12
13
|
* Either an array of error constructors to retry on, or a function
|
|
13
14
|
* that takes an error and returns `true` if it should be retried.
|
|
14
|
-
* Default is to retry
|
|
15
|
+
* Default is to retry unless the error is marked non-retryable.
|
|
15
16
|
*/
|
|
16
|
-
retryOn: zod_v3.z.union([zod_v3.z.function().args(zod_v3.z.instanceof(Error)).returns(zod_v3.z.boolean()), zod_v3.z.array(zod_v3.z.custom())]).default(() => () => true),
|
|
17
|
+
retryOn: zod_v3.z.union([zod_v3.z.function().args(zod_v3.z.instanceof(Error)).returns(zod_v3.z.boolean()), zod_v3.z.array(zod_v3.z.custom())]).default(() => (error) => (0, _langchain_core_errors.getRetryable)(error) ?? true),
|
|
17
18
|
/**
|
|
18
19
|
* Multiplier for exponential backoff. Each retry waits
|
|
19
20
|
* `initialDelayMs * (backoffFactor ** retryNumber)` milliseconds.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.cjs","names":["z"],"sources":["../../../src/agents/middleware/constants.ts"],"sourcesContent":["import { z } from \"zod/v3\";\n\n/** LangGraph's messages handlers skip runs tagged with this, keeping middleware-internal model calls out of the messages stream. */\nexport const INTERNAL_CALL_TAG = \"nostream\";\n\nexport const RetrySchema = z.object({\n /**\n * Maximum number of retry attempts after the initial call.\n * Default is 2 retries (3 total attempts). Must be >= 0.\n */\n maxRetries: z.number().min(0).default(2),\n\n /**\n * Either an array of error constructors to retry on, or a function\n * that takes an error and returns `true` if it should be retried.\n * Default is to retry
|
|
1
|
+
{"version":3,"file":"constants.cjs","names":["z"],"sources":["../../../src/agents/middleware/constants.ts"],"sourcesContent":["import { getRetryable } from \"@langchain/core/errors\";\nimport { z } from \"zod/v3\";\n\n/** LangGraph's messages handlers skip runs tagged with this, keeping middleware-internal model calls out of the messages stream. */\nexport const INTERNAL_CALL_TAG = \"nostream\";\n\nexport const RetrySchema = z.object({\n /**\n * Maximum number of retry attempts after the initial call.\n * Default is 2 retries (3 total attempts). Must be >= 0.\n */\n maxRetries: z.number().min(0).default(2),\n\n /**\n * Either an array of error constructors to retry on, or a function\n * that takes an error and returns `true` if it should be retried.\n * Default is to retry unless the error is marked non-retryable.\n */\n retryOn: z\n .union([\n z.function().args(z.instanceof(Error)).returns(z.boolean()),\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n z.array(z.custom<new (...args: any[]) => Error>()),\n ])\n .default(() => (error: Error) => getRetryable(error) ?? true),\n\n /**\n * Multiplier for exponential backoff. Each retry waits\n * `initialDelayMs * (backoffFactor ** retryNumber)` milliseconds.\n * Set to 0.0 for constant delay. Default is 2.0.\n */\n backoffFactor: z.number().min(0).default(2.0),\n\n /**\n * Initial delay in milliseconds before first retry. Default is 1000 (1 second).\n */\n initialDelayMs: z.number().min(0).default(1000),\n\n /**\n * Maximum delay in milliseconds between retries. Caps exponential\n * backoff growth. Default is 60000 (60 seconds).\n */\n maxDelayMs: z.number().min(0).default(60000),\n\n /**\n * Whether to add random jitter (±25%) to delay to avoid thundering herd.\n * Default is `true`.\n */\n jitter: z.boolean().default(true),\n});\n"],"mappings":";;;;AAIA,MAAa,oBAAoB;AAEjC,MAAa,cAAcA,OAAAA,EAAE,OAAO;;;;;CAKlC,YAAYA,OAAAA,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;;;;;;CAOvC,SAASA,OAAAA,EACN,MAAM,CACLA,OAAAA,EAAE,SAAS,CAAC,CAAC,KAAKA,OAAAA,EAAE,WAAW,KAAK,CAAC,CAAC,CAAC,QAAQA,OAAAA,EAAE,QAAQ,CAAC,GAE1DA,OAAAA,EAAE,MAAMA,OAAAA,EAAE,OAAsC,CAAC,CACnD,CAAC,CAAC,CACD,eAAe,WAAA,GAAA,uBAAA,aAAA,CAA8B,KAAK,KAAK,IAAI;;;;;;CAO9D,eAAeA,OAAAA,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAG;;;;CAK5C,gBAAgBA,OAAAA,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,GAAI;;;;;CAM9C,YAAYA,OAAAA,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,GAAK;;;;;CAM3C,QAAQA,OAAAA,EAAE,QAAQ,CAAC,CAAC,QAAQ,IAAI;AAClC,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod/v3";
|
|
2
|
+
import { getRetryable } from "@langchain/core/errors";
|
|
2
3
|
//#region src/agents/middleware/constants.ts
|
|
3
4
|
/** LangGraph's messages handlers skip runs tagged with this, keeping middleware-internal model calls out of the messages stream. */
|
|
4
5
|
const INTERNAL_CALL_TAG = "nostream";
|
|
@@ -11,9 +12,9 @@ const RetrySchema = z.object({
|
|
|
11
12
|
/**
|
|
12
13
|
* Either an array of error constructors to retry on, or a function
|
|
13
14
|
* that takes an error and returns `true` if it should be retried.
|
|
14
|
-
* Default is to retry
|
|
15
|
+
* Default is to retry unless the error is marked non-retryable.
|
|
15
16
|
*/
|
|
16
|
-
retryOn: z.union([z.function().args(z.instanceof(Error)).returns(z.boolean()), z.array(z.custom())]).default(() => () => true),
|
|
17
|
+
retryOn: z.union([z.function().args(z.instanceof(Error)).returns(z.boolean()), z.array(z.custom())]).default(() => (error) => getRetryable(error) ?? true),
|
|
17
18
|
/**
|
|
18
19
|
* Multiplier for exponential backoff. Each retry waits
|
|
19
20
|
* `initialDelayMs * (backoffFactor ** retryNumber)` milliseconds.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","names":[],"sources":["../../../src/agents/middleware/constants.ts"],"sourcesContent":["import { z } from \"zod/v3\";\n\n/** LangGraph's messages handlers skip runs tagged with this, keeping middleware-internal model calls out of the messages stream. */\nexport const INTERNAL_CALL_TAG = \"nostream\";\n\nexport const RetrySchema = z.object({\n /**\n * Maximum number of retry attempts after the initial call.\n * Default is 2 retries (3 total attempts). Must be >= 0.\n */\n maxRetries: z.number().min(0).default(2),\n\n /**\n * Either an array of error constructors to retry on, or a function\n * that takes an error and returns `true` if it should be retried.\n * Default is to retry
|
|
1
|
+
{"version":3,"file":"constants.js","names":[],"sources":["../../../src/agents/middleware/constants.ts"],"sourcesContent":["import { getRetryable } from \"@langchain/core/errors\";\nimport { z } from \"zod/v3\";\n\n/** LangGraph's messages handlers skip runs tagged with this, keeping middleware-internal model calls out of the messages stream. */\nexport const INTERNAL_CALL_TAG = \"nostream\";\n\nexport const RetrySchema = z.object({\n /**\n * Maximum number of retry attempts after the initial call.\n * Default is 2 retries (3 total attempts). Must be >= 0.\n */\n maxRetries: z.number().min(0).default(2),\n\n /**\n * Either an array of error constructors to retry on, or a function\n * that takes an error and returns `true` if it should be retried.\n * Default is to retry unless the error is marked non-retryable.\n */\n retryOn: z\n .union([\n z.function().args(z.instanceof(Error)).returns(z.boolean()),\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n z.array(z.custom<new (...args: any[]) => Error>()),\n ])\n .default(() => (error: Error) => getRetryable(error) ?? true),\n\n /**\n * Multiplier for exponential backoff. Each retry waits\n * `initialDelayMs * (backoffFactor ** retryNumber)` milliseconds.\n * Set to 0.0 for constant delay. Default is 2.0.\n */\n backoffFactor: z.number().min(0).default(2.0),\n\n /**\n * Initial delay in milliseconds before first retry. Default is 1000 (1 second).\n */\n initialDelayMs: z.number().min(0).default(1000),\n\n /**\n * Maximum delay in milliseconds between retries. Caps exponential\n * backoff growth. Default is 60000 (60 seconds).\n */\n maxDelayMs: z.number().min(0).default(60000),\n\n /**\n * Whether to add random jitter (±25%) to delay to avoid thundering herd.\n * Default is `true`.\n */\n jitter: z.boolean().default(true),\n});\n"],"mappings":";;;;AAIA,MAAa,oBAAoB;AAEjC,MAAa,cAAc,EAAE,OAAO;;;;;CAKlC,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;;;;;;CAOvC,SAAS,EACN,MAAM,CACL,EAAE,SAAS,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAE1D,EAAE,MAAM,EAAE,OAAsC,CAAC,CACnD,CAAC,CAAC,CACD,eAAe,UAAiB,aAAa,KAAK,KAAK,IAAI;;;;;;CAO9D,eAAe,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAG;;;;CAK5C,gBAAgB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,GAAI;;;;;CAM9C,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,GAAK;;;;;CAM3C,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,IAAI;AAClC,CAAC"}
|
|
@@ -150,14 +150,21 @@ function modelRetryMiddleware(config = {}) {
|
|
|
150
150
|
name: "modelRetryMiddleware",
|
|
151
151
|
contextSchema: ModelRetryMiddlewareOptionsSchema,
|
|
152
152
|
wrapModelCall: async (request, handler) => {
|
|
153
|
+
const delegated = {
|
|
154
|
+
...request,
|
|
155
|
+
modelSettings: {
|
|
156
|
+
maxRetries: 0,
|
|
157
|
+
...request.modelSettings
|
|
158
|
+
}
|
|
159
|
+
};
|
|
153
160
|
for (let attempt = 0; attempt <= maxRetries; attempt++) try {
|
|
154
|
-
return await handler(
|
|
161
|
+
return await handler(delegated);
|
|
155
162
|
} catch (error) {
|
|
156
163
|
const attemptsMade = attempt + 1;
|
|
157
164
|
const err = error && typeof error === "object" && "message" in error ? error : new Error(String(error));
|
|
158
165
|
if (!shouldRetryException(err)) return handleFailure(err, attemptsMade);
|
|
159
166
|
if (attempt < maxRetries) {
|
|
160
|
-
const delay = require_utils.calculateRetryDelay(delayConfig, attempt);
|
|
167
|
+
const delay = require_utils.calculateRetryDelay(delayConfig, attempt, require_utils.getRetryAfterMs(err));
|
|
161
168
|
if (delay > 0) await require_utils.sleep(delay);
|
|
162
169
|
} else return handleFailure(err, attemptsMade);
|
|
163
170
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modelRetry.cjs","names":["z","RetrySchema","InvalidRetryConfigError","AIMessage","createMiddleware","calculateRetryDelay","sleep"],"sources":["../../../src/agents/middleware/modelRetry.ts"],"sourcesContent":["/**\n * Model retry middleware for agents.\n */\nimport { z } from \"zod/v3\";\nimport { AIMessage } from \"@langchain/core/messages\";\n\nimport { createMiddleware } from \"../middleware.js\";\nimport { sleep, calculateRetryDelay } from \"./utils.js\";\nimport { RetrySchema } from \"./constants.js\";\nimport { InvalidRetryConfigError } from \"./error.js\";\n\n/**\n * Configuration options for the Model Retry Middleware.\n */\nexport const ModelRetryMiddlewareOptionsSchema = z\n .object({\n /**\n * Behavior when all retries are exhausted. Options:\n * - `\"continue\"` (default): Return an AIMessage with error details, allowing\n * the agent to potentially handle the failure gracefully.\n * - `\"error\"`: Re-raise the exception, stopping agent execution.\n * - Custom function: Function that takes the exception and returns a string\n * for the AIMessage content, allowing custom error formatting.\n */\n onFailure: z\n .union([\n z.literal(\"error\"),\n z.literal(\"continue\"),\n z.function().args(z.instanceof(Error)).returns(z.string()),\n ])\n .default(\"continue\"),\n })\n .merge(RetrySchema);\n\nexport type ModelRetryMiddlewareConfig = z.input<\n typeof ModelRetryMiddlewareOptionsSchema\n>;\n\n/**\n * Middleware that automatically retries failed model calls with configurable backoff.\n *\n * Supports retrying on specific exceptions and exponential backoff.\n *\n * @example Basic usage with default settings (2 retries, exponential backoff)\n * ```ts\n * import { createAgent, modelRetryMiddleware } from \"langchain\";\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [searchTool],\n * middleware: [modelRetryMiddleware()],\n * });\n * ```\n *\n * @example Retry specific exceptions only\n * ```ts\n * import { modelRetryMiddleware } from \"langchain\";\n *\n * const retry = modelRetryMiddleware({\n * maxRetries: 4,\n * retryOn: [TimeoutError, NetworkError],\n * backoffFactor: 1.5,\n * });\n * ```\n *\n * @example Custom exception filtering\n * ```ts\n * function shouldRetry(error: Error): boolean {\n * // Only retry on rate limit errors\n * if (error.name === \"RateLimitError\") {\n * return true;\n * }\n * // Or check for specific HTTP status codes\n * if (error.name === \"HTTPError\" && \"statusCode\" in error) {\n * const statusCode = (error as any).statusCode;\n * return statusCode === 429 || statusCode === 503;\n * }\n * return false;\n * }\n *\n * const retry = modelRetryMiddleware({\n * maxRetries: 3,\n * retryOn: shouldRetry,\n * });\n * ```\n *\n * @example Return error message instead of raising\n * ```ts\n * const retry = modelRetryMiddleware({\n * maxRetries: 4,\n * onFailure: \"continue\", // Return AIMessage with error instead of throwing\n * });\n * ```\n *\n * @example Custom error message formatting\n * ```ts\n * const formatError = (error: Error) =>\n * `Model call failed: ${error.message}. Please try again later.`;\n *\n * const retry = modelRetryMiddleware({\n * maxRetries: 4,\n * onFailure: formatError,\n * });\n * ```\n *\n * @example Constant backoff (no exponential growth)\n * ```ts\n * const retry = modelRetryMiddleware({\n * maxRetries: 5,\n * backoffFactor: 0.0, // No exponential growth\n * initialDelayMs: 2000, // Always wait 2 seconds\n * });\n * ```\n *\n * @example Raise exception on failure\n * ```ts\n * const retry = modelRetryMiddleware({\n * maxRetries: 2,\n * onFailure: \"error\", // Re-raise exception instead of returning message\n * });\n * ```\n *\n * @param config - Configuration options for the retry middleware\n * @returns A middleware instance that handles model failures with retries\n */\nexport function modelRetryMiddleware(config: ModelRetryMiddlewareConfig = {}) {\n const { success, error, data } =\n ModelRetryMiddlewareOptionsSchema.safeParse(config);\n if (!success) {\n throw new InvalidRetryConfigError(error);\n }\n const {\n maxRetries,\n retryOn,\n onFailure,\n backoffFactor,\n initialDelayMs,\n maxDelayMs,\n jitter,\n } = data;\n\n /**\n * Check if the exception should trigger a retry.\n */\n const shouldRetryException = (error: Error): boolean => {\n if (typeof retryOn === \"function\") {\n return retryOn(error);\n }\n // retryOn is an array of error constructors\n return retryOn.some(\n (ErrorConstructor) => error.constructor === ErrorConstructor\n );\n };\n\n // Use the exported calculateRetryDelay function with our config\n const delayConfig = { backoffFactor, initialDelayMs, maxDelayMs, jitter };\n\n /**\n * Format the failure message when retries are exhausted.\n */\n const formatFailureMessage = (error: Error, attemptsMade: number): string => {\n const errorType = error.constructor.name;\n const attemptWord = attemptsMade === 1 ? \"attempt\" : \"attempts\";\n return `Model call failed after ${attemptsMade} ${attemptWord} with ${errorType}: ${error.message}`;\n };\n\n /**\n * Handle failure when all retries are exhausted.\n */\n const handleFailure = (error: Error, attemptsMade: number): AIMessage => {\n if (onFailure === \"error\") {\n throw error;\n }\n\n let content: string;\n if (typeof onFailure === \"function\") {\n content = onFailure(error);\n } else {\n content = formatFailureMessage(error, attemptsMade);\n }\n\n return new AIMessage({\n content,\n });\n };\n\n return createMiddleware({\n name: \"modelRetryMiddleware\",\n contextSchema: ModelRetryMiddlewareOptionsSchema,\n wrapModelCall: async (request, handler) => {\n // Initial attempt + retries\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await handler(
|
|
1
|
+
{"version":3,"file":"modelRetry.cjs","names":["z","RetrySchema","InvalidRetryConfigError","AIMessage","createMiddleware","calculateRetryDelay","getRetryAfterMs","sleep"],"sources":["../../../src/agents/middleware/modelRetry.ts"],"sourcesContent":["/**\n * Model retry middleware for agents.\n */\nimport { z } from \"zod/v3\";\nimport { AIMessage } from \"@langchain/core/messages\";\n\nimport { createMiddleware } from \"../middleware.js\";\nimport { sleep, calculateRetryDelay, getRetryAfterMs } from \"./utils.js\";\nimport { RetrySchema } from \"./constants.js\";\nimport { InvalidRetryConfigError } from \"./error.js\";\n\n/**\n * Configuration options for the Model Retry Middleware.\n */\nexport const ModelRetryMiddlewareOptionsSchema = z\n .object({\n /**\n * Behavior when all retries are exhausted. Options:\n * - `\"continue\"` (default): Return an AIMessage with error details, allowing\n * the agent to potentially handle the failure gracefully.\n * - `\"error\"`: Re-raise the exception, stopping agent execution.\n * - Custom function: Function that takes the exception and returns a string\n * for the AIMessage content, allowing custom error formatting.\n */\n onFailure: z\n .union([\n z.literal(\"error\"),\n z.literal(\"continue\"),\n z.function().args(z.instanceof(Error)).returns(z.string()),\n ])\n .default(\"continue\"),\n })\n .merge(RetrySchema);\n\nexport type ModelRetryMiddlewareConfig = z.input<\n typeof ModelRetryMiddlewareOptionsSchema\n>;\n\n/**\n * Middleware that automatically retries failed model calls with configurable backoff.\n *\n * Supports retrying on specific exceptions and exponential backoff.\n *\n * @example Basic usage with default settings (2 retries, exponential backoff)\n * ```ts\n * import { createAgent, modelRetryMiddleware } from \"langchain\";\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [searchTool],\n * middleware: [modelRetryMiddleware()],\n * });\n * ```\n *\n * @example Retry specific exceptions only\n * ```ts\n * import { modelRetryMiddleware } from \"langchain\";\n *\n * const retry = modelRetryMiddleware({\n * maxRetries: 4,\n * retryOn: [TimeoutError, NetworkError],\n * backoffFactor: 1.5,\n * });\n * ```\n *\n * @example Custom exception filtering\n * ```ts\n * function shouldRetry(error: Error): boolean {\n * // Only retry on rate limit errors\n * if (error.name === \"RateLimitError\") {\n * return true;\n * }\n * // Or check for specific HTTP status codes\n * if (error.name === \"HTTPError\" && \"statusCode\" in error) {\n * const statusCode = (error as any).statusCode;\n * return statusCode === 429 || statusCode === 503;\n * }\n * return false;\n * }\n *\n * const retry = modelRetryMiddleware({\n * maxRetries: 3,\n * retryOn: shouldRetry,\n * });\n * ```\n *\n * @example Return error message instead of raising\n * ```ts\n * const retry = modelRetryMiddleware({\n * maxRetries: 4,\n * onFailure: \"continue\", // Return AIMessage with error instead of throwing\n * });\n * ```\n *\n * @example Custom error message formatting\n * ```ts\n * const formatError = (error: Error) =>\n * `Model call failed: ${error.message}. Please try again later.`;\n *\n * const retry = modelRetryMiddleware({\n * maxRetries: 4,\n * onFailure: formatError,\n * });\n * ```\n *\n * @example Constant backoff (no exponential growth)\n * ```ts\n * const retry = modelRetryMiddleware({\n * maxRetries: 5,\n * backoffFactor: 0.0, // No exponential growth\n * initialDelayMs: 2000, // Always wait 2 seconds\n * });\n * ```\n *\n * @example Raise exception on failure\n * ```ts\n * const retry = modelRetryMiddleware({\n * maxRetries: 2,\n * onFailure: \"error\", // Re-raise exception instead of returning message\n * });\n * ```\n *\n * @param config - Configuration options for the retry middleware\n * @returns A middleware instance that handles model failures with retries\n */\nexport function modelRetryMiddleware(config: ModelRetryMiddlewareConfig = {}) {\n const { success, error, data } =\n ModelRetryMiddlewareOptionsSchema.safeParse(config);\n if (!success) {\n throw new InvalidRetryConfigError(error);\n }\n const {\n maxRetries,\n retryOn,\n onFailure,\n backoffFactor,\n initialDelayMs,\n maxDelayMs,\n jitter,\n } = data;\n\n /**\n * Check if the exception should trigger a retry.\n */\n const shouldRetryException = (error: Error): boolean => {\n if (typeof retryOn === \"function\") {\n return retryOn(error);\n }\n // retryOn is an array of error constructors\n return retryOn.some(\n (ErrorConstructor) => error.constructor === ErrorConstructor\n );\n };\n\n // Use the exported calculateRetryDelay function with our config\n const delayConfig = { backoffFactor, initialDelayMs, maxDelayMs, jitter };\n\n /**\n * Format the failure message when retries are exhausted.\n */\n const formatFailureMessage = (error: Error, attemptsMade: number): string => {\n const errorType = error.constructor.name;\n const attemptWord = attemptsMade === 1 ? \"attempt\" : \"attempts\";\n return `Model call failed after ${attemptsMade} ${attemptWord} with ${errorType}: ${error.message}`;\n };\n\n /**\n * Handle failure when all retries are exhausted.\n */\n const handleFailure = (error: Error, attemptsMade: number): AIMessage => {\n if (onFailure === \"error\") {\n throw error;\n }\n\n let content: string;\n if (typeof onFailure === \"function\") {\n content = onFailure(error);\n } else {\n content = formatFailureMessage(error, attemptsMade);\n }\n\n return new AIMessage({\n content,\n });\n };\n\n return createMiddleware({\n name: \"modelRetryMiddleware\",\n contextSchema: ModelRetryMiddlewareOptionsSchema,\n wrapModelCall: async (request, handler) => {\n const delegated = {\n ...request,\n modelSettings: { maxRetries: 0, ...request.modelSettings },\n };\n\n // Initial attempt + retries\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await handler(delegated);\n } catch (error) {\n const attemptsMade = attempt + 1; // attempt is 0-indexed\n\n // Ensure error is an Error instance\n const err =\n error && typeof error === \"object\" && \"message\" in error\n ? (error as Error)\n : new Error(String(error));\n\n // Check if we should retry this exception\n if (!shouldRetryException(err)) {\n // Exception is not retryable, handle failure immediately\n return handleFailure(err, attemptsMade);\n }\n\n // Check if we have more retries left\n if (attempt < maxRetries) {\n // Calculate and apply backoff delay\n const delay = calculateRetryDelay(\n delayConfig,\n attempt,\n getRetryAfterMs(err)\n );\n if (delay > 0) {\n await sleep(delay);\n }\n // Continue to next retry\n } else {\n // No more retries, handle failure\n return handleFailure(err, attemptsMade);\n }\n }\n }\n\n // Unreachable: loop always returns via handler success or handleFailure\n throw new Error(\"Unexpected: retry loop completed without returning\");\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,MAAa,oCAAoCA,OAAAA,EAC9C,OAAO;;;;;;;;;AASN,WAAWA,OAAAA,EACR,MAAM;CACLA,OAAAA,EAAE,QAAQ,OAAO;CACjBA,OAAAA,EAAE,QAAQ,UAAU;CACpBA,OAAAA,EAAE,SAAS,CAAC,CAAC,KAAKA,OAAAA,EAAE,WAAW,KAAK,CAAC,CAAC,CAAC,QAAQA,OAAAA,EAAE,OAAO,CAAC;AAC3D,CAAC,CAAC,CACD,QAAQ,UAAU,EACvB,CAAC,CAAC,CACD,MAAMC,kBAAAA,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6FpB,SAAgB,qBAAqB,SAAqC,CAAC,GAAG;CAC5E,MAAM,EAAE,SAAS,OAAO,SACtB,kCAAkC,UAAU,MAAM;CACpD,IAAI,CAAC,SACH,MAAM,IAAIC,cAAAA,wBAAwB,KAAK;CAEzC,MAAM,EACJ,YACA,SACA,WACA,eACA,gBACA,YACA,WACE;;;;CAKJ,MAAM,wBAAwB,UAA0B;EACtD,IAAI,OAAO,YAAY,YACrB,OAAO,QAAQ,KAAK;EAGtB,OAAO,QAAQ,MACZ,qBAAqB,MAAM,gBAAgB,gBAC9C;CACF;CAGA,MAAM,cAAc;EAAE;EAAe;EAAgB;EAAY;CAAO;;;;CAKxE,MAAM,wBAAwB,OAAc,iBAAiC;EAC3E,MAAM,YAAY,MAAM,YAAY;EAEpC,OAAO,2BAA2B,aAAa,GAD3B,iBAAiB,IAAI,YAAY,WACS,QAAQ,UAAU,IAAI,MAAM;CAC5F;;;;CAKA,MAAM,iBAAiB,OAAc,iBAAoC;EACvE,IAAI,cAAc,SAChB,MAAM;EAGR,IAAI;EACJ,IAAI,OAAO,cAAc,YACvB,UAAU,UAAU,KAAK;OAEzB,UAAU,qBAAqB,OAAO,YAAY;EAGpD,OAAO,IAAIC,yBAAAA,UAAU,EACnB,QACF,CAAC;CACH;CAEA,OAAOC,mBAAAA,iBAAiB;EACtB,MAAM;EACN,eAAe;EACf,eAAe,OAAO,SAAS,YAAY;GACzC,MAAM,YAAY;IAChB,GAAG;IACH,eAAe;KAAE,YAAY;KAAG,GAAG,QAAQ;IAAc;GAC3D;GAGA,KAAK,IAAI,UAAU,GAAG,WAAW,YAAY,WAC3C,IAAI;IACF,OAAO,MAAM,QAAQ,SAAS;GAChC,SAAS,OAAO;IACd,MAAM,eAAe,UAAU;IAG/B,MAAM,MACJ,SAAS,OAAO,UAAU,YAAY,aAAa,QAC9C,QACD,IAAI,MAAM,OAAO,KAAK,CAAC;IAG7B,IAAI,CAAC,qBAAqB,GAAG,GAE3B,OAAO,cAAc,KAAK,YAAY;IAIxC,IAAI,UAAU,YAAY;KAExB,MAAM,QAAQC,cAAAA,oBACZ,aACA,SACAC,cAAAA,gBAAgB,GAAG,CACrB;KACA,IAAI,QAAQ,GACV,MAAMC,cAAAA,MAAM,KAAK;IAGrB,OAEE,OAAO,cAAc,KAAK,YAAY;GAE1C;GAIF,MAAM,IAAI,MAAM,oDAAoD;EACtE;CACF,CAAC;AACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modelRetry.d.cts","names":[],"sources":["../../../src/agents/middleware/modelRetry.ts"],"mappings":";;;;;;cAca,mCAAiC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAoBlC,6BAA6B,EAAE,aAClC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0FO,qBAAqB,SAAQ,wDAA+B,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"modelRetry.d.cts","names":[],"sources":["../../../src/agents/middleware/modelRetry.ts"],"mappings":";;;;;;cAca,mCAAiC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAoBlC,6BAA6B,EAAE,aAClC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0FO,qBAAqB,SAAQ,wDAA+B,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6CAgH3E,6CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modelRetry.d.ts","names":[],"sources":["../../../src/agents/middleware/modelRetry.ts"],"mappings":";;;;;;cAca,mCAAiC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAoBlC,6BAA6B,EAAE,aAClC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0FO,qBAAqB,SAAQ,wDAA+B,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"modelRetry.d.ts","names":[],"sources":["../../../src/agents/middleware/modelRetry.ts"],"mappings":";;;;;;cAca,mCAAiC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAoBlC,6BAA6B,EAAE,aAClC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0FO,qBAAqB,SAAQ,wDAA+B,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6CAgH3E,6CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { calculateRetryDelay, sleep } from "./utils.js";
|
|
1
|
+
import { calculateRetryDelay, getRetryAfterMs, sleep } from "./utils.js";
|
|
2
2
|
import { createMiddleware } from "../middleware.js";
|
|
3
3
|
import { RetrySchema } from "./constants.js";
|
|
4
4
|
import { InvalidRetryConfigError } from "./error.js";
|
|
@@ -150,14 +150,21 @@ function modelRetryMiddleware(config = {}) {
|
|
|
150
150
|
name: "modelRetryMiddleware",
|
|
151
151
|
contextSchema: ModelRetryMiddlewareOptionsSchema,
|
|
152
152
|
wrapModelCall: async (request, handler) => {
|
|
153
|
+
const delegated = {
|
|
154
|
+
...request,
|
|
155
|
+
modelSettings: {
|
|
156
|
+
maxRetries: 0,
|
|
157
|
+
...request.modelSettings
|
|
158
|
+
}
|
|
159
|
+
};
|
|
153
160
|
for (let attempt = 0; attempt <= maxRetries; attempt++) try {
|
|
154
|
-
return await handler(
|
|
161
|
+
return await handler(delegated);
|
|
155
162
|
} catch (error) {
|
|
156
163
|
const attemptsMade = attempt + 1;
|
|
157
164
|
const err = error && typeof error === "object" && "message" in error ? error : new Error(String(error));
|
|
158
165
|
if (!shouldRetryException(err)) return handleFailure(err, attemptsMade);
|
|
159
166
|
if (attempt < maxRetries) {
|
|
160
|
-
const delay = calculateRetryDelay(delayConfig, attempt);
|
|
167
|
+
const delay = calculateRetryDelay(delayConfig, attempt, getRetryAfterMs(err));
|
|
161
168
|
if (delay > 0) await sleep(delay);
|
|
162
169
|
} else return handleFailure(err, attemptsMade);
|
|
163
170
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modelRetry.js","names":[],"sources":["../../../src/agents/middleware/modelRetry.ts"],"sourcesContent":["/**\n * Model retry middleware for agents.\n */\nimport { z } from \"zod/v3\";\nimport { AIMessage } from \"@langchain/core/messages\";\n\nimport { createMiddleware } from \"../middleware.js\";\nimport { sleep, calculateRetryDelay } from \"./utils.js\";\nimport { RetrySchema } from \"./constants.js\";\nimport { InvalidRetryConfigError } from \"./error.js\";\n\n/**\n * Configuration options for the Model Retry Middleware.\n */\nexport const ModelRetryMiddlewareOptionsSchema = z\n .object({\n /**\n * Behavior when all retries are exhausted. Options:\n * - `\"continue\"` (default): Return an AIMessage with error details, allowing\n * the agent to potentially handle the failure gracefully.\n * - `\"error\"`: Re-raise the exception, stopping agent execution.\n * - Custom function: Function that takes the exception and returns a string\n * for the AIMessage content, allowing custom error formatting.\n */\n onFailure: z\n .union([\n z.literal(\"error\"),\n z.literal(\"continue\"),\n z.function().args(z.instanceof(Error)).returns(z.string()),\n ])\n .default(\"continue\"),\n })\n .merge(RetrySchema);\n\nexport type ModelRetryMiddlewareConfig = z.input<\n typeof ModelRetryMiddlewareOptionsSchema\n>;\n\n/**\n * Middleware that automatically retries failed model calls with configurable backoff.\n *\n * Supports retrying on specific exceptions and exponential backoff.\n *\n * @example Basic usage with default settings (2 retries, exponential backoff)\n * ```ts\n * import { createAgent, modelRetryMiddleware } from \"langchain\";\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [searchTool],\n * middleware: [modelRetryMiddleware()],\n * });\n * ```\n *\n * @example Retry specific exceptions only\n * ```ts\n * import { modelRetryMiddleware } from \"langchain\";\n *\n * const retry = modelRetryMiddleware({\n * maxRetries: 4,\n * retryOn: [TimeoutError, NetworkError],\n * backoffFactor: 1.5,\n * });\n * ```\n *\n * @example Custom exception filtering\n * ```ts\n * function shouldRetry(error: Error): boolean {\n * // Only retry on rate limit errors\n * if (error.name === \"RateLimitError\") {\n * return true;\n * }\n * // Or check for specific HTTP status codes\n * if (error.name === \"HTTPError\" && \"statusCode\" in error) {\n * const statusCode = (error as any).statusCode;\n * return statusCode === 429 || statusCode === 503;\n * }\n * return false;\n * }\n *\n * const retry = modelRetryMiddleware({\n * maxRetries: 3,\n * retryOn: shouldRetry,\n * });\n * ```\n *\n * @example Return error message instead of raising\n * ```ts\n * const retry = modelRetryMiddleware({\n * maxRetries: 4,\n * onFailure: \"continue\", // Return AIMessage with error instead of throwing\n * });\n * ```\n *\n * @example Custom error message formatting\n * ```ts\n * const formatError = (error: Error) =>\n * `Model call failed: ${error.message}. Please try again later.`;\n *\n * const retry = modelRetryMiddleware({\n * maxRetries: 4,\n * onFailure: formatError,\n * });\n * ```\n *\n * @example Constant backoff (no exponential growth)\n * ```ts\n * const retry = modelRetryMiddleware({\n * maxRetries: 5,\n * backoffFactor: 0.0, // No exponential growth\n * initialDelayMs: 2000, // Always wait 2 seconds\n * });\n * ```\n *\n * @example Raise exception on failure\n * ```ts\n * const retry = modelRetryMiddleware({\n * maxRetries: 2,\n * onFailure: \"error\", // Re-raise exception instead of returning message\n * });\n * ```\n *\n * @param config - Configuration options for the retry middleware\n * @returns A middleware instance that handles model failures with retries\n */\nexport function modelRetryMiddleware(config: ModelRetryMiddlewareConfig = {}) {\n const { success, error, data } =\n ModelRetryMiddlewareOptionsSchema.safeParse(config);\n if (!success) {\n throw new InvalidRetryConfigError(error);\n }\n const {\n maxRetries,\n retryOn,\n onFailure,\n backoffFactor,\n initialDelayMs,\n maxDelayMs,\n jitter,\n } = data;\n\n /**\n * Check if the exception should trigger a retry.\n */\n const shouldRetryException = (error: Error): boolean => {\n if (typeof retryOn === \"function\") {\n return retryOn(error);\n }\n // retryOn is an array of error constructors\n return retryOn.some(\n (ErrorConstructor) => error.constructor === ErrorConstructor\n );\n };\n\n // Use the exported calculateRetryDelay function with our config\n const delayConfig = { backoffFactor, initialDelayMs, maxDelayMs, jitter };\n\n /**\n * Format the failure message when retries are exhausted.\n */\n const formatFailureMessage = (error: Error, attemptsMade: number): string => {\n const errorType = error.constructor.name;\n const attemptWord = attemptsMade === 1 ? \"attempt\" : \"attempts\";\n return `Model call failed after ${attemptsMade} ${attemptWord} with ${errorType}: ${error.message}`;\n };\n\n /**\n * Handle failure when all retries are exhausted.\n */\n const handleFailure = (error: Error, attemptsMade: number): AIMessage => {\n if (onFailure === \"error\") {\n throw error;\n }\n\n let content: string;\n if (typeof onFailure === \"function\") {\n content = onFailure(error);\n } else {\n content = formatFailureMessage(error, attemptsMade);\n }\n\n return new AIMessage({\n content,\n });\n };\n\n return createMiddleware({\n name: \"modelRetryMiddleware\",\n contextSchema: ModelRetryMiddlewareOptionsSchema,\n wrapModelCall: async (request, handler) => {\n // Initial attempt + retries\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await handler(
|
|
1
|
+
{"version":3,"file":"modelRetry.js","names":[],"sources":["../../../src/agents/middleware/modelRetry.ts"],"sourcesContent":["/**\n * Model retry middleware for agents.\n */\nimport { z } from \"zod/v3\";\nimport { AIMessage } from \"@langchain/core/messages\";\n\nimport { createMiddleware } from \"../middleware.js\";\nimport { sleep, calculateRetryDelay, getRetryAfterMs } from \"./utils.js\";\nimport { RetrySchema } from \"./constants.js\";\nimport { InvalidRetryConfigError } from \"./error.js\";\n\n/**\n * Configuration options for the Model Retry Middleware.\n */\nexport const ModelRetryMiddlewareOptionsSchema = z\n .object({\n /**\n * Behavior when all retries are exhausted. Options:\n * - `\"continue\"` (default): Return an AIMessage with error details, allowing\n * the agent to potentially handle the failure gracefully.\n * - `\"error\"`: Re-raise the exception, stopping agent execution.\n * - Custom function: Function that takes the exception and returns a string\n * for the AIMessage content, allowing custom error formatting.\n */\n onFailure: z\n .union([\n z.literal(\"error\"),\n z.literal(\"continue\"),\n z.function().args(z.instanceof(Error)).returns(z.string()),\n ])\n .default(\"continue\"),\n })\n .merge(RetrySchema);\n\nexport type ModelRetryMiddlewareConfig = z.input<\n typeof ModelRetryMiddlewareOptionsSchema\n>;\n\n/**\n * Middleware that automatically retries failed model calls with configurable backoff.\n *\n * Supports retrying on specific exceptions and exponential backoff.\n *\n * @example Basic usage with default settings (2 retries, exponential backoff)\n * ```ts\n * import { createAgent, modelRetryMiddleware } from \"langchain\";\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [searchTool],\n * middleware: [modelRetryMiddleware()],\n * });\n * ```\n *\n * @example Retry specific exceptions only\n * ```ts\n * import { modelRetryMiddleware } from \"langchain\";\n *\n * const retry = modelRetryMiddleware({\n * maxRetries: 4,\n * retryOn: [TimeoutError, NetworkError],\n * backoffFactor: 1.5,\n * });\n * ```\n *\n * @example Custom exception filtering\n * ```ts\n * function shouldRetry(error: Error): boolean {\n * // Only retry on rate limit errors\n * if (error.name === \"RateLimitError\") {\n * return true;\n * }\n * // Or check for specific HTTP status codes\n * if (error.name === \"HTTPError\" && \"statusCode\" in error) {\n * const statusCode = (error as any).statusCode;\n * return statusCode === 429 || statusCode === 503;\n * }\n * return false;\n * }\n *\n * const retry = modelRetryMiddleware({\n * maxRetries: 3,\n * retryOn: shouldRetry,\n * });\n * ```\n *\n * @example Return error message instead of raising\n * ```ts\n * const retry = modelRetryMiddleware({\n * maxRetries: 4,\n * onFailure: \"continue\", // Return AIMessage with error instead of throwing\n * });\n * ```\n *\n * @example Custom error message formatting\n * ```ts\n * const formatError = (error: Error) =>\n * `Model call failed: ${error.message}. Please try again later.`;\n *\n * const retry = modelRetryMiddleware({\n * maxRetries: 4,\n * onFailure: formatError,\n * });\n * ```\n *\n * @example Constant backoff (no exponential growth)\n * ```ts\n * const retry = modelRetryMiddleware({\n * maxRetries: 5,\n * backoffFactor: 0.0, // No exponential growth\n * initialDelayMs: 2000, // Always wait 2 seconds\n * });\n * ```\n *\n * @example Raise exception on failure\n * ```ts\n * const retry = modelRetryMiddleware({\n * maxRetries: 2,\n * onFailure: \"error\", // Re-raise exception instead of returning message\n * });\n * ```\n *\n * @param config - Configuration options for the retry middleware\n * @returns A middleware instance that handles model failures with retries\n */\nexport function modelRetryMiddleware(config: ModelRetryMiddlewareConfig = {}) {\n const { success, error, data } =\n ModelRetryMiddlewareOptionsSchema.safeParse(config);\n if (!success) {\n throw new InvalidRetryConfigError(error);\n }\n const {\n maxRetries,\n retryOn,\n onFailure,\n backoffFactor,\n initialDelayMs,\n maxDelayMs,\n jitter,\n } = data;\n\n /**\n * Check if the exception should trigger a retry.\n */\n const shouldRetryException = (error: Error): boolean => {\n if (typeof retryOn === \"function\") {\n return retryOn(error);\n }\n // retryOn is an array of error constructors\n return retryOn.some(\n (ErrorConstructor) => error.constructor === ErrorConstructor\n );\n };\n\n // Use the exported calculateRetryDelay function with our config\n const delayConfig = { backoffFactor, initialDelayMs, maxDelayMs, jitter };\n\n /**\n * Format the failure message when retries are exhausted.\n */\n const formatFailureMessage = (error: Error, attemptsMade: number): string => {\n const errorType = error.constructor.name;\n const attemptWord = attemptsMade === 1 ? \"attempt\" : \"attempts\";\n return `Model call failed after ${attemptsMade} ${attemptWord} with ${errorType}: ${error.message}`;\n };\n\n /**\n * Handle failure when all retries are exhausted.\n */\n const handleFailure = (error: Error, attemptsMade: number): AIMessage => {\n if (onFailure === \"error\") {\n throw error;\n }\n\n let content: string;\n if (typeof onFailure === \"function\") {\n content = onFailure(error);\n } else {\n content = formatFailureMessage(error, attemptsMade);\n }\n\n return new AIMessage({\n content,\n });\n };\n\n return createMiddleware({\n name: \"modelRetryMiddleware\",\n contextSchema: ModelRetryMiddlewareOptionsSchema,\n wrapModelCall: async (request, handler) => {\n const delegated = {\n ...request,\n modelSettings: { maxRetries: 0, ...request.modelSettings },\n };\n\n // Initial attempt + retries\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await handler(delegated);\n } catch (error) {\n const attemptsMade = attempt + 1; // attempt is 0-indexed\n\n // Ensure error is an Error instance\n const err =\n error && typeof error === \"object\" && \"message\" in error\n ? (error as Error)\n : new Error(String(error));\n\n // Check if we should retry this exception\n if (!shouldRetryException(err)) {\n // Exception is not retryable, handle failure immediately\n return handleFailure(err, attemptsMade);\n }\n\n // Check if we have more retries left\n if (attempt < maxRetries) {\n // Calculate and apply backoff delay\n const delay = calculateRetryDelay(\n delayConfig,\n attempt,\n getRetryAfterMs(err)\n );\n if (delay > 0) {\n await sleep(delay);\n }\n // Continue to next retry\n } else {\n // No more retries, handle failure\n return handleFailure(err, attemptsMade);\n }\n }\n }\n\n // Unreachable: loop always returns via handler success or handleFailure\n throw new Error(\"Unexpected: retry loop completed without returning\");\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,MAAa,oCAAoC,EAC9C,OAAO;;;;;;;;;AASN,WAAW,EACR,MAAM;CACL,EAAE,QAAQ,OAAO;CACjB,EAAE,QAAQ,UAAU;CACpB,EAAE,SAAS,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC;AAC3D,CAAC,CAAC,CACD,QAAQ,UAAU,EACvB,CAAC,CAAC,CACD,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6FpB,SAAgB,qBAAqB,SAAqC,CAAC,GAAG;CAC5E,MAAM,EAAE,SAAS,OAAO,SACtB,kCAAkC,UAAU,MAAM;CACpD,IAAI,CAAC,SACH,MAAM,IAAI,wBAAwB,KAAK;CAEzC,MAAM,EACJ,YACA,SACA,WACA,eACA,gBACA,YACA,WACE;;;;CAKJ,MAAM,wBAAwB,UAA0B;EACtD,IAAI,OAAO,YAAY,YACrB,OAAO,QAAQ,KAAK;EAGtB,OAAO,QAAQ,MACZ,qBAAqB,MAAM,gBAAgB,gBAC9C;CACF;CAGA,MAAM,cAAc;EAAE;EAAe;EAAgB;EAAY;CAAO;;;;CAKxE,MAAM,wBAAwB,OAAc,iBAAiC;EAC3E,MAAM,YAAY,MAAM,YAAY;EAEpC,OAAO,2BAA2B,aAAa,GAD3B,iBAAiB,IAAI,YAAY,WACS,QAAQ,UAAU,IAAI,MAAM;CAC5F;;;;CAKA,MAAM,iBAAiB,OAAc,iBAAoC;EACvE,IAAI,cAAc,SAChB,MAAM;EAGR,IAAI;EACJ,IAAI,OAAO,cAAc,YACvB,UAAU,UAAU,KAAK;OAEzB,UAAU,qBAAqB,OAAO,YAAY;EAGpD,OAAO,IAAI,UAAU,EACnB,QACF,CAAC;CACH;CAEA,OAAO,iBAAiB;EACtB,MAAM;EACN,eAAe;EACf,eAAe,OAAO,SAAS,YAAY;GACzC,MAAM,YAAY;IAChB,GAAG;IACH,eAAe;KAAE,YAAY;KAAG,GAAG,QAAQ;IAAc;GAC3D;GAGA,KAAK,IAAI,UAAU,GAAG,WAAW,YAAY,WAC3C,IAAI;IACF,OAAO,MAAM,QAAQ,SAAS;GAChC,SAAS,OAAO;IACd,MAAM,eAAe,UAAU;IAG/B,MAAM,MACJ,SAAS,OAAO,UAAU,YAAY,aAAa,QAC9C,QACD,IAAI,MAAM,OAAO,KAAK,CAAC;IAG7B,IAAI,CAAC,qBAAqB,GAAG,GAE3B,OAAO,cAAc,KAAK,YAAY;IAIxC,IAAI,UAAU,YAAY;KAExB,MAAM,QAAQ,oBACZ,aACA,SACA,gBAAgB,GAAG,CACrB;KACA,IAAI,QAAQ,GACV,MAAM,MAAM,KAAK;IAGrB,OAEE,OAAO,cAAc,KAAK,YAAY;GAE1C;GAIF,MAAM,IAAI,MAAM,oDAAoD;EACtE;CACF,CAAC;AACH"}
|
|
@@ -215,7 +215,7 @@ function toolRetryMiddleware(config = {}) {
|
|
|
215
215
|
const err = error && typeof error === "object" && "message" in error ? error : new Error(String(error));
|
|
216
216
|
if (!shouldRetryException(err)) return handleFailure(toolName, toolCallId, err, attemptsMade);
|
|
217
217
|
if (attempt < maxRetries) {
|
|
218
|
-
const delay = require_utils.calculateRetryDelay(delayConfig, attempt);
|
|
218
|
+
const delay = require_utils.calculateRetryDelay(delayConfig, attempt, require_utils.getRetryAfterMs(error));
|
|
219
219
|
if (delay > 0) await require_utils.sleep(delay);
|
|
220
220
|
} else return handleFailure(toolName, toolCallId, err, attemptsMade);
|
|
221
221
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolRetry.cjs","names":["z","RetrySchema","InvalidRetryConfigError","ToolMessage","createMiddleware","calculateRetryDelay","sleep"],"sources":["../../../src/agents/middleware/toolRetry.ts"],"sourcesContent":["/**\n * Tool retry middleware for agents.\n */\nimport { z } from \"zod/v3\";\nimport { ToolMessage } from \"@langchain/core/messages\";\nimport type { ClientTool, ServerTool } from \"@langchain/core/tools\";\n\nimport { createMiddleware } from \"../middleware.js\";\nimport { sleep, calculateRetryDelay } from \"./utils.js\";\nimport { RetrySchema } from \"./constants.js\";\nimport { InvalidRetryConfigError } from \"./error.js\";\n\n/**\n * Configuration options for the Tool Retry Middleware.\n */\nexport const ToolRetryMiddlewareOptionsSchema = z\n .object({\n /**\n * Optional list of tools or tool names to apply retry logic to.\n * Can be a list of `BaseTool` instances or tool name strings.\n * If `undefined`, applies to all tools. Default is `undefined`.\n */\n tools: z\n .array(\n z.union([z.custom<ClientTool>(), z.custom<ServerTool>(), z.string()])\n )\n .optional(),\n\n /**\n * Behavior when all retries are exhausted. Options:\n * - `\"continue\"` (default): Return an AIMessage with error details, allowing\n * the agent to potentially handle the failure gracefully.\n * - `\"error\"`: Re-raise the exception, stopping agent execution.\n * - Custom function: Function that takes the exception and returns a string\n * for the AIMessage content, allowing custom error formatting.\n *\n * Deprecated values:\n * - `\"raise\"`: use `\"error\"` instead.\n * - `\"return_message\"`: use `\"continue\"` instead.\n */\n onFailure: z\n .union([\n z.literal(\"error\"),\n z.literal(\"continue\"),\n /**\n * @deprecated Use `\"error\"` instead.\n */\n z.literal(\"raise\"),\n /**\n * @deprecated Use `\"continue\"` instead.\n */\n z.literal(\"return_message\"),\n z.function().args(z.instanceof(Error)).returns(z.string()),\n ])\n .default(\"continue\"),\n })\n .merge(RetrySchema);\n\nexport type ToolRetryMiddlewareConfig = z.input<\n typeof ToolRetryMiddlewareOptionsSchema\n>;\n\n/**\n * Middleware that automatically retries failed tool calls with configurable backoff.\n *\n * Supports retrying on specific exceptions and exponential backoff.\n *\n * @example Basic usage with default settings (2 retries, exponential backoff)\n * ```ts\n * import { createAgent, toolRetryMiddleware } from \"langchain\";\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [searchTool],\n * middleware: [toolRetryMiddleware()],\n * });\n * ```\n *\n * @example Retry specific exceptions only\n * ```ts\n * import { toolRetryMiddleware } from \"langchain\";\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 4,\n * retryOn: [TimeoutError, NetworkError],\n * backoffFactor: 1.5,\n * });\n * ```\n *\n * @example Custom exception filtering\n * ```ts\n * function shouldRetry(error: Error): boolean {\n * // Only retry on 5xx errors\n * if (error.name === \"HTTPError\" && \"statusCode\" in error) {\n * const statusCode = (error as any).statusCode;\n * return 500 <= statusCode && statusCode < 600;\n * }\n * return false;\n * }\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 3,\n * retryOn: shouldRetry,\n * });\n * ```\n *\n * @example Apply to specific tools with custom error handling\n * ```ts\n * const formatError = (error: Error) =>\n * \"Database temporarily unavailable. Please try again later.\";\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 4,\n * tools: [\"search_database\"],\n * onFailure: formatError,\n * });\n * ```\n *\n * @example Apply to specific tools using BaseTool instances\n * ```ts\n * import { tool } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n *\n * const searchDatabase = tool(\n * async ({ query }) => {\n * // Search implementation\n * return results;\n * },\n * {\n * name: \"search_database\",\n * description: \"Search the database\",\n * schema: z.object({ query: z.string() }),\n * }\n * );\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 4,\n * tools: [searchDatabase], // Pass BaseTool instance\n * });\n * ```\n *\n * @example Constant backoff (no exponential growth)\n * ```ts\n * const retry = toolRetryMiddleware({\n * maxRetries: 5,\n * backoffFactor: 0.0, // No exponential growth\n * initialDelayMs: 2000, // Always wait 2 seconds\n * });\n * ```\n *\n * @example Raise exception on failure\n * ```ts\n * const retry = toolRetryMiddleware({\n * maxRetries: 2,\n * onFailure: \"raise\", // Re-raise exception instead of returning message\n * });\n * ```\n *\n * @param config - Configuration options for the retry middleware\n * @returns A middleware instance that handles tool failures with retries\n */\nexport function toolRetryMiddleware(config: ToolRetryMiddlewareConfig = {}) {\n const { success, error, data } =\n ToolRetryMiddlewareOptionsSchema.safeParse(config);\n if (!success) {\n throw new InvalidRetryConfigError(error);\n }\n const {\n maxRetries,\n tools,\n retryOn,\n onFailure: onFailureConfig,\n backoffFactor,\n initialDelayMs,\n maxDelayMs,\n jitter,\n } = data;\n\n let onFailure = onFailureConfig;\n if (onFailureConfig === \"raise\") {\n console.warn(\n \"⚠️ `onFailure: 'raise'` is deprecated. Use `onFailure: 'error'` instead.\"\n );\n onFailure = \"error\";\n } else if (onFailureConfig === \"return_message\") {\n console.warn(\n \"⚠️ `onFailure: 'return_message'` is deprecated. Use `onFailure: 'continue'` instead.\"\n );\n onFailure = \"continue\";\n }\n\n // Extract tool names from BaseTool instances or strings\n const toolFilter: string[] = [];\n for (const tool of tools ?? []) {\n if (typeof tool === \"string\") {\n toolFilter.push(tool);\n } else if (\"name\" in tool && typeof tool.name === \"string\") {\n toolFilter.push(tool.name);\n } else {\n throw new TypeError(\n \"Expected a tool name string or tool instance to be passed to toolRetryMiddleware\"\n );\n }\n }\n\n /**\n * Check if retry logic should apply to this tool.\n */\n const shouldRetryTool = (toolName: string): boolean => {\n if (toolFilter.length === 0) {\n return true;\n }\n return toolFilter.includes(toolName);\n };\n\n /**\n * Check if the exception should trigger a retry.\n */\n const shouldRetryException = (error: Error): boolean => {\n if (typeof retryOn === \"function\") {\n return retryOn(error);\n }\n // retryOn is an array of error constructors\n return retryOn.some((ErrorConstructor) => {\n // oxlint-disable-next-line no-instanceof/no-instanceof\n return error instanceof ErrorConstructor;\n });\n };\n\n // Use the exported calculateRetryDelay function with our config\n const delayConfig = { backoffFactor, initialDelayMs, maxDelayMs, jitter };\n\n /**\n * Format the failure message when retries are exhausted.\n */\n const formatFailureMessage = (\n toolName: string,\n error: Error,\n attemptsMade: number\n ): string => {\n const errorType = error.constructor.name;\n const attemptWord = attemptsMade === 1 ? \"attempt\" : \"attempts\";\n return `Tool '${toolName}' failed after ${attemptsMade} ${attemptWord} with ${errorType}`;\n };\n\n /**\n * Handle failure when all retries are exhausted.\n */\n const handleFailure = (\n toolName: string,\n toolCallId: string,\n error: Error,\n attemptsMade: number\n ): ToolMessage => {\n if (onFailure === \"error\") {\n throw error;\n }\n\n let content: string;\n if (typeof onFailure === \"function\") {\n content = onFailure(error);\n } else {\n content = formatFailureMessage(toolName, error, attemptsMade);\n }\n\n return new ToolMessage({\n content,\n tool_call_id: toolCallId,\n name: toolName,\n status: \"error\",\n });\n };\n\n return createMiddleware({\n name: \"toolRetryMiddleware\",\n contextSchema: ToolRetryMiddlewareOptionsSchema,\n wrapToolCall: async (request, handler) => {\n const toolName = (request.tool?.name ?? request.toolCall.name) as string;\n\n // Check if retry should apply to this tool\n if (!shouldRetryTool(toolName)) {\n return handler(request);\n }\n\n const toolCallId = request.toolCall.id ?? \"\";\n\n // Initial attempt + retries\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await handler(request);\n } catch (error) {\n const attemptsMade = attempt + 1; // attempt is 0-indexed\n\n // Ensure error is an Error instance\n const err =\n error && typeof error === \"object\" && \"message\" in error\n ? (error as Error)\n : new Error(String(error));\n\n // Check if we should retry this exception\n if (!shouldRetryException(err)) {\n // Exception is not retryable, handle failure immediately\n return handleFailure(toolName, toolCallId, err, attemptsMade);\n }\n\n // Check if we have more retries left\n if (attempt < maxRetries) {\n // Calculate and apply backoff delay\n const delay = calculateRetryDelay(delayConfig, attempt);\n if (delay > 0) {\n await sleep(delay);\n }\n // Continue to next retry\n } else {\n // No more retries, handle failure\n return handleFailure(toolName, toolCallId, err, attemptsMade);\n }\n }\n }\n\n // Unreachable: loop always returns via handler success or handleFailure\n throw new Error(\"Unexpected: retry loop completed without returning\");\n },\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"toolRetry.cjs","names":["z","RetrySchema","InvalidRetryConfigError","ToolMessage","createMiddleware","calculateRetryDelay","getRetryAfterMs","sleep"],"sources":["../../../src/agents/middleware/toolRetry.ts"],"sourcesContent":["/**\n * Tool retry middleware for agents.\n */\nimport { z } from \"zod/v3\";\nimport { ToolMessage } from \"@langchain/core/messages\";\nimport type { ClientTool, ServerTool } from \"@langchain/core/tools\";\n\nimport { createMiddleware } from \"../middleware.js\";\nimport { sleep, calculateRetryDelay, getRetryAfterMs } from \"./utils.js\";\nimport { RetrySchema } from \"./constants.js\";\nimport { InvalidRetryConfigError } from \"./error.js\";\n\n/**\n * Configuration options for the Tool Retry Middleware.\n */\nexport const ToolRetryMiddlewareOptionsSchema = z\n .object({\n /**\n * Optional list of tools or tool names to apply retry logic to.\n * Can be a list of `BaseTool` instances or tool name strings.\n * If `undefined`, applies to all tools. Default is `undefined`.\n */\n tools: z\n .array(\n z.union([z.custom<ClientTool>(), z.custom<ServerTool>(), z.string()])\n )\n .optional(),\n\n /**\n * Behavior when all retries are exhausted. Options:\n * - `\"continue\"` (default): Return an AIMessage with error details, allowing\n * the agent to potentially handle the failure gracefully.\n * - `\"error\"`: Re-raise the exception, stopping agent execution.\n * - Custom function: Function that takes the exception and returns a string\n * for the AIMessage content, allowing custom error formatting.\n *\n * Deprecated values:\n * - `\"raise\"`: use `\"error\"` instead.\n * - `\"return_message\"`: use `\"continue\"` instead.\n */\n onFailure: z\n .union([\n z.literal(\"error\"),\n z.literal(\"continue\"),\n /**\n * @deprecated Use `\"error\"` instead.\n */\n z.literal(\"raise\"),\n /**\n * @deprecated Use `\"continue\"` instead.\n */\n z.literal(\"return_message\"),\n z.function().args(z.instanceof(Error)).returns(z.string()),\n ])\n .default(\"continue\"),\n })\n .merge(RetrySchema);\n\nexport type ToolRetryMiddlewareConfig = z.input<\n typeof ToolRetryMiddlewareOptionsSchema\n>;\n\n/**\n * Middleware that automatically retries failed tool calls with configurable backoff.\n *\n * Supports retrying on specific exceptions and exponential backoff.\n *\n * @example Basic usage with default settings (2 retries, exponential backoff)\n * ```ts\n * import { createAgent, toolRetryMiddleware } from \"langchain\";\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [searchTool],\n * middleware: [toolRetryMiddleware()],\n * });\n * ```\n *\n * @example Retry specific exceptions only\n * ```ts\n * import { toolRetryMiddleware } from \"langchain\";\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 4,\n * retryOn: [TimeoutError, NetworkError],\n * backoffFactor: 1.5,\n * });\n * ```\n *\n * @example Custom exception filtering\n * ```ts\n * function shouldRetry(error: Error): boolean {\n * // Only retry on 5xx errors\n * if (error.name === \"HTTPError\" && \"statusCode\" in error) {\n * const statusCode = (error as any).statusCode;\n * return 500 <= statusCode && statusCode < 600;\n * }\n * return false;\n * }\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 3,\n * retryOn: shouldRetry,\n * });\n * ```\n *\n * @example Apply to specific tools with custom error handling\n * ```ts\n * const formatError = (error: Error) =>\n * \"Database temporarily unavailable. Please try again later.\";\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 4,\n * tools: [\"search_database\"],\n * onFailure: formatError,\n * });\n * ```\n *\n * @example Apply to specific tools using BaseTool instances\n * ```ts\n * import { tool } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n *\n * const searchDatabase = tool(\n * async ({ query }) => {\n * // Search implementation\n * return results;\n * },\n * {\n * name: \"search_database\",\n * description: \"Search the database\",\n * schema: z.object({ query: z.string() }),\n * }\n * );\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 4,\n * tools: [searchDatabase], // Pass BaseTool instance\n * });\n * ```\n *\n * @example Constant backoff (no exponential growth)\n * ```ts\n * const retry = toolRetryMiddleware({\n * maxRetries: 5,\n * backoffFactor: 0.0, // No exponential growth\n * initialDelayMs: 2000, // Always wait 2 seconds\n * });\n * ```\n *\n * @example Raise exception on failure\n * ```ts\n * const retry = toolRetryMiddleware({\n * maxRetries: 2,\n * onFailure: \"raise\", // Re-raise exception instead of returning message\n * });\n * ```\n *\n * @param config - Configuration options for the retry middleware\n * @returns A middleware instance that handles tool failures with retries\n */\nexport function toolRetryMiddleware(config: ToolRetryMiddlewareConfig = {}) {\n const { success, error, data } =\n ToolRetryMiddlewareOptionsSchema.safeParse(config);\n if (!success) {\n throw new InvalidRetryConfigError(error);\n }\n const {\n maxRetries,\n tools,\n retryOn,\n onFailure: onFailureConfig,\n backoffFactor,\n initialDelayMs,\n maxDelayMs,\n jitter,\n } = data;\n\n let onFailure = onFailureConfig;\n if (onFailureConfig === \"raise\") {\n console.warn(\n \"⚠️ `onFailure: 'raise'` is deprecated. Use `onFailure: 'error'` instead.\"\n );\n onFailure = \"error\";\n } else if (onFailureConfig === \"return_message\") {\n console.warn(\n \"⚠️ `onFailure: 'return_message'` is deprecated. Use `onFailure: 'continue'` instead.\"\n );\n onFailure = \"continue\";\n }\n\n // Extract tool names from BaseTool instances or strings\n const toolFilter: string[] = [];\n for (const tool of tools ?? []) {\n if (typeof tool === \"string\") {\n toolFilter.push(tool);\n } else if (\"name\" in tool && typeof tool.name === \"string\") {\n toolFilter.push(tool.name);\n } else {\n throw new TypeError(\n \"Expected a tool name string or tool instance to be passed to toolRetryMiddleware\"\n );\n }\n }\n\n /**\n * Check if retry logic should apply to this tool.\n */\n const shouldRetryTool = (toolName: string): boolean => {\n if (toolFilter.length === 0) {\n return true;\n }\n return toolFilter.includes(toolName);\n };\n\n /**\n * Check if the exception should trigger a retry.\n */\n const shouldRetryException = (error: Error): boolean => {\n if (typeof retryOn === \"function\") {\n return retryOn(error);\n }\n // retryOn is an array of error constructors\n return retryOn.some((ErrorConstructor) => {\n // oxlint-disable-next-line no-instanceof/no-instanceof\n return error instanceof ErrorConstructor;\n });\n };\n\n // Use the exported calculateRetryDelay function with our config\n const delayConfig = { backoffFactor, initialDelayMs, maxDelayMs, jitter };\n\n /**\n * Format the failure message when retries are exhausted.\n */\n const formatFailureMessage = (\n toolName: string,\n error: Error,\n attemptsMade: number\n ): string => {\n const errorType = error.constructor.name;\n const attemptWord = attemptsMade === 1 ? \"attempt\" : \"attempts\";\n return `Tool '${toolName}' failed after ${attemptsMade} ${attemptWord} with ${errorType}`;\n };\n\n /**\n * Handle failure when all retries are exhausted.\n */\n const handleFailure = (\n toolName: string,\n toolCallId: string,\n error: Error,\n attemptsMade: number\n ): ToolMessage => {\n if (onFailure === \"error\") {\n throw error;\n }\n\n let content: string;\n if (typeof onFailure === \"function\") {\n content = onFailure(error);\n } else {\n content = formatFailureMessage(toolName, error, attemptsMade);\n }\n\n return new ToolMessage({\n content,\n tool_call_id: toolCallId,\n name: toolName,\n status: \"error\",\n });\n };\n\n return createMiddleware({\n name: \"toolRetryMiddleware\",\n contextSchema: ToolRetryMiddlewareOptionsSchema,\n wrapToolCall: async (request, handler) => {\n const toolName = (request.tool?.name ?? request.toolCall.name) as string;\n\n // Check if retry should apply to this tool\n if (!shouldRetryTool(toolName)) {\n return handler(request);\n }\n\n const toolCallId = request.toolCall.id ?? \"\";\n\n // Initial attempt + retries\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await handler(request);\n } catch (error) {\n const attemptsMade = attempt + 1; // attempt is 0-indexed\n\n // Ensure error is an Error instance\n const err =\n error && typeof error === \"object\" && \"message\" in error\n ? (error as Error)\n : new Error(String(error));\n\n // Check if we should retry this exception\n if (!shouldRetryException(err)) {\n // Exception is not retryable, handle failure immediately\n return handleFailure(toolName, toolCallId, err, attemptsMade);\n }\n\n // Check if we have more retries left\n if (attempt < maxRetries) {\n // Calculate and apply backoff delay\n const delay = calculateRetryDelay(\n delayConfig,\n attempt,\n getRetryAfterMs(error)\n );\n if (delay > 0) {\n await sleep(delay);\n }\n // Continue to next retry\n } else {\n // No more retries, handle failure\n return handleFailure(toolName, toolCallId, err, attemptsMade);\n }\n }\n }\n\n // Unreachable: loop always returns via handler success or handleFailure\n throw new Error(\"Unexpected: retry loop completed without returning\");\n },\n });\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolRetry.d.cts","names":[],"sources":["../../../src/agents/middleware/toolRetry.ts"],"mappings":";;;;;;;cAea,kCAAgC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2CjC,4BAA4B,EAAE,aACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsGO,oBAAoB,SAAQ,
|
|
1
|
+
{"version":3,"file":"toolRetry.d.cts","names":[],"sources":["../../../src/agents/middleware/toolRetry.ts"],"mappings":";;;;;;;cAea,kCAAgC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2CjC,4BAA4B,EAAE,aACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsGO,oBAAoB,SAAQ,4BAuK3C,2BAvKyE,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAuKzE,aAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolRetry.d.ts","names":[],"sources":["../../../src/agents/middleware/toolRetry.ts"],"mappings":";;;;;;;cAea,kCAAgC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2CjC,4BAA4B,EAAE,aACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsGO,oBAAoB,SAAQ,
|
|
1
|
+
{"version":3,"file":"toolRetry.d.ts","names":[],"sources":["../../../src/agents/middleware/toolRetry.ts"],"mappings":";;;;;;;cAea,kCAAgC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2CjC,4BAA4B,EAAE,aACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsGO,oBAAoB,SAAQ,4BAuK3C,2BAvKyE,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAuKzE,aAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { calculateRetryDelay, sleep } from "./utils.js";
|
|
1
|
+
import { calculateRetryDelay, getRetryAfterMs, sleep } from "./utils.js";
|
|
2
2
|
import { createMiddleware } from "../middleware.js";
|
|
3
3
|
import { RetrySchema } from "./constants.js";
|
|
4
4
|
import { InvalidRetryConfigError } from "./error.js";
|
|
@@ -215,7 +215,7 @@ function toolRetryMiddleware(config = {}) {
|
|
|
215
215
|
const err = error && typeof error === "object" && "message" in error ? error : new Error(String(error));
|
|
216
216
|
if (!shouldRetryException(err)) return handleFailure(toolName, toolCallId, err, attemptsMade);
|
|
217
217
|
if (attempt < maxRetries) {
|
|
218
|
-
const delay = calculateRetryDelay(delayConfig, attempt);
|
|
218
|
+
const delay = calculateRetryDelay(delayConfig, attempt, getRetryAfterMs(error));
|
|
219
219
|
if (delay > 0) await sleep(delay);
|
|
220
220
|
} else return handleFailure(toolName, toolCallId, err, attemptsMade);
|
|
221
221
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolRetry.js","names":[],"sources":["../../../src/agents/middleware/toolRetry.ts"],"sourcesContent":["/**\n * Tool retry middleware for agents.\n */\nimport { z } from \"zod/v3\";\nimport { ToolMessage } from \"@langchain/core/messages\";\nimport type { ClientTool, ServerTool } from \"@langchain/core/tools\";\n\nimport { createMiddleware } from \"../middleware.js\";\nimport { sleep, calculateRetryDelay } from \"./utils.js\";\nimport { RetrySchema } from \"./constants.js\";\nimport { InvalidRetryConfigError } from \"./error.js\";\n\n/**\n * Configuration options for the Tool Retry Middleware.\n */\nexport const ToolRetryMiddlewareOptionsSchema = z\n .object({\n /**\n * Optional list of tools or tool names to apply retry logic to.\n * Can be a list of `BaseTool` instances or tool name strings.\n * If `undefined`, applies to all tools. Default is `undefined`.\n */\n tools: z\n .array(\n z.union([z.custom<ClientTool>(), z.custom<ServerTool>(), z.string()])\n )\n .optional(),\n\n /**\n * Behavior when all retries are exhausted. Options:\n * - `\"continue\"` (default): Return an AIMessage with error details, allowing\n * the agent to potentially handle the failure gracefully.\n * - `\"error\"`: Re-raise the exception, stopping agent execution.\n * - Custom function: Function that takes the exception and returns a string\n * for the AIMessage content, allowing custom error formatting.\n *\n * Deprecated values:\n * - `\"raise\"`: use `\"error\"` instead.\n * - `\"return_message\"`: use `\"continue\"` instead.\n */\n onFailure: z\n .union([\n z.literal(\"error\"),\n z.literal(\"continue\"),\n /**\n * @deprecated Use `\"error\"` instead.\n */\n z.literal(\"raise\"),\n /**\n * @deprecated Use `\"continue\"` instead.\n */\n z.literal(\"return_message\"),\n z.function().args(z.instanceof(Error)).returns(z.string()),\n ])\n .default(\"continue\"),\n })\n .merge(RetrySchema);\n\nexport type ToolRetryMiddlewareConfig = z.input<\n typeof ToolRetryMiddlewareOptionsSchema\n>;\n\n/**\n * Middleware that automatically retries failed tool calls with configurable backoff.\n *\n * Supports retrying on specific exceptions and exponential backoff.\n *\n * @example Basic usage with default settings (2 retries, exponential backoff)\n * ```ts\n * import { createAgent, toolRetryMiddleware } from \"langchain\";\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [searchTool],\n * middleware: [toolRetryMiddleware()],\n * });\n * ```\n *\n * @example Retry specific exceptions only\n * ```ts\n * import { toolRetryMiddleware } from \"langchain\";\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 4,\n * retryOn: [TimeoutError, NetworkError],\n * backoffFactor: 1.5,\n * });\n * ```\n *\n * @example Custom exception filtering\n * ```ts\n * function shouldRetry(error: Error): boolean {\n * // Only retry on 5xx errors\n * if (error.name === \"HTTPError\" && \"statusCode\" in error) {\n * const statusCode = (error as any).statusCode;\n * return 500 <= statusCode && statusCode < 600;\n * }\n * return false;\n * }\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 3,\n * retryOn: shouldRetry,\n * });\n * ```\n *\n * @example Apply to specific tools with custom error handling\n * ```ts\n * const formatError = (error: Error) =>\n * \"Database temporarily unavailable. Please try again later.\";\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 4,\n * tools: [\"search_database\"],\n * onFailure: formatError,\n * });\n * ```\n *\n * @example Apply to specific tools using BaseTool instances\n * ```ts\n * import { tool } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n *\n * const searchDatabase = tool(\n * async ({ query }) => {\n * // Search implementation\n * return results;\n * },\n * {\n * name: \"search_database\",\n * description: \"Search the database\",\n * schema: z.object({ query: z.string() }),\n * }\n * );\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 4,\n * tools: [searchDatabase], // Pass BaseTool instance\n * });\n * ```\n *\n * @example Constant backoff (no exponential growth)\n * ```ts\n * const retry = toolRetryMiddleware({\n * maxRetries: 5,\n * backoffFactor: 0.0, // No exponential growth\n * initialDelayMs: 2000, // Always wait 2 seconds\n * });\n * ```\n *\n * @example Raise exception on failure\n * ```ts\n * const retry = toolRetryMiddleware({\n * maxRetries: 2,\n * onFailure: \"raise\", // Re-raise exception instead of returning message\n * });\n * ```\n *\n * @param config - Configuration options for the retry middleware\n * @returns A middleware instance that handles tool failures with retries\n */\nexport function toolRetryMiddleware(config: ToolRetryMiddlewareConfig = {}) {\n const { success, error, data } =\n ToolRetryMiddlewareOptionsSchema.safeParse(config);\n if (!success) {\n throw new InvalidRetryConfigError(error);\n }\n const {\n maxRetries,\n tools,\n retryOn,\n onFailure: onFailureConfig,\n backoffFactor,\n initialDelayMs,\n maxDelayMs,\n jitter,\n } = data;\n\n let onFailure = onFailureConfig;\n if (onFailureConfig === \"raise\") {\n console.warn(\n \"⚠️ `onFailure: 'raise'` is deprecated. Use `onFailure: 'error'` instead.\"\n );\n onFailure = \"error\";\n } else if (onFailureConfig === \"return_message\") {\n console.warn(\n \"⚠️ `onFailure: 'return_message'` is deprecated. Use `onFailure: 'continue'` instead.\"\n );\n onFailure = \"continue\";\n }\n\n // Extract tool names from BaseTool instances or strings\n const toolFilter: string[] = [];\n for (const tool of tools ?? []) {\n if (typeof tool === \"string\") {\n toolFilter.push(tool);\n } else if (\"name\" in tool && typeof tool.name === \"string\") {\n toolFilter.push(tool.name);\n } else {\n throw new TypeError(\n \"Expected a tool name string or tool instance to be passed to toolRetryMiddleware\"\n );\n }\n }\n\n /**\n * Check if retry logic should apply to this tool.\n */\n const shouldRetryTool = (toolName: string): boolean => {\n if (toolFilter.length === 0) {\n return true;\n }\n return toolFilter.includes(toolName);\n };\n\n /**\n * Check if the exception should trigger a retry.\n */\n const shouldRetryException = (error: Error): boolean => {\n if (typeof retryOn === \"function\") {\n return retryOn(error);\n }\n // retryOn is an array of error constructors\n return retryOn.some((ErrorConstructor) => {\n // oxlint-disable-next-line no-instanceof/no-instanceof\n return error instanceof ErrorConstructor;\n });\n };\n\n // Use the exported calculateRetryDelay function with our config\n const delayConfig = { backoffFactor, initialDelayMs, maxDelayMs, jitter };\n\n /**\n * Format the failure message when retries are exhausted.\n */\n const formatFailureMessage = (\n toolName: string,\n error: Error,\n attemptsMade: number\n ): string => {\n const errorType = error.constructor.name;\n const attemptWord = attemptsMade === 1 ? \"attempt\" : \"attempts\";\n return `Tool '${toolName}' failed after ${attemptsMade} ${attemptWord} with ${errorType}`;\n };\n\n /**\n * Handle failure when all retries are exhausted.\n */\n const handleFailure = (\n toolName: string,\n toolCallId: string,\n error: Error,\n attemptsMade: number\n ): ToolMessage => {\n if (onFailure === \"error\") {\n throw error;\n }\n\n let content: string;\n if (typeof onFailure === \"function\") {\n content = onFailure(error);\n } else {\n content = formatFailureMessage(toolName, error, attemptsMade);\n }\n\n return new ToolMessage({\n content,\n tool_call_id: toolCallId,\n name: toolName,\n status: \"error\",\n });\n };\n\n return createMiddleware({\n name: \"toolRetryMiddleware\",\n contextSchema: ToolRetryMiddlewareOptionsSchema,\n wrapToolCall: async (request, handler) => {\n const toolName = (request.tool?.name ?? request.toolCall.name) as string;\n\n // Check if retry should apply to this tool\n if (!shouldRetryTool(toolName)) {\n return handler(request);\n }\n\n const toolCallId = request.toolCall.id ?? \"\";\n\n // Initial attempt + retries\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await handler(request);\n } catch (error) {\n const attemptsMade = attempt + 1; // attempt is 0-indexed\n\n // Ensure error is an Error instance\n const err =\n error && typeof error === \"object\" && \"message\" in error\n ? (error as Error)\n : new Error(String(error));\n\n // Check if we should retry this exception\n if (!shouldRetryException(err)) {\n // Exception is not retryable, handle failure immediately\n return handleFailure(toolName, toolCallId, err, attemptsMade);\n }\n\n // Check if we have more retries left\n if (attempt < maxRetries) {\n // Calculate and apply backoff delay\n const delay = calculateRetryDelay(delayConfig, attempt);\n if (delay > 0) {\n await sleep(delay);\n }\n // Continue to next retry\n } else {\n // No more retries, handle failure\n return handleFailure(toolName, toolCallId, err, attemptsMade);\n }\n }\n }\n\n // Unreachable: loop always returns via handler success or handleFailure\n throw new Error(\"Unexpected: retry loop completed without returning\");\n },\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"toolRetry.js","names":[],"sources":["../../../src/agents/middleware/toolRetry.ts"],"sourcesContent":["/**\n * Tool retry middleware for agents.\n */\nimport { z } from \"zod/v3\";\nimport { ToolMessage } from \"@langchain/core/messages\";\nimport type { ClientTool, ServerTool } from \"@langchain/core/tools\";\n\nimport { createMiddleware } from \"../middleware.js\";\nimport { sleep, calculateRetryDelay, getRetryAfterMs } from \"./utils.js\";\nimport { RetrySchema } from \"./constants.js\";\nimport { InvalidRetryConfigError } from \"./error.js\";\n\n/**\n * Configuration options for the Tool Retry Middleware.\n */\nexport const ToolRetryMiddlewareOptionsSchema = z\n .object({\n /**\n * Optional list of tools or tool names to apply retry logic to.\n * Can be a list of `BaseTool` instances or tool name strings.\n * If `undefined`, applies to all tools. Default is `undefined`.\n */\n tools: z\n .array(\n z.union([z.custom<ClientTool>(), z.custom<ServerTool>(), z.string()])\n )\n .optional(),\n\n /**\n * Behavior when all retries are exhausted. Options:\n * - `\"continue\"` (default): Return an AIMessage with error details, allowing\n * the agent to potentially handle the failure gracefully.\n * - `\"error\"`: Re-raise the exception, stopping agent execution.\n * - Custom function: Function that takes the exception and returns a string\n * for the AIMessage content, allowing custom error formatting.\n *\n * Deprecated values:\n * - `\"raise\"`: use `\"error\"` instead.\n * - `\"return_message\"`: use `\"continue\"` instead.\n */\n onFailure: z\n .union([\n z.literal(\"error\"),\n z.literal(\"continue\"),\n /**\n * @deprecated Use `\"error\"` instead.\n */\n z.literal(\"raise\"),\n /**\n * @deprecated Use `\"continue\"` instead.\n */\n z.literal(\"return_message\"),\n z.function().args(z.instanceof(Error)).returns(z.string()),\n ])\n .default(\"continue\"),\n })\n .merge(RetrySchema);\n\nexport type ToolRetryMiddlewareConfig = z.input<\n typeof ToolRetryMiddlewareOptionsSchema\n>;\n\n/**\n * Middleware that automatically retries failed tool calls with configurable backoff.\n *\n * Supports retrying on specific exceptions and exponential backoff.\n *\n * @example Basic usage with default settings (2 retries, exponential backoff)\n * ```ts\n * import { createAgent, toolRetryMiddleware } from \"langchain\";\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [searchTool],\n * middleware: [toolRetryMiddleware()],\n * });\n * ```\n *\n * @example Retry specific exceptions only\n * ```ts\n * import { toolRetryMiddleware } from \"langchain\";\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 4,\n * retryOn: [TimeoutError, NetworkError],\n * backoffFactor: 1.5,\n * });\n * ```\n *\n * @example Custom exception filtering\n * ```ts\n * function shouldRetry(error: Error): boolean {\n * // Only retry on 5xx errors\n * if (error.name === \"HTTPError\" && \"statusCode\" in error) {\n * const statusCode = (error as any).statusCode;\n * return 500 <= statusCode && statusCode < 600;\n * }\n * return false;\n * }\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 3,\n * retryOn: shouldRetry,\n * });\n * ```\n *\n * @example Apply to specific tools with custom error handling\n * ```ts\n * const formatError = (error: Error) =>\n * \"Database temporarily unavailable. Please try again later.\";\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 4,\n * tools: [\"search_database\"],\n * onFailure: formatError,\n * });\n * ```\n *\n * @example Apply to specific tools using BaseTool instances\n * ```ts\n * import { tool } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n *\n * const searchDatabase = tool(\n * async ({ query }) => {\n * // Search implementation\n * return results;\n * },\n * {\n * name: \"search_database\",\n * description: \"Search the database\",\n * schema: z.object({ query: z.string() }),\n * }\n * );\n *\n * const retry = toolRetryMiddleware({\n * maxRetries: 4,\n * tools: [searchDatabase], // Pass BaseTool instance\n * });\n * ```\n *\n * @example Constant backoff (no exponential growth)\n * ```ts\n * const retry = toolRetryMiddleware({\n * maxRetries: 5,\n * backoffFactor: 0.0, // No exponential growth\n * initialDelayMs: 2000, // Always wait 2 seconds\n * });\n * ```\n *\n * @example Raise exception on failure\n * ```ts\n * const retry = toolRetryMiddleware({\n * maxRetries: 2,\n * onFailure: \"raise\", // Re-raise exception instead of returning message\n * });\n * ```\n *\n * @param config - Configuration options for the retry middleware\n * @returns A middleware instance that handles tool failures with retries\n */\nexport function toolRetryMiddleware(config: ToolRetryMiddlewareConfig = {}) {\n const { success, error, data } =\n ToolRetryMiddlewareOptionsSchema.safeParse(config);\n if (!success) {\n throw new InvalidRetryConfigError(error);\n }\n const {\n maxRetries,\n tools,\n retryOn,\n onFailure: onFailureConfig,\n backoffFactor,\n initialDelayMs,\n maxDelayMs,\n jitter,\n } = data;\n\n let onFailure = onFailureConfig;\n if (onFailureConfig === \"raise\") {\n console.warn(\n \"⚠️ `onFailure: 'raise'` is deprecated. Use `onFailure: 'error'` instead.\"\n );\n onFailure = \"error\";\n } else if (onFailureConfig === \"return_message\") {\n console.warn(\n \"⚠️ `onFailure: 'return_message'` is deprecated. Use `onFailure: 'continue'` instead.\"\n );\n onFailure = \"continue\";\n }\n\n // Extract tool names from BaseTool instances or strings\n const toolFilter: string[] = [];\n for (const tool of tools ?? []) {\n if (typeof tool === \"string\") {\n toolFilter.push(tool);\n } else if (\"name\" in tool && typeof tool.name === \"string\") {\n toolFilter.push(tool.name);\n } else {\n throw new TypeError(\n \"Expected a tool name string or tool instance to be passed to toolRetryMiddleware\"\n );\n }\n }\n\n /**\n * Check if retry logic should apply to this tool.\n */\n const shouldRetryTool = (toolName: string): boolean => {\n if (toolFilter.length === 0) {\n return true;\n }\n return toolFilter.includes(toolName);\n };\n\n /**\n * Check if the exception should trigger a retry.\n */\n const shouldRetryException = (error: Error): boolean => {\n if (typeof retryOn === \"function\") {\n return retryOn(error);\n }\n // retryOn is an array of error constructors\n return retryOn.some((ErrorConstructor) => {\n // oxlint-disable-next-line no-instanceof/no-instanceof\n return error instanceof ErrorConstructor;\n });\n };\n\n // Use the exported calculateRetryDelay function with our config\n const delayConfig = { backoffFactor, initialDelayMs, maxDelayMs, jitter };\n\n /**\n * Format the failure message when retries are exhausted.\n */\n const formatFailureMessage = (\n toolName: string,\n error: Error,\n attemptsMade: number\n ): string => {\n const errorType = error.constructor.name;\n const attemptWord = attemptsMade === 1 ? \"attempt\" : \"attempts\";\n return `Tool '${toolName}' failed after ${attemptsMade} ${attemptWord} with ${errorType}`;\n };\n\n /**\n * Handle failure when all retries are exhausted.\n */\n const handleFailure = (\n toolName: string,\n toolCallId: string,\n error: Error,\n attemptsMade: number\n ): ToolMessage => {\n if (onFailure === \"error\") {\n throw error;\n }\n\n let content: string;\n if (typeof onFailure === \"function\") {\n content = onFailure(error);\n } else {\n content = formatFailureMessage(toolName, error, attemptsMade);\n }\n\n return new ToolMessage({\n content,\n tool_call_id: toolCallId,\n name: toolName,\n status: \"error\",\n });\n };\n\n return createMiddleware({\n name: \"toolRetryMiddleware\",\n contextSchema: ToolRetryMiddlewareOptionsSchema,\n wrapToolCall: async (request, handler) => {\n const toolName = (request.tool?.name ?? request.toolCall.name) as string;\n\n // Check if retry should apply to this tool\n if (!shouldRetryTool(toolName)) {\n return handler(request);\n }\n\n const toolCallId = request.toolCall.id ?? \"\";\n\n // Initial attempt + retries\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await handler(request);\n } catch (error) {\n const attemptsMade = attempt + 1; // attempt is 0-indexed\n\n // Ensure error is an Error instance\n const err =\n error && typeof error === \"object\" && \"message\" in error\n ? (error as Error)\n : new Error(String(error));\n\n // Check if we should retry this exception\n if (!shouldRetryException(err)) {\n // Exception is not retryable, handle failure immediately\n return handleFailure(toolName, toolCallId, err, attemptsMade);\n }\n\n // Check if we have more retries left\n if (attempt < maxRetries) {\n // Calculate and apply backoff delay\n const delay = calculateRetryDelay(\n delayConfig,\n attempt,\n getRetryAfterMs(error)\n );\n if (delay > 0) {\n await sleep(delay);\n }\n // Continue to next retry\n } else {\n // No more retries, handle failure\n return handleFailure(toolName, toolCallId, err, attemptsMade);\n }\n }\n }\n\n // Unreachable: loop always returns via handler success or handleFailure\n throw new Error(\"Unexpected: retry loop completed without returning\");\n },\n });\n}\n"],"mappings":"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"}
|
|
@@ -58,11 +58,13 @@ function sleep(ms) {
|
|
|
58
58
|
*
|
|
59
59
|
* @param retryNumber - The retry attempt number (0-indexed)
|
|
60
60
|
* @param config - Configuration for backoff calculation
|
|
61
|
+
* @param retryAfterMs - A provider-supplied wait hint, e.g. from a `Retry-After`
|
|
62
|
+
* header. Used as a floor so we never retry sooner than the server asked.
|
|
61
63
|
* @returns Delay in milliseconds before next retry
|
|
62
64
|
*
|
|
63
65
|
* @internal Exported for testing purposes
|
|
64
66
|
*/
|
|
65
|
-
function calculateRetryDelay(config, retryNumber) {
|
|
67
|
+
function calculateRetryDelay(config, retryNumber, retryAfterMs) {
|
|
66
68
|
const { backoffFactor, initialDelayMs, maxDelayMs, jitter } = config;
|
|
67
69
|
let delay;
|
|
68
70
|
if (backoffFactor === 0) delay = initialDelayMs;
|
|
@@ -73,13 +75,19 @@ function calculateRetryDelay(config, retryNumber) {
|
|
|
73
75
|
delay = delay + (Math.random() * 2 - 1) * jitterAmount;
|
|
74
76
|
delay = Math.max(0, delay);
|
|
75
77
|
}
|
|
76
|
-
return delay;
|
|
78
|
+
return Math.max(delay, retryAfterMs ?? 0);
|
|
79
|
+
}
|
|
80
|
+
function getRetryAfterMs(error) {
|
|
81
|
+
if (typeof error !== "object" || error === null) return;
|
|
82
|
+
const { retryAfterMs } = error;
|
|
83
|
+
return typeof retryAfterMs === "number" && retryAfterMs >= 0 ? retryAfterMs : void 0;
|
|
77
84
|
}
|
|
78
85
|
//#endregion
|
|
79
86
|
exports.calculateRetryDelay = calculateRetryDelay;
|
|
80
87
|
exports.countTokensApproximately = countTokensApproximately;
|
|
81
88
|
exports.getHookConstraint = getHookConstraint;
|
|
82
89
|
exports.getHookFunction = getHookFunction;
|
|
90
|
+
exports.getRetryAfterMs = getRetryAfterMs;
|
|
83
91
|
exports.sleep = sleep;
|
|
84
92
|
|
|
85
93
|
//# sourceMappingURL=utils.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","names":["AIMessage","ToolMessage"],"sources":["../../../src/agents/middleware/utils.ts"],"sourcesContent":["import {\n AIMessage,\n ToolMessage,\n type BaseMessage,\n} from \"@langchain/core/messages\";\nimport { isLangChainTool } from \"@langchain/core/tools\";\nimport { convertToOpenAITool } from \"@langchain/core/utils/function_calling\";\nimport {\n AfterModelHook,\n AfterAgentHook,\n BeforeAgentHook,\n BeforeModelHook,\n} from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n\n/**\n * Default token counter that approximates based on character count.\n *\n * If tools are provided, the token count also includes stringified tool schemas.\n *\n * @param messages Messages to count tokens for\n * @param tools Optional list of tools to include in the token count. Each tool\n * can be either a LangChain tool instance or a dict representing a tool schema.\n * LangChain tool instances are converted to OpenAI tool format before counting.\n * @returns Approximate token count\n */\nexport function countTokensApproximately(\n messages: BaseMessage[],\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n tools?: Array<Record<string, any>> | null\n): number {\n const charsPerToken = 4;\n let totalChars = 0;\n\n // Count tokens for tools if provided\n if (tools && tools.length > 0) {\n let toolsChars = 0;\n for (const tool of tools) {\n const toolDict = isLangChainTool(tool) ? convertToOpenAITool(tool) : tool;\n toolsChars += JSON.stringify(toolDict).length;\n }\n totalChars += toolsChars;\n }\n\n for (const msg of messages) {\n let textContent: string;\n if (typeof msg.content === \"string\") {\n textContent = msg.content;\n } else if (Array.isArray(msg.content)) {\n textContent = msg.content\n .map((item) => {\n if (typeof item === \"string\") return item;\n if (item.type === \"text\" && \"text\" in item) return item.text;\n return \"\";\n })\n .join(\"\");\n } else {\n textContent = \"\";\n }\n\n if (\n AIMessage.isInstance(msg) &&\n Array.isArray(msg.tool_calls) &&\n msg.tool_calls.length > 0\n ) {\n textContent += JSON.stringify(msg.tool_calls);\n }\n\n if (ToolMessage.isInstance(msg)) {\n textContent += msg.tool_call_id ?? \"\";\n }\n\n totalChars += textContent.length;\n }\n // Approximate 1 token = 4 characters\n return Math.ceil(totalChars / charsPerToken);\n}\n\nexport function getHookConstraint(\n hook:\n | BeforeAgentHook\n | BeforeModelHook\n | AfterAgentHook\n | AfterModelHook\n | undefined\n): JumpToTarget[] | undefined {\n if (!hook || typeof hook === \"function\") {\n return undefined;\n }\n return hook.canJumpTo;\n}\n\nexport function getHookFunction(\n arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook\n) {\n if (typeof arg === \"function\") {\n return arg;\n }\n return arg.hook;\n}\n\n/**\n * Sleep for the specified number of milliseconds.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay for a retry attempt with exponential backoff and jitter.\n *\n * @param retryNumber - The retry attempt number (0-indexed)\n * @param config - Configuration for backoff calculation\n * @returns Delay in milliseconds before next retry\n *\n * @internal Exported for testing purposes\n */\nexport function calculateRetryDelay(\n config: {\n backoffFactor: number;\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n },\n retryNumber: number\n): number {\n const { backoffFactor, initialDelayMs, maxDelayMs, jitter } = config;\n\n let delay: number;\n if (backoffFactor === 0.0) {\n delay = initialDelayMs;\n } else {\n delay = initialDelayMs * backoffFactor ** retryNumber;\n }\n\n // Cap at maxDelayMs\n delay = Math.min(delay, maxDelayMs);\n\n if (jitter && delay > 0) {\n const jitterAmount = delay * 0.25;\n delay = delay + (Math.random() * 2 - 1) * jitterAmount;\n // Ensure delay is not negative after jitter\n delay = Math.max(0, delay);\n }\n\n return delay;\n}\n"],"mappings":";;;;;;;;;;;;;;;AA0BA,SAAgB,yBACd,UAEA,OACQ;CACR,MAAM,gBAAgB;CACtB,IAAI,aAAa;CAGjB,IAAI,SAAS,MAAM,SAAS,GAAG;EAC7B,IAAI,aAAa;EACjB,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,YAAA,GAAA,sBAAA,gBAAA,CAA2B,IAAI,KAAA,GAAA,uCAAA,oBAAA,CAAwB,IAAI,IAAI;GACrE,cAAc,KAAK,UAAU,QAAQ,CAAC,CAAC;EACzC;EACA,cAAc;CAChB;CAEA,KAAK,MAAM,OAAO,UAAU;EAC1B,IAAI;EACJ,IAAI,OAAO,IAAI,YAAY,UACzB,cAAc,IAAI;OACb,IAAI,MAAM,QAAQ,IAAI,OAAO,GAClC,cAAc,IAAI,QACf,KAAK,SAAS;GACb,IAAI,OAAO,SAAS,UAAU,OAAO;GACrC,IAAI,KAAK,SAAS,UAAU,UAAU,MAAM,OAAO,KAAK;GACxD,OAAO;EACT,CAAC,CAAC,CACD,KAAK,EAAE;OAEV,cAAc;EAGhB,IACEA,yBAAAA,UAAU,WAAW,GAAG,KACxB,MAAM,QAAQ,IAAI,UAAU,KAC5B,IAAI,WAAW,SAAS,GAExB,eAAe,KAAK,UAAU,IAAI,UAAU;EAG9C,IAAIC,yBAAAA,YAAY,WAAW,GAAG,GAC5B,eAAe,IAAI,gBAAgB;EAGrC,cAAc,YAAY;CAC5B;CAEA,OAAO,KAAK,KAAK,aAAa,aAAa;AAC7C;AAEA,SAAgB,kBACd,MAM4B;CAC5B,IAAI,CAAC,QAAQ,OAAO,SAAS,YAC3B;CAEF,OAAO,KAAK;AACd;AAEA,SAAgB,gBACd,KACA;CACA,IAAI,OAAO,QAAQ,YACjB,OAAO;CAET,OAAO,IAAI;AACb;;;;AAKA,SAAgB,MAAM,IAA2B;CAC/C,OAAO,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD
|
|
1
|
+
{"version":3,"file":"utils.cjs","names":["AIMessage","ToolMessage"],"sources":["../../../src/agents/middleware/utils.ts"],"sourcesContent":["import {\n AIMessage,\n ToolMessage,\n type BaseMessage,\n} from \"@langchain/core/messages\";\nimport { isLangChainTool } from \"@langchain/core/tools\";\nimport { convertToOpenAITool } from \"@langchain/core/utils/function_calling\";\nimport {\n AfterModelHook,\n AfterAgentHook,\n BeforeAgentHook,\n BeforeModelHook,\n} from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n\n/**\n * Default token counter that approximates based on character count.\n *\n * If tools are provided, the token count also includes stringified tool schemas.\n *\n * @param messages Messages to count tokens for\n * @param tools Optional list of tools to include in the token count. Each tool\n * can be either a LangChain tool instance or a dict representing a tool schema.\n * LangChain tool instances are converted to OpenAI tool format before counting.\n * @returns Approximate token count\n */\nexport function countTokensApproximately(\n messages: BaseMessage[],\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n tools?: Array<Record<string, any>> | null\n): number {\n const charsPerToken = 4;\n let totalChars = 0;\n\n // Count tokens for tools if provided\n if (tools && tools.length > 0) {\n let toolsChars = 0;\n for (const tool of tools) {\n const toolDict = isLangChainTool(tool) ? convertToOpenAITool(tool) : tool;\n toolsChars += JSON.stringify(toolDict).length;\n }\n totalChars += toolsChars;\n }\n\n for (const msg of messages) {\n let textContent: string;\n if (typeof msg.content === \"string\") {\n textContent = msg.content;\n } else if (Array.isArray(msg.content)) {\n textContent = msg.content\n .map((item) => {\n if (typeof item === \"string\") return item;\n if (item.type === \"text\" && \"text\" in item) return item.text;\n return \"\";\n })\n .join(\"\");\n } else {\n textContent = \"\";\n }\n\n if (\n AIMessage.isInstance(msg) &&\n Array.isArray(msg.tool_calls) &&\n msg.tool_calls.length > 0\n ) {\n textContent += JSON.stringify(msg.tool_calls);\n }\n\n if (ToolMessage.isInstance(msg)) {\n textContent += msg.tool_call_id ?? \"\";\n }\n\n totalChars += textContent.length;\n }\n // Approximate 1 token = 4 characters\n return Math.ceil(totalChars / charsPerToken);\n}\n\nexport function getHookConstraint(\n hook:\n | BeforeAgentHook\n | BeforeModelHook\n | AfterAgentHook\n | AfterModelHook\n | undefined\n): JumpToTarget[] | undefined {\n if (!hook || typeof hook === \"function\") {\n return undefined;\n }\n return hook.canJumpTo;\n}\n\nexport function getHookFunction(\n arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook\n) {\n if (typeof arg === \"function\") {\n return arg;\n }\n return arg.hook;\n}\n\n/**\n * Sleep for the specified number of milliseconds.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay for a retry attempt with exponential backoff and jitter.\n *\n * @param retryNumber - The retry attempt number (0-indexed)\n * @param config - Configuration for backoff calculation\n * @param retryAfterMs - A provider-supplied wait hint, e.g. from a `Retry-After`\n * header. Used as a floor so we never retry sooner than the server asked.\n * @returns Delay in milliseconds before next retry\n *\n * @internal Exported for testing purposes\n */\nexport function calculateRetryDelay(\n config: {\n backoffFactor: number;\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n },\n retryNumber: number,\n retryAfterMs?: number\n): number {\n const { backoffFactor, initialDelayMs, maxDelayMs, jitter } = config;\n\n let delay: number;\n if (backoffFactor === 0.0) {\n delay = initialDelayMs;\n } else {\n delay = initialDelayMs * backoffFactor ** retryNumber;\n }\n\n // Cap at maxDelayMs\n delay = Math.min(delay, maxDelayMs);\n\n if (jitter && delay > 0) {\n const jitterAmount = delay * 0.25;\n delay = delay + (Math.random() * 2 - 1) * jitterAmount;\n // Ensure delay is not negative after jitter\n delay = Math.max(0, delay);\n }\n\n return Math.max(delay, retryAfterMs ?? 0);\n}\n\nexport function getRetryAfterMs(error: unknown): number | undefined {\n if (typeof error !== \"object\" || error === null) {\n return undefined;\n }\n const { retryAfterMs } = error as { retryAfterMs?: unknown };\n return typeof retryAfterMs === \"number\" && retryAfterMs >= 0\n ? retryAfterMs\n : undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;;AA0BA,SAAgB,yBACd,UAEA,OACQ;CACR,MAAM,gBAAgB;CACtB,IAAI,aAAa;CAGjB,IAAI,SAAS,MAAM,SAAS,GAAG;EAC7B,IAAI,aAAa;EACjB,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,YAAA,GAAA,sBAAA,gBAAA,CAA2B,IAAI,KAAA,GAAA,uCAAA,oBAAA,CAAwB,IAAI,IAAI;GACrE,cAAc,KAAK,UAAU,QAAQ,CAAC,CAAC;EACzC;EACA,cAAc;CAChB;CAEA,KAAK,MAAM,OAAO,UAAU;EAC1B,IAAI;EACJ,IAAI,OAAO,IAAI,YAAY,UACzB,cAAc,IAAI;OACb,IAAI,MAAM,QAAQ,IAAI,OAAO,GAClC,cAAc,IAAI,QACf,KAAK,SAAS;GACb,IAAI,OAAO,SAAS,UAAU,OAAO;GACrC,IAAI,KAAK,SAAS,UAAU,UAAU,MAAM,OAAO,KAAK;GACxD,OAAO;EACT,CAAC,CAAC,CACD,KAAK,EAAE;OAEV,cAAc;EAGhB,IACEA,yBAAAA,UAAU,WAAW,GAAG,KACxB,MAAM,QAAQ,IAAI,UAAU,KAC5B,IAAI,WAAW,SAAS,GAExB,eAAe,KAAK,UAAU,IAAI,UAAU;EAG9C,IAAIC,yBAAAA,YAAY,WAAW,GAAG,GAC5B,eAAe,IAAI,gBAAgB;EAGrC,cAAc,YAAY;CAC5B;CAEA,OAAO,KAAK,KAAK,aAAa,aAAa;AAC7C;AAEA,SAAgB,kBACd,MAM4B;CAC5B,IAAI,CAAC,QAAQ,OAAO,SAAS,YAC3B;CAEF,OAAO,KAAK;AACd;AAEA,SAAgB,gBACd,KACA;CACA,IAAI,OAAO,QAAQ,YACjB,OAAO;CAET,OAAO,IAAI;AACb;;;;AAKA,SAAgB,MAAM,IAA2B;CAC/C,OAAO,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;;;;;;;;;;;;AAaA,SAAgB,oBACd,QAMA,aACA,cACQ;CACR,MAAM,EAAE,eAAe,gBAAgB,YAAY,WAAW;CAE9D,IAAI;CACJ,IAAI,kBAAkB,GACpB,QAAQ;MAER,QAAQ,iBAAiB,iBAAiB;CAI5C,QAAQ,KAAK,IAAI,OAAO,UAAU;CAElC,IAAI,UAAU,QAAQ,GAAG;EACvB,MAAM,eAAe,QAAQ;EAC7B,QAAQ,SAAS,KAAK,OAAO,IAAI,IAAI,KAAK;EAE1C,QAAQ,KAAK,IAAI,GAAG,KAAK;CAC3B;CAEA,OAAO,KAAK,IAAI,OAAO,gBAAgB,CAAC;AAC1C;AAEA,SAAgB,gBAAgB,OAAoC;CAClE,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC;CAEF,MAAM,EAAE,iBAAiB;CACzB,OAAO,OAAO,iBAAiB,YAAY,gBAAgB,IACvD,eACA,KAAA;AACN"}
|
|
@@ -58,11 +58,13 @@ function sleep(ms) {
|
|
|
58
58
|
*
|
|
59
59
|
* @param retryNumber - The retry attempt number (0-indexed)
|
|
60
60
|
* @param config - Configuration for backoff calculation
|
|
61
|
+
* @param retryAfterMs - A provider-supplied wait hint, e.g. from a `Retry-After`
|
|
62
|
+
* header. Used as a floor so we never retry sooner than the server asked.
|
|
61
63
|
* @returns Delay in milliseconds before next retry
|
|
62
64
|
*
|
|
63
65
|
* @internal Exported for testing purposes
|
|
64
66
|
*/
|
|
65
|
-
function calculateRetryDelay(config, retryNumber) {
|
|
67
|
+
function calculateRetryDelay(config, retryNumber, retryAfterMs) {
|
|
66
68
|
const { backoffFactor, initialDelayMs, maxDelayMs, jitter } = config;
|
|
67
69
|
let delay;
|
|
68
70
|
if (backoffFactor === 0) delay = initialDelayMs;
|
|
@@ -73,9 +75,14 @@ function calculateRetryDelay(config, retryNumber) {
|
|
|
73
75
|
delay = delay + (Math.random() * 2 - 1) * jitterAmount;
|
|
74
76
|
delay = Math.max(0, delay);
|
|
75
77
|
}
|
|
76
|
-
return delay;
|
|
78
|
+
return Math.max(delay, retryAfterMs ?? 0);
|
|
79
|
+
}
|
|
80
|
+
function getRetryAfterMs(error) {
|
|
81
|
+
if (typeof error !== "object" || error === null) return;
|
|
82
|
+
const { retryAfterMs } = error;
|
|
83
|
+
return typeof retryAfterMs === "number" && retryAfterMs >= 0 ? retryAfterMs : void 0;
|
|
77
84
|
}
|
|
78
85
|
//#endregion
|
|
79
|
-
export { calculateRetryDelay, countTokensApproximately, getHookConstraint, getHookFunction, sleep };
|
|
86
|
+
export { calculateRetryDelay, countTokensApproximately, getHookConstraint, getHookFunction, getRetryAfterMs, sleep };
|
|
80
87
|
|
|
81
88
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":[],"sources":["../../../src/agents/middleware/utils.ts"],"sourcesContent":["import {\n AIMessage,\n ToolMessage,\n type BaseMessage,\n} from \"@langchain/core/messages\";\nimport { isLangChainTool } from \"@langchain/core/tools\";\nimport { convertToOpenAITool } from \"@langchain/core/utils/function_calling\";\nimport {\n AfterModelHook,\n AfterAgentHook,\n BeforeAgentHook,\n BeforeModelHook,\n} from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n\n/**\n * Default token counter that approximates based on character count.\n *\n * If tools are provided, the token count also includes stringified tool schemas.\n *\n * @param messages Messages to count tokens for\n * @param tools Optional list of tools to include in the token count. Each tool\n * can be either a LangChain tool instance or a dict representing a tool schema.\n * LangChain tool instances are converted to OpenAI tool format before counting.\n * @returns Approximate token count\n */\nexport function countTokensApproximately(\n messages: BaseMessage[],\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n tools?: Array<Record<string, any>> | null\n): number {\n const charsPerToken = 4;\n let totalChars = 0;\n\n // Count tokens for tools if provided\n if (tools && tools.length > 0) {\n let toolsChars = 0;\n for (const tool of tools) {\n const toolDict = isLangChainTool(tool) ? convertToOpenAITool(tool) : tool;\n toolsChars += JSON.stringify(toolDict).length;\n }\n totalChars += toolsChars;\n }\n\n for (const msg of messages) {\n let textContent: string;\n if (typeof msg.content === \"string\") {\n textContent = msg.content;\n } else if (Array.isArray(msg.content)) {\n textContent = msg.content\n .map((item) => {\n if (typeof item === \"string\") return item;\n if (item.type === \"text\" && \"text\" in item) return item.text;\n return \"\";\n })\n .join(\"\");\n } else {\n textContent = \"\";\n }\n\n if (\n AIMessage.isInstance(msg) &&\n Array.isArray(msg.tool_calls) &&\n msg.tool_calls.length > 0\n ) {\n textContent += JSON.stringify(msg.tool_calls);\n }\n\n if (ToolMessage.isInstance(msg)) {\n textContent += msg.tool_call_id ?? \"\";\n }\n\n totalChars += textContent.length;\n }\n // Approximate 1 token = 4 characters\n return Math.ceil(totalChars / charsPerToken);\n}\n\nexport function getHookConstraint(\n hook:\n | BeforeAgentHook\n | BeforeModelHook\n | AfterAgentHook\n | AfterModelHook\n | undefined\n): JumpToTarget[] | undefined {\n if (!hook || typeof hook === \"function\") {\n return undefined;\n }\n return hook.canJumpTo;\n}\n\nexport function getHookFunction(\n arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook\n) {\n if (typeof arg === \"function\") {\n return arg;\n }\n return arg.hook;\n}\n\n/**\n * Sleep for the specified number of milliseconds.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay for a retry attempt with exponential backoff and jitter.\n *\n * @param retryNumber - The retry attempt number (0-indexed)\n * @param config - Configuration for backoff calculation\n * @returns Delay in milliseconds before next retry\n *\n * @internal Exported for testing purposes\n */\nexport function calculateRetryDelay(\n config: {\n backoffFactor: number;\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n },\n retryNumber: number\n): number {\n const { backoffFactor, initialDelayMs, maxDelayMs, jitter } = config;\n\n let delay: number;\n if (backoffFactor === 0.0) {\n delay = initialDelayMs;\n } else {\n delay = initialDelayMs * backoffFactor ** retryNumber;\n }\n\n // Cap at maxDelayMs\n delay = Math.min(delay, maxDelayMs);\n\n if (jitter && delay > 0) {\n const jitterAmount = delay * 0.25;\n delay = delay + (Math.random() * 2 - 1) * jitterAmount;\n // Ensure delay is not negative after jitter\n delay = Math.max(0, delay);\n }\n\n return delay;\n}\n"],"mappings":";;;;;;;;;;;;;;;AA0BA,SAAgB,yBACd,UAEA,OACQ;CACR,MAAM,gBAAgB;CACtB,IAAI,aAAa;CAGjB,IAAI,SAAS,MAAM,SAAS,GAAG;EAC7B,IAAI,aAAa;EACjB,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,WAAW,gBAAgB,IAAI,IAAI,oBAAoB,IAAI,IAAI;GACrE,cAAc,KAAK,UAAU,QAAQ,CAAC,CAAC;EACzC;EACA,cAAc;CAChB;CAEA,KAAK,MAAM,OAAO,UAAU;EAC1B,IAAI;EACJ,IAAI,OAAO,IAAI,YAAY,UACzB,cAAc,IAAI;OACb,IAAI,MAAM,QAAQ,IAAI,OAAO,GAClC,cAAc,IAAI,QACf,KAAK,SAAS;GACb,IAAI,OAAO,SAAS,UAAU,OAAO;GACrC,IAAI,KAAK,SAAS,UAAU,UAAU,MAAM,OAAO,KAAK;GACxD,OAAO;EACT,CAAC,CAAC,CACD,KAAK,EAAE;OAEV,cAAc;EAGhB,IACE,UAAU,WAAW,GAAG,KACxB,MAAM,QAAQ,IAAI,UAAU,KAC5B,IAAI,WAAW,SAAS,GAExB,eAAe,KAAK,UAAU,IAAI,UAAU;EAG9C,IAAI,YAAY,WAAW,GAAG,GAC5B,eAAe,IAAI,gBAAgB;EAGrC,cAAc,YAAY;CAC5B;CAEA,OAAO,KAAK,KAAK,aAAa,aAAa;AAC7C;AAEA,SAAgB,kBACd,MAM4B;CAC5B,IAAI,CAAC,QAAQ,OAAO,SAAS,YAC3B;CAEF,OAAO,KAAK;AACd;AAEA,SAAgB,gBACd,KACA;CACA,IAAI,OAAO,QAAQ,YACjB,OAAO;CAET,OAAO,IAAI;AACb;;;;AAKA,SAAgB,MAAM,IAA2B;CAC/C,OAAO,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../../src/agents/middleware/utils.ts"],"sourcesContent":["import {\n AIMessage,\n ToolMessage,\n type BaseMessage,\n} from \"@langchain/core/messages\";\nimport { isLangChainTool } from \"@langchain/core/tools\";\nimport { convertToOpenAITool } from \"@langchain/core/utils/function_calling\";\nimport {\n AfterModelHook,\n AfterAgentHook,\n BeforeAgentHook,\n BeforeModelHook,\n} from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n\n/**\n * Default token counter that approximates based on character count.\n *\n * If tools are provided, the token count also includes stringified tool schemas.\n *\n * @param messages Messages to count tokens for\n * @param tools Optional list of tools to include in the token count. Each tool\n * can be either a LangChain tool instance or a dict representing a tool schema.\n * LangChain tool instances are converted to OpenAI tool format before counting.\n * @returns Approximate token count\n */\nexport function countTokensApproximately(\n messages: BaseMessage[],\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n tools?: Array<Record<string, any>> | null\n): number {\n const charsPerToken = 4;\n let totalChars = 0;\n\n // Count tokens for tools if provided\n if (tools && tools.length > 0) {\n let toolsChars = 0;\n for (const tool of tools) {\n const toolDict = isLangChainTool(tool) ? convertToOpenAITool(tool) : tool;\n toolsChars += JSON.stringify(toolDict).length;\n }\n totalChars += toolsChars;\n }\n\n for (const msg of messages) {\n let textContent: string;\n if (typeof msg.content === \"string\") {\n textContent = msg.content;\n } else if (Array.isArray(msg.content)) {\n textContent = msg.content\n .map((item) => {\n if (typeof item === \"string\") return item;\n if (item.type === \"text\" && \"text\" in item) return item.text;\n return \"\";\n })\n .join(\"\");\n } else {\n textContent = \"\";\n }\n\n if (\n AIMessage.isInstance(msg) &&\n Array.isArray(msg.tool_calls) &&\n msg.tool_calls.length > 0\n ) {\n textContent += JSON.stringify(msg.tool_calls);\n }\n\n if (ToolMessage.isInstance(msg)) {\n textContent += msg.tool_call_id ?? \"\";\n }\n\n totalChars += textContent.length;\n }\n // Approximate 1 token = 4 characters\n return Math.ceil(totalChars / charsPerToken);\n}\n\nexport function getHookConstraint(\n hook:\n | BeforeAgentHook\n | BeforeModelHook\n | AfterAgentHook\n | AfterModelHook\n | undefined\n): JumpToTarget[] | undefined {\n if (!hook || typeof hook === \"function\") {\n return undefined;\n }\n return hook.canJumpTo;\n}\n\nexport function getHookFunction(\n arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook\n) {\n if (typeof arg === \"function\") {\n return arg;\n }\n return arg.hook;\n}\n\n/**\n * Sleep for the specified number of milliseconds.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay for a retry attempt with exponential backoff and jitter.\n *\n * @param retryNumber - The retry attempt number (0-indexed)\n * @param config - Configuration for backoff calculation\n * @param retryAfterMs - A provider-supplied wait hint, e.g. from a `Retry-After`\n * header. Used as a floor so we never retry sooner than the server asked.\n * @returns Delay in milliseconds before next retry\n *\n * @internal Exported for testing purposes\n */\nexport function calculateRetryDelay(\n config: {\n backoffFactor: number;\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n },\n retryNumber: number,\n retryAfterMs?: number\n): number {\n const { backoffFactor, initialDelayMs, maxDelayMs, jitter } = config;\n\n let delay: number;\n if (backoffFactor === 0.0) {\n delay = initialDelayMs;\n } else {\n delay = initialDelayMs * backoffFactor ** retryNumber;\n }\n\n // Cap at maxDelayMs\n delay = Math.min(delay, maxDelayMs);\n\n if (jitter && delay > 0) {\n const jitterAmount = delay * 0.25;\n delay = delay + (Math.random() * 2 - 1) * jitterAmount;\n // Ensure delay is not negative after jitter\n delay = Math.max(0, delay);\n }\n\n return Math.max(delay, retryAfterMs ?? 0);\n}\n\nexport function getRetryAfterMs(error: unknown): number | undefined {\n if (typeof error !== \"object\" || error === null) {\n return undefined;\n }\n const { retryAfterMs } = error as { retryAfterMs?: unknown };\n return typeof retryAfterMs === \"number\" && retryAfterMs >= 0\n ? retryAfterMs\n : undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;;AA0BA,SAAgB,yBACd,UAEA,OACQ;CACR,MAAM,gBAAgB;CACtB,IAAI,aAAa;CAGjB,IAAI,SAAS,MAAM,SAAS,GAAG;EAC7B,IAAI,aAAa;EACjB,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,WAAW,gBAAgB,IAAI,IAAI,oBAAoB,IAAI,IAAI;GACrE,cAAc,KAAK,UAAU,QAAQ,CAAC,CAAC;EACzC;EACA,cAAc;CAChB;CAEA,KAAK,MAAM,OAAO,UAAU;EAC1B,IAAI;EACJ,IAAI,OAAO,IAAI,YAAY,UACzB,cAAc,IAAI;OACb,IAAI,MAAM,QAAQ,IAAI,OAAO,GAClC,cAAc,IAAI,QACf,KAAK,SAAS;GACb,IAAI,OAAO,SAAS,UAAU,OAAO;GACrC,IAAI,KAAK,SAAS,UAAU,UAAU,MAAM,OAAO,KAAK;GACxD,OAAO;EACT,CAAC,CAAC,CACD,KAAK,EAAE;OAEV,cAAc;EAGhB,IACE,UAAU,WAAW,GAAG,KACxB,MAAM,QAAQ,IAAI,UAAU,KAC5B,IAAI,WAAW,SAAS,GAExB,eAAe,KAAK,UAAU,IAAI,UAAU;EAG9C,IAAI,YAAY,WAAW,GAAG,GAC5B,eAAe,IAAI,gBAAgB;EAGrC,cAAc,YAAY;CAC5B;CAEA,OAAO,KAAK,KAAK,aAAa,aAAa;AAC7C;AAEA,SAAgB,kBACd,MAM4B;CAC5B,IAAI,CAAC,QAAQ,OAAO,SAAS,YAC3B;CAEF,OAAO,KAAK;AACd;AAEA,SAAgB,gBACd,KACA;CACA,IAAI,OAAO,QAAQ,YACjB,OAAO;CAET,OAAO,IAAI;AACb;;;;AAKA,SAAgB,MAAM,IAA2B;CAC/C,OAAO,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;;;;;;;;;;;;AAaA,SAAgB,oBACd,QAMA,aACA,cACQ;CACR,MAAM,EAAE,eAAe,gBAAgB,YAAY,WAAW;CAE9D,IAAI;CACJ,IAAI,kBAAkB,GACpB,QAAQ;MAER,QAAQ,iBAAiB,iBAAiB;CAI5C,QAAQ,KAAK,IAAI,OAAO,UAAU;CAElC,IAAI,UAAU,QAAQ,GAAG;EACvB,MAAM,eAAe,QAAQ;EAC7B,QAAQ,SAAS,KAAK,OAAO,IAAI,IAAI,KAAK;EAE1C,QAAQ,KAAK,IAAI,GAAG,KAAK;CAC3B;CAEA,OAAO,KAAK,IAAI,OAAO,gBAAgB,CAAC;AAC1C;AAEA,SAAgB,gBAAgB,OAAoC;CAClE,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC;CAEF,MAAM,EAAE,iBAAiB;CACzB,OAAO,OAAO,iBAAiB,YAAY,gBAAgB,IACvD,eACA,KAAA;AACN"}
|
|
@@ -17,13 +17,13 @@ var universal_exports = /* @__PURE__ */ require_runtime.__exportAll({
|
|
|
17
17
|
function getLangSmithChatModelParams({ apiKey, configuration = {} }) {
|
|
18
18
|
const gatewayConfig = (0, _langchain_core_utils_gateway.resolveLangSmithGatewayConfig)({
|
|
19
19
|
baseURL: configuration.baseURL,
|
|
20
|
-
providerPath: "
|
|
20
|
+
providerPath: "v1"
|
|
21
21
|
});
|
|
22
22
|
return {
|
|
23
23
|
apiKey: apiKey ?? configuration.apiKey ?? gatewayConfig.apiKey ?? ((0, _langchain_core_utils_env.getEnvironmentVariable)("LANGSMITH_GATEWAY_API_KEY") || (0, _langchain_core_utils_env.getEnvironmentVariable)("LANGSMITH_API_KEY")),
|
|
24
24
|
configuration: {
|
|
25
25
|
...configuration,
|
|
26
|
-
baseURL: gatewayConfig.baseURL ?? `${_langchain_core_utils_gateway.DEFAULT_LANGSMITH_GATEWAY}/
|
|
26
|
+
baseURL: gatewayConfig.baseURL ?? `${_langchain_core_utils_gateway.DEFAULT_LANGSMITH_GATEWAY}/v1`
|
|
27
27
|
},
|
|
28
28
|
useResponsesApi: true
|
|
29
29
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"universal.cjs","names":["DEFAULT_LANGSMITH_GATEWAY","BaseChatModel","RunnableBinding","AsyncGeneratorWithSetup","IterableReadableStream","ChatModelStream"],"sources":["../../src/chat_models/universal.ts"],"sourcesContent":["import {\n BaseLanguageModelInput,\n ToolDefinition,\n} from \"@langchain/core/language_models/base\";\nimport {\n BaseChatModel,\n BaseChatModelParams,\n BindToolsInput,\n type BaseChatModelCallOptions,\n} from \"@langchain/core/language_models/chat_models\";\nimport {\n BaseMessage,\n type AIMessageChunk,\n MessageStructure,\n} from \"@langchain/core/messages\";\nimport {\n type RunnableBatchOptions,\n RunnableBinding,\n type RunnableConfig,\n type RunnableToolLike,\n ensureConfig,\n} from \"@langchain/core/runnables\";\nimport {\n AsyncGeneratorWithSetup,\n IterableReadableStream,\n} from \"@langchain/core/utils/stream\";\nimport {\n type LogStreamCallbackHandlerInput,\n type RunLogPatch,\n type StreamEvent,\n} from \"@langchain/core/tracers/log_stream\";\nimport { type StructuredToolInterface } from \"@langchain/core/tools\";\nimport { CallbackManagerForLLMRun } from \"@langchain/core/callbacks/manager\";\nimport { ChatResult } from \"@langchain/core/outputs\";\nimport { ModelProfile } from \"@langchain/core/language_models/profile\";\nimport { ChatModelStream } from \"@langchain/core/language_models/stream\";\nimport {\n DEFAULT_LANGSMITH_GATEWAY,\n resolveLangSmithGatewayConfig,\n} from \"@langchain/core/utils/gateway\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\n\nfunction getLangSmithChatModelParams({\n apiKey,\n configuration = {},\n}: {\n apiKey?: unknown;\n configuration?: { apiKey?: unknown; baseURL?: string };\n}) {\n const gatewayConfig = resolveLangSmithGatewayConfig({\n baseURL: configuration.baseURL,\n providerPath: \"openai/v1\",\n });\n\n return {\n apiKey:\n apiKey ??\n configuration.apiKey ??\n gatewayConfig.apiKey ??\n (getEnvironmentVariable(\"LANGSMITH_GATEWAY_API_KEY\") ||\n getEnvironmentVariable(\"LANGSMITH_API_KEY\")),\n configuration: {\n ...configuration,\n baseURL:\n gatewayConfig.baseURL ?? `${DEFAULT_LANGSMITH_GATEWAY}/openai/v1`,\n },\n useResponsesApi: true,\n };\n}\n\n// TODO: remove once `EventStreamCallbackHandlerInput` is exposed in core\ninterface EventStreamCallbackHandlerInput extends Omit<\n LogStreamCallbackHandlerInput,\n \"_schemaFormat\"\n> {}\n\nexport interface ConfigurableChatModelCallOptions extends BaseChatModelCallOptions {\n tools?: (\n | StructuredToolInterface\n | Record<string, unknown>\n | ToolDefinition\n | RunnableToolLike\n )[];\n}\n\n// Configuration map for model providers\nexport const MODEL_PROVIDER_CONFIG = {\n openai: {\n package: \"@langchain/openai\",\n className: \"ChatOpenAI\",\n },\n anthropic: {\n package: \"@langchain/anthropic\",\n className: \"ChatAnthropic\",\n },\n azure_openai: {\n package: \"@langchain/openai\",\n className: \"AzureChatOpenAI\",\n },\n langsmith: {\n package: \"@langchain/openai\",\n className: \"ChatOpenAI\",\n },\n cohere: {\n package: \"@langchain/cohere\",\n className: \"ChatCohere\",\n },\n google: {\n package: \"@langchain/google\",\n className: \"ChatGoogle\",\n },\n \"google-vertexai\": {\n package: \"@langchain/google-vertexai\",\n className: \"ChatVertexAI\",\n },\n \"google-vertexai-web\": {\n package: \"@langchain/google-vertexai-web\",\n className: \"ChatVertexAI\",\n },\n \"google-genai\": {\n package: \"@langchain/google-genai\",\n className: \"ChatGoogleGenerativeAI\",\n },\n ollama: {\n package: \"@langchain/ollama\",\n className: \"ChatOllama\",\n },\n mistralai: {\n package: \"@langchain/mistralai\",\n className: \"ChatMistralAI\",\n },\n mistral: {\n package: \"@langchain/mistralai\",\n className: \"ChatMistralAI\",\n },\n groq: {\n package: \"@langchain/groq\",\n className: \"ChatGroq\",\n },\n bedrock: {\n package: \"@langchain/aws\",\n className: \"ChatBedrockConverse\",\n },\n aws: {\n package: \"@langchain/aws\",\n className: \"ChatBedrockConverse\",\n },\n deepseek: {\n package: \"@langchain/deepseek\",\n className: \"ChatDeepSeek\",\n },\n xai: {\n package: \"@langchain/xai\",\n className: \"ChatXAI\",\n },\n cerebras: {\n package: \"@langchain/cerebras\",\n className: \"ChatCerebras\",\n },\n fireworks: {\n package: \"@langchain/fireworks\",\n className: \"ChatFireworks\",\n },\n together: {\n package: \"@langchain/together-ai\",\n className: \"ChatTogetherAI\",\n hasCircularDependency: true,\n },\n perplexity: {\n package: \"@langchain/perplexity\",\n className: \"ChatPerplexity\",\n },\n} as const;\n\nconst SUPPORTED_PROVIDERS = Object.keys(\n MODEL_PROVIDER_CONFIG\n) as (keyof typeof MODEL_PROVIDER_CONFIG)[];\nexport type ChatModelProvider = keyof typeof MODEL_PROVIDER_CONFIG;\ntype ModelProviderConfig = {\n package: string;\n className: string;\n hasCircularDependency?: boolean;\n};\n\n/**\n * Helper function to get a chat model class by its class name or model provider.\n * @param className The class name (e.g., \"ChatOpenAI\", \"ChatAnthropic\")\n * @param modelProvider Optional model provider key for direct lookup (e.g., \"google-vertexai-web\").\n * When provided, uses direct lookup to avoid className collision issues.\n * @returns The imported model class or undefined if not found\n */\nexport async function getChatModelByClassName(\n className: string,\n modelProvider?: string\n) {\n let config: ModelProviderConfig | undefined;\n\n if (modelProvider) {\n // Direct lookup by modelProvider key - avoids className collision\n // (e.g., google-vertexai and google-vertexai-web both use \"ChatVertexAI\")\n config = MODEL_PROVIDER_CONFIG[\n modelProvider as keyof typeof MODEL_PROVIDER_CONFIG\n ] as ModelProviderConfig | undefined;\n } else {\n // Fallback to className lookup for backward compatibility\n const providerEntry = Object.entries(MODEL_PROVIDER_CONFIG).find(\n ([, c]) => c.className === className\n );\n config = providerEntry\n ? (providerEntry[1] as ModelProviderConfig)\n : undefined;\n }\n\n if (!config) {\n return undefined;\n }\n\n try {\n const module = await import(config.package);\n return module[config.className];\n } catch (e: unknown) {\n const err = e as Error;\n if (\n \"code\" in err &&\n err.code?.toString().includes(\"ERR_MODULE_NOT_FOUND\") &&\n \"message\" in err &&\n typeof err.message === \"string\"\n ) {\n const msg = err.message.startsWith(\"Error: \")\n ? err.message.slice(\"Error: \".length)\n : err.message;\n const attemptedPackage = msg\n .split(\"Cannot find package '\")[1]\n .split(\"'\")[0];\n throw new Error(\n `Unable to import ${attemptedPackage}. Please install with ` +\n `\\`npm install ${attemptedPackage}\\` or \\`pnpm install ${attemptedPackage}\\``\n );\n }\n throw e;\n }\n}\n\nasync function _initChatModelHelper(\n model: string,\n modelProvider?: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n params: Record<string, any> = {}\n): Promise<BaseChatModel> {\n const modelProviderCopy = modelProvider || _inferModelProvider(model);\n if (!modelProviderCopy) {\n throw new Error(\n `Unable to infer model provider for { model: ${model} }, please specify modelProvider directly.`\n );\n }\n\n const config = MODEL_PROVIDER_CONFIG[\n modelProviderCopy as keyof typeof MODEL_PROVIDER_CONFIG\n ] as ModelProviderConfig;\n if (!config) {\n const supported = SUPPORTED_PROVIDERS.join(\", \");\n throw new Error(\n `Unsupported { modelProvider: ${modelProviderCopy} }.\\n\\nSupported model providers are: ${supported}`\n );\n }\n\n const { modelProvider: _unused, ...passedParams } = params;\n // Pass modelProviderCopy to use direct lookup and avoid className collision\n const ProviderClass = await getChatModelByClassName(\n config.className,\n modelProviderCopy\n );\n return new ProviderClass({\n model,\n ...passedParams,\n ...(modelProviderCopy === \"langsmith\"\n ? getLangSmithChatModelParams(passedParams)\n : {}),\n });\n}\n\n/**\n * Attempts to infer the model provider based on the given model name.\n *\n * @param {string} modelName - The name of the model to infer the provider for.\n * @returns {string | undefined} The inferred model provider name, or undefined if unable to infer.\n *\n * @example\n * _inferModelProvider(\"gpt-4\"); // returns \"openai\"\n * _inferModelProvider(\"claude-2\"); // returns \"anthropic\"\n * _inferModelProvider(\"unknown-model\"); // returns undefined\n */\nexport function _inferModelProvider(modelName: string): string | undefined {\n if (\n modelName.startsWith(\"gpt-3\") ||\n modelName.startsWith(\"gpt-4\") ||\n modelName.startsWith(\"gpt-5\") ||\n modelName.startsWith(\"o1\") ||\n modelName.startsWith(\"o3\") ||\n modelName.startsWith(\"o4\")\n ) {\n return \"openai\";\n } else if (modelName.startsWith(\"claude\")) {\n return \"anthropic\";\n } else if (modelName.startsWith(\"command\")) {\n return \"cohere\";\n } else if (modelName.startsWith(\"accounts/fireworks\")) {\n return \"fireworks\";\n } else if (modelName.startsWith(\"gemini\")) {\n return \"google-vertexai\";\n } else if (modelName.startsWith(\"amazon.\")) {\n return \"bedrock\";\n } else if (modelName.startsWith(\"mistral\")) {\n return \"mistralai\";\n } else if (modelName.startsWith(\"sonar\") || modelName.startsWith(\"pplx\")) {\n return \"perplexity\";\n } else {\n return undefined;\n }\n}\n\ninterface ConfigurableModelFields extends BaseChatModelParams {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n defaultConfig?: Record<string, any>;\n /**\n * @default \"any\"\n */\n configurableFields?: string[] | \"any\";\n /**\n * @default \"\"\n */\n configPrefix?: string;\n /**\n * Methods which should be called after the model is initialized.\n * The key will be the method name, and the value will be the arguments.\n */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n queuedMethodOperations?: Record<string, any>;\n /**\n * Overrides the profiling information for the model. If not provided,\n * the profile will be inferred from the inner model instance.\n */\n profile?: ModelProfile;\n}\n\n/**\n * Internal class used to create chat models.\n *\n * @internal\n */\nexport class ConfigurableModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n> extends BaseChatModel<CallOptions, AIMessageChunk> {\n _llmType(): string {\n return \"chat_model\";\n }\n\n lc_namespace = [\"langchain\", \"chat_models\"];\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n _defaultConfig?: Record<string, any> = {};\n\n /**\n * @default \"any\"\n */\n _configurableFields: string[] | \"any\" = \"any\";\n\n /**\n * @default \"\"\n */\n _configPrefix: string;\n\n /**\n * Methods which should be called after the model is initialized.\n * The key will be the method name, and the value will be the arguments.\n */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n _queuedMethodOperations: Record<string, any> = {};\n\n /** @internal */\n private _modelInstanceCache = new Map<\n string,\n BaseChatModel<BaseChatModelCallOptions, AIMessageChunk<MessageStructure>>\n >();\n\n /** @internal */\n private _profile?: ModelProfile;\n\n constructor(fields: ConfigurableModelFields) {\n super(fields);\n this._defaultConfig = fields.defaultConfig ?? {};\n\n if (fields.configurableFields === \"any\") {\n this._configurableFields = \"any\";\n } else {\n this._configurableFields = fields.configurableFields ?? [\n \"model\",\n \"modelProvider\",\n ];\n }\n\n if (fields.configPrefix) {\n this._configPrefix = fields.configPrefix.endsWith(\"_\")\n ? fields.configPrefix\n : `${fields.configPrefix}_`;\n } else {\n this._configPrefix = \"\";\n }\n\n this._queuedMethodOperations =\n fields.queuedMethodOperations ?? this._queuedMethodOperations;\n\n this._profile = fields.profile ?? undefined;\n\n this.metadata = {\n ...this.metadata,\n ls_integration: \"langchain_init_chat_model\",\n };\n }\n\n async _getModelInstance(\n config?: RunnableConfig\n ): Promise<\n BaseChatModel<BaseChatModelCallOptions, AIMessageChunk<MessageStructure>>\n > {\n // Check cache first\n const cacheKey = this._getCacheKey(config);\n const cachedModel = this._modelInstanceCache.get(cacheKey);\n if (cachedModel) {\n return cachedModel;\n }\n\n // Initialize model with merged params\n const params = { ...this._defaultConfig, ...this._modelParams(config) };\n let initializedModel = await _initChatModelHelper(\n params.model,\n params.modelProvider,\n params\n );\n\n // Apply queued method operations in sequence\n for (const [method, args] of Object.entries(this._queuedMethodOperations)) {\n if (\n method in initializedModel &&\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n typeof (initializedModel as any)[method] === \"function\"\n ) {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n initializedModel = await (initializedModel as any)[method](...args);\n }\n }\n\n // Cache and return the initialized model\n this._modelInstanceCache.set(cacheKey, initializedModel);\n return initializedModel;\n }\n\n async _generate(\n messages: BaseMessage[],\n options?: this[\"ParsedCallOptions\"],\n runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n const model = await this._getModelInstance(options);\n return model._generate(messages, options ?? {}, runManager);\n }\n\n override bindTools(\n tools: BindToolsInput[],\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n params?: Record<string, any>\n ): ConfigurableModel<RunInput, CallOptions> {\n const newQueuedOperations = { ...this._queuedMethodOperations };\n newQueuedOperations.bindTools = [tools, params];\n return new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: this._defaultConfig,\n configurableFields: this._configurableFields,\n configPrefix: this._configPrefix,\n queuedMethodOperations: newQueuedOperations,\n });\n }\n\n // Extract the input types from the `BaseModel` class.\n withStructuredOutput: BaseChatModel[\"withStructuredOutput\"] = (\n schema,\n ...args\n ): ReturnType<BaseChatModel[\"withStructuredOutput\"]> => {\n const newQueuedOperations = { ...this._queuedMethodOperations };\n newQueuedOperations.withStructuredOutput = [schema, ...args];\n return new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: this._defaultConfig,\n configurableFields: this._configurableFields,\n configPrefix: this._configPrefix,\n queuedMethodOperations: newQueuedOperations,\n }) as unknown as ReturnType<BaseChatModel[\"withStructuredOutput\"]>;\n };\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n _modelParams(config?: RunnableConfig): Record<string, any> {\n const configurable = config?.configurable ?? {};\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n let modelParams: Record<string, any> = {};\n\n for (const [key, value] of Object.entries(configurable)) {\n if (key.startsWith(this._configPrefix)) {\n const strippedKey = this._removePrefix(key, this._configPrefix);\n modelParams[strippedKey] = value;\n }\n }\n\n if (this._configurableFields !== \"any\") {\n modelParams = Object.fromEntries(\n Object.entries(modelParams).filter(([key]) =>\n this._configurableFields.includes(key)\n )\n );\n }\n\n return modelParams;\n }\n\n _removePrefix(str: string, prefix: string): string {\n return str.startsWith(prefix) ? str.slice(prefix.length) : str;\n }\n\n /**\n * Bind config to a Runnable, returning a new Runnable.\n * @param {RunnableConfig | undefined} [config] - The config to bind.\n * @returns {RunnableBinding<RunInput, RunOutput, CallOptions>} A new RunnableBinding with the bound config.\n */\n withConfig(\n config?: RunnableConfig\n ): RunnableBinding<RunInput, AIMessageChunk, CallOptions> {\n const mergedConfig: RunnableConfig = { ...(config || {}) };\n const modelParams = this._modelParams(mergedConfig);\n\n const remainingConfig: RunnableConfig = Object.fromEntries(\n Object.entries(mergedConfig).filter(([k]) => k !== \"configurable\")\n );\n\n remainingConfig.configurable = Object.fromEntries(\n Object.entries(mergedConfig.configurable || {}).filter(\n ([k]) =>\n this._configPrefix &&\n !Object.keys(modelParams).includes(\n this._removePrefix(k, this._configPrefix)\n )\n )\n );\n\n const newConfigurableModel = new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: { ...this._defaultConfig, ...modelParams },\n configurableFields: Array.isArray(this._configurableFields)\n ? [...this._configurableFields]\n : this._configurableFields,\n configPrefix: this._configPrefix,\n queuedMethodOperations: this._queuedMethodOperations,\n });\n\n return new RunnableBinding<RunInput, AIMessageChunk, CallOptions>({\n config: mergedConfig,\n bound: newConfigurableModel,\n });\n }\n\n async invoke(\n input: RunInput,\n options?: CallOptions\n ): Promise<AIMessageChunk> {\n const model = await this._getModelInstance(options);\n const config = ensureConfig(options);\n return model.invoke(input, config);\n }\n\n async stream(\n input: RunInput,\n options?: CallOptions\n ): Promise<IterableReadableStream<AIMessageChunk>> {\n const model = await this._getModelInstance(options);\n const wrappedGenerator = new AsyncGeneratorWithSetup({\n generator: await model.stream(input, options),\n config: options,\n });\n await wrappedGenerator.setup;\n return IterableReadableStream.fromAsyncGenerator(wrappedGenerator);\n }\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions & { returnExceptions?: false }\n ): Promise<AIMessageChunk[]>;\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions & { returnExceptions: true }\n ): Promise<(AIMessageChunk | Error)[]>;\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions\n ): Promise<(AIMessageChunk | Error)[]>;\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions\n ): Promise<(AIMessageChunk | Error)[]> {\n // We can super this since the base runnable implementation of\n // `.batch` will call `.invoke` on each input.\n return super.batch(inputs, options, batchOptions);\n }\n\n async *transform(\n generator: AsyncGenerator<RunInput>,\n options: CallOptions\n ): AsyncGenerator<AIMessageChunk> {\n const model = await this._getModelInstance(options);\n const config = ensureConfig(options);\n\n yield* model.transform(generator, config);\n }\n\n async *streamLog(\n input: RunInput,\n options?: Partial<CallOptions>,\n streamOptions?: Omit<LogStreamCallbackHandlerInput, \"autoClose\">\n ): AsyncGenerator<RunLogPatch> {\n const model = await this._getModelInstance(options);\n const config = ensureConfig(options);\n\n yield* model.streamLog(input, config, {\n ...streamOptions,\n _schemaFormat: \"original\",\n includeNames: streamOptions?.includeNames,\n includeTypes: streamOptions?.includeTypes,\n includeTags: streamOptions?.includeTags,\n excludeNames: streamOptions?.excludeNames,\n excludeTypes: streamOptions?.excludeTypes,\n excludeTags: streamOptions?.excludeTags,\n });\n }\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & { version: \"v2\" },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<StreamEvent>;\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & {\n version: \"v2\";\n encoding: \"text/event-stream\";\n },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<Uint8Array>;\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & { version: \"v1\" },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<StreamEvent>;\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & {\n version: \"v1\";\n encoding: \"text/event-stream\";\n },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<Uint8Array>;\n\n streamEvents(\n input: RunInput,\n options?: Partial<CallOptions>\n ): ChatModelStream;\n\n streamEvents(\n input: RunInput,\n options?: Partial<CallOptions> & {\n version?: \"v1\" | \"v2\";\n encoding?: \"text/event-stream\" | undefined;\n },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): ChatModelStream | IterableReadableStream<StreamEvent | Uint8Array> {\n if (options?.version === \"v1\" || options?.version === \"v2\") {\n const outerThis = this;\n const tracingCallOptions = options;\n async function* wrappedGenerator() {\n const model = await outerThis._getModelInstance(tracingCallOptions);\n const config = ensureConfig(tracingCallOptions);\n const tracingOptions = {\n ...config,\n version: tracingCallOptions.version,\n ...(tracingCallOptions.encoding !== undefined\n ? { encoding: tracingCallOptions.encoding }\n : {}),\n };\n let eventStream: IterableReadableStream<StreamEvent | Uint8Array>;\n if (\n tracingCallOptions.version === \"v1\" &&\n tracingCallOptions.encoding === \"text/event-stream\"\n ) {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & {\n version: \"v1\";\n encoding: \"text/event-stream\";\n },\n streamOptions\n );\n } else if (tracingCallOptions.version === \"v1\") {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & { version: \"v1\" },\n streamOptions\n );\n } else if (\n tracingCallOptions.version === \"v2\" &&\n tracingCallOptions.encoding === \"text/event-stream\"\n ) {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & {\n version: \"v2\";\n encoding: \"text/event-stream\";\n },\n streamOptions\n );\n } else {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & { version: \"v2\" },\n streamOptions\n );\n }\n\n for await (const chunk of eventStream) {\n yield chunk;\n }\n }\n return IterableReadableStream.fromAsyncGenerator(wrappedGenerator());\n }\n\n const outerThis = this;\n async function* deferredEvents() {\n const model = await outerThis._getModelInstance(options);\n const config = ensureConfig(options);\n yield* model.streamEvents(input, config);\n }\n return new ChatModelStream(deferredEvents());\n }\n\n /**\n * Return profiling information for the model.\n *\n * @returns {ModelProfile} An object describing the model's capabilities and constraints\n */\n get profile(): ModelProfile {\n if (this._profile) {\n return this._profile;\n }\n const cacheKey = this._getCacheKey({});\n const instance = this._modelInstanceCache.get(cacheKey);\n return instance?.profile ?? {};\n }\n\n /** @internal */\n _getCacheKey(config?: RunnableConfig): string {\n let toStringify = config ?? {};\n if (toStringify.configurable) {\n const { configurable } = toStringify;\n const filtered: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(configurable)) {\n if (!k.startsWith(\"__pregel_\")) {\n filtered[k] = v;\n }\n }\n toStringify = { ...toStringify, configurable: filtered };\n }\n return JSON.stringify(toStringify);\n }\n}\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface InitChatModelFields extends Partial<Record<string, any>> {\n modelProvider?: string;\n configurableFields?: string[] | \"any\";\n configPrefix?: string;\n}\n\nexport type ConfigurableFields = \"any\" | string[];\n\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n fields?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: never;\n configPrefix?: string;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>>;\n\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model: never,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n options?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: never;\n configPrefix?: string;\n profile?: ModelProfile;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>>;\n\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model?: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n options?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: ConfigurableFields;\n configPrefix?: string;\n profile?: ModelProfile;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>>;\n\n// ################################# FOR CONTRIBUTORS #################################\n//\n// If adding support for a new provider, please append the provider\n// name to the supported list in the docstring below.\n//\n// ####################################################################################\n\n/**\n * Initialize a ChatModel from the model name and provider.\n * Must have the integration package corresponding to the model provider installed.\n *\n * @template {extends BaseLanguageModelInput = BaseLanguageModelInput} RunInput - The input type for the model.\n * @template {extends ConfigurableChatModelCallOptions = ConfigurableChatModelCallOptions} CallOptions - Call options for the model.\n *\n * @param {string | ChatModelProvider} [model] - The name of the model, e.g. \"gpt-4\", \"claude-3-opus-20240229\".\n * Can be prefixed with the model provider, e.g. \"openai:gpt-4\", \"anthropic:claude-3-opus-20240229\".\n * @param {Object} [fields] - Additional configuration options.\n * @param {string} [fields.modelProvider] - The model provider. Supported values include:\n * - openai (@langchain/openai)\n * - langsmith (@langchain/openai, via the [LangSmith LLM Gateway](https://docs.langchain.com/langsmith/llm-gateway))\n * - anthropic (@langchain/anthropic)\n * - azure_openai (@langchain/openai)\n * - google-vertexai (@langchain/google-vertexai)\n * - google-vertexai-web (@langchain/google-vertexai-web)\n * - google-genai (@langchain/google-genai)\n * - bedrock (@langchain/aws)\n * - cohere (@langchain/cohere)\n * - fireworks (@langchain/fireworks)\n * - together (@langchain/together-ai)\n * - mistralai (@langchain/mistralai)\n * - groq (@langchain/groq)\n * - ollama (@langchain/ollama)\n * - perplexity (@langchain/perplexity)\n * - cerebras (@langchain/cerebras)\n * - deepseek (@langchain/deepseek)\n * - xai (@langchain/xai)\n * @param {string[] | \"any\"} [fields.configurableFields] - Which model parameters are configurable:\n * - undefined: No configurable fields.\n * - \"any\": All fields are configurable. (See Security Note in description)\n * - string[]: Specified fields are configurable.\n * @param {string} [fields.configPrefix] - Prefix for configurable fields at runtime.\n * @param {ModelProfile} [fields.profile] - Overrides the profiling information for the model. If not provided,\n * the profile will be inferred from the inner model instance.\n * @param {Record<string, any>} [fields.params] - Additional keyword args to pass to the ChatModel constructor.\n * @returns {Promise<ConfigurableModel<RunInput, CallOptions>>} A class which extends BaseChatModel.\n * @throws {Error} If modelProvider cannot be inferred or isn't supported.\n * @throws {Error} If the model provider integration package is not installed.\n *\n * @example Initialize non-configurable models\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const gpt4 = await initChatModel(\"openai:gpt-4\", {\n * temperature: 0.25,\n * });\n * const gpt4Result = await gpt4.invoke(\"what's your name\");\n *\n * const claude = await initChatModel(\"anthropic:claude-3-opus-20240229\", {\n * temperature: 0.25,\n * });\n * const claudeResult = await claude.invoke(\"what's your name\");\n *\n * const gemini = await initChatModel(\"gemini-1.5-pro\", {\n * modelProvider: \"google-vertexai\",\n * temperature: 0.25,\n * });\n * const geminiResult = await gemini.invoke(\"what's your name\");\n * ```\n *\n * @example Create a partially configurable model with no default model\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const configurableModel = await initChatModel(undefined, {\n * temperature: 0,\n * configurableFields: [\"model\", \"apiKey\"],\n * });\n *\n * const gpt4Result = await configurableModel.invoke(\"what's your name\", {\n * configurable: {\n * model: \"gpt-4\",\n * },\n * });\n *\n * const claudeResult = await configurableModel.invoke(\"what's your name\", {\n * configurable: {\n * model: \"claude-sonnet-4-5-20250929\",\n * },\n * });\n * ```\n *\n * @example Create a fully configurable model with a default model and a config prefix\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const configurableModelWithDefault = await initChatModel(\"gpt-4\", {\n * modelProvider: \"openai\",\n * configurableFields: \"any\",\n * configPrefix: \"foo\",\n * temperature: 0,\n * });\n *\n * const openaiResult = await configurableModelWithDefault.invoke(\n * \"what's your name\",\n * {\n * configurable: {\n * foo_apiKey: process.env.OPENAI_API_KEY,\n * },\n * }\n * );\n *\n * const claudeResult = await configurableModelWithDefault.invoke(\n * \"what's your name\",\n * {\n * configurable: {\n * foo_model: \"claude-sonnet-4-5-20250929\",\n * foo_modelProvider: \"anthropic\",\n * foo_temperature: 0.6,\n * foo_apiKey: process.env.ANTHROPIC_API_KEY,\n * },\n * }\n * );\n * ```\n *\n * @example Bind tools to a configurable model:\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n * import { z } from \"zod/v3\";\n * import { tool } from \"@langchain/core/tools\";\n *\n * const getWeatherTool = tool(\n * (input) => {\n * // Do something with the input\n * return JSON.stringify(input);\n * },\n * {\n * schema: z\n * .object({\n * location: z\n * .string()\n * .describe(\"The city and state, e.g. San Francisco, CA\"),\n * })\n * .describe(\"Get the current weather in a given location\"),\n * name: \"GetWeather\",\n * description: \"Get the current weather in a given location\",\n * }\n * );\n *\n * const getPopulationTool = tool(\n * (input) => {\n * // Do something with the input\n * return JSON.stringify(input);\n * },\n * {\n * schema: z\n * .object({\n * location: z\n * .string()\n * .describe(\"The city and state, e.g. San Francisco, CA\"),\n * })\n * .describe(\"Get the current population in a given location\"),\n * name: \"GetPopulation\",\n * description: \"Get the current population in a given location\",\n * }\n * );\n *\n * const configurableModel = await initChatModel(\"gpt-4\", {\n * configurableFields: [\"model\", \"modelProvider\", \"apiKey\"],\n * temperature: 0,\n * });\n *\n * const configurableModelWithTools = configurableModel.bindTools([\n * getWeatherTool,\n * getPopulationTool,\n * ]);\n *\n * const configurableToolResult = await configurableModelWithTools.invoke(\n * \"Which city is hotter today and which is bigger: LA or NY?\",\n * {\n * configurable: {\n * apiKey: process.env.OPENAI_API_KEY,\n * },\n * }\n * );\n *\n * const configurableToolResult2 = await configurableModelWithTools.invoke(\n * \"Which city is hotter today and which is bigger: LA or NY?\",\n * {\n * configurable: {\n * model: \"claude-sonnet-4-5-20250929\",\n * apiKey: process.env.ANTHROPIC_API_KEY,\n * },\n * }\n * );\n * ```\n *\n * @example Initialize a model with a custom profile\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const model = await initChatModel(\"gpt-4o-mini\", {\n * profile: {\n * maxInputTokens: 100000,\n * },\n * });\n *\n * @description\n * This function initializes a ChatModel based on the provided model name and provider.\n * It supports various model providers and allows for runtime configuration of model parameters.\n *\n * Security Note: Setting `configurableFields` to \"any\" means fields like apiKey, baseUrl, etc.\n * can be altered at runtime, potentially redirecting model requests to a different service/user.\n * Make sure that if you're accepting untrusted configurations, you enumerate the\n * `configurableFields` explicitly.\n *\n * The function will attempt to infer the model provider from the model name if not specified.\n * Certain model name prefixes are associated with specific providers:\n * - gpt-3... or gpt-4... -> openai\n * - claude... -> anthropic\n * - amazon.... -> bedrock\n * - gemini... -> google-vertexai\n * - command... -> cohere\n * - accounts/fireworks... -> fireworks\n *\n * @since 0.2.11\n * @version 0.2.11\n */\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model?: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n fields?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: string[] | \"any\";\n configPrefix?: string;\n profile?: ModelProfile;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>> {\n // oxlint-disable-next-line prefer-const\n let { configurableFields, configPrefix, modelProvider, profile, ...params } =\n {\n configPrefix: \"\",\n ...(fields ?? {}),\n };\n if (modelProvider === undefined && model?.includes(\":\")) {\n const [provider, ...remainingParts] = model.split(\":\");\n const modelComponents =\n remainingParts.length === 0\n ? [provider]\n : [provider, remainingParts.join(\":\")];\n if (SUPPORTED_PROVIDERS.includes(modelComponents[0] as ChatModelProvider)) {\n // oxlint-disable-next-line no-param-reassign\n [modelProvider, model] = modelComponents;\n }\n }\n let configurableFieldsCopy = Array.isArray(configurableFields)\n ? [...configurableFields]\n : configurableFields;\n\n if (!model && configurableFieldsCopy === undefined) {\n configurableFieldsCopy = [\"model\", \"modelProvider\"];\n }\n if (configPrefix && configurableFieldsCopy === undefined) {\n console.warn(\n `{ configPrefix: ${configPrefix} } has been set but no fields are configurable. Set ` +\n `{ configurableFields: [...] } to specify the model params that are ` +\n `configurable.`\n );\n }\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const paramsCopy: Record<string, any> = { ...params };\n\n let configurableModel: ConfigurableModel<RunInput, CallOptions>;\n\n if (configurableFieldsCopy === undefined) {\n configurableModel = new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: {\n ...paramsCopy,\n model,\n modelProvider,\n },\n configPrefix,\n profile,\n });\n } else {\n if (model) {\n paramsCopy.model = model;\n }\n if (modelProvider) {\n paramsCopy.modelProvider = modelProvider;\n }\n configurableModel = new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: paramsCopy,\n configPrefix,\n configurableFields: configurableFieldsCopy,\n profile,\n });\n }\n\n // Initialize the model instance to make sure a profile is available\n await configurableModel._getModelInstance();\n return configurableModel;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"universal.cjs","names":["DEFAULT_LANGSMITH_GATEWAY","BaseChatModel","RunnableBinding","AsyncGeneratorWithSetup","IterableReadableStream","ChatModelStream"],"sources":["../../src/chat_models/universal.ts"],"sourcesContent":["import {\n BaseLanguageModelInput,\n ToolDefinition,\n} from \"@langchain/core/language_models/base\";\nimport {\n BaseChatModel,\n BaseChatModelParams,\n BindToolsInput,\n type BaseChatModelCallOptions,\n} from \"@langchain/core/language_models/chat_models\";\nimport {\n BaseMessage,\n type AIMessageChunk,\n MessageStructure,\n} from \"@langchain/core/messages\";\nimport {\n type RunnableBatchOptions,\n RunnableBinding,\n type RunnableConfig,\n type RunnableToolLike,\n ensureConfig,\n} from \"@langchain/core/runnables\";\nimport {\n AsyncGeneratorWithSetup,\n IterableReadableStream,\n} from \"@langchain/core/utils/stream\";\nimport {\n type LogStreamCallbackHandlerInput,\n type RunLogPatch,\n type StreamEvent,\n} from \"@langchain/core/tracers/log_stream\";\nimport { type StructuredToolInterface } from \"@langchain/core/tools\";\nimport { CallbackManagerForLLMRun } from \"@langchain/core/callbacks/manager\";\nimport { ChatResult } from \"@langchain/core/outputs\";\nimport { ModelProfile } from \"@langchain/core/language_models/profile\";\nimport { ChatModelStream } from \"@langchain/core/language_models/stream\";\nimport {\n DEFAULT_LANGSMITH_GATEWAY,\n resolveLangSmithGatewayConfig,\n} from \"@langchain/core/utils/gateway\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\n\nfunction getLangSmithChatModelParams({\n apiKey,\n configuration = {},\n}: {\n apiKey?: unknown;\n configuration?: { apiKey?: unknown; baseURL?: string };\n}) {\n const gatewayConfig = resolveLangSmithGatewayConfig({\n baseURL: configuration.baseURL,\n providerPath: \"v1\",\n });\n\n return {\n apiKey:\n apiKey ??\n configuration.apiKey ??\n gatewayConfig.apiKey ??\n (getEnvironmentVariable(\"LANGSMITH_GATEWAY_API_KEY\") ||\n getEnvironmentVariable(\"LANGSMITH_API_KEY\")),\n configuration: {\n ...configuration,\n baseURL: gatewayConfig.baseURL ?? `${DEFAULT_LANGSMITH_GATEWAY}/v1`,\n },\n useResponsesApi: true,\n };\n}\n\n// TODO: remove once `EventStreamCallbackHandlerInput` is exposed in core\ninterface EventStreamCallbackHandlerInput extends Omit<\n LogStreamCallbackHandlerInput,\n \"_schemaFormat\"\n> {}\n\nexport interface ConfigurableChatModelCallOptions extends BaseChatModelCallOptions {\n tools?: (\n | StructuredToolInterface\n | Record<string, unknown>\n | ToolDefinition\n | RunnableToolLike\n )[];\n}\n\n// Configuration map for model providers\nexport const MODEL_PROVIDER_CONFIG = {\n openai: {\n package: \"@langchain/openai\",\n className: \"ChatOpenAI\",\n },\n anthropic: {\n package: \"@langchain/anthropic\",\n className: \"ChatAnthropic\",\n },\n azure_openai: {\n package: \"@langchain/openai\",\n className: \"AzureChatOpenAI\",\n },\n langsmith: {\n package: \"@langchain/openai\",\n className: \"ChatOpenAI\",\n },\n cohere: {\n package: \"@langchain/cohere\",\n className: \"ChatCohere\",\n },\n google: {\n package: \"@langchain/google\",\n className: \"ChatGoogle\",\n },\n \"google-vertexai\": {\n package: \"@langchain/google-vertexai\",\n className: \"ChatVertexAI\",\n },\n \"google-vertexai-web\": {\n package: \"@langchain/google-vertexai-web\",\n className: \"ChatVertexAI\",\n },\n \"google-genai\": {\n package: \"@langchain/google-genai\",\n className: \"ChatGoogleGenerativeAI\",\n },\n ollama: {\n package: \"@langchain/ollama\",\n className: \"ChatOllama\",\n },\n mistralai: {\n package: \"@langchain/mistralai\",\n className: \"ChatMistralAI\",\n },\n mistral: {\n package: \"@langchain/mistralai\",\n className: \"ChatMistralAI\",\n },\n groq: {\n package: \"@langchain/groq\",\n className: \"ChatGroq\",\n },\n bedrock: {\n package: \"@langchain/aws\",\n className: \"ChatBedrockConverse\",\n },\n aws: {\n package: \"@langchain/aws\",\n className: \"ChatBedrockConverse\",\n },\n deepseek: {\n package: \"@langchain/deepseek\",\n className: \"ChatDeepSeek\",\n },\n xai: {\n package: \"@langchain/xai\",\n className: \"ChatXAI\",\n },\n cerebras: {\n package: \"@langchain/cerebras\",\n className: \"ChatCerebras\",\n },\n fireworks: {\n package: \"@langchain/fireworks\",\n className: \"ChatFireworks\",\n },\n together: {\n package: \"@langchain/together-ai\",\n className: \"ChatTogetherAI\",\n hasCircularDependency: true,\n },\n perplexity: {\n package: \"@langchain/perplexity\",\n className: \"ChatPerplexity\",\n },\n} as const;\n\nconst SUPPORTED_PROVIDERS = Object.keys(\n MODEL_PROVIDER_CONFIG\n) as (keyof typeof MODEL_PROVIDER_CONFIG)[];\nexport type ChatModelProvider = keyof typeof MODEL_PROVIDER_CONFIG;\ntype ModelProviderConfig = {\n package: string;\n className: string;\n hasCircularDependency?: boolean;\n};\n\n/**\n * Helper function to get a chat model class by its class name or model provider.\n * @param className The class name (e.g., \"ChatOpenAI\", \"ChatAnthropic\")\n * @param modelProvider Optional model provider key for direct lookup (e.g., \"google-vertexai-web\").\n * When provided, uses direct lookup to avoid className collision issues.\n * @returns The imported model class or undefined if not found\n */\nexport async function getChatModelByClassName(\n className: string,\n modelProvider?: string\n) {\n let config: ModelProviderConfig | undefined;\n\n if (modelProvider) {\n // Direct lookup by modelProvider key - avoids className collision\n // (e.g., google-vertexai and google-vertexai-web both use \"ChatVertexAI\")\n config = MODEL_PROVIDER_CONFIG[\n modelProvider as keyof typeof MODEL_PROVIDER_CONFIG\n ] as ModelProviderConfig | undefined;\n } else {\n // Fallback to className lookup for backward compatibility\n const providerEntry = Object.entries(MODEL_PROVIDER_CONFIG).find(\n ([, c]) => c.className === className\n );\n config = providerEntry\n ? (providerEntry[1] as ModelProviderConfig)\n : undefined;\n }\n\n if (!config) {\n return undefined;\n }\n\n try {\n const module = await import(config.package);\n return module[config.className];\n } catch (e: unknown) {\n const err = e as Error;\n if (\n \"code\" in err &&\n err.code?.toString().includes(\"ERR_MODULE_NOT_FOUND\") &&\n \"message\" in err &&\n typeof err.message === \"string\"\n ) {\n const msg = err.message.startsWith(\"Error: \")\n ? err.message.slice(\"Error: \".length)\n : err.message;\n const attemptedPackage = msg\n .split(\"Cannot find package '\")[1]\n .split(\"'\")[0];\n throw new Error(\n `Unable to import ${attemptedPackage}. Please install with ` +\n `\\`npm install ${attemptedPackage}\\` or \\`pnpm install ${attemptedPackage}\\``\n );\n }\n throw e;\n }\n}\n\nasync function _initChatModelHelper(\n model: string,\n modelProvider?: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n params: Record<string, any> = {}\n): Promise<BaseChatModel> {\n const modelProviderCopy = modelProvider || _inferModelProvider(model);\n if (!modelProviderCopy) {\n throw new Error(\n `Unable to infer model provider for { model: ${model} }, please specify modelProvider directly.`\n );\n }\n\n const config = MODEL_PROVIDER_CONFIG[\n modelProviderCopy as keyof typeof MODEL_PROVIDER_CONFIG\n ] as ModelProviderConfig;\n if (!config) {\n const supported = SUPPORTED_PROVIDERS.join(\", \");\n throw new Error(\n `Unsupported { modelProvider: ${modelProviderCopy} }.\\n\\nSupported model providers are: ${supported}`\n );\n }\n\n const { modelProvider: _unused, ...passedParams } = params;\n // Pass modelProviderCopy to use direct lookup and avoid className collision\n const ProviderClass = await getChatModelByClassName(\n config.className,\n modelProviderCopy\n );\n return new ProviderClass({\n model,\n ...passedParams,\n ...(modelProviderCopy === \"langsmith\"\n ? getLangSmithChatModelParams(passedParams)\n : {}),\n });\n}\n\n/**\n * Attempts to infer the model provider based on the given model name.\n *\n * @param {string} modelName - The name of the model to infer the provider for.\n * @returns {string | undefined} The inferred model provider name, or undefined if unable to infer.\n *\n * @example\n * _inferModelProvider(\"gpt-4\"); // returns \"openai\"\n * _inferModelProvider(\"claude-2\"); // returns \"anthropic\"\n * _inferModelProvider(\"unknown-model\"); // returns undefined\n */\nexport function _inferModelProvider(modelName: string): string | undefined {\n if (\n modelName.startsWith(\"gpt-3\") ||\n modelName.startsWith(\"gpt-4\") ||\n modelName.startsWith(\"gpt-5\") ||\n modelName.startsWith(\"o1\") ||\n modelName.startsWith(\"o3\") ||\n modelName.startsWith(\"o4\")\n ) {\n return \"openai\";\n } else if (modelName.startsWith(\"claude\")) {\n return \"anthropic\";\n } else if (modelName.startsWith(\"command\")) {\n return \"cohere\";\n } else if (modelName.startsWith(\"accounts/fireworks\")) {\n return \"fireworks\";\n } else if (modelName.startsWith(\"gemini\")) {\n return \"google-vertexai\";\n } else if (modelName.startsWith(\"amazon.\")) {\n return \"bedrock\";\n } else if (modelName.startsWith(\"mistral\")) {\n return \"mistralai\";\n } else if (modelName.startsWith(\"sonar\") || modelName.startsWith(\"pplx\")) {\n return \"perplexity\";\n } else {\n return undefined;\n }\n}\n\ninterface ConfigurableModelFields extends BaseChatModelParams {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n defaultConfig?: Record<string, any>;\n /**\n * @default \"any\"\n */\n configurableFields?: string[] | \"any\";\n /**\n * @default \"\"\n */\n configPrefix?: string;\n /**\n * Methods which should be called after the model is initialized.\n * The key will be the method name, and the value will be the arguments.\n */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n queuedMethodOperations?: Record<string, any>;\n /**\n * Overrides the profiling information for the model. If not provided,\n * the profile will be inferred from the inner model instance.\n */\n profile?: ModelProfile;\n}\n\n/**\n * Internal class used to create chat models.\n *\n * @internal\n */\nexport class ConfigurableModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n> extends BaseChatModel<CallOptions, AIMessageChunk> {\n _llmType(): string {\n return \"chat_model\";\n }\n\n lc_namespace = [\"langchain\", \"chat_models\"];\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n _defaultConfig?: Record<string, any> = {};\n\n /**\n * @default \"any\"\n */\n _configurableFields: string[] | \"any\" = \"any\";\n\n /**\n * @default \"\"\n */\n _configPrefix: string;\n\n /**\n * Methods which should be called after the model is initialized.\n * The key will be the method name, and the value will be the arguments.\n */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n _queuedMethodOperations: Record<string, any> = {};\n\n /** @internal */\n private _modelInstanceCache = new Map<\n string,\n BaseChatModel<BaseChatModelCallOptions, AIMessageChunk<MessageStructure>>\n >();\n\n /** @internal */\n private _profile?: ModelProfile;\n\n constructor(fields: ConfigurableModelFields) {\n super(fields);\n this._defaultConfig = fields.defaultConfig ?? {};\n\n if (fields.configurableFields === \"any\") {\n this._configurableFields = \"any\";\n } else {\n this._configurableFields = fields.configurableFields ?? [\n \"model\",\n \"modelProvider\",\n ];\n }\n\n if (fields.configPrefix) {\n this._configPrefix = fields.configPrefix.endsWith(\"_\")\n ? fields.configPrefix\n : `${fields.configPrefix}_`;\n } else {\n this._configPrefix = \"\";\n }\n\n this._queuedMethodOperations =\n fields.queuedMethodOperations ?? this._queuedMethodOperations;\n\n this._profile = fields.profile ?? undefined;\n\n this.metadata = {\n ...this.metadata,\n ls_integration: \"langchain_init_chat_model\",\n };\n }\n\n async _getModelInstance(\n config?: RunnableConfig\n ): Promise<\n BaseChatModel<BaseChatModelCallOptions, AIMessageChunk<MessageStructure>>\n > {\n // Check cache first\n const cacheKey = this._getCacheKey(config);\n const cachedModel = this._modelInstanceCache.get(cacheKey);\n if (cachedModel) {\n return cachedModel;\n }\n\n // Initialize model with merged params\n const params = { ...this._defaultConfig, ...this._modelParams(config) };\n let initializedModel = await _initChatModelHelper(\n params.model,\n params.modelProvider,\n params\n );\n\n // Apply queued method operations in sequence\n for (const [method, args] of Object.entries(this._queuedMethodOperations)) {\n if (\n method in initializedModel &&\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n typeof (initializedModel as any)[method] === \"function\"\n ) {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n initializedModel = await (initializedModel as any)[method](...args);\n }\n }\n\n // Cache and return the initialized model\n this._modelInstanceCache.set(cacheKey, initializedModel);\n return initializedModel;\n }\n\n async _generate(\n messages: BaseMessage[],\n options?: this[\"ParsedCallOptions\"],\n runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n const model = await this._getModelInstance(options);\n return model._generate(messages, options ?? {}, runManager);\n }\n\n override bindTools(\n tools: BindToolsInput[],\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n params?: Record<string, any>\n ): ConfigurableModel<RunInput, CallOptions> {\n const newQueuedOperations = { ...this._queuedMethodOperations };\n newQueuedOperations.bindTools = [tools, params];\n return new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: this._defaultConfig,\n configurableFields: this._configurableFields,\n configPrefix: this._configPrefix,\n queuedMethodOperations: newQueuedOperations,\n });\n }\n\n // Extract the input types from the `BaseModel` class.\n withStructuredOutput: BaseChatModel[\"withStructuredOutput\"] = (\n schema,\n ...args\n ): ReturnType<BaseChatModel[\"withStructuredOutput\"]> => {\n const newQueuedOperations = { ...this._queuedMethodOperations };\n newQueuedOperations.withStructuredOutput = [schema, ...args];\n return new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: this._defaultConfig,\n configurableFields: this._configurableFields,\n configPrefix: this._configPrefix,\n queuedMethodOperations: newQueuedOperations,\n }) as unknown as ReturnType<BaseChatModel[\"withStructuredOutput\"]>;\n };\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n _modelParams(config?: RunnableConfig): Record<string, any> {\n const configurable = config?.configurable ?? {};\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n let modelParams: Record<string, any> = {};\n\n for (const [key, value] of Object.entries(configurable)) {\n if (key.startsWith(this._configPrefix)) {\n const strippedKey = this._removePrefix(key, this._configPrefix);\n modelParams[strippedKey] = value;\n }\n }\n\n if (this._configurableFields !== \"any\") {\n modelParams = Object.fromEntries(\n Object.entries(modelParams).filter(([key]) =>\n this._configurableFields.includes(key)\n )\n );\n }\n\n return modelParams;\n }\n\n _removePrefix(str: string, prefix: string): string {\n return str.startsWith(prefix) ? str.slice(prefix.length) : str;\n }\n\n /**\n * Bind config to a Runnable, returning a new Runnable.\n * @param {RunnableConfig | undefined} [config] - The config to bind.\n * @returns {RunnableBinding<RunInput, RunOutput, CallOptions>} A new RunnableBinding with the bound config.\n */\n withConfig(\n config?: RunnableConfig\n ): RunnableBinding<RunInput, AIMessageChunk, CallOptions> {\n const mergedConfig: RunnableConfig = { ...(config || {}) };\n const modelParams = this._modelParams(mergedConfig);\n\n const remainingConfig: RunnableConfig = Object.fromEntries(\n Object.entries(mergedConfig).filter(([k]) => k !== \"configurable\")\n );\n\n remainingConfig.configurable = Object.fromEntries(\n Object.entries(mergedConfig.configurable || {}).filter(\n ([k]) =>\n this._configPrefix &&\n !Object.keys(modelParams).includes(\n this._removePrefix(k, this._configPrefix)\n )\n )\n );\n\n const newConfigurableModel = new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: { ...this._defaultConfig, ...modelParams },\n configurableFields: Array.isArray(this._configurableFields)\n ? [...this._configurableFields]\n : this._configurableFields,\n configPrefix: this._configPrefix,\n queuedMethodOperations: this._queuedMethodOperations,\n });\n\n return new RunnableBinding<RunInput, AIMessageChunk, CallOptions>({\n config: mergedConfig,\n bound: newConfigurableModel,\n });\n }\n\n async invoke(\n input: RunInput,\n options?: CallOptions\n ): Promise<AIMessageChunk> {\n const model = await this._getModelInstance(options);\n const config = ensureConfig(options);\n return model.invoke(input, config);\n }\n\n async stream(\n input: RunInput,\n options?: CallOptions\n ): Promise<IterableReadableStream<AIMessageChunk>> {\n const model = await this._getModelInstance(options);\n const wrappedGenerator = new AsyncGeneratorWithSetup({\n generator: await model.stream(input, options),\n config: options,\n });\n await wrappedGenerator.setup;\n return IterableReadableStream.fromAsyncGenerator(wrappedGenerator);\n }\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions & { returnExceptions?: false }\n ): Promise<AIMessageChunk[]>;\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions & { returnExceptions: true }\n ): Promise<(AIMessageChunk | Error)[]>;\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions\n ): Promise<(AIMessageChunk | Error)[]>;\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions\n ): Promise<(AIMessageChunk | Error)[]> {\n // We can super this since the base runnable implementation of\n // `.batch` will call `.invoke` on each input.\n return super.batch(inputs, options, batchOptions);\n }\n\n async *transform(\n generator: AsyncGenerator<RunInput>,\n options: CallOptions\n ): AsyncGenerator<AIMessageChunk> {\n const model = await this._getModelInstance(options);\n const config = ensureConfig(options);\n\n yield* model.transform(generator, config);\n }\n\n async *streamLog(\n input: RunInput,\n options?: Partial<CallOptions>,\n streamOptions?: Omit<LogStreamCallbackHandlerInput, \"autoClose\">\n ): AsyncGenerator<RunLogPatch> {\n const model = await this._getModelInstance(options);\n const config = ensureConfig(options);\n\n yield* model.streamLog(input, config, {\n ...streamOptions,\n _schemaFormat: \"original\",\n includeNames: streamOptions?.includeNames,\n includeTypes: streamOptions?.includeTypes,\n includeTags: streamOptions?.includeTags,\n excludeNames: streamOptions?.excludeNames,\n excludeTypes: streamOptions?.excludeTypes,\n excludeTags: streamOptions?.excludeTags,\n });\n }\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & { version: \"v2\" },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<StreamEvent>;\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & {\n version: \"v2\";\n encoding: \"text/event-stream\";\n },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<Uint8Array>;\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & { version: \"v1\" },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<StreamEvent>;\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & {\n version: \"v1\";\n encoding: \"text/event-stream\";\n },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<Uint8Array>;\n\n streamEvents(\n input: RunInput,\n options?: Partial<CallOptions>\n ): ChatModelStream;\n\n streamEvents(\n input: RunInput,\n options?: Partial<CallOptions> & {\n version?: \"v1\" | \"v2\";\n encoding?: \"text/event-stream\" | undefined;\n },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): ChatModelStream | IterableReadableStream<StreamEvent | Uint8Array> {\n if (options?.version === \"v1\" || options?.version === \"v2\") {\n const outerThis = this;\n const tracingCallOptions = options;\n async function* wrappedGenerator() {\n const model = await outerThis._getModelInstance(tracingCallOptions);\n const config = ensureConfig(tracingCallOptions);\n const tracingOptions = {\n ...config,\n version: tracingCallOptions.version,\n ...(tracingCallOptions.encoding !== undefined\n ? { encoding: tracingCallOptions.encoding }\n : {}),\n };\n let eventStream: IterableReadableStream<StreamEvent | Uint8Array>;\n if (\n tracingCallOptions.version === \"v1\" &&\n tracingCallOptions.encoding === \"text/event-stream\"\n ) {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & {\n version: \"v1\";\n encoding: \"text/event-stream\";\n },\n streamOptions\n );\n } else if (tracingCallOptions.version === \"v1\") {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & { version: \"v1\" },\n streamOptions\n );\n } else if (\n tracingCallOptions.version === \"v2\" &&\n tracingCallOptions.encoding === \"text/event-stream\"\n ) {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & {\n version: \"v2\";\n encoding: \"text/event-stream\";\n },\n streamOptions\n );\n } else {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & { version: \"v2\" },\n streamOptions\n );\n }\n\n for await (const chunk of eventStream) {\n yield chunk;\n }\n }\n return IterableReadableStream.fromAsyncGenerator(wrappedGenerator());\n }\n\n const outerThis = this;\n async function* deferredEvents() {\n const model = await outerThis._getModelInstance(options);\n const config = ensureConfig(options);\n yield* model.streamEvents(input, config);\n }\n return new ChatModelStream(deferredEvents());\n }\n\n /**\n * Return profiling information for the model.\n *\n * @returns {ModelProfile} An object describing the model's capabilities and constraints\n */\n get profile(): ModelProfile {\n if (this._profile) {\n return this._profile;\n }\n const cacheKey = this._getCacheKey({});\n const instance = this._modelInstanceCache.get(cacheKey);\n return instance?.profile ?? {};\n }\n\n /** @internal */\n _getCacheKey(config?: RunnableConfig): string {\n let toStringify = config ?? {};\n if (toStringify.configurable) {\n const { configurable } = toStringify;\n const filtered: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(configurable)) {\n if (!k.startsWith(\"__pregel_\")) {\n filtered[k] = v;\n }\n }\n toStringify = { ...toStringify, configurable: filtered };\n }\n return JSON.stringify(toStringify);\n }\n}\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface InitChatModelFields extends Partial<Record<string, any>> {\n modelProvider?: string;\n configurableFields?: string[] | \"any\";\n configPrefix?: string;\n}\n\nexport type ConfigurableFields = \"any\" | string[];\n\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n fields?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: never;\n configPrefix?: string;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>>;\n\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model: never,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n options?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: never;\n configPrefix?: string;\n profile?: ModelProfile;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>>;\n\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model?: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n options?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: ConfigurableFields;\n configPrefix?: string;\n profile?: ModelProfile;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>>;\n\n// ################################# FOR CONTRIBUTORS #################################\n//\n// If adding support for a new provider, please append the provider\n// name to the supported list in the docstring below.\n//\n// ####################################################################################\n\n/**\n * Initialize a ChatModel from the model name and provider.\n * Must have the integration package corresponding to the model provider installed.\n *\n * @template {extends BaseLanguageModelInput = BaseLanguageModelInput} RunInput - The input type for the model.\n * @template {extends ConfigurableChatModelCallOptions = ConfigurableChatModelCallOptions} CallOptions - Call options for the model.\n *\n * @param {string | ChatModelProvider} [model] - The name of the model, e.g. \"gpt-4\", \"claude-3-opus-20240229\".\n * Can be prefixed with the model provider, e.g. \"openai:gpt-4\", \"anthropic:claude-3-opus-20240229\".\n * @param {Object} [fields] - Additional configuration options.\n * @param {string} [fields.modelProvider] - The model provider. Supported values include:\n * - openai (@langchain/openai)\n * - langsmith (@langchain/openai, via the [LangSmith LLM Gateway](https://docs.langchain.com/langsmith/llm-gateway))\n * - anthropic (@langchain/anthropic)\n * - azure_openai (@langchain/openai)\n * - google-vertexai (@langchain/google-vertexai)\n * - google-vertexai-web (@langchain/google-vertexai-web)\n * - google-genai (@langchain/google-genai)\n * - bedrock (@langchain/aws)\n * - cohere (@langchain/cohere)\n * - fireworks (@langchain/fireworks)\n * - together (@langchain/together-ai)\n * - mistralai (@langchain/mistralai)\n * - groq (@langchain/groq)\n * - ollama (@langchain/ollama)\n * - perplexity (@langchain/perplexity)\n * - cerebras (@langchain/cerebras)\n * - deepseek (@langchain/deepseek)\n * - xai (@langchain/xai)\n * @param {string[] | \"any\"} [fields.configurableFields] - Which model parameters are configurable:\n * - undefined: No configurable fields.\n * - \"any\": All fields are configurable. (See Security Note in description)\n * - string[]: Specified fields are configurable.\n * @param {string} [fields.configPrefix] - Prefix for configurable fields at runtime.\n * @param {ModelProfile} [fields.profile] - Overrides the profiling information for the model. If not provided,\n * the profile will be inferred from the inner model instance.\n * @param {Record<string, any>} [fields.params] - Additional keyword args to pass to the ChatModel constructor.\n * @returns {Promise<ConfigurableModel<RunInput, CallOptions>>} A class which extends BaseChatModel.\n * @throws {Error} If modelProvider cannot be inferred or isn't supported.\n * @throws {Error} If the model provider integration package is not installed.\n *\n * @example Initialize non-configurable models\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const gpt4 = await initChatModel(\"openai:gpt-4\", {\n * temperature: 0.25,\n * });\n * const gpt4Result = await gpt4.invoke(\"what's your name\");\n *\n * const claude = await initChatModel(\"anthropic:claude-3-opus-20240229\", {\n * temperature: 0.25,\n * });\n * const claudeResult = await claude.invoke(\"what's your name\");\n *\n * const gemini = await initChatModel(\"gemini-1.5-pro\", {\n * modelProvider: \"google-vertexai\",\n * temperature: 0.25,\n * });\n * const geminiResult = await gemini.invoke(\"what's your name\");\n * ```\n *\n * @example Create a partially configurable model with no default model\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const configurableModel = await initChatModel(undefined, {\n * temperature: 0,\n * configurableFields: [\"model\", \"apiKey\"],\n * });\n *\n * const gpt4Result = await configurableModel.invoke(\"what's your name\", {\n * configurable: {\n * model: \"gpt-4\",\n * },\n * });\n *\n * const claudeResult = await configurableModel.invoke(\"what's your name\", {\n * configurable: {\n * model: \"claude-sonnet-4-5-20250929\",\n * },\n * });\n * ```\n *\n * @example Create a fully configurable model with a default model and a config prefix\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const configurableModelWithDefault = await initChatModel(\"gpt-4\", {\n * modelProvider: \"openai\",\n * configurableFields: \"any\",\n * configPrefix: \"foo\",\n * temperature: 0,\n * });\n *\n * const openaiResult = await configurableModelWithDefault.invoke(\n * \"what's your name\",\n * {\n * configurable: {\n * foo_apiKey: process.env.OPENAI_API_KEY,\n * },\n * }\n * );\n *\n * const claudeResult = await configurableModelWithDefault.invoke(\n * \"what's your name\",\n * {\n * configurable: {\n * foo_model: \"claude-sonnet-4-5-20250929\",\n * foo_modelProvider: \"anthropic\",\n * foo_temperature: 0.6,\n * foo_apiKey: process.env.ANTHROPIC_API_KEY,\n * },\n * }\n * );\n * ```\n *\n * @example Bind tools to a configurable model:\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n * import { z } from \"zod/v3\";\n * import { tool } from \"@langchain/core/tools\";\n *\n * const getWeatherTool = tool(\n * (input) => {\n * // Do something with the input\n * return JSON.stringify(input);\n * },\n * {\n * schema: z\n * .object({\n * location: z\n * .string()\n * .describe(\"The city and state, e.g. San Francisco, CA\"),\n * })\n * .describe(\"Get the current weather in a given location\"),\n * name: \"GetWeather\",\n * description: \"Get the current weather in a given location\",\n * }\n * );\n *\n * const getPopulationTool = tool(\n * (input) => {\n * // Do something with the input\n * return JSON.stringify(input);\n * },\n * {\n * schema: z\n * .object({\n * location: z\n * .string()\n * .describe(\"The city and state, e.g. San Francisco, CA\"),\n * })\n * .describe(\"Get the current population in a given location\"),\n * name: \"GetPopulation\",\n * description: \"Get the current population in a given location\",\n * }\n * );\n *\n * const configurableModel = await initChatModel(\"gpt-4\", {\n * configurableFields: [\"model\", \"modelProvider\", \"apiKey\"],\n * temperature: 0,\n * });\n *\n * const configurableModelWithTools = configurableModel.bindTools([\n * getWeatherTool,\n * getPopulationTool,\n * ]);\n *\n * const configurableToolResult = await configurableModelWithTools.invoke(\n * \"Which city is hotter today and which is bigger: LA or NY?\",\n * {\n * configurable: {\n * apiKey: process.env.OPENAI_API_KEY,\n * },\n * }\n * );\n *\n * const configurableToolResult2 = await configurableModelWithTools.invoke(\n * \"Which city is hotter today and which is bigger: LA or NY?\",\n * {\n * configurable: {\n * model: \"claude-sonnet-4-5-20250929\",\n * apiKey: process.env.ANTHROPIC_API_KEY,\n * },\n * }\n * );\n * ```\n *\n * @example Initialize a model with a custom profile\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const model = await initChatModel(\"gpt-4o-mini\", {\n * profile: {\n * maxInputTokens: 100000,\n * },\n * });\n *\n * @description\n * This function initializes a ChatModel based on the provided model name and provider.\n * It supports various model providers and allows for runtime configuration of model parameters.\n *\n * Security Note: Setting `configurableFields` to \"any\" means fields like apiKey, baseUrl, etc.\n * can be altered at runtime, potentially redirecting model requests to a different service/user.\n * Make sure that if you're accepting untrusted configurations, you enumerate the\n * `configurableFields` explicitly.\n *\n * The function will attempt to infer the model provider from the model name if not specified.\n * Certain model name prefixes are associated with specific providers:\n * - gpt-3... or gpt-4... -> openai\n * - claude... -> anthropic\n * - amazon.... -> bedrock\n * - gemini... -> google-vertexai\n * - command... -> cohere\n * - accounts/fireworks... -> fireworks\n *\n * @since 0.2.11\n * @version 0.2.11\n */\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model?: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n fields?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: string[] | \"any\";\n configPrefix?: string;\n profile?: ModelProfile;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>> {\n // oxlint-disable-next-line prefer-const\n let { configurableFields, configPrefix, modelProvider, profile, ...params } =\n {\n configPrefix: \"\",\n ...(fields ?? {}),\n };\n if (modelProvider === undefined && model?.includes(\":\")) {\n const [provider, ...remainingParts] = model.split(\":\");\n const modelComponents =\n remainingParts.length === 0\n ? [provider]\n : [provider, remainingParts.join(\":\")];\n if (SUPPORTED_PROVIDERS.includes(modelComponents[0] as ChatModelProvider)) {\n // oxlint-disable-next-line no-param-reassign\n [modelProvider, model] = modelComponents;\n }\n }\n let configurableFieldsCopy = Array.isArray(configurableFields)\n ? [...configurableFields]\n : configurableFields;\n\n if (!model && configurableFieldsCopy === undefined) {\n configurableFieldsCopy = [\"model\", \"modelProvider\"];\n }\n if (configPrefix && configurableFieldsCopy === undefined) {\n console.warn(\n `{ configPrefix: ${configPrefix} } has been set but no fields are configurable. Set ` +\n `{ configurableFields: [...] } to specify the model params that are ` +\n `configurable.`\n );\n }\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const paramsCopy: Record<string, any> = { ...params };\n\n let configurableModel: ConfigurableModel<RunInput, CallOptions>;\n\n if (configurableFieldsCopy === undefined) {\n configurableModel = new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: {\n ...paramsCopy,\n model,\n modelProvider,\n },\n configPrefix,\n profile,\n });\n } else {\n if (model) {\n paramsCopy.model = model;\n }\n if (modelProvider) {\n paramsCopy.modelProvider = modelProvider;\n }\n configurableModel = new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: paramsCopy,\n configPrefix,\n configurableFields: configurableFieldsCopy,\n profile,\n });\n }\n\n // Initialize the model instance to make sure a profile is available\n await configurableModel._getModelInstance();\n return configurableModel;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"universal.d.cts","names":[],"sources":["../../src/chat_models/universal.ts"],"mappings":";;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"universal.d.cts","names":[],"sources":["../../src/chat_models/universal.ts"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"universal.d.ts","names":[],"sources":["../../src/chat_models/universal.ts"],"mappings":";;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"universal.d.ts","names":[],"sources":["../../src/chat_models/universal.ts"],"mappings":"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"}
|
|
@@ -16,13 +16,13 @@ var universal_exports = /* @__PURE__ */ __exportAll({
|
|
|
16
16
|
function getLangSmithChatModelParams({ apiKey, configuration = {} }) {
|
|
17
17
|
const gatewayConfig = resolveLangSmithGatewayConfig({
|
|
18
18
|
baseURL: configuration.baseURL,
|
|
19
|
-
providerPath: "
|
|
19
|
+
providerPath: "v1"
|
|
20
20
|
});
|
|
21
21
|
return {
|
|
22
22
|
apiKey: apiKey ?? configuration.apiKey ?? gatewayConfig.apiKey ?? (getEnvironmentVariable("LANGSMITH_GATEWAY_API_KEY") || getEnvironmentVariable("LANGSMITH_API_KEY")),
|
|
23
23
|
configuration: {
|
|
24
24
|
...configuration,
|
|
25
|
-
baseURL: gatewayConfig.baseURL ?? `${DEFAULT_LANGSMITH_GATEWAY}/
|
|
25
|
+
baseURL: gatewayConfig.baseURL ?? `${DEFAULT_LANGSMITH_GATEWAY}/v1`
|
|
26
26
|
},
|
|
27
27
|
useResponsesApi: true
|
|
28
28
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"universal.js","names":[],"sources":["../../src/chat_models/universal.ts"],"sourcesContent":["import {\n BaseLanguageModelInput,\n ToolDefinition,\n} from \"@langchain/core/language_models/base\";\nimport {\n BaseChatModel,\n BaseChatModelParams,\n BindToolsInput,\n type BaseChatModelCallOptions,\n} from \"@langchain/core/language_models/chat_models\";\nimport {\n BaseMessage,\n type AIMessageChunk,\n MessageStructure,\n} from \"@langchain/core/messages\";\nimport {\n type RunnableBatchOptions,\n RunnableBinding,\n type RunnableConfig,\n type RunnableToolLike,\n ensureConfig,\n} from \"@langchain/core/runnables\";\nimport {\n AsyncGeneratorWithSetup,\n IterableReadableStream,\n} from \"@langchain/core/utils/stream\";\nimport {\n type LogStreamCallbackHandlerInput,\n type RunLogPatch,\n type StreamEvent,\n} from \"@langchain/core/tracers/log_stream\";\nimport { type StructuredToolInterface } from \"@langchain/core/tools\";\nimport { CallbackManagerForLLMRun } from \"@langchain/core/callbacks/manager\";\nimport { ChatResult } from \"@langchain/core/outputs\";\nimport { ModelProfile } from \"@langchain/core/language_models/profile\";\nimport { ChatModelStream } from \"@langchain/core/language_models/stream\";\nimport {\n DEFAULT_LANGSMITH_GATEWAY,\n resolveLangSmithGatewayConfig,\n} from \"@langchain/core/utils/gateway\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\n\nfunction getLangSmithChatModelParams({\n apiKey,\n configuration = {},\n}: {\n apiKey?: unknown;\n configuration?: { apiKey?: unknown; baseURL?: string };\n}) {\n const gatewayConfig = resolveLangSmithGatewayConfig({\n baseURL: configuration.baseURL,\n providerPath: \"openai/v1\",\n });\n\n return {\n apiKey:\n apiKey ??\n configuration.apiKey ??\n gatewayConfig.apiKey ??\n (getEnvironmentVariable(\"LANGSMITH_GATEWAY_API_KEY\") ||\n getEnvironmentVariable(\"LANGSMITH_API_KEY\")),\n configuration: {\n ...configuration,\n baseURL:\n gatewayConfig.baseURL ?? `${DEFAULT_LANGSMITH_GATEWAY}/openai/v1`,\n },\n useResponsesApi: true,\n };\n}\n\n// TODO: remove once `EventStreamCallbackHandlerInput` is exposed in core\ninterface EventStreamCallbackHandlerInput extends Omit<\n LogStreamCallbackHandlerInput,\n \"_schemaFormat\"\n> {}\n\nexport interface ConfigurableChatModelCallOptions extends BaseChatModelCallOptions {\n tools?: (\n | StructuredToolInterface\n | Record<string, unknown>\n | ToolDefinition\n | RunnableToolLike\n )[];\n}\n\n// Configuration map for model providers\nexport const MODEL_PROVIDER_CONFIG = {\n openai: {\n package: \"@langchain/openai\",\n className: \"ChatOpenAI\",\n },\n anthropic: {\n package: \"@langchain/anthropic\",\n className: \"ChatAnthropic\",\n },\n azure_openai: {\n package: \"@langchain/openai\",\n className: \"AzureChatOpenAI\",\n },\n langsmith: {\n package: \"@langchain/openai\",\n className: \"ChatOpenAI\",\n },\n cohere: {\n package: \"@langchain/cohere\",\n className: \"ChatCohere\",\n },\n google: {\n package: \"@langchain/google\",\n className: \"ChatGoogle\",\n },\n \"google-vertexai\": {\n package: \"@langchain/google-vertexai\",\n className: \"ChatVertexAI\",\n },\n \"google-vertexai-web\": {\n package: \"@langchain/google-vertexai-web\",\n className: \"ChatVertexAI\",\n },\n \"google-genai\": {\n package: \"@langchain/google-genai\",\n className: \"ChatGoogleGenerativeAI\",\n },\n ollama: {\n package: \"@langchain/ollama\",\n className: \"ChatOllama\",\n },\n mistralai: {\n package: \"@langchain/mistralai\",\n className: \"ChatMistralAI\",\n },\n mistral: {\n package: \"@langchain/mistralai\",\n className: \"ChatMistralAI\",\n },\n groq: {\n package: \"@langchain/groq\",\n className: \"ChatGroq\",\n },\n bedrock: {\n package: \"@langchain/aws\",\n className: \"ChatBedrockConverse\",\n },\n aws: {\n package: \"@langchain/aws\",\n className: \"ChatBedrockConverse\",\n },\n deepseek: {\n package: \"@langchain/deepseek\",\n className: \"ChatDeepSeek\",\n },\n xai: {\n package: \"@langchain/xai\",\n className: \"ChatXAI\",\n },\n cerebras: {\n package: \"@langchain/cerebras\",\n className: \"ChatCerebras\",\n },\n fireworks: {\n package: \"@langchain/fireworks\",\n className: \"ChatFireworks\",\n },\n together: {\n package: \"@langchain/together-ai\",\n className: \"ChatTogetherAI\",\n hasCircularDependency: true,\n },\n perplexity: {\n package: \"@langchain/perplexity\",\n className: \"ChatPerplexity\",\n },\n} as const;\n\nconst SUPPORTED_PROVIDERS = Object.keys(\n MODEL_PROVIDER_CONFIG\n) as (keyof typeof MODEL_PROVIDER_CONFIG)[];\nexport type ChatModelProvider = keyof typeof MODEL_PROVIDER_CONFIG;\ntype ModelProviderConfig = {\n package: string;\n className: string;\n hasCircularDependency?: boolean;\n};\n\n/**\n * Helper function to get a chat model class by its class name or model provider.\n * @param className The class name (e.g., \"ChatOpenAI\", \"ChatAnthropic\")\n * @param modelProvider Optional model provider key for direct lookup (e.g., \"google-vertexai-web\").\n * When provided, uses direct lookup to avoid className collision issues.\n * @returns The imported model class or undefined if not found\n */\nexport async function getChatModelByClassName(\n className: string,\n modelProvider?: string\n) {\n let config: ModelProviderConfig | undefined;\n\n if (modelProvider) {\n // Direct lookup by modelProvider key - avoids className collision\n // (e.g., google-vertexai and google-vertexai-web both use \"ChatVertexAI\")\n config = MODEL_PROVIDER_CONFIG[\n modelProvider as keyof typeof MODEL_PROVIDER_CONFIG\n ] as ModelProviderConfig | undefined;\n } else {\n // Fallback to className lookup for backward compatibility\n const providerEntry = Object.entries(MODEL_PROVIDER_CONFIG).find(\n ([, c]) => c.className === className\n );\n config = providerEntry\n ? (providerEntry[1] as ModelProviderConfig)\n : undefined;\n }\n\n if (!config) {\n return undefined;\n }\n\n try {\n const module = await import(config.package);\n return module[config.className];\n } catch (e: unknown) {\n const err = e as Error;\n if (\n \"code\" in err &&\n err.code?.toString().includes(\"ERR_MODULE_NOT_FOUND\") &&\n \"message\" in err &&\n typeof err.message === \"string\"\n ) {\n const msg = err.message.startsWith(\"Error: \")\n ? err.message.slice(\"Error: \".length)\n : err.message;\n const attemptedPackage = msg\n .split(\"Cannot find package '\")[1]\n .split(\"'\")[0];\n throw new Error(\n `Unable to import ${attemptedPackage}. Please install with ` +\n `\\`npm install ${attemptedPackage}\\` or \\`pnpm install ${attemptedPackage}\\``\n );\n }\n throw e;\n }\n}\n\nasync function _initChatModelHelper(\n model: string,\n modelProvider?: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n params: Record<string, any> = {}\n): Promise<BaseChatModel> {\n const modelProviderCopy = modelProvider || _inferModelProvider(model);\n if (!modelProviderCopy) {\n throw new Error(\n `Unable to infer model provider for { model: ${model} }, please specify modelProvider directly.`\n );\n }\n\n const config = MODEL_PROVIDER_CONFIG[\n modelProviderCopy as keyof typeof MODEL_PROVIDER_CONFIG\n ] as ModelProviderConfig;\n if (!config) {\n const supported = SUPPORTED_PROVIDERS.join(\", \");\n throw new Error(\n `Unsupported { modelProvider: ${modelProviderCopy} }.\\n\\nSupported model providers are: ${supported}`\n );\n }\n\n const { modelProvider: _unused, ...passedParams } = params;\n // Pass modelProviderCopy to use direct lookup and avoid className collision\n const ProviderClass = await getChatModelByClassName(\n config.className,\n modelProviderCopy\n );\n return new ProviderClass({\n model,\n ...passedParams,\n ...(modelProviderCopy === \"langsmith\"\n ? getLangSmithChatModelParams(passedParams)\n : {}),\n });\n}\n\n/**\n * Attempts to infer the model provider based on the given model name.\n *\n * @param {string} modelName - The name of the model to infer the provider for.\n * @returns {string | undefined} The inferred model provider name, or undefined if unable to infer.\n *\n * @example\n * _inferModelProvider(\"gpt-4\"); // returns \"openai\"\n * _inferModelProvider(\"claude-2\"); // returns \"anthropic\"\n * _inferModelProvider(\"unknown-model\"); // returns undefined\n */\nexport function _inferModelProvider(modelName: string): string | undefined {\n if (\n modelName.startsWith(\"gpt-3\") ||\n modelName.startsWith(\"gpt-4\") ||\n modelName.startsWith(\"gpt-5\") ||\n modelName.startsWith(\"o1\") ||\n modelName.startsWith(\"o3\") ||\n modelName.startsWith(\"o4\")\n ) {\n return \"openai\";\n } else if (modelName.startsWith(\"claude\")) {\n return \"anthropic\";\n } else if (modelName.startsWith(\"command\")) {\n return \"cohere\";\n } else if (modelName.startsWith(\"accounts/fireworks\")) {\n return \"fireworks\";\n } else if (modelName.startsWith(\"gemini\")) {\n return \"google-vertexai\";\n } else if (modelName.startsWith(\"amazon.\")) {\n return \"bedrock\";\n } else if (modelName.startsWith(\"mistral\")) {\n return \"mistralai\";\n } else if (modelName.startsWith(\"sonar\") || modelName.startsWith(\"pplx\")) {\n return \"perplexity\";\n } else {\n return undefined;\n }\n}\n\ninterface ConfigurableModelFields extends BaseChatModelParams {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n defaultConfig?: Record<string, any>;\n /**\n * @default \"any\"\n */\n configurableFields?: string[] | \"any\";\n /**\n * @default \"\"\n */\n configPrefix?: string;\n /**\n * Methods which should be called after the model is initialized.\n * The key will be the method name, and the value will be the arguments.\n */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n queuedMethodOperations?: Record<string, any>;\n /**\n * Overrides the profiling information for the model. If not provided,\n * the profile will be inferred from the inner model instance.\n */\n profile?: ModelProfile;\n}\n\n/**\n * Internal class used to create chat models.\n *\n * @internal\n */\nexport class ConfigurableModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n> extends BaseChatModel<CallOptions, AIMessageChunk> {\n _llmType(): string {\n return \"chat_model\";\n }\n\n lc_namespace = [\"langchain\", \"chat_models\"];\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n _defaultConfig?: Record<string, any> = {};\n\n /**\n * @default \"any\"\n */\n _configurableFields: string[] | \"any\" = \"any\";\n\n /**\n * @default \"\"\n */\n _configPrefix: string;\n\n /**\n * Methods which should be called after the model is initialized.\n * The key will be the method name, and the value will be the arguments.\n */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n _queuedMethodOperations: Record<string, any> = {};\n\n /** @internal */\n private _modelInstanceCache = new Map<\n string,\n BaseChatModel<BaseChatModelCallOptions, AIMessageChunk<MessageStructure>>\n >();\n\n /** @internal */\n private _profile?: ModelProfile;\n\n constructor(fields: ConfigurableModelFields) {\n super(fields);\n this._defaultConfig = fields.defaultConfig ?? {};\n\n if (fields.configurableFields === \"any\") {\n this._configurableFields = \"any\";\n } else {\n this._configurableFields = fields.configurableFields ?? [\n \"model\",\n \"modelProvider\",\n ];\n }\n\n if (fields.configPrefix) {\n this._configPrefix = fields.configPrefix.endsWith(\"_\")\n ? fields.configPrefix\n : `${fields.configPrefix}_`;\n } else {\n this._configPrefix = \"\";\n }\n\n this._queuedMethodOperations =\n fields.queuedMethodOperations ?? this._queuedMethodOperations;\n\n this._profile = fields.profile ?? undefined;\n\n this.metadata = {\n ...this.metadata,\n ls_integration: \"langchain_init_chat_model\",\n };\n }\n\n async _getModelInstance(\n config?: RunnableConfig\n ): Promise<\n BaseChatModel<BaseChatModelCallOptions, AIMessageChunk<MessageStructure>>\n > {\n // Check cache first\n const cacheKey = this._getCacheKey(config);\n const cachedModel = this._modelInstanceCache.get(cacheKey);\n if (cachedModel) {\n return cachedModel;\n }\n\n // Initialize model with merged params\n const params = { ...this._defaultConfig, ...this._modelParams(config) };\n let initializedModel = await _initChatModelHelper(\n params.model,\n params.modelProvider,\n params\n );\n\n // Apply queued method operations in sequence\n for (const [method, args] of Object.entries(this._queuedMethodOperations)) {\n if (\n method in initializedModel &&\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n typeof (initializedModel as any)[method] === \"function\"\n ) {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n initializedModel = await (initializedModel as any)[method](...args);\n }\n }\n\n // Cache and return the initialized model\n this._modelInstanceCache.set(cacheKey, initializedModel);\n return initializedModel;\n }\n\n async _generate(\n messages: BaseMessage[],\n options?: this[\"ParsedCallOptions\"],\n runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n const model = await this._getModelInstance(options);\n return model._generate(messages, options ?? {}, runManager);\n }\n\n override bindTools(\n tools: BindToolsInput[],\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n params?: Record<string, any>\n ): ConfigurableModel<RunInput, CallOptions> {\n const newQueuedOperations = { ...this._queuedMethodOperations };\n newQueuedOperations.bindTools = [tools, params];\n return new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: this._defaultConfig,\n configurableFields: this._configurableFields,\n configPrefix: this._configPrefix,\n queuedMethodOperations: newQueuedOperations,\n });\n }\n\n // Extract the input types from the `BaseModel` class.\n withStructuredOutput: BaseChatModel[\"withStructuredOutput\"] = (\n schema,\n ...args\n ): ReturnType<BaseChatModel[\"withStructuredOutput\"]> => {\n const newQueuedOperations = { ...this._queuedMethodOperations };\n newQueuedOperations.withStructuredOutput = [schema, ...args];\n return new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: this._defaultConfig,\n configurableFields: this._configurableFields,\n configPrefix: this._configPrefix,\n queuedMethodOperations: newQueuedOperations,\n }) as unknown as ReturnType<BaseChatModel[\"withStructuredOutput\"]>;\n };\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n _modelParams(config?: RunnableConfig): Record<string, any> {\n const configurable = config?.configurable ?? {};\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n let modelParams: Record<string, any> = {};\n\n for (const [key, value] of Object.entries(configurable)) {\n if (key.startsWith(this._configPrefix)) {\n const strippedKey = this._removePrefix(key, this._configPrefix);\n modelParams[strippedKey] = value;\n }\n }\n\n if (this._configurableFields !== \"any\") {\n modelParams = Object.fromEntries(\n Object.entries(modelParams).filter(([key]) =>\n this._configurableFields.includes(key)\n )\n );\n }\n\n return modelParams;\n }\n\n _removePrefix(str: string, prefix: string): string {\n return str.startsWith(prefix) ? str.slice(prefix.length) : str;\n }\n\n /**\n * Bind config to a Runnable, returning a new Runnable.\n * @param {RunnableConfig | undefined} [config] - The config to bind.\n * @returns {RunnableBinding<RunInput, RunOutput, CallOptions>} A new RunnableBinding with the bound config.\n */\n withConfig(\n config?: RunnableConfig\n ): RunnableBinding<RunInput, AIMessageChunk, CallOptions> {\n const mergedConfig: RunnableConfig = { ...(config || {}) };\n const modelParams = this._modelParams(mergedConfig);\n\n const remainingConfig: RunnableConfig = Object.fromEntries(\n Object.entries(mergedConfig).filter(([k]) => k !== \"configurable\")\n );\n\n remainingConfig.configurable = Object.fromEntries(\n Object.entries(mergedConfig.configurable || {}).filter(\n ([k]) =>\n this._configPrefix &&\n !Object.keys(modelParams).includes(\n this._removePrefix(k, this._configPrefix)\n )\n )\n );\n\n const newConfigurableModel = new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: { ...this._defaultConfig, ...modelParams },\n configurableFields: Array.isArray(this._configurableFields)\n ? [...this._configurableFields]\n : this._configurableFields,\n configPrefix: this._configPrefix,\n queuedMethodOperations: this._queuedMethodOperations,\n });\n\n return new RunnableBinding<RunInput, AIMessageChunk, CallOptions>({\n config: mergedConfig,\n bound: newConfigurableModel,\n });\n }\n\n async invoke(\n input: RunInput,\n options?: CallOptions\n ): Promise<AIMessageChunk> {\n const model = await this._getModelInstance(options);\n const config = ensureConfig(options);\n return model.invoke(input, config);\n }\n\n async stream(\n input: RunInput,\n options?: CallOptions\n ): Promise<IterableReadableStream<AIMessageChunk>> {\n const model = await this._getModelInstance(options);\n const wrappedGenerator = new AsyncGeneratorWithSetup({\n generator: await model.stream(input, options),\n config: options,\n });\n await wrappedGenerator.setup;\n return IterableReadableStream.fromAsyncGenerator(wrappedGenerator);\n }\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions & { returnExceptions?: false }\n ): Promise<AIMessageChunk[]>;\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions & { returnExceptions: true }\n ): Promise<(AIMessageChunk | Error)[]>;\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions\n ): Promise<(AIMessageChunk | Error)[]>;\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions\n ): Promise<(AIMessageChunk | Error)[]> {\n // We can super this since the base runnable implementation of\n // `.batch` will call `.invoke` on each input.\n return super.batch(inputs, options, batchOptions);\n }\n\n async *transform(\n generator: AsyncGenerator<RunInput>,\n options: CallOptions\n ): AsyncGenerator<AIMessageChunk> {\n const model = await this._getModelInstance(options);\n const config = ensureConfig(options);\n\n yield* model.transform(generator, config);\n }\n\n async *streamLog(\n input: RunInput,\n options?: Partial<CallOptions>,\n streamOptions?: Omit<LogStreamCallbackHandlerInput, \"autoClose\">\n ): AsyncGenerator<RunLogPatch> {\n const model = await this._getModelInstance(options);\n const config = ensureConfig(options);\n\n yield* model.streamLog(input, config, {\n ...streamOptions,\n _schemaFormat: \"original\",\n includeNames: streamOptions?.includeNames,\n includeTypes: streamOptions?.includeTypes,\n includeTags: streamOptions?.includeTags,\n excludeNames: streamOptions?.excludeNames,\n excludeTypes: streamOptions?.excludeTypes,\n excludeTags: streamOptions?.excludeTags,\n });\n }\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & { version: \"v2\" },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<StreamEvent>;\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & {\n version: \"v2\";\n encoding: \"text/event-stream\";\n },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<Uint8Array>;\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & { version: \"v1\" },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<StreamEvent>;\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & {\n version: \"v1\";\n encoding: \"text/event-stream\";\n },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<Uint8Array>;\n\n streamEvents(\n input: RunInput,\n options?: Partial<CallOptions>\n ): ChatModelStream;\n\n streamEvents(\n input: RunInput,\n options?: Partial<CallOptions> & {\n version?: \"v1\" | \"v2\";\n encoding?: \"text/event-stream\" | undefined;\n },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): ChatModelStream | IterableReadableStream<StreamEvent | Uint8Array> {\n if (options?.version === \"v1\" || options?.version === \"v2\") {\n const outerThis = this;\n const tracingCallOptions = options;\n async function* wrappedGenerator() {\n const model = await outerThis._getModelInstance(tracingCallOptions);\n const config = ensureConfig(tracingCallOptions);\n const tracingOptions = {\n ...config,\n version: tracingCallOptions.version,\n ...(tracingCallOptions.encoding !== undefined\n ? { encoding: tracingCallOptions.encoding }\n : {}),\n };\n let eventStream: IterableReadableStream<StreamEvent | Uint8Array>;\n if (\n tracingCallOptions.version === \"v1\" &&\n tracingCallOptions.encoding === \"text/event-stream\"\n ) {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & {\n version: \"v1\";\n encoding: \"text/event-stream\";\n },\n streamOptions\n );\n } else if (tracingCallOptions.version === \"v1\") {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & { version: \"v1\" },\n streamOptions\n );\n } else if (\n tracingCallOptions.version === \"v2\" &&\n tracingCallOptions.encoding === \"text/event-stream\"\n ) {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & {\n version: \"v2\";\n encoding: \"text/event-stream\";\n },\n streamOptions\n );\n } else {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & { version: \"v2\" },\n streamOptions\n );\n }\n\n for await (const chunk of eventStream) {\n yield chunk;\n }\n }\n return IterableReadableStream.fromAsyncGenerator(wrappedGenerator());\n }\n\n const outerThis = this;\n async function* deferredEvents() {\n const model = await outerThis._getModelInstance(options);\n const config = ensureConfig(options);\n yield* model.streamEvents(input, config);\n }\n return new ChatModelStream(deferredEvents());\n }\n\n /**\n * Return profiling information for the model.\n *\n * @returns {ModelProfile} An object describing the model's capabilities and constraints\n */\n get profile(): ModelProfile {\n if (this._profile) {\n return this._profile;\n }\n const cacheKey = this._getCacheKey({});\n const instance = this._modelInstanceCache.get(cacheKey);\n return instance?.profile ?? {};\n }\n\n /** @internal */\n _getCacheKey(config?: RunnableConfig): string {\n let toStringify = config ?? {};\n if (toStringify.configurable) {\n const { configurable } = toStringify;\n const filtered: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(configurable)) {\n if (!k.startsWith(\"__pregel_\")) {\n filtered[k] = v;\n }\n }\n toStringify = { ...toStringify, configurable: filtered };\n }\n return JSON.stringify(toStringify);\n }\n}\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface InitChatModelFields extends Partial<Record<string, any>> {\n modelProvider?: string;\n configurableFields?: string[] | \"any\";\n configPrefix?: string;\n}\n\nexport type ConfigurableFields = \"any\" | string[];\n\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n fields?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: never;\n configPrefix?: string;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>>;\n\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model: never,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n options?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: never;\n configPrefix?: string;\n profile?: ModelProfile;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>>;\n\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model?: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n options?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: ConfigurableFields;\n configPrefix?: string;\n profile?: ModelProfile;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>>;\n\n// ################################# FOR CONTRIBUTORS #################################\n//\n// If adding support for a new provider, please append the provider\n// name to the supported list in the docstring below.\n//\n// ####################################################################################\n\n/**\n * Initialize a ChatModel from the model name and provider.\n * Must have the integration package corresponding to the model provider installed.\n *\n * @template {extends BaseLanguageModelInput = BaseLanguageModelInput} RunInput - The input type for the model.\n * @template {extends ConfigurableChatModelCallOptions = ConfigurableChatModelCallOptions} CallOptions - Call options for the model.\n *\n * @param {string | ChatModelProvider} [model] - The name of the model, e.g. \"gpt-4\", \"claude-3-opus-20240229\".\n * Can be prefixed with the model provider, e.g. \"openai:gpt-4\", \"anthropic:claude-3-opus-20240229\".\n * @param {Object} [fields] - Additional configuration options.\n * @param {string} [fields.modelProvider] - The model provider. Supported values include:\n * - openai (@langchain/openai)\n * - langsmith (@langchain/openai, via the [LangSmith LLM Gateway](https://docs.langchain.com/langsmith/llm-gateway))\n * - anthropic (@langchain/anthropic)\n * - azure_openai (@langchain/openai)\n * - google-vertexai (@langchain/google-vertexai)\n * - google-vertexai-web (@langchain/google-vertexai-web)\n * - google-genai (@langchain/google-genai)\n * - bedrock (@langchain/aws)\n * - cohere (@langchain/cohere)\n * - fireworks (@langchain/fireworks)\n * - together (@langchain/together-ai)\n * - mistralai (@langchain/mistralai)\n * - groq (@langchain/groq)\n * - ollama (@langchain/ollama)\n * - perplexity (@langchain/perplexity)\n * - cerebras (@langchain/cerebras)\n * - deepseek (@langchain/deepseek)\n * - xai (@langchain/xai)\n * @param {string[] | \"any\"} [fields.configurableFields] - Which model parameters are configurable:\n * - undefined: No configurable fields.\n * - \"any\": All fields are configurable. (See Security Note in description)\n * - string[]: Specified fields are configurable.\n * @param {string} [fields.configPrefix] - Prefix for configurable fields at runtime.\n * @param {ModelProfile} [fields.profile] - Overrides the profiling information for the model. If not provided,\n * the profile will be inferred from the inner model instance.\n * @param {Record<string, any>} [fields.params] - Additional keyword args to pass to the ChatModel constructor.\n * @returns {Promise<ConfigurableModel<RunInput, CallOptions>>} A class which extends BaseChatModel.\n * @throws {Error} If modelProvider cannot be inferred or isn't supported.\n * @throws {Error} If the model provider integration package is not installed.\n *\n * @example Initialize non-configurable models\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const gpt4 = await initChatModel(\"openai:gpt-4\", {\n * temperature: 0.25,\n * });\n * const gpt4Result = await gpt4.invoke(\"what's your name\");\n *\n * const claude = await initChatModel(\"anthropic:claude-3-opus-20240229\", {\n * temperature: 0.25,\n * });\n * const claudeResult = await claude.invoke(\"what's your name\");\n *\n * const gemini = await initChatModel(\"gemini-1.5-pro\", {\n * modelProvider: \"google-vertexai\",\n * temperature: 0.25,\n * });\n * const geminiResult = await gemini.invoke(\"what's your name\");\n * ```\n *\n * @example Create a partially configurable model with no default model\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const configurableModel = await initChatModel(undefined, {\n * temperature: 0,\n * configurableFields: [\"model\", \"apiKey\"],\n * });\n *\n * const gpt4Result = await configurableModel.invoke(\"what's your name\", {\n * configurable: {\n * model: \"gpt-4\",\n * },\n * });\n *\n * const claudeResult = await configurableModel.invoke(\"what's your name\", {\n * configurable: {\n * model: \"claude-sonnet-4-5-20250929\",\n * },\n * });\n * ```\n *\n * @example Create a fully configurable model with a default model and a config prefix\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const configurableModelWithDefault = await initChatModel(\"gpt-4\", {\n * modelProvider: \"openai\",\n * configurableFields: \"any\",\n * configPrefix: \"foo\",\n * temperature: 0,\n * });\n *\n * const openaiResult = await configurableModelWithDefault.invoke(\n * \"what's your name\",\n * {\n * configurable: {\n * foo_apiKey: process.env.OPENAI_API_KEY,\n * },\n * }\n * );\n *\n * const claudeResult = await configurableModelWithDefault.invoke(\n * \"what's your name\",\n * {\n * configurable: {\n * foo_model: \"claude-sonnet-4-5-20250929\",\n * foo_modelProvider: \"anthropic\",\n * foo_temperature: 0.6,\n * foo_apiKey: process.env.ANTHROPIC_API_KEY,\n * },\n * }\n * );\n * ```\n *\n * @example Bind tools to a configurable model:\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n * import { z } from \"zod/v3\";\n * import { tool } from \"@langchain/core/tools\";\n *\n * const getWeatherTool = tool(\n * (input) => {\n * // Do something with the input\n * return JSON.stringify(input);\n * },\n * {\n * schema: z\n * .object({\n * location: z\n * .string()\n * .describe(\"The city and state, e.g. San Francisco, CA\"),\n * })\n * .describe(\"Get the current weather in a given location\"),\n * name: \"GetWeather\",\n * description: \"Get the current weather in a given location\",\n * }\n * );\n *\n * const getPopulationTool = tool(\n * (input) => {\n * // Do something with the input\n * return JSON.stringify(input);\n * },\n * {\n * schema: z\n * .object({\n * location: z\n * .string()\n * .describe(\"The city and state, e.g. San Francisco, CA\"),\n * })\n * .describe(\"Get the current population in a given location\"),\n * name: \"GetPopulation\",\n * description: \"Get the current population in a given location\",\n * }\n * );\n *\n * const configurableModel = await initChatModel(\"gpt-4\", {\n * configurableFields: [\"model\", \"modelProvider\", \"apiKey\"],\n * temperature: 0,\n * });\n *\n * const configurableModelWithTools = configurableModel.bindTools([\n * getWeatherTool,\n * getPopulationTool,\n * ]);\n *\n * const configurableToolResult = await configurableModelWithTools.invoke(\n * \"Which city is hotter today and which is bigger: LA or NY?\",\n * {\n * configurable: {\n * apiKey: process.env.OPENAI_API_KEY,\n * },\n * }\n * );\n *\n * const configurableToolResult2 = await configurableModelWithTools.invoke(\n * \"Which city is hotter today and which is bigger: LA or NY?\",\n * {\n * configurable: {\n * model: \"claude-sonnet-4-5-20250929\",\n * apiKey: process.env.ANTHROPIC_API_KEY,\n * },\n * }\n * );\n * ```\n *\n * @example Initialize a model with a custom profile\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const model = await initChatModel(\"gpt-4o-mini\", {\n * profile: {\n * maxInputTokens: 100000,\n * },\n * });\n *\n * @description\n * This function initializes a ChatModel based on the provided model name and provider.\n * It supports various model providers and allows for runtime configuration of model parameters.\n *\n * Security Note: Setting `configurableFields` to \"any\" means fields like apiKey, baseUrl, etc.\n * can be altered at runtime, potentially redirecting model requests to a different service/user.\n * Make sure that if you're accepting untrusted configurations, you enumerate the\n * `configurableFields` explicitly.\n *\n * The function will attempt to infer the model provider from the model name if not specified.\n * Certain model name prefixes are associated with specific providers:\n * - gpt-3... or gpt-4... -> openai\n * - claude... -> anthropic\n * - amazon.... -> bedrock\n * - gemini... -> google-vertexai\n * - command... -> cohere\n * - accounts/fireworks... -> fireworks\n *\n * @since 0.2.11\n * @version 0.2.11\n */\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model?: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n fields?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: string[] | \"any\";\n configPrefix?: string;\n profile?: ModelProfile;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>> {\n // oxlint-disable-next-line prefer-const\n let { configurableFields, configPrefix, modelProvider, profile, ...params } =\n {\n configPrefix: \"\",\n ...(fields ?? {}),\n };\n if (modelProvider === undefined && model?.includes(\":\")) {\n const [provider, ...remainingParts] = model.split(\":\");\n const modelComponents =\n remainingParts.length === 0\n ? [provider]\n : [provider, remainingParts.join(\":\")];\n if (SUPPORTED_PROVIDERS.includes(modelComponents[0] as ChatModelProvider)) {\n // oxlint-disable-next-line no-param-reassign\n [modelProvider, model] = modelComponents;\n }\n }\n let configurableFieldsCopy = Array.isArray(configurableFields)\n ? [...configurableFields]\n : configurableFields;\n\n if (!model && configurableFieldsCopy === undefined) {\n configurableFieldsCopy = [\"model\", \"modelProvider\"];\n }\n if (configPrefix && configurableFieldsCopy === undefined) {\n console.warn(\n `{ configPrefix: ${configPrefix} } has been set but no fields are configurable. Set ` +\n `{ configurableFields: [...] } to specify the model params that are ` +\n `configurable.`\n );\n }\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const paramsCopy: Record<string, any> = { ...params };\n\n let configurableModel: ConfigurableModel<RunInput, CallOptions>;\n\n if (configurableFieldsCopy === undefined) {\n configurableModel = new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: {\n ...paramsCopy,\n model,\n modelProvider,\n },\n configPrefix,\n profile,\n });\n } else {\n if (model) {\n paramsCopy.model = model;\n }\n if (modelProvider) {\n paramsCopy.modelProvider = modelProvider;\n }\n configurableModel = new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: paramsCopy,\n configPrefix,\n configurableFields: configurableFieldsCopy,\n profile,\n });\n }\n\n // Initialize the model instance to make sure a profile is available\n await configurableModel._getModelInstance();\n return configurableModel;\n}\n"],"mappings":";;;;;;;;;;;;;;;AA0CA,SAAS,4BAA4B,EACnC,QACA,gBAAgB,CAAC,KAIhB;CACD,MAAM,gBAAgB,8BAA8B;EAClD,SAAS,cAAc;EACvB,cAAc;CAChB,CAAC;CAED,OAAO;EACL,QACE,UACA,cAAc,UACd,cAAc,WACb,uBAAuB,2BAA2B,KACjD,uBAAuB,mBAAmB;EAC9C,eAAe;GACb,GAAG;GACH,SACE,cAAc,WAAW,GAAG,0BAA0B;EAC1D;EACA,iBAAiB;CACnB;AACF;AAkBA,MAAa,wBAAwB;CACnC,QAAQ;EACN,SAAS;EACT,WAAW;CACb;CACA,WAAW;EACT,SAAS;EACT,WAAW;CACb;CACA,cAAc;EACZ,SAAS;EACT,WAAW;CACb;CACA,WAAW;EACT,SAAS;EACT,WAAW;CACb;CACA,QAAQ;EACN,SAAS;EACT,WAAW;CACb;CACA,QAAQ;EACN,SAAS;EACT,WAAW;CACb;CACA,mBAAmB;EACjB,SAAS;EACT,WAAW;CACb;CACA,uBAAuB;EACrB,SAAS;EACT,WAAW;CACb;CACA,gBAAgB;EACd,SAAS;EACT,WAAW;CACb;CACA,QAAQ;EACN,SAAS;EACT,WAAW;CACb;CACA,WAAW;EACT,SAAS;EACT,WAAW;CACb;CACA,SAAS;EACP,SAAS;EACT,WAAW;CACb;CACA,MAAM;EACJ,SAAS;EACT,WAAW;CACb;CACA,SAAS;EACP,SAAS;EACT,WAAW;CACb;CACA,KAAK;EACH,SAAS;EACT,WAAW;CACb;CACA,UAAU;EACR,SAAS;EACT,WAAW;CACb;CACA,KAAK;EACH,SAAS;EACT,WAAW;CACb;CACA,UAAU;EACR,SAAS;EACT,WAAW;CACb;CACA,WAAW;EACT,SAAS;EACT,WAAW;CACb;CACA,UAAU;EACR,SAAS;EACT,WAAW;EACX,uBAAuB;CACzB;CACA,YAAY;EACV,SAAS;EACT,WAAW;CACb;AACF;AAEA,MAAM,sBAAsB,OAAO,KACjC,qBACF;;;;;;;;AAeA,eAAsB,wBACpB,WACA,eACA;CACA,IAAI;CAEJ,IAAI,eAGF,SAAS,sBACP;MAEG;EAEL,MAAM,gBAAgB,OAAO,QAAQ,qBAAqB,CAAC,CAAC,MACzD,GAAG,OAAO,EAAE,cAAc,SAC7B;EACA,SAAS,gBACJ,cAAc,KACf,KAAA;CACN;CAEA,IAAI,CAAC,QACH;CAGF,IAAI;EAEF,QAAO,MADc,OAAO,OAAO,SAAA,CACrB,OAAO;CACvB,SAAS,GAAY;EACnB,MAAM,MAAM;EACZ,IACE,UAAU,OACV,IAAI,MAAM,SAAS,CAAC,CAAC,SAAS,sBAAsB,KACpD,aAAa,OACb,OAAO,IAAI,YAAY,UACvB;GAIA,MAAM,oBAHM,IAAI,QAAQ,WAAW,SAAS,IACxC,IAAI,QAAQ,MAAM,CAAgB,IAClC,IAAI,QAAA,CAEL,MAAM,uBAAuB,CAAC,CAAC,EAAE,CACjC,MAAM,GAAG,CAAC,CAAC;GACd,MAAM,IAAI,MACR,oBAAoB,iBAAiB,sCAClB,iBAAiB,uBAAuB,iBAAiB,GAC9E;EACF;EACA,MAAM;CACR;AACF;AAEA,eAAe,qBACb,OACA,eAEA,SAA8B,CAAC,GACP;CACxB,MAAM,oBAAoB,iBAAiB,oBAAoB,KAAK;CACpE,IAAI,CAAC,mBACH,MAAM,IAAI,MACR,+CAA+C,MAAM,2CACvD;CAGF,MAAM,SAAS,sBACb;CAEF,IAAI,CAAC,QAAQ;EACX,MAAM,YAAY,oBAAoB,KAAK,IAAI;EAC/C,MAAM,IAAI,MACR,gCAAgC,kBAAkB,wCAAwC,WAC5F;CACF;CAEA,MAAM,EAAE,eAAe,SAAS,GAAG,iBAAiB;CAMpD,OAAO,KAAI,OAJiB,wBAC1B,OAAO,WACP,iBACF,IACyB;EACvB;EACA,GAAG;EACH,GAAI,sBAAsB,cACtB,4BAA4B,YAAY,IACxC,CAAC;CACP,CAAC;AACH;;;;;;;;;;;;AAaA,SAAgB,oBAAoB,WAAuC;CACzE,IACE,UAAU,WAAW,OAAO,KAC5B,UAAU,WAAW,OAAO,KAC5B,UAAU,WAAW,OAAO,KAC5B,UAAU,WAAW,IAAI,KACzB,UAAU,WAAW,IAAI,KACzB,UAAU,WAAW,IAAI,GAEzB,OAAO;MACF,IAAI,UAAU,WAAW,QAAQ,GACtC,OAAO;MACF,IAAI,UAAU,WAAW,SAAS,GACvC,OAAO;MACF,IAAI,UAAU,WAAW,oBAAoB,GAClD,OAAO;MACF,IAAI,UAAU,WAAW,QAAQ,GACtC,OAAO;MACF,IAAI,UAAU,WAAW,SAAS,GACvC,OAAO;MACF,IAAI,UAAU,WAAW,SAAS,GACvC,OAAO;MACF,IAAI,UAAU,WAAW,OAAO,KAAK,UAAU,WAAW,MAAM,GACrE,OAAO;MAEP;AAEJ;;;;;;AA+BA,IAAa,oBAAb,MAAa,0BAIH,cAA2C;CACnD,WAAmB;EACjB,OAAO;CACT;CAEA,eAAe,CAAC,aAAa,aAAa;CAG1C,iBAAuC,CAAC;;;;CAKxC,sBAAwC;;;;CAKxC;;;;;CAOA,0BAA+C,CAAC;;CAGhD,sCAA8B,IAAI,IAGhC;;CAGF;CAEA,YAAY,QAAiC;EAC3C,MAAM,MAAM;EACZ,KAAK,iBAAiB,OAAO,iBAAiB,CAAC;EAE/C,IAAI,OAAO,uBAAuB,OAChC,KAAK,sBAAsB;OAE3B,KAAK,sBAAsB,OAAO,sBAAsB,CACtD,SACA,eACF;EAGF,IAAI,OAAO,cACT,KAAK,gBAAgB,OAAO,aAAa,SAAS,GAAG,IACjD,OAAO,eACP,GAAG,OAAO,aAAa;OAE3B,KAAK,gBAAgB;EAGvB,KAAK,0BACH,OAAO,0BAA0B,KAAK;EAExC,KAAK,WAAW,OAAO,WAAW,KAAA;EAElC,KAAK,WAAW;GACd,GAAG,KAAK;GACR,gBAAgB;EAClB;CACF;CAEA,MAAM,kBACJ,QAGA;EAEA,MAAM,WAAW,KAAK,aAAa,MAAM;EACzC,MAAM,cAAc,KAAK,oBAAoB,IAAI,QAAQ;EACzD,IAAI,aACF,OAAO;EAIT,MAAM,SAAS;GAAE,GAAG,KAAK;GAAgB,GAAG,KAAK,aAAa,MAAM;EAAE;EACtE,IAAI,mBAAmB,MAAM,qBAC3B,OAAO,OACP,OAAO,eACP,MACF;EAGA,KAAK,MAAM,CAAC,QAAQ,SAAS,OAAO,QAAQ,KAAK,uBAAuB,GACtE,IACE,UAAU,oBAEV,OAAQ,iBAAyB,YAAY,YAG7C,mBAAmB,MAAO,iBAAyB,OAAO,CAAC,GAAG,IAAI;EAKtE,KAAK,oBAAoB,IAAI,UAAU,gBAAgB;EACvD,OAAO;CACT;CAEA,MAAM,UACJ,UACA,SACA,YACqB;EAErB,QAAO,MADa,KAAK,kBAAkB,OAAO,EAAA,CACrC,UAAU,UAAU,WAAW,CAAC,GAAG,UAAU;CAC5D;CAEA,UACE,OAEA,QAC0C;EAC1C,MAAM,sBAAsB,EAAE,GAAG,KAAK,wBAAwB;EAC9D,oBAAoB,YAAY,CAAC,OAAO,MAAM;EAC9C,OAAO,IAAI,kBAAyC;GAClD,eAAe,KAAK;GACpB,oBAAoB,KAAK;GACzB,cAAc,KAAK;GACnB,wBAAwB;EAC1B,CAAC;CACH;CAGA,wBACE,QACA,GAAG,SACmD;EACtD,MAAM,sBAAsB,EAAE,GAAG,KAAK,wBAAwB;EAC9D,oBAAoB,uBAAuB,CAAC,QAAQ,GAAG,IAAI;EAC3D,OAAO,IAAI,kBAAyC;GAClD,eAAe,KAAK;GACpB,oBAAoB,KAAK;GACzB,cAAc,KAAK;GACnB,wBAAwB;EAC1B,CAAC;CACH;CAGA,aAAa,QAA8C;EACzD,MAAM,eAAe,QAAQ,gBAAgB,CAAC;EAE9C,IAAI,cAAmC,CAAC;EAExC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,YAAY,GACpD,IAAI,IAAI,WAAW,KAAK,aAAa,GAAG;GACtC,MAAM,cAAc,KAAK,cAAc,KAAK,KAAK,aAAa;GAC9D,YAAY,eAAe;EAC7B;EAGF,IAAI,KAAK,wBAAwB,OAC/B,cAAc,OAAO,YACnB,OAAO,QAAQ,WAAW,CAAC,CAAC,QAAQ,CAAC,SACnC,KAAK,oBAAoB,SAAS,GAAG,CACvC,CACF;EAGF,OAAO;CACT;CAEA,cAAc,KAAa,QAAwB;EACjD,OAAO,IAAI,WAAW,MAAM,IAAI,IAAI,MAAM,OAAO,MAAM,IAAI;CAC7D;;;;;;CAOA,WACE,QACwD;EACxD,MAAM,eAA+B,EAAE,GAAI,UAAU,CAAC,EAAG;EACzD,MAAM,cAAc,KAAK,aAAa,YAAY;EAElD,MAAM,kBAAkC,OAAO,YAC7C,OAAO,QAAQ,YAAY,CAAC,CAAC,QAAQ,CAAC,OAAO,MAAM,cAAc,CACnE;EAEA,gBAAgB,eAAe,OAAO,YACpC,OAAO,QAAQ,aAAa,gBAAgB,CAAC,CAAC,CAAC,CAAC,QAC7C,CAAC,OACA,KAAK,iBACL,CAAC,OAAO,KAAK,WAAW,CAAC,CAAC,SACxB,KAAK,cAAc,GAAG,KAAK,aAAa,CAC1C,CACJ,CACF;EAWA,OAAO,IAAI,gBAAuD;GAChE,QAAQ;GACR,OAAO,IAXwB,kBAAyC;IACxE,eAAe;KAAE,GAAG,KAAK;KAAgB,GAAG;IAAY;IACxD,oBAAoB,MAAM,QAAQ,KAAK,mBAAmB,IACtD,CAAC,GAAG,KAAK,mBAAmB,IAC5B,KAAK;IACT,cAAc,KAAK;IACnB,wBAAwB,KAAK;GAC/B,CAI4B;EAC5B,CAAC;CACH;CAEA,MAAM,OACJ,OACA,SACyB;EACzB,MAAM,QAAQ,MAAM,KAAK,kBAAkB,OAAO;EAClD,MAAM,SAAS,aAAa,OAAO;EACnC,OAAO,MAAM,OAAO,OAAO,MAAM;CACnC;CAEA,MAAM,OACJ,OACA,SACiD;EAEjD,MAAM,mBAAmB,IAAI,wBAAwB;GACnD,WAAW,OAAM,MAFC,KAAK,kBAAkB,OAAO,EAAA,CAEzB,OAAO,OAAO,OAAO;GAC5C,QAAQ;EACV,CAAC;EACD,MAAM,iBAAiB;EACvB,OAAO,uBAAuB,mBAAmB,gBAAgB;CACnE;CAoBA,MAAM,MACJ,QACA,SACA,cACqC;EAGrC,OAAO,MAAM,MAAM,QAAQ,SAAS,YAAY;CAClD;CAEA,OAAO,UACL,WACA,SACgC;EAChC,MAAM,QAAQ,MAAM,KAAK,kBAAkB,OAAO;EAClD,MAAM,SAAS,aAAa,OAAO;EAEnC,OAAO,MAAM,UAAU,WAAW,MAAM;CAC1C;CAEA,OAAO,UACL,OACA,SACA,eAC6B;EAC7B,MAAM,QAAQ,MAAM,KAAK,kBAAkB,OAAO;EAClD,MAAM,SAAS,aAAa,OAAO;EAEnC,OAAO,MAAM,UAAU,OAAO,QAAQ;GACpC,GAAG;GACH,eAAe;GACf,cAAc,eAAe;GAC7B,cAAc,eAAe;GAC7B,aAAa,eAAe;GAC5B,cAAc,eAAe;GAC7B,cAAc,eAAe;GAC7B,aAAa,eAAe;EAC9B,CAAC;CACH;CAqDA,aACE,OACA,SAIA,eACoE;EACpE,IAAI,SAAS,YAAY,QAAQ,SAAS,YAAY,MAAM;GAC1D,MAAM,YAAY;GAClB,MAAM,qBAAqB;GAC3B,gBAAgB,mBAAmB;IACjC,MAAM,QAAQ,MAAM,UAAU,kBAAkB,kBAAkB;IAElE,MAAM,iBAAiB;KACrB,GAFa,aAAa,kBAElB;KACR,SAAS,mBAAmB;KAC5B,GAAI,mBAAmB,aAAa,KAAA,IAChC,EAAE,UAAU,mBAAmB,SAAS,IACxC,CAAC;IACP;IACA,IAAI;IACJ,IACE,mBAAmB,YAAY,QAC/B,mBAAmB,aAAa,qBAEhC,cAAc,MAAM,aAClB,OACA,gBAIA,aACF;SACK,IAAI,mBAAmB,YAAY,MACxC,cAAc,MAAM,aAClB,OACA,gBACA,aACF;SACK,IACL,mBAAmB,YAAY,QAC/B,mBAAmB,aAAa,qBAEhC,cAAc,MAAM,aAClB,OACA,gBAIA,aACF;SAEA,cAAc,MAAM,aAClB,OACA,gBACA,aACF;IAGF,WAAW,MAAM,SAAS,aACxB,MAAM;GAEV;GACA,OAAO,uBAAuB,mBAAmB,iBAAiB,CAAC;EACrE;EAEA,MAAM,YAAY;EAClB,gBAAgB,iBAAiB;GAC/B,MAAM,QAAQ,MAAM,UAAU,kBAAkB,OAAO;GACvD,MAAM,SAAS,aAAa,OAAO;GACnC,OAAO,MAAM,aAAa,OAAO,MAAM;EACzC;EACA,OAAO,IAAI,gBAAgB,eAAe,CAAC;CAC7C;;;;;;CAOA,IAAI,UAAwB;EAC1B,IAAI,KAAK,UACP,OAAO,KAAK;EAEd,MAAM,WAAW,KAAK,aAAa,CAAC,CAAC;EAErC,OADiB,KAAK,oBAAoB,IAAI,QAChC,CAAC,EAAE,WAAW,CAAC;CAC/B;;CAGA,aAAa,QAAiC;EAC5C,IAAI,cAAc,UAAU,CAAC;EAC7B,IAAI,YAAY,cAAc;GAC5B,MAAM,EAAE,iBAAiB;GACzB,MAAM,WAAoC,CAAC;GAC3C,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,YAAY,GAC9C,IAAI,CAAC,EAAE,WAAW,WAAW,GAC3B,SAAS,KAAK;GAGlB,cAAc;IAAE,GAAG;IAAa,cAAc;GAAS;EACzD;EACA,OAAO,KAAK,UAAU,WAAW;CACnC;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0RA,eAAsB,cAKpB,OAEA,QAMmD;CAEnD,IAAI,EAAE,oBAAoB,cAAc,eAAe,SAAS,GAAG,WACjE;EACE,cAAc;EACd,GAAI,UAAU,CAAC;CACjB;CACF,IAAI,kBAAkB,KAAA,KAAa,OAAO,SAAS,GAAG,GAAG;EACvD,MAAM,CAAC,UAAU,GAAG,kBAAkB,MAAM,MAAM,GAAG;EACrD,MAAM,kBACJ,eAAe,WAAW,IACtB,CAAC,QAAQ,IACT,CAAC,UAAU,eAAe,KAAK,GAAG,CAAC;EACzC,IAAI,oBAAoB,SAAS,gBAAgB,EAAuB,GAEtE,CAAC,eAAe,SAAS;CAE7B;CACA,IAAI,yBAAyB,MAAM,QAAQ,kBAAkB,IACzD,CAAC,GAAG,kBAAkB,IACtB;CAEJ,IAAI,CAAC,SAAS,2BAA2B,KAAA,GACvC,yBAAyB,CAAC,SAAS,eAAe;CAEpD,IAAI,gBAAgB,2BAA2B,KAAA,GAC7C,QAAQ,KACN,mBAAmB,aAAa,qIAGlC;CAIF,MAAM,aAAkC,EAAE,GAAG,OAAO;CAEpD,IAAI;CAEJ,IAAI,2BAA2B,KAAA,GAC7B,oBAAoB,IAAI,kBAAyC;EAC/D,eAAe;GACb,GAAG;GACH;GACA;EACF;EACA;EACA;CACF,CAAC;MACI;EACL,IAAI,OACF,WAAW,QAAQ;EAErB,IAAI,eACF,WAAW,gBAAgB;EAE7B,oBAAoB,IAAI,kBAAyC;GAC/D,eAAe;GACf;GACA,oBAAoB;GACpB;EACF,CAAC;CACH;CAGA,MAAM,kBAAkB,kBAAkB;CAC1C,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"universal.js","names":[],"sources":["../../src/chat_models/universal.ts"],"sourcesContent":["import {\n BaseLanguageModelInput,\n ToolDefinition,\n} from \"@langchain/core/language_models/base\";\nimport {\n BaseChatModel,\n BaseChatModelParams,\n BindToolsInput,\n type BaseChatModelCallOptions,\n} from \"@langchain/core/language_models/chat_models\";\nimport {\n BaseMessage,\n type AIMessageChunk,\n MessageStructure,\n} from \"@langchain/core/messages\";\nimport {\n type RunnableBatchOptions,\n RunnableBinding,\n type RunnableConfig,\n type RunnableToolLike,\n ensureConfig,\n} from \"@langchain/core/runnables\";\nimport {\n AsyncGeneratorWithSetup,\n IterableReadableStream,\n} from \"@langchain/core/utils/stream\";\nimport {\n type LogStreamCallbackHandlerInput,\n type RunLogPatch,\n type StreamEvent,\n} from \"@langchain/core/tracers/log_stream\";\nimport { type StructuredToolInterface } from \"@langchain/core/tools\";\nimport { CallbackManagerForLLMRun } from \"@langchain/core/callbacks/manager\";\nimport { ChatResult } from \"@langchain/core/outputs\";\nimport { ModelProfile } from \"@langchain/core/language_models/profile\";\nimport { ChatModelStream } from \"@langchain/core/language_models/stream\";\nimport {\n DEFAULT_LANGSMITH_GATEWAY,\n resolveLangSmithGatewayConfig,\n} from \"@langchain/core/utils/gateway\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\n\nfunction getLangSmithChatModelParams({\n apiKey,\n configuration = {},\n}: {\n apiKey?: unknown;\n configuration?: { apiKey?: unknown; baseURL?: string };\n}) {\n const gatewayConfig = resolveLangSmithGatewayConfig({\n baseURL: configuration.baseURL,\n providerPath: \"v1\",\n });\n\n return {\n apiKey:\n apiKey ??\n configuration.apiKey ??\n gatewayConfig.apiKey ??\n (getEnvironmentVariable(\"LANGSMITH_GATEWAY_API_KEY\") ||\n getEnvironmentVariable(\"LANGSMITH_API_KEY\")),\n configuration: {\n ...configuration,\n baseURL: gatewayConfig.baseURL ?? `${DEFAULT_LANGSMITH_GATEWAY}/v1`,\n },\n useResponsesApi: true,\n };\n}\n\n// TODO: remove once `EventStreamCallbackHandlerInput` is exposed in core\ninterface EventStreamCallbackHandlerInput extends Omit<\n LogStreamCallbackHandlerInput,\n \"_schemaFormat\"\n> {}\n\nexport interface ConfigurableChatModelCallOptions extends BaseChatModelCallOptions {\n tools?: (\n | StructuredToolInterface\n | Record<string, unknown>\n | ToolDefinition\n | RunnableToolLike\n )[];\n}\n\n// Configuration map for model providers\nexport const MODEL_PROVIDER_CONFIG = {\n openai: {\n package: \"@langchain/openai\",\n className: \"ChatOpenAI\",\n },\n anthropic: {\n package: \"@langchain/anthropic\",\n className: \"ChatAnthropic\",\n },\n azure_openai: {\n package: \"@langchain/openai\",\n className: \"AzureChatOpenAI\",\n },\n langsmith: {\n package: \"@langchain/openai\",\n className: \"ChatOpenAI\",\n },\n cohere: {\n package: \"@langchain/cohere\",\n className: \"ChatCohere\",\n },\n google: {\n package: \"@langchain/google\",\n className: \"ChatGoogle\",\n },\n \"google-vertexai\": {\n package: \"@langchain/google-vertexai\",\n className: \"ChatVertexAI\",\n },\n \"google-vertexai-web\": {\n package: \"@langchain/google-vertexai-web\",\n className: \"ChatVertexAI\",\n },\n \"google-genai\": {\n package: \"@langchain/google-genai\",\n className: \"ChatGoogleGenerativeAI\",\n },\n ollama: {\n package: \"@langchain/ollama\",\n className: \"ChatOllama\",\n },\n mistralai: {\n package: \"@langchain/mistralai\",\n className: \"ChatMistralAI\",\n },\n mistral: {\n package: \"@langchain/mistralai\",\n className: \"ChatMistralAI\",\n },\n groq: {\n package: \"@langchain/groq\",\n className: \"ChatGroq\",\n },\n bedrock: {\n package: \"@langchain/aws\",\n className: \"ChatBedrockConverse\",\n },\n aws: {\n package: \"@langchain/aws\",\n className: \"ChatBedrockConverse\",\n },\n deepseek: {\n package: \"@langchain/deepseek\",\n className: \"ChatDeepSeek\",\n },\n xai: {\n package: \"@langchain/xai\",\n className: \"ChatXAI\",\n },\n cerebras: {\n package: \"@langchain/cerebras\",\n className: \"ChatCerebras\",\n },\n fireworks: {\n package: \"@langchain/fireworks\",\n className: \"ChatFireworks\",\n },\n together: {\n package: \"@langchain/together-ai\",\n className: \"ChatTogetherAI\",\n hasCircularDependency: true,\n },\n perplexity: {\n package: \"@langchain/perplexity\",\n className: \"ChatPerplexity\",\n },\n} as const;\n\nconst SUPPORTED_PROVIDERS = Object.keys(\n MODEL_PROVIDER_CONFIG\n) as (keyof typeof MODEL_PROVIDER_CONFIG)[];\nexport type ChatModelProvider = keyof typeof MODEL_PROVIDER_CONFIG;\ntype ModelProviderConfig = {\n package: string;\n className: string;\n hasCircularDependency?: boolean;\n};\n\n/**\n * Helper function to get a chat model class by its class name or model provider.\n * @param className The class name (e.g., \"ChatOpenAI\", \"ChatAnthropic\")\n * @param modelProvider Optional model provider key for direct lookup (e.g., \"google-vertexai-web\").\n * When provided, uses direct lookup to avoid className collision issues.\n * @returns The imported model class or undefined if not found\n */\nexport async function getChatModelByClassName(\n className: string,\n modelProvider?: string\n) {\n let config: ModelProviderConfig | undefined;\n\n if (modelProvider) {\n // Direct lookup by modelProvider key - avoids className collision\n // (e.g., google-vertexai and google-vertexai-web both use \"ChatVertexAI\")\n config = MODEL_PROVIDER_CONFIG[\n modelProvider as keyof typeof MODEL_PROVIDER_CONFIG\n ] as ModelProviderConfig | undefined;\n } else {\n // Fallback to className lookup for backward compatibility\n const providerEntry = Object.entries(MODEL_PROVIDER_CONFIG).find(\n ([, c]) => c.className === className\n );\n config = providerEntry\n ? (providerEntry[1] as ModelProviderConfig)\n : undefined;\n }\n\n if (!config) {\n return undefined;\n }\n\n try {\n const module = await import(config.package);\n return module[config.className];\n } catch (e: unknown) {\n const err = e as Error;\n if (\n \"code\" in err &&\n err.code?.toString().includes(\"ERR_MODULE_NOT_FOUND\") &&\n \"message\" in err &&\n typeof err.message === \"string\"\n ) {\n const msg = err.message.startsWith(\"Error: \")\n ? err.message.slice(\"Error: \".length)\n : err.message;\n const attemptedPackage = msg\n .split(\"Cannot find package '\")[1]\n .split(\"'\")[0];\n throw new Error(\n `Unable to import ${attemptedPackage}. Please install with ` +\n `\\`npm install ${attemptedPackage}\\` or \\`pnpm install ${attemptedPackage}\\``\n );\n }\n throw e;\n }\n}\n\nasync function _initChatModelHelper(\n model: string,\n modelProvider?: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n params: Record<string, any> = {}\n): Promise<BaseChatModel> {\n const modelProviderCopy = modelProvider || _inferModelProvider(model);\n if (!modelProviderCopy) {\n throw new Error(\n `Unable to infer model provider for { model: ${model} }, please specify modelProvider directly.`\n );\n }\n\n const config = MODEL_PROVIDER_CONFIG[\n modelProviderCopy as keyof typeof MODEL_PROVIDER_CONFIG\n ] as ModelProviderConfig;\n if (!config) {\n const supported = SUPPORTED_PROVIDERS.join(\", \");\n throw new Error(\n `Unsupported { modelProvider: ${modelProviderCopy} }.\\n\\nSupported model providers are: ${supported}`\n );\n }\n\n const { modelProvider: _unused, ...passedParams } = params;\n // Pass modelProviderCopy to use direct lookup and avoid className collision\n const ProviderClass = await getChatModelByClassName(\n config.className,\n modelProviderCopy\n );\n return new ProviderClass({\n model,\n ...passedParams,\n ...(modelProviderCopy === \"langsmith\"\n ? getLangSmithChatModelParams(passedParams)\n : {}),\n });\n}\n\n/**\n * Attempts to infer the model provider based on the given model name.\n *\n * @param {string} modelName - The name of the model to infer the provider for.\n * @returns {string | undefined} The inferred model provider name, or undefined if unable to infer.\n *\n * @example\n * _inferModelProvider(\"gpt-4\"); // returns \"openai\"\n * _inferModelProvider(\"claude-2\"); // returns \"anthropic\"\n * _inferModelProvider(\"unknown-model\"); // returns undefined\n */\nexport function _inferModelProvider(modelName: string): string | undefined {\n if (\n modelName.startsWith(\"gpt-3\") ||\n modelName.startsWith(\"gpt-4\") ||\n modelName.startsWith(\"gpt-5\") ||\n modelName.startsWith(\"o1\") ||\n modelName.startsWith(\"o3\") ||\n modelName.startsWith(\"o4\")\n ) {\n return \"openai\";\n } else if (modelName.startsWith(\"claude\")) {\n return \"anthropic\";\n } else if (modelName.startsWith(\"command\")) {\n return \"cohere\";\n } else if (modelName.startsWith(\"accounts/fireworks\")) {\n return \"fireworks\";\n } else if (modelName.startsWith(\"gemini\")) {\n return \"google-vertexai\";\n } else if (modelName.startsWith(\"amazon.\")) {\n return \"bedrock\";\n } else if (modelName.startsWith(\"mistral\")) {\n return \"mistralai\";\n } else if (modelName.startsWith(\"sonar\") || modelName.startsWith(\"pplx\")) {\n return \"perplexity\";\n } else {\n return undefined;\n }\n}\n\ninterface ConfigurableModelFields extends BaseChatModelParams {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n defaultConfig?: Record<string, any>;\n /**\n * @default \"any\"\n */\n configurableFields?: string[] | \"any\";\n /**\n * @default \"\"\n */\n configPrefix?: string;\n /**\n * Methods which should be called after the model is initialized.\n * The key will be the method name, and the value will be the arguments.\n */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n queuedMethodOperations?: Record<string, any>;\n /**\n * Overrides the profiling information for the model. If not provided,\n * the profile will be inferred from the inner model instance.\n */\n profile?: ModelProfile;\n}\n\n/**\n * Internal class used to create chat models.\n *\n * @internal\n */\nexport class ConfigurableModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n> extends BaseChatModel<CallOptions, AIMessageChunk> {\n _llmType(): string {\n return \"chat_model\";\n }\n\n lc_namespace = [\"langchain\", \"chat_models\"];\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n _defaultConfig?: Record<string, any> = {};\n\n /**\n * @default \"any\"\n */\n _configurableFields: string[] | \"any\" = \"any\";\n\n /**\n * @default \"\"\n */\n _configPrefix: string;\n\n /**\n * Methods which should be called after the model is initialized.\n * The key will be the method name, and the value will be the arguments.\n */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n _queuedMethodOperations: Record<string, any> = {};\n\n /** @internal */\n private _modelInstanceCache = new Map<\n string,\n BaseChatModel<BaseChatModelCallOptions, AIMessageChunk<MessageStructure>>\n >();\n\n /** @internal */\n private _profile?: ModelProfile;\n\n constructor(fields: ConfigurableModelFields) {\n super(fields);\n this._defaultConfig = fields.defaultConfig ?? {};\n\n if (fields.configurableFields === \"any\") {\n this._configurableFields = \"any\";\n } else {\n this._configurableFields = fields.configurableFields ?? [\n \"model\",\n \"modelProvider\",\n ];\n }\n\n if (fields.configPrefix) {\n this._configPrefix = fields.configPrefix.endsWith(\"_\")\n ? fields.configPrefix\n : `${fields.configPrefix}_`;\n } else {\n this._configPrefix = \"\";\n }\n\n this._queuedMethodOperations =\n fields.queuedMethodOperations ?? this._queuedMethodOperations;\n\n this._profile = fields.profile ?? undefined;\n\n this.metadata = {\n ...this.metadata,\n ls_integration: \"langchain_init_chat_model\",\n };\n }\n\n async _getModelInstance(\n config?: RunnableConfig\n ): Promise<\n BaseChatModel<BaseChatModelCallOptions, AIMessageChunk<MessageStructure>>\n > {\n // Check cache first\n const cacheKey = this._getCacheKey(config);\n const cachedModel = this._modelInstanceCache.get(cacheKey);\n if (cachedModel) {\n return cachedModel;\n }\n\n // Initialize model with merged params\n const params = { ...this._defaultConfig, ...this._modelParams(config) };\n let initializedModel = await _initChatModelHelper(\n params.model,\n params.modelProvider,\n params\n );\n\n // Apply queued method operations in sequence\n for (const [method, args] of Object.entries(this._queuedMethodOperations)) {\n if (\n method in initializedModel &&\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n typeof (initializedModel as any)[method] === \"function\"\n ) {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n initializedModel = await (initializedModel as any)[method](...args);\n }\n }\n\n // Cache and return the initialized model\n this._modelInstanceCache.set(cacheKey, initializedModel);\n return initializedModel;\n }\n\n async _generate(\n messages: BaseMessage[],\n options?: this[\"ParsedCallOptions\"],\n runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n const model = await this._getModelInstance(options);\n return model._generate(messages, options ?? {}, runManager);\n }\n\n override bindTools(\n tools: BindToolsInput[],\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n params?: Record<string, any>\n ): ConfigurableModel<RunInput, CallOptions> {\n const newQueuedOperations = { ...this._queuedMethodOperations };\n newQueuedOperations.bindTools = [tools, params];\n return new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: this._defaultConfig,\n configurableFields: this._configurableFields,\n configPrefix: this._configPrefix,\n queuedMethodOperations: newQueuedOperations,\n });\n }\n\n // Extract the input types from the `BaseModel` class.\n withStructuredOutput: BaseChatModel[\"withStructuredOutput\"] = (\n schema,\n ...args\n ): ReturnType<BaseChatModel[\"withStructuredOutput\"]> => {\n const newQueuedOperations = { ...this._queuedMethodOperations };\n newQueuedOperations.withStructuredOutput = [schema, ...args];\n return new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: this._defaultConfig,\n configurableFields: this._configurableFields,\n configPrefix: this._configPrefix,\n queuedMethodOperations: newQueuedOperations,\n }) as unknown as ReturnType<BaseChatModel[\"withStructuredOutput\"]>;\n };\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n _modelParams(config?: RunnableConfig): Record<string, any> {\n const configurable = config?.configurable ?? {};\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n let modelParams: Record<string, any> = {};\n\n for (const [key, value] of Object.entries(configurable)) {\n if (key.startsWith(this._configPrefix)) {\n const strippedKey = this._removePrefix(key, this._configPrefix);\n modelParams[strippedKey] = value;\n }\n }\n\n if (this._configurableFields !== \"any\") {\n modelParams = Object.fromEntries(\n Object.entries(modelParams).filter(([key]) =>\n this._configurableFields.includes(key)\n )\n );\n }\n\n return modelParams;\n }\n\n _removePrefix(str: string, prefix: string): string {\n return str.startsWith(prefix) ? str.slice(prefix.length) : str;\n }\n\n /**\n * Bind config to a Runnable, returning a new Runnable.\n * @param {RunnableConfig | undefined} [config] - The config to bind.\n * @returns {RunnableBinding<RunInput, RunOutput, CallOptions>} A new RunnableBinding with the bound config.\n */\n withConfig(\n config?: RunnableConfig\n ): RunnableBinding<RunInput, AIMessageChunk, CallOptions> {\n const mergedConfig: RunnableConfig = { ...(config || {}) };\n const modelParams = this._modelParams(mergedConfig);\n\n const remainingConfig: RunnableConfig = Object.fromEntries(\n Object.entries(mergedConfig).filter(([k]) => k !== \"configurable\")\n );\n\n remainingConfig.configurable = Object.fromEntries(\n Object.entries(mergedConfig.configurable || {}).filter(\n ([k]) =>\n this._configPrefix &&\n !Object.keys(modelParams).includes(\n this._removePrefix(k, this._configPrefix)\n )\n )\n );\n\n const newConfigurableModel = new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: { ...this._defaultConfig, ...modelParams },\n configurableFields: Array.isArray(this._configurableFields)\n ? [...this._configurableFields]\n : this._configurableFields,\n configPrefix: this._configPrefix,\n queuedMethodOperations: this._queuedMethodOperations,\n });\n\n return new RunnableBinding<RunInput, AIMessageChunk, CallOptions>({\n config: mergedConfig,\n bound: newConfigurableModel,\n });\n }\n\n async invoke(\n input: RunInput,\n options?: CallOptions\n ): Promise<AIMessageChunk> {\n const model = await this._getModelInstance(options);\n const config = ensureConfig(options);\n return model.invoke(input, config);\n }\n\n async stream(\n input: RunInput,\n options?: CallOptions\n ): Promise<IterableReadableStream<AIMessageChunk>> {\n const model = await this._getModelInstance(options);\n const wrappedGenerator = new AsyncGeneratorWithSetup({\n generator: await model.stream(input, options),\n config: options,\n });\n await wrappedGenerator.setup;\n return IterableReadableStream.fromAsyncGenerator(wrappedGenerator);\n }\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions & { returnExceptions?: false }\n ): Promise<AIMessageChunk[]>;\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions & { returnExceptions: true }\n ): Promise<(AIMessageChunk | Error)[]>;\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions\n ): Promise<(AIMessageChunk | Error)[]>;\n\n async batch(\n inputs: RunInput[],\n options?: Partial<CallOptions> | Partial<CallOptions>[],\n batchOptions?: RunnableBatchOptions\n ): Promise<(AIMessageChunk | Error)[]> {\n // We can super this since the base runnable implementation of\n // `.batch` will call `.invoke` on each input.\n return super.batch(inputs, options, batchOptions);\n }\n\n async *transform(\n generator: AsyncGenerator<RunInput>,\n options: CallOptions\n ): AsyncGenerator<AIMessageChunk> {\n const model = await this._getModelInstance(options);\n const config = ensureConfig(options);\n\n yield* model.transform(generator, config);\n }\n\n async *streamLog(\n input: RunInput,\n options?: Partial<CallOptions>,\n streamOptions?: Omit<LogStreamCallbackHandlerInput, \"autoClose\">\n ): AsyncGenerator<RunLogPatch> {\n const model = await this._getModelInstance(options);\n const config = ensureConfig(options);\n\n yield* model.streamLog(input, config, {\n ...streamOptions,\n _schemaFormat: \"original\",\n includeNames: streamOptions?.includeNames,\n includeTypes: streamOptions?.includeTypes,\n includeTags: streamOptions?.includeTags,\n excludeNames: streamOptions?.excludeNames,\n excludeTypes: streamOptions?.excludeTypes,\n excludeTags: streamOptions?.excludeTags,\n });\n }\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & { version: \"v2\" },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<StreamEvent>;\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & {\n version: \"v2\";\n encoding: \"text/event-stream\";\n },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<Uint8Array>;\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & { version: \"v1\" },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<StreamEvent>;\n\n /**\n * @deprecated Use {@link BaseChatModel.streamEvents} without a `version`\n * option for content-block streaming instead.\n */\n streamEvents(\n input: RunInput,\n options: Partial<CallOptions> & {\n version: \"v1\";\n encoding: \"text/event-stream\";\n },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): IterableReadableStream<Uint8Array>;\n\n streamEvents(\n input: RunInput,\n options?: Partial<CallOptions>\n ): ChatModelStream;\n\n streamEvents(\n input: RunInput,\n options?: Partial<CallOptions> & {\n version?: \"v1\" | \"v2\";\n encoding?: \"text/event-stream\" | undefined;\n },\n streamOptions?: Omit<EventStreamCallbackHandlerInput, \"autoClose\">\n ): ChatModelStream | IterableReadableStream<StreamEvent | Uint8Array> {\n if (options?.version === \"v1\" || options?.version === \"v2\") {\n const outerThis = this;\n const tracingCallOptions = options;\n async function* wrappedGenerator() {\n const model = await outerThis._getModelInstance(tracingCallOptions);\n const config = ensureConfig(tracingCallOptions);\n const tracingOptions = {\n ...config,\n version: tracingCallOptions.version,\n ...(tracingCallOptions.encoding !== undefined\n ? { encoding: tracingCallOptions.encoding }\n : {}),\n };\n let eventStream: IterableReadableStream<StreamEvent | Uint8Array>;\n if (\n tracingCallOptions.version === \"v1\" &&\n tracingCallOptions.encoding === \"text/event-stream\"\n ) {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & {\n version: \"v1\";\n encoding: \"text/event-stream\";\n },\n streamOptions\n );\n } else if (tracingCallOptions.version === \"v1\") {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & { version: \"v1\" },\n streamOptions\n );\n } else if (\n tracingCallOptions.version === \"v2\" &&\n tracingCallOptions.encoding === \"text/event-stream\"\n ) {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & {\n version: \"v2\";\n encoding: \"text/event-stream\";\n },\n streamOptions\n );\n } else {\n eventStream = model.streamEvents(\n input,\n tracingOptions as Partial<CallOptions> & { version: \"v2\" },\n streamOptions\n );\n }\n\n for await (const chunk of eventStream) {\n yield chunk;\n }\n }\n return IterableReadableStream.fromAsyncGenerator(wrappedGenerator());\n }\n\n const outerThis = this;\n async function* deferredEvents() {\n const model = await outerThis._getModelInstance(options);\n const config = ensureConfig(options);\n yield* model.streamEvents(input, config);\n }\n return new ChatModelStream(deferredEvents());\n }\n\n /**\n * Return profiling information for the model.\n *\n * @returns {ModelProfile} An object describing the model's capabilities and constraints\n */\n get profile(): ModelProfile {\n if (this._profile) {\n return this._profile;\n }\n const cacheKey = this._getCacheKey({});\n const instance = this._modelInstanceCache.get(cacheKey);\n return instance?.profile ?? {};\n }\n\n /** @internal */\n _getCacheKey(config?: RunnableConfig): string {\n let toStringify = config ?? {};\n if (toStringify.configurable) {\n const { configurable } = toStringify;\n const filtered: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(configurable)) {\n if (!k.startsWith(\"__pregel_\")) {\n filtered[k] = v;\n }\n }\n toStringify = { ...toStringify, configurable: filtered };\n }\n return JSON.stringify(toStringify);\n }\n}\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface InitChatModelFields extends Partial<Record<string, any>> {\n modelProvider?: string;\n configurableFields?: string[] | \"any\";\n configPrefix?: string;\n}\n\nexport type ConfigurableFields = \"any\" | string[];\n\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n fields?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: never;\n configPrefix?: string;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>>;\n\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model: never,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n options?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: never;\n configPrefix?: string;\n profile?: ModelProfile;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>>;\n\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model?: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n options?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: ConfigurableFields;\n configPrefix?: string;\n profile?: ModelProfile;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>>;\n\n// ################################# FOR CONTRIBUTORS #################################\n//\n// If adding support for a new provider, please append the provider\n// name to the supported list in the docstring below.\n//\n// ####################################################################################\n\n/**\n * Initialize a ChatModel from the model name and provider.\n * Must have the integration package corresponding to the model provider installed.\n *\n * @template {extends BaseLanguageModelInput = BaseLanguageModelInput} RunInput - The input type for the model.\n * @template {extends ConfigurableChatModelCallOptions = ConfigurableChatModelCallOptions} CallOptions - Call options for the model.\n *\n * @param {string | ChatModelProvider} [model] - The name of the model, e.g. \"gpt-4\", \"claude-3-opus-20240229\".\n * Can be prefixed with the model provider, e.g. \"openai:gpt-4\", \"anthropic:claude-3-opus-20240229\".\n * @param {Object} [fields] - Additional configuration options.\n * @param {string} [fields.modelProvider] - The model provider. Supported values include:\n * - openai (@langchain/openai)\n * - langsmith (@langchain/openai, via the [LangSmith LLM Gateway](https://docs.langchain.com/langsmith/llm-gateway))\n * - anthropic (@langchain/anthropic)\n * - azure_openai (@langchain/openai)\n * - google-vertexai (@langchain/google-vertexai)\n * - google-vertexai-web (@langchain/google-vertexai-web)\n * - google-genai (@langchain/google-genai)\n * - bedrock (@langchain/aws)\n * - cohere (@langchain/cohere)\n * - fireworks (@langchain/fireworks)\n * - together (@langchain/together-ai)\n * - mistralai (@langchain/mistralai)\n * - groq (@langchain/groq)\n * - ollama (@langchain/ollama)\n * - perplexity (@langchain/perplexity)\n * - cerebras (@langchain/cerebras)\n * - deepseek (@langchain/deepseek)\n * - xai (@langchain/xai)\n * @param {string[] | \"any\"} [fields.configurableFields] - Which model parameters are configurable:\n * - undefined: No configurable fields.\n * - \"any\": All fields are configurable. (See Security Note in description)\n * - string[]: Specified fields are configurable.\n * @param {string} [fields.configPrefix] - Prefix for configurable fields at runtime.\n * @param {ModelProfile} [fields.profile] - Overrides the profiling information for the model. If not provided,\n * the profile will be inferred from the inner model instance.\n * @param {Record<string, any>} [fields.params] - Additional keyword args to pass to the ChatModel constructor.\n * @returns {Promise<ConfigurableModel<RunInput, CallOptions>>} A class which extends BaseChatModel.\n * @throws {Error} If modelProvider cannot be inferred or isn't supported.\n * @throws {Error} If the model provider integration package is not installed.\n *\n * @example Initialize non-configurable models\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const gpt4 = await initChatModel(\"openai:gpt-4\", {\n * temperature: 0.25,\n * });\n * const gpt4Result = await gpt4.invoke(\"what's your name\");\n *\n * const claude = await initChatModel(\"anthropic:claude-3-opus-20240229\", {\n * temperature: 0.25,\n * });\n * const claudeResult = await claude.invoke(\"what's your name\");\n *\n * const gemini = await initChatModel(\"gemini-1.5-pro\", {\n * modelProvider: \"google-vertexai\",\n * temperature: 0.25,\n * });\n * const geminiResult = await gemini.invoke(\"what's your name\");\n * ```\n *\n * @example Create a partially configurable model with no default model\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const configurableModel = await initChatModel(undefined, {\n * temperature: 0,\n * configurableFields: [\"model\", \"apiKey\"],\n * });\n *\n * const gpt4Result = await configurableModel.invoke(\"what's your name\", {\n * configurable: {\n * model: \"gpt-4\",\n * },\n * });\n *\n * const claudeResult = await configurableModel.invoke(\"what's your name\", {\n * configurable: {\n * model: \"claude-sonnet-4-5-20250929\",\n * },\n * });\n * ```\n *\n * @example Create a fully configurable model with a default model and a config prefix\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const configurableModelWithDefault = await initChatModel(\"gpt-4\", {\n * modelProvider: \"openai\",\n * configurableFields: \"any\",\n * configPrefix: \"foo\",\n * temperature: 0,\n * });\n *\n * const openaiResult = await configurableModelWithDefault.invoke(\n * \"what's your name\",\n * {\n * configurable: {\n * foo_apiKey: process.env.OPENAI_API_KEY,\n * },\n * }\n * );\n *\n * const claudeResult = await configurableModelWithDefault.invoke(\n * \"what's your name\",\n * {\n * configurable: {\n * foo_model: \"claude-sonnet-4-5-20250929\",\n * foo_modelProvider: \"anthropic\",\n * foo_temperature: 0.6,\n * foo_apiKey: process.env.ANTHROPIC_API_KEY,\n * },\n * }\n * );\n * ```\n *\n * @example Bind tools to a configurable model:\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n * import { z } from \"zod/v3\";\n * import { tool } from \"@langchain/core/tools\";\n *\n * const getWeatherTool = tool(\n * (input) => {\n * // Do something with the input\n * return JSON.stringify(input);\n * },\n * {\n * schema: z\n * .object({\n * location: z\n * .string()\n * .describe(\"The city and state, e.g. San Francisco, CA\"),\n * })\n * .describe(\"Get the current weather in a given location\"),\n * name: \"GetWeather\",\n * description: \"Get the current weather in a given location\",\n * }\n * );\n *\n * const getPopulationTool = tool(\n * (input) => {\n * // Do something with the input\n * return JSON.stringify(input);\n * },\n * {\n * schema: z\n * .object({\n * location: z\n * .string()\n * .describe(\"The city and state, e.g. San Francisco, CA\"),\n * })\n * .describe(\"Get the current population in a given location\"),\n * name: \"GetPopulation\",\n * description: \"Get the current population in a given location\",\n * }\n * );\n *\n * const configurableModel = await initChatModel(\"gpt-4\", {\n * configurableFields: [\"model\", \"modelProvider\", \"apiKey\"],\n * temperature: 0,\n * });\n *\n * const configurableModelWithTools = configurableModel.bindTools([\n * getWeatherTool,\n * getPopulationTool,\n * ]);\n *\n * const configurableToolResult = await configurableModelWithTools.invoke(\n * \"Which city is hotter today and which is bigger: LA or NY?\",\n * {\n * configurable: {\n * apiKey: process.env.OPENAI_API_KEY,\n * },\n * }\n * );\n *\n * const configurableToolResult2 = await configurableModelWithTools.invoke(\n * \"Which city is hotter today and which is bigger: LA or NY?\",\n * {\n * configurable: {\n * model: \"claude-sonnet-4-5-20250929\",\n * apiKey: process.env.ANTHROPIC_API_KEY,\n * },\n * }\n * );\n * ```\n *\n * @example Initialize a model with a custom profile\n * ```typescript\n * import { initChatModel } from \"langchain/chat_models/universal\";\n *\n * const model = await initChatModel(\"gpt-4o-mini\", {\n * profile: {\n * maxInputTokens: 100000,\n * },\n * });\n *\n * @description\n * This function initializes a ChatModel based on the provided model name and provider.\n * It supports various model providers and allows for runtime configuration of model parameters.\n *\n * Security Note: Setting `configurableFields` to \"any\" means fields like apiKey, baseUrl, etc.\n * can be altered at runtime, potentially redirecting model requests to a different service/user.\n * Make sure that if you're accepting untrusted configurations, you enumerate the\n * `configurableFields` explicitly.\n *\n * The function will attempt to infer the model provider from the model name if not specified.\n * Certain model name prefixes are associated with specific providers:\n * - gpt-3... or gpt-4... -> openai\n * - claude... -> anthropic\n * - amazon.... -> bedrock\n * - gemini... -> google-vertexai\n * - command... -> cohere\n * - accounts/fireworks... -> fireworks\n *\n * @since 0.2.11\n * @version 0.2.11\n */\nexport async function initChatModel<\n RunInput extends BaseLanguageModelInput = BaseLanguageModelInput,\n CallOptions extends ConfigurableChatModelCallOptions =\n ConfigurableChatModelCallOptions,\n>(\n model?: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n fields?: Partial<Record<string, any>> & {\n modelProvider?: string;\n configurableFields?: string[] | \"any\";\n configPrefix?: string;\n profile?: ModelProfile;\n }\n): Promise<ConfigurableModel<RunInput, CallOptions>> {\n // oxlint-disable-next-line prefer-const\n let { configurableFields, configPrefix, modelProvider, profile, ...params } =\n {\n configPrefix: \"\",\n ...(fields ?? {}),\n };\n if (modelProvider === undefined && model?.includes(\":\")) {\n const [provider, ...remainingParts] = model.split(\":\");\n const modelComponents =\n remainingParts.length === 0\n ? [provider]\n : [provider, remainingParts.join(\":\")];\n if (SUPPORTED_PROVIDERS.includes(modelComponents[0] as ChatModelProvider)) {\n // oxlint-disable-next-line no-param-reassign\n [modelProvider, model] = modelComponents;\n }\n }\n let configurableFieldsCopy = Array.isArray(configurableFields)\n ? [...configurableFields]\n : configurableFields;\n\n if (!model && configurableFieldsCopy === undefined) {\n configurableFieldsCopy = [\"model\", \"modelProvider\"];\n }\n if (configPrefix && configurableFieldsCopy === undefined) {\n console.warn(\n `{ configPrefix: ${configPrefix} } has been set but no fields are configurable. Set ` +\n `{ configurableFields: [...] } to specify the model params that are ` +\n `configurable.`\n );\n }\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const paramsCopy: Record<string, any> = { ...params };\n\n let configurableModel: ConfigurableModel<RunInput, CallOptions>;\n\n if (configurableFieldsCopy === undefined) {\n configurableModel = new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: {\n ...paramsCopy,\n model,\n modelProvider,\n },\n configPrefix,\n profile,\n });\n } else {\n if (model) {\n paramsCopy.model = model;\n }\n if (modelProvider) {\n paramsCopy.modelProvider = modelProvider;\n }\n configurableModel = new ConfigurableModel<RunInput, CallOptions>({\n defaultConfig: paramsCopy,\n configPrefix,\n configurableFields: configurableFieldsCopy,\n profile,\n });\n }\n\n // Initialize the model instance to make sure a profile is available\n await configurableModel._getModelInstance();\n return configurableModel;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "langchain",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.9",
|
|
4
4
|
"description": "Typescript bindings for langchain",
|
|
5
5
|
"author": "LangChain",
|
|
6
6
|
"license": "MIT",
|
|
@@ -53,15 +53,15 @@
|
|
|
53
53
|
"typescript": "~7.0.2",
|
|
54
54
|
"vitest": "^4.1.8",
|
|
55
55
|
"yaml": "^2.9.0",
|
|
56
|
-
"@langchain/anthropic": "1.5.
|
|
57
|
-
"@langchain/aws": "1.4.
|
|
58
|
-
"@langchain/core": "^1.2.
|
|
59
|
-
"@langchain/fireworks": "0.2.
|
|
60
|
-
"@langchain/openai": "1.5.
|
|
56
|
+
"@langchain/anthropic": "1.5.6",
|
|
57
|
+
"@langchain/aws": "1.4.4",
|
|
58
|
+
"@langchain/core": "^1.2.8",
|
|
59
|
+
"@langchain/fireworks": "0.2.8",
|
|
60
|
+
"@langchain/openai": "1.5.8",
|
|
61
61
|
"@langchain/tsconfig": "0.0.1"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
-
"@langchain/core": "^1.2.
|
|
64
|
+
"@langchain/core": "^1.2.8"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"@langchain/langgraph": "^1.4.8",
|