@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
@@ -0,0 +1,22 @@
1
+ import { type MemoryToolBinding } from './shared';
2
+ export declare function createMemoryGetTool(binding: MemoryToolBinding): import("@langchain/core/tools").DynamicStructuredTool<import("zod").ZodObject<{
3
+ path: import("zod").ZodString;
4
+ from: import("zod").ZodOptional<import("zod").ZodNumber>;
5
+ lines: import("zod").ZodOptional<import("zod").ZodNumber>;
6
+ }, "strip", import("zod").ZodTypeAny, {
7
+ path: string;
8
+ from?: number | undefined;
9
+ lines?: number | undefined;
10
+ }, {
11
+ path: string;
12
+ from?: number | undefined;
13
+ lines?: number | undefined;
14
+ }>, {
15
+ path: string;
16
+ from?: number | undefined;
17
+ lines?: number | undefined;
18
+ }, {
19
+ path: string;
20
+ from?: number | undefined;
21
+ lines?: number | undefined;
22
+ }, string>;
@@ -0,0 +1,22 @@
1
+ import { type MemoryToolBinding } from './shared';
2
+ export declare function createMemorySearchTool(binding: MemoryToolBinding): import("@langchain/core/tools").DynamicStructuredTool<import("zod").ZodObject<{
3
+ query: import("zod").ZodString;
4
+ maxResults: import("zod").ZodOptional<import("zod").ZodNumber>;
5
+ minScore: import("zod").ZodOptional<import("zod").ZodNumber>;
6
+ }, "strip", import("zod").ZodTypeAny, {
7
+ query: string;
8
+ maxResults?: number | undefined;
9
+ minScore?: number | undefined;
10
+ }, {
11
+ query: string;
12
+ maxResults?: number | undefined;
13
+ minScore?: number | undefined;
14
+ }>, {
15
+ query: string;
16
+ maxResults?: number | undefined;
17
+ minScore?: number | undefined;
18
+ }, {
19
+ query: string;
20
+ maxResults?: number | undefined;
21
+ minScore?: number | undefined;
22
+ }, string>;
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Shared Zod schemas + helpers for the memory tool family.
3
+ *
4
+ * The tool schemas deliberately do NOT expose `agent_id` or `user_id`. Scope
5
+ * is captured in a closure at tool construction time by {@link buildMemoryTools},
6
+ * so even a hallucinated tool call with extra fields cannot influence it.
7
+ */
8
+ import { z } from 'zod';
9
+ import type { MemoryAppendInput, MemoryBackend, MemoryEntry, MemoryScope } from '@/memory/types';
10
+ export declare const MemorySearchSchema: z.ZodObject<{
11
+ query: z.ZodString;
12
+ maxResults: z.ZodOptional<z.ZodNumber>;
13
+ minScore: z.ZodOptional<z.ZodNumber>;
14
+ }, "strip", z.ZodTypeAny, {
15
+ query: string;
16
+ maxResults?: number | undefined;
17
+ minScore?: number | undefined;
18
+ }, {
19
+ query: string;
20
+ maxResults?: number | undefined;
21
+ minScore?: number | undefined;
22
+ }>;
23
+ export declare const MemoryGetSchema: z.ZodObject<{
24
+ path: z.ZodString;
25
+ from: z.ZodOptional<z.ZodNumber>;
26
+ lines: z.ZodOptional<z.ZodNumber>;
27
+ }, "strip", z.ZodTypeAny, {
28
+ path: string;
29
+ from?: number | undefined;
30
+ lines?: number | undefined;
31
+ }, {
32
+ path: string;
33
+ from?: number | undefined;
34
+ lines?: number | undefined;
35
+ }>;
36
+ export declare const MemoryAppendSchema: z.ZodObject<{
37
+ path: z.ZodString;
38
+ content: z.ZodString;
39
+ }, "strip", z.ZodTypeAny, {
40
+ content: string;
41
+ path: string;
42
+ }, {
43
+ content: string;
44
+ path: string;
45
+ }>;
46
+ export type MemorySearchArgs = z.infer<typeof MemorySearchSchema>;
47
+ export type MemoryGetArgs = z.infer<typeof MemoryGetSchema>;
48
+ export type MemoryAppendArgs = z.infer<typeof MemoryAppendSchema>;
49
+ /** Shape returned by `memory_search` — serialised as the tool result string. */
50
+ export interface MemorySearchToolResult {
51
+ results: Array<Pick<MemoryEntry, 'id' | 'path' | 'content' | 'score' | 'createdAt'> & {
52
+ citation?: string;
53
+ }>;
54
+ disabled?: boolean;
55
+ unavailable?: boolean;
56
+ error?: string;
57
+ warning?: string;
58
+ action?: string;
59
+ }
60
+ /** Shape returned by `memory_get`. */
61
+ export interface MemoryGetToolResult {
62
+ path: string;
63
+ text: string;
64
+ disabled?: boolean;
65
+ error?: string;
66
+ }
67
+ export declare function buildMemorySearchUnavailableResult(error: string | undefined): MemorySearchToolResult;
68
+ /**
69
+ * Clamp a ranked result list to a total character budget.
70
+ * Ported from upstream `tools.citations.ts::clampResultsByInjectedChars`.
71
+ */
72
+ export declare function clampResultsByInjectedChars<T extends {
73
+ content: string;
74
+ }>(results: T[], maxInjectedChars?: number): T[];
75
+ export interface MemoryToolBinding {
76
+ backend: MemoryBackend;
77
+ scope: MemoryScope;
78
+ maxInjectedChars?: number;
79
+ /** Phase 2 — per-call search options propagated into backend.search. */
80
+ searchOptions?: {
81
+ mmr?: {
82
+ enabled?: boolean;
83
+ lambda?: number;
84
+ };
85
+ temporalDecay?: {
86
+ enabled?: boolean;
87
+ halfLifeDays?: number;
88
+ };
89
+ citations?: 'on' | 'off' | 'auto';
90
+ };
91
+ /** Phase 2 — optional best-effort recall recorder. */
92
+ recallTracker?: {
93
+ record(params: {
94
+ agentId: string;
95
+ query: string;
96
+ hits: Array<{
97
+ id: string;
98
+ path: string;
99
+ score: number;
100
+ }>;
101
+ }): Promise<void>;
102
+ };
103
+ }
104
+ export declare function assertAppendAllowed(path: string): void;
105
+ /** Normalise an append call into the backend input shape. */
106
+ export declare function toAppendInput(args: MemoryAppendArgs): MemoryAppendInput;
@@ -294,6 +294,13 @@ export type GraphEdge = {
294
294
  * Defaults to DEFAULT_HANDOFF_MAX_RESULT_CHARS (32768 chars, ~8192 tokens).
295
295
  */
296
296
  maxResultChars?: number;
297
+ /**
298
+ * For handoff edges: When true, the child agent receives the full parent
299
+ * conversation history plus the orchestrator's instructions appended.
300
+ * When false (default), the child only receives the orchestrator's scoped
301
+ * instructions — isolated from the parent conversation.
302
+ */
303
+ passthrough?: boolean;
297
304
  /**
298
305
  * Approval gate configuration for sequence edges.
299
306
  * When set, inserts an approval gate node between source and destination.
@@ -544,7 +551,7 @@ export interface AgentInputs {
544
551
  discoveredTools?: string[];
545
552
  /**
546
553
  * Optional callback for summarizing messages that were pruned from context.
547
- * When provided, discarded messages are summarized by the caller (e.g., Ranger)
554
+ * When provided, discarded messages are summarized by the host caller
548
555
  * using a cheap LLM call, and the summary is prepended to the context.
549
556
  */
550
557
  summarizeCallback?: (messagesToRefine: import('@langchain/core/messages').BaseMessage[]) => Promise<string | undefined>;
@@ -552,7 +559,7 @@ export interface AgentInputs {
552
559
  * Pre-existing summary text loaded from persistent storage (MongoDB/Redis).
553
560
  * When provided, this summary is injected into the initial message context
554
561
  * so the agent has prior conversation history even on new turns.
555
- * Set by Ranger's SummaryStore when resuming a conversation.
562
+ * Set by the host's summary store when resuming a conversation.
556
563
  */
557
564
  persistedSummary?: string;
558
565
  /**
@@ -573,7 +580,7 @@ export interface AgentInputs {
573
580
  * - file_search (RAG semantic search over embedded files)
574
581
  * - content_tool read (by contentId for exact file retrieval)
575
582
  *
576
- * Built by the orchestrator (e.g., Ranger) from message_file_map
583
+ * Built by the host orchestrator from message_file_map
577
584
  * and metadata.context_files across all conversation messages.
578
585
  */
579
586
  fileManifest?: FileManifestEntry[];
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Child-agent context preparation utilities.
3
+ *
4
+ * When a parent agent invokes a child agent — via handoff, sequence edge,
5
+ * or scoped subgraph — the child cannot just receive `state.messages`
6
+ * verbatim. The parent's conversation contains tool_use/tool_result blocks
7
+ * that are (a) often incompatible with the child's tool registry, and
8
+ * (b) actively harmful to the child's ability to reason cleanly about its
9
+ * own task (noise → schema confusion → malformed tool_use).
10
+ *
11
+ * This module provides the two canonical strategies, extracted from
12
+ * `MultiAgentGraph` so they can be unit-tested in isolation and reused by
13
+ * future sub-agent orchestrators:
14
+ *
15
+ * 1. `prepareHandoffMessages` — "cleaned parent history"
16
+ * Used when the child still needs the orchestrator's context (it's
17
+ * the handoff target). Drops orphaned tool_use, compacts paired
18
+ * tool_use/tool_result into text summaries, and guarantees the tail
19
+ * is a HumanMessage so Bedrock/VertexAI won't reject the conversation
20
+ * with "assistant message prefill" errors.
21
+ *
22
+ * 2. `prepareIsolatedChildMessages` — "fresh session"
23
+ * Used for downstream sequence-node children inside a scoped subgraph.
24
+ * The child sees only the original user request plus a synthetic
25
+ * HumanMessage summarizing the upstream agent's final text output and
26
+ * directing the child to act. Raw upstream tool_use/tool_result blocks
27
+ * are discarded.
28
+ *
29
+ * Both helpers are pure functions over message arrays — no I/O, no
30
+ * LangGraph coupling — so they can be exercised by unit tests with
31
+ * synthetic message fixtures.
32
+ */
33
+ import type { BaseMessage } from '@langchain/core/messages';
34
+ /**
35
+ * Prefix injected in front of a trailing AIMessage when we flip it to a
36
+ * HumanMessage to satisfy provider "last message must be user" rules.
37
+ */
38
+ export declare const HANDOFF_TAIL_CONTEXT_PREFIX = "[Context from orchestrator]: ";
39
+ /**
40
+ * Directive task-framing wrapper for downstream scoped-subgraph children.
41
+ *
42
+ * Design notes — each line is load-bearing:
43
+ * - "Prior step output" names the upstream role without leaking the
44
+ * agent's internal id.
45
+ * - "You MUST now perform..." replaces ambiguity with obligation.
46
+ * - "system instructions" references the agent's stored system prompt
47
+ * as the source of task definition — so operators can tune behavior
48
+ * via data, not code.
49
+ * - The tool-first clause prevents small/fast models from stalling on a
50
+ * text-only acknowledgement when a tool action is expected.
51
+ */
52
+ export declare function buildIsolatedChildPrompt(upstreamText: string): string;
53
+ /**
54
+ * Prepare messages for a handoff child agent.
55
+ *
56
+ * Handles two problems that break Bedrock/Anthropic conversations:
57
+ *
58
+ * 1. **Orphaned tool_use**: The parent's AI message contains a `tool_use`
59
+ * block for the handoff tool itself, with no matching `tool_result`.
60
+ * Providers (Bedrock/Anthropic) reject this.
61
+ *
62
+ * 2. **Paired tool_use/tool_result in history**: The child may not have
63
+ * the same tools as the parent. Bedrock requires `toolConfig` when any
64
+ * tool_use/tool_result blocks exist in the history. Compacting these
65
+ * into text summaries avoids the requirement and reduces context bloat.
66
+ *
67
+ * Also ensures the tail is a HumanMessage — some providers reject a
68
+ * conversation that ends with an assistant message.
69
+ *
70
+ * @param messages - Current state messages from the parent
71
+ * @returns A sanitized copy, safe to pass to any provider as the child's
72
+ * input regardless of which tools the child has registered.
73
+ */
74
+ export declare function prepareHandoffMessages(messages: BaseMessage[]): BaseMessage[];
75
+ /**
76
+ * Build an ISOLATED message context for a downstream scoped-subgraph node.
77
+ *
78
+ * Unlike `prepareHandoffMessages` (which cleans up tool_use artifacts but
79
+ * preserves most of the parent history), this helper produces a fresh
80
+ * minimal context containing only:
81
+ *
82
+ * 1. The original user request (first HumanMessage in the history)
83
+ * 2. A synthetic HumanMessage summarizing the upstream agent's final
84
+ * text output and directing the downstream agent to act on it
85
+ *
86
+ * Tool_use / tool_result blocks from the upstream agent are discarded —
87
+ * the downstream agent shouldn't reason about how the upstream agent did
88
+ * its work, only about the result.
89
+ *
90
+ * This "fresh subagent session" pattern is the primary defense against
91
+ * schema confusion / malformed tool_use JSON that occurs when downstream
92
+ * models see a noisy upstream conversation.
93
+ *
94
+ * Defensive fallback: if the messages array contains neither a user
95
+ * message nor a non-empty upstream AI message, return the input unchanged
96
+ * so the caller still has something to invoke on. This only matters for
97
+ * malformed state fixtures in tests.
98
+ */
99
+ export declare function prepareIsolatedChildMessages(messages: BaseMessage[]): BaseMessage[];
@@ -1,6 +1,27 @@
1
1
  import type { RunnableConfig } from '@langchain/core/runnables';
2
+ /**
3
+ * Returns the RunnableConfig currently active in LangChain's AsyncLocalStorage,
4
+ * or undefined if none is installed. This is the per-async-branch config that
5
+ * LangGraph installs when entering a node — it carries the correct
6
+ * `metadata.spawnKey` for child subgraph invocations inside `Promise.all`
7
+ * parallel handoffs.
8
+ *
9
+ * Prefer this over any Graph-instance-cached config (e.g. `this.config`)
10
+ * when dispatching events from code that may run concurrently across multiple
11
+ * child subgraphs. An instance-level cache is shared state and races between
12
+ * siblings — the last child to enter wins, so events fire with the wrong
13
+ * child's metadata and the backend routes them to the wrong spawnKey.
14
+ */
15
+ export declare function getCurrentRunnableConfig(): RunnableConfig | undefined;
2
16
  /**
3
17
  * Safely dispatches a custom event and properly awaits it to avoid
4
18
  * race conditions where events are dispatched after run cleanup.
19
+ *
20
+ * **Parallel-handoff correctness:** callers should prefer passing
21
+ * `undefined` (or the per-node runtime config). When `config` is omitted,
22
+ * LangChain's `ensureConfig` reads the current RunnableConfig from
23
+ * AsyncLocalStorage, which is correctly isolated per async branch under
24
+ * `Promise.all`. Passing a stale instance-cached config overrides that
25
+ * implicit config's metadata and cross-contaminates parallel children.
5
26
  */
6
27
  export declare function safeDispatchCustomEvent(event: string, payload: unknown, config?: RunnableConfig): Promise<void>;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Finish-reason constants and helpers.
3
+ *
4
+ * LLM providers emit different keys (`finish_reason`, `stop_reason`,
5
+ * `stopReason`, `finishReason`) and different values for the same concept.
6
+ * This module is the single source of truth for detecting *truncation* —
7
+ * i.e., the model hit its output budget and the response is incomplete.
8
+ *
9
+ * Used by:
10
+ * - `Graph.ts` — sticky `lastFinishReason` across inner subgraph invokes,
11
+ * so host's continuation retry can detect truncation that happens
12
+ * inside a scoped-subgraph child node.
13
+ * - Any future continuation / auto-retry logic added to agents.
14
+ *
15
+ * Kept as a small utils module (instead of inline in Graph.ts) so that
16
+ * additional callers — e.g., structured output recovery, sub-agent
17
+ * orchestrators — can reuse the exact same detection logic without drift.
18
+ */
19
+ /**
20
+ * Canonical set of finish-reason strings that mean "output was truncated".
21
+ *
22
+ * Covers:
23
+ * - `max_tokens` — Anthropic direct API, Bedrock
24
+ * - `length` — OpenAI/Azure
25
+ * - `MAX_TOKENS` — VertexAI/Google (uppercased enum)
26
+ */
27
+ export declare const TRUNCATION_FINISH_REASONS: ReadonlySet<string>;
28
+ /**
29
+ * @returns true when the given finish/stop reason indicates the response
30
+ * was cut short by the output token budget.
31
+ */
32
+ export declare function isTruncationReason(reason: string | undefined | null): boolean;
@@ -1 +1,3 @@
1
+ export declare const mlog: (...args: any[]) => void;
2
+ export declare const mwarn: (...args: any[]) => void;
1
3
  export declare function setupLogging(logFileName: string): void;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Tool-call name normalization for malformed LLM tool_use outputs.
3
+ *
4
+ * LLMs — especially smaller / faster models — frequently emit tool_use
5
+ * blocks with names that don't exactly match the registered tool name:
6
+ *
7
+ * - Wrong delimiter: `outlook/operations` vs `outlook_operations`
8
+ * - Function-prefix style: `functions.outlook_operations`
9
+ * - Case drift: `Outlook_Operations`
10
+ * - Counter suffix: `outlook_operations_1`
11
+ * - Missing name, only id: `{name: "", id: "tool_outlook_operations_42"}`
12
+ *
13
+ * Before this normalization layer, any of the above caused the LangGraph
14
+ * ToolNode to throw "Tool X not found" and the whole turn to fail. With
15
+ * normalization, we resolve to the correct registered name case-insensitively
16
+ * and transparently fix the tool_call in place.
17
+ *
18
+ * Resolution order:
19
+ * 1. Exact match
20
+ * 2. Normalized delimiter + exact
21
+ * 3. Case-insensitive match
22
+ * 4. Structured candidates (strip prefixes, take suffix segments)
23
+ * 5. Infer from tool_call id (strip trailing digits, function/tool prefix)
24
+ *
25
+ * Any unresolvable tool_call is left as-is — the downstream ToolNode will
26
+ * fail with its usual error and the auto-recovery path kicks in.
27
+ */
28
+ /**
29
+ * Produce the best allowed tool name for a raw LLM tool_use name.
30
+ * Returns the original name unchanged if no resolution is possible —
31
+ * the downstream executor will then fail with its normal error path.
32
+ */
33
+ export declare function normalizeToolCallName(rawName: string, allowedToolNames: Set<string>, rawToolCallId?: string): string;
34
+ /**
35
+ * In-place normalization of all tool_calls on an AIMessage-like object.
36
+ *
37
+ * Applies `normalizeToolCallName` to each tool_call's `name` field using the
38
+ * provided allowed-tool set (derived from the agent's toolMap keys). Also
39
+ * rewrites the `name` field inside any content blocks of type `tool_use` so
40
+ * that downstream providers see the corrected name.
41
+ *
42
+ * Returns `true` if any name was rewritten.
43
+ */
44
+ export declare function normalizeMessageToolCalls(message: unknown, allowedToolNames: Set<string>): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@illuma-ai/agents",
3
- "version": "1.1.28",
3
+ "version": "1.3.0",
4
4
  "main": "./dist/cjs/main.cjs",
5
5
  "module": "./dist/esm/main.mjs",
6
6
  "types": "./dist/types/index.d.ts",
@@ -123,6 +123,8 @@
123
123
  "dependencies": {
124
124
  "@anthropic-ai/sdk": "^0.73.0",
125
125
  "@aws-sdk/client-bedrock-runtime": "^3.980.0",
126
+ "@illuma-ai/observability-langchain": "^0.2.1",
127
+ "@illuma-ai/observability-otel": "^0.2.1",
126
128
  "@langchain/anthropic": "^0.3.26",
127
129
  "@langchain/aws": "^0.1.15",
128
130
  "@langchain/core": "^0.3.80",
@@ -134,8 +136,6 @@
134
136
  "@langchain/openai": "0.5.18",
135
137
  "@langchain/textsplitters": "^0.1.0",
136
138
  "@langchain/xai": "^0.0.3",
137
- "@illuma-ai/observability-langchain": "^0.2.1",
138
- "@illuma-ai/observability-otel": "^0.2.1",
139
139
  "@opentelemetry/sdk-node": "^0.207.0",
140
140
  "@scarf/scarf": "^1.4.0",
141
141
  "@toon-format/toon": "^2.1.0",
@@ -148,7 +148,8 @@
148
148
  "mathjs": "^15.1.0",
149
149
  "nanoid": "^3.3.7",
150
150
  "okapibm25": "^1.4.1",
151
- "openai": "5.8.2"
151
+ "openai": "5.8.2",
152
+ "pg": "^8.20.0"
152
153
  },
153
154
  "imports": {
154
155
  "@/*": "./src/*",
@@ -166,6 +167,7 @@
166
167
  "@types/jest": "^30.0.0",
167
168
  "@types/node": "^20.14.11",
168
169
  "@types/node-fetch": "^2.6.13",
170
+ "@types/pg": "^8.20.0",
169
171
  "@types/yargs-parser": "^21.0.3",
170
172
  "@typescript-eslint/eslint-plugin": "^8.24.0",
171
173
  "@typescript-eslint/parser": "^8.24.0",
@@ -639,10 +639,18 @@ export class AgentContext {
639
639
  lines.push('');
640
640
  lines.push('### Rules');
641
641
  lines.push('1. **Stay focused** — Do your assigned task, nothing else.');
642
- lines.push('2. **Complete the task** — Your final message will be automatically reported back.');
643
- lines.push('3. **Be autonomous** — Execute directly without asking for user confirmation. Use your tools and best judgment.');
644
- lines.push('4. **No placeholders** — Never generate fake or placeholder data. If you cannot retrieve real data, say so.');
645
- lines.push('5. **No side effects** — Do not send messages, emails, or notifications unless explicitly tasked to do so.');
642
+ lines.push(
643
+ '2. **Complete the task** — Your final message will be automatically reported back.'
644
+ );
645
+ lines.push(
646
+ '3. **Be autonomous** — Execute directly without asking for user confirmation. Use your tools and best judgment.'
647
+ );
648
+ lines.push(
649
+ '4. **No placeholders** — Never generate fake or placeholder data. If you cannot retrieve real data, say so.'
650
+ );
651
+ lines.push(
652
+ '5. **No side effects** — Do not send messages, emails, or notifications unless explicitly tasked to do so.'
653
+ );
646
654
  lines.push('');
647
655
  lines.push('### Output');
648
656
  lines.push('When complete, your final response should include:');
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Unit tests for centralized enums in @illuma-ai/agents.
3
3
  * Verifies enum values remain stable — these are part of the public API
4
- * and are referenced by ranger validation schemas and MongoDB documents.
4
+ * and are referenced by host validation schemas and MongoDB documents.
5
5
  */
6
6
  import {
7
7
  EdgeType,
@@ -33,7 +33,9 @@ describe('EdgeType enum', () => {
33
33
  it('has three members: handoff, transfer, sequence', () => {
34
34
  const values = Object.values(EdgeType);
35
35
  expect(values).toHaveLength(3);
36
- expect(values).toEqual(expect.arrayContaining(['handoff', 'transfer', 'sequence']));
36
+ expect(values).toEqual(
37
+ expect.arrayContaining(['handoff', 'transfer', 'sequence'])
38
+ );
37
39
  });
38
40
  });
39
41
 
@@ -0,0 +1,110 @@
1
+ import {
2
+ SPAWN_PATH_SEP,
3
+ MAX_NESTING_DEPTH,
4
+ buildSpawnPath,
5
+ spawnPathDepth,
6
+ parentSpawnPath,
7
+ spawnPathParts,
8
+ leafSpawnKey,
9
+ isAncestorSpawnPath,
10
+ } from '../spawnPath';
11
+
12
+ describe('spawnPath utilities', () => {
13
+ describe('constants', () => {
14
+ it('exports a slash separator', () => {
15
+ expect(SPAWN_PATH_SEP).toBe('/');
16
+ });
17
+ it('default max nesting depth is 5', () => {
18
+ expect(MAX_NESTING_DEPTH).toBe(5);
19
+ });
20
+ });
21
+
22
+ describe('buildSpawnPath', () => {
23
+ it('returns key as-is when parent is empty/null/undefined', () => {
24
+ expect(buildSpawnPath('', 'a')).toBe('a');
25
+ expect(buildSpawnPath(null, 'a')).toBe('a');
26
+ expect(buildSpawnPath(undefined, 'a')).toBe('a');
27
+ });
28
+ it('appends key to parent with separator', () => {
29
+ expect(buildSpawnPath('a', 'b')).toBe('a/b');
30
+ expect(buildSpawnPath('a/b', 'c')).toBe('a/b/c');
31
+ });
32
+ it('throws on empty key', () => {
33
+ expect(() => buildSpawnPath('a', '')).toThrow(/empty key/);
34
+ });
35
+ });
36
+
37
+ describe('spawnPathDepth', () => {
38
+ it('root is depth 0', () => {
39
+ expect(spawnPathDepth('')).toBe(0);
40
+ expect(spawnPathDepth(null)).toBe(0);
41
+ expect(spawnPathDepth(undefined)).toBe(0);
42
+ });
43
+ it('single segment is depth 1', () => {
44
+ expect(spawnPathDepth('a')).toBe(1);
45
+ });
46
+ it('multi segment counts segments', () => {
47
+ expect(spawnPathDepth('a/b')).toBe(2);
48
+ expect(spawnPathDepth('a/b/c/d')).toBe(4);
49
+ });
50
+ it('ignores empty segments from stray separators', () => {
51
+ expect(spawnPathDepth('a//b')).toBe(2);
52
+ expect(spawnPathDepth('/a/b')).toBe(2);
53
+ });
54
+ });
55
+
56
+ describe('parentSpawnPath', () => {
57
+ it('root returns null', () => {
58
+ expect(parentSpawnPath('')).toBeNull();
59
+ expect(parentSpawnPath(null)).toBeNull();
60
+ });
61
+ it('single segment returns empty (root)', () => {
62
+ expect(parentSpawnPath('a')).toBe('');
63
+ });
64
+ it('multi segment drops last', () => {
65
+ expect(parentSpawnPath('a/b')).toBe('a');
66
+ expect(parentSpawnPath('a/b/c')).toBe('a/b');
67
+ });
68
+ });
69
+
70
+ describe('spawnPathParts', () => {
71
+ it('empty path returns empty array', () => {
72
+ expect(spawnPathParts('')).toEqual([]);
73
+ expect(spawnPathParts(null)).toEqual([]);
74
+ });
75
+ it('splits segments', () => {
76
+ expect(spawnPathParts('a/b/c')).toEqual(['a', 'b', 'c']);
77
+ });
78
+ });
79
+
80
+ describe('leafSpawnKey', () => {
81
+ it('root returns null', () => {
82
+ expect(leafSpawnKey('')).toBeNull();
83
+ });
84
+ it('returns last segment', () => {
85
+ expect(leafSpawnKey('a')).toBe('a');
86
+ expect(leafSpawnKey('a/b/c')).toBe('c');
87
+ });
88
+ });
89
+
90
+ describe('isAncestorSpawnPath', () => {
91
+ it('root is ancestor of any non-root path', () => {
92
+ expect(isAncestorSpawnPath('', 'a')).toBe(true);
93
+ expect(isAncestorSpawnPath('', 'a/b')).toBe(true);
94
+ });
95
+ it('root is not ancestor of root', () => {
96
+ expect(isAncestorSpawnPath('', '')).toBe(false);
97
+ });
98
+ it('strict ancestor detection', () => {
99
+ expect(isAncestorSpawnPath('a', 'a/b')).toBe(true);
100
+ expect(isAncestorSpawnPath('a/b', 'a/b/c')).toBe(true);
101
+ expect(isAncestorSpawnPath('a', 'a')).toBe(false);
102
+ });
103
+ it('sibling is not ancestor', () => {
104
+ expect(isAncestorSpawnPath('a/b', 'a/c')).toBe(false);
105
+ });
106
+ it('partial-prefix is not ancestor (must respect segment boundary)', () => {
107
+ expect(isAncestorSpawnPath('ab', 'abc')).toBe(false);
108
+ });
109
+ });
110
+ });
@@ -1,4 +1,5 @@
1
1
  // src/common/index.ts
2
2
  export * from './enum';
3
3
  export * from './constants';
4
+ export * from './spawnPath';
4
5
  export * from '../tools/approval/constants';