@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
@@ -8,7 +8,8 @@
8
8
  * the required environment variables are not set.
9
9
  *
10
10
  * To run:
11
- * 1. Copy ranger/.env credentials to agents/.env (or set env vars directly)
11
+ * 1. Set env vars directly, or set AGENTS_TEST_ENV_PATH to point at
12
+ * a host .env file containing the required credentials.
12
13
  * 2. npm test -- --testPathPattern=structured-output.integration
13
14
  *
14
15
  * Environment variables needed:
@@ -19,14 +20,23 @@
19
20
  import { config } from 'dotenv';
20
21
  import { resolve } from 'path';
21
22
 
22
- // Load from ranger/.env if agents/.env doesn't exist
23
- config(); // Try local first
24
- config({ path: resolve(__dirname, '../../../../ranger/.env') }); // Then ranger
25
-
26
- import { HumanMessage, SystemMessage, AIMessageChunk } from '@langchain/core/messages';
23
+ // Load local .env first; optionally fall back to a host-provided env file.
24
+ config();
25
+ if (process.env.AGENTS_TEST_ENV_PATH) {
26
+ config({ path: resolve(process.env.AGENTS_TEST_ENV_PATH) });
27
+ }
28
+
29
+ import {
30
+ HumanMessage,
31
+ SystemMessage,
32
+ AIMessageChunk,
33
+ } from '@langchain/core/messages';
27
34
  import { CustomChatBedrockConverse } from '@/llm/bedrock';
28
35
  import { Providers } from '@/common';
29
- import { validateStructuredOutput, prepareSchemaForProvider } from '@/schemas/validate';
36
+ import {
37
+ validateStructuredOutput,
38
+ prepareSchemaForProvider,
39
+ } from '@/schemas/validate';
30
40
 
31
41
  jest.setTimeout(120000);
32
42
 
@@ -114,10 +124,15 @@ describe('Bedrock structured output integration', () => {
114
124
 
115
125
  const result = await structuredModel.invoke([
116
126
  new SystemMessage('Extract person information from the text.'),
117
- new HumanMessage('John Smith is a 35 year old software engineer from Seattle.'),
127
+ new HumanMessage(
128
+ 'John Smith is a 35 year old software engineer from Seattle.'
129
+ ),
118
130
  ]);
119
131
 
120
- console.log('[Integration] Bedrock functionCalling result:', JSON.stringify(result.parsed ?? result, null, 2));
132
+ console.log(
133
+ '[Integration] Bedrock functionCalling result:',
134
+ JSON.stringify(result.parsed ?? result, null, 2)
135
+ );
121
136
 
122
137
  const parsed = result.parsed ?? result;
123
138
  expect(parsed).toBeDefined();
@@ -128,7 +143,7 @@ describe('Bedrock structured output integration', () => {
128
143
  // Validate against schema
129
144
  const validation = validateStructuredOutput(parsed, personSchema);
130
145
  expect(validation.success).toBe(true);
131
- },
146
+ }
132
147
  );
133
148
 
134
149
  conditionalTest(
@@ -144,75 +159,87 @@ describe('Bedrock structured output integration', () => {
144
159
 
145
160
  const result = await structuredModel.invoke([
146
161
  new SystemMessage('Classify the sentiment of the following text.'),
147
- new HumanMessage('I absolutely love this product! It exceeded all my expectations.'),
162
+ new HumanMessage(
163
+ 'I absolutely love this product! It exceeded all my expectations.'
164
+ ),
148
165
  ]);
149
166
 
150
167
  const parsed = result.parsed ?? result;
151
- console.log('[Integration] Bedrock classification result:', JSON.stringify(parsed, null, 2));
168
+ console.log(
169
+ '[Integration] Bedrock classification result:',
170
+ JSON.stringify(parsed, null, 2)
171
+ );
152
172
 
153
173
  expect(parsed).toBeDefined();
154
174
  expect(['positive', 'negative', 'neutral']).toContain(parsed.category);
155
175
  expect(typeof parsed.confidence).toBe('number');
156
176
  expect(typeof parsed.reasoning).toBe('string');
157
- },
177
+ }
158
178
  );
159
179
 
160
- conditionalTest(
161
- 'withStructuredOutput with prepared schema',
162
- async () => {
163
- const rawSchema = {
164
- type: 'object',
165
- properties: {
166
- summary: { type: 'string', maxLength: 500 },
167
- topics: { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: 5 },
168
- wordCount: { type: 'number', minimum: 0 },
180
+ conditionalTest('withStructuredOutput with prepared schema', async () => {
181
+ const rawSchema = {
182
+ type: 'object',
183
+ properties: {
184
+ summary: { type: 'string', maxLength: 500 },
185
+ topics: {
186
+ type: 'array',
187
+ items: { type: 'string' },
188
+ minItems: 1,
189
+ maxItems: 5,
169
190
  },
170
- };
171
-
172
- // Prepare schema for Bedrock
173
- const { schema: prepared, warnings } = prepareSchemaForProvider(
174
- rawSchema,
175
- Providers.BEDROCK,
176
- );
191
+ wordCount: { type: 'number', minimum: 0 },
192
+ },
193
+ };
177
194
 
178
- console.log('[Integration] Schema preparation warnings:', warnings);
195
+ // Prepare schema for Bedrock
196
+ const { schema: prepared, warnings } = prepareSchemaForProvider(
197
+ rawSchema,
198
+ Providers.BEDROCK
199
+ );
179
200
 
180
- // Verify preparation worked
181
- expect(prepared.additionalProperties).toBe(false);
182
- expect(prepared.required).toEqual(
183
- expect.arrayContaining(['summary', 'topics', 'wordCount']),
184
- );
185
- const summaryProp = (prepared.properties as any).summary;
186
- expect(summaryProp.maxLength).toBeUndefined();
187
- expect(summaryProp.description).toContain('maxLength');
201
+ console.log('[Integration] Schema preparation warnings:', warnings);
188
202
 
189
- // Now use the prepared schema with the model
190
- const model = createBedrockModel();
191
- const structuredModel = model.withStructuredOutput(prepared, {
192
- name: 'Analysis',
193
- method: 'functionCalling' as any,
194
- includeRaw: true,
195
- strict: true,
196
- });
203
+ // Verify preparation worked
204
+ expect(prepared.additionalProperties).toBe(false);
205
+ expect(prepared.required).toEqual(
206
+ expect.arrayContaining(['summary', 'topics', 'wordCount'])
207
+ );
208
+ const summaryProp = (prepared.properties as any).summary;
209
+ expect(summaryProp.maxLength).toBeUndefined();
210
+ expect(summaryProp.description).toContain('maxLength');
211
+
212
+ // Now use the prepared schema with the model
213
+ const model = createBedrockModel();
214
+ const structuredModel = model.withStructuredOutput(prepared, {
215
+ name: 'Analysis',
216
+ method: 'functionCalling' as any,
217
+ includeRaw: true,
218
+ strict: true,
219
+ });
197
220
 
198
- const result = await structuredModel.invoke([
199
- new SystemMessage('Analyze the following text and provide a summary, key topics, and word count.'),
200
- new HumanMessage(
201
- 'Artificial intelligence has transformed the technology industry in recent years. ' +
221
+ const result = await structuredModel.invoke([
222
+ new SystemMessage(
223
+ 'Analyze the following text and provide a summary, key topics, and word count.'
224
+ ),
225
+ new HumanMessage(
226
+ 'Artificial intelligence has transformed the technology industry in recent years. ' +
202
227
  'Machine learning models are now capable of generating text, images, and even code. ' +
203
- 'Companies are investing heavily in AI research and development.',
204
- ),
205
- ]);
206
-
207
- const parsed = result.parsed ?? result;
208
- console.log('[Integration] Bedrock analysis result:', JSON.stringify(parsed, null, 2));
228
+ 'Companies are investing heavily in AI research and development.'
229
+ ),
230
+ ]);
231
+
232
+ const parsed = result.parsed ?? result;
233
+ console.log(
234
+ '[Integration] Bedrock analysis result:',
235
+ JSON.stringify(parsed, null, 2)
236
+ );
209
237
 
210
- expect(parsed).toBeDefined();
211
- expect(typeof parsed.summary).toBe('string');
212
- expect(Array.isArray(parsed.topics)).toBe(true);
213
- expect(typeof parsed.wordCount).toBe('number');
214
- },
215
- );
238
+ expect(parsed).toBeDefined();
239
+ expect(typeof parsed.summary).toBe('string');
240
+ expect(Array.isArray(parsed.topics)).toBe(true);
241
+ expect(typeof parsed.wordCount).toBe('number');
242
+ });
216
243
 
217
244
  conditionalTest(
218
245
  'withStructuredOutput with tools - deferred structured output pattern',
@@ -222,10 +249,10 @@ describe('Bedrock structured output integration', () => {
222
249
  // Step 1: Regular invocation with tools (simulate tool use)
223
250
  const messages = [
224
251
  new SystemMessage(
225
- 'You are a helpful assistant. When asked to analyze text, provide a structured analysis.',
252
+ 'You are a helpful assistant. When asked to analyze text, provide a structured analysis.'
226
253
  ),
227
254
  new HumanMessage(
228
- 'Analyze the sentiment: "This movie was absolutely terrible, worst I have ever seen."',
255
+ 'Analyze the sentiment: "This movie was absolutely terrible, worst I have ever seen."'
229
256
  ),
230
257
  ];
231
258
 
@@ -240,14 +267,17 @@ describe('Bedrock structured output integration', () => {
240
267
  const result = await structuredModel.invoke(messages);
241
268
 
242
269
  const parsed = result.parsed ?? result;
243
- console.log('[Integration] Bedrock deferred structured result:', JSON.stringify(parsed, null, 2));
270
+ console.log(
271
+ '[Integration] Bedrock deferred structured result:',
272
+ JSON.stringify(parsed, null, 2)
273
+ );
244
274
 
245
275
  expect(parsed).toBeDefined();
246
276
  expect(['positive', 'negative', 'neutral']).toContain(parsed.category);
247
277
  // The movie review is clearly negative
248
278
  expect(parsed.category).toBe('negative');
249
279
  expect(typeof parsed.confidence).toBe('number');
250
- },
280
+ }
251
281
  );
252
282
 
253
283
  conditionalTest(
@@ -272,7 +302,7 @@ describe('Bedrock structured output integration', () => {
272
302
  const badResult = validateStructuredOutput(badResponse, personSchema);
273
303
  expect(badResult.success).toBe(false);
274
304
  expect(badResult.error).toBeDefined();
275
- },
305
+ }
276
306
  );
277
307
  });
278
308
 
@@ -309,7 +339,13 @@ describe('Bedrock complex tool + structured output integration', () => {
309
339
  properties: {
310
340
  overall_sentiment: {
311
341
  type: 'string',
312
- enum: ['very_positive', 'positive', 'neutral', 'negative', 'very_negative'],
342
+ enum: [
343
+ 'very_positive',
344
+ 'positive',
345
+ 'neutral',
346
+ 'negative',
347
+ 'very_negative',
348
+ ],
313
349
  },
314
350
  confidence: { type: 'number' },
315
351
  key_themes: {
@@ -318,7 +354,10 @@ describe('Bedrock complex tool + structured output integration', () => {
318
354
  type: 'object',
319
355
  properties: {
320
356
  theme: { type: 'string' },
321
- sentiment: { type: 'string', enum: ['positive', 'negative', 'neutral'] },
357
+ sentiment: {
358
+ type: 'string',
359
+ enum: ['positive', 'negative', 'neutral'],
360
+ },
322
361
  evidence: { type: 'string' },
323
362
  },
324
363
  required: ['theme', 'sentiment', 'evidence'],
@@ -335,7 +374,10 @@ describe('Bedrock complex tool + structured output integration', () => {
335
374
  type: 'object',
336
375
  properties: {
337
376
  name: { type: 'string' },
338
- type: { type: 'string', enum: ['person', 'organization', 'location', 'product'] },
377
+ type: {
378
+ type: 'string',
379
+ enum: ['person', 'organization', 'location', 'product'],
380
+ },
339
381
  role: { type: 'string' },
340
382
  },
341
383
  required: ['name', 'type', 'role'],
@@ -362,22 +404,25 @@ describe('Bedrock complex tool + structured output integration', () => {
362
404
 
363
405
  const result = await structuredModel.invoke([
364
406
  new SystemMessage(
365
- 'You are an expert analyst. Analyze the following business communication and extract detailed structured information.',
407
+ 'You are an expert analyst. Analyze the following business communication and extract detailed structured information.'
366
408
  ),
367
409
  new HumanMessage(
368
410
  'From: Sarah Johnson, VP of Engineering at TechCorp\n' +
369
- 'To: All Engineering Teams\n\n' +
370
- 'I am pleased to announce that our new AI platform, CodeAssist, has exceeded Q3 targets by 45%. ' +
371
- 'The Seattle development team, led by Marcus Chen, deserves special recognition for their outstanding work. ' +
372
- 'However, we need to address the performance issues reported by our European clients. ' +
373
- 'The London office has flagged latency problems that must be resolved before the Q4 launch. ' +
374
- 'Action items: 1) Marcus to lead a performance task force. 2) Schedule a meeting with the London team. ' +
375
- '3) Update the deployment pipeline for EU regions.',
411
+ 'To: All Engineering Teams\n\n' +
412
+ 'I am pleased to announce that our new AI platform, CodeAssist, has exceeded Q3 targets by 45%. ' +
413
+ 'The Seattle development team, led by Marcus Chen, deserves special recognition for their outstanding work. ' +
414
+ 'However, we need to address the performance issues reported by our European clients. ' +
415
+ 'The London office has flagged latency problems that must be resolved before the Q4 launch. ' +
416
+ 'Action items: 1) Marcus to lead a performance task force. 2) Schedule a meeting with the London team. ' +
417
+ '3) Update the deployment pipeline for EU regions.'
376
418
  ),
377
419
  ]);
378
420
 
379
421
  const parsed = result.parsed ?? result;
380
- console.log('[Integration] Complex analysis result:', JSON.stringify(parsed, null, 2));
422
+ console.log(
423
+ '[Integration] Complex analysis result:',
424
+ JSON.stringify(parsed, null, 2)
425
+ );
381
426
 
382
427
  // Verify top-level structure
383
428
  // Note: functionCalling mode is best-effort, so some fields may be missing.
@@ -387,15 +432,21 @@ describe('Bedrock complex tool + structured output integration', () => {
387
432
 
388
433
  // Analysis is the most complex nested field — verify if present
389
434
  if (parsed.analysis) {
390
- expect(['very_positive', 'positive', 'neutral', 'negative', 'very_negative']).toContain(
391
- parsed.analysis.overall_sentiment,
392
- );
435
+ expect([
436
+ 'very_positive',
437
+ 'positive',
438
+ 'neutral',
439
+ 'negative',
440
+ 'very_negative',
441
+ ]).toContain(parsed.analysis.overall_sentiment);
393
442
  expect(typeof parsed.analysis.confidence).toBe('number');
394
443
  if (Array.isArray(parsed.analysis.key_themes)) {
395
444
  expect(parsed.analysis.key_themes.length).toBeGreaterThan(0);
396
445
  for (const theme of parsed.analysis.key_themes) {
397
446
  expect(typeof theme.theme).toBe('string');
398
- expect(['positive', 'negative', 'neutral']).toContain(theme.sentiment);
447
+ expect(['positive', 'negative', 'neutral']).toContain(
448
+ theme.sentiment
449
+ );
399
450
  expect(typeof theme.evidence).toBe('string');
400
451
  }
401
452
  }
@@ -406,7 +457,9 @@ describe('Bedrock complex tool + structured output integration', () => {
406
457
  expect(parsed.entities.length).toBeGreaterThan(0);
407
458
  for (const entity of parsed.entities) {
408
459
  expect(typeof entity.name).toBe('string');
409
- expect(['person', 'organization', 'location', 'product']).toContain(entity.type);
460
+ expect(['person', 'organization', 'location', 'product']).toContain(
461
+ entity.type
462
+ );
410
463
  }
411
464
  }
412
465
 
@@ -417,7 +470,7 @@ describe('Bedrock complex tool + structured output integration', () => {
417
470
 
418
471
  // At minimum, we expect the model returned something parseable with the key fields
419
472
  expect(parsed.summary.length).toBeGreaterThan(0);
420
- },
473
+ }
421
474
  );
422
475
 
423
476
  conditionalTest(
@@ -436,10 +489,18 @@ describe('Bedrock complex tool + structured output integration', () => {
436
489
  properties: {
437
490
  category: { type: 'string' },
438
491
  description: { type: 'string' },
439
- severity: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] },
492
+ severity: {
493
+ type: 'string',
494
+ enum: ['low', 'medium', 'high', 'critical'],
495
+ },
440
496
  recommendation: { type: 'string' },
441
497
  },
442
- required: ['category', 'description', 'severity', 'recommendation'],
498
+ required: [
499
+ 'category',
500
+ 'description',
501
+ 'severity',
502
+ 'recommendation',
503
+ ],
443
504
  additionalProperties: false,
444
505
  },
445
506
  },
@@ -452,7 +513,12 @@ describe('Bedrock complex tool + structured output integration', () => {
452
513
  items: { type: 'string' },
453
514
  },
454
515
  },
455
- required: ['report_title', 'findings', 'overall_risk_level', 'next_steps'],
516
+ required: [
517
+ 'report_title',
518
+ 'findings',
519
+ 'overall_risk_level',
520
+ 'next_steps',
521
+ ],
456
522
  additionalProperties: false,
457
523
  };
458
524
 
@@ -462,16 +528,16 @@ describe('Bedrock complex tool + structured output integration', () => {
462
528
  const messages = [
463
529
  new SystemMessage(
464
530
  'You are a security analyst. You have performed a security audit and gathered the following data from various scans. ' +
465
- 'Produce a structured security report.',
531
+ 'Produce a structured security report.'
466
532
  ),
467
533
  new HumanMessage(
468
534
  'Here are the scan results:\n\n' +
469
- 'Port Scan: Ports 22, 80, 443, 8080 are open. Port 8080 is running an outdated Apache Tomcat 8.5.\n\n' +
470
- 'Vulnerability Scan: Found SQL injection in /api/users endpoint. XSS vulnerability in search form. ' +
471
- 'Outdated OpenSSL 1.1.1 (should be 3.x). No rate limiting on login endpoint.\n\n' +
472
- 'Configuration Review: Default admin credentials found on Tomcat manager. ' +
473
- 'CORS is set to wildcard (*). No CSP headers. Cookies without HttpOnly flag.\n\n' +
474
- 'Provide your structured security report.',
535
+ 'Port Scan: Ports 22, 80, 443, 8080 are open. Port 8080 is running an outdated Apache Tomcat 8.5.\n\n' +
536
+ 'Vulnerability Scan: Found SQL injection in /api/users endpoint. XSS vulnerability in search form. ' +
537
+ 'Outdated OpenSSL 1.1.1 (should be 3.x). No rate limiting on login endpoint.\n\n' +
538
+ 'Configuration Review: Default admin credentials found on Tomcat manager. ' +
539
+ 'CORS is set to wildcard (*). No CSP headers. Cookies without HttpOnly flag.\n\n' +
540
+ 'Provide your structured security report.'
475
541
  ),
476
542
  ];
477
543
 
@@ -485,13 +551,18 @@ describe('Bedrock complex tool + structured output integration', () => {
485
551
  const result = await structuredModel.invoke(messages);
486
552
 
487
553
  const parsed = result.parsed ?? result;
488
- console.log('[Integration] Security report result:', JSON.stringify(parsed, null, 2));
554
+ console.log(
555
+ '[Integration] Security report result:',
556
+ JSON.stringify(parsed, null, 2)
557
+ );
489
558
 
490
559
  // Verify structure
491
560
  expect(typeof parsed.report_title).toBe('string');
492
561
  expect(Array.isArray(parsed.findings)).toBe(true);
493
562
  expect(parsed.findings.length).toBeGreaterThanOrEqual(3); // At least SQL injection, XSS, outdated software
494
- expect(['low', 'medium', 'high', 'critical']).toContain(parsed.overall_risk_level);
563
+ expect(['low', 'medium', 'high', 'critical']).toContain(
564
+ parsed.overall_risk_level
565
+ );
495
566
  expect(Array.isArray(parsed.next_steps)).toBe(true);
496
567
  expect(parsed.next_steps.length).toBeGreaterThan(0);
497
568
 
@@ -499,7 +570,9 @@ describe('Bedrock complex tool + structured output integration', () => {
499
570
  for (const finding of parsed.findings) {
500
571
  expect(typeof finding.category).toBe('string');
501
572
  expect(typeof finding.description).toBe('string');
502
- expect(['low', 'medium', 'high', 'critical']).toContain(finding.severity);
573
+ expect(['low', 'medium', 'high', 'critical']).toContain(
574
+ finding.severity
575
+ );
503
576
  expect(typeof finding.recommendation).toBe('string');
504
577
  }
505
578
 
@@ -509,7 +582,7 @@ describe('Bedrock complex tool + structured output integration', () => {
509
582
  // Validate entire response
510
583
  const validation = validateStructuredOutput(parsed, reportSchema);
511
584
  expect(validation.success).toBe(true);
512
- },
585
+ }
513
586
  );
514
587
 
515
588
  conditionalTest(
@@ -542,10 +615,13 @@ describe('Bedrock complex tool + structured output integration', () => {
542
615
  // Prepare for Bedrock
543
616
  const { schema: prepared, warnings } = prepareSchemaForProvider(
544
617
  rawSchema,
545
- Providers.BEDROCK,
618
+ Providers.BEDROCK
546
619
  );
547
620
 
548
- console.log('[Integration] Complex schema warnings count:', warnings.length);
621
+ console.log(
622
+ '[Integration] Complex schema warnings count:',
623
+ warnings.length
624
+ );
549
625
  expect(warnings.length).toBeGreaterThan(5); // Should have many warnings
550
626
 
551
627
  // Verify ALL constraints were stripped
@@ -573,22 +649,27 @@ describe('Bedrock complex tool + structured output integration', () => {
573
649
  });
574
650
 
575
651
  const result = await structuredModel.invoke([
576
- new SystemMessage('You are a book reviewer. Review the book described below.'),
652
+ new SystemMessage(
653
+ 'You are a book reviewer. Review the book described below.'
654
+ ),
577
655
  new HumanMessage(
578
656
  'Review "The Great Gatsby" by F. Scott Fitzgerald. ' +
579
- 'It is a classic American novel written in English about the decline of the American Dream.',
657
+ 'It is a classic American novel written in English about the decline of the American Dream.'
580
658
  ),
581
659
  ]);
582
660
 
583
661
  const parsed = result.parsed ?? result;
584
- console.log('[Integration] Book review result:', JSON.stringify(parsed, null, 2));
662
+ console.log(
663
+ '[Integration] Book review result:',
664
+ JSON.stringify(parsed, null, 2)
665
+ );
585
666
 
586
667
  expect(typeof parsed.title).toBe('string');
587
668
  expect(typeof parsed.rating).toBe('number');
588
669
  expect(Array.isArray(parsed.tags)).toBe(true);
589
670
  expect(parsed.metadata).toBeDefined();
590
671
  expect(['en', 'es', 'fr', 'de']).toContain(parsed.metadata.language);
591
- },
672
+ }
592
673
  );
593
674
  });
594
675
 
@@ -620,11 +701,16 @@ describe('Anthropic direct structured output integration', () => {
620
701
 
621
702
  const result = await structuredModel.invoke([
622
703
  new SystemMessage('Extract person information from the text.'),
623
- new HumanMessage('Marie Curie was a 66 year old physicist and chemist.'),
704
+ new HumanMessage(
705
+ 'Marie Curie was a 66 year old physicist and chemist.'
706
+ ),
624
707
  ]);
625
708
 
626
709
  const parsed = result.parsed ?? result;
627
- console.log('[Integration] Anthropic native result:', JSON.stringify(parsed, null, 2));
710
+ console.log(
711
+ '[Integration] Anthropic native result:',
712
+ JSON.stringify(parsed, null, 2)
713
+ );
628
714
 
629
715
  expect(parsed).toBeDefined();
630
716
  expect(typeof parsed.name).toBe('string');
@@ -633,7 +719,7 @@ describe('Anthropic direct structured output integration', () => {
633
719
 
634
720
  const validation = validateStructuredOutput(parsed, personSchema);
635
721
  expect(validation.success).toBe(true);
636
- },
722
+ }
637
723
  );
638
724
 
639
725
  conditionalTest(
@@ -660,11 +746,14 @@ describe('Anthropic direct structured output integration', () => {
660
746
  ]);
661
747
 
662
748
  const parsed = result.parsed ?? result;
663
- console.log('[Integration] Anthropic classification:', JSON.stringify(parsed, null, 2));
749
+ console.log(
750
+ '[Integration] Anthropic classification:',
751
+ JSON.stringify(parsed, null, 2)
752
+ );
664
753
 
665
754
  expect(['positive', 'negative', 'neutral']).toContain(parsed.category);
666
755
  expect(parsed.category).toBe('positive');
667
- },
756
+ }
668
757
  );
669
758
  });
670
759
 
@@ -695,11 +784,16 @@ describe('OpenAI structured output integration', () => {
695
784
 
696
785
  const result = await structuredModel.invoke([
697
786
  new SystemMessage('Extract person information from the text.'),
698
- new HumanMessage('Albert Einstein was a 76 year old theoretical physicist.'),
787
+ new HumanMessage(
788
+ 'Albert Einstein was a 76 year old theoretical physicist.'
789
+ ),
699
790
  ]);
700
791
 
701
792
  const parsed = result.parsed ?? result;
702
- console.log('[Integration] OpenAI native result:', JSON.stringify(parsed, null, 2));
793
+ console.log(
794
+ '[Integration] OpenAI native result:',
795
+ JSON.stringify(parsed, null, 2)
796
+ );
703
797
 
704
798
  expect(parsed).toBeDefined();
705
799
  expect(typeof parsed.name).toBe('string');
@@ -707,7 +801,7 @@ describe('OpenAI structured output integration', () => {
707
801
 
708
802
  const validation = validateStructuredOutput(parsed, personSchema);
709
803
  expect(validation.success).toBe(true);
710
- },
804
+ }
711
805
  );
712
806
  });
713
807
 
@@ -746,20 +840,20 @@ describe('Schema preparation produces valid schemas for all providers', () => {
746
840
  test('prepares valid schema for Anthropic', () => {
747
841
  const { schema, warnings } = prepareSchemaForProvider(
748
842
  complexSchema,
749
- Providers.ANTHROPIC,
843
+ Providers.ANTHROPIC
750
844
  );
751
845
 
752
846
  // Root object
753
847
  expect(schema.additionalProperties).toBe(false);
754
848
  expect(schema.required).toEqual(
755
- expect.arrayContaining(['analysis', 'tags', 'metadata']),
849
+ expect.arrayContaining(['analysis', 'tags', 'metadata'])
756
850
  );
757
851
 
758
852
  // Nested object: analysis
759
853
  const analysis = (schema.properties as any).analysis;
760
854
  expect(analysis.additionalProperties).toBe(false);
761
855
  expect(analysis.required).toEqual(
762
- expect.arrayContaining(['score', 'label', 'details']),
856
+ expect.arrayContaining(['score', 'label', 'details'])
763
857
  );
764
858
 
765
859
  // Numeric constraints stripped
@@ -788,7 +882,7 @@ describe('Schema preparation produces valid schemas for all providers', () => {
788
882
  test('prepares valid schema for OpenAI', () => {
789
883
  const { schema } = prepareSchemaForProvider(
790
884
  complexSchema,
791
- Providers.OPENAI,
885
+ Providers.OPENAI
792
886
  );
793
887
 
794
888
  expect(schema.additionalProperties).toBe(false);
@@ -799,7 +893,7 @@ describe('Schema preparation produces valid schemas for all providers', () => {
799
893
  test('prepares valid schema for Bedrock', () => {
800
894
  const { schema } = prepareSchemaForProvider(
801
895
  complexSchema,
802
- Providers.BEDROCK,
896
+ Providers.BEDROCK
803
897
  );
804
898
 
805
899
  expect(schema.additionalProperties).toBe(false);
@@ -874,7 +874,7 @@ describe('summaryModel dedicated cheap model usage', () => {
874
874
  const endpointConfig = {
875
875
  titleModel: 'us.amazon.nova-micro-v1:0',
876
876
  summaryModel: 'us.anthropic.claude-haiku-4-5-20251001-v1:0',
877
- modelDisplayLabel: 'Ranger',
877
+ modelDisplayLabel: 'Test',
878
878
  };
879
879
 
880
880
  // summaryModel should be a different, cheaper model than the main model