illuma-agents 1.0.37 → 1.0.39

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 (139) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +112 -14
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/common/enum.cjs +5 -1
  4. package/dist/cjs/common/enum.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +148 -8
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/graphs/MultiAgentGraph.cjs +277 -11
  8. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  9. package/dist/cjs/llm/bedrock/index.cjs +128 -61
  10. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  11. package/dist/cjs/main.cjs +22 -7
  12. package/dist/cjs/main.cjs.map +1 -1
  13. package/dist/cjs/messages/cache.cjs +140 -46
  14. package/dist/cjs/messages/cache.cjs.map +1 -1
  15. package/dist/cjs/messages/core.cjs +1 -1
  16. package/dist/cjs/messages/core.cjs.map +1 -1
  17. package/dist/cjs/messages/tools.cjs +2 -2
  18. package/dist/cjs/messages/tools.cjs.map +1 -1
  19. package/dist/cjs/schemas/validate.cjs +173 -0
  20. package/dist/cjs/schemas/validate.cjs.map +1 -0
  21. package/dist/cjs/stream.cjs +4 -2
  22. package/dist/cjs/stream.cjs.map +1 -1
  23. package/dist/cjs/tools/BrowserTools.cjs.map +1 -1
  24. package/dist/cjs/tools/CodeExecutor.cjs +22 -21
  25. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  26. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +14 -11
  27. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  28. package/dist/cjs/tools/ToolNode.cjs +101 -2
  29. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  30. package/dist/cjs/tools/ToolSearch.cjs +862 -0
  31. package/dist/cjs/tools/ToolSearch.cjs.map +1 -0
  32. package/dist/esm/agents/AgentContext.mjs +112 -14
  33. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  34. package/dist/esm/common/enum.mjs +5 -1
  35. package/dist/esm/common/enum.mjs.map +1 -1
  36. package/dist/esm/graphs/Graph.mjs +149 -9
  37. package/dist/esm/graphs/Graph.mjs.map +1 -1
  38. package/dist/esm/graphs/MultiAgentGraph.mjs +278 -12
  39. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  40. package/dist/esm/llm/bedrock/index.mjs +127 -60
  41. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  42. package/dist/esm/main.mjs +2 -1
  43. package/dist/esm/main.mjs.map +1 -1
  44. package/dist/esm/messages/cache.mjs +140 -46
  45. package/dist/esm/messages/cache.mjs.map +1 -1
  46. package/dist/esm/messages/core.mjs +1 -1
  47. package/dist/esm/messages/core.mjs.map +1 -1
  48. package/dist/esm/messages/tools.mjs +2 -2
  49. package/dist/esm/messages/tools.mjs.map +1 -1
  50. package/dist/esm/schemas/validate.mjs +167 -0
  51. package/dist/esm/schemas/validate.mjs.map +1 -0
  52. package/dist/esm/stream.mjs +4 -2
  53. package/dist/esm/stream.mjs.map +1 -1
  54. package/dist/esm/tools/BrowserTools.mjs.map +1 -1
  55. package/dist/esm/tools/CodeExecutor.mjs +22 -21
  56. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  57. package/dist/esm/tools/ProgrammaticToolCalling.mjs +14 -11
  58. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  59. package/dist/esm/tools/ToolNode.mjs +102 -3
  60. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  61. package/dist/esm/tools/ToolSearch.mjs +827 -0
  62. package/dist/esm/tools/ToolSearch.mjs.map +1 -0
  63. package/dist/types/agents/AgentContext.d.ts +51 -1
  64. package/dist/types/common/enum.d.ts +6 -2
  65. package/dist/types/graphs/Graph.d.ts +12 -0
  66. package/dist/types/graphs/MultiAgentGraph.d.ts +16 -0
  67. package/dist/types/index.d.ts +2 -1
  68. package/dist/types/llm/bedrock/index.d.ts +89 -11
  69. package/dist/types/llm/bedrock/types.d.ts +27 -0
  70. package/dist/types/llm/bedrock/utils/index.d.ts +5 -0
  71. package/dist/types/llm/bedrock/utils/message_inputs.d.ts +31 -0
  72. package/dist/types/llm/bedrock/utils/message_outputs.d.ts +33 -0
  73. package/dist/types/messages/cache.d.ts +4 -1
  74. package/dist/types/schemas/index.d.ts +1 -0
  75. package/dist/types/schemas/validate.d.ts +36 -0
  76. package/dist/types/tools/CodeExecutor.d.ts +0 -3
  77. package/dist/types/tools/ProgrammaticToolCalling.d.ts +0 -3
  78. package/dist/types/tools/ToolNode.d.ts +3 -1
  79. package/dist/types/tools/ToolSearch.d.ts +148 -0
  80. package/dist/types/types/graph.d.ts +71 -0
  81. package/dist/types/types/llm.d.ts +3 -1
  82. package/dist/types/types/tools.d.ts +42 -2
  83. package/package.json +13 -6
  84. package/src/agents/AgentContext.test.ts +312 -0
  85. package/src/agents/AgentContext.ts +144 -16
  86. package/src/common/enum.ts +5 -1
  87. package/src/graphs/Graph.ts +214 -13
  88. package/src/graphs/MultiAgentGraph.ts +350 -13
  89. package/src/index.ts +4 -1
  90. package/src/llm/bedrock/index.ts +221 -99
  91. package/src/llm/bedrock/llm.spec.ts +616 -0
  92. package/src/llm/bedrock/types.ts +51 -0
  93. package/src/llm/bedrock/utils/index.ts +18 -0
  94. package/src/llm/bedrock/utils/message_inputs.ts +563 -0
  95. package/src/llm/bedrock/utils/message_outputs.ts +310 -0
  96. package/src/messages/__tests__/tools.test.ts +21 -21
  97. package/src/messages/cache.test.ts +304 -0
  98. package/src/messages/cache.ts +183 -53
  99. package/src/messages/core.ts +1 -1
  100. package/src/messages/tools.ts +2 -2
  101. package/src/schemas/index.ts +2 -0
  102. package/src/schemas/validate.test.ts +358 -0
  103. package/src/schemas/validate.ts +238 -0
  104. package/src/scripts/caching.ts +27 -19
  105. package/src/scripts/code_exec_files.ts +58 -15
  106. package/src/scripts/code_exec_multi_session.ts +241 -0
  107. package/src/scripts/code_exec_session.ts +282 -0
  108. package/src/scripts/multi-agent-conditional.ts +1 -0
  109. package/src/scripts/multi-agent-supervisor.ts +1 -0
  110. package/src/scripts/programmatic_exec_agent.ts +4 -4
  111. package/src/scripts/test-handoff-preamble.ts +277 -0
  112. package/src/scripts/test-parallel-handoffs.ts +291 -0
  113. package/src/scripts/test-tools-before-handoff.ts +8 -4
  114. package/src/scripts/test_code_api.ts +361 -0
  115. package/src/scripts/thinking-bedrock.ts +159 -0
  116. package/src/scripts/thinking.ts +39 -18
  117. package/src/scripts/{tool_search_regex.ts → tool_search.ts} +5 -5
  118. package/src/scripts/tools.ts +7 -3
  119. package/src/specs/cache.simple.test.ts +396 -0
  120. package/src/stream.ts +4 -2
  121. package/src/tools/BrowserTools.ts +39 -17
  122. package/src/tools/CodeExecutor.ts +26 -23
  123. package/src/tools/ProgrammaticToolCalling.ts +18 -14
  124. package/src/tools/ToolNode.ts +114 -1
  125. package/src/tools/ToolSearch.ts +1041 -0
  126. package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +0 -2
  127. package/src/tools/__tests__/{ToolSearchRegex.integration.test.ts → ToolSearch.integration.test.ts} +6 -6
  128. package/src/tools/__tests__/ToolSearch.test.ts +1003 -0
  129. package/src/types/graph.test.ts +183 -0
  130. package/src/types/graph.ts +73 -0
  131. package/src/types/llm.ts +3 -1
  132. package/src/types/tools.ts +51 -2
  133. package/dist/cjs/tools/ToolSearchRegex.cjs +0 -455
  134. package/dist/cjs/tools/ToolSearchRegex.cjs.map +0 -1
  135. package/dist/esm/tools/ToolSearchRegex.mjs +0 -448
  136. package/dist/esm/tools/ToolSearchRegex.mjs.map +0 -1
  137. package/dist/types/tools/ToolSearchRegex.d.ts +0 -80
  138. package/src/tools/ToolSearchRegex.ts +0 -535
  139. package/src/tools/__tests__/ToolSearchRegex.test.ts +0 -232
@@ -2,6 +2,7 @@ import { z } from 'zod';
2
2
  import { tool } from '@langchain/core/tools';
3
3
  import { PromptTemplate } from '@langchain/core/prompts';
4
4
  import {
5
+ AIMessage,
5
6
  ToolMessage,
6
7
  HumanMessage,
7
8
  getBufferString,
@@ -15,12 +16,15 @@ import {
15
16
  getCurrentTaskInput,
16
17
  messagesStateReducer,
17
18
  } from '@langchain/langgraph';
19
+ import type { BaseMessage, AIMessageChunk } from '@langchain/core/messages';
18
20
  import type { ToolRunnableConfig } from '@langchain/core/tools';
19
- import type { BaseMessage } from '@langchain/core/messages';
20
21
  import type * as t from '@/types';
21
22
  import { StandardGraph } from './Graph';
22
23
  import { Constants } from '@/common';
23
24
 
25
+ /** Pattern to extract instructions from transfer ToolMessage content */
26
+ const HANDOFF_INSTRUCTIONS_PATTERN = /(?:Instructions?|Context):\s*(.+)/is;
27
+
24
28
  /**
25
29
  * MultiAgentGraph extends StandardGraph to support dynamic multi-agent workflows
26
30
  * with handoffs, fan-in/fan-out, and other composable patterns.
@@ -245,8 +249,11 @@ export class MultiAgentGraph extends StandardGraph {
245
249
 
246
250
  // Create handoff tools for this agent's outgoing edges
247
251
  const handoffTools: t.GenericTool[] = [];
252
+ const sourceAgentName = agentContext.name ?? agentId;
248
253
  for (const edge of edges) {
249
- handoffTools.push(...this.createHandoffToolsForEdge(edge));
254
+ handoffTools.push(
255
+ ...this.createHandoffToolsForEdge(edge, agentId, sourceAgentName)
256
+ );
250
257
  }
251
258
 
252
259
  // Add handoff tools to the agent's existing tools
@@ -259,8 +266,15 @@ export class MultiAgentGraph extends StandardGraph {
259
266
 
260
267
  /**
261
268
  * Create handoff tools for an edge (handles multiple destinations)
269
+ * @param edge - The graph edge defining the handoff
270
+ * @param sourceAgentId - The ID of the agent that will perform the handoff
271
+ * @param sourceAgentName - The human-readable name of the source agent
262
272
  */
263
- private createHandoffToolsForEdge(edge: t.GraphEdge): t.GenericTool[] {
273
+ private createHandoffToolsForEdge(
274
+ edge: t.GraphEdge,
275
+ sourceAgentId: string,
276
+ sourceAgentName: string
277
+ ): t.GenericTool[] {
264
278
  const tools: t.GenericTool[] = [];
265
279
  const destinations = Array.isArray(edge.to) ? edge.to : [edge.to];
266
280
 
@@ -312,6 +326,12 @@ export class MultiAgentGraph extends StandardGraph {
312
326
  content,
313
327
  name: toolName,
314
328
  tool_call_id: toolCallId,
329
+ additional_kwargs: {
330
+ /** Store destination for programmatic access in handoff detection */
331
+ handoff_destination: destination,
332
+ /** Store source agent name for receiving agent to know who handed off */
333
+ handoff_source_name: sourceAgentName,
334
+ },
315
335
  });
316
336
 
317
337
  return new Command({
@@ -369,13 +389,81 @@ export class MultiAgentGraph extends StandardGraph {
369
389
  content,
370
390
  name: toolName,
371
391
  tool_call_id: toolCallId,
392
+ additional_kwargs: {
393
+ /** Store source agent name for receiving agent to know who handed off */
394
+ handoff_source_name: sourceAgentName,
395
+ },
372
396
  });
373
397
 
374
398
  const state = getCurrentTaskInput() as t.BaseGraphState;
375
399
 
400
+ /**
401
+ * For parallel handoff support:
402
+ * Build messages that include ONLY this tool call's context.
403
+ * This prevents errors when LLM calls multiple transfers simultaneously -
404
+ * each destination gets a valid AIMessage with matching tool_call and tool_result.
405
+ *
406
+ * Strategy:
407
+ * 1. Find the AIMessage containing this tool call
408
+ * 2. Create a filtered AIMessage with ONLY this tool_call
409
+ * 3. Include all messages before the AIMessage plus the filtered pair
410
+ */
411
+ const messages = state.messages;
412
+ let filteredMessages = messages;
413
+ let aiMessageIndex = -1;
414
+
415
+ /** Find the AIMessage containing this tool call */
416
+ for (let i = messages.length - 1; i >= 0; i--) {
417
+ const msg = messages[i];
418
+ if (msg.getType() === 'ai') {
419
+ const aiMsg = msg as AIMessage;
420
+ const hasThisCall = aiMsg.tool_calls?.some(
421
+ (tc) => tc.id === toolCallId
422
+ );
423
+ if (hasThisCall === true) {
424
+ aiMessageIndex = i;
425
+ break;
426
+ }
427
+ }
428
+ }
429
+
430
+ if (aiMessageIndex >= 0) {
431
+ const originalAiMsg = messages[aiMessageIndex] as AIMessage;
432
+ const thisToolCall = originalAiMsg.tool_calls?.find(
433
+ (tc) => tc.id === toolCallId
434
+ );
435
+
436
+ if (
437
+ thisToolCall != null &&
438
+ (originalAiMsg.tool_calls?.length ?? 0) > 1
439
+ ) {
440
+ /**
441
+ * Multiple tool calls - create filtered AIMessage with ONLY this call.
442
+ * This ensures valid message structure for parallel handoffs.
443
+ */
444
+ const filteredAiMsg = new AIMessage({
445
+ content: originalAiMsg.content,
446
+ tool_calls: [thisToolCall],
447
+ id: originalAiMsg.id,
448
+ });
449
+
450
+ filteredMessages = [
451
+ ...messages.slice(0, aiMessageIndex),
452
+ filteredAiMsg,
453
+ toolMessage,
454
+ ];
455
+ } else {
456
+ /** Single tool call - use messages as-is */
457
+ filteredMessages = messages.concat(toolMessage);
458
+ }
459
+ } else {
460
+ /** Fallback - append tool message */
461
+ filteredMessages = messages.concat(toolMessage);
462
+ }
463
+
376
464
  return new Command({
377
465
  goto: destination,
378
- update: { messages: state.messages.concat(toolMessage) },
466
+ update: { messages: filteredMessages },
379
467
  graph: Command.PARENT,
380
468
  });
381
469
  },
@@ -407,6 +495,179 @@ export class MultiAgentGraph extends StandardGraph {
407
495
  return this.createAgentNode(agentId);
408
496
  }
409
497
 
498
+ /**
499
+ * Detects if the current agent is receiving a handoff and processes the messages accordingly.
500
+ * Returns filtered messages with the transfer tool call/message removed, plus any instructions,
501
+ * source agent, and parallel sibling information extracted from the transfer.
502
+ *
503
+ * Supports both single handoffs (last message is the transfer) and parallel handoffs
504
+ * (multiple transfer ToolMessages, need to find the one targeting this agent).
505
+ *
506
+ * @param messages - Current state messages
507
+ * @param agentId - The agent ID to check for handoff reception
508
+ * @returns Object with filtered messages, extracted instructions, source agent, and parallel siblings
509
+ */
510
+ private processHandoffReception(
511
+ messages: BaseMessage[],
512
+ agentId: string
513
+ ): {
514
+ filteredMessages: BaseMessage[];
515
+ instructions: string | null;
516
+ sourceAgentName: string | null;
517
+ parallelSiblings: string[];
518
+ } | null {
519
+ if (messages.length === 0) return null;
520
+
521
+ /**
522
+ * Search for a transfer ToolMessage targeting this agent.
523
+ * For parallel handoffs, multiple transfer messages may exist - find ours.
524
+ * Search backwards from the end to find the most recent transfer to this agent.
525
+ */
526
+ let toolMessage: ToolMessage | null = null;
527
+ let toolMessageIndex = -1;
528
+
529
+ for (let i = messages.length - 1; i >= 0; i--) {
530
+ const msg = messages[i];
531
+ if (msg.getType() !== 'tool') continue;
532
+
533
+ const candidateMsg = msg as ToolMessage;
534
+ const toolName = candidateMsg.name;
535
+
536
+ if (typeof toolName !== 'string') continue;
537
+
538
+ /** Check for standard transfer pattern */
539
+ const isTransferMessage = toolName.startsWith(Constants.LC_TRANSFER_TO_);
540
+ const isConditionalTransfer = toolName === 'conditional_transfer';
541
+
542
+ if (!isTransferMessage && !isConditionalTransfer) continue;
543
+
544
+ /** Extract destination from tool name or additional_kwargs */
545
+ let destinationAgent: string | null = null;
546
+
547
+ if (isTransferMessage) {
548
+ destinationAgent = toolName.replace(Constants.LC_TRANSFER_TO_, '');
549
+ } else if (isConditionalTransfer) {
550
+ const handoffDest = candidateMsg.additional_kwargs.handoff_destination;
551
+ destinationAgent = typeof handoffDest === 'string' ? handoffDest : null;
552
+ }
553
+
554
+ /** Check if this transfer targets our agent */
555
+ if (destinationAgent === agentId) {
556
+ toolMessage = candidateMsg;
557
+ toolMessageIndex = i;
558
+ break;
559
+ }
560
+ }
561
+
562
+ /** No transfer targeting this agent found */
563
+ if (toolMessage === null || toolMessageIndex < 0) return null;
564
+
565
+ /** Extract instructions from the ToolMessage content */
566
+ const contentStr =
567
+ typeof toolMessage.content === 'string'
568
+ ? toolMessage.content
569
+ : JSON.stringify(toolMessage.content);
570
+
571
+ const instructionsMatch = contentStr.match(HANDOFF_INSTRUCTIONS_PATTERN);
572
+ const instructions = instructionsMatch?.[1]?.trim() ?? null;
573
+
574
+ /** Extract source agent name from additional_kwargs */
575
+ const handoffSourceName = toolMessage.additional_kwargs.handoff_source_name;
576
+ const sourceAgentName =
577
+ typeof handoffSourceName === 'string' ? handoffSourceName : null;
578
+
579
+ /** Extract parallel siblings (set by ToolNode for parallel handoffs) */
580
+ const rawSiblings = toolMessage.additional_kwargs.handoff_parallel_siblings;
581
+ const siblingIds: string[] = Array.isArray(rawSiblings)
582
+ ? rawSiblings.filter((s): s is string => typeof s === 'string')
583
+ : [];
584
+ /** Convert IDs to display names */
585
+ const parallelSiblings = siblingIds.map((id) => {
586
+ const ctx = this.agentContexts.get(id);
587
+ return ctx?.name ?? id;
588
+ });
589
+
590
+ /** Get the tool_call_id to find and filter the AI message's tool call */
591
+ const toolCallId = toolMessage.tool_call_id;
592
+
593
+ /**
594
+ * Collect all transfer tool_call_ids to filter out.
595
+ * For parallel handoffs, we filter ALL transfer messages (not just ours)
596
+ * to give the receiving agent a clean context without handoff noise.
597
+ */
598
+ const transferToolCallIds = new Set<string>([toolCallId]);
599
+ for (const msg of messages) {
600
+ if (msg.getType() !== 'tool') continue;
601
+ const tm = msg as ToolMessage;
602
+ const tName = tm.name;
603
+ if (typeof tName !== 'string') continue;
604
+ if (
605
+ tName.startsWith(Constants.LC_TRANSFER_TO_) ||
606
+ tName === 'conditional_transfer'
607
+ ) {
608
+ transferToolCallIds.add(tm.tool_call_id);
609
+ }
610
+ }
611
+
612
+ /** Filter out all transfer messages */
613
+ const filteredMessages: BaseMessage[] = [];
614
+
615
+ for (let i = 0; i < messages.length; i++) {
616
+ const msg = messages[i];
617
+ const msgType = msg.getType();
618
+
619
+ /** Skip transfer ToolMessages */
620
+ if (msgType === 'tool') {
621
+ const tm = msg as ToolMessage;
622
+ if (transferToolCallIds.has(tm.tool_call_id)) {
623
+ continue;
624
+ }
625
+ }
626
+
627
+ if (msgType === 'ai') {
628
+ /** Check if this AI message contains any transfer tool calls */
629
+ const aiMsg = msg as AIMessage | AIMessageChunk;
630
+ const toolCalls = aiMsg.tool_calls;
631
+
632
+ if (toolCalls && toolCalls.length > 0) {
633
+ /** Filter out all transfer tool calls */
634
+ const remainingToolCalls = toolCalls.filter(
635
+ (tc) => tc.id == null || !transferToolCallIds.has(tc.id)
636
+ );
637
+
638
+ const hasTransferCalls = remainingToolCalls.length < toolCalls.length;
639
+
640
+ if (hasTransferCalls) {
641
+ if (
642
+ remainingToolCalls.length > 0 ||
643
+ (typeof aiMsg.content === 'string' && aiMsg.content.trim())
644
+ ) {
645
+ /** Keep the message but without transfer tool calls */
646
+ const filteredAiMsg = new AIMessage({
647
+ content: aiMsg.content,
648
+ tool_calls: remainingToolCalls,
649
+ id: aiMsg.id,
650
+ });
651
+ filteredMessages.push(filteredAiMsg);
652
+ }
653
+ /** If no remaining content or tool calls, skip this message entirely */
654
+ continue;
655
+ }
656
+ }
657
+ }
658
+
659
+ /** Keep all other messages */
660
+ filteredMessages.push(msg);
661
+ }
662
+
663
+ return {
664
+ filteredMessages,
665
+ instructions,
666
+ sourceAgentName,
667
+ parallelSiblings,
668
+ };
669
+ }
670
+
410
671
  /**
411
672
  * Create the multi-agent workflow with dynamic handoffs
412
673
  */
@@ -474,26 +735,102 @@ export class MultiAgentGraph extends StandardGraph {
474
735
  /** Agent subgraph (includes agent + tools) */
475
736
  const agentSubgraph = this.createAgentSubgraph(agentId);
476
737
 
477
- /** Wrapper function that handles agentMessages channel and conditional routing */
738
+ /** Wrapper function that handles agentMessages channel, handoff reception, and conditional routing */
478
739
  const agentWrapper = async (
479
740
  state: t.MultiAgentGraphState
480
741
  ): Promise<t.MultiAgentGraphState | Command> => {
481
742
  let result: t.MultiAgentGraphState;
482
743
 
483
- if (state.agentMessages != null && state.agentMessages.length > 0) {
744
+ /**
745
+ * Check if this agent is receiving a handoff.
746
+ * If so, filter out the transfer messages and inject instructions as preamble.
747
+ * This prevents the receiving agent from seeing the transfer as "completed work"
748
+ * and prematurely producing an end token.
749
+ */
750
+ const handoffContext = this.processHandoffReception(
751
+ state.messages,
752
+ agentId
753
+ );
754
+
755
+ if (handoffContext !== null) {
756
+ const {
757
+ filteredMessages,
758
+ instructions,
759
+ sourceAgentName,
760
+ parallelSiblings,
761
+ } = handoffContext;
762
+
763
+ /**
764
+ * Set handoff context on the receiving agent.
765
+ * Uses pre-computed graph position for depth and parallel info.
766
+ */
767
+ const agentContext = this.agentContexts.get(agentId);
768
+ if (
769
+ agentContext &&
770
+ sourceAgentName != null &&
771
+ sourceAgentName !== ''
772
+ ) {
773
+ agentContext.setHandoffContext(sourceAgentName, parallelSiblings);
774
+ }
775
+
776
+ /** Build messages for the receiving agent */
777
+ let messagesForAgent = filteredMessages;
778
+
779
+ /** If there are instructions, inject them as a HumanMessage to ground the agent */
780
+ const hasInstructions = instructions !== null && instructions !== '';
781
+ if (hasInstructions) {
782
+ messagesForAgent = [
783
+ ...filteredMessages,
784
+ new HumanMessage(instructions),
785
+ ];
786
+ }
787
+
788
+ /** Update token map if we have a token counter */
789
+ if (agentContext?.tokenCounter && hasInstructions) {
790
+ const freshTokenMap: Record<string, number> = {};
791
+ for (
792
+ let i = 0;
793
+ i < Math.min(filteredMessages.length, this.startIndex);
794
+ i++
795
+ ) {
796
+ const tokenCount = agentContext.indexTokenCountMap[i];
797
+ if (tokenCount !== undefined) {
798
+ freshTokenMap[i] = tokenCount;
799
+ }
800
+ }
801
+ /** Add tokens for the instructions message */
802
+ const instructionsMsg = new HumanMessage(instructions);
803
+ freshTokenMap[messagesForAgent.length - 1] =
804
+ agentContext.tokenCounter(instructionsMsg);
805
+ agentContext.updateTokenMapWithInstructions(freshTokenMap);
806
+ }
807
+
808
+ const transformedState: t.MultiAgentGraphState = {
809
+ ...state,
810
+ messages: messagesForAgent,
811
+ };
812
+ result = await agentSubgraph.invoke(transformedState);
813
+ result = {
814
+ ...result,
815
+ agentMessages: [],
816
+ };
817
+ } else if (
818
+ state.agentMessages != null &&
819
+ state.agentMessages.length > 0
820
+ ) {
484
821
  /**
485
822
  * When using agentMessages (excludeResults=true), we need to update
486
823
  * the token map to account for the new prompt message
487
824
  */
488
825
  const agentContext = this.agentContexts.get(agentId);
489
826
  if (agentContext && agentContext.tokenCounter) {
490
- // The agentMessages contains:
491
- // 1. Filtered messages (0 to startIndex) - already have token counts
492
- // 2. New prompt message - needs token counting
493
-
827
+ /** The agentMessages contains:
828
+ * 1. Filtered messages (0 to startIndex) - already have token counts
829
+ * 2. New prompt message - needs token counting
830
+ */
494
831
  const freshTokenMap: Record<string, number> = {};
495
832
 
496
- // Copy existing token counts for filtered messages (0 to startIndex)
833
+ /** Copy existing token counts for filtered messages (0 to startIndex) */
497
834
  for (let i = 0; i < this.startIndex; i++) {
498
835
  const tokenCount = agentContext.indexTokenCountMap[i];
499
836
  if (tokenCount !== undefined) {
@@ -501,7 +838,7 @@ export class MultiAgentGraph extends StandardGraph {
501
838
  }
502
839
  }
503
840
 
504
- // Calculate tokens only for the new prompt message (last message)
841
+ /** Calculate tokens only for the new prompt message (last message) */
505
842
  const promptMessageIndex = state.agentMessages.length - 1;
506
843
  if (promptMessageIndex >= this.startIndex) {
507
844
  const promptMessage = state.agentMessages[promptMessageIndex];
@@ -509,7 +846,7 @@ export class MultiAgentGraph extends StandardGraph {
509
846
  agentContext.tokenCounter(promptMessage);
510
847
  }
511
848
 
512
- // Update the agent's token map with instructions added
849
+ /** Update the agent's token map with instructions added */
513
850
  agentContext.updateTokenMapWithInstructions(freshTokenMap);
514
851
  }
515
852
 
package/src/index.ts CHANGED
@@ -13,10 +13,13 @@ export * from './tools/Calculator';
13
13
  export * from './tools/CodeExecutor';
14
14
  export * from './tools/BrowserTools';
15
15
  export * from './tools/ProgrammaticToolCalling';
16
- export * from './tools/ToolSearchRegex';
16
+ export * from './tools/ToolSearch';
17
17
  export * from './tools/handlers';
18
18
  export * from './tools/search';
19
19
 
20
+ /* Schemas */
21
+ export * from './schemas';
22
+
20
23
  /* Misc. */
21
24
  export * from './common';
22
25
  export * from './utils';