@langchain/langgraph-cli 0.0.0-preview.7 → 0.0.0-preview.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/README.md +8 -8
- package/dist/api/runs.mjs +3 -3
- package/dist/cli/dev.mjs +2 -2
- package/dist/cli/utils/builder.mjs +1 -1
- package/dist/logging.mjs +51 -6
- package/dist/queue.mjs +11 -9
- package/dist/storage/checkpoint.mjs +4 -0
- package/dist/storage/store.mjs +4 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -12,36 +12,36 @@ npx @langchain/langgraph-cli
|
|
|
12
12
|
|
|
13
13
|
## Commands
|
|
14
14
|
|
|
15
|
-
### `
|
|
15
|
+
### `langgraphjs dev`
|
|
16
16
|
|
|
17
17
|
Run LangGraph.js API server in development mode with hot reloading.
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
langgraph dev
|
|
20
|
+
npx @langchain/langgraph-cli dev
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
### `
|
|
23
|
+
### `langgraphjs build`
|
|
24
24
|
|
|
25
25
|
Build a Docker image for your LangGraph.js application.
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
langgraph build
|
|
28
|
+
npx @langchain/langgraph-cli build
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
### `
|
|
31
|
+
### `langgraphjs up`
|
|
32
32
|
|
|
33
33
|
Run LangGraph.js API server in Docker.
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
langgraph up
|
|
36
|
+
npx @langchain/langgraph-cli up
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
### `
|
|
39
|
+
### `langgraphjs dockerfile`
|
|
40
40
|
|
|
41
41
|
Generate a Dockerfile for custom deployments
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
|
-
langgraph dockerfile <save path>
|
|
44
|
+
npx @langchain/langgraph-cli dockerfile <save path>
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
## Configuration
|
package/dist/api/runs.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { z } from "zod";
|
|
|
8
8
|
import { Runs, Threads } from "../storage/ops.mjs";
|
|
9
9
|
import { serialiseAsDict } from "../utils/serde.mjs";
|
|
10
10
|
import { getDisconnectAbortSignal, jsonExtra, waitKeepAlive, } from "../utils/hono.mjs";
|
|
11
|
-
import { logger } from "../logging.mjs";
|
|
11
|
+
import { logError, logger } from "../logging.mjs";
|
|
12
12
|
import { v4 as uuid4 } from "uuid";
|
|
13
13
|
const api = new Hono();
|
|
14
14
|
const createValidRun = async (threadId, payload) => {
|
|
@@ -115,7 +115,7 @@ api.post("/runs/stream", zValidator("json", schemas.RunCreate), async (c) => {
|
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
catch (error) {
|
|
118
|
-
|
|
118
|
+
logError(error, { prefix: "Error streaming run" });
|
|
119
119
|
}
|
|
120
120
|
});
|
|
121
121
|
});
|
|
@@ -179,7 +179,7 @@ api.post("/threads/:thread_id/runs/stream", zValidator("param", z.object({ threa
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
catch (error) {
|
|
182
|
-
|
|
182
|
+
logError(error, { prefix: "Error streaming run" });
|
|
183
183
|
}
|
|
184
184
|
});
|
|
185
185
|
});
|
package/dist/cli/dev.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { createIpcServer } from "./utils/ipc/server.mjs";
|
|
|
8
8
|
import { getProjectPath } from "./utils/project.mjs";
|
|
9
9
|
import { getConfig } from "../utils/config.mjs";
|
|
10
10
|
import { builder } from "./utils/builder.mjs";
|
|
11
|
-
import { logger } from "../logging.mjs";
|
|
11
|
+
import { logError, logger } from "../logging.mjs";
|
|
12
12
|
import { withAnalytics } from "./utils/analytics.mjs";
|
|
13
13
|
builder
|
|
14
14
|
.command("dev")
|
|
@@ -108,6 +108,6 @@ builder
|
|
|
108
108
|
});
|
|
109
109
|
}
|
|
110
110
|
catch (error) {
|
|
111
|
-
|
|
111
|
+
logError(error, { prefix: "Failed to launch server" });
|
|
112
112
|
}
|
|
113
113
|
});
|
package/dist/logging.mjs
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { createLogger, format, transports } from "winston";
|
|
2
2
|
import { logger as honoLogger } from "hono/logger";
|
|
3
3
|
import { consoleFormat } from "winston-console-format";
|
|
4
|
+
import { parse as stacktraceParser } from "stacktrace-parser";
|
|
5
|
+
import { readFileSync } from "fs";
|
|
6
|
+
import { codeFrameColumns } from "@babel/code-frame";
|
|
7
|
+
import path from "node:path";
|
|
4
8
|
const LOG_JSON = process.env.LOG_JSON === "true";
|
|
5
9
|
const LOG_LEVEL = process.env.LOG_LEVEL || "debug";
|
|
6
10
|
export const logger = createLogger({
|
|
@@ -38,13 +42,54 @@ export const logger = createLogger({
|
|
|
38
42
|
return JSON.stringify({ timestamp, level, event, ...rest });
|
|
39
43
|
}),
|
|
40
44
|
])),
|
|
41
|
-
transports: [
|
|
42
|
-
new transports.Console({
|
|
43
|
-
handleExceptions: true,
|
|
44
|
-
handleRejections: true,
|
|
45
|
-
}),
|
|
46
|
-
],
|
|
45
|
+
transports: [new transports.Console()],
|
|
47
46
|
});
|
|
47
|
+
const formatStack = (stack) => {
|
|
48
|
+
if (!stack)
|
|
49
|
+
return stack;
|
|
50
|
+
const [firstFile] = stacktraceParser(stack).filter((item) => !item.file?.split(path.sep).includes("node_modules") &&
|
|
51
|
+
!item.file?.startsWith("node:"));
|
|
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";
|
|
67
|
+
}
|
|
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
|
+
}
|
|
75
|
+
return stack;
|
|
76
|
+
};
|
|
77
|
+
export const logError = (error, options) => {
|
|
78
|
+
let message;
|
|
79
|
+
let context = options?.context;
|
|
80
|
+
if (error instanceof Error) {
|
|
81
|
+
message = formatStack(error.stack) || error.message;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
message = String(error);
|
|
85
|
+
context = { ...context, error };
|
|
86
|
+
}
|
|
87
|
+
if (options?.prefix != null)
|
|
88
|
+
message = `${options.prefix}:\n${message}`;
|
|
89
|
+
logger.error(message, ...(context != null ? [context] : []));
|
|
90
|
+
};
|
|
91
|
+
process.on("uncaughtException", (error) => logError(error));
|
|
92
|
+
process.on("unhandledRejection", (error) => logError(error));
|
|
48
93
|
export const requestLogger = () => honoLogger((message, ...rest) => {
|
|
49
94
|
logger.info(message, ...rest);
|
|
50
95
|
});
|
package/dist/queue.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Runs, Threads } from "./storage/ops.mjs";
|
|
2
2
|
import { streamState, } from "./stream.mjs";
|
|
3
|
-
import { logger } from "./logging.mjs";
|
|
3
|
+
import { logError, logger } from "./logging.mjs";
|
|
4
4
|
import { serializeError } from "./utils/serde.mjs";
|
|
5
5
|
const MAX_RETRY_ATTEMPTS = 3;
|
|
6
6
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -69,14 +69,16 @@ const worker = async (run, attempt, abortSignal) => {
|
|
|
69
69
|
const endedAt = new Date();
|
|
70
70
|
if (error instanceof Error)
|
|
71
71
|
exception = error;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
logError(error, {
|
|
73
|
+
prefix: "Background run failed",
|
|
74
|
+
context: {
|
|
75
|
+
run_id: run.run_id,
|
|
76
|
+
run_attempt: attempt,
|
|
77
|
+
run_created_at: run.created_at,
|
|
78
|
+
run_started_at: startedAt,
|
|
79
|
+
run_ended_at: endedAt,
|
|
80
|
+
run_exec_ms: endedAt.valueOf() - startedAt.valueOf(),
|
|
81
|
+
},
|
|
80
82
|
});
|
|
81
83
|
await Runs.setStatus(run.run_id, "error");
|
|
82
84
|
}
|
package/dist/storage/store.mjs
CHANGED
|
@@ -33,5 +33,9 @@ class InMemoryStore extends BaseMemoryStore {
|
|
|
33
33
|
async listNamespaces(...args) {
|
|
34
34
|
return await conn.with(() => super.listNamespaces(...args));
|
|
35
35
|
}
|
|
36
|
+
toJSON() {
|
|
37
|
+
// Prevent serialization of internal state
|
|
38
|
+
return "[InMemoryStore]";
|
|
39
|
+
}
|
|
36
40
|
}
|
|
37
41
|
export const store = new InMemoryStore();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langchain/langgraph-cli",
|
|
3
|
-
"version": "0.0.0-preview.
|
|
3
|
+
"version": "0.0.0-preview.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18"
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"license": "Elastic-2.0",
|
|
9
9
|
"main": "./dist/server.mjs",
|
|
10
10
|
"bin": {
|
|
11
|
-
"
|
|
11
|
+
"langgraphjs": "dist/cli/cli.mjs"
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"dist/"
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"hono": "^4.5.4",
|
|
40
40
|
"langsmith": "^0.2.15",
|
|
41
41
|
"open": "^10.1.0",
|
|
42
|
+
"stacktrace-parser": "^0.1.10",
|
|
42
43
|
"superjson": "^2.2.2",
|
|
43
44
|
"tar": "^7.4.3",
|
|
44
45
|
"tsx": "^4.19.2",
|
|
@@ -55,7 +56,9 @@
|
|
|
55
56
|
"typescript": "^5.5.4"
|
|
56
57
|
},
|
|
57
58
|
"devDependencies": {
|
|
59
|
+
"@babel/code-frame": "^7.26.2",
|
|
58
60
|
"@langchain/langgraph-sdk": "^0.0.33",
|
|
61
|
+
"@types/babel__code-frame": "^7.0.6",
|
|
59
62
|
"@types/node": "^22.2.0",
|
|
60
63
|
"@types/uuid": "^10.0.0",
|
|
61
64
|
"postgres": "^3.4.5",
|