@illuma-ai/agents 1.5.1 → 2.1.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 (319) hide show
  1. package/README.md +0 -62
  2. package/dist/cjs/agents/AgentContext.cjs +160 -259
  3. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  4. package/dist/cjs/common/enum.cjs +12 -12
  5. package/dist/cjs/common/enum.cjs.map +1 -1
  6. package/dist/cjs/graphs/Graph.cjs +30 -13
  7. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  8. package/dist/cjs/graphs/MultiAgentGraph.cjs +1 -1
  9. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  10. package/dist/cjs/graphs/phases/memoryFlushPhase.cjs +1 -1
  11. package/dist/cjs/graphs/phases/memoryFlushPhase.cjs.map +1 -1
  12. package/dist/cjs/hooks/HookRegistry.cjs +1 -1
  13. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  14. package/dist/cjs/hooks/matchers.cjs +2 -2
  15. package/dist/cjs/hooks/matchers.cjs.map +1 -1
  16. package/dist/cjs/hooks/types.cjs +1 -1
  17. package/dist/cjs/hooks/types.cjs.map +1 -1
  18. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +1 -5
  19. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  20. package/dist/cjs/llm/bedrock/index.cjs +33 -61
  21. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  22. package/dist/cjs/llm/openai/index.cjs +1 -1
  23. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  24. package/dist/cjs/llm/openai/utils/index.cjs +10 -27
  25. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  26. package/dist/cjs/main.cjs +3 -84
  27. package/dist/cjs/main.cjs.map +1 -1
  28. package/dist/cjs/memory/citations.cjs +4 -4
  29. package/dist/cjs/memory/citations.cjs.map +1 -1
  30. package/dist/cjs/memory/constants.cjs +17 -17
  31. package/dist/cjs/memory/constants.cjs.map +1 -1
  32. package/dist/cjs/memory/mmr.cjs +1 -1
  33. package/dist/cjs/memory/mmr.cjs.map +1 -1
  34. package/dist/cjs/memory/paths.cjs +1 -1
  35. package/dist/cjs/memory/paths.cjs.map +1 -1
  36. package/dist/cjs/memory/recallTracking.cjs +3 -3
  37. package/dist/cjs/memory/recallTracking.cjs.map +1 -1
  38. package/dist/cjs/memory/temporalDecay.cjs +2 -2
  39. package/dist/cjs/memory/temporalDecay.cjs.map +1 -1
  40. package/dist/cjs/messages/cache.cjs +0 -89
  41. package/dist/cjs/messages/cache.cjs.map +1 -1
  42. package/dist/cjs/messages/format.cjs +13 -71
  43. package/dist/cjs/messages/format.cjs.map +1 -1
  44. package/dist/cjs/tools/BashExecutor.cjs +11 -21
  45. package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
  46. package/dist/cjs/tools/CodeExecutor.cjs +13 -41
  47. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  48. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +11 -16
  49. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  50. package/dist/cjs/tools/ToolNode.cjs +78 -13
  51. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  52. package/dist/cjs/tools/memory/memoryAppendTool.cjs +1 -1
  53. package/dist/cjs/tools/memory/memoryAppendTool.cjs.map +1 -1
  54. package/dist/cjs/tools/memory/memoryGetTool.cjs +2 -2
  55. package/dist/cjs/tools/memory/memoryGetTool.cjs.map +1 -1
  56. package/dist/cjs/tools/memory/memorySearchTool.cjs +3 -3
  57. package/dist/cjs/tools/memory/memorySearchTool.cjs.map +1 -1
  58. package/dist/cjs/tools/memory/shared.cjs +1 -1
  59. package/dist/cjs/tools/memory/shared.cjs.map +1 -1
  60. package/dist/cjs/tools/search/search.cjs +3 -11
  61. package/dist/cjs/tools/search/search.cjs.map +1 -1
  62. package/dist/cjs/tools/search/tool.cjs +4 -28
  63. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  64. package/dist/cjs/tools/search/utils.cjs +3 -10
  65. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  66. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +48 -0
  67. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  68. package/dist/cjs/types/graph.cjs.map +1 -1
  69. package/dist/esm/agents/AgentContext.mjs +160 -259
  70. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  71. package/dist/esm/common/enum.mjs +12 -12
  72. package/dist/esm/common/enum.mjs.map +1 -1
  73. package/dist/esm/graphs/Graph.mjs +30 -13
  74. package/dist/esm/graphs/Graph.mjs.map +1 -1
  75. package/dist/esm/graphs/MultiAgentGraph.mjs +1 -1
  76. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  77. package/dist/esm/graphs/phases/memoryFlushPhase.mjs +1 -1
  78. package/dist/esm/graphs/phases/memoryFlushPhase.mjs.map +1 -1
  79. package/dist/esm/hooks/HookRegistry.mjs +1 -1
  80. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  81. package/dist/esm/hooks/matchers.mjs +2 -2
  82. package/dist/esm/hooks/matchers.mjs.map +1 -1
  83. package/dist/esm/hooks/types.mjs +1 -1
  84. package/dist/esm/hooks/types.mjs.map +1 -1
  85. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +1 -5
  86. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  87. package/dist/esm/llm/bedrock/index.mjs +34 -61
  88. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  89. package/dist/esm/llm/openai/index.mjs +1 -1
  90. package/dist/esm/llm/openai/index.mjs.map +1 -1
  91. package/dist/esm/llm/openai/utils/index.mjs +10 -27
  92. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  93. package/dist/esm/main.mjs +1 -5
  94. package/dist/esm/main.mjs.map +1 -1
  95. package/dist/esm/memory/citations.mjs +4 -4
  96. package/dist/esm/memory/citations.mjs.map +1 -1
  97. package/dist/esm/memory/constants.mjs +17 -17
  98. package/dist/esm/memory/constants.mjs.map +1 -1
  99. package/dist/esm/memory/mmr.mjs +1 -1
  100. package/dist/esm/memory/mmr.mjs.map +1 -1
  101. package/dist/esm/memory/paths.mjs +1 -1
  102. package/dist/esm/memory/paths.mjs.map +1 -1
  103. package/dist/esm/memory/recallTracking.mjs +3 -3
  104. package/dist/esm/memory/recallTracking.mjs.map +1 -1
  105. package/dist/esm/memory/temporalDecay.mjs +2 -2
  106. package/dist/esm/memory/temporalDecay.mjs.map +1 -1
  107. package/dist/esm/messages/cache.mjs +0 -89
  108. package/dist/esm/messages/cache.mjs.map +1 -1
  109. package/dist/esm/messages/format.mjs +13 -71
  110. package/dist/esm/messages/format.mjs.map +1 -1
  111. package/dist/esm/tools/BashExecutor.mjs +12 -22
  112. package/dist/esm/tools/BashExecutor.mjs.map +1 -1
  113. package/dist/esm/tools/CodeExecutor.mjs +14 -41
  114. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  115. package/dist/esm/tools/ProgrammaticToolCalling.mjs +12 -17
  116. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  117. package/dist/esm/tools/ToolNode.mjs +78 -13
  118. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  119. package/dist/esm/tools/memory/memoryAppendTool.mjs +1 -1
  120. package/dist/esm/tools/memory/memoryAppendTool.mjs.map +1 -1
  121. package/dist/esm/tools/memory/memoryGetTool.mjs +2 -2
  122. package/dist/esm/tools/memory/memoryGetTool.mjs.map +1 -1
  123. package/dist/esm/tools/memory/memorySearchTool.mjs +3 -3
  124. package/dist/esm/tools/memory/memorySearchTool.mjs.map +1 -1
  125. package/dist/esm/tools/memory/shared.mjs +1 -1
  126. package/dist/esm/tools/memory/shared.mjs.map +1 -1
  127. package/dist/esm/tools/search/search.mjs +3 -11
  128. package/dist/esm/tools/search/search.mjs.map +1 -1
  129. package/dist/esm/tools/search/tool.mjs +4 -28
  130. package/dist/esm/tools/search/tool.mjs.map +1 -1
  131. package/dist/esm/tools/search/utils.mjs +3 -10
  132. package/dist/esm/tools/search/utils.mjs.map +1 -1
  133. package/dist/esm/tools/subagent/SubagentExecutor.mjs +48 -0
  134. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  135. package/dist/esm/types/graph.mjs.map +1 -1
  136. package/dist/types/agents/AgentContext.d.ts +25 -95
  137. package/dist/types/common/enum.d.ts +12 -12
  138. package/dist/types/graphs/Graph.d.ts +2 -2
  139. package/dist/types/graphs/phases/memoryFlushPhase.d.ts +2 -2
  140. package/dist/types/hooks/HookRegistry.d.ts +1 -1
  141. package/dist/types/hooks/matchers.d.ts +2 -2
  142. package/dist/types/hooks/types.d.ts +1 -1
  143. package/dist/types/index.d.ts +0 -1
  144. package/dist/types/llm/bedrock/index.d.ts +1 -54
  145. package/dist/types/llm/openai/index.d.ts +1 -1
  146. package/dist/types/memory/citations.d.ts +4 -4
  147. package/dist/types/memory/constants.d.ts +17 -17
  148. package/dist/types/memory/mmr.d.ts +3 -3
  149. package/dist/types/memory/paths.d.ts +1 -1
  150. package/dist/types/memory/temporalDecay.d.ts +2 -2
  151. package/dist/types/memory/types.d.ts +3 -3
  152. package/dist/types/messages/format.d.ts +2 -5
  153. package/dist/types/tools/CodeExecutor.d.ts +0 -6
  154. package/dist/types/tools/ToolNode.d.ts +3 -3
  155. package/dist/types/tools/memory/shared.d.ts +1 -1
  156. package/dist/types/tools/search/test.d.ts +1 -0
  157. package/dist/types/tools/search/types.d.ts +5 -99
  158. package/dist/types/tools/search/utils.d.ts +2 -2
  159. package/dist/types/tools/subagent/SubagentExecutor.d.ts +29 -0
  160. package/dist/types/types/graph.d.ts +30 -34
  161. package/dist/types/types/index.d.ts +0 -1
  162. package/dist/types/types/messages.d.ts +1 -1
  163. package/dist/types/types/run.d.ts +1 -3
  164. package/dist/types/types/tools.d.ts +5 -14
  165. package/package.json +1 -61
  166. package/src/agents/AgentContext.test.ts +176 -0
  167. package/src/agents/AgentContext.ts +179 -305
  168. package/src/agents/__tests__/AgentContext.test.ts +0 -632
  169. package/src/common/__tests__/enum.test.ts +1 -1
  170. package/src/common/enum.ts +12 -12
  171. package/src/graphs/Graph.ts +32 -13
  172. package/src/graphs/MultiAgentGraph.ts +1 -1
  173. package/src/graphs/gapFeatures.test.ts +1 -1
  174. package/src/graphs/phases/__tests__/memoryFlushPhase.test.ts +1 -1
  175. package/src/graphs/phases/memoryFlushPhase.ts +2 -2
  176. package/src/hooks/HookRegistry.ts +1 -1
  177. package/src/hooks/index.ts +1 -1
  178. package/src/hooks/matchers.ts +2 -2
  179. package/src/hooks/types.ts +1 -1
  180. package/src/index.ts +0 -6
  181. package/src/llm/anthropic/utils/message_inputs.ts +1 -10
  182. package/src/llm/bedrock/__tests__/bedrock-caching.test.ts +18 -166
  183. package/src/llm/bedrock/index.ts +41 -116
  184. package/src/llm/openai/index.ts +2 -2
  185. package/src/llm/openai/utils/index.ts +14 -31
  186. package/src/memory/citations.ts +4 -4
  187. package/src/memory/constants.ts +17 -17
  188. package/src/memory/mmr.ts +3 -3
  189. package/src/memory/paths.ts +1 -1
  190. package/src/memory/recallTracking.ts +3 -3
  191. package/src/memory/temporalDecay.ts +2 -2
  192. package/src/memory/types.ts +3 -3
  193. package/src/messages/cache.test.ts +24 -62
  194. package/src/messages/cache.ts +0 -112
  195. package/src/messages/ensureThinkingBlock.test.ts +1 -1
  196. package/src/messages/format.ts +13 -92
  197. package/src/messages/formatAgentMessages.test.ts +1 -1
  198. package/src/scripts/subagent-configurable-inheritance.ts +263 -0
  199. package/src/scripts/subagent-event-driven-debug.ts +2 -2
  200. package/src/specs/anthropic.simple.test.ts +0 -61
  201. package/src/specs/prune.orphans.test.ts +1 -1
  202. package/src/tools/BashExecutor.ts +13 -37
  203. package/src/tools/CodeExecutor.ts +14 -59
  204. package/src/tools/ProgrammaticToolCalling.ts +14 -29
  205. package/src/tools/ToolNode.ts +75 -14
  206. package/src/tools/__tests__/CodeExecutor.test.ts +3 -3
  207. package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +0 -60
  208. package/src/tools/__tests__/SubagentExecutor.test.ts +157 -0
  209. package/src/tools/memory/memoryAppendTool.ts +1 -1
  210. package/src/tools/memory/memoryGetTool.ts +2 -2
  211. package/src/tools/memory/memorySearchTool.ts +3 -3
  212. package/src/tools/memory/shared.ts +1 -1
  213. package/src/tools/search/output.md +2775 -0
  214. package/src/tools/search/search.ts +2 -12
  215. package/src/tools/search/test.html +884 -0
  216. package/src/tools/search/test.md +643 -0
  217. package/src/tools/search/test.ts +159 -0
  218. package/src/tools/search/tool.ts +2 -36
  219. package/src/tools/search/types.ts +8 -133
  220. package/src/tools/search/utils.ts +5 -13
  221. package/src/tools/subagent/SubagentExecutor.ts +78 -0
  222. package/src/types/graph.ts +27 -34
  223. package/src/types/index.ts +0 -1
  224. package/src/types/messages.ts +1 -1
  225. package/src/types/run.ts +1 -3
  226. package/src/types/tools.ts +5 -14
  227. package/dist/cjs/langchain/google-common.cjs +0 -3
  228. package/dist/cjs/langchain/google-common.cjs.map +0 -1
  229. package/dist/cjs/langchain/index.cjs +0 -86
  230. package/dist/cjs/langchain/index.cjs.map +0 -1
  231. package/dist/cjs/langchain/language_models/chat_models.cjs +0 -3
  232. package/dist/cjs/langchain/language_models/chat_models.cjs.map +0 -1
  233. package/dist/cjs/langchain/messages/tool.cjs +0 -3
  234. package/dist/cjs/langchain/messages/tool.cjs.map +0 -1
  235. package/dist/cjs/langchain/messages.cjs +0 -51
  236. package/dist/cjs/langchain/messages.cjs.map +0 -1
  237. package/dist/cjs/langchain/openai.cjs +0 -3
  238. package/dist/cjs/langchain/openai.cjs.map +0 -1
  239. package/dist/cjs/langchain/prompts.cjs +0 -11
  240. package/dist/cjs/langchain/prompts.cjs.map +0 -1
  241. package/dist/cjs/langchain/runnables.cjs +0 -19
  242. package/dist/cjs/langchain/runnables.cjs.map +0 -1
  243. package/dist/cjs/langchain/tools.cjs +0 -23
  244. package/dist/cjs/langchain/tools.cjs.map +0 -1
  245. package/dist/cjs/langchain/utils/env.cjs +0 -11
  246. package/dist/cjs/langchain/utils/env.cjs.map +0 -1
  247. package/dist/cjs/llm/bedrock/cacheSupport.cjs +0 -55
  248. package/dist/cjs/llm/bedrock/cacheSupport.cjs.map +0 -1
  249. package/dist/cjs/tools/search/tavily-scraper.cjs +0 -189
  250. package/dist/cjs/tools/search/tavily-scraper.cjs.map +0 -1
  251. package/dist/cjs/tools/search/tavily-search.cjs +0 -372
  252. package/dist/cjs/tools/search/tavily-search.cjs.map +0 -1
  253. package/dist/cjs/types/agent-cache.cjs +0 -54
  254. package/dist/cjs/types/agent-cache.cjs.map +0 -1
  255. package/dist/esm/langchain/google-common.mjs +0 -2
  256. package/dist/esm/langchain/google-common.mjs.map +0 -1
  257. package/dist/esm/langchain/index.mjs +0 -5
  258. package/dist/esm/langchain/index.mjs.map +0 -1
  259. package/dist/esm/langchain/language_models/chat_models.mjs +0 -2
  260. package/dist/esm/langchain/language_models/chat_models.mjs.map +0 -1
  261. package/dist/esm/langchain/messages/tool.mjs +0 -2
  262. package/dist/esm/langchain/messages/tool.mjs.map +0 -1
  263. package/dist/esm/langchain/messages.mjs +0 -2
  264. package/dist/esm/langchain/messages.mjs.map +0 -1
  265. package/dist/esm/langchain/openai.mjs +0 -2
  266. package/dist/esm/langchain/openai.mjs.map +0 -1
  267. package/dist/esm/langchain/prompts.mjs +0 -2
  268. package/dist/esm/langchain/prompts.mjs.map +0 -1
  269. package/dist/esm/langchain/runnables.mjs +0 -2
  270. package/dist/esm/langchain/runnables.mjs.map +0 -1
  271. package/dist/esm/langchain/tools.mjs +0 -2
  272. package/dist/esm/langchain/tools.mjs.map +0 -1
  273. package/dist/esm/langchain/utils/env.mjs +0 -2
  274. package/dist/esm/langchain/utils/env.mjs.map +0 -1
  275. package/dist/esm/llm/bedrock/cacheSupport.mjs +0 -52
  276. package/dist/esm/llm/bedrock/cacheSupport.mjs.map +0 -1
  277. package/dist/esm/tools/search/tavily-scraper.mjs +0 -186
  278. package/dist/esm/tools/search/tavily-scraper.mjs.map +0 -1
  279. package/dist/esm/tools/search/tavily-search.mjs +0 -370
  280. package/dist/esm/tools/search/tavily-search.mjs.map +0 -1
  281. package/dist/esm/types/agent-cache.mjs +0 -52
  282. package/dist/esm/types/agent-cache.mjs.map +0 -1
  283. package/dist/types/langchain/google-common.d.ts +0 -1
  284. package/dist/types/langchain/index.d.ts +0 -8
  285. package/dist/types/langchain/language_models/chat_models.d.ts +0 -1
  286. package/dist/types/langchain/messages/tool.d.ts +0 -1
  287. package/dist/types/langchain/messages.d.ts +0 -2
  288. package/dist/types/langchain/openai.d.ts +0 -1
  289. package/dist/types/langchain/prompts.d.ts +0 -1
  290. package/dist/types/langchain/runnables.d.ts +0 -2
  291. package/dist/types/langchain/tools.d.ts +0 -2
  292. package/dist/types/langchain/utils/env.d.ts +0 -1
  293. package/dist/types/llm/bedrock/cacheSupport.d.ts +0 -35
  294. package/dist/types/tools/search/tavily-scraper.d.ts +0 -19
  295. package/dist/types/tools/search/tavily-search.d.ts +0 -4
  296. package/dist/types/tools/subagent/types.d.ts +0 -84
  297. package/dist/types/types/agent-cache.d.ts +0 -71
  298. package/src/agents/__tests__/AgentContext.cacheTtl.live.test.ts +0 -259
  299. package/src/agents/__tests__/AgentContext.crossAgentTier1.live.test.ts +0 -266
  300. package/src/agents/__tests__/AgentContext.crossUserCache.live.test.ts +0 -342
  301. package/src/langchain/google-common.ts +0 -1
  302. package/src/langchain/index.ts +0 -8
  303. package/src/langchain/language_models/chat_models.ts +0 -1
  304. package/src/langchain/messages/tool.ts +0 -5
  305. package/src/langchain/messages.ts +0 -21
  306. package/src/langchain/openai.ts +0 -1
  307. package/src/langchain/prompts.ts +0 -1
  308. package/src/langchain/runnables.ts +0 -7
  309. package/src/langchain/tools.ts +0 -8
  310. package/src/langchain/utils/env.ts +0 -1
  311. package/src/llm/anthropic/utils/server-tool-inputs.test.ts +0 -436
  312. package/src/llm/bedrock/cacheSupport.test.ts +0 -99
  313. package/src/llm/bedrock/cacheSupport.ts +0 -53
  314. package/src/tools/search/tavily-scraper.ts +0 -235
  315. package/src/tools/search/tavily-search.ts +0 -424
  316. package/src/tools/search/tavily.test.ts +0 -965
  317. package/src/tools/subagent/types.test.ts +0 -70
  318. package/src/tools/subagent/types.ts +0 -115
  319. package/src/types/agent-cache.ts +0 -74
@@ -1,71 +0,0 @@
1
- /**
2
- * Agent system-message prompt-cache types.
3
- * ==========================================
4
- *
5
- * `@illuma-ai/agents` exposes a generic primitive — `system_cache_blocks` —
6
- * for composing a system message that gets explicit cache markers
7
- * (cachePoint on Bedrock, cache_control on Anthropic) at consumer-defined
8
- * boundaries. The library encodes each entry into the right wire format
9
- * for the active provider; consumers decide what content to put in each
10
- * block.
11
- *
12
- * Why this is generic rather than tier-named
13
- * ------------------------------------------------
14
- * Earlier iterations exposed `platform_instructions` and `cache_ttl:
15
- * { platform, agent }` — vocabulary borrowed from a specific consumer's
16
- * multi-tenant chat-platform mental model. That leaked one consumer's
17
- * domain into the library and made it confusing for other consumers
18
- * (CLI tools, desktop apps, gateways) which have no notion of
19
- * "platforms" or "agents".
20
- *
21
- * The current shape lets every consumer define their own cache-tier
22
- * organization without the library knowing or caring.
23
- *
24
- * Cache key composition
25
- * ---------------------
26
- * Both Anthropic and Bedrock hash the message bytes leading up to each
27
- * cache marker. So entry N's cache key is the concatenation of bytes
28
- * 0..N. Stable content (universal rules, framework docs) goes earlier;
29
- * volatile content (per-agent identity, per-tool docs) goes later. The
30
- * earlier entries get cross-tenant cache hits; the later entries get
31
- * narrower hits.
32
- *
33
- * Provider budget
34
- * ---------------
35
- * Bedrock's Converse API supports up to 4 cachePoint blocks per request.
36
- * The default tools-array cache strategy (see `IllumaBedrockConverse`)
37
- * uses up to 2 of those. So at most 2 entries should appear in
38
- * `system_cache_blocks` to leave budget for the trailing
39
- * `instructions` block. The library throws on more than 2.
40
- *
41
- * Anthropic supports up to 4 cache breakpoints per request workspace-wide;
42
- * the same constraint applies to keep tools + system within budget.
43
- */
44
- /** Provider TTL hint applied to a cachePoint / cache_control marker. */
45
- export type AgentCacheTTL = '5m' | '1h';
46
- /**
47
- * One cacheable system content block. Each entry produces a text block
48
- * followed by a provider-specific cache marker in the assembled system
49
- * message. Entries are emitted in array order — earlier = more stable
50
- * = wider cache key.
51
- */
52
- export interface SystemCacheBlock {
53
- /**
54
- * Text payload. Caller is responsible for keeping this byte-stable
55
- * across requests that should share a cache entry. ANY change to
56
- * these bytes invalidates every cache key that includes this entry.
57
- */
58
- text: string;
59
- /**
60
- * Optional TTL hint for the cache marker. Defaults to '5m' when
61
- * omitted. '1h' costs more to write (2× base vs 1.25×) but survives
62
- * longer idle, which is the right tradeoff for low-traffic blocks.
63
- */
64
- ttl?: AgentCacheTTL;
65
- }
66
- /**
67
- * Maximum number of `system_cache_blocks` entries the library accepts.
68
- * Higher than this would exceed Bedrock's 4-cachePoint budget once the
69
- * tools array and trailing `instructions` block are counted.
70
- */
71
- export declare const MAX_SYSTEM_CACHE_BLOCKS = 2;
@@ -1,259 +0,0 @@
1
- /* eslint-disable no-console */
2
- /**
3
- * LIVE Bedrock cache TTL comparison: `5m` (default) vs `1h` (extended).
4
- *
5
- * Verifies:
6
- * 1. Bedrock SDK accepts `cachePoint: { type: 'default', ttl: '1h' }`
7
- * against `us.anthropic.claude-sonnet-4-5-20250929-v1:0`.
8
- * 2. Both TTLs create cache entries readable by subsequent calls.
9
- * 3. The `cacheWriteInputTokens` charged on cold-write is the same
10
- * structurally — pricing differs by ~60% but the SDK reports the
11
- * same field.
12
- *
13
- * What this CAN'T verify in a unit-runner timeframe:
14
- * - That a 1h cache actually survives >5 min of idle (would require a
15
- * >5-min sleep). Marked as a manual long-soak test instead.
16
- *
17
- * Run:
18
- * BEDROCK_AWS_REGION=us-east-1 \
19
- * BEDROCK_AWS_ACCESS_KEY_ID=... BEDROCK_AWS_SECRET_ACCESS_KEY=... \
20
- * npx jest src/agents/__tests__/AgentContext.cacheTtl.live.test.ts
21
- */
22
-
23
- import { config } from 'dotenv';
24
- config();
25
-
26
- import { HumanMessage, SystemMessage } from '@langchain/core/messages';
27
- import type { BaseMessage, AIMessage } from '@langchain/core/messages';
28
- import { IllumaBedrockConverse } from '@/llm/bedrock';
29
-
30
- const region =
31
- process.env.BEDROCK_AWS_REGION ??
32
- process.env.BEDROCK_AWS_DEFAULT_REGION ??
33
- process.env.AWS_REGION ??
34
- 'us-east-1';
35
- const accessKeyId =
36
- process.env.BEDROCK_AWS_ACCESS_KEY_ID ?? process.env.AWS_ACCESS_KEY_ID;
37
- const secretAccessKey =
38
- process.env.BEDROCK_AWS_SECRET_ACCESS_KEY ??
39
- process.env.AWS_SECRET_ACCESS_KEY;
40
-
41
- const haveBedrock =
42
- accessKeyId !== undefined &&
43
- accessKeyId !== '' &&
44
- secretAccessKey !== undefined &&
45
- secretAccessKey !== '';
46
-
47
- const describeFn = haveBedrock ? describe : describe.skip;
48
-
49
- /**
50
- * Build a unique-per-test stable prefix so we get a true cold-write on
51
- * the first call (not piggybacking on a cache populated by a prior test).
52
- * 80 rules × ~30 tokens ≈ 2400 tokens — above Bedrock's 1024-token
53
- * minimum cache write threshold.
54
- */
55
- const buildUniquePrefix = (suiteId: string): string => {
56
- const padding = Array.from({ length: 80 }, (_, i) =>
57
- `Rule ${i + 1} (${suiteId}): respond concisely; cite assumptions; treat all users with respect; never fabricate facts; if uncertain, say so explicitly.`
58
- ).join('\n');
59
- return `You are a helpful assistant for suite ${suiteId}.\n\n${padding}`;
60
- };
61
-
62
- interface UsageReadout {
63
- input_tokens: number;
64
- output_tokens: number;
65
- cache_read_input_tokens: number;
66
- cache_write_input_tokens: number;
67
- }
68
-
69
- /**
70
- * Build the system message manually with a chosen TTL, send it to
71
- * Bedrock, and return the cache-related usage from response_metadata.
72
- */
73
- async function callWithTtl({
74
- stableInstructions,
75
- ttl,
76
- query,
77
- }: {
78
- stableInstructions: string;
79
- ttl: '5m' | '1h';
80
- query: string;
81
- }): Promise<UsageReadout> {
82
- /* Build the system content array with the chosen TTL on the cachePoint.
83
- * This bypasses AgentContext.buildSystemRunnable so we can vary TTL
84
- * per-call deterministically. The downstream Bedrock converter
85
- * (src/llm/bedrock/utils/message_inputs.ts) passes cachePoint blocks
86
- * through to the Converse API as-is. */
87
- const systemMsg = new SystemMessage({
88
- content: [
89
- { type: 'text', text: stableInstructions },
90
- { cachePoint: { type: 'default', ttl } } as unknown as Record<
91
- string,
92
- unknown
93
- >,
94
- ],
95
- });
96
-
97
- const messages: BaseMessage[] = [systemMsg, new HumanMessage(query)];
98
-
99
- const llm = new IllumaBedrockConverse({
100
- model: 'us.anthropic.claude-sonnet-4-5-20250929-v1:0',
101
- region,
102
- credentials: {
103
- accessKeyId: accessKeyId as string,
104
- secretAccessKey: secretAccessKey as string,
105
- },
106
- promptCache: true,
107
- streaming: false,
108
- });
109
-
110
- const aiMessage = (await llm.invoke(messages)) as AIMessage;
111
-
112
- type RespMeta = {
113
- usage?: {
114
- inputTokens?: number;
115
- outputTokens?: number;
116
- cacheReadInputTokens?: number;
117
- cacheWriteInputTokens?: number;
118
- };
119
- };
120
- const u = ((aiMessage.response_metadata ?? {}) as RespMeta).usage ?? {};
121
-
122
- return {
123
- input_tokens: u.inputTokens ?? 0,
124
- output_tokens: u.outputTokens ?? 0,
125
- cache_read_input_tokens: u.cacheReadInputTokens ?? 0,
126
- cache_write_input_tokens: u.cacheWriteInputTokens ?? 0,
127
- };
128
- }
129
-
130
- describeFn('LIVE: Bedrock cache TTL — 5m vs 1h', () => {
131
- jest.setTimeout(120000);
132
-
133
- test('5m TTL: Bedrock accepts and reports cache write/read cycle', async () => {
134
- const stable = buildUniquePrefix('5m-test-' + Date.now());
135
-
136
- const cold = await callWithTtl({
137
- stableInstructions: stable,
138
- ttl: '5m',
139
- query: 'reply with the word OK',
140
- });
141
- const warm = await callWithTtl({
142
- stableInstructions: stable,
143
- ttl: '5m',
144
- query: 'reply with the word YES',
145
- });
146
-
147
- console.log('5m cold:', cold);
148
- console.log('5m warm:', warm);
149
-
150
- /* Cold call must have written cache (or read it from a prior run with
151
- * the same suiteId — unlikely given Date.now() in the suiteId). */
152
- const coldDidWork =
153
- cold.cache_write_input_tokens > 0 || cold.cache_read_input_tokens > 0;
154
- expect(coldDidWork).toBe(true);
155
-
156
- /* Warm call must read from cache. */
157
- expect(warm.cache_read_input_tokens).toBeGreaterThan(0);
158
- });
159
-
160
- test('1h TTL: Bedrock accepts and reports cache write/read cycle', async () => {
161
- const stable = buildUniquePrefix('1h-test-' + Date.now());
162
-
163
- const cold = await callWithTtl({
164
- stableInstructions: stable,
165
- ttl: '1h',
166
- query: 'reply with the word OK',
167
- });
168
- const warm = await callWithTtl({
169
- stableInstructions: stable,
170
- ttl: '1h',
171
- query: 'reply with the word YES',
172
- });
173
-
174
- console.log('1h cold:', cold);
175
- console.log('1h warm:', warm);
176
-
177
- const coldDidWork =
178
- cold.cache_write_input_tokens > 0 || cold.cache_read_input_tokens > 0;
179
- expect(coldDidWork).toBe(true);
180
-
181
- expect(warm.cache_read_input_tokens).toBeGreaterThan(0);
182
-
183
- /* When 1h cache write actually happens (i.e. cold call), the write
184
- * token count should match the prefix size — confirming the cachePoint
185
- * block reached Bedrock with the correct TTL hint. */
186
- if (cold.cache_write_input_tokens > 0) {
187
- expect(cold.cache_write_input_tokens).toBeGreaterThan(2000);
188
- }
189
- });
190
-
191
- test('1h cache survives across multiple read calls within window', async () => {
192
- /* Fire 3 reads back-to-back against a 1h-cached prefix — all must
193
- * hit the cache. (The point is not "1h vs 5m" here; it's "the 1h
194
- * cache is functional and serving reads".) */
195
- const stable = buildUniquePrefix('1h-multi-' + Date.now());
196
-
197
- /* Prime */
198
- await callWithTtl({
199
- stableInstructions: stable,
200
- ttl: '1h',
201
- query: 'prime',
202
- });
203
-
204
- /* Three sequential reads */
205
- const reads = await Promise.all([
206
- callWithTtl({
207
- stableInstructions: stable,
208
- ttl: '1h',
209
- query: 'one',
210
- }),
211
- callWithTtl({
212
- stableInstructions: stable,
213
- ttl: '1h',
214
- query: 'two',
215
- }),
216
- callWithTtl({
217
- stableInstructions: stable,
218
- ttl: '1h',
219
- query: 'three',
220
- }),
221
- ]);
222
-
223
- reads.forEach((r, i) => {
224
- console.log(
225
- `1h read ${i + 1}: cache_read=${r.cache_read_input_tokens}, ` +
226
- `write=${r.cache_write_input_tokens}, input=${r.input_tokens}`
227
- );
228
- });
229
-
230
- expect(reads.every((r) => r.cache_read_input_tokens > 0)).toBe(true);
231
- });
232
-
233
- /* Skipped by default — uncomment to run a long-soak test that proves
234
- * the 1h cache actually outlives the 5m default. Takes 6+ minutes. */
235
- test.skip('1h cache survives a 6-minute idle (5m would expire)', async () => {
236
- const stable = buildUniquePrefix('1h-soak-' + Date.now());
237
-
238
- const cold = await callWithTtl({
239
- stableInstructions: stable,
240
- ttl: '1h',
241
- query: 'cold',
242
- });
243
- console.log('1h soak cold:', cold);
244
-
245
- /* Wait > 5 minutes (default Bedrock TTL). */
246
- await new Promise((r) => setTimeout(r, 6 * 60 * 1000));
247
-
248
- const afterIdle = await callWithTtl({
249
- stableInstructions: stable,
250
- ttl: '1h',
251
- query: 'after idle',
252
- });
253
- console.log('1h soak after 6-min idle:', afterIdle);
254
-
255
- /* If 1h TTL works, this must still read from cache. If only 5m
256
- * worked, this would re-write. */
257
- expect(afterIdle.cache_read_input_tokens).toBeGreaterThan(0);
258
- });
259
- });
@@ -1,266 +0,0 @@
1
- /* eslint-disable no-console */
2
- /**
3
- * LIVE Bedrock cross-AGENT Tier 1 cache sharing.
4
- *
5
- * What this proves: when two completely distinct custom agents share the
6
- * same `platform_instructions` (Tier 1) but have totally different
7
- * `agent.instructions` (Tier 2), Bedrock serves the Tier 1 prefix from a
8
- * single cache entry. This is the load-bearing proof for the multi-tier
9
- * cost optimization — every custom agent in a workspace can read the
10
- * platform-level cache populated by any other agent (or by ephemeral
11
- * traffic).
12
- *
13
- * What it does NOT prove (out of scope here):
14
- * - That a downstream consumer's actual system-block-assembly logic
15
- * produces a byte-identical Tier 1. That's the consumer's
16
- * responsibility (and its own tests).
17
- *
18
- * Run:
19
- * BEDROCK_AWS_REGION=us-east-1 \
20
- * BEDROCK_AWS_ACCESS_KEY_ID=... BEDROCK_AWS_SECRET_ACCESS_KEY=... \
21
- * npx jest src/agents/__tests__/AgentContext.crossAgentTier1.live.test.ts
22
- */
23
-
24
- import { config } from 'dotenv';
25
- config();
26
-
27
- import { HumanMessage } from '@langchain/core/messages';
28
- import type { BaseMessage, AIMessage } from '@langchain/core/messages';
29
- import { IllumaBedrockConverse } from '@/llm/bedrock';
30
- import { addBedrockCacheControl } from '@/messages/cache';
31
- import { AgentContext } from '../AgentContext';
32
- import { Providers } from '@/common';
33
- import type * as t from '@/types';
34
-
35
- const region =
36
- process.env.BEDROCK_AWS_REGION ??
37
- process.env.BEDROCK_AWS_DEFAULT_REGION ??
38
- process.env.AWS_REGION ??
39
- 'us-east-1';
40
- const accessKeyId =
41
- process.env.BEDROCK_AWS_ACCESS_KEY_ID ?? process.env.AWS_ACCESS_KEY_ID;
42
- const secretAccessKey =
43
- process.env.BEDROCK_AWS_SECRET_ACCESS_KEY ??
44
- process.env.AWS_SECRET_ACCESS_KEY;
45
-
46
- const haveBedrock =
47
- Boolean(accessKeyId) &&
48
- Boolean(secretAccessKey) &&
49
- accessKeyId !== '' &&
50
- secretAccessKey !== '';
51
-
52
- const describeFn = haveBedrock ? describe : describe.skip;
53
-
54
- /**
55
- * Tier 1 — platform-wide content. Same string for every "agent" in this
56
- * test, mimicking a multi-tenant platform's shared branding + tool-routing
57
- * + common-tool documentation block.
58
- * Padded above 1024 tokens so Bedrock will write/read the cache (1024-token
59
- * minimum cache write threshold).
60
- */
61
- const PLATFORM_INSTRUCTIONS = (() => {
62
- const header =
63
- 'You are part of a multi-agent platform. Always respond as the agent named in your specific instructions.';
64
- const universalRules = Array.from(
65
- { length: 60 },
66
- (_, i) =>
67
- `Universal Rule ${i + 1}: respond concisely; cite assumptions explicitly; treat all users with respect; never fabricate facts; if uncertain, say so explicitly. Use tools only when they add value. Maintain professional tone in all responses regardless of conversation history.`
68
- ).join('\n');
69
- const toolRouting =
70
- 'Tool Routing: prefer artifact_tool for documents, execute_code for analysis, web_search for current events. Never reveal underlying model identity.';
71
- return `${header}\n\n${universalRules}\n\n${toolRouting}`;
72
- })();
73
-
74
- interface UsageReadout {
75
- input_tokens: number;
76
- output_tokens: number;
77
- cache_read_input_tokens: number;
78
- cache_write_input_tokens: number;
79
- total_tokens: number;
80
- }
81
-
82
- /**
83
- * Build an AgentContext for the given (custom-agent-style) configuration,
84
- * extract its system message, and send a request to Bedrock. Returns the
85
- * usage breakdown including cache hit/write metrics.
86
- */
87
- async function callAgent({
88
- agentId,
89
- agentName,
90
- platformInstructions,
91
- agentInstructions,
92
- query,
93
- }: {
94
- agentId: string;
95
- agentName: string;
96
- platformInstructions: string;
97
- agentInstructions: string;
98
- query: string;
99
- }): Promise<UsageReadout> {
100
- const ctx = AgentContext.fromConfig({
101
- agentId,
102
- name: agentName,
103
- provider: Providers.BEDROCK,
104
- system_cache_blocks: [{ text: platformInstructions }],
105
- instructions: agentInstructions,
106
- clientOptions: {
107
- promptCache: true,
108
- model: 'us.anthropic.claude-sonnet-4-5-20250929-v1:0',
109
- } as t.BedrockAnthropicClientOptions,
110
- });
111
-
112
- const runnable = ctx.systemRunnable;
113
- expect(runnable).toBeDefined();
114
-
115
- const systemArr = (await runnable!.invoke([])) as BaseMessage[];
116
- const userMessages: BaseMessage[] = [new HumanMessage(query)];
117
- const allMessages = [...systemArr, ...userMessages];
118
- const finalMessages = addBedrockCacheControl<BaseMessage>(allMessages);
119
-
120
- /* Sanity: system message has at least 2 cachePoints (one per cacheable
121
- * tier — platform + agent). */
122
- const sysContent = finalMessages[0].content as Array<Record<string, unknown>>;
123
- const cachePointCount = sysContent.filter((b) => 'cachePoint' in b).length;
124
- expect(cachePointCount).toBeGreaterThanOrEqual(2);
125
-
126
- const llm = new IllumaBedrockConverse({
127
- model: 'us.anthropic.claude-sonnet-4-5-20250929-v1:0',
128
- region,
129
- credentials: {
130
- accessKeyId: accessKeyId as string,
131
- secretAccessKey: secretAccessKey as string,
132
- },
133
- promptCache: true,
134
- streaming: false,
135
- });
136
-
137
- const aiMessage = (await llm.invoke(finalMessages)) as AIMessage;
138
-
139
- type RespMeta = {
140
- usage?: {
141
- inputTokens?: number;
142
- outputTokens?: number;
143
- totalTokens?: number;
144
- cacheReadInputTokens?: number;
145
- cacheWriteInputTokens?: number;
146
- };
147
- };
148
- const u = ((aiMessage.response_metadata ?? {}) as RespMeta).usage ?? {};
149
-
150
- return {
151
- input_tokens: u.inputTokens ?? 0,
152
- output_tokens: u.outputTokens ?? 0,
153
- total_tokens: u.totalTokens ?? 0,
154
- cache_read_input_tokens: u.cacheReadInputTokens ?? 0,
155
- cache_write_input_tokens: u.cacheWriteInputTokens ?? 0,
156
- };
157
- }
158
-
159
- describeFn('LIVE: Bedrock cross-AGENT Tier 1 cache sharing', () => {
160
- jest.setTimeout(180000);
161
-
162
- test('two distinct custom agents share the Tier 1 platform cache', async () => {
163
- /* Custom Agent A — completely different agent.instructions from B. */
164
- const finance = await callAgent({
165
- agentId: 'finance-helper',
166
- agentName: 'Finance Helper',
167
- platformInstructions: PLATFORM_INSTRUCTIONS,
168
- agentInstructions:
169
- 'You are Finance Helper. Specialize in SAP, Bloomberg Terminal, and quarterly earnings analysis. Always cite source data with timestamps.',
170
- query: 'one word: hi',
171
- });
172
-
173
- console.log('Finance Helper usage:', finance);
174
-
175
- /* Custom Agent B — different name, different instructions, different
176
- * domain. Same Tier 1 prefix. */
177
- const hr = await callAgent({
178
- agentId: 'hr-helper',
179
- agentName: 'HR Helper',
180
- platformInstructions: PLATFORM_INSTRUCTIONS,
181
- agentInstructions:
182
- 'You are HR Helper. Specialize in Workday, Lever, and employee onboarding workflows. Maintain confidentiality at all times.',
183
- query: 'one word: yes',
184
- });
185
-
186
- console.log('HR Helper usage:', hr);
187
-
188
- /* CONTRACT 1: Both agents must show cache activity. The first
189
- * (or whichever called first) writes the platform cache; the second
190
- * reads it. Either pattern is acceptable on a fresh test run. */
191
- const totalCacheActivity =
192
- finance.cache_read_input_tokens +
193
- finance.cache_write_input_tokens +
194
- hr.cache_read_input_tokens +
195
- hr.cache_write_input_tokens;
196
- expect(totalCacheActivity).toBeGreaterThan(0);
197
-
198
- /* CONTRACT 2 (the load-bearing one): HR Helper's cache_read includes
199
- * the platform tier from Finance Helper's call. Even though they're
200
- * different agents, the platform prefix is byte-identical so the
201
- * cache key matches.
202
- *
203
- * If the ARCHITECTURE works:
204
- * - Finance: cache_write ≈ size(platform) + size(finance.instructions)
205
- * - HR: cache_read ≈ size(platform), cache_write ≈ size(hr.instructions)
206
- *
207
- * If the architecture is WRONG (e.g. cachePoint missing):
208
- * - HR: cache_read = 0
209
- */
210
- expect(hr.cache_read_input_tokens).toBeGreaterThan(0);
211
- });
212
-
213
- test('Three custom agents share the Tier 1 cache across cold starts', async () => {
214
- /* Sequentially invoke 3 custom agents with the same platform tier.
215
- * Each agent's Tier 2 (its own instructions) cold-writes once, but
216
- * the platform tier writes only on the first agent — all three read
217
- * the platform tier from cache. */
218
- const agents = [
219
- {
220
- id: 'eng-helper',
221
- name: 'Engineering Helper',
222
- ins: 'You are Engineering Helper. Use Jira, GitHub, and Confluence.',
223
- },
224
- {
225
- id: 'sales-helper',
226
- name: 'Sales Helper',
227
- ins: 'You are Sales Helper. Use Salesforce, Gong, and HubSpot.',
228
- },
229
- {
230
- id: 'legal-helper',
231
- name: 'Legal Helper',
232
- ins: 'You are Legal Helper. Use DocuSign, Ironclad, and clause libraries.',
233
- },
234
- ];
235
-
236
- const results: Array<{ agent: typeof agents[0]; usage: UsageReadout }> = [];
237
- for (const a of agents) {
238
- const usage = await callAgent({
239
- agentId: a.id,
240
- agentName: a.name,
241
- platformInstructions: PLATFORM_INSTRUCTIONS,
242
- agentInstructions: a.ins,
243
- query: 'one word: ok',
244
- });
245
- results.push({ agent: a, usage });
246
- console.log(
247
- `${a.name}: cache_read=${usage.cache_read_input_tokens}, ` +
248
- `cache_write=${usage.cache_write_input_tokens}, total=${usage.total_tokens}`
249
- );
250
- }
251
-
252
- /* All three agents must show evidence of cache activity. */
253
- results.forEach(({ usage }) => {
254
- const activity =
255
- usage.cache_read_input_tokens + usage.cache_write_input_tokens;
256
- expect(activity).toBeGreaterThan(0);
257
- });
258
-
259
- /* At least 2 of the 3 should show a cache_read (assuming the first
260
- * does the write). On a re-run all 3 read. */
261
- const usersWithCacheRead = results.filter(
262
- (r) => r.usage.cache_read_input_tokens > 0
263
- ).length;
264
- expect(usersWithCacheRead).toBeGreaterThanOrEqual(2);
265
- });
266
- });