@langgraph-js/sdk 4.3.3 → 4.3.5

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.
Files changed (37) hide show
  1. package/dist/History.d.ts +1 -1
  2. package/dist/History.js +6 -6
  3. package/dist/LangGraphClient.js +5 -5
  4. package/dist/react/ChatContext.d.ts +2 -1
  5. package/dist/solid/ChatContext.d.ts +2 -1
  6. package/dist/ui-store/createChatStore.d.ts +2 -1
  7. package/dist/ui-store/createChatStore.js +9 -6
  8. package/dist/vue/ChatContext.d.ts +2 -1
  9. package/package.json +1 -1
  10. package/src/History.ts +6 -6
  11. package/src/LangGraphClient.ts +5 -5
  12. package/src/tool/ToolUI.ts +1 -0
  13. package/src/ui-store/createChatStore.ts +9 -7
  14. package/dist/server/createState.d.ts +0 -13
  15. package/dist/server/createState.js +0 -20
  16. package/dist/server/feTools.d.ts +0 -16
  17. package/dist/server/feTools.js +0 -37
  18. package/dist/server/index.d.ts +0 -3
  19. package/dist/server/index.js +0 -3
  20. package/dist/server/interrupt/index.d.ts +0 -23
  21. package/dist/server/interrupt/index.js +0 -36
  22. package/dist/server/swarm/handoff.d.ts +0 -11
  23. package/dist/server/swarm/handoff.js +0 -84
  24. package/dist/server/swarm/keepState.d.ts +0 -6
  25. package/dist/server/swarm/keepState.js +0 -21
  26. package/dist/server/tools/index.d.ts +0 -1
  27. package/dist/server/tools/index.js +0 -1
  28. package/dist/server/tools/sequential-thinking.d.ts +0 -52
  29. package/dist/server/tools/sequential-thinking.js +0 -69
  30. package/dist/server/utils.d.ts +0 -3
  31. package/dist/server/utils.js +0 -24
  32. package/dist/test-type.d.ts +0 -1
  33. package/dist/test-type.js +0 -5
  34. package/dist/types.d.ts +0 -106
  35. package/dist/types.js +0 -1
  36. package/dist/ui-store/rafDebounce.d.ts +0 -6
  37. package/dist/ui-store/rafDebounce.js +0 -26
package/dist/History.d.ts CHANGED
@@ -43,7 +43,7 @@ export declare class History {
43
43
  * @zh 激活指定会话(懒加载创建 Client)
44
44
  * @en Activates the specified session (lazy load client)
45
45
  */
46
- activateSession(sessionId: string): Promise<SessionInfo>;
46
+ activateSession(sessionId: string, mustResetStream?: boolean): Promise<SessionInfo>;
47
47
  /**
48
48
  * @zh 获取当前活跃的会话
49
49
  * @en Gets the current active session
package/dist/History.js CHANGED
@@ -45,18 +45,18 @@ export class History {
45
45
  * @zh 激活指定会话(懒加载创建 Client)
46
46
  * @en Activates the specified session (lazy load client)
47
47
  */
48
- async activateSession(sessionId) {
49
- const session = this.sessions.get(sessionId);
50
- if (!session) {
51
- throw new Error(`Session ${sessionId} not found`);
52
- }
48
+ async activateSession(sessionId, mustResetStream = false) {
49
+ const session = this.sessions.get(sessionId) || {
50
+ sessionId,
51
+ agentName: this.virtualClient.getCurrentAssistant()?.graph_id,
52
+ };
53
53
  // 懒加载:只在激活时创建 Client
54
54
  if (!session.client) {
55
55
  const client = new LangGraphClient(this.clientConfig);
56
56
  await client.initAssistant(session.agentName);
57
57
  // 只有在有 thread 的情况下才重置(恢复已有会话)
58
58
  // 新会话的 thread 会在发送第一条消息时自动创建
59
- if (session.thread) {
59
+ if (session.thread || mustResetStream) {
60
60
  await client.resetThread(session.agentName, sessionId);
61
61
  }
62
62
  session.client = client;
@@ -349,7 +349,6 @@ export class LangGraphClient extends EventEmitter {
349
349
  else if (chunk.event === "values") {
350
350
  const data = chunk.data;
351
351
  if (data?.__interrupt__) {
352
- this._status = "interrupted";
353
352
  const humanInTheLoopData = this.getHumanInTheLoopData(data?.__interrupt__);
354
353
  if (humanInTheLoopData) {
355
354
  this.humanInTheLoop = humanInTheLoopData;
@@ -357,9 +356,6 @@ export class LangGraphClient extends EventEmitter {
357
356
  else {
358
357
  this.interruptData = data.__interrupt__;
359
358
  }
360
- this.emit("interruptChange", {
361
- event: "interruptChange",
362
- });
363
359
  }
364
360
  else if (data?.messages) {
365
361
  const isResume = !!command?.resume;
@@ -396,9 +392,13 @@ export class LangGraphClient extends EventEmitter {
396
392
  // json 校验
397
393
  return this.callFETool(toolMessage, tool.args);
398
394
  });
395
+ console.log("batch call tools", result.length);
396
+ // 只有当卡住流程时,才改变状态为 interrupted
399
397
  this._status = "interrupted";
400
398
  this.currentThread.status = "interrupted"; // 修复某些机制下,状态不为 interrupted 与后端有差异
401
- console.log("batch call tools", result.length);
399
+ this.emit("interruptChange", {
400
+ event: "interruptChange",
401
+ });
402
402
  return Promise.all(result);
403
403
  }
404
404
  }
@@ -16,6 +16,7 @@ export declare const useChat: () => UnionStore<{
16
16
  currentAgent: import("nanostores").PreinitializedWritableAtom<string> & object;
17
17
  currentChatId: import("nanostores").PreinitializedWritableAtom<string | null> & object;
18
18
  currentNodeName: import("nanostores").PreinitializedWritableAtom<string> & object;
19
+ currentStatus: import("nanostores").PreinitializedWritableAtom<string> & object;
19
20
  interruptData: import("nanostores").PreinitializedWritableAtom<import("../humanInTheLoop.js").InterruptData | null> & object;
20
21
  isInterrupted: import("nanostores").PreinitializedWritableAtom<boolean> & object;
21
22
  tools: import("nanostores").PreinitializedWritableAtom<import("../index.js").UnionTool<any, Object, any>[]> & object;
@@ -33,7 +34,7 @@ export declare const useChat: () => UnionStore<{
33
34
  initClient: () => Promise<import("../History.js").History>;
34
35
  getClient: () => import("../LangGraphClient.js").LangGraphClient<unknown> | null;
35
36
  getHistory: () => import("../History.js").History | null;
36
- activateSession: (sessionId: string) => Promise<void>;
37
+ activateSession: (sessionId: string, mustResetStream?: boolean) => Promise<void>;
37
38
  createNewSession: () => Promise<void>;
38
39
  refreshSessionList: () => Promise<void>;
39
40
  refreshHistoryList: () => Promise<void>;
@@ -16,6 +16,7 @@ export declare const useChat: () => UnionStoreSolid<{
16
16
  currentAgent: PreinitializedWritableAtom<string> & object;
17
17
  currentChatId: PreinitializedWritableAtom<string | null> & object;
18
18
  currentNodeName: PreinitializedWritableAtom<string> & object;
19
+ currentStatus: PreinitializedWritableAtom<string> & object;
19
20
  interruptData: PreinitializedWritableAtom<import("../humanInTheLoop.js").InterruptData | null> & object;
20
21
  isInterrupted: PreinitializedWritableAtom<boolean> & object;
21
22
  tools: PreinitializedWritableAtom<import("../index.js").UnionTool<any, Object, any>[]> & object;
@@ -33,7 +34,7 @@ export declare const useChat: () => UnionStoreSolid<{
33
34
  initClient: () => Promise<import("../History.js").History>;
34
35
  getClient: () => import("../LangGraphClient.js").LangGraphClient<unknown> | null;
35
36
  getHistory: () => import("../History.js").History | null;
36
- activateSession: (sessionId: string) => Promise<void>;
37
+ activateSession: (sessionId: string, mustResetStream?: boolean) => Promise<void>;
37
38
  createNewSession: () => Promise<void>;
38
39
  refreshSessionList: () => Promise<void>;
39
40
  refreshHistoryList: () => Promise<void>;
@@ -32,6 +32,7 @@ export declare const createChatStore: (initClientName: string, config: Partial<L
32
32
  currentAgent: import("nanostores").PreinitializedWritableAtom<string> & object;
33
33
  currentChatId: import("nanostores").PreinitializedWritableAtom<string | null> & object;
34
34
  currentNodeName: import("nanostores").PreinitializedWritableAtom<string> & object;
35
+ currentStatus: import("nanostores").PreinitializedWritableAtom<string> & object;
35
36
  interruptData: import("nanostores").PreinitializedWritableAtom<InterruptData | null> & object;
36
37
  isInterrupted: import("nanostores").PreinitializedWritableAtom<boolean> & object;
37
38
  tools: import("nanostores").PreinitializedWritableAtom<UnionTool<any, Object, any>[]> & object;
@@ -49,7 +50,7 @@ export declare const createChatStore: (initClientName: string, config: Partial<L
49
50
  initClient: () => Promise<History>;
50
51
  getClient: () => LangGraphClient<unknown> | null;
51
52
  getHistory: () => History | null;
52
- activateSession: (sessionId: string) => Promise<void>;
53
+ activateSession: (sessionId: string, mustResetStream?: boolean) => Promise<void>;
53
54
  createNewSession: () => Promise<void>;
54
55
  refreshSessionList: () => Promise<void>;
55
56
  refreshHistoryList: () => Promise<void>;
@@ -58,6 +58,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
58
58
  const currentAgent = atom(initClientName);
59
59
  const currentChatId = atom(null);
60
60
  const currentNodeName = atom("__start__");
61
+ const currentStatus = atom("idle");
61
62
  // Interrupt 状态
62
63
  const interruptData = atom(null);
63
64
  const isInterrupted = atom(false);
@@ -87,6 +88,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
87
88
  const lastMessage = messages[messages.length - 1];
88
89
  currentNodeName.set(lastMessage?.node_name || lastMessage?.name || "__start__");
89
90
  renderMessages.set(messages);
91
+ currentStatus.set(newClient.status);
90
92
  }, 10);
91
93
  // ============ 工具和图表辅助函数 ============
92
94
  const refreshTools = async () => {
@@ -212,6 +214,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
212
214
  isInterrupted.set(false);
213
215
  }
214
216
  updateUI(newClient);
217
+ client.set(client.get());
215
218
  };
216
219
  newClient.on("start", onStart);
217
220
  newClient.on("thread", onThread);
@@ -231,7 +234,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
231
234
  };
232
235
  }
233
236
  // ============ 会话激活逻辑 ============
234
- async function activateSession(sessionId) {
237
+ async function activateSession(sessionId, mustResetStream = false) {
235
238
  const historyManager = history.get();
236
239
  if (!historyManager)
237
240
  return;
@@ -243,7 +246,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
243
246
  inChatError.set(null);
244
247
  interruptData.set(null);
245
248
  isInterrupted.set(false);
246
- const session = await historyManager.activateSession(sessionId);
249
+ const session = await historyManager.activateSession(sessionId, mustResetStream);
247
250
  const activeClient = session.client;
248
251
  if (activeClient) {
249
252
  cleanupCurrentClient = setupClientListeners(activeClient);
@@ -325,9 +328,8 @@ export const createChatStore = (initClientName, config, context = {}) => {
325
328
  const c = client.get();
326
329
  if (!c)
327
330
  return null;
328
- const toolsDefine = c.tools.getAllTools();
329
- const tool = toolsDefine.find((i) => i.name === tool_name)?.render;
330
- return tool ? (message) => tool(new ToolRenderData(message, c)) : null;
331
+ const toolRender = c.tools.getTool(tool_name)?.render;
332
+ return toolRender ? (message) => toolRender(new ToolRenderData(message, c)) : null;
331
333
  }
332
334
  // ============ 返回 Store API ============
333
335
  const artifactHook = useArtifacts(renderMessages, client);
@@ -345,6 +347,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
345
347
  currentAgent,
346
348
  currentChatId,
347
349
  currentNodeName,
350
+ currentStatus,
348
351
  // Interrupt 状态
349
352
  interruptData,
350
353
  isInterrupted,
@@ -413,7 +416,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
413
416
  // 历史记录(兼容旧 API)
414
417
  addToHistory,
415
418
  createNewChat: createNewSession,
416
- toHistoryChat: (thread) => activateSession(thread.thread_id),
419
+ toHistoryChat: (thread) => activateSession(thread.thread_id, true),
417
420
  async deleteHistoryChat(thread) {
418
421
  const historyManager = history.get();
419
422
  if (historyManager) {
@@ -59,6 +59,7 @@ export declare const useChatProvider: (props: ChatProviderProps) => {
59
59
  currentAgent: PreinitializedWritableAtom<string> & object;
60
60
  currentChatId: PreinitializedWritableAtom<string | null> & object;
61
61
  currentNodeName: PreinitializedWritableAtom<string> & object;
62
+ currentStatus: PreinitializedWritableAtom<string> & object;
62
63
  interruptData: PreinitializedWritableAtom<import("../humanInTheLoop.js").InterruptData | null> & object;
63
64
  isInterrupted: PreinitializedWritableAtom<boolean> & object;
64
65
  tools: PreinitializedWritableAtom<import("../index.js").UnionTool<any, Object, any>[]> & object;
@@ -76,7 +77,7 @@ export declare const useChatProvider: (props: ChatProviderProps) => {
76
77
  initClient: () => Promise<import("../History.js").History>;
77
78
  getClient: () => import("../LangGraphClient.js").LangGraphClient<unknown> | null;
78
79
  getHistory: () => import("../History.js").History | null;
79
- activateSession: (sessionId: string) => Promise<void>;
80
+ activateSession: (sessionId: string, mustResetStream?: boolean) => Promise<void>;
80
81
  createNewSession: () => Promise<void>;
81
82
  refreshSessionList: () => Promise<void>;
82
83
  refreshHistoryList: () => Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langgraph-js/sdk",
3
- "version": "4.3.3",
3
+ "version": "4.3.5",
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
@@ -78,11 +78,11 @@ export class History {
78
78
  * @zh 激活指定会话(懒加载创建 Client)
79
79
  * @en Activates the specified session (lazy load client)
80
80
  */
81
- async activateSession(sessionId: string): Promise<SessionInfo> {
82
- const session = this.sessions.get(sessionId);
83
- if (!session) {
84
- throw new Error(`Session ${sessionId} not found`);
85
- }
81
+ async activateSession(sessionId: string, mustResetStream = false): Promise<SessionInfo> {
82
+ const session: SessionInfo = this.sessions.get(sessionId) || {
83
+ sessionId,
84
+ agentName: this.virtualClient.getCurrentAssistant()?.graph_id!,
85
+ };
86
86
 
87
87
  // 懒加载:只在激活时创建 Client
88
88
  if (!session.client) {
@@ -91,7 +91,7 @@ export class History {
91
91
 
92
92
  // 只有在有 thread 的情况下才重置(恢复已有会话)
93
93
  // 新会话的 thread 会在发送第一条消息时自动创建
94
- if (session.thread) {
94
+ if (session.thread || mustResetStream) {
95
95
  await client.resetThread(session.agentName, sessionId);
96
96
  }
97
97
 
@@ -472,16 +472,12 @@ export class LangGraphClient<TStateType = unknown> extends EventEmitter<LangGrap
472
472
  }
473
473
  | undefined;
474
474
  if (data?.__interrupt__) {
475
- this._status = "interrupted";
476
475
  const humanInTheLoopData = this.getHumanInTheLoopData(data?.__interrupt__);
477
476
  if (humanInTheLoopData) {
478
477
  this.humanInTheLoop = humanInTheLoopData;
479
478
  } else {
480
479
  this.interruptData = data.__interrupt__;
481
480
  }
482
- this.emit("interruptChange", {
483
- event: "interruptChange",
484
- });
485
481
  } else if (data?.messages) {
486
482
  const isResume = !!command?.resume;
487
483
  const isLongerThanLocal = data.messages.length >= this.messageProcessor.getGraphMessages().length;
@@ -516,9 +512,13 @@ export class LangGraphClient<TStateType = unknown> extends EventEmitter<LangGrap
516
512
  // json 校验
517
513
  return this.callFETool(toolMessage, tool.args);
518
514
  });
515
+ console.log("batch call tools", result.length);
516
+ // 只有当卡住流程时,才改变状态为 interrupted
519
517
  this._status = "interrupted";
520
518
  this.currentThread!.status = "interrupted"; // 修复某些机制下,状态不为 interrupted 与后端有差异
521
- console.log("batch call tools", result.length);
519
+ this.emit("interruptChange", {
520
+ event: "interruptChange",
521
+ });
522
522
  return Promise.all(result);
523
523
  }
524
524
  }
@@ -50,6 +50,7 @@ export class ToolRenderData<I, D> {
50
50
 
51
51
  return this.client.doneHumanInTheLoopWaiting(this.message.id!, this.getToolActionRequestID(), response);
52
52
  }
53
+
53
54
  get state() {
54
55
  if (this.message.type === "tool" && this.message?.additional_kwargs?.done) {
55
56
  return "done";
@@ -78,7 +78,7 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
78
78
  const currentAgent = atom<string>(initClientName);
79
79
  const currentChatId = atom<string | null>(null);
80
80
  const currentNodeName = atom<string>("__start__");
81
-
81
+ const currentStatus = atom<string>("idle");
82
82
  // Interrupt 状态
83
83
  const interruptData = atom<InterruptData | null>(null);
84
84
  const isInterrupted = atom<boolean>(false);
@@ -117,6 +117,7 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
117
117
 
118
118
  currentNodeName.set(lastMessage?.node_name || lastMessage?.name || "__start__");
119
119
  renderMessages.set(messages);
120
+ currentStatus.set(newClient.status);
120
121
  }, 10);
121
122
  // ============ 工具和图表辅助函数 ============
122
123
 
@@ -256,6 +257,7 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
256
257
  isInterrupted.set(false);
257
258
  }
258
259
  updateUI(newClient);
260
+ client.set(client.get());
259
261
  };
260
262
 
261
263
  newClient.on("start", onStart);
@@ -279,7 +281,7 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
279
281
 
280
282
  // ============ 会话激活逻辑 ============
281
283
 
282
- async function activateSession(sessionId: string) {
284
+ async function activateSession(sessionId: string, mustResetStream = false) {
283
285
  const historyManager = history.get();
284
286
  if (!historyManager) return;
285
287
 
@@ -293,7 +295,7 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
293
295
  interruptData.set(null);
294
296
  isInterrupted.set(false);
295
297
 
296
- const session = await historyManager.activateSession(sessionId);
298
+ const session = await historyManager.activateSession(sessionId, mustResetStream);
297
299
  const activeClient = session.client;
298
300
 
299
301
  if (activeClient) {
@@ -383,9 +385,8 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
383
385
  function getToolUIRender(tool_name: string) {
384
386
  const c = client.get();
385
387
  if (!c) return null;
386
- const toolsDefine = c.tools.getAllTools();
387
- const tool = toolsDefine.find((i) => i.name === tool_name!)?.render;
388
- return tool ? (message: RenderMessage) => tool(new ToolRenderData(message, c)) : null;
388
+ const toolRender = c.tools.getTool(tool_name)?.render;
389
+ return toolRender ? (message: RenderMessage) => toolRender(new ToolRenderData(message, c)) : null;
389
390
  }
390
391
 
391
392
  // ============ 返回 Store API ============
@@ -407,6 +408,7 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
407
408
  currentAgent,
408
409
  currentChatId,
409
410
  currentNodeName,
411
+ currentStatus,
410
412
 
411
413
  // Interrupt 状态
412
414
  interruptData,
@@ -486,7 +488,7 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
486
488
  // 历史记录(兼容旧 API)
487
489
  addToHistory,
488
490
  createNewChat: createNewSession,
489
- toHistoryChat: (thread: Thread<{ messages: Message[] }>) => activateSession(thread.thread_id),
491
+ toHistoryChat: (thread: Thread<{ messages: Message[] }>) => activateSession(thread.thread_id, true),
490
492
  async deleteHistoryChat(thread: Thread<{ messages: Message[] }>) {
491
493
  const historyManager = history.get();
492
494
  if (historyManager) {
@@ -1,13 +0,0 @@
1
- import { AnnotationRoot, StateDefinition } from "@langchain/langgraph";
2
- /**
3
- * create state for langgraph
4
- * @example
5
- * export const GraphState = createState(createReactAgentAnnotation(), ModelState, SwarmState).build({
6
- * current_plan: createDefaultAnnotation<Plan | null>(() => null),
7
- * title: createDefaultAnnotation<string>(() => ""),
8
- *});
9
- */
10
- export declare const createState: <T extends readonly AnnotationRoot<any>[]>(...parents: T) => {
11
- build: <D extends StateDefinition>(state?: D) => any;
12
- };
13
- export declare const createDefaultAnnotation: <T>(defaultValue: () => T) => any;
@@ -1,20 +0,0 @@
1
- import { Annotation } from "@langchain/langgraph";
2
- /**
3
- * create state for langgraph
4
- * @example
5
- * export const GraphState = createState(createReactAgentAnnotation(), ModelState, SwarmState).build({
6
- * current_plan: createDefaultAnnotation<Plan | null>(() => null),
7
- * title: createDefaultAnnotation<string>(() => ""),
8
- *});
9
- */
10
- export const createState = (...parents) => {
11
- return {
12
- build: (state = {}) => {
13
- return Annotation.Root(Object.assign({}, ...parents.map((p) => p.spec), state));
14
- },
15
- };
16
- };
17
- export const createDefaultAnnotation = (defaultValue) => Annotation({
18
- reducer: (_, a) => a,
19
- default: defaultValue,
20
- });
@@ -1,16 +0,0 @@
1
- import { DynamicStructuredTool } from "@langchain/core/tools";
2
- export declare const FEToolsState: any;
3
- export interface FEToolParameters {
4
- name: string;
5
- type: string;
6
- description: string;
7
- required: boolean;
8
- }
9
- export interface FETool {
10
- name: string;
11
- description: string;
12
- parameters: FEToolParameters[];
13
- }
14
- export declare const createFETool: (tool: FETool) => FETool;
15
- export declare const createFeTools: (tools: FETool[]) => DynamicStructuredTool[];
16
- export declare const actionToTool: (tool: FETool) => DynamicStructuredTool;
@@ -1,37 +0,0 @@
1
- import { interrupt } from "@langchain/langgraph";
2
- import { createDefaultAnnotation } from "./createState.js";
3
- import { DynamicStructuredTool } from "@langchain/core/tools";
4
- import { createState } from "./createState.js";
5
- export const FEToolsState = createState().build({
6
- fe_tools: createDefaultAnnotation(() => []),
7
- });
8
- export const createFETool = (tool) => {
9
- return tool;
10
- };
11
- export const createFeTools = (tools) => {
12
- return tools
13
- .map((tool) => {
14
- try {
15
- return actionToTool(tool);
16
- }
17
- catch (e) {
18
- console.error(e);
19
- return null;
20
- }
21
- })
22
- .filter((tool) => tool !== null);
23
- };
24
- export const actionToTool = (tool) => {
25
- const callTool = async (args) => {
26
- const data = interrupt(JSON.stringify(args));
27
- return [data, null];
28
- };
29
- const schema = tool.parameters;
30
- return new DynamicStructuredTool({
31
- name: tool.name,
32
- description: tool.description || "",
33
- schema,
34
- func: callTool,
35
- responseFormat: "content_and_artifact",
36
- });
37
- };
@@ -1,3 +0,0 @@
1
- export * from "./createState.js";
2
- export * from "./feTools.js";
3
- export * from "./tools/index.js";
@@ -1,3 +0,0 @@
1
- export * from "./createState.js";
2
- export * from "./feTools.js";
3
- export * from "./tools/index.js";
@@ -1,23 +0,0 @@
1
- import { AIMessage, HumanMessage } from "@langchain/core/messages";
2
- export declare class InterruptModal {
3
- private inputParams;
4
- constructor(inputParams: {
5
- action: "prompt" | string;
6
- });
7
- rawResponse?: {
8
- response: string;
9
- request: {
10
- message: string;
11
- action: "prompt" | string;
12
- };
13
- };
14
- get response(): {
15
- answer?: string;
16
- };
17
- interrupt(message: string): this;
18
- isApprove(): string | undefined;
19
- isReject(): boolean;
20
- toMessages(options?: {
21
- AIAskMessage?: boolean;
22
- }): (false | HumanMessage | AIMessage | undefined)[];
23
- }
@@ -1,36 +0,0 @@
1
- import { AIMessage, HumanMessage } from "@langchain/core/messages";
2
- import { interrupt } from "@langchain/langgraph";
3
- export class InterruptModal {
4
- constructor(inputParams) {
5
- this.inputParams = inputParams;
6
- }
7
- get response() {
8
- if (!this.rawResponse)
9
- throw new Error("rawResponse is undefined");
10
- return JSON.parse(this.rawResponse.response);
11
- }
12
- interrupt(message) {
13
- const inputData = Object.assign({ message }, this.inputParams);
14
- const input = JSON.stringify(inputData);
15
- const response = interrupt(input);
16
- this.rawResponse = {
17
- request: inputData,
18
- response,
19
- };
20
- return this;
21
- }
22
- isApprove() {
23
- return this.response.answer;
24
- }
25
- isReject() {
26
- return !this.response.answer;
27
- }
28
- toMessages(options) {
29
- if (!this.rawResponse)
30
- throw new Error("rawResponse is undefined");
31
- return [
32
- (options === null || options === void 0 ? void 0 : options.AIAskMessage) && new AIMessage(this.rawResponse.request.message),
33
- new HumanMessage(this.response.answer),
34
- ].filter(Boolean);
35
- }
36
- }
@@ -1,11 +0,0 @@
1
- import { z } from "zod";
2
- import { AnnotationRoot, CompiledStateGraph } from "@langchain/langgraph";
3
- declare const METADATA_KEY_HANDOFF_DESTINATION = "__handoff_destination";
4
- interface CreateHandoffToolParams {
5
- agentName: string;
6
- description?: string;
7
- updateState?: (state: any) => Record<string, any>;
8
- }
9
- declare const createHandoffTool: ({ agentName, description, updateState }: CreateHandoffToolParams) => import("@langchain/core/tools").DynamicStructuredTool<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>, {}, {}, any>;
10
- declare const getHandoffDestinations: <AnnotationRootT extends AnnotationRoot<any>>(agent: CompiledStateGraph<AnnotationRootT["State"], AnnotationRootT["Update"], string, AnnotationRootT["spec"], AnnotationRootT["spec"]>, toolNodeName?: string) => string[];
11
- export { createHandoffTool, getHandoffDestinations, METADATA_KEY_HANDOFF_DESTINATION };
@@ -1,84 +0,0 @@
1
- import { z } from "zod";
2
- import { ToolMessage } from "@langchain/core/messages";
3
- import { tool } from "@langchain/core/tools";
4
- import { Command, getCurrentTaskInput, } from "@langchain/langgraph";
5
- const WHITESPACE_RE = /\s+/g;
6
- const METADATA_KEY_HANDOFF_DESTINATION = "__handoff_destination";
7
- function _normalizeAgentName(agentName) {
8
- /**
9
- * Normalize an agent name to be used inside the tool name.
10
- */
11
- return agentName.trim().replace(WHITESPACE_RE, "_").toLowerCase();
12
- }
13
- // type guard
14
- function isDynamicTool(tool) {
15
- return "schema" in tool && "name" in tool && "description" in tool && "responseFormat" in tool;
16
- }
17
- const createHandoffTool = ({ agentName, description, updateState }) => {
18
- /**
19
- * Create a tool that can handoff control to the requested agent.
20
- *
21
- * @param agentName - The name of the agent to handoff control to, i.e.
22
- * the name of the agent node in the multi-agent graph.
23
- * Agent names should be simple, clear and unique, preferably in snake_case,
24
- * although you are only limited to the names accepted by LangGraph
25
- * nodes as well as the tool names accepted by LLM providers
26
- * (the tool name will look like this: `transfer_to_<agent_name>`).
27
- * @param description - Optional description for the handoff tool.
28
- * @param updateState - Optional function to customize state updates during handoff.
29
- */
30
- const toolName = `transfer_to_${_normalizeAgentName(agentName)}`;
31
- const toolDescription = description || `Ask agent '${agentName}' for help`;
32
- const handoffTool = tool(async (_, config) => {
33
- /**
34
- * Ask another agent for help.
35
- */
36
- const toolMessage = new ToolMessage({
37
- content: `Successfully transferred to ${agentName}`,
38
- name: toolName,
39
- tool_call_id: config.toolCall.id,
40
- });
41
- // inject the current agent state
42
- const state = getCurrentTaskInput();
43
- // Base update object containing essential state updates
44
- const baseUpdate = {
45
- messages: state.messages.concat(toolMessage),
46
- activeAgent: agentName,
47
- };
48
- // Merge custom updates with base updates if updateState function is provided
49
- const finalUpdate = updateState ? { ...baseUpdate, ...updateState(state) } : baseUpdate;
50
- return new Command({
51
- goto: agentName,
52
- graph: Command.PARENT,
53
- update: finalUpdate,
54
- });
55
- }, {
56
- name: toolName,
57
- schema: z.object({}),
58
- description: toolDescription,
59
- });
60
- handoffTool.metadata = { [METADATA_KEY_HANDOFF_DESTINATION]: agentName };
61
- return handoffTool;
62
- };
63
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
- const getHandoffDestinations = (agent, toolNodeName = "tools") => {
65
- /**
66
- * Get a list of destinations from agent's handoff tools.
67
- *
68
- * @param agent - The compiled state graph
69
- * @param toolNodeName - The name of the tool node in the graph
70
- */
71
- const { nodes } = agent.getGraph();
72
- if (!(toolNodeName in nodes)) {
73
- return [];
74
- }
75
- const toolNode = nodes[toolNodeName].data;
76
- if (!toolNode || !("tools" in toolNode) || !toolNode.tools) {
77
- return [];
78
- }
79
- const { tools } = toolNode;
80
- return tools
81
- .filter((tool) => isDynamicTool(tool) && tool.metadata !== undefined && METADATA_KEY_HANDOFF_DESTINATION in tool.metadata)
82
- .map((tool) => tool.metadata[METADATA_KEY_HANDOFF_DESTINATION]);
83
- };
84
- export { createHandoffTool, getHandoffDestinations, METADATA_KEY_HANDOFF_DESTINATION };
@@ -1,6 +0,0 @@
1
- import { SwarmState } from "@langchain/langgraph-swarm";
2
- /**
3
- * 保留 langgraph-swarm 在 handoff 时丢失的 state
4
- */
5
- export declare const keepAllStateInHandOff: (state: typeof SwarmState.State) => any;
6
- export declare const createHandoffCommand: <T>(name: string, state: T) => any;
@@ -1,21 +0,0 @@
1
- import { Command } from "@langchain/langgraph";
2
- /**
3
- * 保留 langgraph-swarm 在 handoff 时丢失的 state
4
- */
5
- export const keepAllStateInHandOff = (state) => {
6
- // omit activeAgent and messages
7
- const { activeAgent, messages, ...rest } = state;
8
- return {
9
- ...rest,
10
- };
11
- };
12
- export const createHandoffCommand = (name, state) => {
13
- return new Command({
14
- goto: name,
15
- graph: Command.PARENT,
16
- update: {
17
- active_agent: name,
18
- ...state,
19
- },
20
- });
21
- };
@@ -1 +0,0 @@
1
- export * from "./sequential-thinking.js";
@@ -1 +0,0 @@
1
- export * from "./sequential-thinking.js";
@@ -1,52 +0,0 @@
1
- import { z } from "zod";
2
- export declare const SequentialThinkingTool: import("@langchain/core/tools").DynamicStructuredTool<z.ZodObject<{
3
- thought: z.ZodString;
4
- nextThoughtNeeded: z.ZodBoolean;
5
- thoughtNumber: z.ZodNumber;
6
- totalThoughts: z.ZodNumber;
7
- isRevision: z.ZodOptional<z.ZodBoolean>;
8
- revisesThought: z.ZodOptional<z.ZodNumber>;
9
- branchFromThought: z.ZodOptional<z.ZodNumber>;
10
- branchId: z.ZodOptional<z.ZodString>;
11
- needsMoreThoughts: z.ZodOptional<z.ZodBoolean>;
12
- }, "strip", z.ZodTypeAny, {
13
- thought: string;
14
- nextThoughtNeeded: boolean;
15
- thoughtNumber: number;
16
- totalThoughts: number;
17
- isRevision?: boolean | undefined;
18
- revisesThought?: number | undefined;
19
- branchFromThought?: number | undefined;
20
- branchId?: string | undefined;
21
- needsMoreThoughts?: boolean | undefined;
22
- }, {
23
- thought: string;
24
- nextThoughtNeeded: boolean;
25
- thoughtNumber: number;
26
- totalThoughts: number;
27
- isRevision?: boolean | undefined;
28
- revisesThought?: number | undefined;
29
- branchFromThought?: number | undefined;
30
- branchId?: string | undefined;
31
- needsMoreThoughts?: boolean | undefined;
32
- }>, {
33
- thought: string;
34
- nextThoughtNeeded: boolean;
35
- thoughtNumber: number;
36
- totalThoughts: number;
37
- isRevision?: boolean | undefined;
38
- revisesThought?: number | undefined;
39
- branchFromThought?: number | undefined;
40
- branchId?: string | undefined;
41
- needsMoreThoughts?: boolean | undefined;
42
- }, {
43
- thought: string;
44
- nextThoughtNeeded: boolean;
45
- thoughtNumber: number;
46
- totalThoughts: number;
47
- isRevision?: boolean | undefined;
48
- revisesThought?: number | undefined;
49
- branchFromThought?: number | undefined;
50
- branchId?: string | undefined;
51
- needsMoreThoughts?: boolean | undefined;
52
- }, string>;
@@ -1,69 +0,0 @@
1
- import { tool } from "@langchain/core/tools";
2
- import { z } from "zod";
3
- const schema = z.object({
4
- thought: z.string().describe("Your current thinking step"),
5
- nextThoughtNeeded: z.boolean().describe("Whether another thought step is needed"),
6
- thoughtNumber: z.number().min(1).describe("Current thought number"),
7
- totalThoughts: z.number().min(1).describe("Estimated total thoughts needed"),
8
- isRevision: z.boolean().optional().describe("Whether this revises previous thinking"),
9
- revisesThought: z.number().min(1).optional().describe("Which thought is being reconsidered"),
10
- branchFromThought: z.number().min(1).optional().describe("Branching point thought number"),
11
- branchId: z.string().optional().describe("Branch identifier"),
12
- needsMoreThoughts: z.boolean().optional().describe("If more thoughts are needed"),
13
- });
14
- // 存储思考历史
15
- const thoughtHistory = [];
16
- const branches = {};
17
- export const SequentialThinkingTool = tool(async (args) => {
18
- try {
19
- if (args.thoughtNumber > args.totalThoughts) {
20
- args.totalThoughts = args.thoughtNumber;
21
- }
22
- thoughtHistory.push(args);
23
- if (args.branchFromThought && args.branchId) {
24
- if (!branches[args.branchId]) {
25
- branches[args.branchId] = [];
26
- }
27
- branches[args.branchId].push(args);
28
- }
29
- return JSON.stringify({
30
- thoughtNumber: args.thoughtNumber,
31
- totalThoughts: args.totalThoughts,
32
- nextThoughtNeeded: args.nextThoughtNeeded,
33
- branches: Object.keys(branches),
34
- thoughtHistoryLength: thoughtHistory.length,
35
- }, null, 2);
36
- }
37
- catch (error) {
38
- return JSON.stringify({
39
- error: error instanceof Error ? error.message : String(error),
40
- status: "failed",
41
- }, null, 2);
42
- }
43
- }, {
44
- name: "sequential-thinking",
45
- description: `A detailed tool for dynamic and reflective problem-solving through thoughts.
46
- This tool helps analyze problems through a flexible thinking process that can adapt and evolve.
47
- Each thought can build on, question, or revise previous insights as understanding deepens.
48
-
49
- When to use this tool:
50
- - Breaking down complex problems into steps
51
- - Planning and design with room for revision
52
- - Analysis that might need course correction
53
- - Problems where the full scope might not be clear initially
54
- - Problems that require a multi-step solution
55
- - Tasks that need to maintain context over multiple steps
56
- - Situations where irrelevant information needs to be filtered out
57
-
58
- Key features:
59
- - You can adjust total_thoughts up or down as you progress
60
- - You can question or revise previous thoughts
61
- - You can add more thoughts even after reaching what seemed like the end
62
- - You can express uncertainty and explore alternative approaches
63
- - Not every thought needs to build linearly - you can branch or backtrack
64
- - Generates a solution hypothesis
65
- - Verifies the hypothesis based on the Chain of Thought steps
66
- - Repeats the process until satisfied
67
- - Provides a correct answer`,
68
- schema,
69
- });
@@ -1,3 +0,0 @@
1
- import { BaseMessage, HumanMessage } from "@langchain/core/messages";
2
- export declare const getTextMessageContent: (message: BaseMessage) => string;
3
- export declare function getLastHumanMessage(messages: BaseMessage[]): HumanMessage | undefined;
@@ -1,24 +0,0 @@
1
- import { isHumanMessage } from "@langchain/core/messages";
2
- export const getTextMessageContent = (message) => {
3
- if (typeof message.content === "string") {
4
- return message.content;
5
- }
6
- else {
7
- return message.content
8
- .filter((i) => i.type === "text")
9
- .map((i) => i.text)
10
- .join("\n");
11
- }
12
- };
13
- export function getLastHumanMessage(messages) {
14
- // 从后往前遍历消息列表
15
- for (let i = messages.length - 1; i >= 0; i--) {
16
- const message = messages[i];
17
- // 检查消息是否是 HumanMessage 的实例
18
- if (isHumanMessage(message)) {
19
- return message;
20
- }
21
- }
22
- // 如果没有找到 HumanMessage,则返回 undefined
23
- return undefined;
24
- }
@@ -1 +0,0 @@
1
- export {};
package/dist/test-type.js DELETED
@@ -1,5 +0,0 @@
1
- const t = {
2
- type: "tool",
3
- tool_call_id: "123"
4
- };
5
- export {};
package/dist/types.d.ts DELETED
@@ -1,106 +0,0 @@
1
- import { Thread, Assistant, Run, StreamMode, Command, Metadata, AssistantGraph, OnConflictBehavior, ThreadStatus, ValuesStreamEvent, UpdatesStreamEvent, DebugStreamEvent, MessagesStreamEvent, MessagesTupleStreamEvent, CustomStreamEvent, EventsStreamEvent, ErrorStreamEvent, MetadataStreamEvent, FeedbackStreamEvent, Config, Checkpoint } from "@langchain/langgraph-sdk";
2
- import { StreamEvent } from "@langchain/core/tracers/log_stream";
3
- export type AssistantSortBy = "assistant_id" | "graph_id" | "name" | "created_at" | "updated_at";
4
- export type ThreadSortBy = "thread_id" | "status" | "created_at" | "updated_at";
5
- export type SortOrder = "asc" | "desc";
6
- export type RunStatus = "pending" | "running" | "error" | "success" | "timeout" | "interrupted";
7
- export type MultitaskStrategy = "reject" | "interrupt" | "rollback" | "enqueue";
8
- export type DisconnectMode = "cancel" | "continue";
9
- export type OnCompletionBehavior = "complete" | "continue";
10
- export type CancelAction = "interrupt" | "rollback";
11
- export type TypedAsyncGenerator<TStateType = unknown, TUpdateType = TStateType, TCustomType = unknown> = AsyncGenerator<{
12
- values: ValuesStreamEvent<TStateType>;
13
- updates: UpdatesStreamEvent<TUpdateType>;
14
- custom: CustomStreamEvent<TCustomType>;
15
- debug: DebugStreamEvent;
16
- messages: MessagesStreamEvent;
17
- "messages-tuple": MessagesTupleStreamEvent;
18
- events: EventsStreamEvent;
19
- }[StreamMode] | ErrorStreamEvent | MetadataStreamEvent | FeedbackStreamEvent>;
20
- /**
21
- * 兼容 LangGraph SDK 的接口定义,方便进行无侵入式的扩展
22
- */
23
- export interface ILangGraphClient<TStateType = {}, TUpdateType = TStateType> {
24
- assistants: {
25
- search(query?: {
26
- graphId?: string;
27
- metadata?: Metadata;
28
- limit?: number;
29
- offset?: number;
30
- sortBy?: AssistantSortBy;
31
- sortOrder?: SortOrder;
32
- }): Promise<Assistant[]>;
33
- getGraph(assistantId: string, options?: {
34
- xray?: boolean | number;
35
- }): Promise<AssistantGraph>;
36
- };
37
- threads: {
38
- create(payload?: {
39
- metadata?: Metadata;
40
- threadId?: string;
41
- ifExists?: OnConflictBehavior;
42
- graphId?: string;
43
- supersteps?: Array<{
44
- updates: Array<{
45
- values: unknown;
46
- command?: Command;
47
- asNode: string;
48
- }>;
49
- }>;
50
- }): Promise<Thread<TStateType>>;
51
- search(query?: {
52
- metadata?: Metadata;
53
- limit?: number;
54
- offset?: number;
55
- status?: ThreadStatus;
56
- sortBy?: ThreadSortBy;
57
- sortOrder?: SortOrder;
58
- }): Promise<Thread<TStateType>[]>;
59
- get(threadId: string): Promise<Thread<TStateType>>;
60
- delete(threadId: string): Promise<void>;
61
- };
62
- runs: {
63
- list(threadId: string, options?: {
64
- limit?: number;
65
- offset?: number;
66
- status?: RunStatus;
67
- }): Promise<Run[]>;
68
- stream<TSubgraphs extends boolean = false>(threadId: string, assistantId: string, payload?: {
69
- input?: Record<string, unknown> | null;
70
- metadata?: Metadata;
71
- config?: Config;
72
- checkpointId?: string;
73
- checkpoint?: Omit<Checkpoint, "thread_id">;
74
- checkpointDuring?: boolean;
75
- interruptBefore?: "*" | string[];
76
- interruptAfter?: "*" | string[];
77
- multitaskStrategy?: MultitaskStrategy;
78
- onCompletion?: OnCompletionBehavior;
79
- signal?: AbortController["signal"];
80
- webhook?: string;
81
- onDisconnect?: DisconnectMode;
82
- afterSeconds?: number;
83
- ifNotExists?: "create" | "reject";
84
- command?: Command;
85
- onRunCreated?: (params: {
86
- run_id: string;
87
- thread_id?: string;
88
- }) => void;
89
- streamMode?: StreamMode[];
90
- streamSubgraphs?: TSubgraphs;
91
- streamResumable?: boolean;
92
- feedbackKeys?: string[];
93
- }): TypedAsyncGenerator<TSubgraphs, TStateType, TUpdateType>;
94
- joinStream(threadId: string, runId: string, options?: {
95
- signal?: AbortSignal;
96
- cancelOnDisconnect?: boolean;
97
- lastEventId?: string;
98
- streamMode?: StreamMode | StreamMode[];
99
- } | AbortSignal): AsyncGenerator<{
100
- id?: string;
101
- event: StreamEvent;
102
- data: any;
103
- }>;
104
- cancel(threadId: string, runId: string, wait?: boolean, action?: CancelAction): Promise<void>;
105
- };
106
- }
package/dist/types.js DELETED
@@ -1 +0,0 @@
1
- export {};
@@ -1,6 +0,0 @@
1
- /**
2
- * Creates a debounced function that executes once per animation frame
3
- * @param callback - The function to debounce
4
- * @returns A function that executes the callback on the next animation frame
5
- */
6
- export declare function rafDebounce<T extends (...args: any[]) => any>(callback: T): (...args: Parameters<T>) => void;
@@ -1,26 +0,0 @@
1
- /**
2
- * Creates a debounced function that executes once per animation frame
3
- * @param callback - The function to debounce
4
- * @returns A function that executes the callback on the next animation frame
5
- */
6
- export function rafDebounce(callback) {
7
- let rafId = null;
8
- let lastArgs = null;
9
- // Return the debounced function
10
- return function (...args) {
11
- // Store the most recent arguments
12
- lastArgs = args;
13
- // Cancel any pending animation frame
14
- if (rafId !== null) {
15
- cancelAnimationFrame(rafId);
16
- }
17
- // Schedule execution on the next animation frame
18
- rafId = requestAnimationFrame(() => {
19
- if (lastArgs !== null) {
20
- callback(...lastArgs);
21
- lastArgs = null;
22
- }
23
- rafId = null;
24
- });
25
- };
26
- }