@librechat/agents 3.4.0 → 3.4.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.
Files changed (114) hide show
  1. package/dist/cjs/graphs/Graph.cjs +111 -27
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/hooks/HookRegistry.cjs +83 -0
  4. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  5. package/dist/cjs/hooks/executeHooks.cjs +60 -14
  6. package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
  7. package/dist/cjs/hooks/index.cjs.map +1 -1
  8. package/dist/cjs/hooks/types.cjs +2 -0
  9. package/dist/cjs/hooks/types.cjs.map +1 -1
  10. package/dist/cjs/llm/init.cjs +3 -3
  11. package/dist/cjs/llm/invoke.cjs +2 -2
  12. package/dist/cjs/main.cjs +14 -13
  13. package/dist/cjs/messages/format.cjs +40 -23
  14. package/dist/cjs/messages/format.cjs.map +1 -1
  15. package/dist/cjs/run.cjs +82 -15
  16. package/dist/cjs/run.cjs.map +1 -1
  17. package/dist/cjs/session/AgentSession.cjs +37 -2
  18. package/dist/cjs/session/AgentSession.cjs.map +1 -1
  19. package/dist/cjs/stream.cjs +1 -1
  20. package/dist/cjs/summarization/node.cjs +6 -3
  21. package/dist/cjs/summarization/node.cjs.map +1 -1
  22. package/dist/cjs/tools/BashExecutor.cjs +1 -1
  23. package/dist/cjs/tools/CodeExecutor.cjs +1 -1
  24. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +1 -1
  25. package/dist/cjs/tools/ToolNode.cjs +316 -94
  26. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  27. package/dist/cjs/tools/ToolSearch.cjs +1 -1
  28. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +630 -78
  29. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  30. package/dist/cjs/tools/subagent/SubagentReplay.cjs +175 -0
  31. package/dist/cjs/tools/subagent/SubagentReplay.cjs.map +1 -0
  32. package/dist/cjs/tools/toolOutputReferences.cjs +20 -0
  33. package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
  34. package/dist/cjs/utils/index.cjs +2 -2
  35. package/dist/esm/graphs/Graph.mjs +111 -27
  36. package/dist/esm/graphs/Graph.mjs.map +1 -1
  37. package/dist/esm/hooks/HookRegistry.mjs +83 -0
  38. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  39. package/dist/esm/hooks/executeHooks.mjs +60 -14
  40. package/dist/esm/hooks/executeHooks.mjs.map +1 -1
  41. package/dist/esm/hooks/index.mjs.map +1 -1
  42. package/dist/esm/hooks/types.mjs +2 -1
  43. package/dist/esm/hooks/types.mjs.map +1 -1
  44. package/dist/esm/llm/init.mjs +1 -1
  45. package/dist/esm/llm/invoke.mjs +2 -2
  46. package/dist/esm/main.mjs +11 -11
  47. package/dist/esm/messages/format.mjs +40 -23
  48. package/dist/esm/messages/format.mjs.map +1 -1
  49. package/dist/esm/run.mjs +83 -16
  50. package/dist/esm/run.mjs.map +1 -1
  51. package/dist/esm/session/AgentSession.mjs +37 -2
  52. package/dist/esm/session/AgentSession.mjs.map +1 -1
  53. package/dist/esm/stream.mjs +1 -1
  54. package/dist/esm/summarization/node.mjs +6 -3
  55. package/dist/esm/summarization/node.mjs.map +1 -1
  56. package/dist/esm/tools/BashExecutor.mjs +1 -1
  57. package/dist/esm/tools/CodeExecutor.mjs +1 -1
  58. package/dist/esm/tools/ProgrammaticToolCalling.mjs +1 -1
  59. package/dist/esm/tools/ToolNode.mjs +317 -95
  60. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  61. package/dist/esm/tools/ToolSearch.mjs +1 -1
  62. package/dist/esm/tools/subagent/SubagentExecutor.mjs +631 -79
  63. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  64. package/dist/esm/tools/subagent/SubagentReplay.mjs +168 -0
  65. package/dist/esm/tools/subagent/SubagentReplay.mjs.map +1 -0
  66. package/dist/esm/tools/toolOutputReferences.mjs +20 -0
  67. package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
  68. package/dist/esm/utils/index.mjs +2 -2
  69. package/dist/types/graphs/Graph.d.ts +16 -1
  70. package/dist/types/hooks/HookRegistry.d.ts +10 -1
  71. package/dist/types/hooks/executeHooks.d.ts +5 -1
  72. package/dist/types/hooks/index.d.ts +2 -2
  73. package/dist/types/hooks/types.d.ts +12 -0
  74. package/dist/types/run.d.ts +4 -1
  75. package/dist/types/session/AgentSession.d.ts +1 -0
  76. package/dist/types/tools/ToolNode.d.ts +23 -15
  77. package/dist/types/tools/subagent/SubagentExecutor.d.ts +46 -7
  78. package/dist/types/tools/subagent/SubagentReplay.d.ts +81 -0
  79. package/dist/types/tools/toolOutputReferences.d.ts +12 -0
  80. package/dist/types/types/graph.d.ts +5 -5
  81. package/dist/types/types/hitl.d.ts +15 -0
  82. package/package.json +6 -2
  83. package/src/graphs/Graph.ts +246 -52
  84. package/src/graphs/__tests__/Graph.breakerLifecycle.test.ts +48 -9
  85. package/src/graphs/__tests__/Graph.contextOverflow.test.ts +1 -1
  86. package/src/graphs/__tests__/Graph.subagentResumeState.test.ts +80 -0
  87. package/src/hooks/HookRegistry.ts +151 -1
  88. package/src/hooks/__tests__/HookRegistry.test.ts +96 -0
  89. package/src/hooks/__tests__/executeHooks.test.ts +160 -0
  90. package/src/hooks/executeHooks.ts +133 -15
  91. package/src/hooks/index.ts +3 -1
  92. package/src/hooks/types.ts +16 -0
  93. package/src/messages/format.ts +54 -26
  94. package/src/messages/formatAgentMessages.reducer.test.ts +162 -0
  95. package/src/messages/formatAgentMessages.steer.test.ts +16 -11
  96. package/src/messages/formatAgentMessages.test.ts +7 -2
  97. package/src/run.ts +164 -18
  98. package/src/session/AgentSession.ts +52 -2
  99. package/src/session/__tests__/JsonlSessionStore.test.ts +53 -0
  100. package/src/summarization/__tests__/node.test.ts +32 -14
  101. package/src/summarization/node.ts +15 -11
  102. package/src/tools/ToolNode.ts +631 -157
  103. package/src/tools/__tests__/SubagentExecutor.test.ts +542 -6
  104. package/src/tools/__tests__/SubagentReplay.test.ts +300 -0
  105. package/src/tools/__tests__/ToolNode.breakerSignal.test.ts +208 -2
  106. package/src/tools/__tests__/directToolHITLResumeScope.test.ts +486 -2
  107. package/src/tools/__tests__/hitl.test.ts +234 -5
  108. package/src/tools/__tests__/subagentHooks.test.ts +1040 -62
  109. package/src/tools/__tests__/toolOutputReferences.test.ts +19 -2
  110. package/src/tools/subagent/SubagentExecutor.ts +1369 -131
  111. package/src/tools/subagent/SubagentReplay.ts +575 -0
  112. package/src/tools/toolOutputReferences.ts +40 -1
  113. package/src/types/graph.ts +5 -5
  114. package/src/types/hitl.ts +16 -0
package/dist/cjs/run.cjs CHANGED
@@ -1,3 +1,4 @@
1
+ const require_SubagentReplay = require("./tools/subagent/SubagentReplay.cjs");
1
2
  const require_langfuseRuntimeContext = require("./langfuseRuntimeContext.cjs");
2
3
  const require_langfuseConfig = require("./langfuseConfig.cjs");
3
4
  const require_langfuseRuntimeScope = require("./langfuseRuntimeScope.cjs");
@@ -11,8 +12,8 @@ const require_title = require("./utils/title.cjs");
11
12
  const require_tokens = require("./utils/tokens.cjs");
12
13
  const require_instrumentation = require("./instrumentation.cjs");
13
14
  const require_llm = require("./utils/llm.cjs");
14
- const require_preempt = require("./llm/preempt.cjs");
15
15
  const require_events = require("./events.cjs");
16
+ const require_preempt = require("./llm/preempt.cjs");
16
17
  const require_init = require("./llm/init.cjs");
17
18
  const require_executeHooks = require("./hooks/executeHooks.cjs");
18
19
  require("./hooks/index.cjs");
@@ -69,6 +70,30 @@ function isLangGraphResumeMapForInterrupt(value, interruptId) {
69
70
  if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
70
71
  return Object.prototype.hasOwnProperty.call(value, interruptId);
71
72
  }
73
+ function getInterruptHookSessionId(payload) {
74
+ const publicPayload = require_SubagentReplay.stripSubagentResumeManifest(payload);
75
+ if (publicPayload == null || typeof publicPayload !== "object" || publicPayload.type !== "tool_approval") return;
76
+ const sessionId = publicPayload.hook_session_id;
77
+ return typeof sessionId === "string" && sessionId.length > 0 ? sessionId : void 0;
78
+ }
79
+ function getFirstPersistedInterrupt(snapshot) {
80
+ for (const task of snapshot.tasks ?? []) for (const pendingInterrupt of task.interrupts ?? []) if (typeof pendingInterrupt.id === "string" && pendingInterrupt.id.length > 0) return {
81
+ id: pendingInterrupt.id,
82
+ value: pendingInterrupt.value
83
+ };
84
+ }
85
+ function getPersistedMessages(snapshot) {
86
+ const messages = snapshot.values?.messages;
87
+ if (!Array.isArray(messages) || !messages.every(_langchain_core_messages.BaseMessage.isInstance)) return;
88
+ return messages;
89
+ }
90
+ function getResumeUpdateMessages(update) {
91
+ if (update == null) return;
92
+ const messages = Array.isArray(update) ? update.find(([key]) => key === "messages")?.[1] : update.messages;
93
+ if (_langchain_core_messages.BaseMessage.isInstance(messages)) return [messages];
94
+ if (!Array.isArray(messages) || !messages.every(_langchain_core_messages.BaseMessage.isInstance)) return;
95
+ return messages;
96
+ }
72
97
  var Run = class Run {
73
98
  id;
74
99
  tokenCounter;
@@ -140,10 +165,7 @@ var Run = class Run {
140
165
  } else {
141
166
  /** Default to legacy graph for 'standard' or undefined type */
142
167
  this.graphRunnable = this.createLegacyGraph(config.graphConfig);
143
- if (this.Graph) {
144
- this.Graph.compileOptions = config.graphConfig.compileOptions ?? this.Graph.compileOptions;
145
- this.Graph.handlerRegistry = handlerRegistry;
146
- }
168
+ if (this.Graph) this.Graph.handlerRegistry = handlerRegistry;
147
169
  }
148
170
  if (config.initialSessions && this.Graph) for (const [key, value] of config.initialSessions) this.Graph.sessions.set(key, value);
149
171
  this.returnContent = config.returnContent ?? false;
@@ -380,6 +402,9 @@ var Run = class Run {
380
402
  if (!this.Graph) throw new Error("Graph not initialized. Make sure to use Run.create() to instantiate the Run.");
381
403
  return this.Graph.getRunMessages();
382
404
  }
405
+ getChildCheckpointThreadIds() {
406
+ return this.Graph?.getChildCheckpointThreadIds() ?? [];
407
+ }
383
408
  /**
384
409
  * Returns a defensive snapshot of tools discovered by the current run.
385
410
  * Pass an agent id for that context, or omit it for the ordered union across
@@ -498,6 +523,10 @@ var Run = class Run {
498
523
  recursionLimit,
499
524
  configurable: { ...callerConfig.configurable }
500
525
  };
526
+ if (!isResume) {
527
+ delete config.configurable?.[require_SubagentReplay.SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY];
528
+ delete config.configurable?.[require_SubagentReplay.SUBAGENT_RESUME_MANIFEST_CONFIG_KEY];
529
+ }
501
530
  /**
502
531
  * Cancellation can arrive either at graph construction or per-call through
503
532
  * `callerConfig.signal`, and boundary hooks need to observe both — for a
@@ -855,7 +884,11 @@ var Run = class Run {
855
884
  * fields.
856
885
  */
857
886
  getInterrupt() {
858
- return this._interrupt;
887
+ if (this._interrupt == null) return;
888
+ return {
889
+ ...this._interrupt,
890
+ payload: require_SubagentReplay.stripSubagentResumeManifest(this._interrupt.payload)
891
+ };
859
892
  }
860
893
  /**
861
894
  * Returns the reason a hook halted the run via
@@ -926,29 +959,42 @@ var Run = class Run {
926
959
  * tool-node resume). Intended for custom, Command-routed graphs.
927
960
  */
928
961
  async resume(resumeValue, callerConfig, streamOptions, commandOptions) {
962
+ const resumeConfig = await this.resolveInterruptResumeConfig(callerConfig, commandOptions?.update);
929
963
  const interruptId = this._interrupt?.interruptId;
930
964
  const scopedResume = typeof interruptId === "string" && interruptId.length > 0 && !isLangGraphResumeMapForInterrupt(resumeValue, interruptId) ? { [interruptId]: resumeValue } : resumeValue;
931
- const resumeConfig = await this.resolveInterruptResumeConfig(callerConfig);
932
965
  return this.processStream(new _langchain_langgraph.Command({
933
966
  resume: scopedResume,
934
967
  ...commandOptions?.update !== void 0 ? { update: commandOptions.update } : {},
935
968
  ...commandOptions?.goto !== void 0 ? { goto: commandOptions.goto } : {}
936
969
  }), resumeConfig, streamOptions);
937
970
  }
938
- async resolveInterruptResumeConfig(callerConfig) {
971
+ async resolveInterruptResumeConfig(callerConfig, resumeUpdate) {
972
+ await this.restoreInterruptFromCheckpoint(callerConfig, resumeUpdate);
939
973
  const interrupt = this._interrupt;
974
+ const resumeManifest = require_SubagentReplay.requireValidSubagentResumeManifest(interrupt?.payload);
975
+ const resumeConfigurable = { ...callerConfig.configurable };
976
+ delete resumeConfigurable[require_SubagentReplay.SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY];
977
+ delete resumeConfigurable[require_SubagentReplay.SUBAGENT_RESUME_MANIFEST_CONFIG_KEY];
978
+ resumeConfigurable[require_SubagentReplay.SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY] = (0, nanoid.nanoid)();
979
+ if (resumeManifest != null) resumeConfigurable[require_SubagentReplay.SUBAGENT_RESUME_MANIFEST_CONFIG_KEY] = resumeManifest;
980
+ const manifestConfig = {
981
+ ...callerConfig,
982
+ configurable: resumeConfigurable
983
+ };
984
+ const hookSessionId = getInterruptHookSessionId(interrupt?.payload);
985
+ if (hookSessionId != null) this.hookRegistry?.copySession(hookSessionId, this.id);
940
986
  const interruptId = interrupt?.interruptId;
941
987
  const stateHistory = this.graphRunnable?.getStateHistory;
942
988
  if (interrupt?.checkpointId != null && interrupt.checkpointId.length > 0) return {
943
- ...callerConfig,
989
+ ...manifestConfig,
944
990
  configurable: {
945
- ...callerConfig.configurable,
991
+ ...manifestConfig.configurable,
946
992
  checkpoint_id: interrupt.checkpointId,
947
993
  ...typeof interrupt.checkpointNs === "string" ? { checkpoint_ns: interrupt.checkpointNs } : {}
948
994
  }
949
995
  };
950
- if (interrupt == null || typeof interruptId !== "string" || interruptId.length === 0 || typeof stateHistory !== "function") return callerConfig;
951
- for await (const snapshot of stateHistory.call(this.graphRunnable, callerConfig)) {
996
+ if (interrupt == null || typeof interruptId !== "string" || interruptId.length === 0 || typeof stateHistory !== "function") return manifestConfig;
997
+ for await (const snapshot of stateHistory.call(this.graphRunnable, manifestConfig)) {
952
998
  const hasMatchingInterrupt = snapshot.tasks?.some((task) => task.interrupts?.some((interrupt) => interrupt.id === interruptId) === true) === true;
953
999
  const checkpointConfigurable = snapshot.config?.configurable;
954
1000
  if (!hasMatchingInterrupt || checkpointConfigurable == null) continue;
@@ -961,16 +1007,37 @@ var Run = class Run {
961
1007
  ...typeof checkpointNs === "string" ? { checkpointNs } : {}
962
1008
  };
963
1009
  return {
964
- ...callerConfig,
1010
+ ...manifestConfig,
965
1011
  configurable: {
966
- ...callerConfig.configurable,
1012
+ ...manifestConfig.configurable,
967
1013
  checkpoint_id: checkpointId,
968
1014
  ...typeof checkpointNs === "string" ? { checkpoint_ns: checkpointNs } : {}
969
1015
  }
970
1016
  };
971
1017
  }
972
1018
  }
973
- return callerConfig;
1019
+ return manifestConfig;
1020
+ }
1021
+ async restoreInterruptFromCheckpoint(callerConfig, resumeUpdate) {
1022
+ if (this._interrupt != null || this.humanInTheLoop?.enabled !== true) return;
1023
+ const workflow = this.graphRunnable;
1024
+ if (typeof workflow?.getState !== "function") return;
1025
+ const snapshot = await workflow.getState(callerConfig);
1026
+ const persistedInterrupt = getFirstPersistedInterrupt(snapshot);
1027
+ if (persistedInterrupt == null) return;
1028
+ const persistedMessages = getPersistedMessages(snapshot);
1029
+ if (persistedMessages != null) this.Graph?.restoreCheckpointMessages(persistedMessages, getResumeUpdateMessages(resumeUpdate));
1030
+ const checkpointConfigurable = snapshot.config?.configurable;
1031
+ const checkpointId = checkpointConfigurable?.checkpoint_id;
1032
+ const checkpointNs = checkpointConfigurable?.checkpoint_ns;
1033
+ const threadId = callerConfig.configurable?.thread_id;
1034
+ this._interrupt = {
1035
+ interruptId: persistedInterrupt.id,
1036
+ payload: persistedInterrupt.value,
1037
+ ...typeof threadId === "string" ? { threadId } : {},
1038
+ ...typeof checkpointId === "string" ? { checkpointId } : {},
1039
+ ...typeof checkpointNs === "string" ? { checkpointNs } : {}
1040
+ };
974
1041
  }
975
1042
  createSystemCallback(clientCallbacks, key) {
976
1043
  return ((...args) => {