@illuma-ai/agents 1.1.25 → 1.3.0

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 (272) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +20 -3
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/common/spawnPath.cjs +104 -0
  4. package/dist/cjs/common/spawnPath.cjs.map +1 -0
  5. package/dist/cjs/graphs/Graph.cjs +87 -31
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/graphs/HandoffRegistry.cjs +143 -0
  8. package/dist/cjs/graphs/HandoffRegistry.cjs.map +1 -0
  9. package/dist/cjs/graphs/MultiAgentGraph.cjs +587 -184
  10. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  11. package/dist/cjs/graphs/phases/flushLoop.cjs +214 -0
  12. package/dist/cjs/graphs/phases/flushLoop.cjs.map +1 -0
  13. package/dist/cjs/graphs/phases/memoryFlushPhase.cjs +102 -0
  14. package/dist/cjs/graphs/phases/memoryFlushPhase.cjs.map +1 -0
  15. package/dist/cjs/llm/bedrock/index.cjs +4 -3
  16. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  17. package/dist/cjs/main.cjs +115 -0
  18. package/dist/cjs/main.cjs.map +1 -1
  19. package/dist/cjs/memory/citations.cjs +69 -0
  20. package/dist/cjs/memory/citations.cjs.map +1 -0
  21. package/dist/cjs/memory/compositeBackend.cjs +60 -0
  22. package/dist/cjs/memory/compositeBackend.cjs.map +1 -0
  23. package/dist/cjs/memory/constants.cjs +232 -0
  24. package/dist/cjs/memory/constants.cjs.map +1 -0
  25. package/dist/cjs/memory/embeddings.cjs +151 -0
  26. package/dist/cjs/memory/embeddings.cjs.map +1 -0
  27. package/dist/cjs/memory/factory.cjs +95 -0
  28. package/dist/cjs/memory/factory.cjs.map +1 -0
  29. package/dist/cjs/memory/migrate.cjs +81 -0
  30. package/dist/cjs/memory/migrate.cjs.map +1 -0
  31. package/dist/cjs/memory/mmr.cjs +138 -0
  32. package/dist/cjs/memory/mmr.cjs.map +1 -0
  33. package/dist/cjs/memory/paths.cjs +217 -0
  34. package/dist/cjs/memory/paths.cjs.map +1 -0
  35. package/dist/cjs/memory/pgvectorStore.cjs +225 -0
  36. package/dist/cjs/memory/pgvectorStore.cjs.map +1 -0
  37. package/dist/cjs/memory/recallTracking.cjs +98 -0
  38. package/dist/cjs/memory/recallTracking.cjs.map +1 -0
  39. package/dist/cjs/memory/schema.sql +51 -0
  40. package/dist/cjs/memory/temporalDecay.cjs +118 -0
  41. package/dist/cjs/memory/temporalDecay.cjs.map +1 -0
  42. package/dist/cjs/nodes/ApprovalGateNode.cjs +1 -1
  43. package/dist/cjs/nodes/ApprovalGateNode.cjs.map +1 -1
  44. package/dist/cjs/prompts/memoryFlushPrompt.cjs +49 -0
  45. package/dist/cjs/prompts/memoryFlushPrompt.cjs.map +1 -0
  46. package/dist/cjs/run.cjs +16 -3
  47. package/dist/cjs/run.cjs.map +1 -1
  48. package/dist/cjs/stream.cjs +4 -4
  49. package/dist/cjs/stream.cjs.map +1 -1
  50. package/dist/cjs/tools/AskUser.cjs +6 -1
  51. package/dist/cjs/tools/AskUser.cjs.map +1 -1
  52. package/dist/cjs/tools/BrowserTools.cjs +1 -1
  53. package/dist/cjs/tools/BrowserTools.cjs.map +1 -1
  54. package/dist/cjs/tools/ToolNode.cjs +127 -10
  55. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  56. package/dist/cjs/tools/approval/constants.cjs +2 -2
  57. package/dist/cjs/tools/approval/constants.cjs.map +1 -1
  58. package/dist/cjs/tools/memory/index.cjs +58 -0
  59. package/dist/cjs/tools/memory/index.cjs.map +1 -0
  60. package/dist/cjs/tools/memory/memoryAppendTool.cjs +69 -0
  61. package/dist/cjs/tools/memory/memoryAppendTool.cjs.map +1 -0
  62. package/dist/cjs/tools/memory/memoryGetTool.cjs +49 -0
  63. package/dist/cjs/tools/memory/memoryGetTool.cjs.map +1 -0
  64. package/dist/cjs/tools/memory/memorySearchTool.cjs +65 -0
  65. package/dist/cjs/tools/memory/memorySearchTool.cjs.map +1 -0
  66. package/dist/cjs/tools/memory/shared.cjs +106 -0
  67. package/dist/cjs/tools/memory/shared.cjs.map +1 -0
  68. package/dist/cjs/types/graph.cjs.map +1 -1
  69. package/dist/cjs/utils/childAgentContext.cjs +242 -0
  70. package/dist/cjs/utils/childAgentContext.cjs.map +1 -0
  71. package/dist/cjs/utils/events.cjs +36 -4
  72. package/dist/cjs/utils/events.cjs.map +1 -1
  73. package/dist/cjs/utils/finishReasons.cjs +44 -0
  74. package/dist/cjs/utils/finishReasons.cjs.map +1 -0
  75. package/dist/cjs/utils/llm.cjs.map +1 -1
  76. package/dist/cjs/utils/logging.cjs +34 -0
  77. package/dist/cjs/utils/logging.cjs.map +1 -0
  78. package/dist/cjs/utils/toolCallNormalization.cjs +250 -0
  79. package/dist/cjs/utils/toolCallNormalization.cjs.map +1 -0
  80. package/dist/esm/agents/AgentContext.mjs +20 -3
  81. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  82. package/dist/esm/common/spawnPath.mjs +95 -0
  83. package/dist/esm/common/spawnPath.mjs.map +1 -0
  84. package/dist/esm/graphs/Graph.mjs +87 -31
  85. package/dist/esm/graphs/Graph.mjs.map +1 -1
  86. package/dist/esm/graphs/HandoffRegistry.mjs +141 -0
  87. package/dist/esm/graphs/HandoffRegistry.mjs.map +1 -0
  88. package/dist/esm/graphs/MultiAgentGraph.mjs +587 -184
  89. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  90. package/dist/esm/graphs/phases/flushLoop.mjs +209 -0
  91. package/dist/esm/graphs/phases/flushLoop.mjs.map +1 -0
  92. package/dist/esm/graphs/phases/memoryFlushPhase.mjs +99 -0
  93. package/dist/esm/graphs/phases/memoryFlushPhase.mjs.map +1 -0
  94. package/dist/esm/llm/bedrock/index.mjs +4 -3
  95. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  96. package/dist/esm/main.mjs +21 -0
  97. package/dist/esm/main.mjs.map +1 -1
  98. package/dist/esm/memory/citations.mjs +64 -0
  99. package/dist/esm/memory/citations.mjs.map +1 -0
  100. package/dist/esm/memory/compositeBackend.mjs +58 -0
  101. package/dist/esm/memory/compositeBackend.mjs.map +1 -0
  102. package/dist/esm/memory/constants.mjs +198 -0
  103. package/dist/esm/memory/constants.mjs.map +1 -0
  104. package/dist/esm/memory/embeddings.mjs +148 -0
  105. package/dist/esm/memory/embeddings.mjs.map +1 -0
  106. package/dist/esm/memory/factory.mjs +93 -0
  107. package/dist/esm/memory/factory.mjs.map +1 -0
  108. package/dist/esm/memory/migrate.mjs +78 -0
  109. package/dist/esm/memory/migrate.mjs.map +1 -0
  110. package/dist/esm/memory/mmr.mjs +130 -0
  111. package/dist/esm/memory/mmr.mjs.map +1 -0
  112. package/dist/esm/memory/paths.mjs +207 -0
  113. package/dist/esm/memory/paths.mjs.map +1 -0
  114. package/dist/esm/memory/pgvectorStore.mjs +223 -0
  115. package/dist/esm/memory/pgvectorStore.mjs.map +1 -0
  116. package/dist/esm/memory/recallTracking.mjs +94 -0
  117. package/dist/esm/memory/recallTracking.mjs.map +1 -0
  118. package/dist/esm/memory/schema.sql +51 -0
  119. package/dist/esm/memory/temporalDecay.mjs +110 -0
  120. package/dist/esm/memory/temporalDecay.mjs.map +1 -0
  121. package/dist/esm/nodes/ApprovalGateNode.mjs +1 -1
  122. package/dist/esm/nodes/ApprovalGateNode.mjs.map +1 -1
  123. package/dist/esm/prompts/memoryFlushPrompt.mjs +44 -0
  124. package/dist/esm/prompts/memoryFlushPrompt.mjs.map +1 -0
  125. package/dist/esm/run.mjs +16 -3
  126. package/dist/esm/run.mjs.map +1 -1
  127. package/dist/esm/stream.mjs +4 -4
  128. package/dist/esm/stream.mjs.map +1 -1
  129. package/dist/esm/tools/AskUser.mjs +6 -1
  130. package/dist/esm/tools/AskUser.mjs.map +1 -1
  131. package/dist/esm/tools/BrowserTools.mjs +1 -1
  132. package/dist/esm/tools/BrowserTools.mjs.map +1 -1
  133. package/dist/esm/tools/ToolNode.mjs +128 -11
  134. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  135. package/dist/esm/tools/approval/constants.mjs +2 -2
  136. package/dist/esm/tools/approval/constants.mjs.map +1 -1
  137. package/dist/esm/tools/memory/index.mjs +46 -0
  138. package/dist/esm/tools/memory/index.mjs.map +1 -0
  139. package/dist/esm/tools/memory/memoryAppendTool.mjs +67 -0
  140. package/dist/esm/tools/memory/memoryAppendTool.mjs.map +1 -0
  141. package/dist/esm/tools/memory/memoryGetTool.mjs +47 -0
  142. package/dist/esm/tools/memory/memoryGetTool.mjs.map +1 -0
  143. package/dist/esm/tools/memory/memorySearchTool.mjs +63 -0
  144. package/dist/esm/tools/memory/memorySearchTool.mjs.map +1 -0
  145. package/dist/esm/tools/memory/shared.mjs +98 -0
  146. package/dist/esm/tools/memory/shared.mjs.map +1 -0
  147. package/dist/esm/types/graph.mjs.map +1 -1
  148. package/dist/esm/utils/childAgentContext.mjs +237 -0
  149. package/dist/esm/utils/childAgentContext.mjs.map +1 -0
  150. package/dist/esm/utils/events.mjs +36 -5
  151. package/dist/esm/utils/events.mjs.map +1 -1
  152. package/dist/esm/utils/finishReasons.mjs +41 -0
  153. package/dist/esm/utils/finishReasons.mjs.map +1 -0
  154. package/dist/esm/utils/llm.mjs.map +1 -1
  155. package/dist/esm/utils/logging.mjs +31 -0
  156. package/dist/esm/utils/logging.mjs.map +1 -0
  157. package/dist/esm/utils/toolCallNormalization.mjs +247 -0
  158. package/dist/esm/utils/toolCallNormalization.mjs.map +1 -0
  159. package/dist/types/common/index.d.ts +1 -0
  160. package/dist/types/common/spawnPath.d.ts +59 -0
  161. package/dist/types/graphs/HandoffRegistry.d.ts +97 -0
  162. package/dist/types/graphs/MultiAgentGraph.d.ts +58 -18
  163. package/dist/types/graphs/index.d.ts +1 -0
  164. package/dist/types/graphs/phases/flushLoop.d.ts +106 -0
  165. package/dist/types/graphs/phases/memoryFlushPhase.d.ts +100 -0
  166. package/dist/types/index.d.ts +7 -0
  167. package/dist/types/memory/__tests__/mockBackend.d.ts +40 -0
  168. package/dist/types/memory/citations.d.ts +39 -0
  169. package/dist/types/memory/compositeBackend.d.ts +30 -0
  170. package/dist/types/memory/constants.d.ts +121 -0
  171. package/dist/types/memory/embeddings.d.ts +15 -0
  172. package/dist/types/memory/factory.d.ts +23 -0
  173. package/dist/types/memory/index.d.ts +21 -0
  174. package/dist/types/memory/migrate.d.ts +14 -0
  175. package/dist/types/memory/mmr.d.ts +50 -0
  176. package/dist/types/memory/paths.d.ts +107 -0
  177. package/dist/types/memory/pgvectorStore.d.ts +56 -0
  178. package/dist/types/memory/recallTracking.d.ts +30 -0
  179. package/dist/types/memory/temporalDecay.d.ts +53 -0
  180. package/dist/types/memory/types.d.ts +182 -0
  181. package/dist/types/prompts/memoryFlushPrompt.d.ts +54 -0
  182. package/dist/types/run.d.ts +1 -0
  183. package/dist/types/tools/AskUser.d.ts +1 -1
  184. package/dist/types/tools/BrowserTools.d.ts +2 -2
  185. package/dist/types/tools/approval/constants.d.ts +2 -2
  186. package/dist/types/tools/memory/index.d.ts +39 -0
  187. package/dist/types/tools/memory/memoryAppendTool.d.ts +27 -0
  188. package/dist/types/tools/memory/memoryGetTool.d.ts +22 -0
  189. package/dist/types/tools/memory/memorySearchTool.d.ts +22 -0
  190. package/dist/types/tools/memory/shared.d.ts +106 -0
  191. package/dist/types/types/graph.d.ts +16 -3
  192. package/dist/types/utils/childAgentContext.d.ts +99 -0
  193. package/dist/types/utils/events.d.ts +21 -0
  194. package/dist/types/utils/finishReasons.d.ts +32 -0
  195. package/dist/types/utils/logging.d.ts +2 -0
  196. package/dist/types/utils/toolCallNormalization.d.ts +44 -0
  197. package/package.json +6 -4
  198. package/src/agents/AgentContext.ts +26 -3
  199. package/src/common/__tests__/enum.test.ts +4 -2
  200. package/src/common/__tests__/spawnPath.test.ts +110 -0
  201. package/src/common/index.ts +1 -0
  202. package/src/common/spawnPath.ts +101 -0
  203. package/src/graphs/Graph.ts +94 -43
  204. package/src/graphs/HandoffRegistry.ts +199 -0
  205. package/src/graphs/MultiAgentGraph.ts +694 -226
  206. package/src/graphs/__tests__/HandoffRegistry.test.ts +410 -0
  207. package/src/graphs/__tests__/multi-agent-delegate.test.ts +61 -16
  208. package/src/graphs/__tests__/multi-agent-edges.test.ts +4 -2
  209. package/src/graphs/__tests__/multi-agent-nested-subgraph.test.ts +221 -0
  210. package/src/graphs/__tests__/structured-output.integration.test.ts +212 -118
  211. package/src/graphs/contextManagement.e2e.test.ts +1 -1
  212. package/src/graphs/index.ts +1 -0
  213. package/src/graphs/phases/__tests__/flushLoop.test.ts +264 -0
  214. package/src/graphs/phases/__tests__/memoryFlushPhase.test.ts +37 -0
  215. package/src/graphs/phases/__tests__/runMemoryFlush.test.ts +150 -0
  216. package/src/graphs/phases/flushLoop.ts +303 -0
  217. package/src/graphs/phases/memoryFlushPhase.ts +209 -0
  218. package/src/index.ts +30 -1
  219. package/src/llm/bedrock/index.ts +4 -5
  220. package/src/memory/__tests__/citations.test.ts +61 -0
  221. package/src/memory/__tests__/compositeBackend.test.ts +79 -0
  222. package/src/memory/__tests__/isolation.test.ts +206 -0
  223. package/src/memory/__tests__/mmr.test.ts +148 -0
  224. package/src/memory/__tests__/mockBackend.ts +161 -0
  225. package/src/memory/__tests__/paths.test.ts +168 -0
  226. package/src/memory/__tests__/recallTracking.test.ts +96 -0
  227. package/src/memory/__tests__/temporalDecay.test.ts +151 -0
  228. package/src/memory/citations.ts +80 -0
  229. package/src/memory/compositeBackend.ts +99 -0
  230. package/src/memory/constants.ts +229 -0
  231. package/src/memory/embeddings.ts +188 -0
  232. package/src/memory/factory.ts +111 -0
  233. package/src/memory/index.ts +46 -0
  234. package/src/memory/migrate.ts +116 -0
  235. package/src/memory/mmr.ts +161 -0
  236. package/src/memory/paths.ts +258 -0
  237. package/src/memory/pgvectorStore.ts +324 -0
  238. package/src/memory/recallTracking.ts +127 -0
  239. package/src/memory/schema.sql +51 -0
  240. package/src/memory/temporalDecay.ts +134 -0
  241. package/src/memory/types.ts +185 -0
  242. package/src/nodes/ApprovalGateNode.ts +4 -10
  243. package/src/nodes/__tests__/ApprovalGateNode.test.ts +11 -20
  244. package/src/prompts/memoryFlushPrompt.ts +78 -0
  245. package/src/run.ts +17 -6
  246. package/src/scripts/test-bedrock-handoff-autonomous.ts +56 -20
  247. package/src/specs/agent-handoffs-bedrock.integration.test.ts +8 -5
  248. package/src/specs/agent-handoffs.test.ts +8 -2
  249. package/src/stream.ts +4 -6
  250. package/src/tools/AskUser.ts +7 -2
  251. package/src/tools/BrowserTools.ts +3 -5
  252. package/src/tools/ToolNode.ts +150 -13
  253. package/src/tools/__tests__/ToolApproval.test.ts +22 -9
  254. package/src/tools/approval/__tests__/constants.test.ts +4 -4
  255. package/src/tools/approval/constants.ts +2 -2
  256. package/src/tools/memory/__tests__/memoryTools.test.ts +205 -0
  257. package/src/tools/memory/index.ts +96 -0
  258. package/src/tools/memory/memoryAppendTool.ts +101 -0
  259. package/src/tools/memory/memoryGetTool.ts +53 -0
  260. package/src/tools/memory/memorySearchTool.ts +80 -0
  261. package/src/tools/memory/shared.ts +169 -0
  262. package/src/tools/search/search.test.ts +6 -1
  263. package/src/types/graph.ts +16 -3
  264. package/src/utils/__tests__/childAgentContext.test.ts +217 -0
  265. package/src/utils/__tests__/finishReasons.test.ts +55 -0
  266. package/src/utils/__tests__/toolCallNormalization.test.ts +181 -0
  267. package/src/utils/childAgentContext.ts +259 -0
  268. package/src/utils/events.ts +37 -4
  269. package/src/utils/finishReasons.ts +40 -0
  270. package/src/utils/llm.ts +0 -1
  271. package/src/utils/logging.ts +45 -8
  272. package/src/utils/toolCallNormalization.ts +271 -0
@@ -31,6 +31,9 @@ import { getChatModelClass, manualToolStreamProviders } from '../llm/providers.m
31
31
  import { ToolNode, toolsCondition } from '../tools/ToolNode.mjs';
32
32
  import { ChatOpenAI, AzureChatOpenAI } from '../llm/openai/index.mjs';
33
33
  import { safeDispatchCustomEvent } from '../utils/events.mjs';
34
+ import { mwarn, mlog } from '../utils/logging.mjs';
35
+ import { normalizeMessageToolCalls } from '../utils/toolCallNormalization.mjs';
36
+ import { isTruncationReason } from '../utils/finishReasons.mjs';
34
37
  import { createSchemaOnlyTools } from '../tools/schema.mjs';
35
38
  import { prepareSchemaForProvider } from '../schemas/validate.mjs';
36
39
  import { AgentContext } from '../agents/AgentContext.mjs';
@@ -795,7 +798,7 @@ class StandardGraph extends Graph {
795
798
  const resolved = agentContext.resolveStructuredOutputMode();
796
799
  method = resolved.method;
797
800
  if (resolved.warnings.length > 0) {
798
- console.warn('[Graph] Structured output mode warnings:', resolved.warnings);
801
+ mwarn('[Graph] Structured output mode warnings:', resolved.warnings);
799
802
  }
800
803
  }
801
804
  else {
@@ -818,7 +821,7 @@ class StandardGraph extends Graph {
818
821
  const { schema: prepared, warnings } = prepareSchemaForProvider(schema, provider, structuredOutputConfig.strict !== false);
819
822
  preparedSchema = prepared;
820
823
  if (warnings.length > 0) {
821
- console.warn('[Graph] Schema preparation warnings:', warnings);
824
+ mwarn('[Graph] Schema preparation warnings:', warnings);
822
825
  }
823
826
  }
824
827
  // Use withStructuredOutput to bind the schema
@@ -888,7 +891,7 @@ class StandardGraph extends Graph {
888
891
  const errorMessage = typeof handleErrors === 'string'
889
892
  ? handleErrors
890
893
  : `The response did not match the expected schema. Error: ${lastError.message}. Please try again with a valid response.`;
891
- console.warn(`[Graph] Structured output attempt ${attempts} failed: ${lastError.message}. Retrying...`);
894
+ mwarn(`[Graph] Structured output attempt ${attempts} failed: ${lastError.message}. Retrying...`);
892
895
  // Add the error as a human message for context
893
896
  finalMessages = [
894
897
  ...finalMessages,
@@ -1038,7 +1041,7 @@ class StandardGraph extends Graph {
1038
1041
  const cachedDiscoveries = this._toolDiscoveryCache.getNewDiscoveries(messages);
1039
1042
  if (cachedDiscoveries.length > 0) {
1040
1043
  agentContext.markToolsAsDiscovered(cachedDiscoveries);
1041
- console.debug(`[Graph:ToolDiscovery] Cached ${cachedDiscoveries.length} new tools (total: ${this._toolDiscoveryCache.size})`);
1044
+ mlog(`[Graph:ToolDiscovery] Cached ${cachedDiscoveries.length} new tools (total: ${this._toolDiscoveryCache.size})`);
1042
1045
  }
1043
1046
  const toolsForBinding = agentContext.getToolsForBinding();
1044
1047
  // PERF: Detect subsequent ReAct iterations (tool results present in messages)
@@ -1056,6 +1059,11 @@ class StandardGraph extends Graph {
1056
1059
  provider: agentContext.provider,
1057
1060
  clientOptions: effectiveClientOptions,
1058
1061
  });
1062
+ // DEBUG: Log which model and tools each agent uses during handoff
1063
+ mlog(`[createCallModel] Agent "${agentId}" invoking LLM | provider=${agentContext.provider} | ` +
1064
+ `model=${effectiveClientOptions.model ?? 'default'} | ` +
1065
+ `toolsForBinding=${toolsForBinding?.length ?? 0} | ` +
1066
+ `toolNames=[${(toolsForBinding ?? []).map((t) => t.name ?? 'unknown').join(', ')}]`);
1059
1067
  if (agentContext.systemRunnable) {
1060
1068
  model = agentContext.systemRunnable.pipe(model);
1061
1069
  }
@@ -1065,7 +1073,15 @@ class StandardGraph extends Graph {
1065
1073
  if (!config.signal) {
1066
1074
  config.signal = this.signal;
1067
1075
  }
1068
- this.config = config;
1076
+ // First-writer-wins: `this.config` is used ONLY as a "has a run started"
1077
+ // existence flag by the dispatch* methods (they never read its value —
1078
+ // they read the current RunnableConfig from LangChain AsyncLocalStorage).
1079
+ // Unconditionally reassigning here races across concurrent child
1080
+ // subgraph.invoke() calls under parallel multi-agent handoffs; the last
1081
+ // writer wins, and any dispatch firing between writes would historically
1082
+ // have been tagged with the wrong child's metadata. Keeping the first
1083
+ // write pinned makes this a true flag, eliminating the race.
1084
+ this.config ??= config;
1069
1085
  let messagesToUse = messages;
1070
1086
  // ====================================================================
1071
1087
  // PRE-PRUNING DELEGATION CHECK
@@ -1131,13 +1147,13 @@ class StandardGraph extends Graph {
1131
1147
  const oldMessages = messages.slice(messages[0]?.getType() === 'system' ? 1 : 0, Math.max(1, messages.length - recentTurnCount));
1132
1148
  if (oldMessages.length > 0) {
1133
1149
  this._summaryInFlight = true;
1134
- console.debug(`[Graph:ProactiveSummary] Context at ${utilization.toFixed(1)}% (threshold ${threshold}%) — summarizing ${oldMessages.length} older msgs in background`);
1150
+ mlog(`[Graph:ProactiveSummary] Context at ${utilization.toFixed(1)}% (threshold ${threshold}%) — summarizing ${oldMessages.length} older msgs in background`);
1135
1151
  agentContext
1136
1152
  .summarizeCallback(oldMessages)
1137
1153
  .then((updated) => {
1138
1154
  if (updated != null && updated !== '') {
1139
1155
  this._cachedRunSummary = updated;
1140
- console.debug(`[Graph:ProactiveSummary] Background summary ready (len=${updated.length})`);
1156
+ mlog(`[Graph:ProactiveSummary] Background summary ready (len=${updated.length})`);
1141
1157
  }
1142
1158
  })
1143
1159
  .catch((err) => {
@@ -1313,7 +1329,7 @@ class StandardGraph extends Graph {
1313
1329
  viewIdx++;
1314
1330
  }
1315
1331
  agentContext.indexTokenCountMap = viewTokenMap;
1316
- console.debug(`[Graph:Compaction] ${messages.length}→${viewParts.length} msgs | ` +
1332
+ mlog(`[Graph:Compaction] ${messages.length}→${viewParts.length} msgs | ` +
1317
1333
  `compacted=${compactedMessages.length} window=${recentMessages.length} | ` +
1318
1334
  `summary=${summarySource} | budget=${usedTokens}/${recentBudget}` +
1319
1335
  (fileManifestTokens > 0
@@ -1327,7 +1343,7 @@ class StandardGraph extends Graph {
1327
1343
  if (shouldSummarize) {
1328
1344
  if (this._summaryInFlight) {
1329
1345
  this._pendingMessagesToRefine.push(...compactedMessages);
1330
- console.debug(`[Graph:Compaction] Summary in-flight, queued ${compactedMessages.length} msgs (pending=${this._pendingMessagesToRefine.length})`);
1346
+ mlog(`[Graph:Compaction] Summary in-flight, queued ${compactedMessages.length} msgs (pending=${this._pendingMessagesToRefine.length})`);
1331
1347
  }
1332
1348
  else {
1333
1349
  this._summaryInFlight = true;
@@ -1368,7 +1384,7 @@ class StandardGraph extends Graph {
1368
1384
  const { messages: dedupedMessages, removedCount } = deduplicateSystemMessages(messagesToUse);
1369
1385
  if (removedCount > 0) {
1370
1386
  messagesToUse = dedupedMessages;
1371
- console.debug(`[Graph:Dedup] Removed ${removedCount} duplicate system message(s)`);
1387
+ mlog(`[Graph:Dedup] Removed ${removedCount} duplicate system message(s)`);
1372
1388
  }
1373
1389
  let finalMessages = messagesToUse;
1374
1390
  if (agentContext.useLegacyContent) {
@@ -1542,8 +1558,8 @@ class StandardGraph extends Graph {
1542
1558
  errorMessage.includes('prompt is too long');
1543
1559
  // Log when we detect the error
1544
1560
  if (isInputTooLongError) {
1545
- console.warn('[Graph] Detected input too long error:', errorMessage.substring(0, 200));
1546
- console.warn('[Graph] Checking emergency pruning conditions:', {
1561
+ mwarn('[Graph] Detected input too long error:', errorMessage.substring(0, 200));
1562
+ mwarn('[Graph] Checking emergency pruning conditions:', {
1547
1563
  hasPruneMessages: !!agentContext.pruneMessages,
1548
1564
  hasTokenCounter: !!agentContext.tokenCounter,
1549
1565
  maxContextTokens: agentContext.maxContextTokens,
@@ -1563,12 +1579,12 @@ class StandardGraph extends Graph {
1563
1579
  if (result)
1564
1580
  break; // Exit if we got a result
1565
1581
  const reducedMaxTokens = Math.floor(agentContext.maxContextTokens * reductionFactor);
1566
- console.warn(`[Graph] Input too long. Retrying with ${reductionFactor * 100}% context (${reducedMaxTokens} tokens)...`);
1582
+ mwarn(`[Graph] Input too long. Retrying with ${reductionFactor * 100}% context (${reducedMaxTokens} tokens)...`);
1567
1583
  // Build fresh indexTokenCountMap if missing/incomplete
1568
1584
  // This is needed when messages were dynamically added without updating the token map
1569
1585
  let tokenMapForPruning = agentContext.indexTokenCountMap;
1570
1586
  if (Object.keys(tokenMapForPruning).length < messages.length) {
1571
- console.warn('[Graph] Building fresh token count map for emergency pruning...');
1587
+ mwarn('[Graph] Building fresh token count map for emergency pruning...');
1572
1588
  tokenMapForPruning = {};
1573
1589
  for (let i = 0; i < messages.length; i++) {
1574
1590
  tokenMapForPruning[i] = agentContext.tokenCounter(messages[i]);
@@ -1588,7 +1604,7 @@ class StandardGraph extends Graph {
1588
1604
  });
1589
1605
  // Skip if we can't fit any messages
1590
1606
  if (reducedMessages.length === 0) {
1591
- console.warn(`[Graph] Cannot fit any messages at ${reductionFactor * 100}% reduction, trying next level...`);
1607
+ mwarn(`[Graph] Cannot fit any messages at ${reductionFactor * 100}% reduction, trying next level...`);
1592
1608
  continue;
1593
1609
  }
1594
1610
  // Calculate how many messages were pruned and estimate context timeframe
@@ -1648,7 +1664,7 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1648
1664
  retryErrorMsg.includes('context length') ||
1649
1665
  retryErrorMsg.includes('validationexception');
1650
1666
  if (stillTooLong && reductionFactor > 0.1) {
1651
- console.warn(`[Graph] Still too long at ${reductionFactor * 100}%, trying more aggressive pruning...`);
1667
+ mwarn(`[Graph] Still too long at ${reductionFactor * 100}%, trying more aggressive pruning...`);
1652
1668
  }
1653
1669
  else {
1654
1670
  console.error(`[Graph] Retry at ${reductionFactor * 100}% failed:`, retryError.message);
@@ -1708,6 +1724,20 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1708
1724
  * handled everything — both paths become no-ops.
1709
1725
  */
1710
1726
  const responseMessage = result.messages?.[0];
1727
+ // Tool-call name normalization — catches LLM output that names tools
1728
+ // with wrong delimiters (outlook/operations), prefixes
1729
+ // (functions.outlook_operations), case drift, counter suffixes, or
1730
+ // empty names recoverable from the tool_call id. Mutates in place so
1731
+ // the downstream ToolNode dispatch sees the corrected names.
1732
+ if (responseMessage && agentContext.toolMap) {
1733
+ const allowedNames = new Set(Object.keys(agentContext.toolMap));
1734
+ if (allowedNames.size > 0) {
1735
+ const rewrote = normalizeMessageToolCalls(responseMessage, allowedNames);
1736
+ if (rewrote) {
1737
+ mlog(`[Graph] normalized tool_call names on agent "${agentId}" response`);
1738
+ }
1739
+ }
1740
+ }
1711
1741
  const toolCalls = responseMessage
1712
1742
  ?.tool_calls;
1713
1743
  const hasToolCalls = Array.isArray(toolCalls) && toolCalls.length > 0;
@@ -1794,12 +1824,20 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1794
1824
  const meta = finalMsg.response_metadata;
1795
1825
  // Bedrock streaming nests stopReason inside messageStop: { stopReason: '...' }
1796
1826
  const messageStop = meta.messageStop;
1797
- this.lastFinishReason =
1798
- meta.finish_reason ?? // OpenAI/Azure
1799
- meta.stop_reason ?? // Anthropic direct API
1800
- meta.stopReason ?? // Bedrock invoke (non-streaming)
1801
- messageStop?.stopReason ?? // Bedrock streaming
1802
- meta.finishReason; // VertexAI/Google
1827
+ const nextReason = meta.finish_reason ?? // OpenAI/Azure
1828
+ meta.stop_reason ?? // Anthropic direct API
1829
+ meta.stopReason ?? // Bedrock invoke (non-streaming)
1830
+ messageStop?.stopReason ?? // Bedrock streaming
1831
+ meta.finishReason; // VertexAI/Google
1832
+ // Sticky on truncation: a single Graph instance is reused across
1833
+ // every scoped-subgraph inner node invocation (see MultiAgentGraph
1834
+ // buildScopedSubgraph). If an earlier inner node hit max_tokens
1835
+ // but a later inner node finished cleanly, the host's continuation layer
1836
+ // would miss the truncation signal unless we preserve it. Keep the
1837
+ // truncation reason pinned so the outer caller can retry.
1838
+ if (!isTruncationReason(this.lastFinishReason)) {
1839
+ this.lastFinishReason = nextReason;
1840
+ }
1803
1841
  }
1804
1842
  this.cleanupSignalListener();
1805
1843
  // DEFERRED STRUCTURED OUTPUT: When the agent has tools AND structured output configured,
@@ -1847,7 +1885,7 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1847
1885
  // but we couldn't format the output as structured JSON.
1848
1886
  // Return the unstructured text response from attemptInvoke.
1849
1887
  console.error('[Graph] Deferred structured output failed after successful tool use:', structuredError);
1850
- console.warn('[Graph] Falling back to unstructured response from tool-use phase');
1888
+ mwarn('[Graph] Falling back to unstructured response from tool-use phase');
1851
1889
  return result;
1852
1890
  }
1853
1891
  }
@@ -1863,7 +1901,10 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1863
1901
  const agentNode = `${AGENT}${agentId}`;
1864
1902
  const toolNode = `${TOOLS}${agentId}`;
1865
1903
  const routeMessage = (state, config) => {
1866
- this.config = config;
1904
+ // First-writer-wins — see note in createCallModel. `this.config` is an
1905
+ // existence flag only; assigning unconditionally would race under
1906
+ // parallel child subgraph.invoke().
1907
+ this.config ??= config;
1867
1908
  return toolsCondition(state, toolNode, this.invokedToolIds);
1868
1909
  };
1869
1910
  const StateAnnotation = Annotation.Root({
@@ -1901,10 +1942,16 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1901
1942
  default: () => [],
1902
1943
  }),
1903
1944
  });
1945
+ // Pass compileOptions (including the HITL checkpointer) to the OUTER
1946
+ // workflow — not just the inner agent subgraph. hasInterrupts() calls
1947
+ // getState() on the outer compiled graph; without a checkpointer here,
1948
+ // getState reports zero tasks and the HITL interrupt/resume loop breaks
1949
+ // out immediately even though interrupt() fired correctly inside the
1950
+ // agent subgraph.
1904
1951
  const workflow = new StateGraph(StateAnnotation)
1905
1952
  .addNode(this.defaultAgentId, agentNode, { ends: [END] })
1906
1953
  .addEdge(START, this.defaultAgentId)
1907
- .compile();
1954
+ .compile(this.compileOptions);
1908
1955
  return workflow;
1909
1956
  }
1910
1957
  /**
@@ -1975,12 +2022,16 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1975
2022
  }
1976
2023
  catch (_e) {
1977
2024
  /** If we can't get agent context, that's okay - agentId remains undefined */
1978
- console.debug(`[dispatchRunStep] Could not resolve agentId from metadata.langgraph_node="${metadata.langgraph_node}": ${_e.message}`);
2025
+ mlog(`[dispatchRunStep] Could not resolve agentId from metadata.langgraph_node="${metadata.langgraph_node}": ${_e.message}`);
1979
2026
  }
1980
2027
  }
1981
2028
  this.contentData.push(runStep);
1982
2029
  this.contentIndexMap.set(stepId, runStep.index);
1983
- await safeDispatchCustomEvent(GraphEvents.ON_RUN_STEP, runStep, this.config);
2030
+ // Pass undefined so safeDispatchCustomEvent resolves the runnable config
2031
+ // from LangChain's AsyncLocalStorage. Using the shared `this.config` would
2032
+ // race across concurrent child subgraph.invoke calls under parallel
2033
+ // multi-agent handoffs and tag events with the wrong child's spawnKey.
2034
+ await safeDispatchCustomEvent(GraphEvents.ON_RUN_STEP, runStep);
1984
2035
  return stepId;
1985
2036
  }
1986
2037
  async handleToolCallCompleted(data, metadata, omitOutput) {
@@ -2088,7 +2139,7 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
2088
2139
  throw new Error('No config provided');
2089
2140
  }
2090
2141
  if (!data.id) {
2091
- console.warn('No Tool ID provided for Tool Error');
2142
+ mwarn('No Tool ID provided for Tool Error');
2092
2143
  return;
2093
2144
  }
2094
2145
  const stepId = graph.toolCallStepIds.get(data.id) ?? '';
@@ -2136,7 +2187,10 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
2136
2187
  id,
2137
2188
  delta,
2138
2189
  };
2139
- await safeDispatchCustomEvent(GraphEvents.ON_RUN_STEP_DELTA, runStepDelta, this.config);
2190
+ // See dispatchRunStep note: do not pass `this.config`. The implicit
2191
+ // AsyncLocalStorage config is the correct per-async-branch source under
2192
+ // parallel handoffs.
2193
+ await safeDispatchCustomEvent(GraphEvents.ON_RUN_STEP_DELTA, runStepDelta);
2140
2194
  }
2141
2195
  async dispatchMessageDelta(id, delta) {
2142
2196
  if (!this.config) {
@@ -2146,7 +2200,8 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
2146
2200
  id,
2147
2201
  delta,
2148
2202
  };
2149
- await safeDispatchCustomEvent(GraphEvents.ON_MESSAGE_DELTA, messageDelta, this.config);
2203
+ // See dispatchRunStep note.
2204
+ await safeDispatchCustomEvent(GraphEvents.ON_MESSAGE_DELTA, messageDelta);
2150
2205
  }
2151
2206
  dispatchReasoningDelta = async (stepId, delta) => {
2152
2207
  if (!this.config) {
@@ -2156,7 +2211,8 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
2156
2211
  id: stepId,
2157
2212
  delta,
2158
2213
  };
2159
- await safeDispatchCustomEvent(GraphEvents.ON_REASONING_DELTA, reasoningDelta, this.config);
2214
+ // See dispatchRunStep note.
2215
+ await safeDispatchCustomEvent(GraphEvents.ON_REASONING_DELTA, reasoningDelta);
2160
2216
  };
2161
2217
  }
2162
2218