@langgraph-js/sdk 1.6.0 → 1.6.1

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.
@@ -1,4 +1,4 @@
1
- import { Client, Thread, Message, Assistant, HumanMessage, ToolMessage, Command } from "@langchain/langgraph-sdk";
1
+ import { Client, Thread, Message, Assistant, HumanMessage, AIMessage, ToolMessage, Command } from "@langchain/langgraph-sdk";
2
2
  import { ToolManager } from "./ToolManager.js";
3
3
  import { CallToolResult } from "./tool/createTool.js";
4
4
  interface AsyncCallerParams {
@@ -71,8 +71,8 @@ export interface LangGraphClientConfig {
71
71
  export declare class StreamingMessageType {
72
72
  static isUser(m: Message): m is HumanMessage;
73
73
  static isTool(m: Message): m is ToolMessage;
74
- static isAssistant(m: Message): boolean;
75
- static isToolAssistant(m: Message): any;
74
+ static isAssistant(m: Message): m is AIMessage;
75
+ static isToolAssistant(m: Message): m is AIMessage;
76
76
  }
77
77
  type StreamingUpdateEvent = {
78
78
  type: "message" | "value" | "update" | "error" | "thread" | "done" | "start";
@@ -120,7 +120,6 @@ export declare class LangGraphClient extends Client {
120
120
  graphMessages: RenderMessage[];
121
121
  cloneMessage(message: Message): Message;
122
122
  private updateStreamingMessage;
123
- private replaceMessageWithValuesMessage;
124
123
  /** 将 graphMessages 和 streamingMessage 合并,并返回新的消息数组 */
125
124
  private combineGraphMessagesWithStreamingMessages;
126
125
  /**
@@ -167,6 +166,16 @@ export declare class LangGraphClient extends Client {
167
166
  * @en Sends a message to the LangGraph backend.
168
167
  */
169
168
  sendMessage(input: string | Message[], { extraParams, _debug, command }?: SendMessageOptions): Promise<any[]>;
169
+ /** 当前子图位置,但是依赖 stream,不太适合稳定使用*/
170
+ private graphPosition;
171
+ getGraphPosition(): {
172
+ id: string;
173
+ name: string;
174
+ }[];
175
+ getGraphNodeNow(): {
176
+ id: string;
177
+ name: string;
178
+ };
170
179
  /** 子图的数据需要通过 merge 的方式重新进行合并更新 */
171
180
  private mergeSubGraphMessagesToStreamingMessages;
172
181
  private runFETool;
@@ -37,6 +37,8 @@ export class LangGraphClient extends Client {
37
37
  /** 图发过来的更新信息 */
38
38
  this.graphMessages = [];
39
39
  this.graphState = {};
40
+ /** 当前子图位置,但是依赖 stream,不太适合稳定使用*/
41
+ this.graphPosition = "";
40
42
  }
41
43
  listAssistants() {
42
44
  return this.assistants.search({
@@ -134,18 +136,6 @@ export class LangGraphClient extends Client {
134
136
  }
135
137
  this.streamingMessage[this.streamingMessage.length - 1] = message;
136
138
  }
137
- replaceMessageWithValuesMessage(message, isTool = false) {
138
- const key = (isTool ? "tool_call_id" : "id");
139
- const valuesMessage = this.graphMessages.find((i) => i[key] === message[key]);
140
- if (valuesMessage) {
141
- return {
142
- ...valuesMessage,
143
- /** @ts-ignore */
144
- tool_input: message.tool_input,
145
- };
146
- }
147
- return message;
148
- }
149
139
  /** 将 graphMessages 和 streamingMessage 合并,并返回新的消息数组 */
150
140
  combineGraphMessagesWithStreamingMessages() {
151
141
  const idMap = new Map(this.streamingMessage.map((i) => [i.id, i]));
@@ -171,6 +161,7 @@ export class LangGraphClient extends Client {
171
161
  const closedToolCallIds = new Set();
172
162
  const result = [];
173
163
  const inputMessages = this.combineGraphMessagesWithStreamingMessages();
164
+ console.log(inputMessages);
174
165
  // 从后往前遍历,这样可以保证最新的消息在前面
175
166
  for (let i = inputMessages.length - 1; i >= 0; i--) {
176
167
  const message = this.cloneMessage(inputMessages[i]);
@@ -178,8 +169,13 @@ export class LangGraphClient extends Client {
178
169
  result.unshift(message);
179
170
  continue;
180
171
  }
172
+ if (message.type === "ai") {
173
+ /** @ts-ignore */
174
+ if (!message.name)
175
+ message.name = this.getGraphNodeNow().name;
176
+ }
181
177
  if (StreamingMessageType.isToolAssistant(message)) {
182
- const m = this.replaceMessageWithValuesMessage(message);
178
+ const m = message;
183
179
  // 记录这个 id 的消息,并添加到结果中
184
180
  previousMessage.set(message.id, m);
185
181
  /** @ts-ignore */
@@ -190,7 +186,7 @@ export class LangGraphClient extends Client {
190
186
  })
191
187
  .map((tool, index) => {
192
188
  var _a, _b, _c, _d;
193
- return this.replaceMessageWithValuesMessage({
189
+ return {
194
190
  type: "tool",
195
191
  additional_kwargs: {},
196
192
  /** @ts-ignore */
@@ -199,7 +195,8 @@ export class LangGraphClient extends Client {
199
195
  name: tool.name,
200
196
  response_metadata: {},
201
197
  tool_call_id: tool.id,
202
- }, true);
198
+ content: "",
199
+ };
203
200
  });
204
201
  for (const tool of new_tool_calls) {
205
202
  if (!previousMessage.has(tool.id)) {
@@ -213,10 +210,8 @@ export class LangGraphClient extends Client {
213
210
  if (message.type === "tool" && message.tool_call_id) {
214
211
  closedToolCallIds.add(message.tool_call_id);
215
212
  }
216
- // 记录这个 id 的消息,并添加到结果中
217
- const m = this.replaceMessageWithValuesMessage(message);
218
- previousMessage.set(message.id, m);
219
- result.unshift(m);
213
+ previousMessage.set(message.id, message);
214
+ result.unshift(message);
220
215
  }
221
216
  }
222
217
  return this.attachInfoForMessage(this.composeToolMessages(result));
@@ -255,7 +250,7 @@ export class LangGraphClient extends Client {
255
250
  * @en Composes tool messages, associating AI tool calls with tool execution results.
256
251
  */
257
252
  composeToolMessages(messages) {
258
- var _a;
253
+ var _a, _b;
259
254
  const result = [];
260
255
  const assistantToolMessages = new Map();
261
256
  const toolParentMessage = new Map();
@@ -288,6 +283,10 @@ export class LangGraphClient extends Client {
288
283
  if (parentMessage) {
289
284
  message.usage_metadata = parentMessage.usage_metadata;
290
285
  message.node_name = parentMessage.name;
286
+ // 修补特殊情况下,tool name 丢失的问题
287
+ if (!message.name) {
288
+ message.name = (_b = parentMessage.tool_calls.find((i) => i.id === message.tool_call_id)) === null || _b === void 0 ? void 0 : _b.name;
289
+ }
291
290
  }
292
291
  }
293
292
  result.push(message);
@@ -427,6 +426,7 @@ export class LangGraphClient extends Client {
427
426
  if (chunk.data.messages) {
428
427
  this.mergeSubGraphMessagesToStreamingMessages(chunk.data.messages);
429
428
  }
429
+ this.graphPosition = chunk.event.split("|")[1];
430
430
  }
431
431
  }
432
432
  const data = await this.runFETool();
@@ -441,6 +441,19 @@ export class LangGraphClient extends Client {
441
441
  this.streamingMessage = [];
442
442
  return streamRecord;
443
443
  }
444
+ getGraphPosition() {
445
+ return this.graphPosition.split("|").map((i) => {
446
+ const [name, id] = i.split(":");
447
+ return {
448
+ id,
449
+ name,
450
+ };
451
+ });
452
+ }
453
+ getGraphNodeNow() {
454
+ const position = this.getGraphPosition();
455
+ return position[position.length - 1];
456
+ }
444
457
  /** 子图的数据需要通过 merge 的方式重新进行合并更新 */
445
458
  mergeSubGraphMessagesToStreamingMessages(messages) {
446
459
  const map = new Map(messages.filter((i) => i.id).map((i) => [i.id, i]));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langgraph-js/sdk",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
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",
@@ -68,16 +68,16 @@ export interface LangGraphClientConfig {
68
68
  * @en The StreamingMessageType class is used to determine the type of a message.
69
69
  */
70
70
  export class StreamingMessageType {
71
- static isUser(m: Message) {
71
+ static isUser(m: Message): m is HumanMessage {
72
72
  return m.type === "human";
73
73
  }
74
- static isTool(m: Message) {
74
+ static isTool(m: Message): m is ToolMessage {
75
75
  return m.type === "tool";
76
76
  }
77
- static isAssistant(m: Message) {
77
+ static isAssistant(m: Message): m is AIMessage {
78
78
  return m.type === "ai" && !this.isToolAssistant(m);
79
79
  }
80
- static isToolAssistant(m: Message) {
80
+ static isToolAssistant(m: Message): m is AIMessage {
81
81
  /** @ts-ignore */
82
82
  return m.type === "ai" && (m.tool_calls?.length || m.tool_call_chunks?.length);
83
83
  }
@@ -207,18 +207,6 @@ export class LangGraphClient extends Client {
207
207
  }
208
208
  this.streamingMessage[this.streamingMessage.length - 1] = message;
209
209
  }
210
- private replaceMessageWithValuesMessage(message: AIMessage | ToolMessage, isTool = false): Message {
211
- const key = (isTool ? "tool_call_id" : "id") as any as "id";
212
- const valuesMessage = this.graphMessages.find((i) => i[key] === message[key]);
213
- if (valuesMessage) {
214
- return {
215
- ...valuesMessage,
216
- /** @ts-ignore */
217
- tool_input: message.tool_input,
218
- };
219
- }
220
- return message;
221
- }
222
210
  /** 将 graphMessages 和 streamingMessage 合并,并返回新的消息数组 */
223
211
  private combineGraphMessagesWithStreamingMessages() {
224
212
  const idMap = new Map<string, RenderMessage>(this.streamingMessage.map((i) => [i.id!, i]));
@@ -243,6 +231,7 @@ export class LangGraphClient extends Client {
243
231
  const closedToolCallIds = new Set<string>();
244
232
  const result: Message[] = [];
245
233
  const inputMessages = this.combineGraphMessagesWithStreamingMessages();
234
+ console.log(inputMessages);
246
235
  // 从后往前遍历,这样可以保证最新的消息在前面
247
236
  for (let i = inputMessages.length - 1; i >= 0; i--) {
248
237
  const message = this.cloneMessage(inputMessages[i]);
@@ -251,9 +240,12 @@ export class LangGraphClient extends Client {
251
240
  result.unshift(message);
252
241
  continue;
253
242
  }
254
-
243
+ if (message.type === "ai") {
244
+ /** @ts-ignore */
245
+ if (!message.name) message.name = this.getGraphNodeNow().name;
246
+ }
255
247
  if (StreamingMessageType.isToolAssistant(message)) {
256
- const m = this.replaceMessageWithValuesMessage(message as AIMessage);
248
+ const m = message;
257
249
  // 记录这个 id 的消息,并添加到结果中
258
250
  previousMessage.set(message.id, m);
259
251
 
@@ -264,19 +256,17 @@ export class LangGraphClient extends Client {
264
256
  return !closedToolCallIds.has(i.id!);
265
257
  })!
266
258
  .map((tool, index) => {
267
- return this.replaceMessageWithValuesMessage(
268
- {
269
- type: "tool",
270
- additional_kwargs: {},
271
- /** @ts-ignore */
272
- tool_input: m.additional_kwargs?.tool_calls?.[index]?.function?.arguments,
273
- id: tool.id,
274
- name: tool.name,
275
- response_metadata: {},
276
- tool_call_id: tool.id!,
277
- },
278
- true
279
- );
259
+ return {
260
+ type: "tool",
261
+ additional_kwargs: {},
262
+ /** @ts-ignore */
263
+ tool_input: m.additional_kwargs?.tool_calls?.[index]?.function?.arguments,
264
+ id: tool.id,
265
+ name: tool.name,
266
+ response_metadata: {},
267
+ tool_call_id: tool.id!,
268
+ content: "",
269
+ } as ToolMessage;
280
270
  });
281
271
  for (const tool of new_tool_calls) {
282
272
  if (!previousMessage.has(tool.id!)) {
@@ -289,10 +279,9 @@ export class LangGraphClient extends Client {
289
279
  if (message.type === "tool" && message.tool_call_id) {
290
280
  closedToolCallIds.add(message.tool_call_id);
291
281
  }
292
- // 记录这个 id 的消息,并添加到结果中
293
- const m = this.replaceMessageWithValuesMessage(message as AIMessage);
294
- previousMessage.set(message.id, m);
295
- result.unshift(m);
282
+
283
+ previousMessage.set(message.id, message);
284
+ result.unshift(message);
296
285
  }
297
286
  }
298
287
 
@@ -364,6 +353,10 @@ export class LangGraphClient extends Client {
364
353
  if (parentMessage) {
365
354
  message.usage_metadata = parentMessage.usage_metadata;
366
355
  message.node_name = parentMessage.name;
356
+ // 修补特殊情况下,tool name 丢失的问题
357
+ if (!message.name) {
358
+ message.name = (parentMessage as AIMessage).tool_calls!.find((i) => i.id === message.tool_call_id)?.name;
359
+ }
367
360
  }
368
361
  }
369
362
  result.push(message);
@@ -510,6 +503,7 @@ export class LangGraphClient extends Client {
510
503
  if (chunk.data.messages) {
511
504
  this.mergeSubGraphMessagesToStreamingMessages(chunk.data.messages);
512
505
  }
506
+ this.graphPosition = chunk.event.split("|")[1];
513
507
  }
514
508
  }
515
509
  const data = await this.runFETool();
@@ -523,6 +517,21 @@ export class LangGraphClient extends Client {
523
517
  this.streamingMessage = [];
524
518
  return streamRecord;
525
519
  }
520
+ /** 当前子图位置,但是依赖 stream,不太适合稳定使用*/
521
+ private graphPosition = "";
522
+ getGraphPosition() {
523
+ return this.graphPosition.split("|").map((i) => {
524
+ const [name, id] = i.split(":");
525
+ return {
526
+ id,
527
+ name,
528
+ };
529
+ });
530
+ }
531
+ getGraphNodeNow() {
532
+ const position = this.getGraphPosition();
533
+ return position[position.length - 1];
534
+ }
526
535
  /** 子图的数据需要通过 merge 的方式重新进行合并更新 */
527
536
  private mergeSubGraphMessagesToStreamingMessages(messages: Message[]) {
528
537
  const map = new Map(messages.filter((i) => i.id).map((i) => [i.id!, i]));