Skip to content

Commit 6c40d00

Browse files
Revert "fix(@langchain/core): update and bundle dependencies (#9534)" (#9574)
Co-authored-by: Christian Bromann <git@bromann.dev>
1 parent 08148ae commit 6c40d00

File tree

11 files changed

+6449
-4876
lines changed

11 files changed

+6449
-4876
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@langchain/core": patch
3+
---
4+
5+
Revert "fix(@langchain/core): update and bundle dependencies (#9534)"

environment_tests/scripts/test-runner.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,12 @@ class EnvironmentTestRunner {
8282
* Copy a directory from src to dest, excluding files that match the excludePatterns
8383
* @param src - The source directory
8484
* @param dest - The destination directory
85-
* @param excludePatterns - An array of file names to exclude from the copy (only at the top level)
86-
* @param isTopLevel - Whether this is the top level call (used to only apply excludePatterns at root)
85+
* @param excludePatterns - An array of file names to exclude from the copy
8786
*/
8887
private async copyDirectory(
8988
src: string,
9089
dest: string,
91-
excludePatterns: string[] = [],
92-
isTopLevel: boolean = true
90+
excludePatterns: string[] = []
9391
): Promise<void> {
9492
await fs.mkdir(dest, { recursive: true });
9593

@@ -100,17 +98,13 @@ class EnvironmentTestRunner {
10098
const srcPath = path.join(src, entry.name);
10199
const destPath = path.join(dest, entry.name);
102100

103-
// Skip excluded patterns only at the top level
104-
// This allows dist/node_modules (bundled dependencies) to be copied
105-
if (
106-
isTopLevel &&
107-
excludePatterns.some((pattern) => entry.name === pattern)
108-
) {
101+
// Skip excluded patterns
102+
if (excludePatterns.some((pattern) => entry.name === pattern)) {
109103
return;
110104
}
111105

112106
if (entry.isDirectory()) {
113-
await this.copyDirectory(srcPath, destPath, excludePatterns, false);
107+
await this.copyDirectory(srcPath, destPath, excludePatterns);
114108
} else {
115109
await fs.copyFile(srcPath, destPath);
116110
}
@@ -233,10 +227,12 @@ class EnvironmentTestRunner {
233227
return;
234228
}
235229

236-
const destDirName: string =
237-
pkg.name === "langchain"
238-
? "langchain"
239-
: pkg.name.replace("@langchain/", "langchain-");
230+
let destDirName: string;
231+
if (pkg.name === "langchain") {
232+
destDirName = "langchain";
233+
} else {
234+
destDirName = pkg.name.replace("@langchain/", "langchain-");
235+
}
240236
const destDir = path.join(libsDir, destDirName);
241237
await fs.mkdir(destDir, { recursive: true });
242238

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,9 @@
11
import { langchainConfig, type ConfigArray } from "@langchain/eslint";
22

3-
/**
4-
* Packages bundled via `noExternal` in tsdown.config.ts.
5-
* These packages are ESM-only and bundled into the output for CJS compatibility.
6-
* They only need to be devDependencies, not runtime dependencies.
7-
* Listed here as core-modules so import/no-extraneous-dependencies ignores them.
8-
*/
9-
const bundledPackages = ["p-retry", "ansi-styles", "camelcase", "decamelize"];
10-
113
const config: ConfigArray = [
124
...langchainConfig,
135
{
146
ignores: ["src/utils/zod-to-json-schema/**"],
157
},
16-
{
17-
// Treat bundled packages as core modules so they don't need to be in dependencies
18-
settings: {
19-
"import/core-modules": bundledPackages,
20-
},
21-
},
228
];
239
export default config;

libs/langchain-core/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,14 @@
3131
"license": "MIT",
3232
"dependencies": {
3333
"@cfworker/json-schema": "^4.0.2",
34+
"ansi-styles": "^5.0.0",
35+
"camelcase": "6",
36+
"decamelize": "1.2.0",
3437
"js-tiktoken": "^1.0.12",
3538
"langsmith": "^0.3.64",
3639
"mustache": "^4.2.0",
37-
"p-queue": "^9.0.1",
40+
"p-queue": "^6.6.2",
41+
"p-retry": "^7.0.0",
3842
"uuid": "^10.0.0",
3943
"zod": "^3.25.76 || ^4"
4044
},
@@ -43,14 +47,10 @@
4347
"@types/decamelize": "^1.2.0",
4448
"@types/mustache": "^4",
4549
"@types/uuid": "^10.0.0",
46-
"ansi-styles": "^6.2.3",
47-
"camelcase": "^9.0.0",
48-
"decamelize": "^6.0.1",
4950
"dotenv": "^17.2.1",
5051
"dpdm": "^3.14.0",
5152
"eslint": "^9.34.0",
5253
"ml-matrix": "^6.10.4",
53-
"p-retry": "^7.0.0",
5454
"prettier": "^2.8.3",
5555
"rimraf": "^5.0.1",
5656
"typescript": "~5.8.3",
@@ -843,4 +843,4 @@
843843
"outputs.js"
844844
],
845845
"module": "./dist/index.js"
846-
}
846+
}

libs/langchain-core/src/callbacks/tests/callbacks.test.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,6 @@ test("CallbackManager Chat Message Handling", async () => {
242242
await llmCb.handleLLMEnd({ generations: [] });
243243
})
244244
);
245-
246-
// In case background mode is on while running this test
247-
await awaitAllCallbacks();
248-
249245
// Everything treated as llm in handler 1
250246
expect(handler1.llmStarts).toBe(1);
251247
expect(handler2.llmStarts).toBe(0);

libs/langchain-core/src/singletons/callbacks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import PQueueMod from "p-queue";
44
import { getGlobalAsyncLocalStorageInstance } from "./async_local_storage/globals.js";
55
import { getDefaultLangChainClientSingleton } from "./tracer.js";
66

7-
let queue: (typeof PQueueMod)["prototype"];
7+
let queue: typeof import("p-queue")["default"]["prototype"];
88

99
/**
1010
* Creates a queue using the p-queue library. The queue is configured to

libs/langchain-core/src/tracers/tests/__snapshots__/langchain_tracer.test.ts.snap

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,12 @@ exports[`LangChainTracer payload snapshots for run create and update 3`] = `
109109
"inputs": {
110110
"input": "test input",
111111
},
112-
"name": "RunnableLambda",
113112
"outputs": {
114113
"output": "processed: test input",
115114
},
116115
"parent_run_id": Any<String>,
117116
"reference_example_id": undefined,
118-
"run_type": "chain",
119117
"session_name": Any<String>,
120-
"start_time": Any<String>,
121118
"tags": [],
122119
"trace_id": Any<String>,
123120
}
@@ -144,15 +141,12 @@ exports[`LangChainTracer payload snapshots for run create and update 4`] = `
144141
"inputs": {
145142
"input": "test input",
146143
},
147-
"name": "RunnableLambda",
148144
"outputs": {
149145
"output": "parent: processed: test input",
150146
},
151147
"parent_run_id": undefined,
152148
"reference_example_id": undefined,
153-
"run_type": "chain",
154149
"session_name": Any<String>,
155-
"start_time": Any<String>,
156150
"tags": [],
157151
"trace_id": Any<String>,
158152
}

libs/langchain-core/src/tracers/tests/langchain_tracer.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ test("LangChainTracer payload snapshots for run create and update", async () =>
7373
expect(updatePayloads[0]).toMatchSnapshot({
7474
session_name: expect.any(String),
7575
dotted_order: expect.any(String),
76-
start_time: expect.any(String),
7776
end_time: expect.any(Number),
7877
events: expect.arrayContaining([
7978
expect.objectContaining({
@@ -87,7 +86,6 @@ test("LangChainTracer payload snapshots for run create and update", async () =>
8786
expect(updatePayloads[1]).toMatchSnapshot({
8887
session_name: expect.any(String),
8988
dotted_order: expect.any(String),
90-
start_time: expect.any(String),
9189
end_time: expect.any(Number),
9290
events: expect.arrayContaining([
9391
expect.objectContaining({

libs/langchain-core/src/utils/async_caller.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
import PQueueMod from "p-queue";
2-
import pRetry from "p-retry";
32

43
import { getAbortSignalError } from "./signal.js";
54

5+
// p-retry is ESM-only, so we use dynamic import for CJS compatibility.
6+
// The module is cached after first import, so subsequent calls are essentially free.
7+
// This approach is recommended by the p-retry author for async contexts:
8+
// https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
9+
let pRetryModule: typeof import("p-retry") | null = null;
10+
11+
async function getPRetry() {
12+
if (!pRetryModule) {
13+
pRetryModule = await import("p-retry");
14+
}
15+
return pRetryModule.default;
16+
}
17+
618
const STATUS_NO_RETRY = [
719
400, // Bad Request
820
401, // Unauthorized
@@ -107,6 +119,7 @@ export class AsyncCaller {
107119
callable: T,
108120
...args: Parameters<T>
109121
): Promise<Awaited<ReturnType<T>>> {
122+
const pRetry = await getPRetry();
110123
return this.queue.add(
111124
() =>
112125
pRetry(

libs/langchain-core/tsdown.config.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@ import {
77
} from "@langchain/build";
88

99
export default getBuildConfig({
10-
/**
11-
* bundling these packages into the output for CJS compatibility
12-
* they only need to be devDependencies, not runtime dependencies
13-
*/
14-
noExternal: [`ansi-styles`, `camelcase`, `decamelize`, `p-retry`],
1510
entry: [
1611
"./src/index.ts",
1712
"./src/agents.ts",

0 commit comments

Comments
 (0)