@illuma-ai/agents 1.1.28 → 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 (263) hide show
  1. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  2. package/dist/cjs/common/spawnPath.cjs +104 -0
  3. package/dist/cjs/common/spawnPath.cjs.map +1 -0
  4. package/dist/cjs/graphs/Graph.cjs +84 -33
  5. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  6. package/dist/cjs/graphs/HandoffRegistry.cjs +47 -8
  7. package/dist/cjs/graphs/HandoffRegistry.cjs.map +1 -1
  8. package/dist/cjs/graphs/MultiAgentGraph.cjs +493 -267
  9. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  10. package/dist/cjs/graphs/phases/flushLoop.cjs +214 -0
  11. package/dist/cjs/graphs/phases/flushLoop.cjs.map +1 -0
  12. package/dist/cjs/graphs/phases/memoryFlushPhase.cjs +102 -0
  13. package/dist/cjs/graphs/phases/memoryFlushPhase.cjs.map +1 -0
  14. package/dist/cjs/llm/bedrock/index.cjs +4 -3
  15. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  16. package/dist/cjs/main.cjs +113 -0
  17. package/dist/cjs/main.cjs.map +1 -1
  18. package/dist/cjs/memory/citations.cjs +69 -0
  19. package/dist/cjs/memory/citations.cjs.map +1 -0
  20. package/dist/cjs/memory/compositeBackend.cjs +60 -0
  21. package/dist/cjs/memory/compositeBackend.cjs.map +1 -0
  22. package/dist/cjs/memory/constants.cjs +232 -0
  23. package/dist/cjs/memory/constants.cjs.map +1 -0
  24. package/dist/cjs/memory/embeddings.cjs +151 -0
  25. package/dist/cjs/memory/embeddings.cjs.map +1 -0
  26. package/dist/cjs/memory/factory.cjs +95 -0
  27. package/dist/cjs/memory/factory.cjs.map +1 -0
  28. package/dist/cjs/memory/migrate.cjs +81 -0
  29. package/dist/cjs/memory/migrate.cjs.map +1 -0
  30. package/dist/cjs/memory/mmr.cjs +138 -0
  31. package/dist/cjs/memory/mmr.cjs.map +1 -0
  32. package/dist/cjs/memory/paths.cjs +217 -0
  33. package/dist/cjs/memory/paths.cjs.map +1 -0
  34. package/dist/cjs/memory/pgvectorStore.cjs +225 -0
  35. package/dist/cjs/memory/pgvectorStore.cjs.map +1 -0
  36. package/dist/cjs/memory/recallTracking.cjs +98 -0
  37. package/dist/cjs/memory/recallTracking.cjs.map +1 -0
  38. package/dist/cjs/memory/schema.sql +51 -0
  39. package/dist/cjs/memory/temporalDecay.cjs +118 -0
  40. package/dist/cjs/memory/temporalDecay.cjs.map +1 -0
  41. package/dist/cjs/nodes/ApprovalGateNode.cjs +1 -1
  42. package/dist/cjs/nodes/ApprovalGateNode.cjs.map +1 -1
  43. package/dist/cjs/prompts/memoryFlushPrompt.cjs +49 -0
  44. package/dist/cjs/prompts/memoryFlushPrompt.cjs.map +1 -0
  45. package/dist/cjs/run.cjs +16 -3
  46. package/dist/cjs/run.cjs.map +1 -1
  47. package/dist/cjs/tools/AskUser.cjs +6 -1
  48. package/dist/cjs/tools/AskUser.cjs.map +1 -1
  49. package/dist/cjs/tools/BrowserTools.cjs +1 -1
  50. package/dist/cjs/tools/BrowserTools.cjs.map +1 -1
  51. package/dist/cjs/tools/ToolNode.cjs +127 -10
  52. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  53. package/dist/cjs/tools/approval/constants.cjs +2 -2
  54. package/dist/cjs/tools/approval/constants.cjs.map +1 -1
  55. package/dist/cjs/tools/memory/index.cjs +58 -0
  56. package/dist/cjs/tools/memory/index.cjs.map +1 -0
  57. package/dist/cjs/tools/memory/memoryAppendTool.cjs +69 -0
  58. package/dist/cjs/tools/memory/memoryAppendTool.cjs.map +1 -0
  59. package/dist/cjs/tools/memory/memoryGetTool.cjs +49 -0
  60. package/dist/cjs/tools/memory/memoryGetTool.cjs.map +1 -0
  61. package/dist/cjs/tools/memory/memorySearchTool.cjs +65 -0
  62. package/dist/cjs/tools/memory/memorySearchTool.cjs.map +1 -0
  63. package/dist/cjs/tools/memory/shared.cjs +106 -0
  64. package/dist/cjs/tools/memory/shared.cjs.map +1 -0
  65. package/dist/cjs/types/graph.cjs.map +1 -1
  66. package/dist/cjs/utils/childAgentContext.cjs +242 -0
  67. package/dist/cjs/utils/childAgentContext.cjs.map +1 -0
  68. package/dist/cjs/utils/events.cjs +36 -7
  69. package/dist/cjs/utils/events.cjs.map +1 -1
  70. package/dist/cjs/utils/finishReasons.cjs +44 -0
  71. package/dist/cjs/utils/finishReasons.cjs.map +1 -0
  72. package/dist/cjs/utils/llm.cjs.map +1 -1
  73. package/dist/cjs/utils/logging.cjs +34 -0
  74. package/dist/cjs/utils/logging.cjs.map +1 -0
  75. package/dist/cjs/utils/toolCallNormalization.cjs +250 -0
  76. package/dist/cjs/utils/toolCallNormalization.cjs.map +1 -0
  77. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  78. package/dist/esm/common/spawnPath.mjs +95 -0
  79. package/dist/esm/common/spawnPath.mjs.map +1 -0
  80. package/dist/esm/graphs/Graph.mjs +84 -33
  81. package/dist/esm/graphs/Graph.mjs.map +1 -1
  82. package/dist/esm/graphs/HandoffRegistry.mjs +47 -8
  83. package/dist/esm/graphs/HandoffRegistry.mjs.map +1 -1
  84. package/dist/esm/graphs/MultiAgentGraph.mjs +493 -267
  85. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  86. package/dist/esm/graphs/phases/flushLoop.mjs +209 -0
  87. package/dist/esm/graphs/phases/flushLoop.mjs.map +1 -0
  88. package/dist/esm/graphs/phases/memoryFlushPhase.mjs +99 -0
  89. package/dist/esm/graphs/phases/memoryFlushPhase.mjs.map +1 -0
  90. package/dist/esm/llm/bedrock/index.mjs +4 -3
  91. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  92. package/dist/esm/main.mjs +20 -0
  93. package/dist/esm/main.mjs.map +1 -1
  94. package/dist/esm/memory/citations.mjs +64 -0
  95. package/dist/esm/memory/citations.mjs.map +1 -0
  96. package/dist/esm/memory/compositeBackend.mjs +58 -0
  97. package/dist/esm/memory/compositeBackend.mjs.map +1 -0
  98. package/dist/esm/memory/constants.mjs +198 -0
  99. package/dist/esm/memory/constants.mjs.map +1 -0
  100. package/dist/esm/memory/embeddings.mjs +148 -0
  101. package/dist/esm/memory/embeddings.mjs.map +1 -0
  102. package/dist/esm/memory/factory.mjs +93 -0
  103. package/dist/esm/memory/factory.mjs.map +1 -0
  104. package/dist/esm/memory/migrate.mjs +78 -0
  105. package/dist/esm/memory/migrate.mjs.map +1 -0
  106. package/dist/esm/memory/mmr.mjs +130 -0
  107. package/dist/esm/memory/mmr.mjs.map +1 -0
  108. package/dist/esm/memory/paths.mjs +207 -0
  109. package/dist/esm/memory/paths.mjs.map +1 -0
  110. package/dist/esm/memory/pgvectorStore.mjs +223 -0
  111. package/dist/esm/memory/pgvectorStore.mjs.map +1 -0
  112. package/dist/esm/memory/recallTracking.mjs +94 -0
  113. package/dist/esm/memory/recallTracking.mjs.map +1 -0
  114. package/dist/esm/memory/schema.sql +51 -0
  115. package/dist/esm/memory/temporalDecay.mjs +110 -0
  116. package/dist/esm/memory/temporalDecay.mjs.map +1 -0
  117. package/dist/esm/nodes/ApprovalGateNode.mjs +1 -1
  118. package/dist/esm/nodes/ApprovalGateNode.mjs.map +1 -1
  119. package/dist/esm/prompts/memoryFlushPrompt.mjs +44 -0
  120. package/dist/esm/prompts/memoryFlushPrompt.mjs.map +1 -0
  121. package/dist/esm/run.mjs +16 -3
  122. package/dist/esm/run.mjs.map +1 -1
  123. package/dist/esm/tools/AskUser.mjs +6 -1
  124. package/dist/esm/tools/AskUser.mjs.map +1 -1
  125. package/dist/esm/tools/BrowserTools.mjs +1 -1
  126. package/dist/esm/tools/BrowserTools.mjs.map +1 -1
  127. package/dist/esm/tools/ToolNode.mjs +128 -11
  128. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  129. package/dist/esm/tools/approval/constants.mjs +2 -2
  130. package/dist/esm/tools/approval/constants.mjs.map +1 -1
  131. package/dist/esm/tools/memory/index.mjs +46 -0
  132. package/dist/esm/tools/memory/index.mjs.map +1 -0
  133. package/dist/esm/tools/memory/memoryAppendTool.mjs +67 -0
  134. package/dist/esm/tools/memory/memoryAppendTool.mjs.map +1 -0
  135. package/dist/esm/tools/memory/memoryGetTool.mjs +47 -0
  136. package/dist/esm/tools/memory/memoryGetTool.mjs.map +1 -0
  137. package/dist/esm/tools/memory/memorySearchTool.mjs +63 -0
  138. package/dist/esm/tools/memory/memorySearchTool.mjs.map +1 -0
  139. package/dist/esm/tools/memory/shared.mjs +98 -0
  140. package/dist/esm/tools/memory/shared.mjs.map +1 -0
  141. package/dist/esm/types/graph.mjs.map +1 -1
  142. package/dist/esm/utils/childAgentContext.mjs +237 -0
  143. package/dist/esm/utils/childAgentContext.mjs.map +1 -0
  144. package/dist/esm/utils/events.mjs +36 -8
  145. package/dist/esm/utils/events.mjs.map +1 -1
  146. package/dist/esm/utils/finishReasons.mjs +41 -0
  147. package/dist/esm/utils/finishReasons.mjs.map +1 -0
  148. package/dist/esm/utils/llm.mjs.map +1 -1
  149. package/dist/esm/utils/logging.mjs +31 -0
  150. package/dist/esm/utils/logging.mjs.map +1 -0
  151. package/dist/esm/utils/toolCallNormalization.mjs +247 -0
  152. package/dist/esm/utils/toolCallNormalization.mjs.map +1 -0
  153. package/dist/types/common/index.d.ts +1 -0
  154. package/dist/types/common/spawnPath.d.ts +59 -0
  155. package/dist/types/graphs/HandoffRegistry.d.ts +24 -7
  156. package/dist/types/graphs/MultiAgentGraph.d.ts +43 -23
  157. package/dist/types/graphs/phases/flushLoop.d.ts +106 -0
  158. package/dist/types/graphs/phases/memoryFlushPhase.d.ts +100 -0
  159. package/dist/types/index.d.ts +7 -0
  160. package/dist/types/memory/__tests__/mockBackend.d.ts +40 -0
  161. package/dist/types/memory/citations.d.ts +39 -0
  162. package/dist/types/memory/compositeBackend.d.ts +30 -0
  163. package/dist/types/memory/constants.d.ts +121 -0
  164. package/dist/types/memory/embeddings.d.ts +15 -0
  165. package/dist/types/memory/factory.d.ts +23 -0
  166. package/dist/types/memory/index.d.ts +21 -0
  167. package/dist/types/memory/migrate.d.ts +14 -0
  168. package/dist/types/memory/mmr.d.ts +50 -0
  169. package/dist/types/memory/paths.d.ts +107 -0
  170. package/dist/types/memory/pgvectorStore.d.ts +56 -0
  171. package/dist/types/memory/recallTracking.d.ts +30 -0
  172. package/dist/types/memory/temporalDecay.d.ts +53 -0
  173. package/dist/types/memory/types.d.ts +182 -0
  174. package/dist/types/prompts/memoryFlushPrompt.d.ts +54 -0
  175. package/dist/types/run.d.ts +1 -0
  176. package/dist/types/tools/AskUser.d.ts +1 -1
  177. package/dist/types/tools/BrowserTools.d.ts +2 -2
  178. package/dist/types/tools/approval/constants.d.ts +2 -2
  179. package/dist/types/tools/memory/index.d.ts +39 -0
  180. package/dist/types/tools/memory/memoryAppendTool.d.ts +27 -0
  181. package/dist/types/tools/memory/memoryGetTool.d.ts +22 -0
  182. package/dist/types/tools/memory/memorySearchTool.d.ts +22 -0
  183. package/dist/types/tools/memory/shared.d.ts +106 -0
  184. package/dist/types/types/graph.d.ts +10 -3
  185. package/dist/types/utils/childAgentContext.d.ts +99 -0
  186. package/dist/types/utils/events.d.ts +21 -0
  187. package/dist/types/utils/finishReasons.d.ts +32 -0
  188. package/dist/types/utils/logging.d.ts +2 -0
  189. package/dist/types/utils/toolCallNormalization.d.ts +44 -0
  190. package/package.json +6 -4
  191. package/src/agents/AgentContext.ts +12 -4
  192. package/src/common/__tests__/enum.test.ts +4 -2
  193. package/src/common/__tests__/spawnPath.test.ts +110 -0
  194. package/src/common/index.ts +1 -0
  195. package/src/common/spawnPath.ts +101 -0
  196. package/src/graphs/Graph.ts +90 -47
  197. package/src/graphs/HandoffRegistry.ts +48 -17
  198. package/src/graphs/MultiAgentGraph.ts +588 -327
  199. package/src/graphs/__tests__/HandoffRegistry.test.ts +4 -1
  200. package/src/graphs/__tests__/multi-agent-delegate.test.ts +61 -16
  201. package/src/graphs/__tests__/multi-agent-edges.test.ts +4 -2
  202. package/src/graphs/__tests__/multi-agent-nested-subgraph.test.ts +221 -0
  203. package/src/graphs/__tests__/structured-output.integration.test.ts +212 -118
  204. package/src/graphs/contextManagement.e2e.test.ts +1 -1
  205. package/src/graphs/phases/__tests__/flushLoop.test.ts +264 -0
  206. package/src/graphs/phases/__tests__/memoryFlushPhase.test.ts +37 -0
  207. package/src/graphs/phases/__tests__/runMemoryFlush.test.ts +150 -0
  208. package/src/graphs/phases/flushLoop.ts +303 -0
  209. package/src/graphs/phases/memoryFlushPhase.ts +209 -0
  210. package/src/index.ts +30 -1
  211. package/src/llm/bedrock/index.ts +4 -5
  212. package/src/memory/__tests__/citations.test.ts +61 -0
  213. package/src/memory/__tests__/compositeBackend.test.ts +79 -0
  214. package/src/memory/__tests__/isolation.test.ts +206 -0
  215. package/src/memory/__tests__/mmr.test.ts +148 -0
  216. package/src/memory/__tests__/mockBackend.ts +161 -0
  217. package/src/memory/__tests__/paths.test.ts +168 -0
  218. package/src/memory/__tests__/recallTracking.test.ts +96 -0
  219. package/src/memory/__tests__/temporalDecay.test.ts +151 -0
  220. package/src/memory/citations.ts +80 -0
  221. package/src/memory/compositeBackend.ts +99 -0
  222. package/src/memory/constants.ts +229 -0
  223. package/src/memory/embeddings.ts +188 -0
  224. package/src/memory/factory.ts +111 -0
  225. package/src/memory/index.ts +46 -0
  226. package/src/memory/migrate.ts +116 -0
  227. package/src/memory/mmr.ts +161 -0
  228. package/src/memory/paths.ts +258 -0
  229. package/src/memory/pgvectorStore.ts +324 -0
  230. package/src/memory/recallTracking.ts +127 -0
  231. package/src/memory/schema.sql +51 -0
  232. package/src/memory/temporalDecay.ts +134 -0
  233. package/src/memory/types.ts +185 -0
  234. package/src/nodes/ApprovalGateNode.ts +4 -10
  235. package/src/nodes/__tests__/ApprovalGateNode.test.ts +11 -20
  236. package/src/prompts/memoryFlushPrompt.ts +78 -0
  237. package/src/run.ts +17 -6
  238. package/src/scripts/test-bedrock-handoff-autonomous.ts +56 -20
  239. package/src/specs/agent-handoffs-bedrock.integration.test.ts +8 -5
  240. package/src/specs/agent-handoffs.test.ts +8 -2
  241. package/src/tools/AskUser.ts +7 -2
  242. package/src/tools/BrowserTools.ts +3 -5
  243. package/src/tools/ToolNode.ts +150 -13
  244. package/src/tools/__tests__/ToolApproval.test.ts +22 -9
  245. package/src/tools/approval/__tests__/constants.test.ts +1 -1
  246. package/src/tools/approval/constants.ts +2 -2
  247. package/src/tools/memory/__tests__/memoryTools.test.ts +205 -0
  248. package/src/tools/memory/index.ts +96 -0
  249. package/src/tools/memory/memoryAppendTool.ts +101 -0
  250. package/src/tools/memory/memoryGetTool.ts +53 -0
  251. package/src/tools/memory/memorySearchTool.ts +80 -0
  252. package/src/tools/memory/shared.ts +169 -0
  253. package/src/tools/search/search.test.ts +6 -1
  254. package/src/types/graph.ts +10 -3
  255. package/src/utils/__tests__/childAgentContext.test.ts +217 -0
  256. package/src/utils/__tests__/finishReasons.test.ts +55 -0
  257. package/src/utils/__tests__/toolCallNormalization.test.ts +181 -0
  258. package/src/utils/childAgentContext.ts +259 -0
  259. package/src/utils/events.ts +37 -7
  260. package/src/utils/finishReasons.ts +40 -0
  261. package/src/utils/llm.ts +0 -1
  262. package/src/utils/logging.ts +45 -8
  263. 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)
@@ -1057,8 +1060,8 @@ class StandardGraph extends Graph {
1057
1060
  clientOptions: effectiveClientOptions,
1058
1061
  });
1059
1062
  // DEBUG: Log which model and tools each agent uses during handoff
1060
- console.debug(`[createCallModel] Agent "${agentId}" invoking LLM | provider=${agentContext.provider} | ` +
1061
- `model=${effectiveClientOptions?.model ?? 'default'} | ` +
1063
+ mlog(`[createCallModel] Agent "${agentId}" invoking LLM | provider=${agentContext.provider} | ` +
1064
+ `model=${effectiveClientOptions.model ?? 'default'} | ` +
1062
1065
  `toolsForBinding=${toolsForBinding?.length ?? 0} | ` +
1063
1066
  `toolNames=[${(toolsForBinding ?? []).map((t) => t.name ?? 'unknown').join(', ')}]`);
1064
1067
  if (agentContext.systemRunnable) {
@@ -1070,7 +1073,15 @@ class StandardGraph extends Graph {
1070
1073
  if (!config.signal) {
1071
1074
  config.signal = this.signal;
1072
1075
  }
1073
- 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;
1074
1085
  let messagesToUse = messages;
1075
1086
  // ====================================================================
1076
1087
  // PRE-PRUNING DELEGATION CHECK
@@ -1136,13 +1147,13 @@ class StandardGraph extends Graph {
1136
1147
  const oldMessages = messages.slice(messages[0]?.getType() === 'system' ? 1 : 0, Math.max(1, messages.length - recentTurnCount));
1137
1148
  if (oldMessages.length > 0) {
1138
1149
  this._summaryInFlight = true;
1139
- 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`);
1140
1151
  agentContext
1141
1152
  .summarizeCallback(oldMessages)
1142
1153
  .then((updated) => {
1143
1154
  if (updated != null && updated !== '') {
1144
1155
  this._cachedRunSummary = updated;
1145
- console.debug(`[Graph:ProactiveSummary] Background summary ready (len=${updated.length})`);
1156
+ mlog(`[Graph:ProactiveSummary] Background summary ready (len=${updated.length})`);
1146
1157
  }
1147
1158
  })
1148
1159
  .catch((err) => {
@@ -1318,7 +1329,7 @@ class StandardGraph extends Graph {
1318
1329
  viewIdx++;
1319
1330
  }
1320
1331
  agentContext.indexTokenCountMap = viewTokenMap;
1321
- console.debug(`[Graph:Compaction] ${messages.length}→${viewParts.length} msgs | ` +
1332
+ mlog(`[Graph:Compaction] ${messages.length}→${viewParts.length} msgs | ` +
1322
1333
  `compacted=${compactedMessages.length} window=${recentMessages.length} | ` +
1323
1334
  `summary=${summarySource} | budget=${usedTokens}/${recentBudget}` +
1324
1335
  (fileManifestTokens > 0
@@ -1332,7 +1343,7 @@ class StandardGraph extends Graph {
1332
1343
  if (shouldSummarize) {
1333
1344
  if (this._summaryInFlight) {
1334
1345
  this._pendingMessagesToRefine.push(...compactedMessages);
1335
- 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})`);
1336
1347
  }
1337
1348
  else {
1338
1349
  this._summaryInFlight = true;
@@ -1373,7 +1384,7 @@ class StandardGraph extends Graph {
1373
1384
  const { messages: dedupedMessages, removedCount } = deduplicateSystemMessages(messagesToUse);
1374
1385
  if (removedCount > 0) {
1375
1386
  messagesToUse = dedupedMessages;
1376
- console.debug(`[Graph:Dedup] Removed ${removedCount} duplicate system message(s)`);
1387
+ mlog(`[Graph:Dedup] Removed ${removedCount} duplicate system message(s)`);
1377
1388
  }
1378
1389
  let finalMessages = messagesToUse;
1379
1390
  if (agentContext.useLegacyContent) {
@@ -1547,8 +1558,8 @@ class StandardGraph extends Graph {
1547
1558
  errorMessage.includes('prompt is too long');
1548
1559
  // Log when we detect the error
1549
1560
  if (isInputTooLongError) {
1550
- console.warn('[Graph] Detected input too long error:', errorMessage.substring(0, 200));
1551
- 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:', {
1552
1563
  hasPruneMessages: !!agentContext.pruneMessages,
1553
1564
  hasTokenCounter: !!agentContext.tokenCounter,
1554
1565
  maxContextTokens: agentContext.maxContextTokens,
@@ -1568,12 +1579,12 @@ class StandardGraph extends Graph {
1568
1579
  if (result)
1569
1580
  break; // Exit if we got a result
1570
1581
  const reducedMaxTokens = Math.floor(agentContext.maxContextTokens * reductionFactor);
1571
- 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)...`);
1572
1583
  // Build fresh indexTokenCountMap if missing/incomplete
1573
1584
  // This is needed when messages were dynamically added without updating the token map
1574
1585
  let tokenMapForPruning = agentContext.indexTokenCountMap;
1575
1586
  if (Object.keys(tokenMapForPruning).length < messages.length) {
1576
- console.warn('[Graph] Building fresh token count map for emergency pruning...');
1587
+ mwarn('[Graph] Building fresh token count map for emergency pruning...');
1577
1588
  tokenMapForPruning = {};
1578
1589
  for (let i = 0; i < messages.length; i++) {
1579
1590
  tokenMapForPruning[i] = agentContext.tokenCounter(messages[i]);
@@ -1593,7 +1604,7 @@ class StandardGraph extends Graph {
1593
1604
  });
1594
1605
  // Skip if we can't fit any messages
1595
1606
  if (reducedMessages.length === 0) {
1596
- 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...`);
1597
1608
  continue;
1598
1609
  }
1599
1610
  // Calculate how many messages were pruned and estimate context timeframe
@@ -1653,7 +1664,7 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1653
1664
  retryErrorMsg.includes('context length') ||
1654
1665
  retryErrorMsg.includes('validationexception');
1655
1666
  if (stillTooLong && reductionFactor > 0.1) {
1656
- 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...`);
1657
1668
  }
1658
1669
  else {
1659
1670
  console.error(`[Graph] Retry at ${reductionFactor * 100}% failed:`, retryError.message);
@@ -1713,6 +1724,20 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1713
1724
  * handled everything — both paths become no-ops.
1714
1725
  */
1715
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
+ }
1716
1741
  const toolCalls = responseMessage
1717
1742
  ?.tool_calls;
1718
1743
  const hasToolCalls = Array.isArray(toolCalls) && toolCalls.length > 0;
@@ -1799,12 +1824,20 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1799
1824
  const meta = finalMsg.response_metadata;
1800
1825
  // Bedrock streaming nests stopReason inside messageStop: { stopReason: '...' }
1801
1826
  const messageStop = meta.messageStop;
1802
- this.lastFinishReason =
1803
- meta.finish_reason ?? // OpenAI/Azure
1804
- meta.stop_reason ?? // Anthropic direct API
1805
- meta.stopReason ?? // Bedrock invoke (non-streaming)
1806
- messageStop?.stopReason ?? // Bedrock streaming
1807
- 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
+ }
1808
1841
  }
1809
1842
  this.cleanupSignalListener();
1810
1843
  // DEFERRED STRUCTURED OUTPUT: When the agent has tools AND structured output configured,
@@ -1852,7 +1885,7 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1852
1885
  // but we couldn't format the output as structured JSON.
1853
1886
  // Return the unstructured text response from attemptInvoke.
1854
1887
  console.error('[Graph] Deferred structured output failed after successful tool use:', structuredError);
1855
- console.warn('[Graph] Falling back to unstructured response from tool-use phase');
1888
+ mwarn('[Graph] Falling back to unstructured response from tool-use phase');
1856
1889
  return result;
1857
1890
  }
1858
1891
  }
@@ -1868,7 +1901,10 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1868
1901
  const agentNode = `${AGENT}${agentId}`;
1869
1902
  const toolNode = `${TOOLS}${agentId}`;
1870
1903
  const routeMessage = (state, config) => {
1871
- 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;
1872
1908
  return toolsCondition(state, toolNode, this.invokedToolIds);
1873
1909
  };
1874
1910
  const StateAnnotation = Annotation.Root({
@@ -1906,10 +1942,16 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1906
1942
  default: () => [],
1907
1943
  }),
1908
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.
1909
1951
  const workflow = new StateGraph(StateAnnotation)
1910
1952
  .addNode(this.defaultAgentId, agentNode, { ends: [END] })
1911
1953
  .addEdge(START, this.defaultAgentId)
1912
- .compile();
1954
+ .compile(this.compileOptions);
1913
1955
  return workflow;
1914
1956
  }
1915
1957
  /**
@@ -1980,12 +2022,16 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1980
2022
  }
1981
2023
  catch (_e) {
1982
2024
  /** If we can't get agent context, that's okay - agentId remains undefined */
1983
- 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}`);
1984
2026
  }
1985
2027
  }
1986
2028
  this.contentData.push(runStep);
1987
2029
  this.contentIndexMap.set(stepId, runStep.index);
1988
- 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);
1989
2035
  return stepId;
1990
2036
  }
1991
2037
  async handleToolCallCompleted(data, metadata, omitOutput) {
@@ -2093,7 +2139,7 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
2093
2139
  throw new Error('No config provided');
2094
2140
  }
2095
2141
  if (!data.id) {
2096
- console.warn('No Tool ID provided for Tool Error');
2142
+ mwarn('No Tool ID provided for Tool Error');
2097
2143
  return;
2098
2144
  }
2099
2145
  const stepId = graph.toolCallStepIds.get(data.id) ?? '';
@@ -2141,7 +2187,10 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
2141
2187
  id,
2142
2188
  delta,
2143
2189
  };
2144
- 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);
2145
2194
  }
2146
2195
  async dispatchMessageDelta(id, delta) {
2147
2196
  if (!this.config) {
@@ -2151,7 +2200,8 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
2151
2200
  id,
2152
2201
  delta,
2153
2202
  };
2154
- await safeDispatchCustomEvent(GraphEvents.ON_MESSAGE_DELTA, messageDelta, this.config);
2203
+ // See dispatchRunStep note.
2204
+ await safeDispatchCustomEvent(GraphEvents.ON_MESSAGE_DELTA, messageDelta);
2155
2205
  }
2156
2206
  dispatchReasoningDelta = async (stepId, delta) => {
2157
2207
  if (!this.config) {
@@ -2161,7 +2211,8 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
2161
2211
  id: stepId,
2162
2212
  delta,
2163
2213
  };
2164
- await safeDispatchCustomEvent(GraphEvents.ON_REASONING_DELTA, reasoningDelta, this.config);
2214
+ // See dispatchRunStep note.
2215
+ await safeDispatchCustomEvent(GraphEvents.ON_REASONING_DELTA, reasoningDelta);
2165
2216
  };
2166
2217
  }
2167
2218