@langchain/langgraph-sdk 0.0.46-experimental.0 → 0.0.47-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.
- package/dist/react/stream.cjs +21 -8
- package/dist/react/stream.d.ts +9 -1
- package/dist/react/stream.js +21 -8
- package/dist/react-ui/client.cjs +75 -34
- package/dist/react-ui/client.d.ts +45 -6
- package/dist/react-ui/client.js +72 -33
- package/dist/react-ui/index.cjs +8 -0
- package/dist/react-ui/index.d.ts +2 -0
- package/dist/react-ui/index.js +3 -0
- package/dist/react-ui/server/index.cjs +7 -0
- package/dist/react-ui/server/index.d.ts +2 -0
- package/dist/react-ui/server/index.js +2 -0
- package/dist/react-ui/{server.d.ts → server/server.d.ts} +2 -2
- package/package.json +12 -25
- package/react-ui/server.cjs +1 -1
- package/react-ui/server.d.cts +1 -1
- package/react-ui/server.d.ts +1 -1
- package/react-ui/server.js +1 -1
- package/react-ui.cjs +1 -0
- package/react-ui.d.cts +1 -0
- package/react-ui.d.ts +1 -0
- package/react-ui.js +1 -0
- package/react-ui/types.cjs +0 -1
- package/react-ui/types.d.cts +0 -1
- package/react-ui/types.d.ts +0 -1
- package/react-ui/types.js +0 -1
- /package/dist/react-ui/{server.cjs → server/server.cjs} +0 -0
- /package/dist/react-ui/{server.js → server/server.js} +0 -0
package/dist/react/stream.cjs
CHANGED
|
@@ -203,15 +203,25 @@ const useControllableThreadId = (options) => {
|
|
|
203
203
|
_setLocalThreadId(threadId);
|
|
204
204
|
onThreadIdRef.current?.(threadId);
|
|
205
205
|
}, []);
|
|
206
|
-
if (
|
|
206
|
+
if (!options || !("threadId" in options)) {
|
|
207
207
|
return [localThreadId, onThreadId];
|
|
208
208
|
}
|
|
209
|
-
return [options.threadId, onThreadId];
|
|
209
|
+
return [options.threadId ?? null, onThreadId];
|
|
210
210
|
};
|
|
211
211
|
function useStream(options) {
|
|
212
212
|
let { assistantId, messagesKey, onError, onFinish } = options;
|
|
213
213
|
messagesKey ??= "messages";
|
|
214
|
-
const client = (0, react_1.useMemo)(() => new client_js_1.Client({
|
|
214
|
+
const client = (0, react_1.useMemo)(() => new client_js_1.Client({
|
|
215
|
+
apiUrl: options.apiUrl,
|
|
216
|
+
apiKey: options.apiKey,
|
|
217
|
+
callerOptions: options.callerOptions,
|
|
218
|
+
defaultHeaders: options.defaultHeaders,
|
|
219
|
+
}), [
|
|
220
|
+
options.apiKey,
|
|
221
|
+
options.apiUrl,
|
|
222
|
+
options.callerOptions,
|
|
223
|
+
options.defaultHeaders,
|
|
224
|
+
]);
|
|
215
225
|
const [threadId, onThreadId] = useControllableThreadId(options);
|
|
216
226
|
const [branch, setBranch] = (0, react_1.useState)("");
|
|
217
227
|
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
|
|
@@ -221,9 +231,12 @@ function useStream(options) {
|
|
|
221
231
|
const submittingRef = (0, react_1.useRef)(false);
|
|
222
232
|
const abortRef = (0, react_1.useRef)(null);
|
|
223
233
|
const trackStreamModeRef = (0, react_1.useRef)([]);
|
|
224
|
-
const trackStreamMode = (0, react_1.useCallback)((mode) => {
|
|
225
|
-
|
|
226
|
-
trackStreamModeRef.current.
|
|
234
|
+
const trackStreamMode = (0, react_1.useCallback)((...mode) => {
|
|
235
|
+
for (const m of mode) {
|
|
236
|
+
if (!trackStreamModeRef.current.includes(m)) {
|
|
237
|
+
trackStreamModeRef.current.push(m);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
227
240
|
}, []);
|
|
228
241
|
const hasUpdateListener = options.onUpdateEvent != null;
|
|
229
242
|
const hasCustomListener = options.onCustomEvent != null;
|
|
@@ -445,11 +458,11 @@ function useStream(options) {
|
|
|
445
458
|
return interrupts.at(-1);
|
|
446
459
|
},
|
|
447
460
|
get messages() {
|
|
448
|
-
trackStreamMode("messages-tuple");
|
|
461
|
+
trackStreamMode("messages-tuple", "values");
|
|
449
462
|
return getMessages(values);
|
|
450
463
|
},
|
|
451
464
|
getMessagesMetadata(message, index) {
|
|
452
|
-
trackStreamMode("messages-tuple");
|
|
465
|
+
trackStreamMode("messages-tuple", "values");
|
|
453
466
|
return messageMetadata?.find((m) => m.messageId === (message.id ?? index));
|
|
454
467
|
},
|
|
455
468
|
};
|
package/dist/react/stream.d.ts
CHANGED
|
@@ -66,6 +66,14 @@ interface UseStreamOptions<StateType extends Record<string, unknown> = Record<st
|
|
|
66
66
|
* The API key to use.
|
|
67
67
|
*/
|
|
68
68
|
apiKey?: ClientConfig["apiKey"];
|
|
69
|
+
/**
|
|
70
|
+
* Custom call options, such as custom fetch implementation.
|
|
71
|
+
*/
|
|
72
|
+
callerOptions?: ClientConfig["callerOptions"];
|
|
73
|
+
/**
|
|
74
|
+
* Default headers to send with requests.
|
|
75
|
+
*/
|
|
76
|
+
defaultHeaders?: ClientConfig["defaultHeaders"];
|
|
69
77
|
/**
|
|
70
78
|
* Specify the key within the state that contains messages.
|
|
71
79
|
* Defaults to "messages".
|
|
@@ -102,7 +110,7 @@ interface UseStreamOptions<StateType extends Record<string, unknown> = Record<st
|
|
|
102
110
|
*/
|
|
103
111
|
onThreadId?: (threadId: string) => void;
|
|
104
112
|
}
|
|
105
|
-
interface UseStream<StateType extends Record<string, unknown> = Record<string, unknown>, Bag extends BagTemplate = BagTemplate> {
|
|
113
|
+
export interface UseStream<StateType extends Record<string, unknown> = Record<string, unknown>, Bag extends BagTemplate = BagTemplate> {
|
|
106
114
|
/**
|
|
107
115
|
* The current values of the thread.
|
|
108
116
|
*/
|
package/dist/react/stream.js
CHANGED
|
@@ -200,15 +200,25 @@ const useControllableThreadId = (options) => {
|
|
|
200
200
|
_setLocalThreadId(threadId);
|
|
201
201
|
onThreadIdRef.current?.(threadId);
|
|
202
202
|
}, []);
|
|
203
|
-
if (
|
|
203
|
+
if (!options || !("threadId" in options)) {
|
|
204
204
|
return [localThreadId, onThreadId];
|
|
205
205
|
}
|
|
206
|
-
return [options.threadId, onThreadId];
|
|
206
|
+
return [options.threadId ?? null, onThreadId];
|
|
207
207
|
};
|
|
208
208
|
export function useStream(options) {
|
|
209
209
|
let { assistantId, messagesKey, onError, onFinish } = options;
|
|
210
210
|
messagesKey ??= "messages";
|
|
211
|
-
const client = useMemo(() => new Client({
|
|
211
|
+
const client = useMemo(() => new Client({
|
|
212
|
+
apiUrl: options.apiUrl,
|
|
213
|
+
apiKey: options.apiKey,
|
|
214
|
+
callerOptions: options.callerOptions,
|
|
215
|
+
defaultHeaders: options.defaultHeaders,
|
|
216
|
+
}), [
|
|
217
|
+
options.apiKey,
|
|
218
|
+
options.apiUrl,
|
|
219
|
+
options.callerOptions,
|
|
220
|
+
options.defaultHeaders,
|
|
221
|
+
]);
|
|
212
222
|
const [threadId, onThreadId] = useControllableThreadId(options);
|
|
213
223
|
const [branch, setBranch] = useState("");
|
|
214
224
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -218,9 +228,12 @@ export function useStream(options) {
|
|
|
218
228
|
const submittingRef = useRef(false);
|
|
219
229
|
const abortRef = useRef(null);
|
|
220
230
|
const trackStreamModeRef = useRef([]);
|
|
221
|
-
const trackStreamMode = useCallback((mode) => {
|
|
222
|
-
|
|
223
|
-
trackStreamModeRef.current.
|
|
231
|
+
const trackStreamMode = useCallback((...mode) => {
|
|
232
|
+
for (const m of mode) {
|
|
233
|
+
if (!trackStreamModeRef.current.includes(m)) {
|
|
234
|
+
trackStreamModeRef.current.push(m);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
224
237
|
}, []);
|
|
225
238
|
const hasUpdateListener = options.onUpdateEvent != null;
|
|
226
239
|
const hasCustomListener = options.onCustomEvent != null;
|
|
@@ -442,11 +455,11 @@ export function useStream(options) {
|
|
|
442
455
|
return interrupts.at(-1);
|
|
443
456
|
},
|
|
444
457
|
get messages() {
|
|
445
|
-
trackStreamMode("messages-tuple");
|
|
458
|
+
trackStreamMode("messages-tuple", "values");
|
|
446
459
|
return getMessages(values);
|
|
447
460
|
},
|
|
448
461
|
getMessagesMetadata(message, index) {
|
|
449
|
-
trackStreamMode("messages-tuple");
|
|
462
|
+
trackStreamMode("messages-tuple", "values");
|
|
450
463
|
return messageMetadata?.find((m) => m.messageId === (message.id ?? index));
|
|
451
464
|
},
|
|
452
465
|
};
|
package/dist/react-ui/client.cjs
CHANGED
|
@@ -23,12 +23,27 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.LoadExternalComponent = void 0;
|
|
26
|
+
exports.bootstrapUiContext = exports.LoadExternalComponent = exports.useStreamContext = void 0;
|
|
27
27
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
28
|
+
const index_js_1 = require("../react/index.cjs");
|
|
28
29
|
const React = __importStar(require("react"));
|
|
29
30
|
const ReactDOM = __importStar(require("react-dom"));
|
|
30
31
|
const JsxRuntime = __importStar(require("react/jsx-runtime"));
|
|
31
32
|
const UseStreamContext = React.createContext(null);
|
|
33
|
+
function useStreamContext() {
|
|
34
|
+
const ctx = React.useContext(UseStreamContext);
|
|
35
|
+
if (!ctx) {
|
|
36
|
+
throw new Error("useStreamContext must be used within a LoadExternalComponent");
|
|
37
|
+
}
|
|
38
|
+
return new Proxy(ctx, {
|
|
39
|
+
get(target, prop) {
|
|
40
|
+
if (prop === "meta")
|
|
41
|
+
return target.meta;
|
|
42
|
+
return target.stream[prop];
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
exports.useStreamContext = useStreamContext;
|
|
32
47
|
class ComponentStore {
|
|
33
48
|
constructor() {
|
|
34
49
|
Object.defineProperty(this, "cache", {
|
|
@@ -50,63 +65,89 @@ class ComponentStore {
|
|
|
50
65
|
value: {}
|
|
51
66
|
});
|
|
52
67
|
}
|
|
53
|
-
respond(
|
|
54
|
-
this.cache[
|
|
55
|
-
this.callbacks[
|
|
68
|
+
respond(shadowRootId, comp, targetElement) {
|
|
69
|
+
this.cache[shadowRootId] = { comp, target: targetElement };
|
|
70
|
+
this.callbacks[shadowRootId]?.forEach((c) => c(comp, targetElement));
|
|
56
71
|
}
|
|
57
|
-
getBoundStore(
|
|
58
|
-
this.boundCache[
|
|
72
|
+
getBoundStore(shadowRootId) {
|
|
73
|
+
this.boundCache[shadowRootId] ??= {
|
|
59
74
|
subscribe: (onStoreChange) => {
|
|
60
|
-
this.callbacks[
|
|
61
|
-
this.callbacks[
|
|
75
|
+
this.callbacks[shadowRootId] ??= [];
|
|
76
|
+
this.callbacks[shadowRootId].push(onStoreChange);
|
|
62
77
|
return () => {
|
|
63
|
-
this.callbacks[
|
|
78
|
+
this.callbacks[shadowRootId] = this.callbacks[shadowRootId].filter((c) => c !== onStoreChange);
|
|
64
79
|
};
|
|
65
80
|
},
|
|
66
|
-
getSnapshot: () => this.cache[
|
|
81
|
+
getSnapshot: () => this.cache[shadowRootId],
|
|
67
82
|
};
|
|
68
|
-
return this.boundCache[
|
|
83
|
+
return this.boundCache[shadowRootId];
|
|
69
84
|
}
|
|
70
85
|
}
|
|
71
86
|
const COMPONENT_STORE = new ComponentStore();
|
|
87
|
+
const COMPONENT_PROMISE_CACHE = {};
|
|
72
88
|
const EXT_STORE_SYMBOL = Symbol.for("LGUI_EXT_STORE");
|
|
73
89
|
const REQUIRE_SYMBOL = Symbol.for("LGUI_REQUIRE");
|
|
74
|
-
function
|
|
90
|
+
function fetchComponent(apiUrl, assistantId, agentName) {
|
|
91
|
+
const cacheKey = `${apiUrl}-${assistantId}-${agentName}`;
|
|
92
|
+
if (COMPONENT_PROMISE_CACHE[cacheKey] != null) {
|
|
93
|
+
return COMPONENT_PROMISE_CACHE[cacheKey];
|
|
94
|
+
}
|
|
95
|
+
const request = fetch(`${apiUrl}/ui/${assistantId}`, {
|
|
96
|
+
headers: { Accept: "text/html", "Content-Type": "application/json" },
|
|
97
|
+
method: "POST",
|
|
98
|
+
body: JSON.stringify({ name: agentName }),
|
|
99
|
+
}).then((a) => a.text());
|
|
100
|
+
COMPONENT_PROMISE_CACHE[cacheKey] = request;
|
|
101
|
+
return request;
|
|
102
|
+
}
|
|
103
|
+
function LoadExternalComponent({ apiUrl = "http://localhost:2024", assistantId, stream, message, meta, fallback, ...props }) {
|
|
75
104
|
const ref = React.useRef(null);
|
|
76
105
|
const id = React.useId();
|
|
77
106
|
const shadowRootId = `child-shadow-${id}`;
|
|
78
107
|
const store = React.useMemo(() => COMPONENT_STORE.getBoundStore(shadowRootId), [shadowRootId]);
|
|
79
108
|
const state = React.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
80
109
|
React.useEffect(() => {
|
|
81
|
-
|
|
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) => {
|
|
110
|
+
fetchComponent(apiUrl, assistantId, message.name).then((html) => {
|
|
88
111
|
const dom = ref.current;
|
|
89
112
|
if (!dom)
|
|
90
113
|
return;
|
|
91
114
|
const root = dom.shadowRoot ?? dom.attachShadow({ mode: "open" });
|
|
92
|
-
const fragment = document
|
|
115
|
+
const fragment = document
|
|
116
|
+
.createRange()
|
|
117
|
+
.createContextualFragment(html.replace("{{shadowRootId}}", shadowRootId));
|
|
93
118
|
root.appendChild(fragment);
|
|
94
119
|
});
|
|
95
120
|
}, [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,
|
|
97
|
-
ReactDOM.createPortal(React.createElement(state.comp, message.content), state.target)
|
|
121
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { id: shadowRootId, ref: ref, ...props }), (0, jsx_runtime_1.jsx)(UseStreamContext.Provider, { value: { stream, meta }, children: state?.target != null
|
|
122
|
+
? ReactDOM.createPortal(React.createElement(state.comp, message.content), state.target)
|
|
123
|
+
: fallback })] }));
|
|
98
124
|
}
|
|
99
125
|
exports.LoadExternalComponent = LoadExternalComponent;
|
|
100
|
-
|
|
101
|
-
window
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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) };
|
|
126
|
+
function bootstrapUiContext() {
|
|
127
|
+
if (typeof window === "undefined") {
|
|
128
|
+
console.warn("Attempting to bootstrap UI context outside of browser environment. " +
|
|
129
|
+
"Avoid importing from `@langchain/langgraph-sdk/react-ui` in server context.");
|
|
130
|
+
return;
|
|
110
131
|
}
|
|
111
|
-
|
|
112
|
-
|
|
132
|
+
window[EXT_STORE_SYMBOL] = COMPONENT_STORE;
|
|
133
|
+
window[REQUIRE_SYMBOL] = (name) => {
|
|
134
|
+
if (name === "react")
|
|
135
|
+
return React;
|
|
136
|
+
if (name === "react-dom")
|
|
137
|
+
return ReactDOM;
|
|
138
|
+
if (name === "react/jsx-runtime")
|
|
139
|
+
return JsxRuntime;
|
|
140
|
+
if (name === "@langchain/langgraph-sdk/react")
|
|
141
|
+
return { useStream: index_js_1.useStream };
|
|
142
|
+
if (name === "@langchain/langgraph-sdk/react-ui") {
|
|
143
|
+
return {
|
|
144
|
+
useStreamContext,
|
|
145
|
+
LoadExternalComponent: () => {
|
|
146
|
+
throw new Error("Nesting LoadExternalComponent is not supported");
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
throw new Error(`Unknown module...: ${name}`);
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
exports.bootstrapUiContext = bootstrapUiContext;
|
|
@@ -1,7 +1,37 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useStream } from "../react/index.js";
|
|
2
2
|
import type { UIMessage } from "./types.js";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import * as JsxRuntime from "react/jsx-runtime";
|
|
5
|
+
import type { UseStream } from "../react/stream.js";
|
|
6
|
+
declare const UseStreamContext: React.Context<{
|
|
7
|
+
stream: UseStream<Record<string, unknown>, {
|
|
8
|
+
ConfigurableType?: Record<string, unknown> | undefined;
|
|
9
|
+
InterruptType?: unknown;
|
|
10
|
+
CustomEventType?: unknown;
|
|
11
|
+
UpdateType?: unknown;
|
|
12
|
+
}>;
|
|
13
|
+
meta: unknown;
|
|
14
|
+
}>;
|
|
15
|
+
type BagTemplate = {
|
|
16
|
+
ConfigurableType?: Record<string, unknown>;
|
|
17
|
+
InterruptType?: unknown;
|
|
18
|
+
CustomEventType?: unknown;
|
|
19
|
+
UpdateType?: unknown;
|
|
20
|
+
MetaType?: unknown;
|
|
21
|
+
};
|
|
22
|
+
type GetMetaType<Bag extends BagTemplate> = Bag extends {
|
|
23
|
+
MetaType: unknown;
|
|
24
|
+
} ? Bag["MetaType"] : unknown;
|
|
25
|
+
interface UseStreamContext<StateType extends Record<string, unknown> = Record<string, unknown>, Bag extends BagTemplate = BagTemplate> extends UseStream<StateType, Bag> {
|
|
26
|
+
meta?: GetMetaType<Bag>;
|
|
27
|
+
}
|
|
28
|
+
export declare function useStreamContext<StateType extends Record<string, unknown> = Record<string, unknown>, Bag extends {
|
|
29
|
+
ConfigurableType?: Record<string, unknown>;
|
|
30
|
+
InterruptType?: unknown;
|
|
31
|
+
CustomEventType?: unknown;
|
|
32
|
+
UpdateType?: unknown;
|
|
33
|
+
MetaType?: unknown;
|
|
34
|
+
} = BagTemplate>(): UseStreamContext<StateType, Bag>;
|
|
5
35
|
interface ComponentTarget {
|
|
6
36
|
comp: React.FunctionComponent | React.ComponentClass;
|
|
7
37
|
target: HTMLElement;
|
|
@@ -10,25 +40,34 @@ declare class ComponentStore {
|
|
|
10
40
|
private cache;
|
|
11
41
|
private boundCache;
|
|
12
42
|
private callbacks;
|
|
13
|
-
respond(
|
|
14
|
-
getBoundStore(
|
|
43
|
+
respond(shadowRootId: string, comp: React.FunctionComponent | React.ComponentClass, targetElement: HTMLElement): void;
|
|
44
|
+
getBoundStore(shadowRootId: string): {
|
|
15
45
|
subscribe: (onStoreChange: () => void) => () => void;
|
|
16
46
|
getSnapshot: () => ComponentTarget | undefined;
|
|
17
47
|
};
|
|
18
48
|
}
|
|
19
49
|
declare const EXT_STORE_SYMBOL: unique symbol;
|
|
20
50
|
declare const REQUIRE_SYMBOL: unique symbol;
|
|
21
|
-
|
|
51
|
+
interface LoadExternalComponentProps extends Pick<React.HTMLAttributes<HTMLDivElement>, "style" | "className"> {
|
|
52
|
+
/** API URL of the LangGraph Platform */
|
|
22
53
|
apiUrl?: string;
|
|
54
|
+
/** ID of the assistant */
|
|
23
55
|
assistantId: string;
|
|
56
|
+
/** Stream of the assistant */
|
|
24
57
|
stream: ReturnType<typeof useStream>;
|
|
58
|
+
/** UI message to be rendered */
|
|
25
59
|
message: UIMessage;
|
|
26
|
-
|
|
27
|
-
|
|
60
|
+
/** Additional context to be passed to the child component */
|
|
61
|
+
meta?: unknown;
|
|
62
|
+
/** Fallback to be rendered when the component is loading */
|
|
63
|
+
fallback?: React.ReactNode;
|
|
64
|
+
}
|
|
65
|
+
export declare function LoadExternalComponent({ apiUrl, assistantId, stream, message, meta, fallback, ...props }: LoadExternalComponentProps): JsxRuntime.JSX.Element;
|
|
28
66
|
declare global {
|
|
29
67
|
interface Window {
|
|
30
68
|
[EXT_STORE_SYMBOL]: ComponentStore;
|
|
31
69
|
[REQUIRE_SYMBOL]: (name: string) => unknown;
|
|
32
70
|
}
|
|
33
71
|
}
|
|
72
|
+
export declare function bootstrapUiContext(): void;
|
|
34
73
|
export {};
|
package/dist/react-ui/client.js
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useStream } from "../react/index.js";
|
|
2
3
|
import * as React from "react";
|
|
3
4
|
import * as ReactDOM from "react-dom";
|
|
4
5
|
import * as JsxRuntime from "react/jsx-runtime";
|
|
5
6
|
const UseStreamContext = React.createContext(null);
|
|
7
|
+
export function useStreamContext() {
|
|
8
|
+
const ctx = React.useContext(UseStreamContext);
|
|
9
|
+
if (!ctx) {
|
|
10
|
+
throw new Error("useStreamContext must be used within a LoadExternalComponent");
|
|
11
|
+
}
|
|
12
|
+
return new Proxy(ctx, {
|
|
13
|
+
get(target, prop) {
|
|
14
|
+
if (prop === "meta")
|
|
15
|
+
return target.meta;
|
|
16
|
+
return target.stream[prop];
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
}
|
|
6
20
|
class ComponentStore {
|
|
7
21
|
constructor() {
|
|
8
22
|
Object.defineProperty(this, "cache", {
|
|
@@ -24,62 +38,87 @@ class ComponentStore {
|
|
|
24
38
|
value: {}
|
|
25
39
|
});
|
|
26
40
|
}
|
|
27
|
-
respond(
|
|
28
|
-
this.cache[
|
|
29
|
-
this.callbacks[
|
|
41
|
+
respond(shadowRootId, comp, targetElement) {
|
|
42
|
+
this.cache[shadowRootId] = { comp, target: targetElement };
|
|
43
|
+
this.callbacks[shadowRootId]?.forEach((c) => c(comp, targetElement));
|
|
30
44
|
}
|
|
31
|
-
getBoundStore(
|
|
32
|
-
this.boundCache[
|
|
45
|
+
getBoundStore(shadowRootId) {
|
|
46
|
+
this.boundCache[shadowRootId] ??= {
|
|
33
47
|
subscribe: (onStoreChange) => {
|
|
34
|
-
this.callbacks[
|
|
35
|
-
this.callbacks[
|
|
48
|
+
this.callbacks[shadowRootId] ??= [];
|
|
49
|
+
this.callbacks[shadowRootId].push(onStoreChange);
|
|
36
50
|
return () => {
|
|
37
|
-
this.callbacks[
|
|
51
|
+
this.callbacks[shadowRootId] = this.callbacks[shadowRootId].filter((c) => c !== onStoreChange);
|
|
38
52
|
};
|
|
39
53
|
},
|
|
40
|
-
getSnapshot: () => this.cache[
|
|
54
|
+
getSnapshot: () => this.cache[shadowRootId],
|
|
41
55
|
};
|
|
42
|
-
return this.boundCache[
|
|
56
|
+
return this.boundCache[shadowRootId];
|
|
43
57
|
}
|
|
44
58
|
}
|
|
45
59
|
const COMPONENT_STORE = new ComponentStore();
|
|
60
|
+
const COMPONENT_PROMISE_CACHE = {};
|
|
46
61
|
const EXT_STORE_SYMBOL = Symbol.for("LGUI_EXT_STORE");
|
|
47
62
|
const REQUIRE_SYMBOL = Symbol.for("LGUI_REQUIRE");
|
|
48
|
-
|
|
63
|
+
function fetchComponent(apiUrl, assistantId, agentName) {
|
|
64
|
+
const cacheKey = `${apiUrl}-${assistantId}-${agentName}`;
|
|
65
|
+
if (COMPONENT_PROMISE_CACHE[cacheKey] != null) {
|
|
66
|
+
return COMPONENT_PROMISE_CACHE[cacheKey];
|
|
67
|
+
}
|
|
68
|
+
const request = fetch(`${apiUrl}/ui/${assistantId}`, {
|
|
69
|
+
headers: { Accept: "text/html", "Content-Type": "application/json" },
|
|
70
|
+
method: "POST",
|
|
71
|
+
body: JSON.stringify({ name: agentName }),
|
|
72
|
+
}).then((a) => a.text());
|
|
73
|
+
COMPONENT_PROMISE_CACHE[cacheKey] = request;
|
|
74
|
+
return request;
|
|
75
|
+
}
|
|
76
|
+
export function LoadExternalComponent({ apiUrl = "http://localhost:2024", assistantId, stream, message, meta, fallback, ...props }) {
|
|
49
77
|
const ref = React.useRef(null);
|
|
50
78
|
const id = React.useId();
|
|
51
79
|
const shadowRootId = `child-shadow-${id}`;
|
|
52
80
|
const store = React.useMemo(() => COMPONENT_STORE.getBoundStore(shadowRootId), [shadowRootId]);
|
|
53
81
|
const state = React.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
54
82
|
React.useEffect(() => {
|
|
55
|
-
|
|
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) => {
|
|
83
|
+
fetchComponent(apiUrl, assistantId, message.name).then((html) => {
|
|
62
84
|
const dom = ref.current;
|
|
63
85
|
if (!dom)
|
|
64
86
|
return;
|
|
65
87
|
const root = dom.shadowRoot ?? dom.attachShadow({ mode: "open" });
|
|
66
|
-
const fragment = document
|
|
88
|
+
const fragment = document
|
|
89
|
+
.createRange()
|
|
90
|
+
.createContextualFragment(html.replace("{{shadowRootId}}", shadowRootId));
|
|
67
91
|
root.appendChild(fragment);
|
|
68
92
|
});
|
|
69
93
|
}, [apiUrl, assistantId, message.name, shadowRootId]);
|
|
70
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { id: shadowRootId, ref: ref,
|
|
71
|
-
ReactDOM.createPortal(React.createElement(state.comp, message.content), state.target)
|
|
94
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { id: shadowRootId, ref: ref, ...props }), _jsx(UseStreamContext.Provider, { value: { stream, meta }, children: state?.target != null
|
|
95
|
+
? ReactDOM.createPortal(React.createElement(state.comp, message.content), state.target)
|
|
96
|
+
: fallback })] }));
|
|
72
97
|
}
|
|
73
|
-
|
|
74
|
-
window
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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) };
|
|
98
|
+
export function bootstrapUiContext() {
|
|
99
|
+
if (typeof window === "undefined") {
|
|
100
|
+
console.warn("Attempting to bootstrap UI context outside of browser environment. " +
|
|
101
|
+
"Avoid importing from `@langchain/langgraph-sdk/react-ui` in server context.");
|
|
102
|
+
return;
|
|
83
103
|
}
|
|
84
|
-
|
|
85
|
-
|
|
104
|
+
window[EXT_STORE_SYMBOL] = COMPONENT_STORE;
|
|
105
|
+
window[REQUIRE_SYMBOL] = (name) => {
|
|
106
|
+
if (name === "react")
|
|
107
|
+
return React;
|
|
108
|
+
if (name === "react-dom")
|
|
109
|
+
return ReactDOM;
|
|
110
|
+
if (name === "react/jsx-runtime")
|
|
111
|
+
return JsxRuntime;
|
|
112
|
+
if (name === "@langchain/langgraph-sdk/react")
|
|
113
|
+
return { useStream };
|
|
114
|
+
if (name === "@langchain/langgraph-sdk/react-ui") {
|
|
115
|
+
return {
|
|
116
|
+
useStreamContext,
|
|
117
|
+
LoadExternalComponent: () => {
|
|
118
|
+
throw new Error("Nesting LoadExternalComponent is not supported");
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
throw new Error(`Unknown module...: ${name}`);
|
|
123
|
+
};
|
|
124
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LoadExternalComponent = exports.useStreamContext = void 0;
|
|
4
|
+
const client_js_1 = require("./client.cjs");
|
|
5
|
+
(0, client_js_1.bootstrapUiContext)();
|
|
6
|
+
var client_js_2 = require("./client.cjs");
|
|
7
|
+
Object.defineProperty(exports, "useStreamContext", { enumerable: true, get: function () { return client_js_2.useStreamContext; } });
|
|
8
|
+
Object.defineProperty(exports, "LoadExternalComponent", { enumerable: true, get: function () { return client_js_2.LoadExternalComponent; } });
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uiMessageReducer = exports.typedUi = void 0;
|
|
4
|
+
var server_js_1 = require("./server.cjs");
|
|
5
|
+
Object.defineProperty(exports, "typedUi", { enumerable: true, get: function () { return server_js_1.typedUi; } });
|
|
6
|
+
var types_js_1 = require("../types.cjs");
|
|
7
|
+
Object.defineProperty(exports, "uiMessageReducer", { enumerable: true, get: function () { return types_js_1.uiMessageReducer; } });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef, ElementType } from "react";
|
|
2
|
-
import type { RemoveUIMessage, UIMessage } from "
|
|
2
|
+
import type { RemoveUIMessage, UIMessage } from "../types.js";
|
|
3
3
|
export declare const typedUi: <Decl extends Record<string, ElementType>>(config: {
|
|
4
4
|
writer?: (chunk: unknown) => void;
|
|
5
5
|
runId?: string;
|
|
@@ -9,6 +9,6 @@ export declare const typedUi: <Decl extends Record<string, ElementType>>(config:
|
|
|
9
9
|
}) => {
|
|
10
10
|
create: <K extends keyof Decl & string>(name: K, props: { [K_1 in keyof Decl]: ComponentPropsWithoutRef<Decl[K_1]>; }[K]) => UIMessage;
|
|
11
11
|
remove: (id: string) => RemoveUIMessage;
|
|
12
|
-
collect:
|
|
12
|
+
collect: (UIMessage | RemoveUIMessage)[];
|
|
13
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
14
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langchain/langgraph-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.47-experimental.0",
|
|
4
4
|
"description": "Client library for interacting with the LangGraph API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "yarn@1.22.19",
|
|
@@ -81,14 +81,14 @@
|
|
|
81
81
|
"import": "./react.js",
|
|
82
82
|
"require": "./react.cjs"
|
|
83
83
|
},
|
|
84
|
-
"./react-ui
|
|
84
|
+
"./react-ui": {
|
|
85
85
|
"types": {
|
|
86
|
-
"import": "./react-ui
|
|
87
|
-
"require": "./react-ui
|
|
88
|
-
"default": "./react-ui
|
|
86
|
+
"import": "./react-ui.d.ts",
|
|
87
|
+
"require": "./react-ui.d.cts",
|
|
88
|
+
"default": "./react-ui.d.ts"
|
|
89
89
|
},
|
|
90
|
-
"import": "./react-ui
|
|
91
|
-
"require": "./react-ui
|
|
90
|
+
"import": "./react-ui.js",
|
|
91
|
+
"require": "./react-ui.cjs"
|
|
92
92
|
},
|
|
93
93
|
"./react-ui/server": {
|
|
94
94
|
"types": {
|
|
@@ -99,15 +99,6 @@
|
|
|
99
99
|
"import": "./react-ui/server.js",
|
|
100
100
|
"require": "./react-ui/server.cjs"
|
|
101
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
|
-
},
|
|
111
102
|
"./package.json": "./package.json"
|
|
112
103
|
},
|
|
113
104
|
"files": [
|
|
@@ -124,17 +115,13 @@
|
|
|
124
115
|
"react.js",
|
|
125
116
|
"react.d.ts",
|
|
126
117
|
"react.d.cts",
|
|
127
|
-
"react-ui
|
|
128
|
-
"react-ui
|
|
129
|
-
"react-ui
|
|
130
|
-
"react-ui
|
|
118
|
+
"react-ui.cjs",
|
|
119
|
+
"react-ui.js",
|
|
120
|
+
"react-ui.d.ts",
|
|
121
|
+
"react-ui.d.cts",
|
|
131
122
|
"react-ui/server.cjs",
|
|
132
123
|
"react-ui/server.js",
|
|
133
124
|
"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"
|
|
125
|
+
"react-ui/server.d.cts"
|
|
139
126
|
]
|
|
140
127
|
}
|
package/react-ui/server.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = require('../dist/react-ui/server.cjs');
|
|
1
|
+
module.exports = require('../dist/react-ui/server/index.cjs');
|
package/react-ui/server.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from '../dist/react-ui/server.js'
|
|
1
|
+
export * from '../dist/react-ui/server/index.js'
|
package/react-ui/server.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from '../dist/react-ui/server.js'
|
|
1
|
+
export * from '../dist/react-ui/server/index.js'
|
package/react-ui/server.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from '../dist/react-ui/server.js'
|
|
1
|
+
export * from '../dist/react-ui/server/index.js'
|
package/react-ui.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./dist/react-ui/index.cjs');
|
package/react-ui.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/react-ui/index.js'
|
package/react-ui.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/react-ui/index.js'
|
package/react-ui.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/react-ui/index.js'
|
package/react-ui/types.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = require('../dist/react-ui/types.cjs');
|
package/react-ui/types.d.cts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from '../dist/react-ui/types.js'
|
package/react-ui/types.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from '../dist/react-ui/types.js'
|
package/react-ui/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from '../dist/react-ui/types.js'
|
|
File without changes
|
|
File without changes
|