@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
@@ -38,7 +38,6 @@ import type { BaseMessage } from '@langchain/core/messages';
38
38
  import { ChatGenerationChunk, ChatResult } from '@langchain/core/outputs';
39
39
  import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
40
40
  import type { ChatBedrockConverseInput } from '@langchain/aws';
41
- import { isBedrockCacheSupported } from './cacheSupport';
42
41
  import {
43
42
  convertToConverseMessages,
44
43
  handleConverseStreamContentBlockStart,
@@ -53,72 +52,19 @@ import {
53
52
  */
54
53
  export type ServiceTierType = 'priority' | 'default' | 'flex' | 'reserved';
55
54
 
56
- /**
57
- * Tool cachePoint allocation strategy.
58
- *
59
- * - 'single': one cachePoint at the END of the tools array (whole array
60
- * cached as one unit). Lightest budget use (1 cachePoint).
61
- * - 'split': split tools into groups via `toolGroupSelector`. Each
62
- * non-empty group gets its own cachePoint. Use when groups
63
- * have different volatility (e.g. stable core tools vs
64
- * volatile MCP tools). Costs more cachePoint budget.
65
- * - 'none': no cachePoint on tools array. Use when tool definitions
66
- * change every request anyway.
67
- */
68
- export type ToolCacheStrategy = 'single' | 'split' | 'none';
69
-
70
- /**
71
- * Group selector for `toolCacheStrategy: 'split'`. Receives the tool name
72
- * and returns a stable group key — tools with the same key are grouped
73
- * together. Group order in the output array follows first-encounter order.
74
- */
75
- export type ToolGroupSelector = (toolName: string) => string;
76
-
77
- /**
78
- * Default group selector — puts all tools in a single group named 'core'.
79
- * Equivalent to 'single' strategy but explicit. Consumers override this
80
- * to enable per-source grouping (e.g. by inspecting tool-name substrings
81
- * to separate stable framework tools from volatile MCP-sourced tools).
82
- */
83
- export const DEFAULT_TOOL_GROUP_SELECTOR: ToolGroupSelector = () => 'core';
84
-
85
55
  /**
86
56
  * Extended input interface with additional features:
87
57
  * - promptCache: Enable Bedrock prompt caching for tool definitions
88
58
  * - applicationInferenceProfile: Use an inference profile ARN instead of model ID
89
59
  * - serviceTier: Specify service tier (Priority, Standard, Flex, Reserved)
90
- * - toolCacheStrategy: How to allocate cachePoints across tools array
91
- * - toolGroupSelector: Group key resolver for the 'split' strategy
92
60
  */
93
61
  export interface IllumaBedrockConverseInput extends ChatBedrockConverseInput {
94
62
  /**
95
63
  * Enable Bedrock prompt caching for tool definitions.
96
- * When true, adds cachePoint marker(s) to tools array per
97
- * `toolCacheStrategy`. Defaults to 'single'.
64
+ * When true, adds cachePoint markers to tools array.
98
65
  */
99
66
  promptCache?: boolean;
100
67
 
101
- /**
102
- * Tool cachePoint allocation. Defaults to 'single' — one cachePoint at
103
- * the end of the tools array. Set to 'split' (with `toolGroupSelector`)
104
- * when different tool groups have different volatility.
105
- */
106
- toolCacheStrategy?: ToolCacheStrategy;
107
-
108
- /**
109
- * Group selector for 'split' strategy. Receives a tool name, returns
110
- * a stable group key. Defaults to a one-group selector (equivalent
111
- * to 'single').
112
- */
113
- toolGroupSelector?: ToolGroupSelector;
114
-
115
- /**
116
- * Additional model ID patterns to consider Bedrock-cache-supported.
117
- * Defaults are in `src/llm/bedrock/cacheSupport.ts`. Use this when
118
- * AWS adds a new model family before the next library release.
119
- */
120
- bedrockCacheModelPatterns?: readonly RegExp[];
121
-
122
68
  /**
123
69
  * Application Inference Profile ARN to use for the model.
124
70
  * For example, "arn:aws:bedrock:eu-west-1:123456789102:application-inference-profile/fm16bt65tzgx"
@@ -162,24 +108,11 @@ export class IllumaBedrockConverse extends ChatBedrockConverse {
162
108
  /** Service tier for model invocation */
163
109
  serviceTier?: ServiceTierType;
164
110
 
165
- /** Tool cachePoint allocation strategy. */
166
- toolCacheStrategy: ToolCacheStrategy;
167
-
168
- /** Group selector for 'split' strategy. */
169
- toolGroupSelector: ToolGroupSelector;
170
-
171
- /** Optional consumer extensions to the cache-supported model allowlist. */
172
- bedrockCacheModelPatterns?: readonly RegExp[];
173
-
174
111
  constructor(fields?: IllumaBedrockConverseInput) {
175
112
  super(fields);
176
113
  this.promptCache = fields?.promptCache ?? false;
177
114
  this.applicationInferenceProfile = fields?.applicationInferenceProfile;
178
115
  this.serviceTier = fields?.serviceTier;
179
- this.toolCacheStrategy = fields?.toolCacheStrategy ?? 'single';
180
- this.toolGroupSelector =
181
- fields?.toolGroupSelector ?? DEFAULT_TOOL_GROUP_SELECTOR;
182
- this.bedrockCacheModelPatterns = fields?.bedrockCacheModelPatterns;
183
116
 
184
117
  // Fix: Force supportsToolChoiceValues for Claude models
185
118
  // The parent constructor checks `model.includes('claude-3')` but this fails when:
@@ -250,64 +183,56 @@ export class IllumaBedrockConverse extends ChatBedrockConverse {
250
183
  }
251
184
  }
252
185
 
253
- /* Allowlist-based gate (see cacheSupport.ts). Replaces the old
254
- * substring heuristic — same default behavior for Claude/Anthropic/
255
- * Nova models, plus extension via `bedrockCacheModelPatterns`. */
256
- const cacheSupported = isBedrockCacheSupported(
257
- this.model,
258
- this.bedrockCacheModelPatterns,
259
- );
186
+ // Only Claude models support cachePoint - check model name
187
+ const modelId = this.model.toLowerCase();
188
+ const isClaudeModel =
189
+ modelId.includes('claude') || modelId.includes('anthropic');
260
190
 
261
191
  if (
262
192
  this.promptCache &&
263
- cacheSupported &&
264
- this.toolCacheStrategy !== 'none' &&
193
+ isClaudeModel &&
265
194
  params.toolConfig?.tools &&
266
195
  Array.isArray(params.toolConfig.tools) &&
267
196
  params.toolConfig.tools.length > 0
268
197
  ) {
269
- const tools = params.toolConfig.tools;
270
-
271
- if (this.toolCacheStrategy === 'single') {
272
- /* SINGLE: one cachePoint at the end of the tools array. Lightest
273
- * budget use; appropriate when the entire tools array is treated
274
- * as one unit and changes together. */
275
- const toolsWithCache = [
276
- ...tools,
277
- { cachePoint: { type: 'default' } } as (typeof tools)[number],
278
- ];
279
- params.toolConfig.tools = toolsWithCache;
280
- } else if (this.toolCacheStrategy === 'split') {
281
- /* SPLIT: group tools by `toolGroupSelector` and emit a cachePoint
282
- * after each non-empty group. Group order follows first-encounter
283
- * order in the input. Use when groups have different volatility
284
- * (e.g. stable core tools + volatile MCP tools). */
285
- const groupOrder: string[] = [];
286
- const groupMap = new Map<string, typeof tools>();
287
- for (const tool of tools) {
288
- const toolName =
289
- (tool as { toolSpec?: { name?: string } }).toolSpec?.name ?? '';
290
- const groupKey = this.toolGroupSelector(toolName);
291
- let group = groupMap.get(groupKey);
292
- if (!group) {
293
- group = [];
294
- groupMap.set(groupKey, group);
295
- groupOrder.push(groupKey);
296
- }
297
- group.push(tool);
198
+ // Separate core tools from MCP tools
199
+ // MCP tools have '_mcp_' in their name (e.g., 'search_emails_mcp_Google-Workspace')
200
+ const coreTools: typeof params.toolConfig.tools = [];
201
+ const mcpTools: typeof params.toolConfig.tools = [];
202
+
203
+ for (const tool of params.toolConfig.tools) {
204
+ // Check if tool has a name property with '_mcp_' pattern
205
+ const toolName =
206
+ (tool as { toolSpec?: { name?: string } }).toolSpec?.name ?? '';
207
+ if (toolName.includes('_mcp_')) {
208
+ mcpTools.push(tool);
209
+ } else {
210
+ coreTools.push(tool);
298
211
  }
212
+ }
299
213
 
300
- const toolsWithCache: typeof tools = [];
301
- for (const groupKey of groupOrder) {
302
- const group = groupMap.get(groupKey);
303
- if (!group || group.length === 0) continue;
304
- toolsWithCache.push(...group);
305
- toolsWithCache.push(
306
- { cachePoint: { type: 'default' } } as (typeof tools)[number],
307
- );
308
- }
309
- params.toolConfig.tools = toolsWithCache;
214
+ // Build tools array with strategic cachePoints:
215
+ // [CoreTool1, CoreTool2, cachePoint] + [MCPTool1, MCPTool2, cachePoint]
216
+ const toolsWithCache: typeof params.toolConfig.tools = [];
217
+
218
+ // Add core tools with cachePoint (if any)
219
+ if (coreTools.length > 0) {
220
+ toolsWithCache.push(...coreTools);
221
+ toolsWithCache.push({ cachePoint: { type: 'default' } });
222
+ }
223
+
224
+ // Add MCP tools with their own cachePoint (if any)
225
+ if (mcpTools.length > 0) {
226
+ toolsWithCache.push(...mcpTools);
227
+ toolsWithCache.push({ cachePoint: { type: 'default' } });
228
+ }
229
+
230
+ // If no tools at all (shouldn't happen but safety check)
231
+ if (toolsWithCache.length === 0) {
232
+ toolsWithCache.push({ cachePoint: { type: 'default' } });
310
233
  }
234
+
235
+ params.toolConfig.tools = toolsWithCache;
311
236
  }
312
237
 
313
238
  // Add serviceTier support
@@ -896,8 +896,8 @@ export interface XAIUsageMetadata
896
896
  }
897
897
 
898
898
  export class ChatMoonshot extends ChatOpenAI {
899
- static lc_name(): 'IllumaMoonshot' {
900
- return 'IllumaMoonshot';
899
+ static lc_name(): 'LibreChatMoonshot' {
900
+ return 'LibreChatMoonshot';
901
901
  }
902
902
 
903
903
  protected _convertMessages(messages: BaseMessage[]): OpenAICompletionParam[] {
@@ -302,10 +302,6 @@ export function _convertMessagesToOpenAIParams(
302
302
  model?: string,
303
303
  options?: ConvertMessagesOptions
304
304
  ): OpenAICompletionParam[] {
305
- /* DeepSeek reasoning roundtrip (PR #136): reasoning_content on
306
- * an AI message must be re-sent only when the message participates in a
307
- * tool-call exchange. Track context across the message flat-map. */
308
- let hasReasoningToolCallContext = false;
309
305
  // TODO: Function messages do not support array content, fix cast
310
306
  return messages.flatMap((message) => {
311
307
  let role = messageToOpenAIRole(message);
@@ -336,8 +332,6 @@ export function _convertMessagesToOpenAIParams(
336
332
  role,
337
333
  content,
338
334
  };
339
- let messageHasToolCalls = false;
340
- let messageIsToolResult = false;
341
335
  if (message.name != null) {
342
336
  completionParam.name = message.name;
343
337
  }
@@ -346,11 +340,17 @@ export function _convertMessagesToOpenAIParams(
346
340
  completionParam.content = '';
347
341
  }
348
342
  if (isAIMessage(message) && !!message.tool_calls?.length) {
349
- messageHasToolCalls = true;
350
343
  completionParam.tool_calls = message.tool_calls.map(
351
344
  convertLangChainToolCallToOpenAI
352
345
  );
353
346
  completionParam.content = hasAnthropicThinkingBlock ? content : '';
347
+ if (
348
+ options?.includeReasoningContent === true &&
349
+ message.additional_kwargs.reasoning_content != null
350
+ ) {
351
+ completionParam.reasoning_content =
352
+ message.additional_kwargs.reasoning_content;
353
+ }
354
354
  if (
355
355
  options?.includeReasoningDetails === true &&
356
356
  message.additional_kwargs.reasoning_details != null
@@ -398,10 +398,14 @@ export function _convertMessagesToOpenAIParams(
398
398
  }
399
399
  } else {
400
400
  if (message.additional_kwargs.tool_calls != null) {
401
- messageHasToolCalls =
402
- !Array.isArray(message.additional_kwargs.tool_calls) ||
403
- message.additional_kwargs.tool_calls.length > 0;
404
401
  completionParam.tool_calls = message.additional_kwargs.tool_calls;
402
+ if (
403
+ options?.includeReasoningContent === true &&
404
+ message.additional_kwargs.reasoning_content != null
405
+ ) {
406
+ completionParam.reasoning_content =
407
+ message.additional_kwargs.reasoning_content;
408
+ }
405
409
  if (
406
410
  options?.includeReasoningDetails === true &&
407
411
  message.additional_kwargs.reasoning_details != null
@@ -449,31 +453,10 @@ export function _convertMessagesToOpenAIParams(
449
453
  }
450
454
  }
451
455
  if ((message as ToolMessage).tool_call_id != null) {
452
- messageIsToolResult = true;
453
456
  completionParam.tool_call_id = (message as ToolMessage).tool_call_id;
454
457
  }
455
458
  }
456
459
 
457
- /* DeepSeek reasoning roundtrip (PR #136): emit
458
- * reasoning_content only when the message is part of a tool-call
459
- * exchange — either the message itself has tool_calls, or a previous
460
- * AI/tool message established the context. Skipping the gate causes
461
- * DeepSeek to drop reasoning content during multi-turn replays. */
462
- if (
463
- options?.includeReasoningContent === true &&
464
- isAIMessage(message) &&
465
- (hasReasoningToolCallContext || messageHasToolCalls) &&
466
- typeof message.additional_kwargs.reasoning_content === 'string' &&
467
- message.additional_kwargs.reasoning_content !== ''
468
- ) {
469
- completionParam.reasoning_content =
470
- message.additional_kwargs.reasoning_content;
471
- }
472
-
473
- if (messageHasToolCalls || messageIsToolResult) {
474
- hasReasoningToolCallContext = true;
475
- }
476
-
477
460
  if (
478
461
  message.additional_kwargs.audio &&
479
462
  typeof message.additional_kwargs.audio === 'object' &&
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Citation decoration — Phase 2.
3
3
  *
4
- * Ported from a reference implementation `extensions/memory-core/src/tools.citations.ts`.
4
+ * Ported from upstream `extensions/memory-core/src/tools.citations.ts`.
5
5
  * Decorates memory_search hits with `[path#L{start}-L{end}]` markers so
6
6
  * the model can attribute claims back to specific memory files when it
7
7
  * uses them in its answer.
@@ -10,7 +10,7 @@
10
10
  * compute line ranges from the returned content block on the fly:
11
11
  * - `startLine` = 1 (line 1 of the file)
12
12
  * - `endLine` = total number of lines in the block
13
- * This matches the standard output format exactly while keeping the pg
13
+ * This matches upstream's output format exactly while keeping the pg
14
14
  * schema chunk-free.
15
15
  */
16
16
 
@@ -48,7 +48,7 @@ function formatCitation(
48
48
  }
49
49
 
50
50
  /**
51
- * Decorate each hit with a citation marker. Mirrors the standard behavior:
51
+ * Decorate each hit with a citation marker. Mirrors upstream's behavior:
52
52
  * appends `\n\nSource: <citation>` to the content and sets `citation`.
53
53
  * When `include=false`, clears any existing citation field.
54
54
  */
@@ -69,7 +69,7 @@ export function decorateCitations<T extends CitationCandidate>(
69
69
  /**
70
70
  * Whether citations should be emitted for this call.
71
71
  *
72
- * The reference implementation keys `auto` off the session type (direct/group/channel). In
72
+ * Upstream keys `auto` off the session type (direct/group/channel). In
73
73
  * Phase 1 we only have direct chat, so `auto` => `on`. Callers that
74
74
  * later distinguish session types can pass `mode` explicitly.
75
75
  */
@@ -26,14 +26,14 @@ export const MEMORY_PHASE_NORMAL = 'normal';
26
26
  export const MEMORY_PHASE_FLUSHING = 'memory_flushing';
27
27
 
28
28
  /**
29
- * Search defaults — aligned with the standard defaults.
29
+ * Search defaults — aligned with upstream's upstream defaults.
30
30
  *
31
31
  * Sources:
32
- * - `reference` → maxResults=6
33
- * - `reference` → maxInjectedChars=4000
32
+ * - `upstream reference` → maxResults=6
33
+ * - `upstream reference` → maxInjectedChars=4000
34
34
  *
35
- * Keeping these in lockstep with means the mandatory-recall tool
36
- * description, budget clamps, and eval corpora line up with the standard
35
+ * Keeping these in lockstep with upstream means the mandatory-recall tool
36
+ * description, budget clamps, and eval corpora line up with upstream's
37
37
  * tuning — we inherit their calibration instead of re-tuning from scratch.
38
38
  */
39
39
  export const DEFAULT_MAX_SEARCH_RESULTS = 6;
@@ -45,11 +45,11 @@ export const HYBRID_VECTOR_WEIGHT = 0.7;
45
45
  export const HYBRID_TEXT_WEIGHT = 0.3;
46
46
 
47
47
  /**
48
- * Phase 2 rerank defaults — ported from a reference implementation.
48
+ * Phase 2 rerank defaults — ported from upstream.
49
49
  *
50
50
  * Sources:
51
- * - `reference` → lambda=0.7
52
- * - `reference` → halfLifeDays=30
51
+ * - `upstream reference` → lambda=0.7
52
+ * - `upstream reference` → halfLifeDays=30
53
53
  *
54
54
  * Both features are opt-in (enabled=false by default) — the Phase 2
55
55
  * features are layered on top of hybrid search and don't change default
@@ -63,11 +63,11 @@ export const DEFAULT_RECALL_TRACKING_ENABLED = false;
63
63
  export const DEFAULT_CITATIONS_MODE = 'auto' as const;
64
64
 
65
65
  /**
66
- * Flush trigger margins (token counts) — aligned with standard.
66
+ * Flush trigger margins (token counts) — aligned with upstream upstream.
67
67
  *
68
68
  * Sources:
69
- * - `reference` → softThreshold=4000
70
- * - `reference` → reserveFloor=20000
69
+ * - `upstream reference` → softThreshold=4000
70
+ * - `upstream reference` → reserveFloor=20000
71
71
  */
72
72
  export const DEFAULT_FLUSH_SOFT_THRESHOLD_TOKENS = 4000;
73
73
  export const DEFAULT_FLUSH_RESERVE_FLOOR_TOKENS = 20000;
@@ -79,7 +79,7 @@ export const DEFAULT_MAX_APPENDS_PER_FLUSH = 20;
79
79
  * Hard cap on agentic loop iterations inside {@link runMemoryFlush}.
80
80
  *
81
81
  * Each iteration = one model.invoke() followed by execution of any
82
- * `memory_append` tool_calls it emits. Mirrors the standard flush-plan
82
+ * `memory_append` tool_calls it emits. Mirrors upstream's flush-plan
83
83
  * loop cap; 8 is enough for ~2–3 reflections of batched notes while
84
84
  * protecting against runaway cycles if the model refuses to stop.
85
85
  */
@@ -97,9 +97,9 @@ export const MEMORY_APPEND_TOOL_NAME = 'memory_append';
97
97
  * Mandatory-recall description — the single most load-bearing line in the
98
98
  * whole memory system. Do not soften, shorten, or reword without an eval run.
99
99
  *
100
- * Ported VERBATIM from a reference implementation `extensions/memory-core/src/tools.ts:186`.
100
+ * Ported VERBATIM from upstream `extensions/memory-core/src/tools.ts:186`.
101
101
  * The wiki/corpus clause is retained even though Phase 1 doesn't ship
102
- * compiled-wiki supplements — keeping the string identical means the standard
102
+ * compiled-wiki supplements — keeping the string identical means upstream's
103
103
  * eval corpora remain drop-in valid.
104
104
  */
105
105
  export const MEMORY_SEARCH_DESCRIPTION =
@@ -111,7 +111,7 @@ export const MEMORY_SEARCH_DESCRIPTION =
111
111
  'unavailable and should be surfaced to the user.';
112
112
 
113
113
  /**
114
- * Ported VERBATIM from a reference implementation `extensions/memory-core/src/tools.ts:322`.
114
+ * Ported VERBATIM from upstream `extensions/memory-core/src/tools.ts:322`.
115
115
  */
116
116
  export const MEMORY_GET_DESCRIPTION =
117
117
  'Safe snippet read from MEMORY.md or memory/*.md with optional from/lines; ' +
@@ -122,7 +122,7 @@ export const MEMORY_GET_DESCRIPTION =
122
122
  * `memory_append` tool description.
123
123
  *
124
124
  * Phase 1 historically wrote to a single date-keyed file
125
- * (`memory/YYYY-MM-DD.md`), ported verbatim from a reference implementation. That scheme
125
+ * (`memory/YYYY-MM-DD.md`), ported verbatim from upstream. That scheme
126
126
  * is now replaced by an 8-path canonical whitelist — see
127
127
  * {@link ./paths.MEMORY_ALL_PATHS}. The tool description no longer
128
128
  * names a specific file; the flush-turn prompt renders the full rubric
@@ -137,7 +137,7 @@ export const MEMORY_APPEND_DESCRIPTION =
137
137
 
138
138
  /**
139
139
  * Reply token that signals the flush turn produced no user-visible output.
140
- * Ported VERBATIM from a reference implementation `src/auto-reply/tokens.ts:4`.
140
+ * Ported VERBATIM from upstream `src/auto-reply/tokens.ts:4`.
141
141
  */
142
142
  export const SILENT_REPLY_TOKEN = 'NO_REPLY';
143
143
 
package/src/memory/mmr.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Maximal Marginal Relevance (MMR) re-ranking — Phase 2.
3
3
  *
4
- * Ported from a reference implementation `extensions/memory-core/src/memory/mmr.ts` with
4
+ * Ported from upstream `extensions/memory-core/src/memory/mmr.ts` with
5
5
  * minor adaptation for our `MemoryEntry` shape (content vs snippet, id vs
6
6
  * path+startLine). Behavior is identical: normalize scores, iteratively
7
7
  * pick the item that maximizes `λ * relevance - (1-λ) * max_similarity`
@@ -11,9 +11,9 @@
11
11
  */
12
12
 
13
13
  export interface MMRConfig {
14
- /** Opt-in. Default is false. */
14
+ /** Opt-in. Upstream default is false. */
15
15
  enabled: boolean;
16
- /** 0 = max diversity, 1 = max relevance. Default 0.7. */
16
+ /** 0 = max diversity, 1 = max relevance. Upstream default 0.7. */
17
17
  lambda: number;
18
18
  }
19
19
 
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * ## Why a whitelist?
10
10
  *
11
- * Earlier historical designs used date-keyed files
11
+ * Earlier upstream-faithful designs used date-keyed files
12
12
  * (`memory/YYYY-MM-DD.md`), which have three problems for a persistent
13
13
  * multi-user agent:
14
14
  *
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Recall tracking — Phase 2.
3
3
  *
4
- * Lightweight adaptation of an external recall-tracking module
4
+ * Lightweight adaptation of upstream
5
5
  * `extensions/memory-core/src/short-term-promotion.ts::recordShortTermRecalls`.
6
- * The reference implementation stores recalls in a JSON file under `memory/.dreams/`; we store
6
+ * Upstream stores recalls in a JSON file under `memory/.dreams/`; we store
7
7
  * them in a Postgres table `agent_memory_recalls`. Schema captures what the
8
8
  * future Phase 3 dreaming/promotion algorithm will need:
9
9
  * - which memory row was surfaced (`memory_id`)
@@ -90,7 +90,7 @@ export class PgvectorRecallTracker implements RecallTracker {
90
90
  const bucket = dayBucket(nowMs);
91
91
 
92
92
  // [recall-tracking] debug: upsert one row per (agent, memory, query, day)
93
- // The reference implementation dedupes per-day per-query so repeated searches don't inflate counts.
93
+ // Upstream dedupes per-day per-query so repeated searches don't inflate counts.
94
94
  const values: string[] = [];
95
95
  const args: unknown[] = [];
96
96
  let i = 1;
@@ -1,14 +1,14 @@
1
1
  /**
2
2
  * Temporal decay — Phase 2.
3
3
  *
4
- * Ported from a reference implementation `extensions/memory-core/src/memory/temporal-decay.ts`.
4
+ * Ported from upstream `extensions/memory-core/src/memory/temporal-decay.ts`.
5
5
  * Ages dated memory files (`memory/YYYY-MM-DD.md`) using exponential decay
6
6
  * `multiplier = exp(-ln(2) / halfLifeDays * ageInDays)`. At half-life, the
7
7
  * score is exactly halved.
8
8
  *
9
9
  * Evergreen files (MEMORY.md, memory/topics.md, any non-dated file inside
10
10
  * memory/) do NOT decay — they represent durable knowledge and should stay
11
- * hot regardless of age. This mirrors the standard `isEvergreenMemoryPath`.
11
+ * hot regardless of age. This mirrors upstream's `isEvergreenMemoryPath`.
12
12
  *
13
13
  * Since our pgvector rows carry `createdAt`, we don't need filesystem stat
14
14
  * fallback — the row timestamp is authoritative for any file without a
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Autonomous memory — core types.
3
3
  *
4
- * Ported from the reference implementation's memory-core pattern, adapted for Postgres + pgvector
4
+ * Ported from upstream's memory-core pattern, adapted for Postgres + pgvector
5
5
  * and shaped so a future graph-backend layer (Graphiti, Neo4j agent-memory, etc.)
6
6
  * can be added alongside the vector store without changing the tool contracts.
7
7
  *
@@ -79,7 +79,7 @@ export interface MemorySearchOptions {
79
79
  minScore?: number;
80
80
  /**
81
81
  * Phase 2 toggles — when the backend supports them. Each is independently
82
- * opt-in; all false = Phase 1 behavior.
82
+ * opt-in; all false = upstream Phase 1 behavior.
83
83
  */
84
84
  mmr?: { enabled?: boolean; lambda?: number };
85
85
  temporalDecay?: { enabled?: boolean; halfLifeDays?: number };
@@ -156,7 +156,7 @@ export interface MemoryConfig {
156
156
  search?: {
157
157
  maxResults?: number;
158
158
  maxInjectedChars?: number;
159
- /** Phase 2 — enable MMR reranking (defaults when true). */
159
+ /** Phase 2 — enable MMR reranking (upstream-aligned defaults when true). */
160
160
  mmr?: { enabled?: boolean; lambda?: number };
161
161
  /** Phase 2 — enable temporal decay on dated memory files. */
162
162
  temporalDecay?: { enabled?: boolean; halfLifeDays?: number };
@@ -412,14 +412,7 @@ describe('addBedrockCacheControl (Bedrock cache checkpoints)', () => {
412
412
  expect(first[1]).toEqual({ cachePoint: { type: 'default' } });
413
413
  });
414
414
 
415
- it('skips system messages (cachePoint added inline by AgentContext.buildSystemRunnable)', () => {
416
- /* Contract change (PR #128 alignment): system message
417
- * cachePoint is now emitted inline in AgentContext.buildSystemRunnable.
418
- * addBedrockCacheControl must therefore SKIP system messages so the
419
- * 2-cachePoint per-request budget stays available for the conversation
420
- * tail. Caching the system prefix is what unlocks cross-user cost
421
- * savings — Bedrock's prompt cache is account-scoped, so a stable
422
- * system prefix shared across users hits the same cache entry. */
415
+ it('works with the example from the langchain pr (with multi-turn behavior)', () => {
423
416
  const messages: TestMsg[] = [
424
417
  {
425
418
  role: 'system',
@@ -437,17 +430,15 @@ describe('addBedrockCacheControl (Bedrock cache checkpoints)', () => {
437
430
 
438
431
  const result = addBedrockCacheControl(messages);
439
432
 
440
- const system = result[0].content as MessageContentComplex[];
441
- const user = result[1].content as MessageContentComplex[];
433
+ let system = result[0].content as MessageContentComplex[];
434
+ let user = result[1].content as MessageContentComplex[];
442
435
 
443
- // System message is left untouched addBedrockCacheControl does NOT
444
- // add a cachePoint here. The cachePoint is added in AgentContext when
445
- // the system message is first built.
446
- expect(system).toEqual([
447
- { type: ContentTypes.TEXT, text: 'You\'re an advanced AI assistant.' },
448
- ]);
449
-
450
- // User message still gets a cachePoint (last eligible).
436
+ // Both messages get cachePoints (last 2 eligible messages)
437
+ expect(system[0]).toEqual({
438
+ type: ContentTypes.TEXT,
439
+ text: 'You\'re an advanced AI assistant.',
440
+ });
441
+ expect(system[1]).toEqual({ cachePoint: { type: 'default' } });
451
442
  expect(user[0]).toEqual({
452
443
  type: ContentTypes.TEXT,
453
444
  text: 'What is the capital of France?',
@@ -467,59 +458,30 @@ describe('addBedrockCacheControl (Bedrock cache checkpoints)', () => {
467
458
 
468
459
  const result2 = addBedrockCacheControl(result);
469
460
 
470
- const system2 = result2[0].content as MessageContentComplex[];
471
- const user2 = result2[1].content as MessageContentComplex[];
472
- const assistant2 = result2[2].content as MessageContentComplex[];
461
+ system = result2[0].content as MessageContentComplex[];
462
+ user = result2[1].content as MessageContentComplex[];
463
+ const assistant = result2[2].content as MessageContentComplex[];
473
464
 
474
- // System message still untouched.
475
- expect(system2).toEqual([
476
- { type: ContentTypes.TEXT, text: 'You\'re an advanced AI assistant.' },
477
- ]);
465
+ // System message no longer has cachePoint (it's not in the last 2 eligible)
466
+ expect(system[0]).toEqual({
467
+ type: ContentTypes.TEXT,
468
+ text: 'You\'re an advanced AI assistant.',
469
+ });
470
+ expect(system.length).toBe(1);
478
471
 
479
- // Both conversation messages now get cachePoints (last 2 eligible).
480
- expect(user2[0]).toEqual({
472
+ // User message gets cachePoint (second-to-last eligible)
473
+ expect(user[0]).toEqual({
481
474
  type: ContentTypes.TEXT,
482
475
  text: 'What is the capital of France?',
483
476
  });
484
- expect(user2[1]).toEqual({ cachePoint: { type: 'default' } });
477
+ expect(user[1]).toEqual({ cachePoint: { type: 'default' } });
485
478
 
486
- expect(assistant2[0]).toEqual({
479
+ // Assistant message gets cachePoint (last eligible)
480
+ expect(assistant[0]).toEqual({
487
481
  type: ContentTypes.TEXT,
488
482
  text: 'Sure! The capital of France is Paris.',
489
483
  });
490
- expect(assistant2[1]).toEqual({ cachePoint: { type: 'default' } });
491
- });
492
-
493
- it('strips stray Anthropic cache_control from system message (cross-provider safety)', () => {
494
- /* If a system message arrives with an Anthropic-style cache_control
495
- * marker (e.g. cross-provider switch), addBedrockCacheControl should
496
- * sanitize it — Bedrock ignores cache_control and stale markers can
497
- * confuse provider validation. */
498
- const messages: TestMsg[] = [
499
- {
500
- role: 'system',
501
- content: [
502
- {
503
- type: ContentTypes.TEXT,
504
- text: 'You\'re an advanced AI assistant.',
505
- cache_control: { type: 'ephemeral' },
506
- } as MessageContentComplex,
507
- ],
508
- },
509
- {
510
- role: 'user',
511
- content: [{ type: ContentTypes.TEXT, text: 'Hi' }],
512
- },
513
- ];
514
-
515
- const result = addBedrockCacheControl(messages);
516
- const system = result[0].content as MessageContentComplex[];
517
-
518
- expect(system).toHaveLength(1);
519
- expect('cache_control' in system[0]).toBe(false);
520
- expect((system[0] as { text?: string }).text).toBe(
521
- 'You\'re an advanced AI assistant.'
522
- );
484
+ expect(assistant[1]).toEqual({ cachePoint: { type: 'default' } });
523
485
  });
524
486
 
525
487
  it('is idempotent - calling multiple times does not add duplicate cache points', () => {