@langgraph-js/sdk 2.0.1 → 2.2.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/LangGraphClient.d.ts +11 -5
- package/dist/LangGraphClient.js +15 -2
- package/dist/time-travel/index.d.ts +11 -0
- package/dist/time-travel/index.js +30 -0
- package/dist/types.d.ts +1 -1
- package/dist/ui-store/createChatStore.d.ts +6 -1
- package/dist/ui-store/createChatStore.js +30 -6
- package/package.json +1 -1
- package/src/LangGraphClient.ts +16 -1
- package/src/time-travel/index.ts +33 -0
- package/src/types.ts +1 -1
- package/src/ui-store/createChatStore.ts +25 -7
|
@@ -148,15 +148,13 @@ export declare class LangGraphClient<TStateType = unknown, TUpdateType = TStateT
|
|
|
148
148
|
supersteps?: Array<{
|
|
149
149
|
updates: Array<{
|
|
150
150
|
values: unknown;
|
|
151
|
-
command
|
|
151
|
+
command?: Command;
|
|
152
152
|
asNode: string;
|
|
153
153
|
}>;
|
|
154
154
|
}>;
|
|
155
155
|
}): Promise<Thread<TStateType>>;
|
|
156
156
|
search(query?: {
|
|
157
|
-
metadata
|
|
158
|
-
/** Thread 创建事件 */
|
|
159
|
-
? /** Thread 创建事件 */: import("@langchain/langgraph-sdk").Metadata;
|
|
157
|
+
metadata?: import("@langchain/langgraph-sdk").Metadata;
|
|
160
158
|
limit?: number;
|
|
161
159
|
offset?: number;
|
|
162
160
|
status?: import("@langchain/langgraph-sdk").ThreadStatus;
|
|
@@ -221,8 +219,9 @@ export declare class LangGraphClient<TStateType = unknown, TUpdateType = TStateT
|
|
|
221
219
|
* @zh 创建一个新的 Thread。
|
|
222
220
|
* @en Creates a new Thread.
|
|
223
221
|
*/
|
|
224
|
-
createThread({ threadId, }?: {
|
|
222
|
+
createThread({ threadId, graphId, }?: {
|
|
225
223
|
threadId?: string;
|
|
224
|
+
graphId?: string;
|
|
226
225
|
}): Promise<Thread<TStateType>>;
|
|
227
226
|
graphVisualize(): Promise<import("@langchain/langgraph-sdk").AssistantGraph>;
|
|
228
227
|
/**
|
|
@@ -259,6 +258,13 @@ export declare class LangGraphClient<TStateType = unknown, TUpdateType = TStateT
|
|
|
259
258
|
* @en Cancels the current Run.
|
|
260
259
|
*/
|
|
261
260
|
cancelRun(): void;
|
|
261
|
+
/**
|
|
262
|
+
* @zh 回滚到指定的消息。但是不会触发数据的重新更新
|
|
263
|
+
* @en Reverts to the specified message.
|
|
264
|
+
*/
|
|
265
|
+
revertChatTo(messageId: string): Promise<{
|
|
266
|
+
messages: Message[];
|
|
267
|
+
}>;
|
|
262
268
|
/**
|
|
263
269
|
* @zh 发送消息到 LangGraph 后端。
|
|
264
270
|
* @en Sends a message to the LangGraph backend.
|
package/dist/LangGraphClient.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from "eventemitter3";
|
|
2
2
|
import { ToolManager } from "./ToolManager.js";
|
|
3
3
|
import { MessageProcessor } from "./MessageProcessor.js";
|
|
4
|
+
import { revertChatTo } from "./time-travel/index.js";
|
|
4
5
|
/**
|
|
5
6
|
* @zh LangGraphClient 类是与 LangGraph 后端交互的主要客户端。
|
|
6
7
|
* @en The LangGraphClient class is the main client for interacting with the LangGraph backend.
|
|
@@ -73,10 +74,11 @@ export class LangGraphClient extends EventEmitter {
|
|
|
73
74
|
* @zh 创建一个新的 Thread。
|
|
74
75
|
* @en Creates a new Thread.
|
|
75
76
|
*/
|
|
76
|
-
async createThread({ threadId, } = {}) {
|
|
77
|
+
async createThread({ threadId, graphId, } = {}) {
|
|
77
78
|
try {
|
|
78
79
|
this.currentThread = await this.threads.create({
|
|
79
80
|
threadId,
|
|
81
|
+
graphId,
|
|
80
82
|
});
|
|
81
83
|
return this.currentThread;
|
|
82
84
|
}
|
|
@@ -185,6 +187,17 @@ export class LangGraphClient extends EventEmitter {
|
|
|
185
187
|
this.runs.cancel(this.currentThread.thread_id, this.currentRun.run_id);
|
|
186
188
|
}
|
|
187
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* @zh 回滚到指定的消息。但是不会触发数据的重新更新
|
|
192
|
+
* @en Reverts to the specified message.
|
|
193
|
+
*/
|
|
194
|
+
async revertChatTo(messageId) {
|
|
195
|
+
const { state, checkpoint } = await revertChatTo(this.client, this.currentThread.thread_id, messageId);
|
|
196
|
+
this.graphState = state;
|
|
197
|
+
this.messageProcessor.clearStreamingMessages();
|
|
198
|
+
this.messageProcessor.setGraphMessages(state.messages);
|
|
199
|
+
return state;
|
|
200
|
+
}
|
|
188
201
|
/**
|
|
189
202
|
* @zh 发送消息到 LangGraph 后端。
|
|
190
203
|
* @en Sends a message to the LangGraph backend.
|
|
@@ -195,7 +208,7 @@ export class LangGraphClient extends EventEmitter {
|
|
|
195
208
|
throw new Error("Thread or Assistant not initialized");
|
|
196
209
|
}
|
|
197
210
|
if (!this.currentThread) {
|
|
198
|
-
await this.createThread();
|
|
211
|
+
await this.createThread({ graphId: this.currentAssistant.graph_id });
|
|
199
212
|
this.emit("thread", {
|
|
200
213
|
event: "thread/create",
|
|
201
214
|
data: {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Client, Message } from "@langchain/langgraph-sdk";
|
|
2
|
+
export declare function revertChatTo(client: Client<{
|
|
3
|
+
messages: Message[];
|
|
4
|
+
}, {
|
|
5
|
+
messages: Message[];
|
|
6
|
+
}, unknown>, threadId: string, messageId: string): Promise<{
|
|
7
|
+
state: {
|
|
8
|
+
messages: Message[];
|
|
9
|
+
};
|
|
10
|
+
checkpoint: Pick<import("@langchain/langgraph-sdk").Config, "configurable">;
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export async function revertChatTo(client, threadId, messageId) {
|
|
2
|
+
const thread = await client.threads.get(threadId);
|
|
3
|
+
const messages = thread.values.messages;
|
|
4
|
+
const idx = messages.findIndex((message) => message.id === messageId);
|
|
5
|
+
if (idx === -1) {
|
|
6
|
+
throw new Error(`Message id ${messageId} not found`);
|
|
7
|
+
}
|
|
8
|
+
const removeMessages = messages.slice(idx + 1);
|
|
9
|
+
const state = {
|
|
10
|
+
...thread.values,
|
|
11
|
+
messages: removeMessages.map((i) => {
|
|
12
|
+
// sb langgraph 官方实现都不能正常工作
|
|
13
|
+
// return new RemoveMessage({ id: i.id! }).toJSON();
|
|
14
|
+
return {
|
|
15
|
+
type: "remove",
|
|
16
|
+
id: i.id,
|
|
17
|
+
};
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
const res = await client.threads.updateState(threadId, {
|
|
21
|
+
values: state,
|
|
22
|
+
});
|
|
23
|
+
// client.runs.wait();
|
|
24
|
+
return {
|
|
25
|
+
state: {
|
|
26
|
+
messages: messages.slice(0, idx + 1),
|
|
27
|
+
},
|
|
28
|
+
checkpoint: res,
|
|
29
|
+
};
|
|
30
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export type TypedAsyncGenerator<TStateType = unknown, TUpdateType = TStateType,
|
|
|
20
20
|
/**
|
|
21
21
|
* 兼容 LangGraph SDK 的接口定义,方便进行无侵入式的扩展
|
|
22
22
|
*/
|
|
23
|
-
export interface ILangGraphClient<TStateType =
|
|
23
|
+
export interface ILangGraphClient<TStateType = {}, TUpdateType = TStateType> {
|
|
24
24
|
assistants: {
|
|
25
25
|
search(query?: {
|
|
26
26
|
graphId?: string;
|
|
@@ -53,7 +53,7 @@ export declare const createChatStore: (initClientName: string, config: Partial<L
|
|
|
53
53
|
setTools(new_tools: UnionTool<any>[]): void;
|
|
54
54
|
isFELocking(): boolean | undefined;
|
|
55
55
|
initClient: () => Promise<LangGraphClient<unknown, unknown>>;
|
|
56
|
-
sendMessage: (message?: Message[], extraData?: SendMessageOptions) => Promise<void>;
|
|
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,25 @@ 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
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
userInput.set("");
|
|
178
|
+
loading.set(false);
|
|
179
|
+
}
|
|
170
180
|
};
|
|
171
181
|
/**
|
|
172
182
|
* @zh 停止当前的消息生成。
|
|
@@ -259,6 +269,20 @@ export const createChatStore = (initClientName, config, context = {}) => {
|
|
|
259
269
|
toggleHistoryVisible,
|
|
260
270
|
refreshHistoryList,
|
|
261
271
|
addToHistory,
|
|
272
|
+
/**
|
|
273
|
+
* @zh 回滚到指定的消息。
|
|
274
|
+
* @en Reverts to the specified message.
|
|
275
|
+
*/
|
|
276
|
+
async revertChatTo(messageId, resend = false, sendOptions) {
|
|
277
|
+
var _a;
|
|
278
|
+
await ((_a = client.get()) === null || _a === void 0 ? void 0 : _a.revertChatTo(messageId));
|
|
279
|
+
if (resend) {
|
|
280
|
+
return sendMessage([], sendOptions, true);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
updateUI(client.get());
|
|
284
|
+
}
|
|
285
|
+
},
|
|
262
286
|
/**
|
|
263
287
|
* @zh 设置用户输入内容。
|
|
264
288
|
* @en Sets the user input content.
|
package/package.json
CHANGED
package/src/LangGraphClient.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { ToolManager } from "./ToolManager.js";
|
|
|
4
4
|
import { CallToolResult } from "./tool/createTool.js";
|
|
5
5
|
import { ILangGraphClient } from "./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 来说是节点名称,对于工具节点来说是工具名称 */
|
|
@@ -164,12 +165,15 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
|
|
|
164
165
|
*/
|
|
165
166
|
async createThread({
|
|
166
167
|
threadId,
|
|
168
|
+
graphId,
|
|
167
169
|
}: {
|
|
168
170
|
threadId?: string;
|
|
171
|
+
graphId?: string;
|
|
169
172
|
} = {}) {
|
|
170
173
|
try {
|
|
171
174
|
this.currentThread = await this.threads.create({
|
|
172
175
|
threadId,
|
|
176
|
+
graphId,
|
|
173
177
|
});
|
|
174
178
|
return this.currentThread;
|
|
175
179
|
} catch (error) {
|
|
@@ -284,6 +288,17 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
|
|
|
284
288
|
this.runs.cancel((this.currentThread as any)!.thread_id, this.currentRun.run_id);
|
|
285
289
|
}
|
|
286
290
|
}
|
|
291
|
+
/**
|
|
292
|
+
* @zh 回滚到指定的消息。但是不会触发数据的重新更新
|
|
293
|
+
* @en Reverts to the specified message.
|
|
294
|
+
*/
|
|
295
|
+
async revertChatTo(messageId: string) {
|
|
296
|
+
const { state, checkpoint } = await revertChatTo(this.client as any, this.currentThread!.thread_id, messageId);
|
|
297
|
+
this.graphState = state;
|
|
298
|
+
this.messageProcessor.clearStreamingMessages();
|
|
299
|
+
this.messageProcessor.setGraphMessages(state.messages! as RenderMessage[]);
|
|
300
|
+
return state;
|
|
301
|
+
}
|
|
287
302
|
/**
|
|
288
303
|
* @zh 发送消息到 LangGraph 后端。
|
|
289
304
|
* @en Sends a message to the LangGraph backend.
|
|
@@ -293,7 +308,7 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
|
|
|
293
308
|
throw new Error("Thread or Assistant not initialized");
|
|
294
309
|
}
|
|
295
310
|
if (!this.currentThread) {
|
|
296
|
-
await this.createThread();
|
|
311
|
+
await this.createThread({ graphId: this.currentAssistant!.graph_id });
|
|
297
312
|
this.emit("thread", {
|
|
298
313
|
event: "thread/create",
|
|
299
314
|
data: {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { RemoveMessage } from "@langchain/core/messages";
|
|
2
|
+
import { Client, Message } from "@langchain/langgraph-sdk";
|
|
3
|
+
|
|
4
|
+
export async function revertChatTo(client: Client<{ messages: Message[] }, { messages: Message[] }, unknown>, threadId: string, messageId: string) {
|
|
5
|
+
const thread = await client.threads.get(threadId);
|
|
6
|
+
const messages = thread.values.messages;
|
|
7
|
+
const idx = messages.findIndex((message) => message.id === messageId);
|
|
8
|
+
if (idx === -1) {
|
|
9
|
+
throw new Error(`Message id ${messageId} not found`);
|
|
10
|
+
}
|
|
11
|
+
const removeMessages = messages.slice(idx + 1);
|
|
12
|
+
const state = {
|
|
13
|
+
...thread.values,
|
|
14
|
+
messages: removeMessages.map((i) => {
|
|
15
|
+
// sb langgraph 官方实现都不能正常工作
|
|
16
|
+
// return new RemoveMessage({ id: i.id! }).toJSON();
|
|
17
|
+
return {
|
|
18
|
+
type: "remove",
|
|
19
|
+
id: i.id!,
|
|
20
|
+
};
|
|
21
|
+
}),
|
|
22
|
+
};
|
|
23
|
+
const res = await client.threads.updateState(threadId, {
|
|
24
|
+
values: state,
|
|
25
|
+
});
|
|
26
|
+
// client.runs.wait();
|
|
27
|
+
return {
|
|
28
|
+
state: {
|
|
29
|
+
messages: messages.slice(0, idx + 1),
|
|
30
|
+
},
|
|
31
|
+
checkpoint: res,
|
|
32
|
+
};
|
|
33
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -52,7 +52,7 @@ export type TypedAsyncGenerator<TStateType = unknown, TUpdateType = TStateType,
|
|
|
52
52
|
/**
|
|
53
53
|
* 兼容 LangGraph SDK 的接口定义,方便进行无侵入式的扩展
|
|
54
54
|
*/
|
|
55
|
-
export interface ILangGraphClient<TStateType =
|
|
55
|
+
export interface ILangGraphClient<TStateType = {}, TUpdateType = TStateType> {
|
|
56
56
|
assistants: {
|
|
57
57
|
search(query?: { graphId?: string; metadata?: Metadata; limit?: number; offset?: number; sortBy?: AssistantSortBy; sortOrder?: SortOrder }): Promise<Assistant[]>;
|
|
58
58
|
getGraph(assistantId: string, options?: { xray?: boolean | number }): Promise<AssistantGraph>;
|
|
@@ -167,16 +167,22 @@ export const createChatStore = (
|
|
|
167
167
|
* @zh 发送消息。
|
|
168
168
|
* @en Sends a message.
|
|
169
169
|
*/
|
|
170
|
-
const sendMessage = async (message?: Message[], extraData?: SendMessageOptions) => {
|
|
171
|
-
if ((!userInput.get().trim() && !message?.length) || loading.get() || !client.get()) return;
|
|
170
|
+
const sendMessage = async (message?: Message[], extraData?: SendMessageOptions, withoutCheck = false) => {
|
|
171
|
+
if ((!withoutCheck && !userInput.get().trim() && !message?.length) || loading.get() || !client.get()) return;
|
|
172
172
|
|
|
173
173
|
loading.set(true);
|
|
174
174
|
inChatError.set(null);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
175
|
+
try {
|
|
176
|
+
await client.get()?.sendMessage(message || userInput.get(), extraData);
|
|
177
|
+
} catch (e) {
|
|
178
|
+
const isThreadRunning = (e as Error).message.includes("422");
|
|
179
|
+
if (isThreadRunning) {
|
|
180
|
+
await client.get()?.resetStream();
|
|
181
|
+
}
|
|
182
|
+
} finally {
|
|
183
|
+
userInput.set("");
|
|
184
|
+
loading.set(false);
|
|
185
|
+
}
|
|
180
186
|
};
|
|
181
187
|
|
|
182
188
|
/**
|
|
@@ -270,6 +276,18 @@ export const createChatStore = (
|
|
|
270
276
|
toggleHistoryVisible,
|
|
271
277
|
refreshHistoryList,
|
|
272
278
|
addToHistory,
|
|
279
|
+
/**
|
|
280
|
+
* @zh 回滚到指定的消息。
|
|
281
|
+
* @en Reverts to the specified message.
|
|
282
|
+
*/
|
|
283
|
+
async revertChatTo(messageId: string, resend = false, sendOptions?: SendMessageOptions) {
|
|
284
|
+
await client.get()?.revertChatTo(messageId);
|
|
285
|
+
if (resend) {
|
|
286
|
+
return sendMessage([], sendOptions, true);
|
|
287
|
+
} else {
|
|
288
|
+
updateUI(client.get()!);
|
|
289
|
+
}
|
|
290
|
+
},
|
|
273
291
|
/**
|
|
274
292
|
* @zh 设置用户输入内容。
|
|
275
293
|
* @en Sets the user input content.
|