@langgraph-js/sdk 3.7.1 → 3.8.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/History.d.ts +115 -0
- package/dist/History.js +226 -0
- package/dist/LangGraphClient.d.ts +10 -1
- package/dist/LangGraphClient.js +17 -3
- package/dist/TestKit.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/react/ChatContext.d.ts +28 -20
- package/dist/react/ChatContext.js +3 -2
- package/dist/ui-store/createChatStore.d.ts +33 -66
- package/dist/ui-store/createChatStore.js +255 -225
- package/dist/vue/ChatContext.d.ts +38 -21
- package/dist/vue/ChatContext.js +5 -0
- package/package.json +1 -1
- package/src/History.ts +294 -0
- package/src/LangGraphClient.ts +25 -3
- package/src/index.ts +1 -0
- package/src/react/ChatContext.ts +5 -1
- package/src/ui-store/createChatStore.ts +310 -236
- package/src/vue/ChatContext.ts +7 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { LangGraphClient, LangGraphClientConfig } from "./LangGraphClient.js";
|
|
2
|
+
import type { Thread } from "@langchain/langgraph-sdk";
|
|
3
|
+
export interface SessionInfo {
|
|
4
|
+
/** 会话唯一标识,同时也是 threadId */
|
|
5
|
+
sessionId: string;
|
|
6
|
+
/** LangGraphClient 实例(懒加载) */
|
|
7
|
+
client?: LangGraphClient;
|
|
8
|
+
/** Thread 信息(懒加载,第一条消息后才创建) */
|
|
9
|
+
thread?: Thread<any>;
|
|
10
|
+
/** Agent 名称 */
|
|
11
|
+
agentName: string;
|
|
12
|
+
}
|
|
13
|
+
export interface CreateSessionOptions {
|
|
14
|
+
/** 会话 ID / Thread ID,不提供则自动生成 */
|
|
15
|
+
sessionId?: string;
|
|
16
|
+
/** Agent 名称 */
|
|
17
|
+
agentName?: string;
|
|
18
|
+
/** 是否从已有 Thread 恢复会话 */
|
|
19
|
+
restore?: boolean;
|
|
20
|
+
/** Graph ID */
|
|
21
|
+
graphId?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* @zh History 类用于管理多个 LangGraphClient 实例,支持多会话场景
|
|
25
|
+
* @en History class manages multiple LangGraphClient instances for multi-session scenarios
|
|
26
|
+
*/
|
|
27
|
+
export declare class History {
|
|
28
|
+
/** 存储所有会话的 Map */
|
|
29
|
+
private sessions;
|
|
30
|
+
/** 当前活跃的会话 ID */
|
|
31
|
+
private activeSessionId;
|
|
32
|
+
/** 客户端配置,用于创建新的 LangGraphClient 实例 */
|
|
33
|
+
private clientConfig;
|
|
34
|
+
/** 虚拟 Client,用于查询操作(不绑定特定 Thread) */
|
|
35
|
+
private virtualClient;
|
|
36
|
+
constructor(clientConfig: LangGraphClientConfig);
|
|
37
|
+
/**
|
|
38
|
+
* @zh 创建新会话(延迟创建 Thread,直到发送第一条消息)
|
|
39
|
+
* @en Creates a new session (lazy Thread creation until first message)
|
|
40
|
+
*/
|
|
41
|
+
createSession(options?: CreateSessionOptions): Promise<SessionInfo>;
|
|
42
|
+
/**
|
|
43
|
+
* @zh 激活指定会话(懒加载创建 Client)
|
|
44
|
+
* @en Activates the specified session (lazy load client)
|
|
45
|
+
*/
|
|
46
|
+
activateSession(sessionId: string): Promise<SessionInfo>;
|
|
47
|
+
/**
|
|
48
|
+
* @zh 获取当前活跃的会话
|
|
49
|
+
* @en Gets the current active session
|
|
50
|
+
*/
|
|
51
|
+
getActiveSession(): SessionInfo | null;
|
|
52
|
+
/**
|
|
53
|
+
* @zh 获取指定会话
|
|
54
|
+
* @en Gets the specified session
|
|
55
|
+
*/
|
|
56
|
+
getSession(sessionId: string): SessionInfo | null;
|
|
57
|
+
/**
|
|
58
|
+
* @zh 获取所有会话
|
|
59
|
+
* @en Gets all sessions
|
|
60
|
+
*/
|
|
61
|
+
getAllSessions(): SessionInfo[];
|
|
62
|
+
/**
|
|
63
|
+
* @zh 删除指定会话
|
|
64
|
+
* @en Deletes the specified session
|
|
65
|
+
*/
|
|
66
|
+
deleteSession(sessionId: string): Promise<boolean>;
|
|
67
|
+
/**
|
|
68
|
+
* @zh 清空所有会话
|
|
69
|
+
* @en Clears all sessions
|
|
70
|
+
*/
|
|
71
|
+
clearAllSessions(): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* @zh 获取会话数量
|
|
74
|
+
* @en Gets the number of sessions
|
|
75
|
+
*/
|
|
76
|
+
getSessionCount(): number;
|
|
77
|
+
/**
|
|
78
|
+
* @zh 生成会话 ID (UUID v4 格式)
|
|
79
|
+
* @en Generates a session ID (UUID v4 format)
|
|
80
|
+
*/
|
|
81
|
+
private generateSessionId;
|
|
82
|
+
/**
|
|
83
|
+
* @zh 从已有的 Thread 添加会话(仅添加元数据,不创建 Client)
|
|
84
|
+
* @en Adds a session from an existing Thread (metadata only, no client created)
|
|
85
|
+
*/
|
|
86
|
+
addSessionFromThread(threadId: string, agentName?: string): Promise<SessionInfo>;
|
|
87
|
+
/**
|
|
88
|
+
* @zh 获取当前活跃的客户端
|
|
89
|
+
* @en Gets the current active client
|
|
90
|
+
*/
|
|
91
|
+
getActiveClient(): LangGraphClient | null;
|
|
92
|
+
/**
|
|
93
|
+
* @zh 从远程列出所有会话
|
|
94
|
+
* @en Lists all sessions from remote
|
|
95
|
+
*/
|
|
96
|
+
listRemoteSessions(options?: {
|
|
97
|
+
sortOrder?: "asc" | "desc";
|
|
98
|
+
sortBy?: "created_at" | "updated_at";
|
|
99
|
+
offset?: number;
|
|
100
|
+
limit?: number;
|
|
101
|
+
}): Promise<Thread<unknown>[]>;
|
|
102
|
+
/**
|
|
103
|
+
* @zh 从远程同步会话到本地(仅同步元数据,不创建 Client)
|
|
104
|
+
* @en Syncs sessions from remote to local (metadata only, no client created)
|
|
105
|
+
*/
|
|
106
|
+
syncFromRemote(options?: {
|
|
107
|
+
limit?: number;
|
|
108
|
+
agentName?: string;
|
|
109
|
+
}): Promise<SessionInfo[]>;
|
|
110
|
+
/**
|
|
111
|
+
* @zh 初始化 History(必须先调用)
|
|
112
|
+
* @en Initializes History (must be called first)
|
|
113
|
+
*/
|
|
114
|
+
init(agentName?: string): Promise<import("@langchain/langgraph-sdk").Assistant | undefined>;
|
|
115
|
+
}
|
package/dist/History.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { LangGraphClient } from "./LangGraphClient.js";
|
|
2
|
+
/**
|
|
3
|
+
* @zh History 类用于管理多个 LangGraphClient 实例,支持多会话场景
|
|
4
|
+
* @en History class manages multiple LangGraphClient instances for multi-session scenarios
|
|
5
|
+
*/
|
|
6
|
+
export class History {
|
|
7
|
+
/** 存储所有会话的 Map */
|
|
8
|
+
sessions = new Map();
|
|
9
|
+
/** 当前活跃的会话 ID */
|
|
10
|
+
activeSessionId = null;
|
|
11
|
+
/** 客户端配置,用于创建新的 LangGraphClient 实例 */
|
|
12
|
+
clientConfig;
|
|
13
|
+
/** 虚拟 Client,用于查询操作(不绑定特定 Thread) */
|
|
14
|
+
virtualClient;
|
|
15
|
+
constructor(clientConfig) {
|
|
16
|
+
this.clientConfig = clientConfig;
|
|
17
|
+
this.virtualClient = new LangGraphClient(clientConfig);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* @zh 创建新会话(延迟创建 Thread,直到发送第一条消息)
|
|
21
|
+
* @en Creates a new session (lazy Thread creation until first message)
|
|
22
|
+
*/
|
|
23
|
+
async createSession(options = {}) {
|
|
24
|
+
const sessionId = options.sessionId || this.generateSessionId();
|
|
25
|
+
const agentName = options.agentName || this.virtualClient.getCurrentAssistant()?.graph_id;
|
|
26
|
+
if (!agentName) {
|
|
27
|
+
throw new Error("Agent name is required. Please call init() first or provide agentName.");
|
|
28
|
+
}
|
|
29
|
+
if (this.sessions.has(sessionId)) {
|
|
30
|
+
throw new Error(`Session ${sessionId} already exists`);
|
|
31
|
+
}
|
|
32
|
+
const sessionInfo = {
|
|
33
|
+
sessionId,
|
|
34
|
+
agentName,
|
|
35
|
+
};
|
|
36
|
+
// 如果是从已有 Thread 恢复,则立即获取 Thread
|
|
37
|
+
if (options.restore) {
|
|
38
|
+
sessionInfo.thread = (await this.virtualClient.threads.get(sessionId));
|
|
39
|
+
}
|
|
40
|
+
// 否则 thread 为 undefined,等待第一条消息时由 Client 自动创建
|
|
41
|
+
this.sessions.set(sessionId, sessionInfo);
|
|
42
|
+
return sessionInfo;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* @zh 激活指定会话(懒加载创建 Client)
|
|
46
|
+
* @en Activates the specified session (lazy load client)
|
|
47
|
+
*/
|
|
48
|
+
async activateSession(sessionId) {
|
|
49
|
+
const session = this.sessions.get(sessionId);
|
|
50
|
+
if (!session) {
|
|
51
|
+
throw new Error(`Session ${sessionId} not found`);
|
|
52
|
+
}
|
|
53
|
+
// 懒加载:只在激活时创建 Client
|
|
54
|
+
if (!session.client) {
|
|
55
|
+
const client = new LangGraphClient(this.clientConfig);
|
|
56
|
+
await client.initAssistant(session.agentName);
|
|
57
|
+
// 只有在有 thread 的情况下才重置(恢复已有会话)
|
|
58
|
+
// 新会话的 thread 会在发送第一条消息时自动创建
|
|
59
|
+
if (session.thread) {
|
|
60
|
+
await client.resetThread(session.agentName, sessionId);
|
|
61
|
+
}
|
|
62
|
+
session.client = client;
|
|
63
|
+
}
|
|
64
|
+
const lastSession = this.activeSessionId && this.sessions.get(this.activeSessionId);
|
|
65
|
+
// 空闲的 client 就需要销毁
|
|
66
|
+
if (lastSession && lastSession.client?.status === "idle") {
|
|
67
|
+
lastSession.client?.reset();
|
|
68
|
+
lastSession.client = undefined;
|
|
69
|
+
}
|
|
70
|
+
this.activeSessionId = sessionId;
|
|
71
|
+
return session;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* @zh 获取当前活跃的会话
|
|
75
|
+
* @en Gets the current active session
|
|
76
|
+
*/
|
|
77
|
+
getActiveSession() {
|
|
78
|
+
if (!this.activeSessionId) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
return this.sessions.get(this.activeSessionId) || null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* @zh 获取指定会话
|
|
85
|
+
* @en Gets the specified session
|
|
86
|
+
*/
|
|
87
|
+
getSession(sessionId) {
|
|
88
|
+
return this.sessions.get(sessionId) || null;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* @zh 获取所有会话
|
|
92
|
+
* @en Gets all sessions
|
|
93
|
+
*/
|
|
94
|
+
getAllSessions() {
|
|
95
|
+
return Array.from(this.sessions.values());
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* @zh 删除指定会话
|
|
99
|
+
* @en Deletes the specified session
|
|
100
|
+
*/
|
|
101
|
+
async deleteSession(sessionId) {
|
|
102
|
+
const session = this.sessions.get(sessionId);
|
|
103
|
+
if (!session) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
// 如果删除的是当前活跃会话,清空活跃会话
|
|
107
|
+
if (this.activeSessionId === sessionId) {
|
|
108
|
+
this.activeSessionId = null;
|
|
109
|
+
}
|
|
110
|
+
// 删除对应的远程 Thread
|
|
111
|
+
try {
|
|
112
|
+
await this.virtualClient.deleteThread(sessionId);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.warn(`Failed to delete thread for session ${sessionId}:`, error);
|
|
116
|
+
}
|
|
117
|
+
this.sessions.delete(sessionId);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* @zh 清空所有会话
|
|
122
|
+
* @en Clears all sessions
|
|
123
|
+
*/
|
|
124
|
+
async clearAllSessions() {
|
|
125
|
+
const sessionIds = Array.from(this.sessions.keys());
|
|
126
|
+
for (const sessionId of sessionIds) {
|
|
127
|
+
await this.deleteSession(sessionId);
|
|
128
|
+
}
|
|
129
|
+
this.activeSessionId = null;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* @zh 获取会话数量
|
|
133
|
+
* @en Gets the number of sessions
|
|
134
|
+
*/
|
|
135
|
+
getSessionCount() {
|
|
136
|
+
return this.sessions.size;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* @zh 生成会话 ID (UUID v4 格式)
|
|
140
|
+
* @en Generates a session ID (UUID v4 format)
|
|
141
|
+
*/
|
|
142
|
+
generateSessionId() {
|
|
143
|
+
// 优先使用 crypto.randomUUID (Node.js 15.6+, 浏览器支持)
|
|
144
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
145
|
+
return crypto.randomUUID();
|
|
146
|
+
}
|
|
147
|
+
// 降级方案:生成符合 UUID v4 格式的随机 ID
|
|
148
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
149
|
+
const r = (Math.random() * 16) | 0;
|
|
150
|
+
const v = c === "x" ? r : (r & 0x3) | 0x8;
|
|
151
|
+
return v.toString(16);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* @zh 从已有的 Thread 添加会话(仅添加元数据,不创建 Client)
|
|
156
|
+
* @en Adds a session from an existing Thread (metadata only, no client created)
|
|
157
|
+
*/
|
|
158
|
+
async addSessionFromThread(threadId, agentName) {
|
|
159
|
+
const agent = agentName || this.virtualClient.getCurrentAssistant()?.graph_id;
|
|
160
|
+
if (!agent) {
|
|
161
|
+
throw new Error("Agent name is required. Please call init() first or provide agentName.");
|
|
162
|
+
}
|
|
163
|
+
return this.createSession({
|
|
164
|
+
sessionId: threadId,
|
|
165
|
+
agentName: agent,
|
|
166
|
+
restore: true,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* @zh 获取当前活跃的客户端
|
|
171
|
+
* @en Gets the current active client
|
|
172
|
+
*/
|
|
173
|
+
getActiveClient() {
|
|
174
|
+
const session = this.getActiveSession();
|
|
175
|
+
return session?.client || null;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* @zh 从远程列出所有会话
|
|
179
|
+
* @en Lists all sessions from remote
|
|
180
|
+
*/
|
|
181
|
+
async listRemoteSessions(options = {}) {
|
|
182
|
+
return this.virtualClient.listThreads(options);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* @zh 从远程同步会话到本地(仅同步元数据,不创建 Client)
|
|
186
|
+
* @en Syncs sessions from remote to local (metadata only, no client created)
|
|
187
|
+
*/
|
|
188
|
+
async syncFromRemote(options = {}) {
|
|
189
|
+
const agentName = options.agentName || this.virtualClient.getCurrentAssistant()?.graph_id;
|
|
190
|
+
if (!agentName) {
|
|
191
|
+
throw new Error("Agent name is required. Please call init() first or provide agentName.");
|
|
192
|
+
}
|
|
193
|
+
const threads = await this.listRemoteSessions({
|
|
194
|
+
limit: options.limit || 100,
|
|
195
|
+
sortBy: "updated_at",
|
|
196
|
+
sortOrder: "desc",
|
|
197
|
+
});
|
|
198
|
+
const syncedSessions = [];
|
|
199
|
+
for (const thread of threads) {
|
|
200
|
+
const threadId = thread.thread_id;
|
|
201
|
+
// 更新或创建会话信息
|
|
202
|
+
if (this.sessions.has(threadId)) {
|
|
203
|
+
const session = this.sessions.get(threadId);
|
|
204
|
+
session.thread = thread;
|
|
205
|
+
syncedSessions.push(session);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
const sessionInfo = {
|
|
209
|
+
sessionId: threadId,
|
|
210
|
+
thread,
|
|
211
|
+
agentName,
|
|
212
|
+
};
|
|
213
|
+
this.sessions.set(threadId, sessionInfo);
|
|
214
|
+
syncedSessions.push(sessionInfo);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return syncedSessions;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* @zh 初始化 History(必须先调用)
|
|
221
|
+
* @en Initializes History (must be called first)
|
|
222
|
+
*/
|
|
223
|
+
async init(agentName) {
|
|
224
|
+
return this.virtualClient.initAssistant(agentName);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -139,6 +139,8 @@ export declare class LangGraphClient<TStateType = unknown> extends EventEmitter<
|
|
|
139
139
|
/** Message 处理器 */
|
|
140
140
|
private messageProcessor;
|
|
141
141
|
private legacyMode;
|
|
142
|
+
/** 当前流式状态 */
|
|
143
|
+
private _status;
|
|
142
144
|
constructor(config: LangGraphClientConfig);
|
|
143
145
|
/** 代理 assistants 属性到内部 client */
|
|
144
146
|
get assistants(): {
|
|
@@ -179,6 +181,8 @@ export declare class LangGraphClient<TStateType = unknown> extends EventEmitter<
|
|
|
179
181
|
};
|
|
180
182
|
/** 代理 runs 属性到内部 client */
|
|
181
183
|
get runs(): ILangGraphClient["runs"];
|
|
184
|
+
/** 获取当前流式状态 */
|
|
185
|
+
get status(): "error" | "idle" | "busy" | "interrupted";
|
|
182
186
|
private listAssistants;
|
|
183
187
|
/**
|
|
184
188
|
* @zh 初始化 Assistant。
|
|
@@ -200,7 +204,12 @@ export declare class LangGraphClient<TStateType = unknown> extends EventEmitter<
|
|
|
200
204
|
* @zh 列出所有的 Thread。
|
|
201
205
|
* @en Lists all Threads.
|
|
202
206
|
*/
|
|
203
|
-
listThreads(
|
|
207
|
+
listThreads(options?: {
|
|
208
|
+
sortOrder?: "asc" | "desc";
|
|
209
|
+
sortBy?: "created_at" | "updated_at";
|
|
210
|
+
offset?: number;
|
|
211
|
+
limit?: number;
|
|
212
|
+
}): Promise<Thread<TStateType>[]>;
|
|
204
213
|
deleteThread(threadId: string): Promise<void>;
|
|
205
214
|
/**
|
|
206
215
|
* @zh 从历史中恢复 Thread 数据。
|
package/dist/LangGraphClient.js
CHANGED
|
@@ -19,6 +19,8 @@ export class LangGraphClient extends EventEmitter {
|
|
|
19
19
|
/** Message 处理器 */
|
|
20
20
|
messageProcessor;
|
|
21
21
|
legacyMode;
|
|
22
|
+
/** 当前流式状态 */
|
|
23
|
+
_status = "idle";
|
|
22
24
|
constructor(config) {
|
|
23
25
|
super();
|
|
24
26
|
this.client = config.client;
|
|
@@ -37,6 +39,10 @@ export class LangGraphClient extends EventEmitter {
|
|
|
37
39
|
get runs() {
|
|
38
40
|
return this.client.runs;
|
|
39
41
|
}
|
|
42
|
+
/** 获取当前流式状态 */
|
|
43
|
+
get status() {
|
|
44
|
+
return this._status;
|
|
45
|
+
}
|
|
40
46
|
listAssistants() {
|
|
41
47
|
return this.assistants.search({
|
|
42
48
|
metadata: null,
|
|
@@ -103,10 +109,12 @@ export class LangGraphClient extends EventEmitter {
|
|
|
103
109
|
* @zh 列出所有的 Thread。
|
|
104
110
|
* @en Lists all Threads.
|
|
105
111
|
*/
|
|
106
|
-
async listThreads() {
|
|
112
|
+
async listThreads(options = {}) {
|
|
107
113
|
return this.threads.search({
|
|
108
|
-
sortOrder: "desc",
|
|
109
|
-
sortBy: "updated_at",
|
|
114
|
+
sortOrder: options.sortOrder || "desc",
|
|
115
|
+
sortBy: options.sortBy || "updated_at",
|
|
116
|
+
offset: options.offset || 0,
|
|
117
|
+
limit: options.limit || 10,
|
|
110
118
|
});
|
|
111
119
|
}
|
|
112
120
|
async deleteThread(threadId) {
|
|
@@ -229,6 +237,7 @@ export class LangGraphClient extends EventEmitter {
|
|
|
229
237
|
},
|
|
230
238
|
];
|
|
231
239
|
const streamRecord = [];
|
|
240
|
+
this._status = "busy";
|
|
232
241
|
this.emit("start", {
|
|
233
242
|
event: "start",
|
|
234
243
|
});
|
|
@@ -275,6 +284,7 @@ export class LangGraphClient extends EventEmitter {
|
|
|
275
284
|
if (data)
|
|
276
285
|
streamRecord.push(...data);
|
|
277
286
|
this.humanInTheLoop = null;
|
|
287
|
+
this._status = "idle";
|
|
278
288
|
this.emit("done", {
|
|
279
289
|
event: "done",
|
|
280
290
|
});
|
|
@@ -306,6 +316,7 @@ export class LangGraphClient extends EventEmitter {
|
|
|
306
316
|
this.currentRun = chunk.data;
|
|
307
317
|
}
|
|
308
318
|
else if (chunk.event === "error" || chunk.event === "Error" || chunk.event === "__stream_error__") {
|
|
319
|
+
this._status = "error";
|
|
309
320
|
this.emit("error", chunk);
|
|
310
321
|
}
|
|
311
322
|
else if (chunk.event === "messages/metadata") {
|
|
@@ -322,6 +333,7 @@ export class LangGraphClient extends EventEmitter {
|
|
|
322
333
|
else if (chunk.event === "values") {
|
|
323
334
|
const data = chunk.data;
|
|
324
335
|
if (data.__interrupt__) {
|
|
336
|
+
this._status = "interrupted";
|
|
325
337
|
this.humanInTheLoop = camelcaseKeys(data.__interrupt__, {
|
|
326
338
|
deep: true,
|
|
327
339
|
});
|
|
@@ -361,6 +373,7 @@ export class LangGraphClient extends EventEmitter {
|
|
|
361
373
|
// json 校验
|
|
362
374
|
return this.callFETool(toolMessage, tool.args);
|
|
363
375
|
});
|
|
376
|
+
this._status = "interrupted";
|
|
364
377
|
this.currentThread.status = "interrupted"; // 修复某些机制下,状态不为 interrupted 与后端有差异
|
|
365
378
|
return Promise.all(result);
|
|
366
379
|
}
|
|
@@ -421,6 +434,7 @@ export class LangGraphClient extends EventEmitter {
|
|
|
421
434
|
this.messageProcessor.clearStreamingMessages();
|
|
422
435
|
this.currentRun = undefined;
|
|
423
436
|
this.tools.clearWaiting();
|
|
437
|
+
this._status = "idle";
|
|
424
438
|
this.emit("value", {
|
|
425
439
|
event: "messages/partial",
|
|
426
440
|
data: {
|
package/dist/TestKit.d.ts
CHANGED
|
@@ -89,7 +89,7 @@ export declare class TestLangGraphChat {
|
|
|
89
89
|
* @zh 准备测试环境,初始化客户端连接
|
|
90
90
|
* @en Prepare test environment, initialize client connection
|
|
91
91
|
*/
|
|
92
|
-
ready(): Promise<import("./
|
|
92
|
+
ready(): Promise<import("./History.js").History> | undefined;
|
|
93
93
|
/**
|
|
94
94
|
* @zh 模拟人类输入消息并等待测试任务完成,这是测试的核心方法
|
|
95
95
|
* @en Simulate human input and wait for test tasks to complete, this is the core test method
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -7,51 +7,57 @@ export declare const useChat: () => UnionStore<{
|
|
|
7
7
|
currentArtifactId: import("nanostores").PreinitializedWritableAtom<[string, string] | null> & object;
|
|
8
8
|
showArtifact: import("nanostores").PreinitializedWritableAtom<boolean> & object;
|
|
9
9
|
client: import("nanostores").PreinitializedWritableAtom<import("../LangGraphClient.js").LangGraphClient<unknown> | null> & object;
|
|
10
|
+
history: import("nanostores").PreinitializedWritableAtom<import("../History.js").History | null> & object;
|
|
11
|
+
sessions: import("nanostores").PreinitializedWritableAtom<import("../History.js").SessionInfo[]> & object;
|
|
10
12
|
renderMessages: import("nanostores").PreinitializedWritableAtom<import("../LangGraphClient.js").RenderMessage[]> & object;
|
|
11
13
|
userInput: import("nanostores").PreinitializedWritableAtom<string> & object;
|
|
12
14
|
loading: import("nanostores").PreinitializedWritableAtom<boolean> & object;
|
|
13
15
|
inChatError: import("nanostores").PreinitializedWritableAtom<string | null> & object;
|
|
14
16
|
currentAgent: import("nanostores").PreinitializedWritableAtom<string> & object;
|
|
17
|
+
currentChatId: import("nanostores").PreinitializedWritableAtom<string | null> & object;
|
|
18
|
+
currentNodeName: import("nanostores").PreinitializedWritableAtom<string> & object;
|
|
19
|
+
tools: import("nanostores").PreinitializedWritableAtom<import("../index.js").UnionTool<any, Object, any>[]> & object;
|
|
15
20
|
collapsedTools: import("nanostores").PreinitializedWritableAtom<string[]> & object;
|
|
21
|
+
showGraph: import("nanostores").PreinitializedWritableAtom<boolean> & object;
|
|
22
|
+
graphVisualize: import("nanostores").PreinitializedWritableAtom<import("@langchain/langgraph-sdk").AssistantGraph | null> & object;
|
|
16
23
|
showHistory: import("nanostores").PreinitializedWritableAtom<boolean> & object;
|
|
17
24
|
historyList: import("nanostores").PreinitializedWritableAtom<import("@langchain/langgraph-sdk").Thread<{
|
|
18
25
|
messages: import("@langchain/langgraph-sdk").Message[];
|
|
19
26
|
}>[]> & object;
|
|
20
|
-
currentChatId: import("nanostores").PreinitializedWritableAtom<string | null> & object;
|
|
21
|
-
showGraph: import("nanostores").PreinitializedWritableAtom<boolean> & object;
|
|
22
|
-
graphVisualize: import("nanostores").PreinitializedWritableAtom<import("@langchain/langgraph-sdk").AssistantGraph | null> & object;
|
|
23
|
-
currentNodeName: import("nanostores").PreinitializedWritableAtom<string> & object;
|
|
24
|
-
tools: import("nanostores").PreinitializedWritableAtom<import("../index.js").UnionTool<any, Object, any>[]> & object;
|
|
25
27
|
};
|
|
26
28
|
mutations: {
|
|
27
29
|
setCurrentArtifactById: (id: string, tool_id: string) => void;
|
|
28
30
|
setShowArtifact: (show: boolean) => void;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
initClient: () => Promise<import("../History.js").History>;
|
|
32
|
+
getClient: () => import("../LangGraphClient.js").LangGraphClient<unknown> | null;
|
|
33
|
+
getHistory: () => import("../History.js").History | null;
|
|
34
|
+
activateSession: (sessionId: string) => Promise<void>;
|
|
35
|
+
createNewSession: () => Promise<void>;
|
|
36
|
+
refreshSessionList: () => Promise<void>;
|
|
37
|
+
refreshHistoryList: () => Promise<void>;
|
|
34
38
|
sendMessage: (message?: import("@langchain/langgraph-sdk").Message[], extraData?: import("../LangGraphClient.js").SendMessageOptions, withoutCheck?: boolean) => Promise<void>;
|
|
35
39
|
stopGeneration: () => void;
|
|
40
|
+
setUserInput: (input: string) => void;
|
|
41
|
+
revertChatTo(messageId: string, resend?: boolean, sendOptions?: import("../LangGraphClient.js").SendMessageOptions & import("../time-travel/index.js").RevertChatToOptions): Promise<void>;
|
|
42
|
+
refreshTools: () => Promise<void>;
|
|
43
|
+
setTools(new_tools: import("../index.js").UnionTool<any>[]): void;
|
|
36
44
|
toggleToolCollapse: (toolId: string) => void;
|
|
45
|
+
getToolUIRender: (tool_name: string) => ((message: import("../LangGraphClient.js").RenderMessage) => Object) | null;
|
|
46
|
+
isFELocking: () => boolean | undefined;
|
|
37
47
|
toggleHistoryVisible: () => void;
|
|
38
|
-
|
|
48
|
+
toggleGraphVisible(): void;
|
|
49
|
+
refreshGraph: () => Promise<void>;
|
|
50
|
+
setCurrentAgent(agent: string): Promise<import("../History.js").History>;
|
|
39
51
|
addToHistory: (thread: import("@langchain/langgraph-sdk").Thread<{
|
|
40
52
|
messages: import("@langchain/langgraph-sdk").Message[];
|
|
41
53
|
}>) => void;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
setCurrentAgent(agent: string): Promise<void>;
|
|
45
|
-
toggleGraphVisible(): void;
|
|
46
|
-
refreshGraph: () => Promise<void>;
|
|
47
|
-
createNewChat(): void;
|
|
48
|
-
toHistoryChat(thread: import("@langchain/langgraph-sdk").Thread<{
|
|
54
|
+
createNewChat: () => Promise<void>;
|
|
55
|
+
toHistoryChat: (thread: import("@langchain/langgraph-sdk").Thread<{
|
|
49
56
|
messages: import("@langchain/langgraph-sdk").Message[];
|
|
50
|
-
}>)
|
|
57
|
+
}>) => Promise<void>;
|
|
51
58
|
deleteHistoryChat(thread: import("@langchain/langgraph-sdk").Thread<{
|
|
52
59
|
messages: import("@langchain/langgraph-sdk").Message[];
|
|
53
60
|
}>): Promise<void>;
|
|
54
|
-
getToolUIRender: (tool_name: string) => ((message: import("../LangGraphClient.js").RenderMessage) => Object) | null;
|
|
55
61
|
};
|
|
56
62
|
}>;
|
|
57
63
|
interface ChatProviderProps {
|
|
@@ -63,6 +69,8 @@ interface ChatProviderProps {
|
|
|
63
69
|
showHistory?: boolean;
|
|
64
70
|
showGraph?: boolean;
|
|
65
71
|
fallbackToAvailableAssistants?: boolean;
|
|
72
|
+
/** 初始化时是否自动激活最近的历史会话(默认 false,创建新会话) */
|
|
73
|
+
autoRestoreLastSession?: boolean;
|
|
66
74
|
onInitError?: (error: any, currentAgent: string) => void;
|
|
67
75
|
client?: ILangGraphClient;
|
|
68
76
|
legacyMode?: boolean;
|
|
@@ -9,7 +9,7 @@ export const useChat = () => {
|
|
|
9
9
|
}
|
|
10
10
|
return context;
|
|
11
11
|
};
|
|
12
|
-
export const ChatProvider = ({ children, defaultAgent = "", apiUrl = "http://localhost:8123", defaultHeaders, withCredentials = false, showHistory = false, showGraph = false, fallbackToAvailableAssistants = false, onInitError, client, legacyMode = false, }) => {
|
|
12
|
+
export const ChatProvider = ({ children, defaultAgent = "", apiUrl = "http://localhost:8123", defaultHeaders, withCredentials = false, showHistory = false, showGraph = false, fallbackToAvailableAssistants = false, autoRestoreLastSession = false, onInitError, client, legacyMode = false, }) => {
|
|
13
13
|
// 使用 useMemo 稳定 defaultHeaders 的引用
|
|
14
14
|
const stableHeaders = useMemo(() => defaultHeaders || {}, [defaultHeaders]);
|
|
15
15
|
// 使用 useRef 保存 onInitError 的最新引用
|
|
@@ -40,8 +40,9 @@ export const ChatProvider = ({ children, defaultAgent = "", apiUrl = "http://loc
|
|
|
40
40
|
showHistory,
|
|
41
41
|
showGraph,
|
|
42
42
|
fallbackToAvailableAssistants,
|
|
43
|
+
autoRestoreLastSession,
|
|
43
44
|
});
|
|
44
|
-
}, [defaultAgent, apiUrl, stableHeaders, withCredentials, showHistory, showGraph, fallbackToAvailableAssistants]);
|
|
45
|
+
}, [defaultAgent, apiUrl, stableHeaders, withCredentials, showHistory, showGraph, fallbackToAvailableAssistants, autoRestoreLastSession]);
|
|
45
46
|
const unionStore = useUnionStore(store, useStore);
|
|
46
47
|
// 使用 ref 标记是否已初始化
|
|
47
48
|
const initializedRef = useRef(false);
|