@langgraph-js/sdk 1.10.3 → 1.11.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.
@@ -57,6 +57,7 @@ export type SendMessageOptions = {
57
57
  streamResponse?: any;
58
58
  };
59
59
  command?: Command;
60
+ joinRunId?: string;
60
61
  };
61
62
  export interface LangGraphClientConfig {
62
63
  apiUrl?: string;
@@ -115,7 +116,8 @@ export declare class LangGraphClient extends Client {
115
116
  * @zh 从历史中恢复 Thread 数据。
116
117
  * @en Resets the Thread data from history.
117
118
  */
118
- resetThread(agent: string, threadId: string): Promise<void>;
119
+ resetThread(agent: string, threadId: string): Promise<Thread<import("@langchain/langgraph-sdk").DefaultValues>>;
120
+ resetStream(): Promise<void>;
119
121
  streamingMessage: RenderMessage[];
120
122
  /** 图发过来的更新信息 */
121
123
  graphMessages: RenderMessage[];
@@ -168,7 +170,7 @@ export declare class LangGraphClient extends Client {
168
170
  * @zh 发送消息到 LangGraph 后端。
169
171
  * @en Sends a message to the LangGraph backend.
170
172
  */
171
- sendMessage(input: string | Message[], { extraParams, _debug, command }?: SendMessageOptions): Promise<any[]>;
173
+ sendMessage(input: string | Message[], { joinRunId, extraParams, _debug, command }?: SendMessageOptions): Promise<any[]>;
172
174
  /** 当前子图位置,但是依赖 stream,不太适合稳定使用*/
173
175
  private graphPosition;
174
176
  getGraphPosition(): {
@@ -112,10 +112,11 @@ export class LangGraphClient extends Client {
112
112
  * @en Resets the Thread data from history.
113
113
  */
114
114
  async resetThread(agent, threadId) {
115
+ var _a;
115
116
  await this.initAssistant(agent);
116
117
  this.currentThread = await this.threads.get(threadId);
117
118
  this.graphState = this.currentThread.values;
118
- this.graphMessages = this.graphState.messages;
119
+ this.graphMessages = ((_a = this.graphState) === null || _a === void 0 ? void 0 : _a.messages) || [];
119
120
  this.emitStreamingUpdate({
120
121
  type: "value",
121
122
  data: {
@@ -125,6 +126,15 @@ export class LangGraphClient extends Client {
125
126
  },
126
127
  },
127
128
  });
129
+ return this.currentThread;
130
+ }
131
+ // 从历史中恢复时,应该恢复流式状态
132
+ async resetStream() {
133
+ const runs = await this.runs.list(this.currentThread.thread_id);
134
+ const runningRun = runs === null || runs === void 0 ? void 0 : runs.find((run) => run.status === "running" || run.status === "pending");
135
+ if (runningRun) {
136
+ await this.sendMessage([], { joinRunId: runningRun.run_id });
137
+ }
128
138
  }
129
139
  cloneMessage(message) {
130
140
  return JSON.parse(JSON.stringify(message));
@@ -352,7 +362,7 @@ export class LangGraphClient extends Client {
352
362
  * @zh 发送消息到 LangGraph 后端。
353
363
  * @en Sends a message to the LangGraph backend.
354
364
  */
355
- async sendMessage(input, { extraParams, _debug, command } = {}) {
365
+ async sendMessage(input, { joinRunId, extraParams, _debug, command } = {}) {
356
366
  var _a;
357
367
  if (!this.currentAssistant) {
358
368
  throw new Error("Thread or Assistant not initialized");
@@ -377,8 +387,14 @@ export class LangGraphClient extends Client {
377
387
  content: input,
378
388
  },
379
389
  ];
380
- const streamResponse = (_debug === null || _debug === void 0 ? void 0 : _debug.streamResponse) ||
381
- this.runs.stream(this.currentThread.thread_id, this.currentAssistant.assistant_id, {
390
+ const createStreamResponse = async () => {
391
+ if (_debug === null || _debug === void 0 ? void 0 : _debug.streamResponse) {
392
+ return _debug.streamResponse;
393
+ }
394
+ if (joinRunId) {
395
+ return this.runs.joinStream(this.currentThread.thread_id, joinRunId);
396
+ }
397
+ return this.runs.stream(this.currentThread.thread_id, this.currentAssistant.assistant_id, {
382
398
  input: {
383
399
  ...this.graphState,
384
400
  ...this.extraParams,
@@ -390,6 +406,8 @@ export class LangGraphClient extends Client {
390
406
  streamSubgraphs: true,
391
407
  command,
392
408
  });
409
+ };
410
+ const streamResponse = await createStreamResponse();
393
411
  const streamRecord = [];
394
412
  this.emitStreamingUpdate({
395
413
  type: "start",
package/dist/TestKit.d.ts CHANGED
@@ -16,7 +16,7 @@ interface TestTask {
16
16
  }
17
17
  export declare class TestLogger {
18
18
  info(message: string): void;
19
- logMessage(message: RenderMessage): string | undefined;
19
+ logMessage(message: RenderMessage): void;
20
20
  }
21
21
  /**
22
22
  * @zh LangGraph 测试工具,可以配合 vitest 等常用框架进行测试
package/dist/TestKit.js CHANGED
@@ -8,10 +8,10 @@ export class TestLogger {
8
8
  const emoji = message.type === "ai" ? "🤖" : message.type === "human" ? "👤" : "🔧";
9
9
  const header = `${emoji} ${message.type} | ${(_a = message.name) !== null && _a !== void 0 ? _a : "null"} | ${message.id}`;
10
10
  if (message.type === "tool") {
11
- return `${header}
11
+ return console.log(`${header}
12
12
  🔧 Input: ${(_c = (_b = message.tool_input) === null || _b === void 0 ? void 0 : _b.slice(0, 100)) !== null && _c !== void 0 ? _c : ""}
13
13
  💬 Output: ${(_e = (_d = message.content) === null || _d === void 0 ? void 0 : _d.slice(0, 100)) !== null && _e !== void 0 ? _e : ""}
14
- `;
14
+ `);
15
15
  }
16
16
  console.log(`---
17
17
  ${header}
@@ -83,7 +83,7 @@ export class TestLangGraphChat {
83
83
  this.checkAllTask(this.getMessages(), {
84
84
  skipLengthCheck: true,
85
85
  });
86
- }, 100);
86
+ }, 10);
87
87
  return oldExecute(...args);
88
88
  };
89
89
  }
@@ -166,7 +166,7 @@ export class TestLangGraphChat {
166
166
  ])
167
167
  .then(async () => {
168
168
  // messages 有 10 ms 的 debounce,我们需要稍等一下
169
- await new Promise((resolve) => setTimeout(resolve, 20));
169
+ await new Promise((resolve) => setTimeout(resolve, 100));
170
170
  this.checkAllTask(this.getMessages(), {
171
171
  skipLengthCheck: true,
172
172
  });
@@ -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.
@@ -110,6 +110,8 @@ export const createChatStore = (initClientName, config, context = {}) => {
110
110
  // await newClient.createThread();
111
111
  inChatError.set(null);
112
112
  newClient.onStreamingUpdate((event) => {
113
+ var _a;
114
+ currentChatId.set(((_a = newClient.getCurrentThread()) === null || _a === void 0 ? void 0 : _a.thread_id) || null);
113
115
  if (event.type === "start")
114
116
  loading.set(true);
115
117
  if (event.type === "thread" || event.type === "done") {
@@ -281,11 +283,15 @@ export const createChatStore = (initClientName, config, context = {}) => {
281
283
  * @zh 切换到指定的历史聊天会话。
282
284
  * @en Switches to the specified historical chat session.
283
285
  */
284
- toHistoryChat(thread) {
285
- var _a, _b;
286
+ async toHistoryChat(thread) {
287
+ var _a, _b, _c;
286
288
  inChatError.set(null);
287
289
  loading.set(false);
288
- (_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;
289
295
  },
290
296
  /**
291
297
  * @zh 删除指定的历史聊天会话。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langgraph-js/sdk",
3
- "version": "1.10.3",
3
+ "version": "1.11.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",
@@ -55,6 +55,7 @@ export type SendMessageOptions = {
55
55
  extraParams?: Record<string, any>;
56
56
  _debug?: { streamResponse?: any };
57
57
  command?: Command;
58
+ joinRunId?: string;
58
59
  };
59
60
  export interface LangGraphClientConfig {
60
61
  apiUrl?: string;
@@ -182,7 +183,7 @@ export class LangGraphClient extends Client {
182
183
  await this.initAssistant(agent);
183
184
  this.currentThread = await this.threads.get(threadId);
184
185
  this.graphState = this.currentThread.values;
185
- this.graphMessages = this.graphState.messages;
186
+ this.graphMessages = this.graphState?.messages || [];
186
187
  this.emitStreamingUpdate({
187
188
  type: "value",
188
189
  data: {
@@ -192,6 +193,15 @@ export class LangGraphClient extends Client {
192
193
  },
193
194
  },
194
195
  });
196
+ return this.currentThread;
197
+ }
198
+ // 从历史中恢复时,应该恢复流式状态
199
+ async resetStream() {
200
+ const runs = await this.runs.list(this.currentThread!.thread_id);
201
+ const runningRun = runs?.find((run) => run.status === "running" || run.status === "pending");
202
+ if (runningRun) {
203
+ await this.sendMessage([], { joinRunId: runningRun.run_id });
204
+ }
195
205
  }
196
206
 
197
207
  streamingMessage: RenderMessage[] = [];
@@ -432,7 +442,7 @@ export class LangGraphClient extends Client {
432
442
  * @zh 发送消息到 LangGraph 后端。
433
443
  * @en Sends a message to the LangGraph backend.
434
444
  */
435
- async sendMessage(input: string | Message[], { extraParams, _debug, command }: SendMessageOptions = {}) {
445
+ async sendMessage(input: string | Message[], { joinRunId, extraParams, _debug, command }: SendMessageOptions = {}) {
436
446
  if (!this.currentAssistant) {
437
447
  throw new Error("Thread or Assistant not initialized");
438
448
  }
@@ -457,20 +467,29 @@ export class LangGraphClient extends Client {
457
467
  content: input,
458
468
  } as HumanMessage,
459
469
  ];
460
- const streamResponse =
461
- _debug?.streamResponse ||
462
- this.runs.stream(this.currentThread!.thread_id, this.currentAssistant.assistant_id, {
470
+ const createStreamResponse = async () => {
471
+ if (_debug?.streamResponse) {
472
+ return _debug.streamResponse;
473
+ }
474
+ if (joinRunId) {
475
+ return this.runs.joinStream(this.currentThread!.thread_id, joinRunId);
476
+ }
477
+
478
+ return this.runs.stream(this.currentThread!.thread_id, this.currentAssistant!.assistant_id, {
463
479
  input: {
464
480
  ...this.graphState,
465
481
  ...this.extraParams,
466
482
  ...(extraParams || {}),
467
483
  messages: messagesToSend,
468
- fe_tools: await this.tools.toJSON(this.currentAssistant.graph_id),
484
+ fe_tools: await this.tools.toJSON(this.currentAssistant!.graph_id),
469
485
  },
470
486
  streamMode: ["messages", "values"],
471
487
  streamSubgraphs: true,
472
488
  command,
473
489
  });
490
+ };
491
+ const streamResponse = await createStreamResponse();
492
+
474
493
  const streamRecord: any[] = [];
475
494
  this.emitStreamingUpdate({
476
495
  type: "start",
package/src/TestKit.ts CHANGED
@@ -25,10 +25,10 @@ export class TestLogger {
25
25
 
26
26
  const header = `${emoji} ${message.type} | ${message.name ?? "null"} | ${message.id}`;
27
27
  if (message.type === "tool") {
28
- return `${header}
28
+ return console.log(`${header}
29
29
  🔧 Input: ${message.tool_input?.slice(0, 100) ?? ""}
30
30
  💬 Output: ${message.content?.slice(0, 100) ?? ""}
31
- `;
31
+ `);
32
32
  }
33
33
 
34
34
  console.log(`---
@@ -110,7 +110,7 @@ export class TestLangGraphChat {
110
110
  this.checkAllTask(this.getMessages(), {
111
111
  skipLengthCheck: true,
112
112
  });
113
- }, 100);
113
+ }, 10);
114
114
  return oldExecute!(...args);
115
115
  };
116
116
  }
@@ -199,7 +199,7 @@ export class TestLangGraphChat {
199
199
  ])
200
200
  .then(async () => {
201
201
  // messages 有 10 ms 的 debounce,我们需要稍等一下
202
- await new Promise((resolve) => setTimeout(resolve, 20));
202
+ await new Promise((resolve) => setTimeout(resolve, 100));
203
203
  this.checkAllTask(this.getMessages(), {
204
204
  skipLengthCheck: true,
205
205
  });
@@ -117,6 +117,7 @@ export const createChatStore = (
117
117
  // await newClient.createThread();
118
118
  inChatError.set(null);
119
119
  newClient.onStreamingUpdate((event) => {
120
+ currentChatId.set(newClient.getCurrentThread()?.thread_id || null);
120
121
  if (event.type === "start") loading.set(true);
121
122
  if (event.type === "thread" || event.type === "done") {
122
123
  // console.log(event.data);
@@ -288,14 +289,18 @@ export const createChatStore = (
288
289
  * @zh 切换到指定的历史聊天会话。
289
290
  * @en Switches to the specified historical chat session.
290
291
  */
291
- toHistoryChat(
292
+ async toHistoryChat(
292
293
  thread: Thread<{
293
294
  messages: Message[];
294
295
  }>
295
296
  ) {
296
297
  inChatError.set(null);
297
298
  loading.set(false);
298
- 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;
299
304
  },
300
305
  /**
301
306
  * @zh 删除指定的历史聊天会话。