@langgraph-js/sdk 1.10.4 → 1.12.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.
@@ -35,6 +35,7 @@ export type RenderMessage = Message & {
35
35
  };
36
36
  }[];
37
37
  };
38
+ sub_agent_messages?: RenderMessage[];
38
39
  usage_metadata?: {
39
40
  total_tokens: number;
40
41
  input_tokens: number;
@@ -57,6 +58,7 @@ export type SendMessageOptions = {
57
58
  streamResponse?: any;
58
59
  };
59
60
  command?: Command;
61
+ joinRunId?: string;
60
62
  };
61
63
  export interface LangGraphClientConfig {
62
64
  apiUrl?: string;
@@ -90,6 +92,8 @@ export declare class LangGraphClient extends Client {
90
92
  private streamingCallbacks;
91
93
  tools: ToolManager;
92
94
  stopController: AbortController | null;
95
+ /** 用于存储 subAgent 状态数据的键 */
96
+ subAgentsKey: string;
93
97
  constructor(config: LangGraphClientConfig);
94
98
  availableAssistants: Assistant[];
95
99
  private listAssistants;
@@ -115,7 +119,8 @@ export declare class LangGraphClient extends Client {
115
119
  * @zh 从历史中恢复 Thread 数据。
116
120
  * @en Resets the Thread data from history.
117
121
  */
118
- resetThread(agent: string, threadId: string): Promise<void>;
122
+ resetThread(agent: string, threadId: string): Promise<Thread<import("@langchain/langgraph-sdk").DefaultValues>>;
123
+ resetStream(): Promise<void>;
119
124
  streamingMessage: RenderMessage[];
120
125
  /** 图发过来的更新信息 */
121
126
  graphMessages: RenderMessage[];
@@ -128,6 +133,8 @@ export declare class LangGraphClient extends Client {
128
133
  * @en Messages used for streaming rendering in the UI.
129
134
  */
130
135
  get renderMessage(): RenderMessage[];
136
+ /** 转换 subAgent 消息为工具的子消息 */
137
+ private convertSubAgentMessages;
131
138
  /**
132
139
  * @zh 为消息附加额外的信息,如耗时、唯一 ID 等。
133
140
  * @en Attaches additional information to messages, such as spend time, unique ID, etc.
@@ -168,7 +175,7 @@ export declare class LangGraphClient extends Client {
168
175
  * @zh 发送消息到 LangGraph 后端。
169
176
  * @en Sends a message to the LangGraph backend.
170
177
  */
171
- sendMessage(input: string | Message[], { extraParams, _debug, command }?: SendMessageOptions): Promise<any[]>;
178
+ sendMessage(input: string | Message[], { joinRunId, extraParams, _debug, command }?: SendMessageOptions): Promise<any[]>;
172
179
  /** 当前子图位置,但是依赖 stream,不太适合稳定使用*/
173
180
  private graphPosition;
174
181
  getGraphPosition(): {
@@ -32,6 +32,8 @@ export class LangGraphClient extends Client {
32
32
  this.streamingCallbacks = new Set();
33
33
  this.tools = new ToolManager();
34
34
  this.stopController = null;
35
+ /** 用于存储 subAgent 状态数据的键 */
36
+ this.subAgentsKey = "task_store";
35
37
  this.availableAssistants = [];
36
38
  this.streamingMessage = [];
37
39
  /** 图发过来的更新信息 */
@@ -112,10 +114,11 @@ export class LangGraphClient extends Client {
112
114
  * @en Resets the Thread data from history.
113
115
  */
114
116
  async resetThread(agent, threadId) {
117
+ var _a;
115
118
  await this.initAssistant(agent);
116
119
  this.currentThread = await this.threads.get(threadId);
117
120
  this.graphState = this.currentThread.values;
118
- this.graphMessages = this.graphState.messages;
121
+ this.graphMessages = ((_a = this.graphState) === null || _a === void 0 ? void 0 : _a.messages) || [];
119
122
  this.emitStreamingUpdate({
120
123
  type: "value",
121
124
  data: {
@@ -125,6 +128,15 @@ export class LangGraphClient extends Client {
125
128
  },
126
129
  },
127
130
  });
131
+ return this.currentThread;
132
+ }
133
+ // 从历史中恢复时,应该恢复流式状态
134
+ async resetStream() {
135
+ const runs = await this.runs.list(this.currentThread.thread_id);
136
+ const runningRun = runs === null || runs === void 0 ? void 0 : runs.find((run) => run.status === "running" || run.status === "pending");
137
+ if (runningRun) {
138
+ await this.sendMessage([], { joinRunId: runningRun.run_id });
139
+ }
128
140
  }
129
141
  cloneMessage(message) {
130
142
  return JSON.parse(JSON.stringify(message));
@@ -215,7 +227,56 @@ export class LangGraphClient extends Client {
215
227
  result.unshift(message);
216
228
  }
217
229
  }
218
- return this.attachInfoForMessage(this.composeToolMessages(result));
230
+ return this.convertSubAgentMessages(this.attachInfoForMessage(this.composeToolMessages(result)));
231
+ }
232
+ /** 转换 subAgent 消息为工具的子消息 */
233
+ convertSubAgentMessages(messages) {
234
+ const origin_task_store = this.graphState[this.subAgentsKey];
235
+ if (!origin_task_store)
236
+ return messages;
237
+ const task_store = JSON.parse(JSON.stringify(origin_task_store));
238
+ console.log(messages);
239
+ /** 获取 subAgent 消息的 id,用于流式过程中对数据进行标记 */
240
+ messages
241
+ .filter((i) => {
242
+ var _a;
243
+ return (_a = i.node_name) === null || _a === void 0 ? void 0 : _a.startsWith("subagent_");
244
+ })
245
+ .forEach((i) => {
246
+ const tool_call_id = i.node_name.replace("subagent_", "");
247
+ const store = task_store[tool_call_id];
248
+ if (store) {
249
+ // 根据 id 进行去重
250
+ const exists = store.messages.some((msg) => msg.id === i.id);
251
+ if (!exists) {
252
+ store.messages.push(i);
253
+ }
254
+ }
255
+ else {
256
+ task_store[tool_call_id] = {
257
+ messages: [i],
258
+ };
259
+ }
260
+ });
261
+ const ignoreIds = new Set();
262
+ Object.values(task_store).forEach((task) => {
263
+ task.messages.forEach((message) => {
264
+ ignoreIds.add(message.id);
265
+ });
266
+ });
267
+ const result = [];
268
+ for (const message of messages) {
269
+ if (message.type === "tool" && message.tool_call_id) {
270
+ const task = task_store[message.tool_call_id];
271
+ if (task) {
272
+ message.sub_agent_messages = this.attachInfoForMessage(this.composeToolMessages(task.messages));
273
+ }
274
+ }
275
+ if (message.id && ignoreIds.has(message.id))
276
+ continue;
277
+ result.push(message);
278
+ }
279
+ return result;
219
280
  }
220
281
  /**
221
282
  * @zh 为消息附加额外的信息,如耗时、唯一 ID 等。
@@ -352,7 +413,7 @@ export class LangGraphClient extends Client {
352
413
  * @zh 发送消息到 LangGraph 后端。
353
414
  * @en Sends a message to the LangGraph backend.
354
415
  */
355
- async sendMessage(input, { extraParams, _debug, command } = {}) {
416
+ async sendMessage(input, { joinRunId, extraParams, _debug, command } = {}) {
356
417
  var _a;
357
418
  if (!this.currentAssistant) {
358
419
  throw new Error("Thread or Assistant not initialized");
@@ -377,8 +438,14 @@ export class LangGraphClient extends Client {
377
438
  content: input,
378
439
  },
379
440
  ];
380
- const streamResponse = (_debug === null || _debug === void 0 ? void 0 : _debug.streamResponse) ||
381
- this.runs.stream(this.currentThread.thread_id, this.currentAssistant.assistant_id, {
441
+ const createStreamResponse = async () => {
442
+ if (_debug === null || _debug === void 0 ? void 0 : _debug.streamResponse) {
443
+ return _debug.streamResponse;
444
+ }
445
+ if (joinRunId) {
446
+ return this.runs.joinStream(this.currentThread.thread_id, joinRunId);
447
+ }
448
+ return this.runs.stream(this.currentThread.thread_id, this.currentAssistant.assistant_id, {
382
449
  input: {
383
450
  ...this.graphState,
384
451
  ...this.extraParams,
@@ -390,6 +457,8 @@ export class LangGraphClient extends Client {
390
457
  streamSubgraphs: true,
391
458
  command,
392
459
  });
460
+ };
461
+ const streamResponse = await createStreamResponse();
393
462
  const streamRecord = [];
394
463
  this.emitStreamingUpdate({
395
464
  type: "start",
package/dist/TestKit.d.ts CHANGED
@@ -158,6 +158,7 @@ export declare class TestLangGraphChat {
158
158
  };
159
159
  }[];
160
160
  };
161
+ sub_agent_messages?: RenderMessage[];
161
162
  usage_metadata?: {
162
163
  total_tokens: number;
163
164
  input_tokens: number;
@@ -182,6 +183,7 @@ export declare class TestLangGraphChat {
182
183
  };
183
184
  }[];
184
185
  };
186
+ sub_agent_messages?: RenderMessage[];
185
187
  usage_metadata?: {
186
188
  total_tokens: number;
187
189
  input_tokens: number;
@@ -206,6 +208,7 @@ export declare class TestLangGraphChat {
206
208
  };
207
209
  }[];
208
210
  };
211
+ sub_agent_messages?: RenderMessage[];
209
212
  usage_metadata?: {
210
213
  total_tokens: number;
211
214
  input_tokens: number;
@@ -84,7 +84,7 @@ export declare const createChatStore: (initClientName: string, config: LangGraph
84
84
  */
85
85
  toHistoryChat(thread: Thread<{
86
86
  messages: Message[];
87
- }>): void;
87
+ }>): Promise<Thread<import("@langchain/langgraph-sdk").DefaultValues> | undefined>;
88
88
  /**
89
89
  * @zh 删除指定的历史聊天会话。
90
90
  * @en Deletes the specified historical chat session.
@@ -283,11 +283,15 @@ export const createChatStore = (initClientName, config, context = {}) => {
283
283
  * @zh 切换到指定的历史聊天会话。
284
284
  * @en Switches to the specified historical chat session.
285
285
  */
286
- toHistoryChat(thread) {
287
- var _a, _b;
286
+ async toHistoryChat(thread) {
287
+ var _a, _b, _c;
288
288
  inChatError.set(null);
289
289
  loading.set(false);
290
- (_a = client.get()) === null || _a === void 0 ? void 0 : _a.resetThread((_b = thread.metadata) === null || _b === void 0 ? void 0 : _b.graph_id, thread.thread_id);
290
+ const nowThread = await ((_a = client.get()) === null || _a === void 0 ? void 0 : _a.resetThread((_b = thread.metadata) === null || _b === void 0 ? void 0 : _b.graph_id, thread.thread_id));
291
+ if (nowThread) {
292
+ (_c = client.get()) === null || _c === void 0 ? void 0 : _c.resetStream();
293
+ }
294
+ return nowThread;
291
295
  },
292
296
  /**
293
297
  * @zh 删除指定的历史聊天会话。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langgraph-js/sdk",
3
- "version": "1.10.4",
3
+ "version": "1.12.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",
@@ -35,6 +35,7 @@ export type RenderMessage = Message & {
35
35
  };
36
36
  }[];
37
37
  };
38
+ sub_agent_messages?: RenderMessage[];
38
39
  usage_metadata?: {
39
40
  total_tokens: number;
40
41
  input_tokens: number;
@@ -55,6 +56,7 @@ export type SendMessageOptions = {
55
56
  extraParams?: Record<string, any>;
56
57
  _debug?: { streamResponse?: any };
57
58
  command?: Command;
59
+ joinRunId?: string;
58
60
  };
59
61
  export interface LangGraphClientConfig {
60
62
  apiUrl?: string;
@@ -101,6 +103,8 @@ export class LangGraphClient extends Client {
101
103
  private streamingCallbacks: Set<StreamingUpdateCallback> = new Set();
102
104
  tools: ToolManager = new ToolManager();
103
105
  stopController: AbortController | null = null;
106
+ /** 用于存储 subAgent 状态数据的键 */
107
+ subAgentsKey = "task_store";
104
108
 
105
109
  constructor(config: LangGraphClientConfig) {
106
110
  super(config);
@@ -182,7 +186,7 @@ export class LangGraphClient extends Client {
182
186
  await this.initAssistant(agent);
183
187
  this.currentThread = await this.threads.get(threadId);
184
188
  this.graphState = this.currentThread.values;
185
- this.graphMessages = this.graphState.messages;
189
+ this.graphMessages = this.graphState?.messages || [];
186
190
  this.emitStreamingUpdate({
187
191
  type: "value",
188
192
  data: {
@@ -192,6 +196,15 @@ export class LangGraphClient extends Client {
192
196
  },
193
197
  },
194
198
  });
199
+ return this.currentThread;
200
+ }
201
+ // 从历史中恢复时,应该恢复流式状态
202
+ async resetStream() {
203
+ const runs = await this.runs.list(this.currentThread!.thread_id);
204
+ const runningRun = runs?.find((run) => run.status === "running" || run.status === "pending");
205
+ if (runningRun) {
206
+ await this.sendMessage([], { joinRunId: runningRun.run_id });
207
+ }
195
208
  }
196
209
 
197
210
  streamingMessage: RenderMessage[] = [];
@@ -286,7 +299,54 @@ export class LangGraphClient extends Client {
286
299
  }
287
300
  }
288
301
 
289
- return this.attachInfoForMessage(this.composeToolMessages(result as RenderMessage[]));
302
+ return this.convertSubAgentMessages(this.attachInfoForMessage(this.composeToolMessages(result as RenderMessage[])));
303
+ }
304
+ /** 转换 subAgent 消息为工具的子消息 */
305
+ private convertSubAgentMessages(messages: RenderMessage[]) {
306
+ const origin_task_store = this.graphState[this.subAgentsKey];
307
+ if (!origin_task_store) return messages;
308
+
309
+ const task_store = JSON.parse(JSON.stringify(origin_task_store));
310
+ console.log(messages);
311
+ /** 获取 subAgent 消息的 id,用于流式过程中对数据进行标记 */
312
+ messages
313
+ .filter((i) => {
314
+ return i.node_name?.startsWith("subagent_");
315
+ })
316
+ .forEach((i) => {
317
+ const tool_call_id = i.node_name!.replace("subagent_", "");
318
+ const store = task_store[tool_call_id];
319
+ if (store) {
320
+ // 根据 id 进行去重
321
+ const exists = (store.messages as RenderMessage[]).some((msg) => msg.id === i.id);
322
+ if (!exists) {
323
+ (store.messages as RenderMessage[]).push(i);
324
+ }
325
+ } else {
326
+ task_store[tool_call_id] = {
327
+ messages: [i],
328
+ };
329
+ }
330
+ });
331
+
332
+ const ignoreIds = new Set<string>();
333
+ Object.values(task_store).forEach((task: any) => {
334
+ task.messages.forEach((message: RenderMessage) => {
335
+ ignoreIds.add(message.id!);
336
+ });
337
+ });
338
+ const result: RenderMessage[] = [];
339
+ for (const message of messages) {
340
+ if (message.type === "tool" && message.tool_call_id) {
341
+ const task = task_store[message.tool_call_id];
342
+ if (task) {
343
+ message.sub_agent_messages = this.attachInfoForMessage(this.composeToolMessages(task.messages));
344
+ }
345
+ }
346
+ if (message.id && ignoreIds.has(message.id)) continue;
347
+ result.push(message);
348
+ }
349
+ return result;
290
350
  }
291
351
  /**
292
352
  * @zh 为消息附加额外的信息,如耗时、唯一 ID 等。
@@ -432,7 +492,7 @@ export class LangGraphClient extends Client {
432
492
  * @zh 发送消息到 LangGraph 后端。
433
493
  * @en Sends a message to the LangGraph backend.
434
494
  */
435
- async sendMessage(input: string | Message[], { extraParams, _debug, command }: SendMessageOptions = {}) {
495
+ async sendMessage(input: string | Message[], { joinRunId, extraParams, _debug, command }: SendMessageOptions = {}) {
436
496
  if (!this.currentAssistant) {
437
497
  throw new Error("Thread or Assistant not initialized");
438
498
  }
@@ -457,20 +517,29 @@ export class LangGraphClient extends Client {
457
517
  content: input,
458
518
  } as HumanMessage,
459
519
  ];
460
- const streamResponse =
461
- _debug?.streamResponse ||
462
- this.runs.stream(this.currentThread!.thread_id, this.currentAssistant.assistant_id, {
520
+ const createStreamResponse = async () => {
521
+ if (_debug?.streamResponse) {
522
+ return _debug.streamResponse;
523
+ }
524
+ if (joinRunId) {
525
+ return this.runs.joinStream(this.currentThread!.thread_id, joinRunId);
526
+ }
527
+
528
+ return this.runs.stream(this.currentThread!.thread_id, this.currentAssistant!.assistant_id, {
463
529
  input: {
464
530
  ...this.graphState,
465
531
  ...this.extraParams,
466
532
  ...(extraParams || {}),
467
533
  messages: messagesToSend,
468
- fe_tools: await this.tools.toJSON(this.currentAssistant.graph_id),
534
+ fe_tools: await this.tools.toJSON(this.currentAssistant!.graph_id),
469
535
  },
470
536
  streamMode: ["messages", "values"],
471
537
  streamSubgraphs: true,
472
538
  command,
473
539
  });
540
+ };
541
+ const streamResponse = await createStreamResponse();
542
+
474
543
  const streamRecord: any[] = [];
475
544
  this.emitStreamingUpdate({
476
545
  type: "start",
@@ -289,14 +289,18 @@ export const createChatStore = (
289
289
  * @zh 切换到指定的历史聊天会话。
290
290
  * @en Switches to the specified historical chat session.
291
291
  */
292
- toHistoryChat(
292
+ async toHistoryChat(
293
293
  thread: Thread<{
294
294
  messages: Message[];
295
295
  }>
296
296
  ) {
297
297
  inChatError.set(null);
298
298
  loading.set(false);
299
- client.get()?.resetThread(thread.metadata?.graph_id as string, thread.thread_id);
299
+ const nowThread = await client.get()?.resetThread(thread.metadata?.graph_id as string, thread.thread_id);
300
+ if (nowThread) {
301
+ client.get()?.resetStream();
302
+ }
303
+ return nowThread;
300
304
  },
301
305
  /**
302
306
  * @zh 删除指定的历史聊天会话。