@illuma-ai/agents 1.1.28 → 1.3.1

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.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 +89 -45
  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 +117 -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/errors.cjs +113 -0
  69. package/dist/cjs/utils/errors.cjs.map +1 -0
  70. package/dist/cjs/utils/events.cjs +36 -7
  71. package/dist/cjs/utils/events.cjs.map +1 -1
  72. package/dist/cjs/utils/finishReasons.cjs +44 -0
  73. package/dist/cjs/utils/finishReasons.cjs.map +1 -0
  74. package/dist/cjs/utils/llm.cjs.map +1 -1
  75. package/dist/cjs/utils/logging.cjs +34 -0
  76. package/dist/cjs/utils/logging.cjs.map +1 -0
  77. package/dist/cjs/utils/toolCallNormalization.cjs +250 -0
  78. package/dist/cjs/utils/toolCallNormalization.cjs.map +1 -0
  79. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  80. package/dist/esm/common/spawnPath.mjs +95 -0
  81. package/dist/esm/common/spawnPath.mjs.map +1 -0
  82. package/dist/esm/graphs/Graph.mjs +89 -45
  83. package/dist/esm/graphs/Graph.mjs.map +1 -1
  84. package/dist/esm/graphs/HandoffRegistry.mjs +47 -8
  85. package/dist/esm/graphs/HandoffRegistry.mjs.map +1 -1
  86. package/dist/esm/graphs/MultiAgentGraph.mjs +493 -267
  87. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  88. package/dist/esm/graphs/phases/flushLoop.mjs +209 -0
  89. package/dist/esm/graphs/phases/flushLoop.mjs.map +1 -0
  90. package/dist/esm/graphs/phases/memoryFlushPhase.mjs +99 -0
  91. package/dist/esm/graphs/phases/memoryFlushPhase.mjs.map +1 -0
  92. package/dist/esm/llm/bedrock/index.mjs +4 -3
  93. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  94. package/dist/esm/main.mjs +21 -0
  95. package/dist/esm/main.mjs.map +1 -1
  96. package/dist/esm/memory/citations.mjs +64 -0
  97. package/dist/esm/memory/citations.mjs.map +1 -0
  98. package/dist/esm/memory/compositeBackend.mjs +58 -0
  99. package/dist/esm/memory/compositeBackend.mjs.map +1 -0
  100. package/dist/esm/memory/constants.mjs +198 -0
  101. package/dist/esm/memory/constants.mjs.map +1 -0
  102. package/dist/esm/memory/embeddings.mjs +148 -0
  103. package/dist/esm/memory/embeddings.mjs.map +1 -0
  104. package/dist/esm/memory/factory.mjs +93 -0
  105. package/dist/esm/memory/factory.mjs.map +1 -0
  106. package/dist/esm/memory/migrate.mjs +78 -0
  107. package/dist/esm/memory/migrate.mjs.map +1 -0
  108. package/dist/esm/memory/mmr.mjs +130 -0
  109. package/dist/esm/memory/mmr.mjs.map +1 -0
  110. package/dist/esm/memory/paths.mjs +207 -0
  111. package/dist/esm/memory/paths.mjs.map +1 -0
  112. package/dist/esm/memory/pgvectorStore.mjs +223 -0
  113. package/dist/esm/memory/pgvectorStore.mjs.map +1 -0
  114. package/dist/esm/memory/recallTracking.mjs +94 -0
  115. package/dist/esm/memory/recallTracking.mjs.map +1 -0
  116. package/dist/esm/memory/schema.sql +51 -0
  117. package/dist/esm/memory/temporalDecay.mjs +110 -0
  118. package/dist/esm/memory/temporalDecay.mjs.map +1 -0
  119. package/dist/esm/nodes/ApprovalGateNode.mjs +1 -1
  120. package/dist/esm/nodes/ApprovalGateNode.mjs.map +1 -1
  121. package/dist/esm/prompts/memoryFlushPrompt.mjs +44 -0
  122. package/dist/esm/prompts/memoryFlushPrompt.mjs.map +1 -0
  123. package/dist/esm/run.mjs +16 -3
  124. package/dist/esm/run.mjs.map +1 -1
  125. package/dist/esm/tools/AskUser.mjs +6 -1
  126. package/dist/esm/tools/AskUser.mjs.map +1 -1
  127. package/dist/esm/tools/BrowserTools.mjs +1 -1
  128. package/dist/esm/tools/BrowserTools.mjs.map +1 -1
  129. package/dist/esm/tools/ToolNode.mjs +128 -11
  130. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  131. package/dist/esm/tools/approval/constants.mjs +2 -2
  132. package/dist/esm/tools/approval/constants.mjs.map +1 -1
  133. package/dist/esm/tools/memory/index.mjs +46 -0
  134. package/dist/esm/tools/memory/index.mjs.map +1 -0
  135. package/dist/esm/tools/memory/memoryAppendTool.mjs +67 -0
  136. package/dist/esm/tools/memory/memoryAppendTool.mjs.map +1 -0
  137. package/dist/esm/tools/memory/memoryGetTool.mjs +47 -0
  138. package/dist/esm/tools/memory/memoryGetTool.mjs.map +1 -0
  139. package/dist/esm/tools/memory/memorySearchTool.mjs +63 -0
  140. package/dist/esm/tools/memory/memorySearchTool.mjs.map +1 -0
  141. package/dist/esm/tools/memory/shared.mjs +98 -0
  142. package/dist/esm/tools/memory/shared.mjs.map +1 -0
  143. package/dist/esm/types/graph.mjs.map +1 -1
  144. package/dist/esm/utils/childAgentContext.mjs +237 -0
  145. package/dist/esm/utils/childAgentContext.mjs.map +1 -0
  146. package/dist/esm/utils/errors.mjs +109 -0
  147. package/dist/esm/utils/errors.mjs.map +1 -0
  148. package/dist/esm/utils/events.mjs +36 -8
  149. package/dist/esm/utils/events.mjs.map +1 -1
  150. package/dist/esm/utils/finishReasons.mjs +41 -0
  151. package/dist/esm/utils/finishReasons.mjs.map +1 -0
  152. package/dist/esm/utils/llm.mjs.map +1 -1
  153. package/dist/esm/utils/logging.mjs +31 -0
  154. package/dist/esm/utils/logging.mjs.map +1 -0
  155. package/dist/esm/utils/toolCallNormalization.mjs +247 -0
  156. package/dist/esm/utils/toolCallNormalization.mjs.map +1 -0
  157. package/dist/types/common/index.d.ts +1 -0
  158. package/dist/types/common/spawnPath.d.ts +59 -0
  159. package/dist/types/graphs/HandoffRegistry.d.ts +24 -7
  160. package/dist/types/graphs/MultiAgentGraph.d.ts +43 -23
  161. package/dist/types/graphs/phases/flushLoop.d.ts +106 -0
  162. package/dist/types/graphs/phases/memoryFlushPhase.d.ts +100 -0
  163. package/dist/types/index.d.ts +7 -0
  164. package/dist/types/memory/__tests__/mockBackend.d.ts +40 -0
  165. package/dist/types/memory/citations.d.ts +39 -0
  166. package/dist/types/memory/compositeBackend.d.ts +30 -0
  167. package/dist/types/memory/constants.d.ts +121 -0
  168. package/dist/types/memory/embeddings.d.ts +15 -0
  169. package/dist/types/memory/factory.d.ts +23 -0
  170. package/dist/types/memory/index.d.ts +21 -0
  171. package/dist/types/memory/migrate.d.ts +14 -0
  172. package/dist/types/memory/mmr.d.ts +50 -0
  173. package/dist/types/memory/paths.d.ts +107 -0
  174. package/dist/types/memory/pgvectorStore.d.ts +56 -0
  175. package/dist/types/memory/recallTracking.d.ts +30 -0
  176. package/dist/types/memory/temporalDecay.d.ts +53 -0
  177. package/dist/types/memory/types.d.ts +182 -0
  178. package/dist/types/prompts/memoryFlushPrompt.d.ts +54 -0
  179. package/dist/types/run.d.ts +1 -0
  180. package/dist/types/tools/AskUser.d.ts +1 -1
  181. package/dist/types/tools/BrowserTools.d.ts +2 -2
  182. package/dist/types/tools/approval/constants.d.ts +2 -2
  183. package/dist/types/tools/memory/index.d.ts +39 -0
  184. package/dist/types/tools/memory/memoryAppendTool.d.ts +27 -0
  185. package/dist/types/tools/memory/memoryGetTool.d.ts +22 -0
  186. package/dist/types/tools/memory/memorySearchTool.d.ts +22 -0
  187. package/dist/types/tools/memory/shared.d.ts +106 -0
  188. package/dist/types/types/graph.d.ts +10 -3
  189. package/dist/types/utils/childAgentContext.d.ts +99 -0
  190. package/dist/types/utils/errors.d.ts +37 -0
  191. package/dist/types/utils/events.d.ts +21 -0
  192. package/dist/types/utils/finishReasons.d.ts +32 -0
  193. package/dist/types/utils/index.d.ts +1 -0
  194. package/dist/types/utils/logging.d.ts +2 -0
  195. package/dist/types/utils/toolCallNormalization.d.ts +44 -0
  196. package/package.json +6 -4
  197. package/src/agents/AgentContext.ts +12 -4
  198. package/src/common/__tests__/enum.test.ts +4 -2
  199. package/src/common/__tests__/spawnPath.test.ts +110 -0
  200. package/src/common/index.ts +1 -0
  201. package/src/common/spawnPath.ts +101 -0
  202. package/src/graphs/Graph.ts +95 -61
  203. package/src/graphs/HandoffRegistry.ts +48 -17
  204. package/src/graphs/MultiAgentGraph.ts +588 -327
  205. package/src/graphs/__tests__/HandoffRegistry.test.ts +4 -1
  206. package/src/graphs/__tests__/multi-agent-delegate.test.ts +61 -16
  207. package/src/graphs/__tests__/multi-agent-edges.test.ts +4 -2
  208. package/src/graphs/__tests__/multi-agent-nested-subgraph.test.ts +221 -0
  209. package/src/graphs/__tests__/structured-output.integration.test.ts +212 -118
  210. package/src/graphs/contextManagement.e2e.test.ts +1 -1
  211. package/src/graphs/phases/__tests__/flushLoop.test.ts +264 -0
  212. package/src/graphs/phases/__tests__/memoryFlushPhase.test.ts +37 -0
  213. package/src/graphs/phases/__tests__/runMemoryFlush.test.ts +150 -0
  214. package/src/graphs/phases/flushLoop.ts +303 -0
  215. package/src/graphs/phases/memoryFlushPhase.ts +209 -0
  216. package/src/index.ts +30 -1
  217. package/src/llm/bedrock/index.ts +4 -5
  218. package/src/memory/__tests__/citations.test.ts +61 -0
  219. package/src/memory/__tests__/compositeBackend.test.ts +79 -0
  220. package/src/memory/__tests__/isolation.test.ts +206 -0
  221. package/src/memory/__tests__/mmr.test.ts +148 -0
  222. package/src/memory/__tests__/mockBackend.ts +161 -0
  223. package/src/memory/__tests__/paths.test.ts +168 -0
  224. package/src/memory/__tests__/recallTracking.test.ts +96 -0
  225. package/src/memory/__tests__/temporalDecay.test.ts +151 -0
  226. package/src/memory/citations.ts +80 -0
  227. package/src/memory/compositeBackend.ts +99 -0
  228. package/src/memory/constants.ts +229 -0
  229. package/src/memory/embeddings.ts +188 -0
  230. package/src/memory/factory.ts +111 -0
  231. package/src/memory/index.ts +46 -0
  232. package/src/memory/migrate.ts +116 -0
  233. package/src/memory/mmr.ts +161 -0
  234. package/src/memory/paths.ts +258 -0
  235. package/src/memory/pgvectorStore.ts +324 -0
  236. package/src/memory/recallTracking.ts +127 -0
  237. package/src/memory/schema.sql +51 -0
  238. package/src/memory/temporalDecay.ts +134 -0
  239. package/src/memory/types.ts +185 -0
  240. package/src/nodes/ApprovalGateNode.ts +4 -10
  241. package/src/nodes/__tests__/ApprovalGateNode.test.ts +11 -20
  242. package/src/prompts/memoryFlushPrompt.ts +78 -0
  243. package/src/run.ts +17 -6
  244. package/src/scripts/test-bedrock-handoff-autonomous.ts +56 -20
  245. package/src/specs/agent-handoffs-bedrock.integration.test.ts +8 -5
  246. package/src/specs/agent-handoffs.test.ts +8 -2
  247. package/src/tools/AskUser.ts +7 -2
  248. package/src/tools/BrowserTools.ts +3 -5
  249. package/src/tools/ToolNode.ts +150 -13
  250. package/src/tools/__tests__/ToolApproval.test.ts +22 -9
  251. package/src/tools/approval/__tests__/constants.test.ts +1 -1
  252. package/src/tools/approval/constants.ts +2 -2
  253. package/src/tools/memory/__tests__/memoryTools.test.ts +205 -0
  254. package/src/tools/memory/index.ts +96 -0
  255. package/src/tools/memory/memoryAppendTool.ts +101 -0
  256. package/src/tools/memory/memoryGetTool.ts +53 -0
  257. package/src/tools/memory/memorySearchTool.ts +80 -0
  258. package/src/tools/memory/shared.ts +169 -0
  259. package/src/tools/search/search.test.ts +6 -1
  260. package/src/types/graph.ts +10 -3
  261. package/src/utils/__tests__/childAgentContext.test.ts +217 -0
  262. package/src/utils/__tests__/errors.test.ts +136 -0
  263. package/src/utils/__tests__/finishReasons.test.ts +55 -0
  264. package/src/utils/__tests__/toolCallNormalization.test.ts +181 -0
  265. package/src/utils/childAgentContext.ts +259 -0
  266. package/src/utils/errors.ts +115 -0
  267. package/src/utils/events.ts +37 -7
  268. package/src/utils/finishReasons.ts +40 -0
  269. package/src/utils/index.ts +1 -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
@@ -27,10 +27,14 @@ import { hasTaskTool, buildPostPruneNote, detectDocuments, shouldInjectMultiDocH
27
27
  import { ToolDiscoveryCache } from '../utils/toolDiscoveryCache.mjs';
28
28
  import { createPruneCalibration, applyCalibration, updatePruneCalibration } from '../utils/pruneCalibration.mjs';
29
29
  import { buildFileManifestBlock } from '../utils/fileManifest.mjs';
30
+ import { isLikelyContextOverflowError } from '../utils/errors.mjs';
30
31
  import { getChatModelClass, manualToolStreamProviders } from '../llm/providers.mjs';
31
32
  import { ToolNode, toolsCondition } from '../tools/ToolNode.mjs';
32
33
  import { ChatOpenAI, AzureChatOpenAI } from '../llm/openai/index.mjs';
33
34
  import { safeDispatchCustomEvent } from '../utils/events.mjs';
35
+ import { mwarn, mlog } from '../utils/logging.mjs';
36
+ import { normalizeMessageToolCalls } from '../utils/toolCallNormalization.mjs';
37
+ import { isTruncationReason } from '../utils/finishReasons.mjs';
34
38
  import { createSchemaOnlyTools } from '../tools/schema.mjs';
35
39
  import { prepareSchemaForProvider } from '../schemas/validate.mjs';
36
40
  import { AgentContext } from '../agents/AgentContext.mjs';
@@ -795,7 +799,7 @@ class StandardGraph extends Graph {
795
799
  const resolved = agentContext.resolveStructuredOutputMode();
796
800
  method = resolved.method;
797
801
  if (resolved.warnings.length > 0) {
798
- console.warn('[Graph] Structured output mode warnings:', resolved.warnings);
802
+ mwarn('[Graph] Structured output mode warnings:', resolved.warnings);
799
803
  }
800
804
  }
801
805
  else {
@@ -818,7 +822,7 @@ class StandardGraph extends Graph {
818
822
  const { schema: prepared, warnings } = prepareSchemaForProvider(schema, provider, structuredOutputConfig.strict !== false);
819
823
  preparedSchema = prepared;
820
824
  if (warnings.length > 0) {
821
- console.warn('[Graph] Schema preparation warnings:', warnings);
825
+ mwarn('[Graph] Schema preparation warnings:', warnings);
822
826
  }
823
827
  }
824
828
  // Use withStructuredOutput to bind the schema
@@ -888,7 +892,7 @@ class StandardGraph extends Graph {
888
892
  const errorMessage = typeof handleErrors === 'string'
889
893
  ? handleErrors
890
894
  : `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...`);
895
+ mwarn(`[Graph] Structured output attempt ${attempts} failed: ${lastError.message}. Retrying...`);
892
896
  // Add the error as a human message for context
893
897
  finalMessages = [
894
898
  ...finalMessages,
@@ -1038,7 +1042,7 @@ class StandardGraph extends Graph {
1038
1042
  const cachedDiscoveries = this._toolDiscoveryCache.getNewDiscoveries(messages);
1039
1043
  if (cachedDiscoveries.length > 0) {
1040
1044
  agentContext.markToolsAsDiscovered(cachedDiscoveries);
1041
- console.debug(`[Graph:ToolDiscovery] Cached ${cachedDiscoveries.length} new tools (total: ${this._toolDiscoveryCache.size})`);
1045
+ mlog(`[Graph:ToolDiscovery] Cached ${cachedDiscoveries.length} new tools (total: ${this._toolDiscoveryCache.size})`);
1042
1046
  }
1043
1047
  const toolsForBinding = agentContext.getToolsForBinding();
1044
1048
  // PERF: Detect subsequent ReAct iterations (tool results present in messages)
@@ -1057,8 +1061,8 @@ class StandardGraph extends Graph {
1057
1061
  clientOptions: effectiveClientOptions,
1058
1062
  });
1059
1063
  // 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'} | ` +
1064
+ mlog(`[createCallModel] Agent "${agentId}" invoking LLM | provider=${agentContext.provider} | ` +
1065
+ `model=${effectiveClientOptions.model ?? 'default'} | ` +
1062
1066
  `toolsForBinding=${toolsForBinding?.length ?? 0} | ` +
1063
1067
  `toolNames=[${(toolsForBinding ?? []).map((t) => t.name ?? 'unknown').join(', ')}]`);
1064
1068
  if (agentContext.systemRunnable) {
@@ -1070,7 +1074,15 @@ class StandardGraph extends Graph {
1070
1074
  if (!config.signal) {
1071
1075
  config.signal = this.signal;
1072
1076
  }
1073
- this.config = config;
1077
+ // First-writer-wins: `this.config` is used ONLY as a "has a run started"
1078
+ // existence flag by the dispatch* methods (they never read its value —
1079
+ // they read the current RunnableConfig from LangChain AsyncLocalStorage).
1080
+ // Unconditionally reassigning here races across concurrent child
1081
+ // subgraph.invoke() calls under parallel multi-agent handoffs; the last
1082
+ // writer wins, and any dispatch firing between writes would historically
1083
+ // have been tagged with the wrong child's metadata. Keeping the first
1084
+ // write pinned makes this a true flag, eliminating the race.
1085
+ this.config ??= config;
1074
1086
  let messagesToUse = messages;
1075
1087
  // ====================================================================
1076
1088
  // PRE-PRUNING DELEGATION CHECK
@@ -1136,13 +1148,13 @@ class StandardGraph extends Graph {
1136
1148
  const oldMessages = messages.slice(messages[0]?.getType() === 'system' ? 1 : 0, Math.max(1, messages.length - recentTurnCount));
1137
1149
  if (oldMessages.length > 0) {
1138
1150
  this._summaryInFlight = true;
1139
- console.debug(`[Graph:ProactiveSummary] Context at ${utilization.toFixed(1)}% (threshold ${threshold}%) — summarizing ${oldMessages.length} older msgs in background`);
1151
+ mlog(`[Graph:ProactiveSummary] Context at ${utilization.toFixed(1)}% (threshold ${threshold}%) — summarizing ${oldMessages.length} older msgs in background`);
1140
1152
  agentContext
1141
1153
  .summarizeCallback(oldMessages)
1142
1154
  .then((updated) => {
1143
1155
  if (updated != null && updated !== '') {
1144
1156
  this._cachedRunSummary = updated;
1145
- console.debug(`[Graph:ProactiveSummary] Background summary ready (len=${updated.length})`);
1157
+ mlog(`[Graph:ProactiveSummary] Background summary ready (len=${updated.length})`);
1146
1158
  }
1147
1159
  })
1148
1160
  .catch((err) => {
@@ -1318,7 +1330,7 @@ class StandardGraph extends Graph {
1318
1330
  viewIdx++;
1319
1331
  }
1320
1332
  agentContext.indexTokenCountMap = viewTokenMap;
1321
- console.debug(`[Graph:Compaction] ${messages.length}→${viewParts.length} msgs | ` +
1333
+ mlog(`[Graph:Compaction] ${messages.length}→${viewParts.length} msgs | ` +
1322
1334
  `compacted=${compactedMessages.length} window=${recentMessages.length} | ` +
1323
1335
  `summary=${summarySource} | budget=${usedTokens}/${recentBudget}` +
1324
1336
  (fileManifestTokens > 0
@@ -1332,7 +1344,7 @@ class StandardGraph extends Graph {
1332
1344
  if (shouldSummarize) {
1333
1345
  if (this._summaryInFlight) {
1334
1346
  this._pendingMessagesToRefine.push(...compactedMessages);
1335
- console.debug(`[Graph:Compaction] Summary in-flight, queued ${compactedMessages.length} msgs (pending=${this._pendingMessagesToRefine.length})`);
1347
+ mlog(`[Graph:Compaction] Summary in-flight, queued ${compactedMessages.length} msgs (pending=${this._pendingMessagesToRefine.length})`);
1336
1348
  }
1337
1349
  else {
1338
1350
  this._summaryInFlight = true;
@@ -1373,7 +1385,7 @@ class StandardGraph extends Graph {
1373
1385
  const { messages: dedupedMessages, removedCount } = deduplicateSystemMessages(messagesToUse);
1374
1386
  if (removedCount > 0) {
1375
1387
  messagesToUse = dedupedMessages;
1376
- console.debug(`[Graph:Dedup] Removed ${removedCount} duplicate system message(s)`);
1388
+ mlog(`[Graph:Dedup] Removed ${removedCount} duplicate system message(s)`);
1377
1389
  }
1378
1390
  let finalMessages = messagesToUse;
1379
1391
  if (agentContext.useLegacyContent) {
@@ -1537,18 +1549,12 @@ class StandardGraph extends Graph {
1537
1549
  }, config);
1538
1550
  }
1539
1551
  catch (primaryError) {
1540
- // Check if this is a "input too long" error from Bedrock/Anthropic
1541
- const errorMessage = primaryError.message.toLowerCase();
1542
- const isInputTooLongError = errorMessage.includes('too long') ||
1543
- errorMessage.includes('input is too long') ||
1544
- errorMessage.includes('context length') ||
1545
- errorMessage.includes('maximum context') ||
1546
- errorMessage.includes('validationexception') ||
1547
- errorMessage.includes('prompt is too long');
1552
+ const errorMessage = primaryError.message;
1553
+ const isInputTooLongError = isLikelyContextOverflowError(errorMessage);
1548
1554
  // Log when we detect the error
1549
1555
  if (isInputTooLongError) {
1550
- console.warn('[Graph] Detected input too long error:', errorMessage.substring(0, 200));
1551
- console.warn('[Graph] Checking emergency pruning conditions:', {
1556
+ mwarn('[Graph] Detected input too long error:', errorMessage.substring(0, 200));
1557
+ mwarn('[Graph] Checking emergency pruning conditions:', {
1552
1558
  hasPruneMessages: !!agentContext.pruneMessages,
1553
1559
  hasTokenCounter: !!agentContext.tokenCounter,
1554
1560
  maxContextTokens: agentContext.maxContextTokens,
@@ -1568,12 +1574,12 @@ class StandardGraph extends Graph {
1568
1574
  if (result)
1569
1575
  break; // Exit if we got a result
1570
1576
  const reducedMaxTokens = Math.floor(agentContext.maxContextTokens * reductionFactor);
1571
- console.warn(`[Graph] Input too long. Retrying with ${reductionFactor * 100}% context (${reducedMaxTokens} tokens)...`);
1577
+ mwarn(`[Graph] Input too long. Retrying with ${reductionFactor * 100}% context (${reducedMaxTokens} tokens)...`);
1572
1578
  // Build fresh indexTokenCountMap if missing/incomplete
1573
1579
  // This is needed when messages were dynamically added without updating the token map
1574
1580
  let tokenMapForPruning = agentContext.indexTokenCountMap;
1575
1581
  if (Object.keys(tokenMapForPruning).length < messages.length) {
1576
- console.warn('[Graph] Building fresh token count map for emergency pruning...');
1582
+ mwarn('[Graph] Building fresh token count map for emergency pruning...');
1577
1583
  tokenMapForPruning = {};
1578
1584
  for (let i = 0; i < messages.length; i++) {
1579
1585
  tokenMapForPruning[i] = agentContext.tokenCounter(messages[i]);
@@ -1593,7 +1599,7 @@ class StandardGraph extends Graph {
1593
1599
  });
1594
1600
  // Skip if we can't fit any messages
1595
1601
  if (reducedMessages.length === 0) {
1596
- console.warn(`[Graph] Cannot fit any messages at ${reductionFactor * 100}% reduction, trying next level...`);
1602
+ mwarn(`[Graph] Cannot fit any messages at ${reductionFactor * 100}% reduction, trying next level...`);
1597
1603
  continue;
1598
1604
  }
1599
1605
  // Calculate how many messages were pruned and estimate context timeframe
@@ -1648,12 +1654,10 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1648
1654
  console.info(`[Graph] ✅ Retry successful at ${reductionFactor * 100}% with ${reducedMessages.length} messages (reduced from ${finalMessages.length})`);
1649
1655
  }
1650
1656
  catch (retryError) {
1651
- const retryErrorMsg = retryError.message.toLowerCase();
1652
- const stillTooLong = retryErrorMsg.includes('too long') ||
1653
- retryErrorMsg.includes('context length') ||
1654
- retryErrorMsg.includes('validationexception');
1657
+ const retryErrorMsg = retryError.message;
1658
+ const stillTooLong = isLikelyContextOverflowError(retryErrorMsg);
1655
1659
  if (stillTooLong && reductionFactor > 0.1) {
1656
- console.warn(`[Graph] Still too long at ${reductionFactor * 100}%, trying more aggressive pruning...`);
1660
+ mwarn(`[Graph] Still too long at ${reductionFactor * 100}%, trying more aggressive pruning...`);
1657
1661
  }
1658
1662
  else {
1659
1663
  console.error(`[Graph] Retry at ${reductionFactor * 100}% failed:`, retryError.message);
@@ -1713,6 +1717,20 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1713
1717
  * handled everything — both paths become no-ops.
1714
1718
  */
1715
1719
  const responseMessage = result.messages?.[0];
1720
+ // Tool-call name normalization — catches LLM output that names tools
1721
+ // with wrong delimiters (outlook/operations), prefixes
1722
+ // (functions.outlook_operations), case drift, counter suffixes, or
1723
+ // empty names recoverable from the tool_call id. Mutates in place so
1724
+ // the downstream ToolNode dispatch sees the corrected names.
1725
+ if (responseMessage && agentContext.toolMap) {
1726
+ const allowedNames = new Set(Object.keys(agentContext.toolMap));
1727
+ if (allowedNames.size > 0) {
1728
+ const rewrote = normalizeMessageToolCalls(responseMessage, allowedNames);
1729
+ if (rewrote) {
1730
+ mlog(`[Graph] normalized tool_call names on agent "${agentId}" response`);
1731
+ }
1732
+ }
1733
+ }
1716
1734
  const toolCalls = responseMessage
1717
1735
  ?.tool_calls;
1718
1736
  const hasToolCalls = Array.isArray(toolCalls) && toolCalls.length > 0;
@@ -1799,12 +1817,20 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1799
1817
  const meta = finalMsg.response_metadata;
1800
1818
  // Bedrock streaming nests stopReason inside messageStop: { stopReason: '...' }
1801
1819
  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
1820
+ const nextReason = meta.finish_reason ?? // OpenAI/Azure
1821
+ meta.stop_reason ?? // Anthropic direct API
1822
+ meta.stopReason ?? // Bedrock invoke (non-streaming)
1823
+ messageStop?.stopReason ?? // Bedrock streaming
1824
+ meta.finishReason; // VertexAI/Google
1825
+ // Sticky on truncation: a single Graph instance is reused across
1826
+ // every scoped-subgraph inner node invocation (see MultiAgentGraph
1827
+ // buildScopedSubgraph). If an earlier inner node hit max_tokens
1828
+ // but a later inner node finished cleanly, the host's continuation layer
1829
+ // would miss the truncation signal unless we preserve it. Keep the
1830
+ // truncation reason pinned so the outer caller can retry.
1831
+ if (!isTruncationReason(this.lastFinishReason)) {
1832
+ this.lastFinishReason = nextReason;
1833
+ }
1808
1834
  }
1809
1835
  this.cleanupSignalListener();
1810
1836
  // DEFERRED STRUCTURED OUTPUT: When the agent has tools AND structured output configured,
@@ -1852,7 +1878,7 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1852
1878
  // but we couldn't format the output as structured JSON.
1853
1879
  // Return the unstructured text response from attemptInvoke.
1854
1880
  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');
1881
+ mwarn('[Graph] Falling back to unstructured response from tool-use phase');
1856
1882
  return result;
1857
1883
  }
1858
1884
  }
@@ -1868,7 +1894,10 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1868
1894
  const agentNode = `${AGENT}${agentId}`;
1869
1895
  const toolNode = `${TOOLS}${agentId}`;
1870
1896
  const routeMessage = (state, config) => {
1871
- this.config = config;
1897
+ // First-writer-wins — see note in createCallModel. `this.config` is an
1898
+ // existence flag only; assigning unconditionally would race under
1899
+ // parallel child subgraph.invoke().
1900
+ this.config ??= config;
1872
1901
  return toolsCondition(state, toolNode, this.invokedToolIds);
1873
1902
  };
1874
1903
  const StateAnnotation = Annotation.Root({
@@ -1906,10 +1935,16 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1906
1935
  default: () => [],
1907
1936
  }),
1908
1937
  });
1938
+ // Pass compileOptions (including the HITL checkpointer) to the OUTER
1939
+ // workflow — not just the inner agent subgraph. hasInterrupts() calls
1940
+ // getState() on the outer compiled graph; without a checkpointer here,
1941
+ // getState reports zero tasks and the HITL interrupt/resume loop breaks
1942
+ // out immediately even though interrupt() fired correctly inside the
1943
+ // agent subgraph.
1909
1944
  const workflow = new StateGraph(StateAnnotation)
1910
1945
  .addNode(this.defaultAgentId, agentNode, { ends: [END] })
1911
1946
  .addEdge(START, this.defaultAgentId)
1912
- .compile();
1947
+ .compile(this.compileOptions);
1913
1948
  return workflow;
1914
1949
  }
1915
1950
  /**
@@ -1980,12 +2015,16 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
1980
2015
  }
1981
2016
  catch (_e) {
1982
2017
  /** 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}`);
2018
+ mlog(`[dispatchRunStep] Could not resolve agentId from metadata.langgraph_node="${metadata.langgraph_node}": ${_e.message}`);
1984
2019
  }
1985
2020
  }
1986
2021
  this.contentData.push(runStep);
1987
2022
  this.contentIndexMap.set(stepId, runStep.index);
1988
- await safeDispatchCustomEvent(GraphEvents.ON_RUN_STEP, runStep, this.config);
2023
+ // Pass undefined so safeDispatchCustomEvent resolves the runnable config
2024
+ // from LangChain's AsyncLocalStorage. Using the shared `this.config` would
2025
+ // race across concurrent child subgraph.invoke calls under parallel
2026
+ // multi-agent handoffs and tag events with the wrong child's spawnKey.
2027
+ await safeDispatchCustomEvent(GraphEvents.ON_RUN_STEP, runStep);
1989
2028
  return stepId;
1990
2029
  }
1991
2030
  async handleToolCallCompleted(data, metadata, omitOutput) {
@@ -2093,7 +2132,7 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
2093
2132
  throw new Error('No config provided');
2094
2133
  }
2095
2134
  if (!data.id) {
2096
- console.warn('No Tool ID provided for Tool Error');
2135
+ mwarn('No Tool ID provided for Tool Error');
2097
2136
  return;
2098
2137
  }
2099
2138
  const stepId = graph.toolCallStepIds.get(data.id) ?? '';
@@ -2141,7 +2180,10 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
2141
2180
  id,
2142
2181
  delta,
2143
2182
  };
2144
- await safeDispatchCustomEvent(GraphEvents.ON_RUN_STEP_DELTA, runStepDelta, this.config);
2183
+ // See dispatchRunStep note: do not pass `this.config`. The implicit
2184
+ // AsyncLocalStorage config is the correct per-async-branch source under
2185
+ // parallel handoffs.
2186
+ await safeDispatchCustomEvent(GraphEvents.ON_RUN_STEP_DELTA, runStepDelta);
2145
2187
  }
2146
2188
  async dispatchMessageDelta(id, delta) {
2147
2189
  if (!this.config) {
@@ -2151,7 +2193,8 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
2151
2193
  id,
2152
2194
  delta,
2153
2195
  };
2154
- await safeDispatchCustomEvent(GraphEvents.ON_MESSAGE_DELTA, messageDelta, this.config);
2196
+ // See dispatchRunStep note.
2197
+ await safeDispatchCustomEvent(GraphEvents.ON_MESSAGE_DELTA, messageDelta);
2155
2198
  }
2156
2199
  dispatchReasoningDelta = async (stepId, delta) => {
2157
2200
  if (!this.config) {
@@ -2161,7 +2204,8 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
2161
2204
  id: stepId,
2162
2205
  delta,
2163
2206
  };
2164
- await safeDispatchCustomEvent(GraphEvents.ON_REASONING_DELTA, reasoningDelta, this.config);
2207
+ // See dispatchRunStep note.
2208
+ await safeDispatchCustomEvent(GraphEvents.ON_REASONING_DELTA, reasoningDelta);
2165
2209
  };
2166
2210
  }
2167
2211