@librechat/agents 3.1.36 → 3.1.38

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 (35) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +3 -0
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +38 -29
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/stream.cjs +2 -1
  6. package/dist/cjs/stream.cjs.map +1 -1
  7. package/dist/cjs/tools/ToolNode.cjs +90 -14
  8. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  9. package/dist/cjs/tools/handlers.cjs +25 -8
  10. package/dist/cjs/tools/handlers.cjs.map +1 -1
  11. package/dist/esm/agents/AgentContext.mjs +3 -0
  12. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  13. package/dist/esm/graphs/Graph.mjs +38 -29
  14. package/dist/esm/graphs/Graph.mjs.map +1 -1
  15. package/dist/esm/stream.mjs +2 -1
  16. package/dist/esm/stream.mjs.map +1 -1
  17. package/dist/esm/tools/ToolNode.mjs +90 -14
  18. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  19. package/dist/esm/tools/handlers.mjs +25 -8
  20. package/dist/esm/tools/handlers.mjs.map +1 -1
  21. package/dist/types/agents/AgentContext.d.ts +2 -0
  22. package/dist/types/tools/ToolNode.d.ts +10 -0
  23. package/dist/types/types/tools.d.ts +7 -1
  24. package/package.json +1 -1
  25. package/src/agents/AgentContext.ts +3 -0
  26. package/src/graphs/Graph.ts +41 -36
  27. package/src/scripts/bedrock-content-aggregation-test.ts +265 -0
  28. package/src/scripts/bedrock-parallel-tools-test.ts +203 -0
  29. package/src/scripts/tools.ts +3 -12
  30. package/src/stream.ts +2 -1
  31. package/src/tools/ToolNode.ts +120 -14
  32. package/src/tools/__tests__/ToolNode.session.test.ts +465 -0
  33. package/src/tools/__tests__/handlers.test.ts +994 -0
  34. package/src/tools/handlers.ts +32 -13
  35. package/src/types/tools.ts +7 -1
@@ -117,6 +117,7 @@ export async function handleToolCallChunks({
117
117
  metadata
118
118
  );
119
119
  }
120
+
120
121
  await graph.dispatchRunStepDelta(stepId, {
121
122
  type: StepTypes.TOOL_CALLS,
122
123
  tool_calls: toolCallChunks,
@@ -129,7 +130,7 @@ export const handleToolCalls = async (
129
130
  graph?: StandardGraph | MultiAgentGraph
130
131
  ): Promise<void> => {
131
132
  if (!graph || !metadata) {
132
- console.warn(`Graph or metadata not found in ${event} event`);
133
+ console.warn('Graph or metadata not found in `handleToolCalls`');
133
134
  return;
134
135
  }
135
136
 
@@ -143,6 +144,13 @@ export const handleToolCalls = async (
143
144
 
144
145
  const stepKey = graph.getStepKey(metadata);
145
146
 
147
+ /**
148
+ * Track whether we've already reused an empty TOOL_CALLS step created by
149
+ * handleToolCallChunks during streaming. Only reuse it once (for the first
150
+ * tool call); subsequent parallel tool calls must create their own steps.
151
+ */
152
+ let reusedChunkStepId: string | undefined;
153
+
146
154
  for (const tool_call of toolCalls) {
147
155
  const toolCallId = tool_call.id ?? `toolu_${nanoid()}`;
148
156
  tool_call.id = toolCallId;
@@ -159,6 +167,27 @@ export const handleToolCalls = async (
159
167
  // no previous step
160
168
  }
161
169
 
170
+ /**
171
+ * If the previous step is TOOL_CALLS (from handleToolCallChunks or a prior
172
+ * iteration), either reuse it (if empty) or dispatch a new TOOL_CALLS step
173
+ * directly — skip the intermediate MESSAGE_CREATION to avoid orphaned gaps.
174
+ */
175
+ if (prevRunStep?.type === StepTypes.TOOL_CALLS) {
176
+ const details = prevRunStep.stepDetails as t.ToolCallsDetails;
177
+ const isEmpty = !details.tool_calls || details.tool_calls.length === 0;
178
+ if (isEmpty && prevStepId !== reusedChunkStepId) {
179
+ graph.toolCallStepIds.set(toolCallId, prevStepId);
180
+ reusedChunkStepId = prevStepId;
181
+ continue;
182
+ }
183
+ await graph.dispatchRunStep(
184
+ stepKey,
185
+ { type: StepTypes.TOOL_CALLS, tool_calls: [tool_call] },
186
+ metadata
187
+ );
188
+ continue;
189
+ }
190
+
162
191
  /**
163
192
  * NOTE: We do NOT dispatch empty text blocks with tool_call_ids because:
164
193
  * - Empty text blocks cause providers (Anthropic, Bedrock) to reject messages
@@ -167,19 +196,9 @@ export const handleToolCalls = async (
167
196
  * "The content field in the Message object is empty" (Bedrock)
168
197
  * - The tool_calls themselves are sufficient
169
198
  */
170
-
171
- /* If the previous step exists and is a message creation */
172
- if (
173
- prevStepId &&
174
- prevRunStep &&
175
- prevRunStep.type === StepTypes.MESSAGE_CREATION
176
- ) {
199
+ if (prevStepId && prevRunStep) {
177
200
  graph.messageStepHasToolCalls.set(prevStepId, true);
178
- /* If the previous step doesn't exist or is not a message creation */
179
- } else if (
180
- !prevRunStep ||
181
- prevRunStep.type !== StepTypes.MESSAGE_CREATION
182
- ) {
201
+ } else if (!prevRunStep) {
183
202
  const messageId = getMessageId(stepKey, graph, true) ?? '';
184
203
  const stepId = await graph.dispatchRunStep(
185
204
  stepKey,
@@ -60,6 +60,7 @@ export type ToolEndEvent = {
60
60
  tool_call: ToolCall;
61
61
  /** The content index of the tool call */
62
62
  index: number;
63
+ type?: 'tool_call';
63
64
  };
64
65
 
65
66
  export type CodeEnvFile = {
@@ -153,6 +154,11 @@ export type ToolCallRequest = {
153
154
  stepId?: string;
154
155
  /** Usage turn count for this tool */
155
156
  turn?: number;
157
+ /** Code execution session context for session continuity in event-driven mode */
158
+ codeSessionContext?: {
159
+ session_id: string;
160
+ files?: CodeEnvFile[];
161
+ };
156
162
  };
157
163
 
158
164
  /** Batch request containing ALL tool calls for a graph step */
@@ -335,7 +341,7 @@ export type CodeSessionContext = {
335
341
  /** Session ID from the code execution environment */
336
342
  session_id: string;
337
343
  /** Files generated in this session (for context/tracking) */
338
- files: FileRefs;
344
+ files?: FileRefs;
339
345
  /** Timestamp of last update */
340
346
  lastUpdated: number;
341
347
  };