@langgraph-js/sdk 2.0.1 → 3.0.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.
@@ -31,7 +31,7 @@ export declare const createChatStore: (initClientName: string, config: Partial<L
31
31
  onInit?: (client: LangGraphClient) => void;
32
32
  }) => {
33
33
  data: {
34
- client: import("nanostores").PreinitializedWritableAtom<LangGraphClient<unknown, unknown> | null> & object;
34
+ client: import("nanostores").PreinitializedWritableAtom<LangGraphClient<unknown> | null> & object;
35
35
  renderMessages: import("nanostores").PreinitializedWritableAtom<RenderMessage[]> & object;
36
36
  userInput: import("nanostores").PreinitializedWritableAtom<string> & object;
37
37
  loading: import("nanostores").PreinitializedWritableAtom<boolean> & object;
@@ -52,8 +52,8 @@ export declare const createChatStore: (initClientName: string, config: Partial<L
52
52
  refreshTools: () => Promise<void>;
53
53
  setTools(new_tools: UnionTool<any>[]): void;
54
54
  isFELocking(): boolean | undefined;
55
- initClient: () => Promise<LangGraphClient<unknown, unknown>>;
56
- sendMessage: (message?: Message[], extraData?: SendMessageOptions) => Promise<void>;
55
+ initClient: () => Promise<LangGraphClient<unknown>>;
56
+ sendMessage: (message?: Message[], extraData?: SendMessageOptions, withoutCheck?: boolean) => Promise<void>;
57
57
  stopGeneration: () => void;
58
58
  toggleToolCollapse: (toolId: string) => void;
59
59
  toggleHistoryVisible: () => void;
@@ -61,6 +61,11 @@ export declare const createChatStore: (initClientName: string, config: Partial<L
61
61
  addToHistory: (thread: Thread<{
62
62
  messages: Message[];
63
63
  }>) => void;
64
+ /**
65
+ * @zh 回滚到指定的消息。
66
+ * @en Reverts to the specified message.
67
+ */
68
+ revertChatTo(messageId: string, resend?: boolean, sendOptions?: SendMessageOptions): Promise<void>;
64
69
  /**
65
70
  * @zh 设置用户输入内容。
66
71
  * @en Sets the user input content.
@@ -158,15 +158,28 @@ export const createChatStore = (initClientName, config, context = {}) => {
158
158
  * @zh 发送消息。
159
159
  * @en Sends a message.
160
160
  */
161
- const sendMessage = async (message, extraData) => {
162
- var _a;
163
- if ((!userInput.get().trim() && !(message === null || message === void 0 ? void 0 : message.length)) || loading.get() || !client.get())
161
+ const sendMessage = async (message, extraData, withoutCheck = false) => {
162
+ var _a, _b;
163
+ if ((!withoutCheck && !userInput.get().trim() && !(message === null || message === void 0 ? void 0 : message.length)) || loading.get() || !client.get())
164
164
  return;
165
165
  loading.set(true);
166
166
  inChatError.set(null);
167
- await ((_a = client.get()) === null || _a === void 0 ? void 0 : _a.sendMessage(message || userInput.get(), extraData));
168
- userInput.set("");
169
- loading.set(false);
167
+ try {
168
+ await ((_a = client.get()) === null || _a === void 0 ? void 0 : _a.sendMessage(message || userInput.get(), extraData));
169
+ }
170
+ catch (e) {
171
+ const isThreadRunning = e.message.includes("422");
172
+ if (isThreadRunning) {
173
+ await ((_b = client.get()) === null || _b === void 0 ? void 0 : _b.resetStream());
174
+ }
175
+ else {
176
+ throw e;
177
+ }
178
+ }
179
+ finally {
180
+ userInput.set("");
181
+ loading.set(false);
182
+ }
170
183
  };
171
184
  /**
172
185
  * @zh 停止当前的消息生成。
@@ -259,6 +272,20 @@ export const createChatStore = (initClientName, config, context = {}) => {
259
272
  toggleHistoryVisible,
260
273
  refreshHistoryList,
261
274
  addToHistory,
275
+ /**
276
+ * @zh 回滚到指定的消息。
277
+ * @en Reverts to the specified message.
278
+ */
279
+ async revertChatTo(messageId, resend = false, sendOptions) {
280
+ var _a;
281
+ await ((_a = client.get()) === null || _a === void 0 ? void 0 : _a.revertChatTo(messageId));
282
+ if (resend) {
283
+ return sendMessage([], sendOptions, true);
284
+ }
285
+ else {
286
+ updateUI(client.get());
287
+ }
288
+ },
262
289
  /**
263
290
  * @zh 设置用户输入内容。
264
291
  * @en Sets the user input content.
@@ -0,0 +1,161 @@
1
+ import { type PropType, Ref } from "vue";
2
+ import { createChatStore } from "../ui-store/index.js";
3
+ import { PreinitializedWritableAtom, StoreValue } from "nanostores";
4
+ /**
5
+ * @zh UnionStore 类型用于合并 store 的 data 和 mutations,使其可以直接访问。
6
+ * @en The UnionStore type is used to merge the data and mutations of a store, allowing direct access.
7
+ */
8
+ export type UnionStoreVue<T extends {
9
+ data: Record<string, PreinitializedWritableAtom<any>>;
10
+ mutations: Record<string, any>;
11
+ }> = {
12
+ [k in keyof T["data"]]: Readonly<Ref<StoreValue<T["data"][k]>>>;
13
+ } & T["mutations"];
14
+ /**
15
+ * @zh useUnionStore Hook 用于将 nanostores 的 store 结构转换为更易于在 UI 组件中使用的扁平结构。
16
+ * @en The useUnionStore Hook is used to transform the nanostores store structure into a flatter structure that is easier to use in UI components.
17
+ */
18
+ export declare const useUnionStoreVue: <T extends {
19
+ data: Record<string, any>;
20
+ mutations: Record<string, any>;
21
+ }>(store: T, useStore: (store: PreinitializedWritableAtom<any>) => Readonly<Ref<any>>) => UnionStoreVue<T>;
22
+ /**
23
+ * 使用 Chat Store 的组合式函数
24
+ * @throws {Error} 如果在 ChatProvider 外部使用会抛出错误
25
+ */
26
+ export declare const useChat: () => UnionStoreVue<ReturnType<typeof createChatStore>>;
27
+ export interface ChatProviderProps {
28
+ defaultAgent?: string;
29
+ apiUrl?: string;
30
+ defaultHeaders?: Record<string, string>;
31
+ withCredentials?: boolean;
32
+ showHistory?: boolean;
33
+ showGraph?: boolean;
34
+ onInitError?: (error: any, currentAgent: string) => void;
35
+ }
36
+ /**
37
+ * @zh Chat Provider Hook,用于在 setup 中直接使用
38
+ * @en Chat Provider Hook, used directly in setup
39
+ */
40
+ export declare const useChatProvider: (props: ChatProviderProps) => {
41
+ unionStore: UnionStoreVue<{
42
+ data: {
43
+ client: PreinitializedWritableAtom<import("../LangGraphClient.js").LangGraphClient<unknown> | null> & object;
44
+ renderMessages: PreinitializedWritableAtom<import("../LangGraphClient.js").RenderMessage[]> & object;
45
+ userInput: PreinitializedWritableAtom<string> & object;
46
+ loading: PreinitializedWritableAtom<boolean> & object;
47
+ inChatError: PreinitializedWritableAtom<string | null> & object;
48
+ currentAgent: PreinitializedWritableAtom<string> & object;
49
+ collapsedTools: PreinitializedWritableAtom<string[]> & object;
50
+ showHistory: PreinitializedWritableAtom<boolean> & object;
51
+ historyList: PreinitializedWritableAtom<import("@langchain/langgraph-sdk").Thread<{
52
+ messages: import("@langchain/langgraph-sdk").Message[];
53
+ }>[]> & object;
54
+ currentChatId: PreinitializedWritableAtom<string | null> & object;
55
+ showGraph: PreinitializedWritableAtom<boolean> & object;
56
+ graphVisualize: PreinitializedWritableAtom<import("@langchain/langgraph-sdk").AssistantGraph | null> & object;
57
+ currentNodeName: PreinitializedWritableAtom<string> & object;
58
+ tools: PreinitializedWritableAtom<import("../index.js").UnionTool<any, Object, any>[]> & object;
59
+ };
60
+ mutations: {
61
+ refreshTools: () => Promise<void>;
62
+ setTools(new_tools: import("../index.js").UnionTool<any>[]): void;
63
+ isFELocking(): boolean | undefined;
64
+ initClient: () => Promise<import("../LangGraphClient.js").LangGraphClient<unknown>>;
65
+ sendMessage: (message?: import("@langchain/langgraph-sdk").Message[], extraData?: import("../LangGraphClient.js").SendMessageOptions, withoutCheck?: boolean) => Promise<void>;
66
+ stopGeneration: () => void;
67
+ toggleToolCollapse: (toolId: string) => void;
68
+ toggleHistoryVisible: () => void;
69
+ refreshHistoryList: () => Promise<void>;
70
+ addToHistory: (thread: import("@langchain/langgraph-sdk").Thread<{
71
+ messages: import("@langchain/langgraph-sdk").Message[];
72
+ }>) => void;
73
+ revertChatTo(messageId: string, resend?: boolean, sendOptions?: import("../LangGraphClient.js").SendMessageOptions): Promise<void>;
74
+ setUserInput(input: string): void;
75
+ setCurrentAgent(agent: string): Promise<void>;
76
+ toggleGraphVisible(): void;
77
+ refreshGraph: () => Promise<void>;
78
+ createNewChat(): void;
79
+ toHistoryChat(thread: import("@langchain/langgraph-sdk").Thread<{
80
+ messages: import("@langchain/langgraph-sdk").Message[];
81
+ }>): Promise<import("@langchain/langgraph-sdk").Thread<unknown> | undefined>;
82
+ deleteHistoryChat(thread: import("@langchain/langgraph-sdk").Thread<{
83
+ messages: import("@langchain/langgraph-sdk").Message[];
84
+ }>): Promise<void>;
85
+ getToolUIRender: (tool_name: string) => ((message: import("../LangGraphClient.js").RenderMessage) => Object) | null;
86
+ };
87
+ }>;
88
+ };
89
+ /**
90
+ * Chat Provider 组件
91
+ * 提供 Chat Store 的上下文
92
+ */
93
+ export declare const ChatProvider: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
94
+ defaultAgent: {
95
+ type: PropType<string>;
96
+ default: string;
97
+ };
98
+ apiUrl: {
99
+ type: PropType<string>;
100
+ default: string;
101
+ };
102
+ defaultHeaders: {
103
+ type: PropType<Record<string, string>>;
104
+ default: () => {};
105
+ };
106
+ withCredentials: {
107
+ type: PropType<boolean>;
108
+ default: boolean;
109
+ };
110
+ showHistory: {
111
+ type: PropType<boolean>;
112
+ default: boolean;
113
+ };
114
+ showGraph: {
115
+ type: PropType<boolean>;
116
+ default: boolean;
117
+ };
118
+ onInitError: {
119
+ type: PropType<(error: any, currentAgent: string) => void>;
120
+ default: undefined;
121
+ };
122
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
123
+ [key: string]: any;
124
+ }>[] | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
125
+ defaultAgent: {
126
+ type: PropType<string>;
127
+ default: string;
128
+ };
129
+ apiUrl: {
130
+ type: PropType<string>;
131
+ default: string;
132
+ };
133
+ defaultHeaders: {
134
+ type: PropType<Record<string, string>>;
135
+ default: () => {};
136
+ };
137
+ withCredentials: {
138
+ type: PropType<boolean>;
139
+ default: boolean;
140
+ };
141
+ showHistory: {
142
+ type: PropType<boolean>;
143
+ default: boolean;
144
+ };
145
+ showGraph: {
146
+ type: PropType<boolean>;
147
+ default: boolean;
148
+ };
149
+ onInitError: {
150
+ type: PropType<(error: any, currentAgent: string) => void>;
151
+ default: undefined;
152
+ };
153
+ }>> & Readonly<{}>, {
154
+ apiUrl: string;
155
+ defaultHeaders: Record<string, string>;
156
+ showHistory: boolean;
157
+ showGraph: boolean;
158
+ defaultAgent: string;
159
+ withCredentials: boolean;
160
+ onInitError: (error: any, currentAgent: string) => void;
161
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,121 @@
1
+ import { defineComponent, inject, provide, onMounted } from "vue";
2
+ import { createChatStore } from "../ui-store/index.js";
3
+ import { useStore } from "@nanostores/vue";
4
+ /**
5
+ * @zh useUnionStore Hook 用于将 nanostores 的 store 结构转换为更易于在 UI 组件中使用的扁平结构。
6
+ * @en The useUnionStore Hook is used to transform the nanostores store structure into a flatter structure that is easier to use in UI components.
7
+ */
8
+ export const useUnionStoreVue = (store, useStore) => {
9
+ const data = Object.fromEntries(Object.entries(store.data).map(([key, value]) => {
10
+ return [key, useStore(value)];
11
+ }));
12
+ return {
13
+ ...data,
14
+ ...store.mutations,
15
+ };
16
+ };
17
+ // 定义注入的 key,提供完整类型
18
+ const ChatContextKey = Symbol("ChatContext");
19
+ /**
20
+ * 使用 Chat Store 的组合式函数
21
+ * @throws {Error} 如果在 ChatProvider 外部使用会抛出错误
22
+ */
23
+ export const useChat = () => {
24
+ const context = inject(ChatContextKey);
25
+ if (!context) {
26
+ throw new Error("useChat must be used within a ChatProvider");
27
+ }
28
+ return context;
29
+ };
30
+ /**
31
+ * @zh Chat Provider Hook,用于在 setup 中直接使用
32
+ * @en Chat Provider Hook, used directly in setup
33
+ */
34
+ export const useChatProvider = (props) => {
35
+ const F = props.withCredentials
36
+ ? (url, options) => {
37
+ options.credentials = "include";
38
+ return fetch(url, options);
39
+ }
40
+ : fetch;
41
+ const store = createChatStore(props.defaultAgent || "", {
42
+ apiUrl: props.apiUrl,
43
+ defaultHeaders: props.defaultHeaders,
44
+ callerOptions: {
45
+ fetch: F,
46
+ maxRetries: 1,
47
+ },
48
+ }, {
49
+ showHistory: props.showHistory,
50
+ showGraph: props.showGraph,
51
+ });
52
+ const unionStore = useUnionStoreVue(store, useStore);
53
+ // 提供 store 给子组件
54
+ provide(ChatContextKey, unionStore);
55
+ // 初始化客户端
56
+ onMounted(() => {
57
+ unionStore
58
+ .initClient()
59
+ .then(() => {
60
+ if (unionStore.showHistory) {
61
+ unionStore.refreshHistoryList();
62
+ }
63
+ })
64
+ .catch((err) => {
65
+ console.error(err);
66
+ if (props.onInitError) {
67
+ props.onInitError(err, unionStore.currentAgent.value);
68
+ }
69
+ });
70
+ });
71
+ return {
72
+ unionStore,
73
+ };
74
+ };
75
+ /**
76
+ * Chat Provider 组件
77
+ * 提供 Chat Store 的上下文
78
+ */
79
+ export const ChatProvider = defineComponent({
80
+ name: "ChatProvider",
81
+ props: {
82
+ defaultAgent: {
83
+ type: String,
84
+ default: "",
85
+ },
86
+ apiUrl: {
87
+ type: String,
88
+ default: "http://localhost:8123",
89
+ },
90
+ defaultHeaders: {
91
+ type: Object,
92
+ default: () => ({}),
93
+ },
94
+ withCredentials: {
95
+ type: Boolean,
96
+ default: false,
97
+ },
98
+ showHistory: {
99
+ type: Boolean,
100
+ default: false,
101
+ },
102
+ showGraph: {
103
+ type: Boolean,
104
+ default: false,
105
+ },
106
+ onInitError: {
107
+ type: Function,
108
+ default: undefined,
109
+ },
110
+ },
111
+ setup(props, { slots }) {
112
+ const { unionStore } = useChatProvider(props);
113
+ defineExpose({
114
+ unionStore,
115
+ });
116
+ return () => {
117
+ var _a;
118
+ return (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots);
119
+ };
120
+ },
121
+ });
@@ -0,0 +1 @@
1
+ export * from "./ChatContext.js";
@@ -0,0 +1 @@
1
+ export * from "./ChatContext.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langgraph-js/sdk",
3
- "version": "2.0.1",
3
+ "version": "3.0.0",
4
4
  "description": "The UI SDK for LangGraph - seamlessly integrate your AI agents with frontend interfaces",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -8,6 +8,20 @@
8
8
  "registry": "https://registry.npmjs.org/",
9
9
  "access": "public"
10
10
  },
11
+ "exports": {
12
+ "./react": {
13
+ "import": "./dist/react/index.js",
14
+ "types": "./dist/react/index.d.ts"
15
+ },
16
+ "./vue": {
17
+ "import": "./dist/vue/index.js",
18
+ "types": "./dist/vue/index.d.ts"
19
+ },
20
+ ".": {
21
+ "import": "./dist/index.js",
22
+ "types": "./dist/index.d.ts"
23
+ }
24
+ },
11
25
  "keywords": [
12
26
  "langgraph",
13
27
  "ui",
@@ -16,7 +30,8 @@
16
30
  "ai",
17
31
  "agents",
18
32
  "langchain",
19
- "react"
33
+ "react",
34
+ "vue"
20
35
  ],
21
36
  "author": "LangGraph Team",
22
37
  "license": "Apache-2.0",
@@ -29,7 +44,8 @@
29
44
  "url": "https://github.com/KonghaYao/YaoAgent/issues"
30
45
  },
31
46
  "dependencies": {
32
- "@langchain/langgraph-sdk": "^0.0.77",
47
+ "@langchain/langgraph-sdk": "^0.1.10",
48
+ "@langgraph-js/pure-graph": "^1.5.2",
33
49
  "eventemitter3": "^5.0.1",
34
50
  "jsonrepair": "^3.12.0",
35
51
  "nanostores": "^1.0.1",
@@ -37,6 +53,30 @@
37
53
  "zod": "^3.25.17",
38
54
  "zod-to-json-schema": "^3.24.5"
39
55
  },
56
+ "peerDependencies": {
57
+ "@nanostores/react": "^1.0.0",
58
+ "@nanostores/vue": "^1.0.0",
59
+ "react": "^19||^18",
60
+ "vue": "^3.0.0"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "@nanostores/react": {
64
+ "optional": true
65
+ },
66
+ "@nanostores/vue": {
67
+ "optional": true
68
+ },
69
+ "react": {
70
+ "optional": true
71
+ },
72
+ "vue": {
73
+ "optional": true
74
+ }
75
+ },
76
+ "devDependencies": {
77
+ "@types/react": "^19.1.6",
78
+ "vue": "^3.5.14"
79
+ },
40
80
  "scripts": {
41
81
  "build": "tsc",
42
82
  "prepublish": "pnpm build"
@@ -2,8 +2,9 @@ import type { Thread, Message, Assistant, HumanMessage, AIMessage, ToolMessage,
2
2
  import { EventEmitter } from "eventemitter3";
3
3
  import { ToolManager } from "./ToolManager.js";
4
4
  import { CallToolResult } from "./tool/createTool.js";
5
- import { ILangGraphClient } from "./types.js";
5
+ import { type ILangGraphClient } from "@langgraph-js/pure-graph/dist/types.js";
6
6
  import { MessageProcessor } from "./MessageProcessor.js";
7
+ import { revertChatTo } from "./time-travel/index.js";
7
8
 
8
9
  export type RenderMessage = Message & {
9
10
  /** 对于 AIMessage 来说是节点名称,对于工具节点来说是工具名称 */
@@ -68,7 +69,7 @@ export interface LangGraphClientConfig {
68
69
  timeoutMs?: number;
69
70
  defaultHeaders?: Record<string, string | null | undefined>;
70
71
  /** 自定义客户端实现,如果不提供则使用官方 Client */
71
- client: ILangGraphClient<any, any>;
72
+ client: ILangGraphClient<any>;
72
73
  }
73
74
 
74
75
  // 定义事件数据类型
@@ -91,8 +92,8 @@ export interface LangGraphEvents {
91
92
  * @zh LangGraphClient 类是与 LangGraph 后端交互的主要客户端。
92
93
  * @en The LangGraphClient class is the main client for interacting with the LangGraph backend.
93
94
  */
94
- export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> extends EventEmitter<LangGraphEvents> {
95
- private client: ILangGraphClient<TStateType, TUpdateType>;
95
+ export class LangGraphClient<TStateType = unknown> extends EventEmitter<LangGraphEvents> {
96
+ private client: ILangGraphClient<TStateType>;
96
97
  private currentAssistant: Assistant | null = null;
97
98
  private currentThread: Thread<TStateType> | null = null;
98
99
  tools: ToolManager = new ToolManager();
@@ -122,7 +123,7 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
122
123
  }
123
124
 
124
125
  /** 代理 runs 属性到内部 client */
125
- get runs() {
126
+ get runs(): ILangGraphClient["runs"] {
126
127
  return this.client.runs;
127
128
  }
128
129
  private listAssistants() {
@@ -162,14 +163,11 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
162
163
  * @zh 创建一个新的 Thread。
163
164
  * @en Creates a new Thread.
164
165
  */
165
- async createThread({
166
- threadId,
167
- }: {
168
- threadId?: string;
169
- } = {}) {
166
+ async createThread({ threadId, graphId }: { threadId?: string; graphId?: string } = {}) {
170
167
  try {
171
168
  this.currentThread = await this.threads.create({
172
169
  threadId,
170
+ graphId,
173
171
  });
174
172
  return this.currentThread;
175
173
  } catch (error) {
@@ -284,6 +282,17 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
284
282
  this.runs.cancel((this.currentThread as any)!.thread_id, this.currentRun.run_id);
285
283
  }
286
284
  }
285
+ /**
286
+ * @zh 回滚到指定的消息。但是不会触发数据的重新更新
287
+ * @en Reverts to the specified message.
288
+ */
289
+ async revertChatTo(messageId: string) {
290
+ const { state, checkpoint } = await revertChatTo(this.client as any, this.currentThread!.thread_id, messageId);
291
+ this.graphState = state;
292
+ this.messageProcessor.clearStreamingMessages();
293
+ this.messageProcessor.setGraphMessages(state.messages! as RenderMessage[]);
294
+ return state;
295
+ }
287
296
  /**
288
297
  * @zh 发送消息到 LangGraph 后端。
289
298
  * @en Sends a message to the LangGraph backend.
@@ -293,7 +302,7 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
293
302
  throw new Error("Thread or Assistant not initialized");
294
303
  }
295
304
  if (!this.currentThread) {
296
- await this.createThread();
305
+ await this.createThread({ graphId: this.currentAssistant!.graph_id!, threadId: this.currentThread!.thread_id! });
297
306
  this.emit("thread", {
298
307
  event: "thread/create",
299
308
  data: {
@@ -341,7 +350,7 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
341
350
  streamRecord.push(chunk);
342
351
  if (chunk.event === "metadata") {
343
352
  this.currentRun = chunk.data;
344
- } else if (chunk.event === "error") {
353
+ } else if (chunk.event === "error" || chunk.event === "Error" || chunk.event === "__stream_error__") {
345
354
  this.emit("error", chunk);
346
355
  } else if (chunk.event === "messages/partial") {
347
356
  for (const message of chunk.data) {
@@ -1,7 +1,7 @@
1
1
  import { LangGraphClientConfig } from "../LangGraphClient.js";
2
- import { ILangGraphClient } from "../types.js";
2
+ import { type ILangGraphClient } from "@langgraph-js/pure-graph/dist/types.js";
3
3
 
4
4
  export const createLangGraphServerClient = async (config: LangGraphClientConfig): Promise<ILangGraphClient> => {
5
5
  const { Client } = await import("@langchain/langgraph-sdk");
6
- return new Client(config) as unknown as ILangGraphClient;
6
+ return new Client(config) as ILangGraphClient;
7
7
  };
package/src/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export * from "./LangGraphClient.js";
2
2
  export * from "./MessageProcessor.js";
3
- export * from "./types.js";
4
3
  export * from "./tool/index.js";
5
4
  export * from "@langchain/langgraph-sdk";
6
5
  export * from "./ui-store/index.js";
@@ -0,0 +1,81 @@
1
+ import { createElement, createContext, useContext, useMemo, ReactNode, useEffect } from "react";
2
+
3
+ import { createChatStore, UnionStore, useUnionStore } from "../ui-store/index.js";
4
+ import { useStore } from "@nanostores/react";
5
+
6
+ const ChatContext = createContext<UnionStore<ReturnType<typeof createChatStore>> | undefined>(undefined);
7
+
8
+ export const useChat = () => {
9
+ const context = useContext(ChatContext);
10
+ if (!context) {
11
+ throw new Error("useChat must be used within a ChatProvider");
12
+ }
13
+ return context;
14
+ };
15
+
16
+ interface ChatProviderProps {
17
+ children: ReactNode;
18
+ defaultAgent?: string;
19
+ apiUrl?: string;
20
+ defaultHeaders?: Record<string, string>;
21
+ withCredentials?: boolean;
22
+ showHistory?: boolean;
23
+ showGraph?: boolean;
24
+ onInitError?: (error: any, currentAgent: string) => void;
25
+ }
26
+
27
+ export const ChatProvider: React.FC<ChatProviderProps> = ({
28
+ children,
29
+ defaultAgent = "",
30
+ apiUrl = "http://localhost:8123",
31
+ defaultHeaders = {},
32
+ withCredentials = false,
33
+ showHistory = false,
34
+ showGraph = false,
35
+ onInitError,
36
+ }) => {
37
+ const store = useMemo(() => {
38
+ const F = withCredentials
39
+ ? (url: string, options: RequestInit) => {
40
+ options.credentials = "include";
41
+ return fetch(url, options);
42
+ }
43
+ : fetch;
44
+
45
+ return createChatStore(
46
+ defaultAgent,
47
+ {
48
+ apiUrl,
49
+ defaultHeaders,
50
+ callerOptions: {
51
+ fetch: F,
52
+ maxRetries: 1,
53
+ },
54
+ },
55
+ {
56
+ showHistory,
57
+ showGraph,
58
+ }
59
+ );
60
+ }, [defaultAgent, apiUrl, defaultHeaders, withCredentials, showHistory, showGraph]);
61
+
62
+ const unionStore = useUnionStore(store, useStore);
63
+
64
+ useEffect(() => {
65
+ unionStore
66
+ .initClient()
67
+ .then((res) => {
68
+ if (unionStore.showHistory) {
69
+ unionStore.refreshHistoryList();
70
+ }
71
+ })
72
+ .catch((err) => {
73
+ console.error(err);
74
+ if (onInitError) {
75
+ onInitError(err, unionStore.currentAgent);
76
+ }
77
+ });
78
+ }, [unionStore, onInitError]);
79
+
80
+ return createElement(ChatContext.Provider, { value: unionStore }, children);
81
+ };
@@ -0,0 +1 @@
1
+ export * from "./ChatContext.js";