@librechat/agents 3.1.88 → 3.1.90

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 (96) hide show
  1. package/dist/cjs/graphs/Graph.cjs +25 -1
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/hooks/executeHooks.cjs +14 -7
  4. package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
  5. package/dist/cjs/llm/anthropic/index.cjs +8 -2
  6. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  7. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +34 -0
  8. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  9. package/dist/cjs/main.cjs +9 -0
  10. package/dist/cjs/main.cjs.map +1 -1
  11. package/dist/cjs/stream.cjs +115 -8
  12. package/dist/cjs/stream.cjs.map +1 -1
  13. package/dist/cjs/tools/BashExecutor.cjs +10 -9
  14. package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
  15. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +12 -8
  16. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
  17. package/dist/cjs/tools/CodeExecutor.cjs +35 -11
  18. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  19. package/dist/cjs/tools/CodeSessionFileSummary.cjs +63 -0
  20. package/dist/cjs/tools/CodeSessionFileSummary.cjs.map +1 -0
  21. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +16 -12
  22. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  23. package/dist/cjs/tools/ToolNode.cjs +32 -12
  24. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  25. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +319 -29
  26. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  27. package/dist/cjs/tools/toolOutputReferences.cjs +8 -0
  28. package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
  29. package/dist/cjs/utils/events.cjs +3 -1
  30. package/dist/cjs/utils/events.cjs.map +1 -1
  31. package/dist/esm/graphs/Graph.mjs +25 -1
  32. package/dist/esm/graphs/Graph.mjs.map +1 -1
  33. package/dist/esm/hooks/executeHooks.mjs +14 -7
  34. package/dist/esm/hooks/executeHooks.mjs.map +1 -1
  35. package/dist/esm/llm/anthropic/index.mjs +9 -3
  36. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  37. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +33 -1
  38. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  39. package/dist/esm/main.mjs +2 -1
  40. package/dist/esm/main.mjs.map +1 -1
  41. package/dist/esm/stream.mjs +115 -8
  42. package/dist/esm/stream.mjs.map +1 -1
  43. package/dist/esm/tools/BashExecutor.mjs +11 -10
  44. package/dist/esm/tools/BashExecutor.mjs.map +1 -1
  45. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +13 -9
  46. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
  47. package/dist/esm/tools/CodeExecutor.mjs +29 -12
  48. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  49. package/dist/esm/tools/CodeSessionFileSummary.mjs +60 -0
  50. package/dist/esm/tools/CodeSessionFileSummary.mjs.map +1 -0
  51. package/dist/esm/tools/ProgrammaticToolCalling.mjs +17 -13
  52. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  53. package/dist/esm/tools/ToolNode.mjs +32 -12
  54. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  55. package/dist/esm/tools/subagent/SubagentExecutor.mjs +320 -31
  56. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  57. package/dist/esm/tools/toolOutputReferences.mjs +8 -1
  58. package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
  59. package/dist/esm/utils/events.mjs +3 -1
  60. package/dist/esm/utils/events.mjs.map +1 -1
  61. package/dist/types/graphs/Graph.d.ts +8 -0
  62. package/dist/types/llm/anthropic/index.d.ts +3 -1
  63. package/dist/types/llm/anthropic/utils/message_inputs.d.ts +4 -0
  64. package/dist/types/tools/BashExecutor.d.ts +3 -3
  65. package/dist/types/tools/CodeExecutor.d.ts +10 -3
  66. package/dist/types/tools/CodeSessionFileSummary.d.ts +3 -0
  67. package/dist/types/tools/ProgrammaticToolCalling.d.ts +4 -4
  68. package/dist/types/tools/subagent/SubagentExecutor.d.ts +8 -5
  69. package/dist/types/types/tools.d.ts +11 -3
  70. package/dist/types/utils/events.d.ts +1 -1
  71. package/package.json +1 -1
  72. package/src/__tests__/stream.eagerEventExecution.test.ts +1073 -221
  73. package/src/graphs/Graph.ts +27 -5
  74. package/src/hooks/__tests__/executeHooks.test.ts +38 -0
  75. package/src/hooks/executeHooks.ts +27 -7
  76. package/src/llm/anthropic/index.ts +27 -3
  77. package/src/llm/anthropic/llm.spec.ts +60 -1
  78. package/src/llm/anthropic/utils/message_inputs.ts +46 -0
  79. package/src/specs/subagent.test.ts +87 -1
  80. package/src/stream.ts +163 -12
  81. package/src/tools/BashExecutor.ts +21 -10
  82. package/src/tools/BashProgrammaticToolCalling.ts +21 -9
  83. package/src/tools/CodeExecutor.ts +55 -12
  84. package/src/tools/CodeSessionFileSummary.ts +80 -0
  85. package/src/tools/ProgrammaticToolCalling.ts +25 -12
  86. package/src/tools/ToolNode.ts +142 -116
  87. package/src/tools/__tests__/BashExecutor.test.ts +9 -0
  88. package/src/tools/__tests__/CodeApiAuthHeaders.test.ts +43 -0
  89. package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +100 -16
  90. package/src/tools/__tests__/SubagentExecutor.test.ts +540 -6
  91. package/src/tools/__tests__/ToolNode.eagerEventExecution.test.ts +278 -14
  92. package/src/tools/__tests__/ToolNode.outputReferences.test.ts +52 -0
  93. package/src/tools/__tests__/subagentHooks.test.ts +237 -0
  94. package/src/tools/subagent/SubagentExecutor.ts +514 -36
  95. package/src/types/tools.ts +11 -3
  96. package/src/utils/events.ts +4 -2
@@ -1,17 +1,24 @@
1
1
  import { nanoid } from 'nanoid';
2
2
  import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
3
3
  import { HumanMessage } from '@langchain/core/messages';
4
- import { GraphEvents, Callback } from '../../common/enum.mjs';
4
+ import { GraphEvents, Callback, StepTypes } from '../../common/enum.mjs';
5
5
  import { executeHooks } from '../../hooks/executeHooks.mjs';
6
6
  import '../../hooks/createWorkspacePolicyHook.mjs';
7
7
 
8
8
  const DEFAULT_MAX_TURNS = 25;
9
9
  const RECURSION_MULTIPLIER = 3;
10
10
  const ERROR_MESSAGE_MAX_CHARS = 200;
11
+ const MAX_PENDING_SUBAGENT_UPDATES = 64;
11
12
  const HOOK_FALLBACK = Object.freeze({
12
13
  additionalContexts: [],
13
14
  errors: [],
14
15
  });
16
+ const LANGGRAPH_RUNTIME_CONFIG_PREFIX = '__pregel_';
17
+ const LANGGRAPH_CHECKPOINT_CONFIG_KEYS = new Set([
18
+ 'checkpoint_id',
19
+ 'checkpoint_map',
20
+ 'checkpoint_ns',
21
+ ]);
15
22
  class SubagentExecutor {
16
23
  configs;
17
24
  parentSignal;
@@ -110,7 +117,7 @@ class SubagentExecutor {
110
117
  agents: [childInputs],
111
118
  tokenCounter: this.tokenCounter,
112
119
  });
113
- const forwarder = forwardingEnabled
120
+ const forwarding = forwardingEnabled
114
121
  ? this.createForwarderCallback({
115
122
  parentRegistry: parentRegistry,
116
123
  subagentType,
@@ -119,6 +126,7 @@ class SubagentExecutor {
119
126
  parentToolCallId,
120
127
  })
121
128
  : undefined;
129
+ const forwarder = forwarding?.handler;
122
130
  if (forwarder) {
123
131
  await this.emitSubagentUpdate(parentRegistry, {
124
132
  childRunId,
@@ -151,10 +159,11 @@ class SubagentExecutor {
151
159
  */
152
160
  const callbacks = forwarder ? [forwarder] : [];
153
161
  /**
154
- * Inherit the parent's `configurable` verbatim — host-set fields
162
+ * Inherit the parent's host `configurable` — host-set fields
155
163
  * (`requestBody`, `user`, `userMCPAuthMap`, etc.) AND the run-
156
164
  * identity fields (`run_id`, `parent_run_id`, `thread_id`) all
157
- * propagate.
165
+ * propagate. LangGraph's own runtime keys are excluded because the
166
+ * child graph creates its own scratchpad/checkpoint/abort plumbing.
158
167
  *
159
168
  * Run-identity propagation is intentional and matches the
160
169
  * convention this executor itself already uses for `SubagentStart`
@@ -178,7 +187,7 @@ class SubagentExecutor {
178
187
  * For now the inheritance path matches LibreChat's primary use
179
188
  * case (synchronous subagents within a single user turn).
180
189
  */
181
- const inheritedConfigurable = params.parentConfigurable ?? {};
190
+ const inheritedConfigurable = sanitizeChildConfigurable(params.parentConfigurable);
182
191
  result = await workflow.invoke({ messages: [new HumanMessage(description)] }, {
183
192
  recursionLimit: maxTurns * RECURSION_MULTIPLIER,
184
193
  signal: this.parentSignal,
@@ -193,6 +202,7 @@ class SubagentExecutor {
193
202
  catch (error) {
194
203
  const errorMessage = truncateErrorMessage(error);
195
204
  if (forwarder) {
205
+ await forwarding.drain();
196
206
  await this.emitSubagentUpdate(parentRegistry, {
197
207
  childRunId,
198
208
  subagentType,
@@ -234,6 +244,7 @@ class SubagentExecutor {
234
244
  });
235
245
  }
236
246
  if (forwarder) {
247
+ await forwarding.drain();
237
248
  await this.emitSubagentUpdate(parentRegistry, {
238
249
  childRunId,
239
250
  subagentType,
@@ -296,25 +307,67 @@ class SubagentExecutor {
296
307
  if (!handler) {
297
308
  return;
298
309
  }
299
- const event = {
300
- runId: parentRunId,
301
- subagentRunId: childRunId,
302
- subagentType,
303
- subagentAgentId,
304
- parentAgentId,
305
- parentToolCallId,
306
- phase,
307
- data,
308
- label: summarizeEvent(eventName, data),
309
- timestamp: new Date().toISOString(),
310
- };
311
310
  try {
311
+ const event = {
312
+ runId: parentRunId,
313
+ subagentRunId: childRunId,
314
+ subagentType,
315
+ subagentAgentId,
316
+ parentAgentId,
317
+ parentToolCallId,
318
+ phase,
319
+ data: sanitizeForwardedSubagentUpdateData(eventName, data),
320
+ label: summarizeEvent(eventName, data),
321
+ timestamp: new Date().toISOString(),
322
+ };
312
323
  await handler.handle(GraphEvents.ON_SUBAGENT_UPDATE, event);
313
324
  }
314
325
  catch {
315
326
  /* observational — swallow */
316
327
  }
317
328
  };
329
+ const queuedUpdates = [];
330
+ let drainPromise;
331
+ const enqueue = (update) => {
332
+ if (queuedUpdates.length >= MAX_PENDING_SUBAGENT_UPDATES) {
333
+ const dropIndex = queuedUpdates.findIndex((queued) => isDroppableSubagentUpdatePhase(queued.phase));
334
+ if (dropIndex >= 0) {
335
+ queuedUpdates.splice(dropIndex, 1);
336
+ }
337
+ else if (isDroppableSubagentUpdatePhase(update.phase)) {
338
+ return;
339
+ }
340
+ }
341
+ queuedUpdates.push(update);
342
+ };
343
+ const drain = async () => {
344
+ if (drainPromise != null) {
345
+ await drainPromise;
346
+ return;
347
+ }
348
+ drainPromise = (async () => {
349
+ while (queuedUpdates.length > 0) {
350
+ const update = queuedUpdates.shift();
351
+ if (update == null) {
352
+ continue;
353
+ }
354
+ await wrap(update.eventName, update.phase, update.data);
355
+ }
356
+ })();
357
+ try {
358
+ await drainPromise;
359
+ }
360
+ finally {
361
+ drainPromise = undefined;
362
+ if (queuedUpdates.length > 0) {
363
+ await drain();
364
+ }
365
+ }
366
+ };
367
+ const scheduleWrap = (eventName, phase, data) => {
368
+ enqueue({ eventName, phase, data });
369
+ void drain();
370
+ };
318
371
  const handler = BaseCallbackHandler.fromMethods({
319
372
  [Callback.CUSTOM_EVENT]: async (eventName, data) => {
320
373
  if (eventName === GraphEvents.ON_TOOL_EXECUTE) {
@@ -326,27 +379,27 @@ class SubagentExecutor {
326
379
  * We also surface a short notice in the subagent-update stream so
327
380
  * the UI can show "calling <tool>" for each tool the child spawns.
328
381
  */
329
- await wrap(eventName, 'run_step', data);
382
+ scheduleWrap(eventName, 'run_step', data);
330
383
  return;
331
384
  }
332
385
  if (eventName === GraphEvents.ON_RUN_STEP) {
333
- await wrap(eventName, 'run_step', data);
386
+ scheduleWrap(eventName, 'run_step', data);
334
387
  return;
335
388
  }
336
389
  if (eventName === GraphEvents.ON_RUN_STEP_DELTA) {
337
- await wrap(eventName, 'run_step_delta', data);
390
+ scheduleWrap(eventName, 'run_step_delta', data);
338
391
  return;
339
392
  }
340
393
  if (eventName === GraphEvents.ON_RUN_STEP_COMPLETED) {
341
- await wrap(eventName, 'run_step_completed', data);
394
+ scheduleWrap(eventName, 'run_step_completed', data);
342
395
  return;
343
396
  }
344
397
  if (eventName === GraphEvents.ON_MESSAGE_DELTA) {
345
- await wrap(eventName, 'message_delta', data);
398
+ scheduleWrap(eventName, 'message_delta', data);
346
399
  return;
347
400
  }
348
401
  if (eventName === GraphEvents.ON_REASONING_DELTA) {
349
- await wrap(eventName, 'reasoning_delta', data);
402
+ scheduleWrap(eventName, 'reasoning_delta', data);
350
403
  return;
351
404
  }
352
405
  },
@@ -354,15 +407,251 @@ class SubagentExecutor {
354
407
  /**
355
408
  * `awaitHandlers = true` is required so the child's `ToolNode` actually
356
409
  * blocks on the parent's `ON_TOOL_EXECUTE` handler until it resolves
357
- * the batch request. The same flag applies to observational events
358
- * (message_delta, run_step, …), which means a slow
359
- * `ON_SUBAGENT_UPDATE` handler on the host serializes the child
360
- * stream. If host-side latency becomes a concern, a future
361
- * refinement could split operational and observational events into
362
- * separate callback handlers with distinct await semantics.
410
+ * the batch request. Observational `ON_SUBAGENT_UPDATE` calls are queued
411
+ * behind a bounded sequential dispatcher so host UI publication cannot
412
+ * backpressure each child emission or run unbounded concurrent publishes.
413
+ * The executor drains this queue before terminal stop/error envelopes to
414
+ * preserve phase ordering.
363
415
  */
364
416
  handler.awaitHandlers = true;
365
- return handler;
417
+ return { handler, drain };
418
+ }
419
+ }
420
+ function sanitizeChildConfigurable(parentConfigurable) {
421
+ if (parentConfigurable == null) {
422
+ return {};
423
+ }
424
+ return Object.fromEntries(Object.entries(parentConfigurable).filter(([key]) => !isLangGraphRuntimeConfigKey(key)));
425
+ }
426
+ function isLangGraphRuntimeConfigKey(key) {
427
+ return (key.startsWith(LANGGRAPH_RUNTIME_CONFIG_PREFIX) ||
428
+ LANGGRAPH_CHECKPOINT_CONFIG_KEYS.has(key));
429
+ }
430
+ function sanitizeForwardedSubagentUpdateData(eventName, data) {
431
+ if (eventName === GraphEvents.ON_TOOL_EXECUTE) {
432
+ return sanitizeToolExecuteUpdateData(data);
433
+ }
434
+ if (eventName === GraphEvents.ON_RUN_STEP) {
435
+ return sanitizeRunStepUpdateData(data);
436
+ }
437
+ if (eventName === GraphEvents.ON_RUN_STEP_DELTA) {
438
+ return sanitizeRunStepDeltaUpdateData(data);
439
+ }
440
+ if (eventName === GraphEvents.ON_RUN_STEP_COMPLETED) {
441
+ return sanitizeRunStepCompletedUpdateData(data);
442
+ }
443
+ if (eventName === GraphEvents.ON_MESSAGE_DELTA) {
444
+ return sanitizeMessageDeltaUpdateData(data);
445
+ }
446
+ if (eventName === GraphEvents.ON_REASONING_DELTA) {
447
+ return sanitizeReasoningDeltaUpdateData(data);
448
+ }
449
+ return undefined;
450
+ }
451
+ function isDroppableSubagentUpdatePhase(phase) {
452
+ return (phase === 'message_delta' ||
453
+ phase === 'reasoning_delta' ||
454
+ phase === 'run_step_delta');
455
+ }
456
+ function sanitizeToolExecuteUpdateData(data) {
457
+ const request = data;
458
+ const toolCalls = Array.isArray(request.toolCalls)
459
+ ? request.toolCalls.map(sanitizeToolCallForUpdate)
460
+ : [];
461
+ const sanitized = { toolCalls };
462
+ if (typeof request.agentId === 'string') {
463
+ sanitized.agentId = request.agentId;
464
+ }
465
+ return sanitized;
466
+ }
467
+ function sanitizeToolCallForUpdate(call) {
468
+ const sanitized = {
469
+ id: call.id,
470
+ name: call.name,
471
+ args: call.args,
472
+ };
473
+ return sanitized;
474
+ }
475
+ function sanitizeRunStepUpdateData(data) {
476
+ if (!isObjectLike(data)) {
477
+ return undefined;
478
+ }
479
+ const step = data;
480
+ const sanitized = {};
481
+ assignString(sanitized, 'agentId', step.agentId);
482
+ assignNumber(sanitized, 'groupId', step.groupId);
483
+ assignString(sanitized, 'id', step.id);
484
+ assignNumber(sanitized, 'index', step.index);
485
+ assignString(sanitized, 'runId', step.runId);
486
+ assignNumber(sanitized, 'stepIndex', step.stepIndex);
487
+ assignString(sanitized, 'type', step.type);
488
+ if (step.summary !== undefined) {
489
+ sanitized.summary = step.summary;
490
+ }
491
+ if (step.usage !== undefined) {
492
+ sanitized.usage = step.usage;
493
+ }
494
+ sanitized.stepDetails = sanitizeStepDetails(step.stepDetails);
495
+ return sanitized;
496
+ }
497
+ function sanitizeRunStepDeltaUpdateData(data) {
498
+ if (!isObjectLike(data)) {
499
+ return undefined;
500
+ }
501
+ const event = data;
502
+ const sanitized = {};
503
+ assignString(sanitized, 'id', event.id);
504
+ sanitized.delta = sanitizeToolCallDelta(event.delta);
505
+ return sanitized;
506
+ }
507
+ function sanitizeRunStepCompletedUpdateData(data) {
508
+ if (!isObjectLike(data)) {
509
+ return undefined;
510
+ }
511
+ const event = data;
512
+ return { result: sanitizeStepCompleted(event.result) };
513
+ }
514
+ function sanitizeMessageDeltaUpdateData(data) {
515
+ if (!isObjectLike(data)) {
516
+ return undefined;
517
+ }
518
+ const event = data;
519
+ const sanitized = {};
520
+ assignString(sanitized, 'id', event.id);
521
+ if (event.delta != null) {
522
+ sanitized.delta = {};
523
+ if (event.delta.content !== undefined) {
524
+ sanitized.delta.content = event.delta.content;
525
+ }
526
+ if (event.delta.tool_call_ids !== undefined) {
527
+ sanitized.delta.tool_call_ids = event.delta.tool_call_ids;
528
+ }
529
+ }
530
+ return sanitized;
531
+ }
532
+ function sanitizeReasoningDeltaUpdateData(data) {
533
+ if (!isObjectLike(data)) {
534
+ return undefined;
535
+ }
536
+ const event = data;
537
+ const sanitized = {};
538
+ assignString(sanitized, 'id', event.id);
539
+ if (event.delta?.content !== undefined) {
540
+ sanitized.delta = { content: event.delta.content };
541
+ }
542
+ return sanitized;
543
+ }
544
+ function sanitizeStepDetails(stepDetails) {
545
+ if (!isObjectLike(stepDetails)) {
546
+ return undefined;
547
+ }
548
+ const rawDetails = stepDetails;
549
+ if (rawDetails.type === StepTypes.MESSAGE_CREATION) {
550
+ const sanitized = {
551
+ type: StepTypes.MESSAGE_CREATION,
552
+ };
553
+ const messageId = rawDetails.message_creation?.message_id;
554
+ if (typeof messageId === 'string') {
555
+ sanitized.message_creation = { message_id: messageId };
556
+ }
557
+ return sanitized;
558
+ }
559
+ if (rawDetails.type === StepTypes.TOOL_CALLS) {
560
+ const sanitized = {
561
+ type: StepTypes.TOOL_CALLS,
562
+ };
563
+ if (Array.isArray(rawDetails.tool_calls)) {
564
+ sanitized.tool_calls = rawDetails.tool_calls.map(sanitizeAgentToolCall);
565
+ }
566
+ return sanitized;
567
+ }
568
+ return undefined;
569
+ }
570
+ function sanitizeToolCallDelta(delta) {
571
+ if (!isObjectLike(delta)) {
572
+ return undefined;
573
+ }
574
+ const sanitized = {};
575
+ assignString(sanitized, 'auth', delta.auth);
576
+ assignNumber(sanitized, 'expires_at', delta.expires_at);
577
+ assignString(sanitized, 'type', delta.type);
578
+ if (delta.summary !== undefined) {
579
+ sanitized.summary = delta.summary;
580
+ }
581
+ if (Array.isArray(delta.tool_calls)) {
582
+ sanitized.tool_calls = delta.tool_calls.map(sanitizeAgentToolCall);
583
+ }
584
+ return sanitized;
585
+ }
586
+ function sanitizeStepCompleted(data) {
587
+ if (!isObjectLike(data)) {
588
+ return undefined;
589
+ }
590
+ const completed = data;
591
+ if (completed.type === 'summary') {
592
+ return {
593
+ type: 'summary',
594
+ summary: completed.summary,
595
+ };
596
+ }
597
+ if (completed.type !== 'tool_call') {
598
+ return undefined;
599
+ }
600
+ const sanitized = { type: 'tool_call' };
601
+ assignString(sanitized, 'id', completed.id);
602
+ assignNumber(sanitized, 'index', completed.index);
603
+ sanitized.tool_call = sanitizeProcessedToolCall(completed.tool_call);
604
+ return sanitized;
605
+ }
606
+ function sanitizeProcessedToolCall(toolCall) {
607
+ if (!isObjectLike(toolCall)) {
608
+ return undefined;
609
+ }
610
+ const call = toolCall;
611
+ const sanitized = {};
612
+ assignString(sanitized, 'id', call.id);
613
+ assignString(sanitized, 'name', call.name);
614
+ if (call.args !== undefined) {
615
+ sanitized.args = call.args;
616
+ }
617
+ assignString(sanitized, 'output', call.output);
618
+ assignNumber(sanitized, 'progress', call.progress);
619
+ return sanitized;
620
+ }
621
+ function sanitizeAgentToolCall(toolCall) {
622
+ if (!isObjectLike(toolCall)) {
623
+ return {};
624
+ }
625
+ const call = toolCall;
626
+ const sanitized = {};
627
+ assignString(sanitized, 'id', call.id);
628
+ assignString(sanitized, 'name', call.name);
629
+ assignString(sanitized, 'type', call.type);
630
+ if (call.args !== undefined) {
631
+ sanitized.args = call.args;
632
+ }
633
+ if (isObjectLike(call.function)) {
634
+ const fn = {};
635
+ assignString(fn, 'name', call.function.name);
636
+ if (typeof call.function.arguments === 'string' ||
637
+ isObjectLike(call.function.arguments)) {
638
+ fn.arguments = call.function.arguments;
639
+ }
640
+ sanitized.function = fn;
641
+ }
642
+ return sanitized;
643
+ }
644
+ function isObjectLike(value) {
645
+ return value != null && typeof value === 'object' && !Array.isArray(value);
646
+ }
647
+ function assignString(target, key, value) {
648
+ if (typeof value === 'string') {
649
+ target[key] = value;
650
+ }
651
+ }
652
+ function assignNumber(target, key, value) {
653
+ if (typeof value === 'number') {
654
+ target[key] = value;
366
655
  }
367
656
  }
368
657
  /**
@@ -532,5 +821,5 @@ function truncateErrorMessage(error) {
532
821
  return `${message.slice(0, ERROR_MESSAGE_MAX_CHARS)}...`;
533
822
  }
534
823
 
535
- export { SubagentExecutor, buildChildInputs, filterSubagentResult, resolveSubagentConfigs, summarizeEvent };
824
+ export { SubagentExecutor, buildChildInputs, filterSubagentResult, resolveSubagentConfigs, sanitizeForwardedSubagentUpdateData, summarizeEvent };
536
825
  //# sourceMappingURL=SubagentExecutor.mjs.map