@langchain/langgraph-cli 0.0.6 → 0.0.8-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/dev.mjs CHANGED
@@ -37,11 +37,12 @@ builder
37
37
  });
38
38
  let hasOpenedFlag = false;
39
39
  let child = undefined;
40
+ let hostUrl = "https://smith.langchain.com";
40
41
  server.on("data", (data) => {
41
42
  const response = z.object({ queryParams: z.string() }).parse(data);
42
43
  if (options.browser && !hasOpenedFlag) {
43
44
  hasOpenedFlag = true;
44
- open(`https://smith.langchain.com/studio${response.queryParams}`);
45
+ open(`${hostUrl}/studio${response.queryParams}`);
45
46
  }
46
47
  });
47
48
  // check if .gitignore already contains .langgraph-api
@@ -78,20 +79,30 @@ builder
78
79
  const addedTarget = newWatch.filter((target) => !oldWatch.includes(target));
79
80
  const removedTarget = oldWatch.filter((target) => !newWatch.includes(target));
80
81
  watcher.unwatch(removedTarget).add(addedTarget);
81
- return { config, env };
82
+ try {
83
+ const { Client } = await import("langsmith");
84
+ const apiUrl = env?.["LANGSMITH_ENDPOINT"] ||
85
+ env?.["LANGCHAIN_ENDPOINT"] ||
86
+ undefined;
87
+ hostUrl = new Client({ apiUrl }).getHostUrl() || hostUrl;
88
+ }
89
+ catch {
90
+ // pass
91
+ }
92
+ return { config, env, hostUrl };
82
93
  };
83
94
  const launchServer = async () => {
84
- const { config, env } = await prepareContext();
95
+ const { config, env, hostUrl } = await prepareContext();
85
96
  if (child != null)
86
97
  child.kill();
87
98
  if ("python_version" in config) {
88
99
  logger.warn("Launching Python server from @langchain/langgraph-cli is experimental. Please use the `langgraph-cli` package from PyPi instead.");
89
100
  const { spawnPythonServer } = await import("./dev.python.mjs");
90
- child = await spawnPythonServer({ ...options, rest: args }, { configPath, config, env }, { pid, projectCwd });
101
+ child = await spawnPythonServer({ ...options, rest: args }, { configPath, config, env, hostUrl }, { pid, projectCwd });
91
102
  }
92
103
  else {
93
104
  const { spawnNodeServer } = await import("./dev.node.mjs");
94
- child = await spawnNodeServer({ ...options, rest: args }, { configPath, config, env }, { pid, projectCwd });
105
+ child = await spawnNodeServer({ ...options, rest: args }, { configPath, config, env, hostUrl }, { pid, projectCwd });
95
106
  }
96
107
  };
97
108
  watcher.on("all", async (_name, path) => {
@@ -3,7 +3,7 @@ import { spawn } from "node:child_process";
3
3
  import {} from "../utils/config.mjs";
4
4
  export async function spawnNodeServer(args, context, options) {
5
5
  const localUrl = `http://${args.host}:${args.port}`;
6
- const studioUrl = `https://smith.langchain.com/studio?baseUrl=${localUrl}`;
6
+ const studioUrl = `${context.hostUrl}/studio?baseUrl=${localUrl}`;
7
7
  console.log(`
8
8
  Welcome to
9
9
 
@@ -12,21 +12,6 @@ async function exists(path) {
12
12
  }
13
13
  }
14
14
  export async function assembleLocalDeps(configPath, config) {
15
- if ("node_version" in config) {
16
- const rebuildFiles = [];
17
- const workingDir = `/deps/${path.basename(path.dirname(configPath))}`;
18
- rebuildFiles.push(path.resolve(path.dirname(configPath), "package.json"));
19
- rebuildFiles.push(path.resolve(path.dirname(configPath), "package-lock.json"));
20
- rebuildFiles.push(path.resolve(path.dirname(configPath), "yarn.lock"));
21
- rebuildFiles.push(path.resolve(path.dirname(configPath), "pnpm-lock.yaml"));
22
- return {
23
- pipReqs: [],
24
- realPkgs: {},
25
- fauxPkgs: {},
26
- rebuildFiles,
27
- workingDir,
28
- };
29
- }
30
15
  const reserved = new Set([
31
16
  "src",
32
17
  "langgraph-api",
@@ -54,7 +39,8 @@ export async function assembleLocalDeps(configPath, config) {
54
39
  const rebuildFiles = [];
55
40
  let workingDir;
56
41
  let reloadDir;
57
- for (const localDep of config.dependencies) {
42
+ const dependencies = "dependencies" in config ? config.dependencies : [];
43
+ for (const localDep of dependencies) {
58
44
  if (!localDep.startsWith("."))
59
45
  continue;
60
46
  const resolved = path.resolve(path.dirname(configPath), localDep);
@@ -130,6 +116,19 @@ export async function assembleLocalDeps(configPath, config) {
130
116
  }
131
117
  }
132
118
  }
119
+ if ("node_version" in config) {
120
+ for (const name of [
121
+ "package.json",
122
+ "package-lock.json",
123
+ "yarn.lock",
124
+ "pnpm-lock.yaml",
125
+ "bun.lockb",
126
+ ]) {
127
+ const jsFile = path.resolve(path.dirname(configPath), name);
128
+ rebuildFiles.push(jsFile);
129
+ }
130
+ workingDir ??= `/deps/${path.basename(path.dirname(configPath))}`;
131
+ }
133
132
  return { pipReqs, realPkgs, fauxPkgs, workingDir, reloadDir, rebuildFiles };
134
133
  }
135
134
  async function updateGraphPaths(configPath, config, localDeps) {
@@ -168,30 +167,59 @@ async function updateGraphPaths(configPath, config, localDeps) {
168
167
  }
169
168
  }
170
169
  export function getBaseImage(config) {
171
- if ("python_version" in config) {
172
- return `langchain/langgraph-api:${config._INTERNAL_docker_tag || config.python_version}`;
173
- }
174
170
  if ("node_version" in config) {
175
171
  return `langchain/langgraphjs-api:${config._INTERNAL_docker_tag || config.node_version}`;
176
172
  }
177
- throw new Error("Invalid config type");
178
- }
179
- export async function configToDocker(configPath, config, localDeps, options) {
180
173
  if ("python_version" in config) {
181
- return pythonConfigToDocker(configPath, config, localDeps, options);
182
- }
183
- if ("node_version" in config) {
184
- return nodeConfigToDocker(configPath, config, localDeps, options);
174
+ return `langchain/langgraph-api:${config._INTERNAL_docker_tag || config.python_version}`;
185
175
  }
186
176
  throw new Error("Invalid config type");
187
177
  }
188
- export async function nodeConfigToDocker(configPath, config, localDeps, options) {
178
+ export async function configToDocker(configPath, config, localDeps, options) {
189
179
  // figure out the package manager used here
190
- const projectFolder = path.dirname(configPath);
191
180
  const testFile = async (file) => fs
192
- .stat(path.resolve(projectFolder, file))
181
+ .stat(path.resolve(path.dirname(configPath), file))
193
182
  .then((a) => a.isFile())
194
183
  .catch(() => false);
184
+ let pipInstall = `PYTHONDONTWRITEBYTECODE=1 pip install -c /api/constraints.txt`;
185
+ if ("python_version" in config && config.pip_config_file) {
186
+ pipInstall = `PIP_CONFIG_FILE=/pipconfig.txt ${pipInstall}`;
187
+ }
188
+ pipInstall = `--mount=type=cache,target=/root/.cache/pip ${pipInstall}`;
189
+ const pipConfigFile = "python_version" in config && config.pip_config_file
190
+ ? `ADD ${config.pip_config_file} /pipconfig.txt`
191
+ : undefined;
192
+ const _pypiDeps = "python_version" in config
193
+ ? config.dependencies.filter((dep) => !dep.startsWith("."))
194
+ : [];
195
+ await updateGraphPaths(configPath, config, localDeps);
196
+ const pipPkgs = _pypiDeps.length
197
+ ? `RUN ${pipInstall} ${_pypiDeps.join(" ")}`
198
+ : undefined;
199
+ const pipReqs = localDeps.pipReqs.map(([reqpath, destpath]) => `ADD ${reqpath} ${destpath}`);
200
+ if (pipReqs.length) {
201
+ pipReqs.push(`RUN ${pipInstall} ${localDeps.pipReqs.map(([, r]) => `-r ${r}`).join(" ")}`);
202
+ }
203
+ const localPkg = Object.entries(localDeps.realPkgs).map(([fullpath, relpath]) => `ADD ${relpath} /deps/${path.basename(fullpath)}`);
204
+ const fauxPkgs = Object.entries(localDeps.fauxPkgs).flatMap(([fullpath, [relpath, destpath]]) => [
205
+ `ADD ${relpath} ${destpath}`,
206
+ dedenter `
207
+ RUN set -ex && \
208
+ for line in '[project]' \
209
+ 'name = "${path.basename(fullpath)}"' \
210
+ 'version = "0.1"' \
211
+ '[tool.setuptools.package-data]' \
212
+ '"*" = ["**/*"]'; do \
213
+ echo "${options?.dockerCommand === "build" ? "$line" : "$$line"}" >> /deps/__outer_${path.basename(fullpath)}/pyproject.toml; \
214
+ done
215
+ `,
216
+ ]);
217
+ if (!pipReqs.length &&
218
+ !localPkg.length &&
219
+ !fauxPkgs.length &&
220
+ "node_version" in config) {
221
+ pipReqs.push(`ADD . ${localDeps.workingDir}`);
222
+ }
195
223
  const [npm, yarn, pnpm, bun] = await Promise.all([
196
224
  testFile("package-lock.json"),
197
225
  testFile("yarn.lock"),
@@ -213,94 +241,31 @@ export async function nodeConfigToDocker(configPath, config, localDeps, options)
213
241
  }
214
242
  const lines = [
215
243
  `FROM ${getBaseImage(config)}`,
216
- ...config.dockerfile_lines,
217
- `ADD . ${localDeps.workingDir}`,
218
- `RUN cd ${localDeps.workingDir} && ${installCmd}`,
219
- `ENV LANGSERVE_GRAPHS='${JSON.stringify(config.graphs)}'`,
220
- ...(config.store
221
- ? [`ENV LANGGRAPH_STORE='${JSON.stringify(config.store)}'`]
222
- : []),
223
- ...(config.auth
224
- ? [`ENV LANGGRAPH_AUTH='${JSON.stringify(config.auth)}'`]
225
- : []),
226
- `WORKDIR ${localDeps.workingDir}`,
227
- `RUN (test ! -f /api/langgraph_api/js/build.mts && echo "Prebuild script not found, skipping") || tsx /api/langgraph_api/js/build.mts`,
228
- ];
229
- if (options?.watch) {
230
- // TODO: hacky, should add as entrypoint to the langgraph-api base image
231
- lines.push(`CMD exec uvicorn langgraph_api.server:app --log-config /api/logging.json --no-access-log --host 0.0.0.0 --port 8000 --reload --reload-dir ${localDeps.workingDir}`);
232
- }
233
- return lines.filter(Boolean).join("\n");
234
- }
235
- export async function pythonConfigToDocker(configPath, config, localDeps, options) {
236
- let pipInstall = `PYTHONDONTWRITEBYTECODE=1 pip install -c /api/constraints.txt`;
237
- if (config.pip_config_file) {
238
- pipInstall = `PIP_CONFIG_FILE=/pipconfig.txt ${pipInstall}`;
239
- }
240
- pipInstall = `--mount=type=cache,target=/root/.cache/pip ${pipInstall}`;
241
- const pipConfigFileStr = config.pip_config_file
242
- ? [`ADD ${config.pip_config_file} /pipconfig.txt`].join("\n")
243
- : "";
244
- const pypiDeps = config.dependencies.filter((dep) => !dep.startsWith("."));
245
- await updateGraphPaths(configPath, config, localDeps);
246
- const pipPkgsStr = pypiDeps.length
247
- ? `RUN ${pipInstall} ${pypiDeps.join(" ")}`
248
- : "";
249
- let pipReqStr;
250
- if (localDeps.pipReqs.length) {
251
- const pipReqsStr = localDeps.pipReqs
252
- .map(([reqpath, destpath]) => `ADD ${reqpath} ${destpath}`)
253
- .join("\n");
254
- pipReqStr = `${pipReqsStr}\nRUN ${pipInstall} ${localDeps.pipReqs.map(([, r]) => `-r ${r}`)}`;
255
- }
256
- else {
257
- pipReqStr = "";
258
- }
259
- const localPkgStr = Object.entries(localDeps.realPkgs)
260
- .map(([fullpath, relpath]) => `ADD ${relpath} /deps/${path.basename(fullpath)}`)
261
- .join("\n");
262
- const fauxPkgsStr = Object.entries(localDeps.fauxPkgs)
263
- .map(([fullpath, [relpath, destpath]]) => {
264
- const x = dedenter `
265
- ADD ${relpath} ${destpath}
266
- RUN set -ex && \
267
- for line in '[project]' \
268
- 'name = "${path.basename(fullpath)}"' \
269
- 'version = "0.1"' \
270
- '[tool.setuptools.package-data]' \
271
- '"*" = ["**/*"]'; do \
272
- echo "${options?.dockerCommand === "build" ? "$line" : "$$line"}" >> /deps/__outer_${path.basename(fullpath)}/pyproject.toml; \
273
- done
274
- `;
275
- return x;
276
- })
277
- .join("\n");
278
- const lines = [
279
- `FROM ${getBaseImage(config)}`,
280
- ...config.dockerfile_lines,
281
- pipConfigFileStr,
282
- pipPkgsStr,
283
- pipReqStr,
284
- localPkgStr,
285
- fauxPkgsStr,
286
- `RUN ${pipInstall} -e /deps/*`,
244
+ config.dockerfile_lines,
245
+ pipConfigFile,
246
+ pipPkgs,
247
+ pipReqs,
248
+ localPkg,
249
+ fauxPkgs,
250
+ "python_version" in config ? `RUN ${pipInstall} -e /deps/*` : undefined,
287
251
  `ENV LANGSERVE_GRAPHS='${JSON.stringify(config.graphs)}'`,
288
- ...(config.store
289
- ? [`ENV LANGGRAPH_STORE='${JSON.stringify(config.store)}'`]
290
- : []),
291
- ...(config.auth
292
- ? [`ENV LANGGRAPH_AUTH='${JSON.stringify(config.auth)}'`]
293
- : []),
294
- localDeps.workingDir ? `WORKDIR ${localDeps.workingDir}` : null,
252
+ !!config.store && `ENV LANGGRAPH_STORE='${JSON.stringify(config.store)}'`,
253
+ !!config.auth && `ENV LANGGRAPH_AUTH='${JSON.stringify(config.auth)}'`,
254
+ !!localDeps.workingDir && `WORKDIR ${localDeps.workingDir}`,
255
+ "node_version" in config
256
+ ? [
257
+ `RUN ${installCmd}`,
258
+ `RUN (test ! -f /api/langgraph_api/js/build.mts && echo "Prebuild script not found, skipping") || tsx /api/langgraph_api/js/build.mts`,
259
+ ]
260
+ : undefined,
295
261
  ];
296
262
  if (options?.watch && (localDeps.workingDir || localDeps.reloadDir)) {
297
263
  // TODO: hacky, should add as entrypoint to the langgraph-api base image
298
264
  lines.push(`CMD exec uvicorn langgraph_api.server:app --log-config /api/logging.json --no-access-log --host 0.0.0.0 --port 8000 --reload --reload-dir ${localDeps.workingDir || localDeps.reloadDir}`);
299
265
  }
300
- return lines.filter(Boolean).join("\n");
266
+ return lines.flat().filter(Boolean).join("\n");
301
267
  }
302
- export async function configToWatch(configPath, config) {
303
- const localDeps = await assembleLocalDeps(configPath, config);
268
+ export async function configToWatch(configPath, config, localDeps) {
304
269
  const projectDir = path.dirname(configPath);
305
270
  const watch = [];
306
271
  const watchSources = "python_version" in config
@@ -367,7 +332,7 @@ export async function configToCompose(configPath, config, options) {
367
332
  });
368
333
  }
369
334
  if (options?.watch) {
370
- const watch = await configToWatch(configPath, config);
335
+ const watch = await configToWatch(configPath, config, localDeps);
371
336
  if (watch)
372
337
  result.develop = { watch };
373
338
  }
@@ -41,7 +41,9 @@ type Inspect<T> = T extends unknown
41
41
 
42
42
  type ReflectCompiled<T> = T extends { RunInput: infer S; RunOutput: infer U }
43
43
  ? { state: S; update: U }
44
- : never;
44
+ : T extends { "~InputType": infer InputType; "~OutputType": infer OutputType }
45
+ ? { state: OutputType; update: InputType }
46
+ : never;
45
47
 
46
48
  // @ts-expect-error
47
49
  type Reflect<T> =
package/dist/logging.mjs CHANGED
@@ -50,27 +50,32 @@ const formatStack = (stack) => {
50
50
  const [firstFile] = stacktraceParser(stack).filter((item) => !item.file?.split(path.sep).includes("node_modules") &&
51
51
  !item.file?.startsWith("node:"));
52
52
  if (firstFile?.file && firstFile?.lineNumber) {
53
- const filePath = firstFile.file;
54
- const line = firstFile.lineNumber;
55
- const column = firstFile.column ?? 0;
56
- const messageLines = stack.split("\n");
57
- const spliceIndex = messageLines.findIndex((i) => i.includes(filePath));
58
- const padding = " ".repeat(Math.max(0, messageLines[spliceIndex].indexOf("at")));
59
- const highlightCode = process.stdout.isTTY;
60
- let codeFrame = codeFrameColumns(readFileSync(filePath, "utf-8"), { start: { line, column } }, { highlightCode });
61
- codeFrame = codeFrame
62
- .split("\n")
63
- .map((i) => padding + i + "\x1b[0m")
64
- .join("\n");
65
- if (highlightCode) {
66
- codeFrame = "\x1b[36m" + codeFrame + "\x1b[31m";
53
+ try {
54
+ const filePath = firstFile.file;
55
+ const line = firstFile.lineNumber;
56
+ const column = firstFile.column ?? 0;
57
+ const messageLines = stack.split("\n");
58
+ const spliceIndex = messageLines.findIndex((i) => i.includes(filePath));
59
+ const padding = " ".repeat(Math.max(0, messageLines[spliceIndex].indexOf("at")));
60
+ const highlightCode = process.stdout.isTTY;
61
+ let codeFrame = codeFrameColumns(readFileSync(filePath, "utf-8"), { start: { line, column } }, { highlightCode });
62
+ codeFrame = codeFrame
63
+ .split("\n")
64
+ .map((i) => padding + i + "\x1b[0m")
65
+ .join("\n");
66
+ if (highlightCode) {
67
+ codeFrame = "\x1b[36m" + codeFrame + "\x1b[31m";
68
+ }
69
+ // insert codeframe after the line but dont lose the stack
70
+ return [
71
+ ...messageLines.slice(0, spliceIndex + 1),
72
+ codeFrame,
73
+ ...messageLines.slice(spliceIndex + 1),
74
+ ].join("\n");
75
+ }
76
+ catch {
77
+ // pass
67
78
  }
68
- // insert codeframe after the line but dont lose the stack
69
- return [
70
- ...messageLines.slice(0, spliceIndex + 1),
71
- codeFrame,
72
- ...messageLines.slice(spliceIndex + 1),
73
- ].join("\n");
74
79
  }
75
80
  return stack;
76
81
  };
@@ -1,47 +1,71 @@
1
1
  import { z } from "zod";
2
- const AuthConfigSchema = z.object({
3
- path: z.string().optional(),
4
- disable_studio_auth: z.boolean().default(false),
5
- });
6
- const IndexConfigSchema = z.object({
7
- dims: z.number().optional(),
8
- embed: z.string().optional(),
9
- fields: z.array(z.string()).optional(),
10
- });
11
- const StoreConfigSchema = z.object({
12
- index: IndexConfigSchema.optional(),
13
- });
2
+ import { extname } from "node:path";
14
3
  const BaseConfigSchema = z.object({
15
4
  docker_compose_file: z.string().optional(),
16
5
  dockerfile_lines: z.array(z.string()).default([]),
17
- graphs: z.record(z.string()),
6
+ graphs: z.record(z.string().refine((i) => i.includes(":"), {
7
+ message: "Import string must be in format '<file>:<export>'",
8
+ })),
9
+ _INTERNAL_docker_tag: z.string().optional(),
18
10
  env: z
19
11
  .union([z.array(z.string()), z.record(z.string()), z.string()])
20
12
  .default({}),
21
- store: StoreConfigSchema.optional(),
22
- _INTERNAL_docker_tag: z.string().optional(),
23
- auth: AuthConfigSchema.optional(),
13
+ store: z
14
+ .object({
15
+ index: z
16
+ .object({
17
+ dims: z.number().optional(),
18
+ embed: z.string().optional(),
19
+ fields: z.array(z.string()).optional(),
20
+ })
21
+ .optional(),
22
+ })
23
+ .optional(),
24
+ auth: z
25
+ .object({
26
+ path: z.string().optional(),
27
+ disable_studio_auth: z.boolean().default(false),
28
+ })
29
+ .optional(),
24
30
  });
31
+ const DEFAULT_PYTHON_VERSION = "3.11";
32
+ const DEFAULT_NODE_VERSION = "20";
33
+ const PYTHON_EXTENSIONS = [".py", ".pyx", ".pyd", ".pyi"];
34
+ const PythonVersionSchema = z.union([z.literal("3.11"), z.literal("3.12")]);
35
+ const NodeVersionSchema = z.literal("20");
25
36
  const PythonConfigSchema = BaseConfigSchema.merge(z.object({
26
- python_version: z
27
- .union([z.literal("3.11"), z.literal("3.12")])
28
- .default("3.11"),
29
37
  pip_config_file: z.string().optional(),
30
38
  dependencies: z
31
39
  .array(z.string())
32
40
  .nonempty("You need to specify at least one dependency"),
41
+ })).merge(z.object({
42
+ python_version: PythonVersionSchema.default(DEFAULT_PYTHON_VERSION),
43
+ node_version: NodeVersionSchema.optional(),
33
44
  }));
34
- const NodeConfigSchema = BaseConfigSchema.merge(z.object({ node_version: z.literal("20").default("20") }));
45
+ const NodeConfigSchema = BaseConfigSchema.merge(z.object({ node_version: NodeVersionSchema.default(DEFAULT_NODE_VERSION) }));
35
46
  const ConfigSchema = z.union([NodeConfigSchema, PythonConfigSchema]);
36
- import * as path from "node:path";
37
- const PYTHON_EXTENSIONS = [".py", ".pyx", ".pyd", ".pyi"];
38
47
  // TODO: implement this in Python CLI
39
48
  export const getConfig = (config) => {
40
- const rawConfig = typeof config === "string" ? JSON.parse(config) : config;
41
- const { graphs } = BaseConfigSchema.parse(rawConfig);
42
- const preferPython = Object.values(graphs).every((i) => PYTHON_EXTENSIONS.includes(path.extname(i.split(":")[0])));
43
- if (preferPython) {
44
- return z.union([PythonConfigSchema, NodeConfigSchema]).parse(rawConfig);
49
+ let input = typeof config === "string" ? JSON.parse(config) : config;
50
+ const { graphs } = BaseConfigSchema.parse(input);
51
+ const isPython = Object.values(graphs).map((i) => PYTHON_EXTENSIONS.includes(extname(i.split(":")[0])));
52
+ const somePython = isPython.some((i) => i);
53
+ const someNode = !isPython.every((i) => i);
54
+ const node_version = someNode
55
+ ? input.node_version || DEFAULT_NODE_VERSION
56
+ : undefined;
57
+ const python_version = somePython
58
+ ? input.python_version || (someNode ? "3.12" : DEFAULT_PYTHON_VERSION)
59
+ : undefined;
60
+ if (node_version && python_version && python_version !== "3.12") {
61
+ throw new Error("Only Python 3.12 is supported with Node.js");
45
62
  }
46
- return z.union([NodeConfigSchema, PythonConfigSchema]).parse(rawConfig);
63
+ input = { ...input, node_version, python_version };
64
+ if (!input.node_version)
65
+ delete input.node_version;
66
+ if (!input.python_version)
67
+ delete input.python_version;
68
+ if (python_version)
69
+ return PythonConfigSchema.parse(input);
70
+ return NodeConfigSchema.parse(input);
47
71
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph-cli",
3
- "version": "0.0.6",
3
+ "version": "0.0.8-dev.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -51,9 +51,9 @@
51
51
  "@babel/code-frame": "^7.26.2"
52
52
  },
53
53
  "peerDependencies": {
54
- "@langchain/core": "^0.3.27",
55
- "@langchain/langgraph": "^0.2.39",
56
- "@langchain/langgraph-checkpoint": "^0.0.13",
54
+ "@langchain/core": "^0.3.36",
55
+ "@langchain/langgraph": "^0.2.42",
56
+ "@langchain/langgraph-checkpoint": "^0.0.14",
57
57
  "typescript": "^5.5.4"
58
58
  },
59
59
  "devDependencies": {