@librechat/agents 3.1.86 → 3.1.88

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 (160) hide show
  1. package/README.md +69 -0
  2. package/dist/cjs/events.cjs +23 -0
  3. package/dist/cjs/events.cjs.map +1 -1
  4. package/dist/cjs/graphs/Graph.cjs +133 -18
  5. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  6. package/dist/cjs/graphs/MultiAgentGraph.cjs +1 -1
  7. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  8. package/dist/cjs/llm/anthropic/index.cjs +251 -53
  9. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  10. package/dist/cjs/llm/init.cjs +1 -5
  11. package/dist/cjs/llm/init.cjs.map +1 -1
  12. package/dist/cjs/llm/openai/index.cjs +113 -24
  13. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  14. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  15. package/dist/cjs/llm/openrouter/index.cjs +3 -1
  16. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  17. package/dist/cjs/main.cjs +18 -5
  18. package/dist/cjs/main.cjs.map +1 -1
  19. package/dist/cjs/openai/index.cjs +253 -0
  20. package/dist/cjs/openai/index.cjs.map +1 -0
  21. package/dist/cjs/responses/index.cjs +448 -0
  22. package/dist/cjs/responses/index.cjs.map +1 -0
  23. package/dist/cjs/run.cjs +108 -7
  24. package/dist/cjs/run.cjs.map +1 -1
  25. package/dist/cjs/session/AgentSession.cjs +1057 -0
  26. package/dist/cjs/session/AgentSession.cjs.map +1 -0
  27. package/dist/cjs/session/JsonlSessionStore.cjs +425 -0
  28. package/dist/cjs/session/JsonlSessionStore.cjs.map +1 -0
  29. package/dist/cjs/session/handlers.cjs +221 -0
  30. package/dist/cjs/session/handlers.cjs.map +1 -0
  31. package/dist/cjs/session/ids.cjs +22 -0
  32. package/dist/cjs/session/ids.cjs.map +1 -0
  33. package/dist/cjs/session/messageSerialization.cjs +179 -0
  34. package/dist/cjs/session/messageSerialization.cjs.map +1 -0
  35. package/dist/cjs/stream.cjs +475 -11
  36. package/dist/cjs/stream.cjs.map +1 -1
  37. package/dist/cjs/summarization/node.cjs +1 -1
  38. package/dist/cjs/summarization/node.cjs.map +1 -1
  39. package/dist/cjs/tools/ToolNode.cjs +177 -59
  40. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  41. package/dist/cjs/tools/eagerEventExecution.cjs +113 -0
  42. package/dist/cjs/tools/eagerEventExecution.cjs.map +1 -0
  43. package/dist/cjs/tools/handlers.cjs +1 -1
  44. package/dist/cjs/tools/handlers.cjs.map +1 -1
  45. package/dist/cjs/tools/streamedToolCallSeals.cjs +42 -0
  46. package/dist/cjs/tools/streamedToolCallSeals.cjs.map +1 -0
  47. package/dist/esm/events.mjs +23 -1
  48. package/dist/esm/events.mjs.map +1 -1
  49. package/dist/esm/graphs/Graph.mjs +133 -18
  50. package/dist/esm/graphs/Graph.mjs.map +1 -1
  51. package/dist/esm/graphs/MultiAgentGraph.mjs +1 -1
  52. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  53. package/dist/esm/llm/anthropic/index.mjs +251 -53
  54. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  55. package/dist/esm/llm/init.mjs +1 -5
  56. package/dist/esm/llm/init.mjs.map +1 -1
  57. package/dist/esm/llm/openai/index.mjs +113 -25
  58. package/dist/esm/llm/openai/index.mjs.map +1 -1
  59. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  60. package/dist/esm/llm/openrouter/index.mjs +4 -2
  61. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  62. package/dist/esm/main.mjs +5 -1
  63. package/dist/esm/main.mjs.map +1 -1
  64. package/dist/esm/openai/index.mjs +246 -0
  65. package/dist/esm/openai/index.mjs.map +1 -0
  66. package/dist/esm/responses/index.mjs +440 -0
  67. package/dist/esm/responses/index.mjs.map +1 -0
  68. package/dist/esm/run.mjs +108 -7
  69. package/dist/esm/run.mjs.map +1 -1
  70. package/dist/esm/session/AgentSession.mjs +1054 -0
  71. package/dist/esm/session/AgentSession.mjs.map +1 -0
  72. package/dist/esm/session/JsonlSessionStore.mjs +422 -0
  73. package/dist/esm/session/JsonlSessionStore.mjs.map +1 -0
  74. package/dist/esm/session/handlers.mjs +219 -0
  75. package/dist/esm/session/handlers.mjs.map +1 -0
  76. package/dist/esm/session/ids.mjs +17 -0
  77. package/dist/esm/session/ids.mjs.map +1 -0
  78. package/dist/esm/session/messageSerialization.mjs +173 -0
  79. package/dist/esm/session/messageSerialization.mjs.map +1 -0
  80. package/dist/esm/stream.mjs +476 -12
  81. package/dist/esm/stream.mjs.map +1 -1
  82. package/dist/esm/summarization/node.mjs +1 -1
  83. package/dist/esm/summarization/node.mjs.map +1 -1
  84. package/dist/esm/tools/ToolNode.mjs +177 -59
  85. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  86. package/dist/esm/tools/eagerEventExecution.mjs +107 -0
  87. package/dist/esm/tools/eagerEventExecution.mjs.map +1 -0
  88. package/dist/esm/tools/handlers.mjs +1 -1
  89. package/dist/esm/tools/handlers.mjs.map +1 -1
  90. package/dist/esm/tools/streamedToolCallSeals.mjs +36 -0
  91. package/dist/esm/tools/streamedToolCallSeals.mjs.map +1 -0
  92. package/dist/types/events.d.ts +1 -0
  93. package/dist/types/graphs/Graph.d.ts +24 -9
  94. package/dist/types/index.d.ts +1 -0
  95. package/dist/types/llm/openai/index.d.ts +1 -0
  96. package/dist/types/openai/index.d.ts +75 -0
  97. package/dist/types/responses/index.d.ts +97 -0
  98. package/dist/types/run.d.ts +2 -0
  99. package/dist/types/session/AgentSession.d.ts +32 -0
  100. package/dist/types/session/JsonlSessionStore.d.ts +67 -0
  101. package/dist/types/session/handlers.d.ts +8 -0
  102. package/dist/types/session/ids.d.ts +4 -0
  103. package/dist/types/session/index.d.ts +5 -0
  104. package/dist/types/session/messageSerialization.d.ts +7 -0
  105. package/dist/types/session/types.d.ts +191 -0
  106. package/dist/types/tools/ToolNode.d.ts +12 -1
  107. package/dist/types/tools/eagerEventExecution.d.ts +23 -0
  108. package/dist/types/tools/streamedToolCallSeals.d.ts +13 -0
  109. package/dist/types/types/hitl.d.ts +4 -0
  110. package/dist/types/types/run.d.ts +11 -1
  111. package/dist/types/types/tools.d.ts +36 -0
  112. package/package.json +19 -2
  113. package/src/__tests__/stream.eagerEventExecution.test.ts +2571 -0
  114. package/src/events.ts +29 -0
  115. package/src/graphs/Graph.ts +224 -50
  116. package/src/graphs/MultiAgentGraph.ts +1 -1
  117. package/src/graphs/__tests__/composition.smoke.test.ts +30 -0
  118. package/src/index.ts +3 -0
  119. package/src/llm/anthropic/index.ts +356 -84
  120. package/src/llm/anthropic/llm.spec.ts +64 -0
  121. package/src/llm/custom-chat-models.smoke.test.ts +175 -4
  122. package/src/llm/openai/contentBlocks.test.ts +35 -0
  123. package/src/llm/openai/deepseek.test.ts +201 -2
  124. package/src/llm/openai/index.ts +171 -26
  125. package/src/llm/openai/utils/index.ts +22 -0
  126. package/src/llm/openrouter/index.ts +4 -2
  127. package/src/openai/__tests__/openai.test.ts +337 -0
  128. package/src/openai/index.ts +404 -0
  129. package/src/responses/__tests__/responses.test.ts +652 -0
  130. package/src/responses/index.ts +677 -0
  131. package/src/run.ts +158 -8
  132. package/src/scripts/compare_pi_vs_ours.ts +592 -173
  133. package/src/scripts/session_live.ts +548 -0
  134. package/src/session/AgentSession.ts +1432 -0
  135. package/src/session/JsonlSessionStore.ts +572 -0
  136. package/src/session/__tests__/JsonlSessionStore.test.ts +1410 -0
  137. package/src/session/__tests__/handlers.test.ts +161 -0
  138. package/src/session/handlers.ts +272 -0
  139. package/src/session/ids.ts +17 -0
  140. package/src/session/index.ts +44 -0
  141. package/src/session/messageSerialization.ts +207 -0
  142. package/src/session/types.ts +275 -0
  143. package/src/specs/custom-event-await.test.ts +89 -0
  144. package/src/specs/summarization.test.ts +1 -1
  145. package/src/stream.ts +756 -48
  146. package/src/summarization/node.ts +1 -1
  147. package/src/tools/ToolNode.ts +299 -126
  148. package/src/tools/__tests__/ToolNode.eagerEventExecution.test.ts +373 -0
  149. package/src/tools/__tests__/handlers.test.ts +2 -1
  150. package/src/tools/__tests__/hitl.test.ts +206 -110
  151. package/src/tools/eagerEventExecution.ts +153 -0
  152. package/src/tools/handlers.ts +8 -4
  153. package/src/tools/streamedToolCallSeals.ts +57 -0
  154. package/src/types/hitl.ts +4 -0
  155. package/src/types/run.ts +11 -0
  156. package/src/types/tools.ts +36 -0
  157. package/dist/cjs/llm/text.cjs +0 -69
  158. package/dist/cjs/llm/text.cjs.map +0 -1
  159. package/dist/esm/llm/text.mjs +0 -67
  160. package/dist/esm/llm/text.mjs.map +0 -1
package/src/run.ts CHANGED
@@ -47,6 +47,60 @@ export const defaultOmitOptions = new Set([
47
47
  'additionalModelRequestFields',
48
48
  ]);
49
49
 
50
+ const CUSTOM_GRAPH_EVENTS = new Set<string>([
51
+ GraphEvents.ON_AGENT_UPDATE,
52
+ GraphEvents.ON_RUN_STEP,
53
+ GraphEvents.ON_RUN_STEP_DELTA,
54
+ GraphEvents.ON_RUN_STEP_COMPLETED,
55
+ GraphEvents.ON_MESSAGE_DELTA,
56
+ GraphEvents.ON_REASONING_DELTA,
57
+ GraphEvents.ON_TOOL_EXECUTE,
58
+ GraphEvents.ON_SUMMARIZE_START,
59
+ GraphEvents.ON_SUMMARIZE_DELTA,
60
+ GraphEvents.ON_SUMMARIZE_COMPLETE,
61
+ GraphEvents.ON_SUBAGENT_UPDATE,
62
+ GraphEvents.ON_AGENT_LOG,
63
+ GraphEvents.ON_CUSTOM_EVENT,
64
+ ]);
65
+
66
+ const DIRECT_DISPATCHED_STEP_EVENTS = new Set<string>([
67
+ GraphEvents.ON_RUN_STEP,
68
+ GraphEvents.ON_RUN_STEP_DELTA,
69
+ GraphEvents.ON_MESSAGE_DELTA,
70
+ GraphEvents.ON_REASONING_DELTA,
71
+ ]);
72
+
73
+ function getStepScopedEventId(data: unknown): string | undefined {
74
+ if (data == null || typeof data !== 'object') {
75
+ return undefined;
76
+ }
77
+ const candidate = data as { id?: unknown };
78
+ return typeof candidate.id === 'string' ? candidate.id : undefined;
79
+ }
80
+
81
+ function isLangGraphResumeMapForInterrupt(
82
+ value: unknown,
83
+ interruptId: string
84
+ ): value is Record<string, unknown> {
85
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
86
+ return false;
87
+ }
88
+ return Object.prototype.hasOwnProperty.call(value, interruptId);
89
+ }
90
+
91
+ type InterruptStateSnapshot = {
92
+ config?: RunnableConfig;
93
+ tasks?: Array<{
94
+ interrupts?: Array<{ id?: string }>;
95
+ }>;
96
+ };
97
+
98
+ type WorkflowWithStateHistory = {
99
+ getStateHistory?(
100
+ config: RunnableConfig
101
+ ): AsyncIterableIterator<InterruptStateSnapshot>;
102
+ };
103
+
50
104
  export class Run<_T extends t.BaseGraphState> {
51
105
  id: string;
52
106
  private tokenCounter?: t.TokenCounter;
@@ -54,6 +108,7 @@ export class Run<_T extends t.BaseGraphState> {
54
108
  private hookRegistry?: HookRegistry;
55
109
  private humanInTheLoop?: t.HumanInTheLoopConfig;
56
110
  private toolOutputReferences?: t.ToolOutputReferencesConfig;
111
+ private eagerEventToolExecution?: t.EagerEventToolExecutionConfig;
57
112
  private toolExecution?: t.ToolExecutionConfig;
58
113
  private indexTokenCountMap?: Record<string, number>;
59
114
  calibrationRatio: number = 1;
@@ -99,6 +154,7 @@ export class Run<_T extends t.BaseGraphState> {
99
154
  this.hookRegistry = config.hooks;
100
155
  this.humanInTheLoop = config.humanInTheLoop;
101
156
  this.toolOutputReferences = config.toolOutputReferences;
157
+ this.eagerEventToolExecution = config.eagerEventToolExecution;
102
158
  this.toolExecution = config.toolExecution;
103
159
 
104
160
  if (!config.graphConfig) {
@@ -180,6 +236,7 @@ export class Run<_T extends t.BaseGraphState> {
180
236
  standardGraph.hookRegistry = this.hookRegistry;
181
237
  standardGraph.humanInTheLoop = this.humanInTheLoop;
182
238
  standardGraph.toolOutputReferences = this.toolOutputReferences;
239
+ standardGraph.eagerEventToolExecution = this.eagerEventToolExecution;
183
240
  standardGraph.toolExecution = this.toolExecution;
184
241
  this.Graph = standardGraph;
185
242
  return standardGraph.createWorkflow();
@@ -205,6 +262,7 @@ export class Run<_T extends t.BaseGraphState> {
205
262
  multiAgentGraph.hookRegistry = this.hookRegistry;
206
263
  multiAgentGraph.humanInTheLoop = this.humanInTheLoop;
207
264
  multiAgentGraph.toolOutputReferences = this.toolOutputReferences;
265
+ multiAgentGraph.eagerEventToolExecution = this.eagerEventToolExecution;
208
266
  multiAgentGraph.toolExecution = this.toolExecution;
209
267
  this.Graph = multiAgentGraph;
210
268
  return multiAgentGraph.createWorkflow();
@@ -444,13 +502,15 @@ export class Run<_T extends t.BaseGraphState> {
444
502
  tags?: string[],
445
503
  metadata?: Record<string, unknown>
446
504
  ): Promise<void> => {
447
- // ON_RUN_STEP is dispatched directly via handler registry in
448
- // Graph.dispatchRunStep (primary, reliable path). Skip the
449
- // callback-based dispatch to prevent double handling.
505
+ // Step-scoped SDK events are dispatched directly via the handler
506
+ // registry first. Skip callback-based echoes to prevent double
507
+ // handling when LangGraph invokes custom callbacks more than once.
508
+ const stepScopedEventId = getStepScopedEventId(data);
450
509
  if (
451
- eventName === GraphEvents.ON_RUN_STEP &&
510
+ DIRECT_DISPATCHED_STEP_EVENTS.has(eventName) &&
452
511
  this.Graph != null &&
453
- this.Graph.handlerDispatchedStepIds.has((data as t.RunStep).id)
512
+ stepScopedEventId != null &&
513
+ this.Graph.hasHandlerDispatchedEvent(eventName, stepScopedEventId)
454
514
  ) {
455
515
  return;
456
516
  }
@@ -630,7 +690,7 @@ export class Run<_T extends t.BaseGraphState> {
630
690
  const eventName: t.EventName = info.event;
631
691
 
632
692
  /** Skip custom events as they're handled by our callback */
633
- if (eventName === GraphEvents.ON_CUSTOM_EVENT) {
693
+ if (CUSTOM_GRAPH_EVENTS.has(eventName)) {
634
694
  continue;
635
695
  }
636
696
 
@@ -697,6 +757,10 @@ export class Run<_T extends t.BaseGraphState> {
697
757
  }
698
758
  }
699
759
 
760
+ if (this._interrupt != null) {
761
+ await this.resolveInterruptResumeConfig(config);
762
+ }
763
+
700
764
  /**
701
765
  * Skip the Stop hook when the run paused on a HITL interrupt
702
766
  * (still pending human input) or was halted by a hook (the host
@@ -937,13 +1001,99 @@ export class Run<_T extends t.BaseGraphState> {
937
1001
  },
938
1002
  streamOptions?: t.EventStreamOptions
939
1003
  ): Promise<MessageContentComplex[] | undefined> {
1004
+ const interruptId = this._interrupt?.interruptId;
1005
+ const scopedResume =
1006
+ typeof interruptId === 'string' &&
1007
+ interruptId.length > 0 &&
1008
+ !isLangGraphResumeMapForInterrupt(resumeValue, interruptId)
1009
+ ? { [interruptId]: resumeValue }
1010
+ : resumeValue;
1011
+ const resumeConfig = await this.resolveInterruptResumeConfig(callerConfig);
940
1012
  return this.processStream(
941
- new Command({ resume: resumeValue }),
942
- callerConfig,
1013
+ new Command({ resume: scopedResume }),
1014
+ resumeConfig,
943
1015
  streamOptions
944
1016
  );
945
1017
  }
946
1018
 
1019
+ private async resolveInterruptResumeConfig(
1020
+ callerConfig: Partial<RunnableConfig> & {
1021
+ version: 'v1' | 'v2';
1022
+ run_id?: string;
1023
+ }
1024
+ ): Promise<
1025
+ Partial<RunnableConfig> & {
1026
+ version: 'v1' | 'v2';
1027
+ run_id?: string;
1028
+ }
1029
+ > {
1030
+ const interrupt = this._interrupt;
1031
+ const interruptId = interrupt?.interruptId;
1032
+ const workflow = this.graphRunnable as
1033
+ | (t.CompiledStateWorkflow & WorkflowWithStateHistory)
1034
+ | undefined;
1035
+ const stateHistory = workflow?.getStateHistory;
1036
+ if (interrupt?.checkpointId != null && interrupt.checkpointId.length > 0) {
1037
+ return {
1038
+ ...callerConfig,
1039
+ configurable: {
1040
+ ...callerConfig.configurable,
1041
+ checkpoint_id: interrupt.checkpointId,
1042
+ ...(typeof interrupt.checkpointNs === 'string'
1043
+ ? { checkpoint_ns: interrupt.checkpointNs }
1044
+ : {}),
1045
+ },
1046
+ };
1047
+ }
1048
+ if (
1049
+ interrupt == null ||
1050
+ typeof interruptId !== 'string' ||
1051
+ interruptId.length === 0 ||
1052
+ typeof stateHistory !== 'function'
1053
+ ) {
1054
+ return callerConfig;
1055
+ }
1056
+
1057
+ for await (const snapshot of stateHistory.call(
1058
+ this.graphRunnable,
1059
+ callerConfig as RunnableConfig
1060
+ )) {
1061
+ const hasMatchingInterrupt =
1062
+ snapshot.tasks?.some(
1063
+ (task) =>
1064
+ task.interrupts?.some(
1065
+ (interrupt) => interrupt.id === interruptId
1066
+ ) === true
1067
+ ) === true;
1068
+ const checkpointConfigurable = snapshot.config?.configurable;
1069
+ if (!hasMatchingInterrupt || checkpointConfigurable == null) {
1070
+ continue;
1071
+ }
1072
+
1073
+ const checkpointId = checkpointConfigurable.checkpoint_id;
1074
+ const checkpointNs = checkpointConfigurable.checkpoint_ns;
1075
+ if (typeof checkpointId === 'string' && checkpointId.length > 0) {
1076
+ this._interrupt = {
1077
+ ...interrupt,
1078
+ checkpointId,
1079
+ ...(typeof checkpointNs === 'string' ? { checkpointNs } : {}),
1080
+ };
1081
+ return {
1082
+ ...callerConfig,
1083
+ configurable: {
1084
+ ...callerConfig.configurable,
1085
+ checkpoint_id: checkpointId,
1086
+ ...(typeof checkpointNs === 'string'
1087
+ ? { checkpoint_ns: checkpointNs }
1088
+ : {}),
1089
+ },
1090
+ };
1091
+ }
1092
+ }
1093
+
1094
+ return callerConfig;
1095
+ }
1096
+
947
1097
  private createSystemCallback<K extends keyof t.ClientCallbacks>(
948
1098
  clientCallbacks: t.ClientCallbacks,
949
1099
  key: K