@langchain/langgraph-sdk 0.0.45 → 0.0.46-experimental.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.
@@ -220,7 +220,7 @@ function useStream(options) {
220
220
  const messageManagerRef = (0, react_1.useRef)(new MessageTupleManager());
221
221
  const submittingRef = (0, react_1.useRef)(false);
222
222
  const abortRef = (0, react_1.useRef)(null);
223
- const trackStreamModeRef = (0, react_1.useRef)(["values"]);
223
+ const trackStreamModeRef = (0, react_1.useRef)([]);
224
224
  const trackStreamMode = (0, react_1.useCallback)((mode) => {
225
225
  if (!trackStreamModeRef.current.includes(mode))
226
226
  trackStreamModeRef.current.push(mode);
@@ -434,8 +434,13 @@ function useStream(options) {
434
434
  if (isLoading)
435
435
  return undefined;
436
436
  const interrupts = threadHead?.tasks?.at(-1)?.interrupts;
437
- if (interrupts == null || interrupts.length === 0)
438
- return undefined;
437
+ if (interrupts == null || interrupts.length === 0) {
438
+ // check if there's a next task present
439
+ const next = threadHead?.next ?? [];
440
+ if (!next.length || error != null)
441
+ return undefined;
442
+ return { when: "breakpoint" };
443
+ }
439
444
  // Return only the current interrupt
440
445
  return interrupts.at(-1);
441
446
  },
@@ -217,7 +217,7 @@ export function useStream(options) {
217
217
  const messageManagerRef = useRef(new MessageTupleManager());
218
218
  const submittingRef = useRef(false);
219
219
  const abortRef = useRef(null);
220
- const trackStreamModeRef = useRef(["values"]);
220
+ const trackStreamModeRef = useRef([]);
221
221
  const trackStreamMode = useCallback((mode) => {
222
222
  if (!trackStreamModeRef.current.includes(mode))
223
223
  trackStreamModeRef.current.push(mode);
@@ -431,8 +431,13 @@ export function useStream(options) {
431
431
  if (isLoading)
432
432
  return undefined;
433
433
  const interrupts = threadHead?.tasks?.at(-1)?.interrupts;
434
- if (interrupts == null || interrupts.length === 0)
435
- return undefined;
434
+ if (interrupts == null || interrupts.length === 0) {
435
+ // check if there's a next task present
436
+ const next = threadHead?.next ?? [];
437
+ if (!next.length || error != null)
438
+ return undefined;
439
+ return { when: "breakpoint" };
440
+ }
436
441
  // Return only the current interrupt
437
442
  return interrupts.at(-1);
438
443
  },
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.LoadExternalComponent = void 0;
27
+ const jsx_runtime_1 = require("react/jsx-runtime");
28
+ const React = __importStar(require("react"));
29
+ const ReactDOM = __importStar(require("react-dom"));
30
+ const JsxRuntime = __importStar(require("react/jsx-runtime"));
31
+ const UseStreamContext = React.createContext(null);
32
+ class ComponentStore {
33
+ constructor() {
34
+ Object.defineProperty(this, "cache", {
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true,
38
+ value: {}
39
+ });
40
+ Object.defineProperty(this, "boundCache", {
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true,
44
+ value: {}
45
+ });
46
+ Object.defineProperty(this, "callbacks", {
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ value: {}
51
+ });
52
+ }
53
+ respond(name, comp, targetElement) {
54
+ this.cache[name] = { comp, target: targetElement };
55
+ this.callbacks[name]?.forEach((c) => c(comp, targetElement));
56
+ }
57
+ getBoundStore(name) {
58
+ this.boundCache[name] ??= {
59
+ subscribe: (onStoreChange) => {
60
+ this.callbacks[name] ??= [];
61
+ this.callbacks[name].push(onStoreChange);
62
+ return () => {
63
+ this.callbacks[name] = this.callbacks[name].filter((c) => c !== onStoreChange);
64
+ };
65
+ },
66
+ getSnapshot: () => this.cache[name],
67
+ };
68
+ return this.boundCache[name];
69
+ }
70
+ }
71
+ const COMPONENT_STORE = new ComponentStore();
72
+ const EXT_STORE_SYMBOL = Symbol.for("LGUI_EXT_STORE");
73
+ const REQUIRE_SYMBOL = Symbol.for("LGUI_REQUIRE");
74
+ function LoadExternalComponent({ apiUrl = "http://localhost:2024", assistantId, stream, message, className, }) {
75
+ const ref = React.useRef(null);
76
+ const id = React.useId();
77
+ const shadowRootId = `child-shadow-${id}`;
78
+ const store = React.useMemo(() => COMPONENT_STORE.getBoundStore(shadowRootId), [shadowRootId]);
79
+ const state = React.useSyncExternalStore(store.subscribe, store.getSnapshot);
80
+ React.useEffect(() => {
81
+ fetch(`${apiUrl}/ui/${assistantId}`, {
82
+ headers: { "Content-Type": "application/json" },
83
+ method: "POST",
84
+ body: JSON.stringify({ name: message.name, shadowRootId }),
85
+ })
86
+ .then((a) => a.text())
87
+ .then((html) => {
88
+ const dom = ref.current;
89
+ if (!dom)
90
+ return;
91
+ const root = dom.shadowRoot ?? dom.attachShadow({ mode: "open" });
92
+ const fragment = document.createRange().createContextualFragment(html);
93
+ root.appendChild(fragment);
94
+ });
95
+ }, [apiUrl, assistantId, message.name, shadowRootId]);
96
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { id: shadowRootId, ref: ref, className: className }), (0, jsx_runtime_1.jsx)(UseStreamContext.Provider, { value: stream, children: state?.target &&
97
+ ReactDOM.createPortal(React.createElement(state.comp, message.content), state.target) })] }));
98
+ }
99
+ exports.LoadExternalComponent = LoadExternalComponent;
100
+ window[EXT_STORE_SYMBOL] = COMPONENT_STORE;
101
+ window[REQUIRE_SYMBOL] = (name) => {
102
+ if (name === "react")
103
+ return React;
104
+ if (name === "react-dom")
105
+ return ReactDOM;
106
+ if (name === "react/jsx-runtime")
107
+ return JsxRuntime;
108
+ if (name === "@langchain/langgraph-sdk/react") {
109
+ return { useStream: () => React.useContext(UseStreamContext) };
110
+ }
111
+ throw new Error(`Unknown module...: ${name}`);
112
+ };
@@ -0,0 +1,34 @@
1
+ import type { useStream } from "../react/index.js";
2
+ import type { UIMessage } from "./types.js";
3
+ import * as React from "react";
4
+ import * as JsxRuntime from "react/jsx-runtime";
5
+ interface ComponentTarget {
6
+ comp: React.FunctionComponent | React.ComponentClass;
7
+ target: HTMLElement;
8
+ }
9
+ declare class ComponentStore {
10
+ private cache;
11
+ private boundCache;
12
+ private callbacks;
13
+ respond(name: string, comp: React.FunctionComponent | React.ComponentClass, targetElement: HTMLElement): void;
14
+ getBoundStore(name: string): {
15
+ subscribe: (onStoreChange: () => void) => () => void;
16
+ getSnapshot: () => ComponentTarget | undefined;
17
+ };
18
+ }
19
+ declare const EXT_STORE_SYMBOL: unique symbol;
20
+ declare const REQUIRE_SYMBOL: unique symbol;
21
+ export declare function LoadExternalComponent({ apiUrl, assistantId, stream, message, className, }: {
22
+ apiUrl?: string;
23
+ assistantId: string;
24
+ stream: ReturnType<typeof useStream>;
25
+ message: UIMessage;
26
+ className?: string;
27
+ }): JsxRuntime.JSX.Element;
28
+ declare global {
29
+ interface Window {
30
+ [EXT_STORE_SYMBOL]: ComponentStore;
31
+ [REQUIRE_SYMBOL]: (name: string) => unknown;
32
+ }
33
+ }
34
+ export {};
@@ -0,0 +1,85 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import * as ReactDOM from "react-dom";
4
+ import * as JsxRuntime from "react/jsx-runtime";
5
+ const UseStreamContext = React.createContext(null);
6
+ class ComponentStore {
7
+ constructor() {
8
+ Object.defineProperty(this, "cache", {
9
+ enumerable: true,
10
+ configurable: true,
11
+ writable: true,
12
+ value: {}
13
+ });
14
+ Object.defineProperty(this, "boundCache", {
15
+ enumerable: true,
16
+ configurable: true,
17
+ writable: true,
18
+ value: {}
19
+ });
20
+ Object.defineProperty(this, "callbacks", {
21
+ enumerable: true,
22
+ configurable: true,
23
+ writable: true,
24
+ value: {}
25
+ });
26
+ }
27
+ respond(name, comp, targetElement) {
28
+ this.cache[name] = { comp, target: targetElement };
29
+ this.callbacks[name]?.forEach((c) => c(comp, targetElement));
30
+ }
31
+ getBoundStore(name) {
32
+ this.boundCache[name] ??= {
33
+ subscribe: (onStoreChange) => {
34
+ this.callbacks[name] ??= [];
35
+ this.callbacks[name].push(onStoreChange);
36
+ return () => {
37
+ this.callbacks[name] = this.callbacks[name].filter((c) => c !== onStoreChange);
38
+ };
39
+ },
40
+ getSnapshot: () => this.cache[name],
41
+ };
42
+ return this.boundCache[name];
43
+ }
44
+ }
45
+ const COMPONENT_STORE = new ComponentStore();
46
+ const EXT_STORE_SYMBOL = Symbol.for("LGUI_EXT_STORE");
47
+ const REQUIRE_SYMBOL = Symbol.for("LGUI_REQUIRE");
48
+ export function LoadExternalComponent({ apiUrl = "http://localhost:2024", assistantId, stream, message, className, }) {
49
+ const ref = React.useRef(null);
50
+ const id = React.useId();
51
+ const shadowRootId = `child-shadow-${id}`;
52
+ const store = React.useMemo(() => COMPONENT_STORE.getBoundStore(shadowRootId), [shadowRootId]);
53
+ const state = React.useSyncExternalStore(store.subscribe, store.getSnapshot);
54
+ React.useEffect(() => {
55
+ fetch(`${apiUrl}/ui/${assistantId}`, {
56
+ headers: { "Content-Type": "application/json" },
57
+ method: "POST",
58
+ body: JSON.stringify({ name: message.name, shadowRootId }),
59
+ })
60
+ .then((a) => a.text())
61
+ .then((html) => {
62
+ const dom = ref.current;
63
+ if (!dom)
64
+ return;
65
+ const root = dom.shadowRoot ?? dom.attachShadow({ mode: "open" });
66
+ const fragment = document.createRange().createContextualFragment(html);
67
+ root.appendChild(fragment);
68
+ });
69
+ }, [apiUrl, assistantId, message.name, shadowRootId]);
70
+ return (_jsxs(_Fragment, { children: [_jsx("div", { id: shadowRootId, ref: ref, className: className }), _jsx(UseStreamContext.Provider, { value: stream, children: state?.target &&
71
+ ReactDOM.createPortal(React.createElement(state.comp, message.content), state.target) })] }));
72
+ }
73
+ window[EXT_STORE_SYMBOL] = COMPONENT_STORE;
74
+ window[REQUIRE_SYMBOL] = (name) => {
75
+ if (name === "react")
76
+ return React;
77
+ if (name === "react-dom")
78
+ return ReactDOM;
79
+ if (name === "react/jsx-runtime")
80
+ return JsxRuntime;
81
+ if (name === "@langchain/langgraph-sdk/react") {
82
+ return { useStream: () => React.useContext(UseStreamContext) };
83
+ }
84
+ throw new Error(`Unknown module...: ${name}`);
85
+ };
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.typedUi = void 0;
4
+ const uuid_1 = require("uuid");
5
+ const typedUi = (config) => {
6
+ let collect = [];
7
+ const runId = config.metadata?.run_id ?? config.runId;
8
+ if (!runId)
9
+ throw new Error("run_id is required");
10
+ const metadata = {
11
+ ...config.metadata,
12
+ tags: config.tags,
13
+ name: config.runName,
14
+ run_id: runId,
15
+ };
16
+ const create = (name, props) => ({
17
+ type: "ui",
18
+ id: (0, uuid_1.v4)(),
19
+ name,
20
+ content: props,
21
+ additional_kwargs: metadata,
22
+ });
23
+ const remove = (id) => ({ type: "remove-ui", id });
24
+ return {
25
+ create,
26
+ remove,
27
+ collect,
28
+ write: (name, props) => {
29
+ const evt = create(name, props);
30
+ collect.push(evt);
31
+ config.writer?.(evt);
32
+ },
33
+ };
34
+ };
35
+ exports.typedUi = typedUi;
@@ -0,0 +1,14 @@
1
+ import type { ComponentPropsWithoutRef, ElementType } from "react";
2
+ import type { RemoveUIMessage, UIMessage } from "./types.js";
3
+ export declare const typedUi: <Decl extends Record<string, ElementType>>(config: {
4
+ writer?: (chunk: unknown) => void;
5
+ runId?: string;
6
+ metadata?: Record<string, unknown>;
7
+ tags?: string[];
8
+ runName?: string;
9
+ }) => {
10
+ create: <K extends keyof Decl & string>(name: K, props: { [K_1 in keyof Decl]: ComponentPropsWithoutRef<Decl[K_1]>; }[K]) => UIMessage;
11
+ remove: (id: string) => RemoveUIMessage;
12
+ collect: unknown[];
13
+ write: <K_2 extends keyof Decl & string>(name: K_2, props: { [K_1 in keyof Decl]: ComponentPropsWithoutRef<Decl[K_1]>; }[K_2]) => void;
14
+ };
@@ -0,0 +1,31 @@
1
+ import { v4 as uuidv4 } from "uuid";
2
+ export const typedUi = (config) => {
3
+ let collect = [];
4
+ const runId = config.metadata?.run_id ?? config.runId;
5
+ if (!runId)
6
+ throw new Error("run_id is required");
7
+ const metadata = {
8
+ ...config.metadata,
9
+ tags: config.tags,
10
+ name: config.runName,
11
+ run_id: runId,
12
+ };
13
+ const create = (name, props) => ({
14
+ type: "ui",
15
+ id: uuidv4(),
16
+ name,
17
+ content: props,
18
+ additional_kwargs: metadata,
19
+ });
20
+ const remove = (id) => ({ type: "remove-ui", id });
21
+ return {
22
+ create,
23
+ remove,
24
+ collect,
25
+ write: (name, props) => {
26
+ const evt = create(name, props);
27
+ collect.push(evt);
28
+ config.writer?.(evt);
29
+ },
30
+ };
31
+ };
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.uiMessageReducer = void 0;
4
+ function uiMessageReducer(state, update) {
5
+ const events = Array.isArray(update) ? update : [update];
6
+ let newState = state.slice();
7
+ for (const event of events) {
8
+ if (event.type === "remove-ui") {
9
+ newState = newState.filter((ui) => ui.id !== event.id);
10
+ continue;
11
+ }
12
+ const index = state.findIndex((ui) => ui.id === event.id);
13
+ if (index !== -1) {
14
+ newState[index] = event;
15
+ }
16
+ else {
17
+ newState.push(event);
18
+ }
19
+ }
20
+ return newState;
21
+ }
22
+ exports.uiMessageReducer = uiMessageReducer;
@@ -0,0 +1,15 @@
1
+ export interface UIMessage {
2
+ type: "ui";
3
+ id: string;
4
+ name: string;
5
+ content: Record<string, unknown>;
6
+ additional_kwargs: {
7
+ run_id: string;
8
+ [key: string]: unknown;
9
+ };
10
+ }
11
+ export interface RemoveUIMessage {
12
+ type: "remove-ui";
13
+ id: string;
14
+ }
15
+ export declare function uiMessageReducer(state: UIMessage[], update: UIMessage | RemoveUIMessage | (UIMessage | RemoveUIMessage)[]): UIMessage[];
@@ -0,0 +1,18 @@
1
+ export function uiMessageReducer(state, update) {
2
+ const events = Array.isArray(update) ? update : [update];
3
+ let newState = state.slice();
4
+ for (const event of events) {
5
+ if (event.type === "remove-ui") {
6
+ newState = newState.filter((ui) => ui.id !== event.id);
7
+ continue;
8
+ }
9
+ const index = state.findIndex((ui) => ui.id === event.id);
10
+ if (index !== -1) {
11
+ newState[index] = event;
12
+ }
13
+ else {
14
+ newState.push(event);
15
+ }
16
+ }
17
+ return newState;
18
+ }
package/dist/schema.d.ts CHANGED
@@ -104,9 +104,9 @@ export interface AssistantGraph {
104
104
  * An interrupt thrown inside a thread.
105
105
  */
106
106
  export interface Interrupt<TValue = unknown> {
107
- value: TValue;
108
- when: "during";
109
- resumable: boolean;
107
+ value?: TValue;
108
+ when: "during" | (string & {});
109
+ resumable?: boolean;
110
110
  ns?: string[];
111
111
  }
112
112
  export interface Thread<ValuesType = DefaultValues> {
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@langchain/langgraph-sdk",
3
- "version": "0.0.45",
3
+ "version": "0.0.46-experimental.0",
4
4
  "description": "Client library for interacting with the LangGraph API",
5
5
  "type": "module",
6
6
  "packageManager": "yarn@1.22.19",
7
7
  "scripts": {
8
8
  "clean": "rm -rf dist/ dist-cjs/",
9
9
  "build": "yarn clean && yarn lc_build --create-entrypoints --pre --tree-shaking",
10
- "prepublish": "yarn run build",
10
+ "prepack": "yarn run build",
11
11
  "format": "prettier --write src",
12
12
  "lint": "prettier --check src && tsc --noEmit",
13
13
  "test": "NODE_OPTIONS=--experimental-vm-modules jest --testPathIgnorePatterns=\\.int\\.test.ts",
@@ -29,7 +29,8 @@
29
29
  "@types/jest": "^29.5.12",
30
30
  "@types/node": "^20.12.12",
31
31
  "@types/uuid": "^9.0.1",
32
- "@types/react": "18.3.2",
32
+ "@types/react": "^19.0.8",
33
+ "@types/react-dom": "^19.0.3",
33
34
  "concat-md": "^0.5.1",
34
35
  "jest": "^29.7.0",
35
36
  "prettier": "^3.2.5",
@@ -37,7 +38,8 @@
37
38
  "typedoc": "^0.27.7",
38
39
  "typedoc-plugin-markdown": "^4.4.2",
39
40
  "typescript": "^5.4.5",
40
- "react": "^18.3.1"
41
+ "react": "^19.0.0",
42
+ "react-dom": "^19.0.0"
41
43
  },
42
44
  "peerDependencies": {
43
45
  "react": "^18 || ^19",
@@ -79,6 +81,33 @@
79
81
  "import": "./react.js",
80
82
  "require": "./react.cjs"
81
83
  },
84
+ "./react-ui/client": {
85
+ "types": {
86
+ "import": "./react-ui/client.d.ts",
87
+ "require": "./react-ui/client.d.cts",
88
+ "default": "./react-ui/client.d.ts"
89
+ },
90
+ "import": "./react-ui/client.js",
91
+ "require": "./react-ui/client.cjs"
92
+ },
93
+ "./react-ui/server": {
94
+ "types": {
95
+ "import": "./react-ui/server.d.ts",
96
+ "require": "./react-ui/server.d.cts",
97
+ "default": "./react-ui/server.d.ts"
98
+ },
99
+ "import": "./react-ui/server.js",
100
+ "require": "./react-ui/server.cjs"
101
+ },
102
+ "./react-ui/types": {
103
+ "types": {
104
+ "import": "./react-ui/types.d.ts",
105
+ "require": "./react-ui/types.d.cts",
106
+ "default": "./react-ui/types.d.ts"
107
+ },
108
+ "import": "./react-ui/types.js",
109
+ "require": "./react-ui/types.cjs"
110
+ },
82
111
  "./package.json": "./package.json"
83
112
  },
84
113
  "files": [
@@ -94,6 +123,18 @@
94
123
  "react.cjs",
95
124
  "react.js",
96
125
  "react.d.ts",
97
- "react.d.cts"
126
+ "react.d.cts",
127
+ "react-ui/client.cjs",
128
+ "react-ui/client.js",
129
+ "react-ui/client.d.ts",
130
+ "react-ui/client.d.cts",
131
+ "react-ui/server.cjs",
132
+ "react-ui/server.js",
133
+ "react-ui/server.d.ts",
134
+ "react-ui/server.d.cts",
135
+ "react-ui/types.cjs",
136
+ "react-ui/types.js",
137
+ "react-ui/types.d.ts",
138
+ "react-ui/types.d.cts"
98
139
  ]
99
140
  }
@@ -0,0 +1 @@
1
+ module.exports = require('../dist/react-ui/client.cjs');
@@ -0,0 +1 @@
1
+ export * from '../dist/react-ui/client.js'
@@ -0,0 +1 @@
1
+ export * from '../dist/react-ui/client.js'
@@ -0,0 +1 @@
1
+ export * from '../dist/react-ui/client.js'
@@ -0,0 +1 @@
1
+ module.exports = require('../dist/react-ui/server.cjs');
@@ -0,0 +1 @@
1
+ export * from '../dist/react-ui/server.js'
@@ -0,0 +1 @@
1
+ export * from '../dist/react-ui/server.js'
@@ -0,0 +1 @@
1
+ export * from '../dist/react-ui/server.js'
@@ -0,0 +1 @@
1
+ module.exports = require('../dist/react-ui/types.cjs');
@@ -0,0 +1 @@
1
+ export * from '../dist/react-ui/types.js'
@@ -0,0 +1 @@
1
+ export * from '../dist/react-ui/types.js'
@@ -0,0 +1 @@
1
+ export * from '../dist/react-ui/types.js'