@langgraph-js/sdk 1.4.0 → 1.5.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/README.md CHANGED
@@ -1,163 +1,163 @@
1
- # @langgraph-js/sdk
2
-
3
- ![npm version](https://img.shields.io/npm/v/@langgraph-js/sdk)
4
- ![license](https://img.shields.io/npm/l/@langgraph-js/sdk)
5
-
6
- > The missing UI SDK for LangGraph - seamlessly integrate your AI agents with frontend interfaces
7
-
8
- ## Why @langgraph-js/sdk?
9
-
10
- Building AI agent applications is complex, especially when you need to bridge the gap between LangGraph agents and interactive user interfaces. This SDK solves the critical challenges of frontend integration:
11
-
12
- - **Provides a complete UI integration layer** - no more complex custom code to handle tools, streaming, and state management
13
- - **Simplifies human-in-the-loop interactions** - easily incorporate user feedback within agent workflows
14
- - **Handles edge cases automatically** - interruptions, errors, token management and more
15
- - **Offers a rich set of UI components** - ready-to-use elements to display agent interactions
16
-
17
- [DOCS](https://langgraph-js.netlify.app)
18
-
19
- ## Installation
20
-
21
- ```bash
22
- # Using npm
23
- npm install @langgraph-js/sdk
24
-
25
- # Using yarn
26
- yarn add @langgraph-js/sdk
27
-
28
- # Using pnpm
29
- pnpm add @langgraph-js/sdk
30
- ```
31
-
32
- ## Key Features
33
-
34
- ### Generative UI
35
-
36
- - ✅ Custom Tool Messages
37
- - ✅ Token Counter
38
- - ✅ Stop Graph Progress
39
- - ✅ Interrupt Handling
40
- - ✅ Error Handling
41
- - ✅ Spend Time Tracking
42
- - ✅ Time Persistence
43
-
44
- ### Frontend Actions
45
-
46
- - ✅ Definition of Union Tools
47
- - ✅ Frontend Functions As Tools
48
- - ✅ Human-in-the-Loop Interaction
49
- - ✅ Interrupt Mode
50
-
51
- ### Authorization
52
-
53
- - ✅ Cookie-Based Authentication
54
- - ✅ Custom Token Authentication
55
-
56
- ### Persistence
57
-
58
- - ✅ Read History from LangGraph
59
-
60
- ## Advanced Usage
61
-
62
- ### Creating a Chat Store
63
-
64
- You can easily create a reactive store for your LangGraph client:
65
-
66
- ```typescript
67
- import { createChatStore } from "@langgraph-js/sdk";
68
-
69
- export const globalChatStore = createChatStore(
70
- "agent",
71
- {
72
- // Custom LangGraph backend interaction
73
- apiUrl: "http://localhost:8123",
74
- // Custom headers for authentication
75
- defaultHeaders: JSON.parse(localStorage.getItem("code") || "{}"),
76
- callerOptions: {
77
- // Example for including cookies
78
- // fetch(url: string, options: RequestInit) {
79
- // options.credentials = "include";
80
- // return fetch(url, options);
81
- // },
82
- },
83
- },
84
- {
85
- onInit(client) {
86
- client.tools.bindTools([]);
87
- },
88
- }
89
- );
90
- ```
91
-
92
- ### React Integration
93
-
94
- First, install the nanostores React integration:
95
-
96
- ```bash
97
- pnpm i @nanostores/react
98
- ```
99
-
100
- Then create a context provider for your chat:
101
-
102
- ```tsx
103
- import React, { createContext, useContext, useEffect } from "react";
104
- import { globalChatStore } from "../store"; // Import your store
105
- import { UnionStore, useUnionStore } from "@langgraph-js/sdk";
106
- import { useStore } from "@nanostores/react";
107
-
108
- type ChatContextType = UnionStore<typeof globalChatStore>;
109
-
110
- const ChatContext = createContext<ChatContextType | undefined>(undefined);
111
-
112
- export const useChat = () => {
113
- const context = useContext(ChatContext);
114
- if (!context) {
115
- throw new Error("useChat must be used within a ChatProvider");
116
- }
117
- return context;
118
- };
119
-
120
- export const ChatProvider = ({ children }) => {
121
- // Use store to ensure React gets reactive state updates
122
- const store = useUnionStore(globalChatStore, useStore);
123
-
124
- useEffect(() => {
125
- // Initialize client
126
- store.initClient().then(() => {
127
- // Initialize conversation history
128
- store.refreshHistoryList();
129
- });
130
- }, [store.currentAgent]);
131
-
132
- return <ChatContext.Provider value={store}>{children}</ChatContext.Provider>;
133
- };
134
- ```
135
-
136
- Use it in your components:
137
-
138
- ```tsx
139
- export const MyChat = () => {
140
- return (
141
- <ChatProvider>
142
- <ChatComp></ChatComp>
143
- </ChatProvider>
144
- );
145
- };
146
-
147
- function ChatComp() {
148
- const chat = useChat();
149
- // Use chat store methods and state here
150
- }
151
- ```
152
-
153
- ## Documentation
154
-
155
- For complete documentation, visit our [official docs](https://langgraph-js.netlify.app).
156
-
157
- ## Contributing
158
-
159
- Contributions are welcome! Please feel free to submit a Pull Request.
160
-
161
- ## License
162
-
163
- This project is licensed under the Apache-2.0 License.
1
+ # @langgraph-js/sdk
2
+
3
+ ![npm version](https://img.shields.io/npm/v/@langgraph-js/sdk)
4
+ ![license](https://img.shields.io/npm/l/@langgraph-js/sdk)
5
+
6
+ > The missing UI SDK for LangGraph - seamlessly integrate your AI agents with frontend interfaces
7
+
8
+ ## Why @langgraph-js/sdk?
9
+
10
+ Building AI agent applications is complex, especially when you need to bridge the gap between LangGraph agents and interactive user interfaces. This SDK solves the critical challenges of frontend integration:
11
+
12
+ - **Provides a complete UI integration layer** - no more complex custom code to handle tools, streaming, and state management
13
+ - **Simplifies human-in-the-loop interactions** - easily incorporate user feedback within agent workflows
14
+ - **Handles edge cases automatically** - interruptions, errors, token management and more
15
+ - **Offers a rich set of UI components** - ready-to-use elements to display agent interactions
16
+
17
+ [DOCS](https://langgraph-js.netlify.app)
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ # Using npm
23
+ npm install @langgraph-js/sdk
24
+
25
+ # Using yarn
26
+ yarn add @langgraph-js/sdk
27
+
28
+ # Using pnpm
29
+ pnpm add @langgraph-js/sdk
30
+ ```
31
+
32
+ ## Key Features
33
+
34
+ ### Generative UI
35
+
36
+ - ✅ Custom Tool Messages
37
+ - ✅ Token Counter
38
+ - ✅ Stop Graph Progress
39
+ - ✅ Interrupt Handling
40
+ - ✅ Error Handling
41
+ - ✅ Spend Time Tracking
42
+ - ✅ Time Persistence
43
+
44
+ ### Frontend Actions
45
+
46
+ - ✅ Definition of Union Tools
47
+ - ✅ Frontend Functions As Tools
48
+ - ✅ Human-in-the-Loop Interaction
49
+ - ✅ Interrupt Mode
50
+
51
+ ### Authorization
52
+
53
+ - ✅ Cookie-Based Authentication
54
+ - ✅ Custom Token Authentication
55
+
56
+ ### Persistence
57
+
58
+ - ✅ Read History from LangGraph
59
+
60
+ ## Advanced Usage
61
+
62
+ ### Creating a Chat Store
63
+
64
+ You can easily create a reactive store for your LangGraph client:
65
+
66
+ ```typescript
67
+ import { createChatStore } from "@langgraph-js/sdk";
68
+
69
+ export const globalChatStore = createChatStore(
70
+ "agent",
71
+ {
72
+ // Custom LangGraph backend interaction
73
+ apiUrl: "http://localhost:8123",
74
+ // Custom headers for authentication
75
+ defaultHeaders: JSON.parse(localStorage.getItem("code") || "{}"),
76
+ callerOptions: {
77
+ // Example for including cookies
78
+ // fetch(url: string, options: RequestInit) {
79
+ // options.credentials = "include";
80
+ // return fetch(url, options);
81
+ // },
82
+ },
83
+ },
84
+ {
85
+ onInit(client) {
86
+ client.tools.bindTools([]);
87
+ },
88
+ }
89
+ );
90
+ ```
91
+
92
+ ### React Integration
93
+
94
+ First, install the nanostores React integration:
95
+
96
+ ```bash
97
+ pnpm i @nanostores/react
98
+ ```
99
+
100
+ Then create a context provider for your chat:
101
+
102
+ ```tsx
103
+ import React, { createContext, useContext, useEffect } from "react";
104
+ import { globalChatStore } from "../store"; // Import your store
105
+ import { UnionStore, useUnionStore } from "@langgraph-js/sdk";
106
+ import { useStore } from "@nanostores/react";
107
+
108
+ type ChatContextType = UnionStore<typeof globalChatStore>;
109
+
110
+ const ChatContext = createContext<ChatContextType | undefined>(undefined);
111
+
112
+ export const useChat = () => {
113
+ const context = useContext(ChatContext);
114
+ if (!context) {
115
+ throw new Error("useChat must be used within a ChatProvider");
116
+ }
117
+ return context;
118
+ };
119
+
120
+ export const ChatProvider = ({ children }) => {
121
+ // Use store to ensure React gets reactive state updates
122
+ const store = useUnionStore(globalChatStore, useStore);
123
+
124
+ useEffect(() => {
125
+ // Initialize client
126
+ store.initClient().then(() => {
127
+ // Initialize conversation history
128
+ store.refreshHistoryList();
129
+ });
130
+ }, [store.currentAgent]);
131
+
132
+ return <ChatContext.Provider value={store}>{children}</ChatContext.Provider>;
133
+ };
134
+ ```
135
+
136
+ Use it in your components:
137
+
138
+ ```tsx
139
+ export const MyChat = () => {
140
+ return (
141
+ <ChatProvider>
142
+ <ChatComp></ChatComp>
143
+ </ChatProvider>
144
+ );
145
+ };
146
+
147
+ function ChatComp() {
148
+ const chat = useChat();
149
+ // Use chat store methods and state here
150
+ }
151
+ ```
152
+
153
+ ## Documentation
154
+
155
+ For complete documentation, visit our [official docs](https://langgraph-js.netlify.app).
156
+
157
+ ## Contributing
158
+
159
+ Contributions are welcome! Please feel free to submit a Pull Request.
160
+
161
+ ## License
162
+
163
+ This project is licensed under the Apache-2.0 License.
@@ -0,0 +1,10 @@
1
+ import { RenderMessage } from "../LangGraphClient.js";
2
+ import { LangGraphClient } from "../LangGraphClient.js";
3
+ export declare class ToolRenderData<D> {
4
+ message: RenderMessage;
5
+ client: LangGraphClient;
6
+ constructor(message: RenderMessage, client: LangGraphClient);
7
+ get state(): "done" | "idle";
8
+ get input(): any;
9
+ response(data: D): void;
10
+ }
@@ -0,0 +1,24 @@
1
+ export class ToolRenderData {
2
+ constructor(message, client) {
3
+ this.message = message;
4
+ this.client = client;
5
+ }
6
+ get state() {
7
+ var _a, _b;
8
+ if (this.message.type === "tool" && ((_b = (_a = this.message) === null || _a === void 0 ? void 0 : _a.additional_kwargs) === null || _b === void 0 ? void 0 : _b.done)) {
9
+ return "done";
10
+ }
11
+ return "idle";
12
+ }
13
+ get input() {
14
+ try {
15
+ return JSON.parse(this.message.tool_input);
16
+ }
17
+ catch (e) {
18
+ return null;
19
+ }
20
+ }
21
+ response(data) {
22
+ this.client.doneFEToolWaiting(this.message.id, JSON.stringify(data));
23
+ }
24
+ }
@@ -1,7 +1,8 @@
1
1
  import { z, ZodRawShape, ZodTypeAny } from "zod";
2
2
  import { Action, Parameter } from "./copilotkit-actions.js";
3
3
  import { Message } from "@langchain/langgraph-sdk";
4
- export interface UnionTool<Args extends ZodRawShape> {
4
+ import { ToolRenderData } from "./ToolUI.js";
5
+ export interface UnionTool<Args extends ZodRawShape, Child extends Object = Object> {
5
6
  name: string;
6
7
  description: string;
7
8
  parameters: Args;
@@ -10,6 +11,8 @@ export interface UnionTool<Args extends ZodRawShape> {
10
11
  execute: ToolCallback<Args>;
11
12
  /** 工具执行成功后触发的附加消息 */
12
13
  callbackMessage?: (result: CallToolResult) => Message[];
14
+ render?: <D>(tool: ToolRenderData<D>) => Child;
15
+ onlyRender?: boolean;
13
16
  }
14
17
  export type ToolCallback<Args extends ZodRawShape> = (args: z.objectOutputType<Args, ZodTypeAny>, context?: any) => CallToolResult | Promise<CallToolResult>;
15
18
  export type CallToolResult = string | {
@@ -17,7 +20,7 @@ export type CallToolResult = string | {
17
20
  text: string;
18
21
  }[];
19
22
  /** 用于格式校验 */
20
- export declare const createTool: <Args extends ZodRawShape>(tool: UnionTool<Args>) => UnionTool<Args>;
23
+ export declare const createTool: <Args extends ZodRawShape>(tool: UnionTool<Args>) => UnionTool<Args, Object>;
21
24
  /** 提供一种兼容 copilotkit 的定义方式,简化定义形式
22
25
  * 来自 copilotkit 的 frontend action
23
26
  */
@@ -45,3 +48,18 @@ export declare const createMCPTool: <Args extends ZodRawShape>(tool: UnionTool<A
45
48
  }[];
46
49
  isError: boolean;
47
50
  }>))[];
51
+ export declare const createToolUI: <Args extends Parameter[] | [] = [], Child extends Object = {}>(tool: Action<Args> & {
52
+ render?: (tool: ToolRenderData<any>) => Child;
53
+ onlyRender?: boolean;
54
+ }) => {
55
+ render: ((tool: ToolRenderData<any>) => Child) | undefined;
56
+ onlyRender: boolean | undefined;
57
+ name: string;
58
+ description: string;
59
+ parameters: z.ZodRawShape;
60
+ /** 是否直接返回工具结果,而不是通过消息返回 */
61
+ returnDirect?: boolean;
62
+ execute: ToolCallback<z.ZodRawShape>;
63
+ /** 工具执行成功后触发的附加消息 */
64
+ callbackMessage?: (result: CallToolResult) => Message[];
65
+ };
@@ -59,3 +59,10 @@ export const createMCPTool = (tool) => {
59
59
  },
60
60
  ];
61
61
  };
62
+ export const createToolUI = (tool) => {
63
+ return {
64
+ ...createFETool(tool),
65
+ render: tool.render,
66
+ onlyRender: tool.onlyRender,
67
+ };
68
+ };
@@ -1,2 +1,3 @@
1
1
  export * from "./createTool.js";
2
2
  export * from "./copilotkit-actions.js";
3
+ export * from "./ToolUI.js";
@@ -1,2 +1,3 @@
1
1
  export * from "./createTool.js";
2
2
  export * from "./copilotkit-actions.js";
3
+ export * from "./ToolUI.js";
@@ -87,5 +87,6 @@ export declare const createChatStore: (initClientName: string, config: LangGraph
87
87
  deleteHistoryChat(thread: Thread<{
88
88
  messages: Message[];
89
89
  }>): Promise<void>;
90
+ getToolUIRender: (tool_name: string) => ((message: RenderMessage) => Object) | null;
90
91
  };
91
92
  };
@@ -1,6 +1,7 @@
1
1
  import { atom } from "nanostores";
2
2
  import { LangGraphClient } from "../LangGraphClient.js";
3
3
  import { rafDebounce } from "./rafDebounce.js";
4
+ import { ToolRenderData } from "../tool/ToolUI.js";
4
5
  /**
5
6
  * @zh 格式化日期对象为时间字符串。
6
7
  * @en Formats a Date object into a time string.
@@ -189,6 +190,12 @@ export const createChatStore = (initClientName, config, context = {}) => {
189
190
  const prev = historyList.get();
190
191
  historyList.set([thread, ...prev]);
191
192
  };
193
+ const getToolUIRender = (tool_name) => {
194
+ var _a;
195
+ const toolsDefine = client.get().tools.getAllTools();
196
+ const tool = (_a = toolsDefine.find((i) => i.name === tool_name)) === null || _a === void 0 ? void 0 : _a.render;
197
+ return tool ? (message) => tool(new ToolRenderData(message, client.get())) : null;
198
+ };
192
199
  return {
193
200
  data: {
194
201
  client,
@@ -271,6 +278,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
271
278
  await ((_a = client.get()) === null || _a === void 0 ? void 0 : _a.threads.delete(thread.thread_id));
272
279
  await refreshHistoryList();
273
280
  },
281
+ getToolUIRender,
274
282
  },
275
283
  };
276
284
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langgraph-js/sdk",
3
- "version": "1.4.0",
3
+ "version": "1.5.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",