@langgraph-js/sdk 4.6.0 → 4.6.2

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.
@@ -0,0 +1,4 @@
1
+
2
+ > @langgraph-js/sdk@4.6.0 build /Users/konghayao/code/ai/YaoAgent/apps/langgraph-client
3
+ > tsc
4
+
package/dist/History.d.ts CHANGED
@@ -9,6 +9,8 @@ export interface SessionInfo {
9
9
  thread?: Thread<any>;
10
10
  /** Agent 名称 */
11
11
  agentName: string;
12
+ /** 会话元数据 */
13
+ metadata?: Record<string, any>;
12
14
  }
13
15
  export interface CreateSessionOptions {
14
16
  /** 会话 ID / Thread ID,不提供则自动生成 */
@@ -19,6 +21,8 @@ export interface CreateSessionOptions {
19
21
  restore?: boolean;
20
22
  /** Graph ID */
21
23
  graphId?: string;
24
+ /** 会话元数据 */
25
+ metadata?: Record<string, any>;
22
26
  }
23
27
  /**
24
28
  * @zh History 类用于管理多个 LangGraphClient 实例,支持多会话场景
package/dist/History.js CHANGED
@@ -32,6 +32,7 @@ export class History {
32
32
  const sessionInfo = {
33
33
  sessionId,
34
34
  agentName,
35
+ metadata: options.metadata,
35
36
  };
36
37
  // 如果是从已有 Thread 恢复,则立即获取 Thread
37
38
  if (options.restore) {
@@ -54,8 +55,14 @@ export class History {
54
55
  if (!session.client) {
55
56
  const client = new LangGraphClient(this.clientConfig);
56
57
  await client.initAssistant(session.agentName);
57
- // 只有在有 thread 的情况下才重置(恢复已有会话)
58
- // 新会话的 thread 会在发送第一条消息时自动创建
58
+ // 如果有 metadata,立即创建 Thread 并带上 metadata
59
+ if (session.metadata && !session.thread) {
60
+ await client.createThread({
61
+ graphId: client.getCurrentAssistant()?.graph_id,
62
+ metadata: session.metadata,
63
+ });
64
+ }
65
+ // 如果已有 thread 或者必须重置,则从历史恢复
59
66
  if (session.thread || mustResetStream) {
60
67
  await client.resetThread(session.agentName, sessionId);
61
68
  }
@@ -35,6 +35,8 @@ export type RenderMessage = Message & {
35
35
  unique_id?: string;
36
36
  /** 工具调用是否完成 */
37
37
  done?: boolean;
38
+ /** 标记工具消息的原始 ai 消息 */
39
+ source_ai_message_id?: string;
38
40
  };
39
41
  export type SendMessageOptions = {
40
42
  extraParams?: Record<string, any>;
@@ -43,6 +45,7 @@ export type SendMessageOptions = {
43
45
  };
44
46
  command?: Command;
45
47
  joinRunId?: string;
48
+ metadata?: Record<string, any>;
46
49
  };
47
50
  export interface LangGraphClientConfig {
48
51
  apiUrl?: string;
@@ -182,9 +185,10 @@ export declare class LangGraphClient<TStateType = unknown> extends EventEmitter<
182
185
  * @zh 创建一个新的 Thread。
183
186
  * @en Creates a new Thread.
184
187
  */
185
- createThread({ threadId, graphId }?: {
188
+ createThread({ threadId, graphId, metadata }?: {
186
189
  threadId?: string;
187
190
  graphId?: string;
191
+ metadata?: Record<string, any>;
188
192
  }): Promise<Thread<TStateType, unknown>>;
189
193
  graphVisualize(): Promise<import("@langchain/langgraph-sdk").AssistantGraph>;
190
194
  /**
@@ -247,7 +251,7 @@ export declare class LangGraphClient<TStateType = unknown> extends EventEmitter<
247
251
  * @zh 发送消息到 LangGraph 后端。
248
252
  * @en Sends a message to the LangGraph backend.
249
253
  */
250
- sendMessage(input: string | Message[], { joinRunId, extraParams, _debug, command }?: SendMessageOptions): Promise<any[]>;
254
+ sendMessage(input: string | Message[], { joinRunId, extraParams, _debug, command, metadata }?: SendMessageOptions): Promise<any[]>;
251
255
  /** 当前子图位置,但是依赖 stream,不太适合稳定使用*/
252
256
  private graphPosition;
253
257
  getGraphPosition(): {
@@ -89,9 +89,10 @@ export class LangGraphClient extends EventEmitter {
89
89
  * @zh 创建一个新的 Thread。
90
90
  * @en Creates a new Thread.
91
91
  */
92
- async createThread({ threadId, graphId } = {}) {
92
+ async createThread({ threadId, graphId, metadata } = {}) {
93
93
  try {
94
94
  this.currentThread = await this.threads.create({
95
+ metadata,
95
96
  threadId,
96
97
  graphId,
97
98
  });
@@ -249,12 +250,15 @@ export class LangGraphClient extends EventEmitter {
249
250
  * @zh 发送消息到 LangGraph 后端。
250
251
  * @en Sends a message to the LangGraph backend.
251
252
  */
252
- async sendMessage(input, { joinRunId, extraParams, _debug, command } = {}) {
253
+ async sendMessage(input, { joinRunId, extraParams, _debug, command, metadata } = {}) {
253
254
  if (!this.currentAssistant) {
254
255
  throw new Error("Thread or Assistant not initialized");
255
256
  }
256
257
  if (!this.currentThread) {
257
- await this.createThread({ graphId: this.currentAssistant.graph_id });
258
+ await this.createThread({
259
+ graphId: this.currentAssistant.graph_id,
260
+ metadata,
261
+ });
258
262
  this.emit("thread", {
259
263
  event: "thread/create",
260
264
  data: {
@@ -162,6 +162,8 @@ export class MessageProcessor {
162
162
  if (parentMessage) {
163
163
  message.usage_metadata = parentMessage.usage_metadata;
164
164
  message.node_name = parentMessage.name;
165
+ /** @ts-ignore 用于标记原始的 AI message 的id */
166
+ message.source_ai_message_id = parentMessage.id;
165
167
  // 修补特殊情况下,tool name 丢失的问题
166
168
  if (!message.name) {
167
169
  message.name = parentMessage.tool_calls.find((i) => i.id === message.tool_call_id)?.name;
@@ -251,10 +253,11 @@ export class MessageProcessor {
251
253
  const childrenMap = state_sub_messages_map;
252
254
  const rootMessages = [];
253
255
  for (const message of messages) {
254
- const isRoot = !nonRootMessageId.has(message.id);
256
+ const sourceId = message.source_ai_message_id || message.id;
257
+ const isRoot = !nonRootMessageId.has(sourceId);
255
258
  if (!isRoot) {
256
259
  // 处理子消息
257
- const parentId = parentPointer.get(message.id);
260
+ const parentId = parentPointer.get(sourceId);
258
261
  const children = childrenMap.get(parentId);
259
262
  if (children) {
260
263
  children.push(message);
@@ -40,7 +40,7 @@ export declare const useChat: () => UnionStore<{
40
40
  createNewSession: () => Promise<void>;
41
41
  refreshSessionList: () => Promise<void>;
42
42
  refreshHistoryList: () => Promise<void>;
43
- sendMessage: (message?: import("@langchain/langgraph-sdk").Message[], extraData?: import("../LangGraphClient.js").SendMessageOptions, withoutCheck?: boolean, isResume?: boolean) => Promise<void>;
43
+ sendMessage: (message?: import("@langchain/langgraph-sdk").Message[], options?: import("../LangGraphClient.js").SendMessageOptions, withoutCheck?: boolean, isResume?: boolean) => Promise<void>;
44
44
  stopGeneration: () => void;
45
45
  setUserInput: (input: string) => void;
46
46
  revertChatTo(messageId: string, resend?: boolean, sendOptions?: import("../LangGraphClient.js").SendMessageOptions & import("../time-travel/index.js").RevertChatToOptions): Promise<void>;
@@ -57,7 +57,7 @@ export declare const useChat: () => UnionStore<{
57
57
  addToHistory: (thread: import("@langchain/langgraph-sdk").Thread<{
58
58
  messages: import("@langchain/langgraph-sdk").Message[];
59
59
  }>) => void;
60
- createNewChat: () => Promise<void>;
60
+ createNewChat(metadata?: Record<string, any>): Promise<void>;
61
61
  toHistoryChat: (thread: import("@langchain/langgraph-sdk").Thread<{
62
62
  messages: import("@langchain/langgraph-sdk").Message[];
63
63
  }>) => Promise<void>;
@@ -40,7 +40,7 @@ export declare const useChat: () => UnionStoreSolid<{
40
40
  createNewSession: () => Promise<void>;
41
41
  refreshSessionList: () => Promise<void>;
42
42
  refreshHistoryList: () => Promise<void>;
43
- sendMessage: (message?: import("@langchain/langgraph-sdk").Message[], extraData?: import("../LangGraphClient.js").SendMessageOptions, withoutCheck?: boolean, isResume?: boolean) => Promise<void>;
43
+ sendMessage: (message?: import("@langchain/langgraph-sdk").Message[], options?: import("../LangGraphClient.js").SendMessageOptions, withoutCheck?: boolean, isResume?: boolean) => Promise<void>;
44
44
  stopGeneration: () => void;
45
45
  setUserInput: (input: string) => void;
46
46
  revertChatTo(messageId: string, resend?: boolean, sendOptions?: import("../LangGraphClient.js").SendMessageOptions & import("../time-travel/index.js").RevertChatToOptions): Promise<void>;
@@ -57,7 +57,7 @@ export declare const useChat: () => UnionStoreSolid<{
57
57
  addToHistory: (thread: import("@langchain/langgraph-sdk").Thread<{
58
58
  messages: import("@langchain/langgraph-sdk").Message[];
59
59
  }>) => void;
60
- createNewChat: () => Promise<void>;
60
+ createNewChat(metadata?: Record<string, any>): Promise<void>;
61
61
  toHistoryChat: (thread: import("@langchain/langgraph-sdk").Thread<{
62
62
  messages: import("@langchain/langgraph-sdk").Message[];
63
63
  }>) => Promise<void>;
@@ -67,7 +67,7 @@ export declare const createChatStore: (initClientName: string, config: Partial<L
67
67
  createNewSession: () => Promise<void>;
68
68
  refreshSessionList: () => Promise<void>;
69
69
  refreshHistoryList: () => Promise<void>;
70
- sendMessage: (message?: Message[], extraData?: SendMessageOptions, withoutCheck?: boolean, isResume?: boolean) => Promise<void>;
70
+ sendMessage: (message?: Message[], options?: SendMessageOptions, withoutCheck?: boolean, isResume?: boolean) => Promise<void>;
71
71
  stopGeneration: () => void;
72
72
  setUserInput: (input: string) => void;
73
73
  revertChatTo(messageId: string, resend?: boolean, sendOptions?: SendMessageOptions & RevertChatToOptions): Promise<void>;
@@ -84,7 +84,7 @@ export declare const createChatStore: (initClientName: string, config: Partial<L
84
84
  addToHistory: (thread: Thread<{
85
85
  messages: Message[];
86
86
  }>) => void;
87
- createNewChat: () => Promise<void>;
87
+ createNewChat(metadata?: Record<string, any>): Promise<void>;
88
88
  toHistoryChat: (thread: Thread<{
89
89
  messages: Message[];
90
90
  }>) => Promise<void>;
@@ -171,6 +171,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
171
171
  sessionId: thread.thread_id,
172
172
  thread,
173
173
  agentName: currentAgent.get(),
174
+ metadata: thread.metadata,
174
175
  })));
175
176
  historyList.set(threads);
176
177
  // 更新分页状态(注意:这里只是估计值,实际总数可能需要从后端获取)
@@ -324,7 +325,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
324
325
  }
325
326
  }
326
327
  // ============ 消息和交互逻辑 ============
327
- async function sendMessage(message, extraData, withoutCheck = false, isResume = false) {
328
+ async function sendMessage(message, options, withoutCheck = false, isResume = false) {
328
329
  const c = client.get();
329
330
  if ((!withoutCheck && !userInput.get().trim() && !message?.length) || !c)
330
331
  return;
@@ -334,7 +335,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
334
335
  inChatError.set(null);
335
336
  try {
336
337
  loading.set(true);
337
- await c.sendMessage(message || userInput.get(), extraData);
338
+ await c.sendMessage(message || userInput.get(), options);
338
339
  }
339
340
  catch (e) {
340
341
  const isThreadRunning = e.message.includes("422");
@@ -461,7 +462,20 @@ export const createChatStore = (initClientName, config, context = {}) => {
461
462
  },
462
463
  // 历史记录(兼容旧 API)
463
464
  addToHistory,
464
- createNewChat: createNewSession,
465
+ async createNewChat(metadata) {
466
+ const historyManager = history.get();
467
+ if (!historyManager)
468
+ return;
469
+ try {
470
+ const session = await historyManager.createSession({ metadata });
471
+ await refreshSessionList();
472
+ await activateSession(session.sessionId);
473
+ }
474
+ catch (error) {
475
+ console.error("Failed to create new chat:", error);
476
+ inChatError.set(error.message);
477
+ }
478
+ },
465
479
  toHistoryChat: (thread) => activateSession(thread.thread_id, true),
466
480
  async deleteHistoryChat(thread) {
467
481
  const historyManager = history.get();
@@ -84,7 +84,7 @@ export declare const useChatProvider: (props: ChatProviderProps) => {
84
84
  createNewSession: () => Promise<void>;
85
85
  refreshSessionList: () => Promise<void>;
86
86
  refreshHistoryList: () => Promise<void>;
87
- sendMessage: (message?: import("@langchain/langgraph-sdk").Message[], extraData?: import("../LangGraphClient.js").SendMessageOptions, withoutCheck?: boolean, isResume?: boolean) => Promise<void>;
87
+ sendMessage: (message?: import("@langchain/langgraph-sdk").Message[], options?: import("../LangGraphClient.js").SendMessageOptions, withoutCheck?: boolean, isResume?: boolean) => Promise<void>;
88
88
  stopGeneration: () => void;
89
89
  setUserInput: (input: string) => void;
90
90
  revertChatTo(messageId: string, resend?: boolean, sendOptions?: import("../LangGraphClient.js").SendMessageOptions & import("../time-travel/index.js").RevertChatToOptions): Promise<void>;
@@ -101,7 +101,7 @@ export declare const useChatProvider: (props: ChatProviderProps) => {
101
101
  addToHistory: (thread: import("@langchain/langgraph-sdk").Thread<{
102
102
  messages: import("@langchain/langgraph-sdk").Message[];
103
103
  }>) => void;
104
- createNewChat: () => Promise<void>;
104
+ createNewChat(metadata?: Record<string, any>): Promise<void>;
105
105
  toHistoryChat: (thread: import("@langchain/langgraph-sdk").Thread<{
106
106
  messages: import("@langchain/langgraph-sdk").Message[];
107
107
  }>) => Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langgraph-js/sdk",
3
- "version": "4.6.0",
3
+ "version": "4.6.2",
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",
package/src/History.ts CHANGED
@@ -10,6 +10,8 @@ export interface SessionInfo {
10
10
  thread?: Thread<any>;
11
11
  /** Agent 名称 */
12
12
  agentName: string;
13
+ /** 会话元数据 */
14
+ metadata?: Record<string, any>;
13
15
  }
14
16
 
15
17
  export interface CreateSessionOptions {
@@ -21,6 +23,8 @@ export interface CreateSessionOptions {
21
23
  restore?: boolean;
22
24
  /** Graph ID */
23
25
  graphId?: string;
26
+ /** 会话元数据 */
27
+ metadata?: Record<string, any>;
24
28
  }
25
29
 
26
30
  /**
@@ -61,6 +65,7 @@ export class History {
61
65
  const sessionInfo: SessionInfo = {
62
66
  sessionId,
63
67
  agentName,
68
+ metadata: options.metadata,
64
69
  };
65
70
 
66
71
  // 如果是从已有 Thread 恢复,则立即获取 Thread
@@ -89,8 +94,15 @@ export class History {
89
94
  const client = new LangGraphClient(this.clientConfig);
90
95
  await client.initAssistant(session.agentName);
91
96
 
92
- // 只有在有 thread 的情况下才重置(恢复已有会话)
93
- // 新会话的 thread 会在发送第一条消息时自动创建
97
+ // 如果有 metadata,立即创建 Thread 并带上 metadata
98
+ if (session.metadata && !session.thread) {
99
+ await client.createThread({
100
+ graphId: client.getCurrentAssistant()?.graph_id,
101
+ metadata: session.metadata,
102
+ });
103
+ }
104
+
105
+ // 如果已有 thread 或者必须重置,则从历史恢复
94
106
  if (session.thread || mustResetStream) {
95
107
  await client.resetThread(session.agentName, sessionId);
96
108
  }
@@ -40,12 +40,15 @@ export type RenderMessage = Message & {
40
40
  unique_id?: string;
41
41
  /** 工具调用是否完成 */
42
42
  done?: boolean;
43
+ /** 标记工具消息的原始 ai 消息 */
44
+ source_ai_message_id?: string;
43
45
  };
44
46
  export type SendMessageOptions = {
45
47
  extraParams?: Record<string, any>;
46
48
  _debug?: { streamResponse?: any };
47
49
  command?: Command;
48
50
  joinRunId?: string;
51
+ metadata?: Record<string, any>;
49
52
  };
50
53
 
51
54
  export interface LangGraphClientConfig {
@@ -188,9 +191,10 @@ export class LangGraphClient<TStateType = unknown> extends EventEmitter<LangGrap
188
191
  * @zh 创建一个新的 Thread。
189
192
  * @en Creates a new Thread.
190
193
  */
191
- async createThread({ threadId, graphId }: { threadId?: string; graphId?: string } = {}) {
194
+ async createThread({ threadId, graphId, metadata }: { threadId?: string; graphId?: string; metadata?: Record<string, any> } = {}) {
192
195
  try {
193
196
  this.currentThread = await this.threads.create({
197
+ metadata,
194
198
  threadId,
195
199
  graphId,
196
200
  });
@@ -363,12 +367,15 @@ export class LangGraphClient<TStateType = unknown> extends EventEmitter<LangGrap
363
367
  * @zh 发送消息到 LangGraph 后端。
364
368
  * @en Sends a message to the LangGraph backend.
365
369
  */
366
- async sendMessage(input: string | Message[], { joinRunId, extraParams, _debug, command }: SendMessageOptions = {}) {
370
+ async sendMessage(input: string | Message[], { joinRunId, extraParams, _debug, command, metadata }: SendMessageOptions = {}) {
367
371
  if (!this.currentAssistant) {
368
372
  throw new Error("Thread or Assistant not initialized");
369
373
  }
370
374
  if (!this.currentThread) {
371
- await this.createThread({ graphId: this.currentAssistant!.graph_id! });
375
+ await this.createThread({
376
+ graphId: this.currentAssistant!.graph_id!,
377
+ metadata,
378
+ });
372
379
  this.emit("thread", {
373
380
  event: "thread/create",
374
381
  data: {
@@ -184,6 +184,8 @@ export class MessageProcessor {
184
184
  if (parentMessage) {
185
185
  message.usage_metadata = parentMessage.usage_metadata;
186
186
  message.node_name = parentMessage.name;
187
+ /** @ts-ignore 用于标记原始的 AI message 的id */
188
+ message.source_ai_message_id = parentMessage.id;
187
189
  // 修补特殊情况下,tool name 丢失的问题
188
190
  if (!message.name) {
189
191
  message.name = (parentMessage as AIMessage).tool_calls!.find((i) => i.id === message.tool_call_id)?.name;
@@ -294,10 +296,11 @@ export class MessageProcessor {
294
296
  const rootMessages: RenderMessage[] = [];
295
297
 
296
298
  for (const message of messages) {
297
- const isRoot = !nonRootMessageId.has(message.id!);
299
+ const sourceId = message.source_ai_message_id || message.id!;
300
+ const isRoot = !nonRootMessageId.has(sourceId!);
298
301
  if (!isRoot) {
299
302
  // 处理子消息
300
- const parentId = parentPointer.get(message.id!)!;
303
+ const parentId = parentPointer.get(sourceId)!;
301
304
  const children = childrenMap.get(parentId);
302
305
  if (children) {
303
306
  children.push(message);
@@ -227,6 +227,7 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
227
227
  sessionId: thread.thread_id,
228
228
  thread,
229
229
  agentName: currentAgent.get(),
230
+ metadata: thread.metadata as Record<string, any> | undefined,
230
231
  }) as SessionInfo
231
232
  )
232
233
  );
@@ -405,7 +406,7 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
405
406
 
406
407
  // ============ 消息和交互逻辑 ============
407
408
 
408
- async function sendMessage(message?: Message[], extraData?: SendMessageOptions, withoutCheck = false, isResume = false) {
409
+ async function sendMessage(message?: Message[], options?: SendMessageOptions, withoutCheck = false, isResume = false) {
409
410
  const c = client.get();
410
411
  if ((!withoutCheck && !userInput.get().trim() && !message?.length) || !c) return;
411
412
 
@@ -415,7 +416,7 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
415
416
  inChatError.set(null);
416
417
  try {
417
418
  loading.set(true);
418
- await c.sendMessage(message || userInput.get(), extraData);
419
+ await c.sendMessage(message || userInput.get(), options);
419
420
  } catch (e) {
420
421
  const isThreadRunning = (e as Error).message.includes("422");
421
422
  if (isThreadRunning) {
@@ -559,7 +560,19 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
559
560
  },
560
561
  // 历史记录(兼容旧 API)
561
562
  addToHistory,
562
- createNewChat: createNewSession,
563
+ async createNewChat(metadata?: Record<string, any>) {
564
+ const historyManager = history.get();
565
+ if (!historyManager) return;
566
+
567
+ try {
568
+ const session = await historyManager.createSession({ metadata });
569
+ await refreshSessionList();
570
+ await activateSession(session.sessionId);
571
+ } catch (error) {
572
+ console.error("Failed to create new chat:", error);
573
+ inChatError.set((error as Error).message);
574
+ }
575
+ },
563
576
  toHistoryChat: (thread: Thread<{ messages: Message[] }>) => activateSession(thread.thread_id, true),
564
577
  async deleteHistoryChat(thread: Thread<{ messages: Message[] }>) {
565
578
  const historyManager = history.get();