@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/LICENSE +201 -201
- package/README.md +163 -163
- package/dist/tool/ToolUI.d.ts +10 -0
- package/dist/tool/ToolUI.js +24 -0
- package/dist/tool/createTool.d.ts +20 -2
- package/dist/tool/createTool.js +7 -0
- package/dist/tool/index.d.ts +1 -0
- package/dist/tool/index.js +1 -0
- package/dist/ui-store/createChatStore.d.ts +1 -0
- package/dist/ui-store/createChatStore.js +8 -0
- package/package.json +1 -1
- package/src/LangGraphClient.ts +613 -613
- package/src/SpendTime.ts +60 -60
- package/src/ToolManager.ts +129 -129
- package/src/index.ts +5 -5
- package/src/tool/ToolUI.ts +26 -0
- package/src/tool/copilotkit-actions.ts +72 -72
- package/src/tool/createTool.ts +89 -78
- package/src/tool/index.ts +3 -2
- package/src/tool/utils.ts +158 -158
- package/src/ui-store/UnionStore.ts +29 -29
- package/src/ui-store/createChatStore.ts +293 -287
- package/src/ui-store/index.ts +2 -2
- package/src/ui-store/rafDebounce.ts +29 -29
- package/test/testResponse.json +5418 -5418
- package/tsconfig.json +112 -112
- package/.env +0 -0
package/README.md
CHANGED
|
@@ -1,163 +1,163 @@
|
|
|
1
|
-
# @langgraph-js/sdk
|
|
2
|
-
|
|
3
|
-

|
|
4
|
-

|
|
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
|
+

|
|
4
|
+

|
|
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
|
-
|
|
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
|
+
};
|
package/dist/tool/createTool.js
CHANGED
package/dist/tool/index.d.ts
CHANGED
package/dist/tool/index.js
CHANGED
|
@@ -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
|
};
|