@langchain/langgraph-api 0.0.14-experimental.1 → 0.0.14

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/server.mjs CHANGED
@@ -6,7 +6,6 @@ import runs from "./api/runs.mjs";
6
6
  import threads from "./api/threads.mjs";
7
7
  import assistants from "./api/assistants.mjs";
8
8
  import store from "./api/store.mjs";
9
- import ui, { registerGraphUi } from "./ui/load.mjs";
10
9
  import { truncate, conn as opsConn } from "./storage/ops.mjs";
11
10
  import { zValidator } from "@hono/zod-validator";
12
11
  import { z } from "zod";
@@ -32,7 +31,6 @@ app.route("/", assistants);
32
31
  app.route("/", runs);
33
32
  app.route("/", threads);
34
33
  app.route("/", store);
35
- app.route("/", ui);
36
34
  app.get("/info", (c) => c.json({ flags: { assistants: true, crons: false } }));
37
35
  app.post("/internal/truncate", zValidator("json", z.object({
38
36
  runs: z.boolean().optional(),
@@ -67,6 +65,13 @@ export async function startServer(options) {
67
65
  logger.info(`Registering graphs from ${options.cwd}`);
68
66
  await registerFromEnv(options.graphs, { cwd: options.cwd });
69
67
  if (options.ui) {
68
+ if (process.versions.node.startsWith("18")) {
69
+ // Not supported due to weird interop issues with `@tailwindcss/postcss` and `tsx`
70
+ throw new Error("Built-in UI is not supported in Node.js 18.x. Please upgrade to Node.js 20.16 or later.");
71
+ }
72
+ logger.info(`Loading UI`);
73
+ const { api, registerGraphUi } = await import("./ui/load.mjs");
74
+ app.route("/", api);
70
75
  logger.info(`Registering UI from ${options.cwd}`);
71
76
  await registerGraphUi(options.ui, { cwd: options.cwd });
72
77
  }
@@ -0,0 +1,9 @@
1
+ import { type BuildOptions } from "esbuild";
2
+ export declare function build(agentName: string, uiUserPath: string): Promise<{
3
+ basename: string;
4
+ contents: Uint8Array;
5
+ }[]>;
6
+ export declare function watch(agentName: string, uiUserPath: string, onResult: (result: {
7
+ basename: string;
8
+ contents: Uint8Array;
9
+ }[]) => void): Promise<import("esbuild").BuildContext<BuildOptions>>;
@@ -0,0 +1,81 @@
1
+ import * as path from "node:path";
2
+ import * as url from "node:url";
3
+ import * as fs from "node:fs";
4
+ import { build as runBuild, context as runContext, } from "esbuild";
5
+ import tailwind from "esbuild-plugin-tailwindcss";
6
+ const renderTemplate = await fs.promises.readFile(url.fileURLToPath(new URL("./render.template.mts", import.meta.url)), "utf-8");
7
+ function entrypointPlugin(uiUserPath) {
8
+ const projectDir = path.dirname(uiUserPath);
9
+ return {
10
+ name: "entrypoint",
11
+ setup(build) {
12
+ build.onResolve({ filter: /^entrypoint$/ }, (args) => ({
13
+ path: path.resolve(projectDir, "ui.entrypoint.tsx"),
14
+ namespace: "entrypoint-ns",
15
+ }));
16
+ build.onLoad({ filter: /.*/, namespace: "entrypoint-ns" }, () => ({
17
+ resolveDir: projectDir,
18
+ contents: [
19
+ `import ui from "${uiUserPath}"`,
20
+ renderTemplate,
21
+ `export const render = createRenderer(ui)`,
22
+ ].join("\n"),
23
+ loader: "tsx",
24
+ }));
25
+ },
26
+ };
27
+ }
28
+ function registerPlugin(onEnd) {
29
+ const textEncoder = new TextEncoder();
30
+ return {
31
+ name: "require-transform",
32
+ setup(build) {
33
+ build.onEnd(async (result) => {
34
+ const newResult = [];
35
+ for (const item of result.outputFiles ?? []) {
36
+ let basename = path.basename(item.path);
37
+ let contents = item.contents;
38
+ if (basename === "entrypoint.js") {
39
+ contents = textEncoder.encode(item.text.replaceAll(`typeof require !== "undefined" ? require`, `typeof globalThis[Symbol.for("LGUI_REQUIRE")] !== "undefined" ? globalThis[Symbol.for("LGUI_REQUIRE")]`));
40
+ }
41
+ newResult.push({ basename, contents });
42
+ }
43
+ if (newResult.length > 0)
44
+ onEnd(newResult);
45
+ });
46
+ },
47
+ };
48
+ }
49
+ function setup(agentName, uiUserPath, onResult) {
50
+ return {
51
+ write: false,
52
+ outdir: path.resolve(path.dirname(uiUserPath), "dist"),
53
+ entryPoints: ["entrypoint"],
54
+ bundle: true,
55
+ platform: "browser",
56
+ target: "es2020",
57
+ jsx: "automatic",
58
+ external: [
59
+ "react",
60
+ "react-dom",
61
+ "@langchain/langgraph-sdk",
62
+ "@langchain/langgraph-sdk/react-ui",
63
+ ],
64
+ plugins: [
65
+ tailwind(),
66
+ entrypointPlugin(uiUserPath),
67
+ registerPlugin(onResult),
68
+ ],
69
+ globalName: `__LGUI_${agentName}`,
70
+ };
71
+ }
72
+ export async function build(agentName, uiUserPath) {
73
+ let results = [];
74
+ await runBuild(setup(agentName, uiUserPath, (result) => (results = result)));
75
+ return results;
76
+ }
77
+ export async function watch(agentName, uiUserPath, onResult) {
78
+ const ctx = await runContext(setup(agentName, uiUserPath, onResult));
79
+ await ctx.watch();
80
+ return ctx;
81
+ }
package/dist/ui/load.mjs CHANGED
@@ -1,80 +1,21 @@
1
- import * as path from "node:path";
2
- import * as url from "node:url";
3
- import * as fs from "node:fs";
4
1
  import { z } from "zod";
5
2
  import { Hono } from "hono";
6
3
  import { getMimeType } from "hono/utils/mime";
7
4
  import { zValidator } from "@hono/zod-validator";
8
- import { context } from "esbuild";
9
- import tailwind from "esbuild-plugin-tailwindcss";
5
+ import * as path from "node:path";
6
+ import { watch } from "./bundler.mjs";
10
7
  const GRAPH_UI = {};
11
8
  export async function registerGraphUi(defs, options) {
12
- const textEncoder = new TextEncoder();
13
- const renderTemplate = await fs.promises.readFile(path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), "./render.template.mts"), "utf-8");
14
- const projectDir = options.cwd;
15
9
  const result = await Promise.all(Object.entries(defs).map(async ([agentName, uiUserPath]) => {
16
- const ctx = await context({
17
- entryPoints: ["entrypoint"],
18
- outdir: path.resolve(projectDir, "dist"),
19
- bundle: true,
20
- platform: "browser",
21
- target: "es2020",
22
- jsx: "automatic",
23
- external: [
24
- "react",
25
- "react-dom",
26
- "@langchain/langgraph-sdk",
27
- "@langchain/langgraph-sdk/react-ui",
28
- ],
29
- plugins: [
30
- {
31
- name: "entrypoint",
32
- setup(build) {
33
- build.onResolve({ filter: /^entrypoint$/ }, (args) => ({
34
- path: path.resolve(projectDir, "ui.entrypoint.tsx"),
35
- namespace: "entrypoint-ns",
36
- }));
37
- build.onLoad({ filter: /.*/, namespace: "entrypoint-ns" }, () => ({
38
- resolveDir: projectDir,
39
- contents: [
40
- `import ui from "${uiUserPath}"`,
41
- renderTemplate,
42
- `export const render = createRenderer(ui)`,
43
- ].join("\n"),
44
- loader: "tsx",
45
- }));
46
- },
47
- },
48
- tailwind(),
49
- {
50
- name: "require-transform",
51
- setup(build) {
52
- build.onEnd(async (result) => {
53
- const newResult = [];
54
- for (const item of result.outputFiles ?? []) {
55
- let basename = path.basename(item.path);
56
- let contents = item.contents;
57
- if (basename === "entrypoint.js") {
58
- contents = textEncoder.encode(item.text.replaceAll(`typeof require !== "undefined" ? require`, `typeof globalThis[Symbol.for("LGUI_REQUIRE")] !== "undefined" ? globalThis[Symbol.for("LGUI_REQUIRE")]`));
59
- }
60
- newResult.push({ basename, contents });
61
- }
62
- if (newResult.length > 0) {
63
- GRAPH_UI[agentName] = newResult;
64
- }
65
- });
66
- },
67
- },
68
- ],
69
- write: false,
70
- globalName: `__LGUI_${agentName}`,
10
+ const userPath = path.resolve(options.cwd, uiUserPath);
11
+ const ctx = await watch(agentName, userPath, (result) => {
12
+ GRAPH_UI[agentName] = result;
71
13
  });
72
- await ctx.watch();
73
14
  return [agentName, ctx];
74
15
  }));
75
16
  return Object.fromEntries(result);
76
17
  }
77
- const api = new Hono();
18
+ export const api = new Hono();
78
19
  api.post("/ui/:agent", zValidator("json", z.object({ name: z.string() })), async (c) => {
79
20
  const agent = c.req.param("agent");
80
21
  const host = c.req.header("host");
@@ -105,4 +46,3 @@ api.get("/ui/:agent/:basename", async (c) => {
105
46
  headers: { "Content-Type": getMimeType(file.basename) ?? "text/plain" },
106
47
  });
107
48
  });
108
- export default api;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph-api",
3
- "version": "0.0.14-experimental.1",
3
+ "version": "0.0.14",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": "^18.19.0 || >=20.16.0"
@@ -10,6 +10,16 @@
10
10
  "files": [
11
11
  "dist/"
12
12
  ],
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/cli/spawn.d.ts",
16
+ "default": "./dist/cli/spawn.mjs"
17
+ },
18
+ "./ui/bundler": {
19
+ "types": "./dist/ui/bundler.d.ts",
20
+ "default": "./dist/ui/bundler.mjs"
21
+ }
22
+ },
13
23
  "repository": {
14
24
  "type": "git",
15
25
  "url": "git@github.com:langchain-ai/langgraphjs-api.git"
@@ -28,8 +38,8 @@
28
38
  "open": "^10.1.0",
29
39
  "stacktrace-parser": "^0.1.10",
30
40
  "superjson": "^2.2.2",
31
- "tsx": "^4.19.2",
32
- "esbuild": "^0.23.1",
41
+ "tsx": "^4.19.3",
42
+ "esbuild": "^0.25.0",
33
43
  "esbuild-plugin-tailwindcss": "^2.0.1",
34
44
  "uuid": "^10.0.0",
35
45
  "winston": "^3.17.0",