@mxf-dev/core 2.0.5 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (466) hide show
  1. package/dist/config/ModelContextLimits.d.ts.map +1 -1
  2. package/dist/config/ModelContextLimits.js +7 -1
  3. package/dist/config/ModelContextLimits.js.map +1 -1
  4. package/dist/constants/CoreTools.d.ts +6 -5
  5. package/dist/constants/CoreTools.d.ts.map +1 -1
  6. package/dist/constants/CoreTools.js +6 -5
  7. package/dist/constants/CoreTools.js.map +1 -1
  8. package/dist/constants/DefaultPhaseProfiles.d.ts.map +1 -1
  9. package/dist/constants/DefaultPhaseProfiles.js +29 -0
  10. package/dist/constants/DefaultPhaseProfiles.js.map +1 -1
  11. package/dist/constants/ReservedIdentities.d.ts +14 -0
  12. package/dist/constants/ReservedIdentities.d.ts.map +1 -0
  13. package/dist/constants/ReservedIdentities.js +42 -0
  14. package/dist/constants/ReservedIdentities.js.map +1 -0
  15. package/dist/database/adapters/mongodb/MongoKnowledgeGraphRepository.d.ts +16 -16
  16. package/dist/database/adapters/mongodb/MongoKnowledgeGraphRepository.d.ts.map +1 -1
  17. package/dist/database/adapters/mongodb/MongoKnowledgeGraphRepository.js +98 -36
  18. package/dist/database/adapters/mongodb/MongoKnowledgeGraphRepository.js.map +1 -1
  19. package/dist/events/ClientEventBus.d.ts +28 -0
  20. package/dist/events/ClientEventBus.d.ts.map +1 -1
  21. package/dist/events/ClientEventBus.js +87 -40
  22. package/dist/events/ClientEventBus.js.map +1 -1
  23. package/dist/events/EventBus.d.ts +19 -1
  24. package/dist/events/EventBus.d.ts.map +1 -1
  25. package/dist/events/EventBus.js +23 -0
  26. package/dist/events/EventBus.js.map +1 -1
  27. package/dist/events/EventBusBase.d.ts +37 -6
  28. package/dist/events/EventBusBase.d.ts.map +1 -1
  29. package/dist/events/EventBusBase.js +75 -27
  30. package/dist/events/EventBusBase.js.map +1 -1
  31. package/dist/events/EventNames.d.ts +49 -36
  32. package/dist/events/EventNames.d.ts.map +1 -1
  33. package/dist/events/EventNames.js +38 -36
  34. package/dist/events/EventNames.js.map +1 -1
  35. package/dist/events/PublicEvents.d.ts +5 -1
  36. package/dist/events/PublicEvents.d.ts.map +1 -1
  37. package/dist/events/PublicEvents.js +7 -0
  38. package/dist/events/PublicEvents.js.map +1 -1
  39. package/dist/events/ServerEventBus.d.ts +7 -54
  40. package/dist/events/ServerEventBus.d.ts.map +1 -1
  41. package/dist/events/ServerEventBus.js +10 -96
  42. package/dist/events/ServerEventBus.js.map +1 -1
  43. package/dist/events/event-definitions/ControlLoopEvents.d.ts +35 -0
  44. package/dist/events/event-definitions/ControlLoopEvents.d.ts.map +1 -1
  45. package/dist/events/event-definitions/ControlLoopEvents.js +6 -0
  46. package/dist/events/event-definitions/ControlLoopEvents.js.map +1 -1
  47. package/dist/events/event-definitions/SdkEvents.d.ts +55 -0
  48. package/dist/events/event-definitions/SdkEvents.d.ts.map +1 -0
  49. package/dist/events/event-definitions/SdkEvents.js +36 -0
  50. package/dist/events/event-definitions/SdkEvents.js.map +1 -0
  51. package/dist/events/event-definitions/TaskEvents.d.ts +2 -7
  52. package/dist/events/event-definitions/TaskEvents.d.ts.map +1 -1
  53. package/dist/index.d.ts +4 -0
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +2 -0
  56. package/dist/index.js.map +1 -1
  57. package/dist/interfaces/AgentInterfaces.d.ts +5 -0
  58. package/dist/interfaces/AgentInterfaces.d.ts.map +1 -1
  59. package/dist/interfaces/ChannelConfig.d.ts +2 -2
  60. package/dist/interfaces/ChannelConfig.d.ts.map +1 -1
  61. package/dist/interfaces/ConversationMessage.d.ts +1 -1
  62. package/dist/interfaces/ConversationMessage.d.ts.map +1 -1
  63. package/dist/interfaces/IMemoryPersistence.d.ts +47 -1
  64. package/dist/interfaces/IMemoryPersistence.d.ts.map +1 -1
  65. package/dist/interfaces/SocketServiceInterface.d.ts +3 -2
  66. package/dist/interfaces/SocketServiceInterface.d.ts.map +1 -1
  67. package/dist/interfaces/TaskInterfaces.d.ts +14 -1
  68. package/dist/interfaces/TaskInterfaces.d.ts.map +1 -1
  69. package/dist/models/agent.d.ts +0 -1
  70. package/dist/models/agent.d.ts.map +1 -1
  71. package/dist/models/agent.js +0 -5
  72. package/dist/models/agent.js.map +1 -1
  73. package/dist/models/agentIdentityReservation.d.ts +42 -0
  74. package/dist/models/agentIdentityReservation.d.ts.map +1 -0
  75. package/dist/models/agentIdentityReservation.js +52 -0
  76. package/dist/models/agentIdentityReservation.js.map +1 -0
  77. package/dist/models/channel.d.ts +2 -0
  78. package/dist/models/channel.d.ts.map +1 -1
  79. package/dist/models/channel.js.map +1 -1
  80. package/dist/models/channelKey.d.ts +1 -0
  81. package/dist/models/channelKey.d.ts.map +1 -1
  82. package/dist/models/channelKey.js +5 -0
  83. package/dist/models/channelKey.js.map +1 -1
  84. package/dist/models/memory.d.ts +1 -1
  85. package/dist/models/memory.d.ts.map +1 -1
  86. package/dist/models/memory.js +9 -12
  87. package/dist/models/memory.js.map +1 -1
  88. package/dist/models/memoryStrata.d.ts +3 -16
  89. package/dist/models/memoryStrata.d.ts.map +1 -1
  90. package/dist/models/memoryStrata.js +3 -5
  91. package/dist/models/memoryStrata.js.map +1 -1
  92. package/dist/models/plan.d.ts +2 -2
  93. package/dist/models/plan.d.ts.map +1 -1
  94. package/dist/models/plan.js +1 -1
  95. package/dist/models/plan.js.map +1 -1
  96. package/dist/models/taskEffectiveness.d.ts +1 -0
  97. package/dist/models/taskEffectiveness.d.ts.map +1 -1
  98. package/dist/models/taskEffectiveness.js +7 -1
  99. package/dist/models/taskEffectiveness.js.map +1 -1
  100. package/dist/models/user.d.ts +4 -0
  101. package/dist/models/user.d.ts.map +1 -1
  102. package/dist/models/user.js +8 -0
  103. package/dist/models/user.js.map +1 -1
  104. package/dist/protocols/mcp/LlmTestEnvironmentGuard.d.ts +16 -0
  105. package/dist/protocols/mcp/LlmTestEnvironmentGuard.d.ts.map +1 -0
  106. package/dist/protocols/mcp/LlmTestEnvironmentGuard.js +25 -0
  107. package/dist/protocols/mcp/LlmTestEnvironmentGuard.js.map +1 -0
  108. package/dist/protocols/mcp/McpServerTypes.d.ts +9 -0
  109. package/dist/protocols/mcp/McpServerTypes.d.ts.map +1 -1
  110. package/dist/protocols/mcp/providers/AnthropicMcpClient.d.ts.map +1 -1
  111. package/dist/protocols/mcp/providers/AnthropicMcpClient.js +1 -0
  112. package/dist/protocols/mcp/providers/AnthropicMcpClient.js.map +1 -1
  113. package/dist/protocols/mcp/providers/AzureOpenAiMcpClient.d.ts.map +1 -1
  114. package/dist/protocols/mcp/providers/AzureOpenAiMcpClient.js +1 -0
  115. package/dist/protocols/mcp/providers/AzureOpenAiMcpClient.js.map +1 -1
  116. package/dist/protocols/mcp/providers/BaseMcpClient.d.ts +4 -0
  117. package/dist/protocols/mcp/providers/BaseMcpClient.d.ts.map +1 -1
  118. package/dist/protocols/mcp/providers/BaseMcpClient.js +10 -0
  119. package/dist/protocols/mcp/providers/BaseMcpClient.js.map +1 -1
  120. package/dist/protocols/mcp/providers/CustomMcpClient.d.ts.map +1 -1
  121. package/dist/protocols/mcp/providers/CustomMcpClient.js +7 -0
  122. package/dist/protocols/mcp/providers/CustomMcpClient.js.map +1 -1
  123. package/dist/protocols/mcp/providers/GeminiMcpClient.d.ts.map +1 -1
  124. package/dist/protocols/mcp/providers/GeminiMcpClient.js +1 -0
  125. package/dist/protocols/mcp/providers/GeminiMcpClient.js.map +1 -1
  126. package/dist/protocols/mcp/providers/OllamaMcpClient.d.ts +1 -0
  127. package/dist/protocols/mcp/providers/OllamaMcpClient.d.ts.map +1 -1
  128. package/dist/protocols/mcp/providers/OllamaMcpClient.js +1 -0
  129. package/dist/protocols/mcp/providers/OllamaMcpClient.js.map +1 -1
  130. package/dist/protocols/mcp/providers/OpenAiMcpClient.d.ts.map +1 -1
  131. package/dist/protocols/mcp/providers/OpenAiMcpClient.js +1 -0
  132. package/dist/protocols/mcp/providers/OpenAiMcpClient.js.map +1 -1
  133. package/dist/protocols/mcp/providers/OpenRouterMcpClient.d.ts.map +1 -1
  134. package/dist/protocols/mcp/providers/OpenRouterMcpClient.js +2 -0
  135. package/dist/protocols/mcp/providers/OpenRouterMcpClient.js.map +1 -1
  136. package/dist/protocols/mcp/providers/XaiMcpClient.d.ts.map +1 -1
  137. package/dist/protocols/mcp/providers/XaiMcpClient.js +1 -0
  138. package/dist/protocols/mcp/providers/XaiMcpClient.js.map +1 -1
  139. package/dist/protocols/mcp/security/BrowserTargetGuard.d.ts +14 -0
  140. package/dist/protocols/mcp/security/BrowserTargetGuard.d.ts.map +1 -0
  141. package/dist/protocols/mcp/security/BrowserTargetGuard.js +55 -0
  142. package/dist/protocols/mcp/security/BrowserTargetGuard.js.map +1 -0
  143. package/dist/protocols/mcp/security/ExternalMcpRegistrationPolicy.d.ts +24 -0
  144. package/dist/protocols/mcp/security/ExternalMcpRegistrationPolicy.d.ts.map +1 -0
  145. package/dist/protocols/mcp/security/ExternalMcpRegistrationPolicy.js +33 -0
  146. package/dist/protocols/mcp/security/ExternalMcpRegistrationPolicy.js.map +1 -0
  147. package/dist/protocols/mcp/security/HttpTargetGuard.d.ts.map +1 -1
  148. package/dist/protocols/mcp/security/HttpTargetGuard.js +68 -6
  149. package/dist/protocols/mcp/security/HttpTargetGuard.js.map +1 -1
  150. package/dist/protocols/mcp/security/McpSecurityGuard.d.ts.map +1 -1
  151. package/dist/protocols/mcp/security/McpSecurityGuard.js +7 -5
  152. package/dist/protocols/mcp/security/McpSecurityGuard.js.map +1 -1
  153. package/dist/protocols/mcp/security/McpToolPolicy.d.ts +18 -0
  154. package/dist/protocols/mcp/security/McpToolPolicy.d.ts.map +1 -1
  155. package/dist/protocols/mcp/security/McpToolPolicy.js +60 -0
  156. package/dist/protocols/mcp/security/McpToolPolicy.js.map +1 -1
  157. package/dist/protocols/mcp/services/ExternalMcpServerManager.d.ts +25 -0
  158. package/dist/protocols/mcp/services/ExternalMcpServerManager.d.ts.map +1 -1
  159. package/dist/protocols/mcp/services/ExternalMcpServerManager.js +93 -17
  160. package/dist/protocols/mcp/services/ExternalMcpServerManager.js.map +1 -1
  161. package/dist/protocols/mcp/services/ExternalServerConfigs.d.ts +2 -2
  162. package/dist/protocols/mcp/services/ExternalServerConfigs.d.ts.map +1 -1
  163. package/dist/protocols/mcp/services/ExternalServerConfigs.js +25 -8
  164. package/dist/protocols/mcp/services/ExternalServerConfigs.js.map +1 -1
  165. package/dist/protocols/mcp/tools/AnalyticsTools.d.ts +3 -37
  166. package/dist/protocols/mcp/tools/AnalyticsTools.d.ts.map +1 -1
  167. package/dist/protocols/mcp/tools/AnalyticsTools.js +134 -614
  168. package/dist/protocols/mcp/tools/AnalyticsTools.js.map +1 -1
  169. package/dist/protocols/mcp/tools/CodeAnalysisTools.d.ts.map +1 -1
  170. package/dist/protocols/mcp/tools/CodeAnalysisTools.js +16 -13
  171. package/dist/protocols/mcp/tools/CodeAnalysisTools.js.map +1 -1
  172. package/dist/protocols/mcp/tools/EffectivenessTools.d.ts.map +1 -1
  173. package/dist/protocols/mcp/tools/EffectivenessTools.js +94 -30
  174. package/dist/protocols/mcp/tools/EffectivenessTools.js.map +1 -1
  175. package/dist/protocols/mcp/tools/GitTools.d.ts.map +1 -1
  176. package/dist/protocols/mcp/tools/GitTools.js +9 -5
  177. package/dist/protocols/mcp/tools/GitTools.js.map +1 -1
  178. package/dist/protocols/mcp/tools/InfrastructureTools.d.ts +10 -40
  179. package/dist/protocols/mcp/tools/InfrastructureTools.d.ts.map +1 -1
  180. package/dist/protocols/mcp/tools/InfrastructureTools.js +29 -70
  181. package/dist/protocols/mcp/tools/InfrastructureTools.js.map +1 -1
  182. package/dist/protocols/mcp/tools/JsonTools.d.ts.map +1 -1
  183. package/dist/protocols/mcp/tools/JsonTools.js +4 -4
  184. package/dist/protocols/mcp/tools/JsonTools.js.map +1 -1
  185. package/dist/protocols/mcp/tools/KnowledgeGraphTools.d.ts +55 -592
  186. package/dist/protocols/mcp/tools/KnowledgeGraphTools.d.ts.map +1 -1
  187. package/dist/protocols/mcp/tools/KnowledgeGraphTools.js +169 -119
  188. package/dist/protocols/mcp/tools/KnowledgeGraphTools.js.map +1 -1
  189. package/dist/protocols/mcp/tools/MemorySearchTools.d.ts +6 -6
  190. package/dist/protocols/mcp/tools/MemorySearchTools.d.ts.map +1 -1
  191. package/dist/protocols/mcp/tools/MemorySearchTools.js +107 -39
  192. package/dist/protocols/mcp/tools/MemorySearchTools.js.map +1 -1
  193. package/dist/protocols/mcp/tools/MemoryUtilityTools.d.ts +4 -5
  194. package/dist/protocols/mcp/tools/MemoryUtilityTools.d.ts.map +1 -1
  195. package/dist/protocols/mcp/tools/MemoryUtilityTools.js +59 -208
  196. package/dist/protocols/mcp/tools/MemoryUtilityTools.js.map +1 -1
  197. package/dist/protocols/mcp/tools/PlanningTools.d.ts +2 -1
  198. package/dist/protocols/mcp/tools/PlanningTools.d.ts.map +1 -1
  199. package/dist/protocols/mcp/tools/PlanningTools.js +111 -49
  200. package/dist/protocols/mcp/tools/PlanningTools.js.map +1 -1
  201. package/dist/protocols/mcp/tools/ProjectContextTools.d.ts.map +1 -1
  202. package/dist/protocols/mcp/tools/ProjectContextTools.js +18 -12
  203. package/dist/protocols/mcp/tools/ProjectContextTools.js.map +1 -1
  204. package/dist/protocols/mcp/tools/SafetyTools.d.ts.map +1 -1
  205. package/dist/protocols/mcp/tools/SafetyTools.js +16 -13
  206. package/dist/protocols/mcp/tools/SafetyTools.js.map +1 -1
  207. package/dist/protocols/mcp/tools/SearchProjectTools.d.ts +24 -7
  208. package/dist/protocols/mcp/tools/SearchProjectTools.d.ts.map +1 -1
  209. package/dist/protocols/mcp/tools/SearchProjectTools.js +226 -126
  210. package/dist/protocols/mcp/tools/SearchProjectTools.js.map +1 -1
  211. package/dist/protocols/mcp/tools/TaskPlanningTools.d.ts +0 -32
  212. package/dist/protocols/mcp/tools/TaskPlanningTools.d.ts.map +1 -1
  213. package/dist/protocols/mcp/tools/TaskPlanningTools.js +363 -450
  214. package/dist/protocols/mcp/tools/TaskPlanningTools.js.map +1 -1
  215. package/dist/protocols/mcp/tools/TestTools.d.ts.map +1 -1
  216. package/dist/protocols/mcp/tools/TestTools.js +18 -11
  217. package/dist/protocols/mcp/tools/TestTools.js.map +1 -1
  218. package/dist/protocols/mcp/tools/TypeScriptTools.d.ts.map +1 -1
  219. package/dist/protocols/mcp/tools/TypeScriptTools.js +22 -12
  220. package/dist/protocols/mcp/tools/TypeScriptTools.js.map +1 -1
  221. package/dist/protocols/mcp/tools/UserInputTools.d.ts.map +1 -1
  222. package/dist/protocols/mcp/tools/UserInputTools.js +14 -1
  223. package/dist/protocols/mcp/tools/UserInputTools.js.map +1 -1
  224. package/dist/protocols/mcp/tools/UserMemoryTools.d.ts +3 -1
  225. package/dist/protocols/mcp/tools/UserMemoryTools.d.ts.map +1 -1
  226. package/dist/protocols/mcp/tools/UserMemoryTools.js +27 -62
  227. package/dist/protocols/mcp/tools/UserMemoryTools.js.map +1 -1
  228. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.d.ts.map +1 -1
  229. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.js +14 -60
  230. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.js.map +1 -1
  231. package/dist/protocols/mcp/tools/shell/ShellSandbox.d.ts.map +1 -1
  232. package/dist/protocols/mcp/tools/shell/ShellSandbox.js +9 -27
  233. package/dist/protocols/mcp/tools/shell/ShellSandbox.js.map +1 -1
  234. package/dist/repositories/interfaces/IKnowledgeGraphRepository.d.ts +40 -30
  235. package/dist/repositories/interfaces/IKnowledgeGraphRepository.d.ts.map +1 -1
  236. package/dist/schemas/EventPayloadSchema.d.ts +28 -0
  237. package/dist/schemas/EventPayloadSchema.d.ts.map +1 -1
  238. package/dist/schemas/EventPayloadSchema.js +30 -1
  239. package/dist/schemas/EventPayloadSchema.js.map +1 -1
  240. package/dist/schemas/MxpProtocolSchemas.d.ts +6 -6
  241. package/dist/services/AgentPerformanceService.d.ts +11 -0
  242. package/dist/services/AgentPerformanceService.d.ts.map +1 -1
  243. package/dist/services/AgentPerformanceService.js +59 -33
  244. package/dist/services/AgentPerformanceService.js.map +1 -1
  245. package/dist/services/AutoCorrectionService.d.ts +3 -0
  246. package/dist/services/AutoCorrectionService.d.ts.map +1 -1
  247. package/dist/services/AutoCorrectionService.js +19 -2
  248. package/dist/services/AutoCorrectionService.js.map +1 -1
  249. package/dist/services/BackgroundTaskManager.d.ts +23 -7
  250. package/dist/services/BackgroundTaskManager.d.ts.map +1 -1
  251. package/dist/services/BackgroundTaskManager.js +137 -57
  252. package/dist/services/BackgroundTaskManager.js.map +1 -1
  253. package/dist/services/BrowserManager.d.ts +2 -0
  254. package/dist/services/BrowserManager.d.ts.map +1 -1
  255. package/dist/services/BrowserManager.js +18 -15
  256. package/dist/services/BrowserManager.js.map +1 -1
  257. package/dist/services/ChannelContextMemoryOperations.d.ts +8 -1
  258. package/dist/services/ChannelContextMemoryOperations.d.ts.map +1 -1
  259. package/dist/services/ChannelContextMemoryOperations.js +89 -165
  260. package/dist/services/ChannelContextMemoryOperations.js.map +1 -1
  261. package/dist/services/ChannelContextMessageOperations.d.ts +4 -3
  262. package/dist/services/ChannelContextMessageOperations.d.ts.map +1 -1
  263. package/dist/services/ChannelContextMessageOperations.js +72 -212
  264. package/dist/services/ChannelContextMessageOperations.js.map +1 -1
  265. package/dist/services/MemoryService.d.ts +52 -21
  266. package/dist/services/MemoryService.d.ts.map +1 -1
  267. package/dist/services/MemoryService.js +775 -548
  268. package/dist/services/MemoryService.js.map +1 -1
  269. package/dist/services/PatternLearningService.d.ts +5 -0
  270. package/dist/services/PatternLearningService.d.ts.map +1 -1
  271. package/dist/services/PatternLearningService.js +26 -3
  272. package/dist/services/PatternLearningService.js.map +1 -1
  273. package/dist/services/PerformanceOptimizationService.d.ts +2 -1
  274. package/dist/services/PerformanceOptimizationService.d.ts.map +1 -1
  275. package/dist/services/PerformanceOptimizationService.js +21 -6
  276. package/dist/services/PerformanceOptimizationService.js.map +1 -1
  277. package/dist/services/PredictiveAnalyticsService.d.ts +1 -0
  278. package/dist/services/PredictiveAnalyticsService.d.ts.map +1 -1
  279. package/dist/services/PredictiveAnalyticsService.js +18 -6
  280. package/dist/services/PredictiveAnalyticsService.js.map +1 -1
  281. package/dist/services/ProactiveValidationService.d.ts +6 -0
  282. package/dist/services/ProactiveValidationService.d.ts.map +1 -1
  283. package/dist/services/ProactiveValidationService.js +58 -39
  284. package/dist/services/ProactiveValidationService.js.map +1 -1
  285. package/dist/services/TaskEffectivenessService.d.ts +55 -31
  286. package/dist/services/TaskEffectivenessService.d.ts.map +1 -1
  287. package/dist/services/TaskEffectivenessService.js +243 -125
  288. package/dist/services/TaskEffectivenessService.js.map +1 -1
  289. package/dist/services/ToolExecutionInterceptor.d.ts +4 -0
  290. package/dist/services/ToolExecutionInterceptor.d.ts.map +1 -1
  291. package/dist/services/ToolExecutionInterceptor.js +31 -5
  292. package/dist/services/ToolExecutionInterceptor.js.map +1 -1
  293. package/dist/services/UserInputRequestManager.d.ts +13 -3
  294. package/dist/services/UserInputRequestManager.d.ts.map +1 -1
  295. package/dist/services/UserInputRequestManager.js +42 -6
  296. package/dist/services/UserInputRequestManager.js.map +1 -1
  297. package/dist/services/UserMemoryService.d.ts +2 -0
  298. package/dist/services/UserMemoryService.d.ts.map +1 -1
  299. package/dist/services/UserMemoryService.js +9 -4
  300. package/dist/services/UserMemoryService.js.map +1 -1
  301. package/dist/services/ValidationAnalyticsService.d.ts +4 -0
  302. package/dist/services/ValidationAnalyticsService.d.ts.map +1 -1
  303. package/dist/services/ValidationAnalyticsService.js +30 -8
  304. package/dist/services/ValidationAnalyticsService.js.map +1 -1
  305. package/dist/services/ValidationCacheService.d.ts +3 -1
  306. package/dist/services/ValidationCacheService.d.ts.map +1 -1
  307. package/dist/services/ValidationCacheService.js +25 -4
  308. package/dist/services/ValidationCacheService.js.map +1 -1
  309. package/dist/services/ValidationMiddleware.d.ts +7 -0
  310. package/dist/services/ValidationMiddleware.d.ts.map +1 -1
  311. package/dist/services/ValidationMiddleware.js +53 -10
  312. package/dist/services/ValidationMiddleware.js.map +1 -1
  313. package/dist/services/ValidationPerformanceService.d.ts +3 -0
  314. package/dist/services/ValidationPerformanceService.d.ts.map +1 -1
  315. package/dist/services/ValidationPerformanceService.js +28 -11
  316. package/dist/services/ValidationPerformanceService.js.map +1 -1
  317. package/dist/services/WebSearchService.d.ts.map +1 -1
  318. package/dist/services/WebSearchService.js +9 -0
  319. package/dist/services/WebSearchService.js.map +1 -1
  320. package/dist/services/dag/TaskDagService.d.ts +3 -0
  321. package/dist/services/dag/TaskDagService.d.ts.map +1 -1
  322. package/dist/services/dag/TaskDagService.js +18 -0
  323. package/dist/services/dag/TaskDagService.js.map +1 -1
  324. package/dist/services/kg/EntityQValueManager.d.ts +3 -1
  325. package/dist/services/kg/EntityQValueManager.d.ts.map +1 -1
  326. package/dist/services/kg/EntityQValueManager.js +10 -10
  327. package/dist/services/kg/EntityQValueManager.js.map +1 -1
  328. package/dist/services/kg/GraphSurpriseCalculator.d.ts +0 -4
  329. package/dist/services/kg/GraphSurpriseCalculator.d.ts.map +1 -1
  330. package/dist/services/kg/GraphSurpriseCalculator.js +0 -9
  331. package/dist/services/kg/GraphSurpriseCalculator.js.map +1 -1
  332. package/dist/services/kg/KnowledgeGraphService.d.ts +12 -12
  333. package/dist/services/kg/KnowledgeGraphService.d.ts.map +1 -1
  334. package/dist/services/kg/KnowledgeGraphService.js +43 -51
  335. package/dist/services/kg/KnowledgeGraphService.js.map +1 -1
  336. package/dist/services/kg/OrparGraphIntegration.d.ts.map +1 -1
  337. package/dist/services/kg/OrparGraphIntegration.js +6 -5
  338. package/dist/services/kg/OrparGraphIntegration.js.map +1 -1
  339. package/dist/services/orpar-memory/CycleConsolidationTrigger.d.ts +1 -0
  340. package/dist/services/orpar-memory/CycleConsolidationTrigger.d.ts.map +1 -1
  341. package/dist/services/orpar-memory/CycleConsolidationTrigger.js +8 -1
  342. package/dist/services/orpar-memory/CycleConsolidationTrigger.js.map +1 -1
  343. package/dist/services/orpar-memory/OrparMemoryCoordinator.d.ts +8 -1
  344. package/dist/services/orpar-memory/OrparMemoryCoordinator.d.ts.map +1 -1
  345. package/dist/services/orpar-memory/OrparMemoryCoordinator.js +93 -45
  346. package/dist/services/orpar-memory/OrparMemoryCoordinator.js.map +1 -1
  347. package/dist/services/orpar-memory/SurpriseOrparAdapter.d.ts +1 -0
  348. package/dist/services/orpar-memory/SurpriseOrparAdapter.d.ts.map +1 -1
  349. package/dist/services/orpar-memory/SurpriseOrparAdapter.js +8 -1
  350. package/dist/services/orpar-memory/SurpriseOrparAdapter.js.map +1 -1
  351. package/dist/types/ChannelContext.d.ts +2 -1
  352. package/dist/types/ChannelContext.d.ts.map +1 -1
  353. package/dist/types/EffectivenessTypes.d.ts +4 -1
  354. package/dist/types/EffectivenessTypes.d.ts.map +1 -1
  355. package/dist/types/TaskCompletionTypes.d.ts +7 -5
  356. package/dist/types/TaskCompletionTypes.d.ts.map +1 -1
  357. package/dist/types/TaskTypes.d.ts +8 -1
  358. package/dist/types/TaskTypes.d.ts.map +1 -1
  359. package/dist/utils/GlobMatcher.d.ts +37 -0
  360. package/dist/utils/GlobMatcher.d.ts.map +1 -0
  361. package/dist/utils/GlobMatcher.js +131 -0
  362. package/dist/utils/GlobMatcher.js.map +1 -0
  363. package/package.json +1 -1
  364. package/src/config/ModelContextLimits.ts +7 -1
  365. package/src/constants/CoreTools.ts +6 -5
  366. package/src/constants/DefaultPhaseProfiles.ts +29 -0
  367. package/src/constants/ReservedIdentities.ts +51 -0
  368. package/src/database/adapters/mongodb/MongoKnowledgeGraphRepository.ts +115 -36
  369. package/src/events/ClientEventBus.ts +117 -48
  370. package/src/events/EventBus.ts +32 -2
  371. package/src/events/EventBusBase.ts +132 -39
  372. package/src/events/EventNames.ts +43 -36
  373. package/src/events/PublicEvents.ts +8 -0
  374. package/src/events/ServerEventBus.ts +9 -128
  375. package/src/events/event-definitions/ControlLoopEvents.ts +12 -0
  376. package/src/events/event-definitions/SdkEvents.ts +58 -0
  377. package/src/events/event-definitions/TaskEvents.ts +2 -2
  378. package/src/index.ts +15 -0
  379. package/src/interfaces/AgentInterfaces.ts +5 -0
  380. package/src/interfaces/ChannelConfig.ts +2 -2
  381. package/src/interfaces/ConversationMessage.ts +5 -0
  382. package/src/interfaces/IMemoryPersistence.ts +55 -1
  383. package/src/interfaces/SocketServiceInterface.ts +3 -2
  384. package/src/interfaces/TaskInterfaces.ts +16 -1
  385. package/src/models/agent.ts +0 -6
  386. package/src/models/agentIdentityReservation.ts +77 -0
  387. package/src/models/channel.ts +2 -0
  388. package/src/models/channelKey.ts +10 -0
  389. package/src/models/memory.ts +18 -19
  390. package/src/models/memoryStrata.ts +9 -23
  391. package/src/models/plan.ts +3 -3
  392. package/src/models/taskEffectiveness.ts +9 -2
  393. package/src/models/user.ts +12 -0
  394. package/src/protocols/mcp/LlmTestEnvironmentGuard.ts +30 -0
  395. package/src/protocols/mcp/McpServerTypes.ts +9 -0
  396. package/src/protocols/mcp/providers/AnthropicMcpClient.ts +2 -0
  397. package/src/protocols/mcp/providers/AzureOpenAiMcpClient.ts +1 -0
  398. package/src/protocols/mcp/providers/BaseMcpClient.ts +13 -0
  399. package/src/protocols/mcp/providers/CustomMcpClient.ts +7 -0
  400. package/src/protocols/mcp/providers/GeminiMcpClient.ts +2 -0
  401. package/src/protocols/mcp/providers/OllamaMcpClient.ts +3 -1
  402. package/src/protocols/mcp/providers/OpenAiMcpClient.ts +2 -0
  403. package/src/protocols/mcp/providers/OpenRouterMcpClient.ts +3 -0
  404. package/src/protocols/mcp/providers/XaiMcpClient.ts +2 -0
  405. package/src/protocols/mcp/security/BrowserTargetGuard.ts +64 -0
  406. package/src/protocols/mcp/security/ExternalMcpRegistrationPolicy.ts +38 -0
  407. package/src/protocols/mcp/security/HttpTargetGuard.ts +77 -6
  408. package/src/protocols/mcp/security/McpSecurityGuard.ts +7 -5
  409. package/src/protocols/mcp/security/McpToolPolicy.ts +74 -0
  410. package/src/protocols/mcp/services/ExternalMcpServerManager.ts +146 -17
  411. package/src/protocols/mcp/services/ExternalServerConfigs.ts +26 -8
  412. package/src/protocols/mcp/tools/AnalyticsTools.ts +167 -641
  413. package/src/protocols/mcp/tools/CodeAnalysisTools.ts +44 -14
  414. package/src/protocols/mcp/tools/EffectivenessTools.ts +185 -45
  415. package/src/protocols/mcp/tools/GitTools.ts +15 -5
  416. package/src/protocols/mcp/tools/InfrastructureTools.ts +42 -90
  417. package/src/protocols/mcp/tools/JsonTools.ts +7 -4
  418. package/src/protocols/mcp/tools/KnowledgeGraphTools.ts +313 -164
  419. package/src/protocols/mcp/tools/MemorySearchTools.ts +158 -46
  420. package/src/protocols/mcp/tools/MemoryUtilityTools.ts +85 -232
  421. package/src/protocols/mcp/tools/PlanningTools.ts +137 -59
  422. package/src/protocols/mcp/tools/ProjectContextTools.ts +33 -12
  423. package/src/protocols/mcp/tools/SafetyTools.ts +49 -13
  424. package/src/protocols/mcp/tools/SearchProjectTools.ts +294 -153
  425. package/src/protocols/mcp/tools/TaskPlanningTools.ts +437 -514
  426. package/src/protocols/mcp/tools/TestTools.ts +41 -11
  427. package/src/protocols/mcp/tools/TypeScriptTools.ts +61 -12
  428. package/src/protocols/mcp/tools/UserInputTools.ts +15 -1
  429. package/src/protocols/mcp/tools/UserMemoryTools.ts +27 -62
  430. package/src/protocols/mcp/tools/shell/ShellExecuteHandler.ts +26 -84
  431. package/src/protocols/mcp/tools/shell/ShellSandbox.ts +13 -31
  432. package/src/repositories/interfaces/IKnowledgeGraphRepository.ts +45 -27
  433. package/src/schemas/EventPayloadSchema.ts +45 -1
  434. package/src/services/AgentPerformanceService.ts +85 -36
  435. package/src/services/AutoCorrectionService.ts +25 -6
  436. package/src/services/BackgroundTaskManager.ts +183 -76
  437. package/src/services/BrowserManager.ts +20 -16
  438. package/src/services/ChannelContextMemoryOperations.ts +169 -202
  439. package/src/services/ChannelContextMessageOperations.ts +112 -274
  440. package/src/services/MemoryService.ts +1053 -760
  441. package/src/services/PatternLearningService.ts +32 -7
  442. package/src/services/PerformanceOptimizationService.ts +26 -9
  443. package/src/services/PredictiveAnalyticsService.ts +23 -10
  444. package/src/services/ProactiveValidationService.ts +66 -40
  445. package/src/services/TaskEffectivenessService.ts +421 -206
  446. package/src/services/ToolExecutionInterceptor.ts +40 -9
  447. package/src/services/UserInputRequestManager.ts +51 -6
  448. package/src/services/UserMemoryService.ts +12 -3
  449. package/src/services/ValidationAnalyticsService.ts +36 -11
  450. package/src/services/ValidationCacheService.ts +30 -7
  451. package/src/services/ValidationMiddleware.ts +62 -14
  452. package/src/services/ValidationPerformanceService.ts +47 -25
  453. package/src/services/WebSearchService.ts +16 -4
  454. package/src/services/dag/TaskDagService.ts +20 -1
  455. package/src/services/kg/EntityQValueManager.ts +21 -10
  456. package/src/services/kg/GraphSurpriseCalculator.ts +0 -14
  457. package/src/services/kg/KnowledgeGraphService.ts +56 -48
  458. package/src/services/kg/OrparGraphIntegration.ts +11 -5
  459. package/src/services/orpar-memory/CycleConsolidationTrigger.ts +10 -1
  460. package/src/services/orpar-memory/OrparMemoryCoordinator.ts +142 -71
  461. package/src/services/orpar-memory/SurpriseOrparAdapter.ts +10 -1
  462. package/src/types/ChannelContext.ts +3 -1
  463. package/src/types/EffectivenessTypes.ts +6 -2
  464. package/src/types/TaskCompletionTypes.ts +9 -9
  465. package/src/types/TaskTypes.ts +12 -1
  466. package/src/utils/GlobMatcher.ts +157 -0
@@ -29,8 +29,12 @@
29
29
  * for LLM workflows (observations, reasoning, plans, reflections).
30
30
  */
31
31
 
32
- import { Observable, of } from 'rxjs';
33
- import { IMemoryPersistence } from '../interfaces/IMemoryPersistence.js';
32
+ import { firstValueFrom, Observable, of, throwError } from 'rxjs';
33
+ import {
34
+ ChannelMemoryAtomicMutation,
35
+ ChannelMemoryAtomicMutationResult,
36
+ IMemoryPersistence
37
+ } from '../interfaces/IMemoryPersistence.js';
34
38
  import { MxfMeilisearchService } from './MxfMeilisearchService.js';
35
39
  import { v4 as uuidv4 } from 'uuid';
36
40
 
@@ -40,8 +44,6 @@ import {
40
44
  IRelationshipMemory,
41
45
  MemoryScope,
42
46
  MemoryPersistenceLevel,
43
- MemoryData,
44
- MemoryQueryParams,
45
47
  createMemoryValidator
46
48
  } from '../types/MemoryTypes.js';
47
49
 
@@ -56,13 +58,12 @@ import {
56
58
  import { Logger } from '../utils/Logger.js';
57
59
  import { EventBus } from '../events/EventBus.js';
58
60
  import { Events } from '../events/EventNames.js';
59
- import { MemoryGetEvent, MemoryUpdateEvent } from '../events/event-definitions/MemoryEvents.js';
60
61
  import { createBaseEventPayload, createMemoryUpdateResultEventPayload,
61
62
  createMemoryDeleteResultEventPayload,
62
- MemoryDeleteResultEventData,
63
63
  MemoryUpdateResultEventData,
64
64
  MemoryGetEventPayload,
65
65
  MemoryUpdateEventPayload,
66
+ MemoryDeleteEventPayload,
66
67
  createMemoryGetResultEventPayload,
67
68
  MemoryGetResultEventData
68
69
  } from '../schemas/EventPayloadSchema.js';
@@ -124,6 +125,11 @@ export interface CognitiveMemoryQueryOptions {
124
125
  textQuery?: string;
125
126
  }
126
127
 
128
+ interface GeneralDataRecord {
129
+ expiresAt?: number;
130
+ [key: string]: unknown;
131
+ }
132
+
127
133
  /**
128
134
  * Enhanced Agent Memory with cognitive operations
129
135
  */
@@ -186,8 +192,11 @@ export class MemoryService {
186
192
  private agentMemory: Map<string, IEnhancedAgentMemory> = new Map();
187
193
  private channelMemory: Map<string, IEnhancedChannelMemory> = new Map();
188
194
  private relationshipMemory: Map<string, IRelationshipMemory> = new Map();
189
- private generalData: Map<string, any> = new Map();
190
- private cognitiveMemory: Map<string, CognitiveMemoryEntry<any>> = new Map();
195
+ private generalData: Map<string, unknown> = new Map();
196
+ private cognitiveMemory: Map<string, CognitiveMemoryEntry<unknown>> = new Map();
197
+ private agentMutationTails: Map<string, Promise<void>> = new Map();
198
+ private channelMutationTails: Map<string, Promise<void>> = new Map();
199
+ private relationshipMutationTails: Map<string, Promise<void>> = new Map();
191
200
 
192
201
  // Configuration
193
202
  private config: MemoryServiceConfig;
@@ -209,10 +218,6 @@ export class MemoryService {
209
218
  this.config = { ...DEFAULT_CONFIG, ...config };
210
219
  this.persistenceService = config.persistenceService;
211
220
 
212
- if (this.persistenceService) {
213
- } else {
214
- }
215
-
216
221
  // Set up event listeners
217
222
  this.setupEventListeners();
218
223
  }
@@ -221,373 +226,656 @@ export class MemoryService {
221
226
  * Set up event listeners
222
227
  */
223
228
  private setupEventListeners(): void {
224
- // Listen for memory update events to keep cache in sync
225
- EventBus.server.on(Events.Memory.UPDATE_RESULT, (data: { scope: MemoryScope, id: string, memory: any }) => {
226
- if (data.scope === MemoryScope.AGENT && data.memory) {
227
- this.agentMemory.set(data.id, data.memory);
228
- // ;
229
- } else if (data.scope === MemoryScope.CHANNEL && data.memory) {
230
- this.channelMemory.set(data.id, data.memory);
231
- // ;
232
- } else if (data.scope === MemoryScope.RELATIONSHIP && data.memory) {
233
- this.relationshipMemory.set(data.id, data.memory);
234
- // ;
229
+ // Return each request promise so EventBus.drain() retains ownership of
230
+ // acknowledged memory work until persistence and the response event
231
+ // have both completed.
232
+ EventBus.server.on(
233
+ Events.Memory.GET,
234
+ (event: MemoryGetEventPayload): Promise<void> => this.handleMemoryGetRequest(event)
235
+ );
236
+ EventBus.server.on(
237
+ Events.Memory.UPDATE,
238
+ (event: MemoryUpdateEventPayload): Promise<void> => this.handleMemoryUpdateRequest(event)
239
+ );
240
+ EventBus.server.on(
241
+ Events.Memory.DELETE,
242
+ (event: MemoryDeleteEventPayload): Promise<void> => this.handleMemoryDeleteRequest(event)
243
+ );
244
+ }
245
+
246
+ private validateMemoryRequestIdentity(
247
+ event: MemoryGetEventPayload | MemoryUpdateEventPayload | MemoryDeleteEventPayload
248
+ ): void {
249
+ this.validator.assertIsNonEmptyString(event.agentId, 'Memory request agentId is required');
250
+ this.validator.assertIsNonEmptyString(event.channelId, 'Memory request channelId is required');
251
+ this.validator.assertIsNonEmptyString(event.data.operationId, 'Memory operationId is required');
252
+ this.validator.validateMemoryScope(event.data.scope);
253
+ }
254
+
255
+ private requireScalarMemoryId(id: string | string[], scope: MemoryScope): string {
256
+ if (Array.isArray(id)) {
257
+ throw new Error(`${scope} memory requires a scalar ID`);
258
+ }
259
+ this.validator.assertIsNonEmptyString(id, `${scope} memory ID is required`);
260
+ return id;
261
+ }
262
+
263
+ /**
264
+ * Agent-scoped requests address the requesting agent's own memory. The
265
+ * socket gateway checks this too; the service checks it again so no other
266
+ * caller of the event bridge can read or change another agent's memory by
267
+ * naming it.
268
+ */
269
+ private requireOwnAgentMemoryId(id: string | string[], requestingAgentId: AgentId): string {
270
+ const agentId = this.requireScalarMemoryId(id, MemoryScope.AGENT);
271
+ if (agentId !== requestingAgentId) {
272
+ throw new Error('Agent memory requests are limited to the requesting agent');
273
+ }
274
+ return agentId;
275
+ }
276
+
277
+ /**
278
+ * Channel-scoped requests address the request's own channel: either the
279
+ * whole channel document (id equal to the request channel) or one of its
280
+ * keyed sub-resources (`channel:...:<channelId>`, validated where the key
281
+ * is resolved).
282
+ */
283
+ private requireOwnChannelMemoryId(id: string | string[], requestChannelId: ChannelId): string {
284
+ const channelMemoryId = this.requireScalarMemoryId(id, MemoryScope.CHANNEL);
285
+ if (!channelMemoryId.startsWith('channel:') && channelMemoryId !== requestChannelId) {
286
+ throw new Error('Channel memory requests are limited to the request channel');
287
+ }
288
+ return channelMemoryId;
289
+ }
290
+
291
+ /**
292
+ * Relationship-scoped requests must come from one of the two agents in
293
+ * the relationship, and the channel component must match the request.
294
+ */
295
+ private requireRelationshipMemoryId(
296
+ id: string | string[],
297
+ channelId: ChannelId,
298
+ requestingAgentId: AgentId
299
+ ): [string, string, string] {
300
+ if (!Array.isArray(id) || (id.length !== 2 && id.length !== 3)) {
301
+ throw new Error('Relationship memory requires two agent IDs and an optional channel ID');
302
+ }
303
+ id.forEach((part, index) => {
304
+ this.validator.assertIsNonEmptyString(part, `Relationship memory ID part ${index} is required`);
305
+ });
306
+ if (id.length === 3 && id[2] !== channelId) {
307
+ throw new Error('Relationship memory channel must match the request channel');
308
+ }
309
+ if (id[0] !== requestingAgentId && id[1] !== requestingAgentId) {
310
+ throw new Error('Relationship memory requests are limited to a participant of the relationship');
311
+ }
312
+ return [id[0], id[1], channelId];
313
+ }
314
+
315
+ private ownsPathOrDescendant(value: unknown, reservedPath: string): boolean {
316
+ if (!value || typeof value !== 'object') {
317
+ return false;
318
+ }
319
+ return Object.keys(value).some(key =>
320
+ key === reservedPath || key.startsWith(`${reservedPath}.`)
321
+ );
322
+ }
323
+
324
+ private getChannelMemoryKey(
325
+ key: string,
326
+ expectedChannelId?: ChannelId
327
+ ): { channelId: string; kind: 'messages' | 'context' | 'history' } {
328
+ const prefixes = [
329
+ { prefix: 'channel:context:history:', kind: 'history' as const },
330
+ { prefix: 'channel:messages:', kind: 'messages' as const },
331
+ { prefix: 'channel:context:', kind: 'context' as const }
332
+ ];
333
+ const matched = prefixes.find(({ prefix }) => key.startsWith(prefix));
334
+ if (!matched) {
335
+ throw new Error(`Unsupported channel memory key: ${key}`);
336
+ }
337
+ const channelId = key.slice(matched.prefix.length);
338
+ this.validator.assertIsNonEmptyString(channelId, 'Channel memory key channelId is required');
339
+ if (expectedChannelId && channelId !== expectedChannelId) {
340
+ throw new Error('Channel memory key must match the request channel');
341
+ }
342
+ return { channelId, kind: matched.kind };
343
+ }
344
+
345
+ private async getKeyedChannelMemory(
346
+ key: string,
347
+ requestChannelId: ChannelId
348
+ ): Promise<MemoryGetResultEventData['memory']> {
349
+ const { channelId, kind } = this.getChannelMemoryKey(key, requestChannelId);
350
+ if (!this.persistenceService && this.generalData.has(key)) {
351
+ return this.generalData.get(key) as MemoryGetResultEventData['memory'];
352
+ }
353
+
354
+ const channelMemory = this.persistenceService
355
+ ? await firstValueFrom(this.persistenceService.getChannelMemory(channelId))
356
+ : await firstValueFrom(this.getChannelMemory(channelId));
357
+ const value = kind === 'messages'
358
+ ? channelMemory.conversationHistory
359
+ : kind === 'context'
360
+ ? channelMemory.sharedState?.context
361
+ : channelMemory.customData?.contextHistory;
362
+ const cachedMemory = this.channelMemory.get(channelId);
363
+ this.channelMemory.set(channelId, {
364
+ ...channelMemory,
365
+ sharedCognitiveInsights: cachedMemory?.sharedCognitiveInsights ?? {
366
+ systemSummaries: [],
367
+ topicExtractions: [],
368
+ collaborativeReflections: []
235
369
  }
236
370
  });
237
-
238
- // Set up EventBus bridge for Memory.UPDATE events
239
- // This bridges EventBus memory events to internal memory operations
240
- // Required for ChannelContextMemoryOperations to save data
241
- EventBus.server.on(Events.Memory.UPDATE, (event: MemoryUpdateEventPayload) => {
242
- try {
243
- // Extract memory operation data from the event (handle EventBus forwarding nesting)
244
- const memoryEventData = event.data.scope ? event.data : (event.data as any).data;
245
-
246
- // Validate required fields
247
- this.validator.assertIsString(memoryEventData.scope, 'Memory scope is required');
248
- this.validator.assertIsString(memoryEventData.operationId, 'Operation ID is required');
249
-
250
- // Determine the action based on memory scope and handle UPDATE operations
251
- if (memoryEventData.scope === MemoryScope.CHANNEL) {
252
- // For channel data, store by key (e.g., "channel:context:${channelId}")
253
- const memoryKey = memoryEventData.id; // Use the id as the key
254
- const memoryData = memoryEventData.data;
255
-
256
- if (memoryKey && memoryData) {
257
- // Store the data in generalData map (in-memory cache)
258
- this.generalData.set(memoryKey, memoryData);
259
-
260
- // Also persist to MongoDB for durability (if persistence service available)
261
- // Extract actual context data - it's wrapped in another object with the key
262
- const actualContextData = memoryData[memoryKey];
263
- if (actualContextData && actualContextData.channelId && this.persistenceService) {
264
- try {
265
- // Convert to IChannelMemory format for persistence
266
- const channelMemoryUpdate: any = {
267
- id: `${actualContextData.channelId}-context`,
268
- channelId: actualContextData.channelId,
269
- createdAt: new Date(actualContextData.createdAt || Date.now()),
270
- updatedAt: new Date(),
271
- persistenceLevel: 'persistent' as any,
272
- sharedState: { context: actualContextData },
273
- notes: { channelContext: 'Auto-saved from ChannelContextService' },
274
- conversationHistory: [],
275
- customData: { contextMetadata: memoryEventData.metadata || {} }
276
- };
277
-
278
- // Persist to MongoDB (fire and forget for performance)
279
- this.persistenceService.saveChannelMemory(channelMemoryUpdate)
280
- .subscribe({
281
- next: () => this.logger.info(`Channel context persisted to MongoDB for ${actualContextData.channelId}`),
282
- error: (err: Error) => this.logger.warn(`Failed to persist channel context to MongoDB: ${err.message}`)
283
- });
284
- } catch (persistError) {
285
- this.logger.warn(`Error persisting channel context: ${persistError}`);
286
- }
287
- }
288
-
289
- // Create success result payload
290
- const updateResultData: MemoryUpdateResultEventData = {
291
- operationId: memoryEventData.operationId,
292
- scope: MemoryScope.CHANNEL,
293
- id: memoryKey,
294
- memory: memoryData
295
- };
296
-
297
- const systemAgentId: AgentId = 'SYSTEM_AGENT';
298
- const channelId: ChannelId = event.channelId || 'NO_CHANNEL';
299
-
300
- const payload = createMemoryUpdateResultEventPayload(
301
- Events.Memory.UPDATE_RESULT,
302
- systemAgentId,
303
- channelId,
304
- updateResultData
305
- );
306
-
307
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, payload);
308
- } else {
309
- this.logger.warn(`Invalid UPDATE data - missing key or data: key=${memoryKey}, data=${!!memoryData}`);
310
- }
371
+ if (value !== undefined) {
372
+ this.generalData.set(key, value);
373
+ } else {
374
+ this.generalData.delete(key);
375
+ }
376
+ return (value as MemoryGetResultEventData['memory']) ?? null;
377
+ }
378
+
379
+ private serializeChannelMutation<T>(
380
+ channelId: string,
381
+ operation: () => Promise<T>
382
+ ): Promise<T> {
383
+ const previousTail = this.channelMutationTails.get(channelId) ?? Promise.resolve();
384
+ const result = previousTail.then(operation);
385
+ const nextTail = result.then(() => undefined, () => undefined);
386
+ this.channelMutationTails.set(channelId, nextTail);
387
+
388
+ return result.finally(() => {
389
+ if (this.channelMutationTails.get(channelId) === nextTail) {
390
+ this.channelMutationTails.delete(channelId);
391
+ }
392
+ });
393
+ }
394
+
395
+ private serializeAgentMutation<T>(
396
+ agentId: string,
397
+ operation: () => Promise<T>
398
+ ): Promise<T> {
399
+ const previousTail = this.agentMutationTails.get(agentId) ?? Promise.resolve();
400
+ const result = previousTail.then(operation);
401
+ const nextTail = result.then(() => undefined, () => undefined);
402
+ this.agentMutationTails.set(agentId, nextTail);
403
+
404
+ return result.finally(() => {
405
+ if (this.agentMutationTails.get(agentId) === nextTail) {
406
+ this.agentMutationTails.delete(agentId);
407
+ }
408
+ });
409
+ }
410
+
411
+ private serializeRelationshipMutation<T>(
412
+ agentId1: string,
413
+ agentId2: string,
414
+ channelId: string,
415
+ operation: () => Promise<T>
416
+ ): Promise<T> {
417
+ const relationshipKey = this.getRelationshipKey(agentId1, agentId2, channelId);
418
+ const previousTail = this.relationshipMutationTails.get(relationshipKey) ?? Promise.resolve();
419
+ const result = previousTail.then(operation);
420
+ const nextTail = result.then(() => undefined, () => undefined);
421
+ this.relationshipMutationTails.set(relationshipKey, nextTail);
422
+
423
+ return result.finally(() => {
424
+ if (this.relationshipMutationTails.get(relationshipKey) === nextTail) {
425
+ this.relationshipMutationTails.delete(relationshipKey);
426
+ }
427
+ });
428
+ }
429
+
430
+ private getAtomicMutation(
431
+ kind: 'messages' | 'context' | 'history',
432
+ value: unknown,
433
+ expectedContextUpdatedAt?: number
434
+ ): ChannelMemoryAtomicMutation {
435
+ switch (kind) {
436
+ case 'messages':
437
+ if (!Array.isArray(value) || value.length === 0) {
438
+ throw new Error('Keyed channel message updates require a non-empty array');
439
+ }
440
+ return { kind: 'append_messages', messages: value };
441
+ case 'context':
442
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
443
+ throw new Error('Keyed channel context updates require an object');
311
444
  }
312
- } catch (error) {
313
- this.logger.error(`Error handling Memory.UPDATE event: ${error instanceof Error ? error.message : String(error)}`);
445
+ return {
446
+ kind: 'replace_context',
447
+ context: value,
448
+ expectedUpdatedAt: expectedContextUpdatedAt
449
+ };
450
+ case 'history':
451
+ if (!Array.isArray(value) || value.length === 0) {
452
+ throw new Error('Keyed channel history updates require a non-empty array');
453
+ }
454
+ return { kind: 'append_context_history', entries: value, retainLast: 100 };
455
+ }
456
+ }
457
+
458
+ private getDeleteMutation(
459
+ kind: 'messages' | 'context' | 'history'
460
+ ): ChannelMemoryAtomicMutation {
461
+ switch (kind) {
462
+ case 'messages':
463
+ return { kind: 'delete_messages' };
464
+ case 'context':
465
+ return { kind: 'delete_context' };
466
+ case 'history':
467
+ return { kind: 'delete_context_history' };
468
+ }
469
+ }
470
+
471
+ private async mutateLocalChannelMemory(
472
+ channelId: string,
473
+ mutation: ChannelMemoryAtomicMutation
474
+ ): Promise<ChannelMemoryAtomicMutationResult> {
475
+ const deleting = mutation.kind.startsWith('delete_');
476
+ const existingMemory = this.channelMemory.get(channelId);
477
+ if (deleting && !existingMemory) {
478
+ return { found: false, memory: null, value: null };
479
+ }
480
+ const originalMemory = existingMemory ?? await firstValueFrom(this.getChannelMemory(channelId));
481
+ if (mutation.kind === 'replace_context') {
482
+ const existingContext = originalMemory.sharedState?.context as
483
+ | { updatedAt?: unknown }
484
+ | undefined;
485
+ const actualUpdatedAt = existingContext?.updatedAt;
486
+ const versionMatches = mutation.expectedUpdatedAt === undefined
487
+ ? existingContext === undefined
488
+ : actualUpdatedAt === mutation.expectedUpdatedAt;
489
+ if (!versionMatches) {
490
+ return { found: false, memory: originalMemory, value: existingContext ?? null };
314
491
  }
492
+ }
493
+ const targetExists = mutation.kind === 'delete_messages'
494
+ ? originalMemory.conversationHistory !== undefined
495
+ : mutation.kind === 'delete_context'
496
+ ? Object.prototype.hasOwnProperty.call(originalMemory.sharedState ?? {}, 'context')
497
+ : mutation.kind === 'delete_context_history'
498
+ ? Object.prototype.hasOwnProperty.call(
499
+ originalMemory.customData ?? {},
500
+ 'contextHistory'
501
+ )
502
+ : true;
503
+ if (!targetExists) {
504
+ return { found: false, memory: originalMemory, value: null };
505
+ }
506
+ let updatedMemory: IEnhancedChannelMemory;
507
+ let value: unknown;
508
+
509
+ switch (mutation.kind) {
510
+ case 'append_messages':
511
+ value = [...(originalMemory.conversationHistory ?? []), ...mutation.messages];
512
+ updatedMemory = { ...originalMemory, conversationHistory: value as unknown[] };
513
+ break;
514
+ case 'replace_context':
515
+ value = mutation.context;
516
+ updatedMemory = {
517
+ ...originalMemory,
518
+ sharedState: { ...originalMemory.sharedState, context: value }
519
+ };
520
+ break;
521
+ case 'append_context_history':
522
+ value = [
523
+ ...((originalMemory.customData?.contextHistory as unknown[] | undefined) ?? []),
524
+ ...mutation.entries
525
+ ].slice(-mutation.retainLast);
526
+ updatedMemory = {
527
+ ...originalMemory,
528
+ customData: { ...originalMemory.customData, contextHistory: value }
529
+ };
530
+ break;
531
+ case 'delete_messages':
532
+ value = [];
533
+ updatedMemory = { ...originalMemory, conversationHistory: [] };
534
+ break;
535
+ case 'delete_context': {
536
+ const sharedState = { ...originalMemory.sharedState };
537
+ delete sharedState.context;
538
+ value = null;
539
+ updatedMemory = { ...originalMemory, sharedState };
540
+ break;
541
+ }
542
+ case 'delete_context_history': {
543
+ const customData = { ...originalMemory.customData };
544
+ delete customData.contextHistory;
545
+ value = null;
546
+ updatedMemory = { ...originalMemory, customData };
547
+ break;
548
+ }
549
+ }
550
+
551
+ updatedMemory.updatedAt = new Date();
552
+ this.channelMemory.set(channelId, updatedMemory);
553
+ return { found: true, memory: updatedMemory, value };
554
+ }
555
+
556
+ private async executeKeyedChannelMutation(
557
+ key: string,
558
+ requestChannelId: ChannelId | undefined,
559
+ mutation: ChannelMemoryAtomicMutation
560
+ ): Promise<ChannelMemoryAtomicMutationResult> {
561
+ const { channelId } = this.getChannelMemoryKey(key, requestChannelId);
562
+ return this.serializeChannelMutation(channelId, async () => {
563
+ const result = this.persistenceService
564
+ ? await firstValueFrom(
565
+ this.persistenceService.mutateChannelMemory(channelId, mutation)
566
+ )
567
+ : await this.mutateLocalChannelMemory(channelId, mutation);
568
+
569
+ if (result.memory) {
570
+ const cachedMemory = this.channelMemory.get(channelId);
571
+ this.channelMemory.set(channelId, {
572
+ ...result.memory,
573
+ sharedCognitiveInsights: cachedMemory?.sharedCognitiveInsights ?? {
574
+ systemSummaries: [],
575
+ topicExtractions: [],
576
+ collaborativeReflections: []
577
+ }
578
+ });
579
+ }
580
+ if (result.found) {
581
+ this.generalData.set(key, result.value);
582
+ } else {
583
+ this.generalData.delete(key);
584
+ }
585
+ return result;
315
586
  });
316
-
317
- // Set up EventBus bridge for Memory.GET events
318
- // This bridges EventBus memory events to internal memory operations
319
- // Required for ChannelContextMessageOperations to work with the memory system
320
- EventBus.server.on(Events.Memory.GET, (event: MemoryGetEventPayload) => {
321
- try {
322
- // Extract memory operation data from the event (handle EventBus forwarding nesting)
323
- const memoryEventData = event.data.scope ? event.data : (event.data as any).data;
324
-
325
- // Validate required fields
326
- this.validator.assertIsString(memoryEventData.scope, 'Memory scope is required');
327
- this.validator.assertIsString(memoryEventData.operationId, 'Operation ID is required');
328
-
329
- let memoryObservable: any = null;
330
-
331
- // Determine the action based on memory scope and handle GET operations
332
- switch (memoryEventData.scope) {
333
- case MemoryScope.CHANNEL:
334
- // Determine the memory key to look up - prioritize key field over id field
335
- const memoryKey = memoryEventData.key || (Array.isArray(memoryEventData.id) ? memoryEventData.id[0] : memoryEventData.id);
336
-
337
- if (memoryKey) {
338
- // For channel data, look up by key (e.g., "channel:messages:${channelId}" or "channel:context:${channelId}")
339
- const channelMemory = this.generalData.get(memoryKey);
340
-
341
- // Create result payload
342
- const getResultData: MemoryGetResultEventData = {
343
- operationId: memoryEventData.operationId,
344
- scope: MemoryScope.CHANNEL,
345
- id: memoryKey, // Use the memory key as the id for proper matching
346
- memory: channelMemory || null
347
- };
348
-
349
- const systemAgentId: AgentId = 'SYSTEM_AGENT';
350
- const noChannelId: ChannelId = 'NO_CHANNEL';
351
-
352
- const payload = createMemoryGetResultEventPayload(
353
- Events.Memory.GET_RESULT,
354
- systemAgentId,
355
- noChannelId,
356
- getResultData
587
+ }
588
+
589
+ private async updateKeyedChannelMemory(
590
+ key: string,
591
+ value: unknown,
592
+ requestChannelId: ChannelId,
593
+ expectedContextUpdatedAt?: number
594
+ ): Promise<MemoryUpdateResultEventData['memory']> {
595
+ const { kind } = this.getChannelMemoryKey(key, requestChannelId);
596
+ const result = await this.executeKeyedChannelMutation(
597
+ key,
598
+ requestChannelId,
599
+ this.getAtomicMutation(kind, value, expectedContextUpdatedAt)
600
+ );
601
+ if (!result.found) {
602
+ throw new Error(`Channel context changed concurrently while updating ${key}`);
603
+ }
604
+ return result.value as MemoryUpdateResultEventData['memory'];
605
+ }
606
+
607
+ private async deleteKeyedChannelMemory(key: string): Promise<boolean> {
608
+ const { kind } = this.getChannelMemoryKey(key);
609
+ const result = await this.executeKeyedChannelMutation(
610
+ key,
611
+ undefined,
612
+ this.getDeleteMutation(kind)
613
+ );
614
+ if (result.found) {
615
+ this.generalData.delete(key);
616
+ }
617
+ return result.found;
618
+ }
619
+
620
+ private async handleMemoryGetRequest(event: MemoryGetEventPayload): Promise<void> {
621
+ let responseId: string | string[] = event.data.id;
622
+ try {
623
+ this.validateMemoryRequestIdentity(event);
624
+ let memory: MemoryGetResultEventData['memory'];
625
+
626
+ switch (event.data.scope) {
627
+ case MemoryScope.AGENT: {
628
+ const agentId = this.requireOwnAgentMemoryId(event.data.id, event.agentId);
629
+ responseId = agentId;
630
+ memory = await firstValueFrom(this.getAgentMemory(agentId));
631
+ break;
632
+ }
633
+ case MemoryScope.CHANNEL: {
634
+ const channelMemoryId = this.requireOwnChannelMemoryId(
635
+ event.data.key ?? event.data.id,
636
+ event.channelId
637
+ );
638
+ responseId = channelMemoryId;
639
+ memory = channelMemoryId.startsWith('channel:')
640
+ ? await this.getKeyedChannelMemory(channelMemoryId, event.channelId)
641
+ : await firstValueFrom(this.getChannelMemory(channelMemoryId));
642
+ break;
643
+ }
644
+ case MemoryScope.RELATIONSHIP: {
645
+ const [agentId1, agentId2, channelId] = this.requireRelationshipMemoryId(
646
+ event.data.id,
647
+ event.channelId,
648
+ event.agentId
649
+ );
650
+ responseId = [agentId1, agentId2, channelId];
651
+ memory = await firstValueFrom(
652
+ this.getRelationshipMemory(agentId1, agentId2, channelId)
653
+ );
654
+ break;
655
+ }
656
+ }
657
+
658
+ EventBus.server.emit(
659
+ Events.Memory.GET_RESULT,
660
+ createMemoryGetResultEventPayload(
661
+ Events.Memory.GET_RESULT,
662
+ event.agentId,
663
+ event.channelId,
664
+ {
665
+ operationId: event.data.operationId,
666
+ scope: event.data.scope,
667
+ id: responseId,
668
+ memory
669
+ }
670
+ )
671
+ );
672
+ } catch (error) {
673
+ this.emitMemoryGetError(event, responseId, error);
674
+ }
675
+ }
676
+
677
+ private async handleMemoryUpdateRequest(event: MemoryUpdateEventPayload): Promise<void> {
678
+ let responseId: string | string[] = event.data.id;
679
+ try {
680
+ this.validateMemoryRequestIdentity(event);
681
+ this.validator.assertIsObject(event.data.data, 'Memory update data is required');
682
+ let memory: MemoryUpdateResultEventData['memory'];
683
+
684
+ switch (event.data.scope) {
685
+ case MemoryScope.AGENT: {
686
+ const agentId = this.requireOwnAgentMemoryId(event.data.id, event.agentId);
687
+ responseId = agentId;
688
+ memory = await firstValueFrom(this.updateAgentMemory(agentId, event.data.data));
689
+ break;
690
+ }
691
+ case MemoryScope.CHANNEL: {
692
+ const channelMemoryId = this.requireOwnChannelMemoryId(
693
+ event.data.id,
694
+ event.channelId
695
+ );
696
+ responseId = channelMemoryId;
697
+ const embeddedMemoryKeys = Object.keys(event.data.data)
698
+ .filter(key => key.startsWith('channel:'));
699
+ const keyedMemoryId = channelMemoryId.startsWith('channel:')
700
+ ? channelMemoryId
701
+ : embeddedMemoryKeys.length === 1
702
+ ? embeddedMemoryKeys[0]
703
+ : undefined;
704
+ if (keyedMemoryId) {
705
+ responseId = keyedMemoryId;
706
+ const nestedValue = event.data.data[keyedMemoryId];
707
+ const value = nestedValue === undefined ? event.data.data : nestedValue;
708
+ const expectedContextUpdatedAt =
709
+ event.data.metadata?.expectedContextUpdatedAt;
710
+ if (
711
+ expectedContextUpdatedAt !== undefined &&
712
+ (
713
+ typeof expectedContextUpdatedAt !== 'number' ||
714
+ !Number.isFinite(expectedContextUpdatedAt) ||
715
+ expectedContextUpdatedAt < 0
716
+ )
717
+ ) {
718
+ throw new Error(
719
+ 'Memory update expectedContextUpdatedAt must be a non-negative number'
357
720
  );
358
-
359
- //// this.logger.info(`[CRITICAL] MemoryService emitting GET_RESULT:`, Object.keys(payload));
360
- EventBus.server.emit(Events.Memory.GET_RESULT, payload);
361
- } else {
362
- this.logger.warn(`[DEBUG] No memory key found in GET event data`);
363
- }
364
- break;
365
-
366
- case MemoryScope.AGENT:
367
- if (typeof memoryEventData.id === 'string') {
368
- // ;
369
- memoryObservable = this.getAgentMemory(memoryEventData.id);
370
-
371
- // Subscribe to the observable and emit result
372
- memoryObservable.subscribe({
373
- next: (agentMemory: IEnhancedAgentMemory) => {
374
- // Create result payload
375
- const getResultData: MemoryGetResultEventData = {
376
- operationId: memoryEventData.operationId,
377
- scope: MemoryScope.AGENT,
378
- id: memoryEventData.id as string,
379
- memory: agentMemory || null
380
- };
381
-
382
- const payload = createMemoryGetResultEventPayload(
383
- Events.Memory.GET_RESULT,
384
- event.agentId,
385
- event.channelId,
386
- getResultData
387
- );
388
-
389
- EventBus.server.emit(Events.Memory.GET_RESULT, payload);
390
- },
391
- error: (error: Error) => {
392
- this.logger.error(`Error getting agent memory: ${error}`);
393
-
394
- // Create error result payload
395
- const getResultData: MemoryGetResultEventData = {
396
- operationId: memoryEventData.operationId,
397
- scope: MemoryScope.AGENT,
398
- id: memoryEventData.id as string,
399
- memory: null
400
- };
401
-
402
- const payload = createMemoryGetResultEventPayload(
403
- Events.Memory.GET_RESULT,
404
- event.agentId,
405
- event.channelId,
406
- getResultData
407
- );
408
-
409
- EventBus.server.emit(Events.Memory.GET_RESULT, payload);
410
- }
411
- });
412
721
  }
413
- break;
414
-
415
- case MemoryScope.RELATIONSHIP:
416
- // Handle relationship memory GET
417
- break;
418
-
419
- default:
420
- this.logger.warn(`Unsupported memory scope: ${memoryEventData.scope}`);
722
+ memory = await this.updateKeyedChannelMemory(
723
+ keyedMemoryId,
724
+ value,
725
+ event.channelId,
726
+ expectedContextUpdatedAt
727
+ );
728
+ } else {
729
+ memory = await firstValueFrom(
730
+ this.updateChannelMemory(channelMemoryId, event.data.data)
731
+ );
732
+ }
733
+ break;
734
+ }
735
+ case MemoryScope.RELATIONSHIP: {
736
+ const [agentId1, agentId2, channelId] = this.requireRelationshipMemoryId(
737
+ event.data.id,
738
+ event.channelId,
739
+ event.agentId
740
+ );
741
+ responseId = [agentId1, agentId2, channelId];
742
+ memory = await firstValueFrom(
743
+ this.updateRelationshipMemory(agentId1, agentId2, channelId, event.data.data)
744
+ );
745
+ break;
421
746
  }
422
-
423
- } catch (error) {
424
- this.logger.error('[ERROR] Error processing EventBus Memory.GET:', error);
425
-
426
- // Log error details for debugging without creating fake event payloads
427
- const operationId = event.data?.operationId || '[NO_OPERATION_ID]';
428
- const memoryId = event.data?.id || event.data?.key || '[NO_MEMORY_ID]';
429
- this.logger.error(`Memory GET operation failed - OperationId: ${operationId}, MemoryId: ${memoryId}, Error: ${(error as Error).message}`);
430
-
431
- // Cannot emit GET_RESULT event without valid agentId and channelId from original request
432
- // Original event should have contained these required identifiers
433
- this.logger.warn('Cannot emit Memory.GET_RESULT event - original event lacked valid agentId/channelId. Memory operation errors should be handled by the requesting component.');
434
747
  }
435
- });
436
-
437
- // Set up EventBus bridge for Memory.UPDATE events
438
- EventBus.server.on(Events.Memory.UPDATE, (event: MemoryUpdateEventPayload) => {
439
- try {
440
- // Extract memory operation data from the event (handle EventBus forwarding nesting)
441
- const memoryEventData = event.data.scope ? event.data : (event.data as any).data;
442
-
443
- // Validate required fields
444
- this.validator.assertIsString(memoryEventData.scope, 'Memory scope is required');
445
- this.validator.assertIsString(memoryEventData.operationId, 'Operation ID is required');
446
-
447
- // Handle UPDATE operations
448
- switch (memoryEventData.scope) {
449
- case MemoryScope.CHANNEL:
450
- // For UPDATE operations, the id field contains the memory key
451
- const updateMemoryKey = Array.isArray(memoryEventData.id) ? memoryEventData.id[0] : memoryEventData.id;
452
-
453
- // Handle the actual data structure from ChannelContextMessageOperations and ChannelContextMemoryOperations
454
- // Data comes in format:
455
- // - { "channel:messages:${channelId}": [...messages] } for messages
456
- // - { "channel:context:${channelId}": {...context} } for context
457
- if (memoryEventData.data && typeof memoryEventData.data === 'object') {
458
- // Check if the data is already properly keyed or needs to be keyed
459
- const dataKeys = Object.keys(memoryEventData.data);
460
-
461
- if (updateMemoryKey.startsWith('channel:')) {
462
- // Direct storage: id field is the memory key, data field contains the actual data
463
- // ;
464
-
465
- // If data has nested structure with the same key, extract the nested data
466
- const actualData = memoryEventData.data[updateMemoryKey] || memoryEventData.data;
467
-
468
- // Check if data has actually changed before updating
469
- const existingData = this.generalData.get(updateMemoryKey);
470
- const dataHasChanged = !this.isDataEqual(existingData, actualData);
471
-
472
- if (!dataHasChanged) {
473
- // ;
474
- return; // Skip update and event emission
475
- }
476
-
477
- // ;
478
- this.generalData.set(updateMemoryKey, actualData);
479
-
480
- // Create success result payload
481
- const updateResult: MemoryUpdateResultEventData = {
482
- operationId: memoryEventData.operationId,
483
- scope: MemoryScope.CHANNEL,
484
- id: updateMemoryKey, // Use the memory key as the id for proper matching
485
- memory: actualData
486
- };
487
-
488
- const systemAgentId: AgentId = 'SYSTEM_AGENT';
489
- const noChannelId: ChannelId = 'NO_CHANNEL';
490
-
491
- const payload = createMemoryUpdateResultEventPayload(
492
- Events.Memory.UPDATE_RESULT,
493
- systemAgentId,
494
- noChannelId,
495
- updateResult
496
- );
497
-
498
- // ;
499
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, payload);
500
- } else {
501
- // Legacy format: Find any channel-related key and data in the data object
502
- const channelKey = dataKeys.find(key =>
503
- key.startsWith('channel:messages:') || key.startsWith('channel:context:')
504
- );
505
-
506
- if (channelKey && memoryEventData.data[channelKey]) {
507
- // ;
508
-
509
- const newData = memoryEventData.data[channelKey];
510
-
511
- // Check if data has actually changed before updating
512
- const existingData = this.generalData.get(channelKey);
513
- const dataHasChanged = !this.isDataEqual(existingData, newData);
514
-
515
- if (!dataHasChanged) {
516
- // ;
517
- return; // Skip update and event emission
518
- }
519
-
520
- // Store the data by the key (messages array or context object)
521
- // ;
522
- this.generalData.set(channelKey, newData);
523
-
524
- // Create success result payload
525
- const updateResult: MemoryUpdateResultEventData = {
526
- operationId: memoryEventData.operationId,
527
- scope: MemoryScope.CHANNEL,
528
- id: channelKey, // Use the memory key as the id for proper matching
529
- memory: newData
530
- };
531
-
532
- const systemAgentId: AgentId = 'SYSTEM_AGENT';
533
- const noChannelId: ChannelId = 'NO_CHANNEL';
534
-
535
- const payload = createMemoryUpdateResultEventPayload(
536
- Events.Memory.UPDATE_RESULT,
537
- systemAgentId,
538
- noChannelId,
539
- updateResult
540
- );
541
-
542
- // ;
543
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, payload);
544
- } else {
545
- this.logger.warn(`No recognized channel key found in data keys: ${dataKeys.join(', ')}`);
546
- }
547
- }
548
- }
549
- break;
550
-
551
- case MemoryScope.AGENT:
552
- // Handle agent memory UPDATE
553
- if (typeof memoryEventData.id === 'string' && memoryEventData.data) {
554
- // CRITICAL: Must subscribe to Observable to trigger execution!
555
- // The request context routes the UPDATE_RESULT back to the
556
- // requesting agent with its own operationId — without it the
557
- // SDK's pending save can never observe its result.
558
- this.updateAgentMemory(memoryEventData.id, memoryEventData.data, {
559
- operationId: memoryEventData.operationId,
560
- requesterAgentId: event.agentId,
561
- requesterChannelId: event.channelId
562
- }).subscribe({
563
- next: () => null,
564
- error: (err) => this.logger.error(`Agent memory update failed for ${memoryEventData.id}: ${err}`)
565
- });
566
- }
567
- break;
568
-
569
- case MemoryScope.RELATIONSHIP:
570
- // Handle relationship memory UPDATE
571
- break;
572
-
573
- default:
574
- this.logger.warn(`Unsupported memory scope: ${memoryEventData.scope}`);
748
+
749
+ EventBus.server.emit(
750
+ Events.Memory.UPDATE_RESULT,
751
+ createMemoryUpdateResultEventPayload(
752
+ Events.Memory.UPDATE_RESULT,
753
+ event.agentId,
754
+ event.channelId,
755
+ {
756
+ operationId: event.data.operationId,
757
+ scope: event.data.scope,
758
+ id: responseId,
759
+ memory
760
+ }
761
+ )
762
+ );
763
+ } catch (error) {
764
+ this.emitMemoryUpdateError(event, responseId, error);
765
+ }
766
+ }
767
+
768
+ private async handleMemoryDeleteRequest(event: MemoryDeleteEventPayload): Promise<void> {
769
+ let responseId: string | string[] = event.data.id;
770
+ try {
771
+ this.validateMemoryRequestIdentity(event);
772
+ if (event.data.scope === MemoryScope.RELATIONSHIP) {
773
+ responseId = this.requireRelationshipMemoryId(
774
+ event.data.id,
775
+ event.channelId,
776
+ event.agentId
777
+ );
778
+ } else if (event.data.scope === MemoryScope.AGENT) {
779
+ responseId = this.requireOwnAgentMemoryId(event.data.id, event.agentId);
780
+ } else {
781
+ responseId = this.requireOwnChannelMemoryId(event.data.id, event.channelId);
782
+ if (responseId.startsWith('channel:')) {
783
+ this.getChannelMemoryKey(responseId, event.channelId);
575
784
  }
576
-
577
- } catch (error) {
578
- this.logger.error('[ERROR] Error processing EventBus Memory.UPDATE:', error);
579
-
580
- // Log error details for debugging without creating fake event payloads
581
- const operationId = event.data?.operationId || '[NO_OPERATION_ID]';
582
- const memoryId = event.data?.id || '[NO_MEMORY_ID]';
583
- this.logger.error(`Memory UPDATE operation failed - OperationId: ${operationId}, MemoryId: ${memoryId}, Error: ${(error as Error).message}`);
584
-
585
- // Cannot emit UPDATE_RESULT event without valid agentId and channelId from original request
586
- // Original event should have contained these required identifiers
587
- this.logger.warn('Cannot emit Memory.UPDATE_RESULT event - original event lacked valid agentId/channelId. Memory operation errors should be handled by the requesting component.');
588
785
  }
589
- });
590
-
786
+
787
+ const success = await firstValueFrom(
788
+ this.deleteMemory(event.data.scope, responseId)
789
+ );
790
+ EventBus.server.emit(
791
+ Events.Memory.DELETE_RESULT,
792
+ createMemoryDeleteResultEventPayload(
793
+ Events.Memory.DELETE_RESULT,
794
+ event.agentId,
795
+ event.channelId,
796
+ {
797
+ operationId: event.data.operationId,
798
+ scope: event.data.scope,
799
+ id: responseId,
800
+ success
801
+ }
802
+ )
803
+ );
804
+ } catch (error) {
805
+ this.emitMemoryDeleteError(event, responseId, error);
806
+ }
807
+ }
808
+
809
+ private emitMemoryGetError(
810
+ event: MemoryGetEventPayload,
811
+ id: string | string[],
812
+ error: unknown
813
+ ): void {
814
+ const message = error instanceof Error ? error.message : String(error);
815
+ this.logger.error(`Memory GET failed: ${message}`);
816
+ EventBus.server.emit(
817
+ Events.Memory.GET_RESULT,
818
+ createMemoryGetResultEventPayload(
819
+ Events.Memory.GET_RESULT,
820
+ event.agentId,
821
+ event.channelId,
822
+ {
823
+ operationId: event.data.operationId,
824
+ scope: event.data.scope,
825
+ id,
826
+ memory: null,
827
+ error: message
828
+ }
829
+ )
830
+ );
831
+ }
832
+
833
+ private emitMemoryUpdateError(
834
+ event: MemoryUpdateEventPayload,
835
+ id: string | string[],
836
+ error: unknown
837
+ ): void {
838
+ const message = error instanceof Error ? error.message : String(error);
839
+ this.logger.error(`Memory UPDATE failed: ${message}`);
840
+ EventBus.server.emit(
841
+ Events.Memory.UPDATE_RESULT,
842
+ createMemoryUpdateResultEventPayload(
843
+ Events.Memory.UPDATE_RESULT,
844
+ event.agentId,
845
+ event.channelId,
846
+ {
847
+ operationId: event.data.operationId,
848
+ scope: event.data.scope,
849
+ id,
850
+ memory: null,
851
+ error: message
852
+ }
853
+ )
854
+ );
855
+ }
856
+
857
+ private emitMemoryDeleteError(
858
+ event: MemoryDeleteEventPayload,
859
+ id: string | string[],
860
+ error: unknown
861
+ ): void {
862
+ const message = error instanceof Error ? error.message : String(error);
863
+ this.logger.error(`Memory DELETE failed: ${message}`);
864
+ EventBus.server.emit(
865
+ Events.Memory.DELETE_RESULT,
866
+ createMemoryDeleteResultEventPayload(
867
+ Events.Memory.DELETE_RESULT,
868
+ event.agentId,
869
+ event.channelId,
870
+ {
871
+ operationId: event.data.operationId,
872
+ scope: event.data.scope,
873
+ id,
874
+ success: false,
875
+ error: message
876
+ }
877
+ )
878
+ );
591
879
  }
592
880
 
593
881
  /**
@@ -625,11 +913,14 @@ export class MemoryService {
625
913
  if (persistence) {
626
914
  return new Observable<IEnhancedAgentMemory>(observer => {
627
915
  persistence.getAgentMemory(agentId).subscribe({
628
- next: (loadedMemory: any) => {
916
+ next: (loadedMemory: IAgentMemory) => {
629
917
  // Enhance the loaded memory with cognitive memory structure
918
+ const loadedCognitiveMemory = (
919
+ loadedMemory as Partial<IEnhancedAgentMemory>
920
+ ).cognitiveMemory;
630
921
  const enhancedMemory: IEnhancedAgentMemory = {
631
922
  ...loadedMemory,
632
- cognitiveMemory: loadedMemory.cognitiveMemory || {
923
+ cognitiveMemory: loadedCognitiveMemory ?? {
633
924
  observationIds: [],
634
925
  reasoningIds: [],
635
926
  planIds: [],
@@ -644,12 +935,10 @@ export class MemoryService {
644
935
  observer.next(enhancedMemory);
645
936
  observer.complete();
646
937
  },
647
- error: (error: any) => {
648
- this.logger.warn(`Failed to load agent memory from MongoDB for ${agentId}: ${error.message}`);
649
- // Fall back to creating new memory
650
- const newMemory = this.createNewAgentMemory(agentId);
651
- observer.next(newMemory);
652
- observer.complete();
938
+ error: (error: unknown) => {
939
+ const message = error instanceof Error ? error.message : String(error);
940
+ this.logger.error(`Failed to load agent memory from MongoDB for ${agentId}: ${message}`);
941
+ observer.error(error);
653
942
  }
654
943
  });
655
944
  });
@@ -685,167 +974,98 @@ export class MemoryService {
685
974
 
686
975
  this.agentMemory.set(agentId, newMemory);
687
976
 
688
- const operationId_agent_get_new = uuidv4();
689
- const systemAgentId_agent_get_new: AgentId = 'SYSTEM_AGENT';
690
- const noChannelId_agent_get_new: ChannelId = 'NO_CHANNEL';
691
- const updateResultData_agent_get_new: MemoryUpdateResultEventData = {
692
- operationId: operationId_agent_get_new,
693
- scope: MemoryScope.AGENT,
694
- id: agentId,
695
- memory: newMemory
696
- };
697
- EventBus.server.emit(
698
- Events.Memory.UPDATE_RESULT,
699
- createMemoryUpdateResultEventPayload(
700
- Events.Memory.UPDATE_RESULT,
701
- systemAgentId_agent_get_new,
702
- noChannelId_agent_get_new,
703
- updateResultData_agent_get_new
704
- )
705
- );
706
-
707
977
  return newMemory;
708
978
  }
709
979
 
710
980
  /**
711
981
  * Update agent memory
712
982
  *
713
- * When the update was requested over the wire (SDK → Events.Memory.UPDATE),
714
- * requestContext carries the requester's operationId and identity. The
715
- * UPDATE_RESULT emitted here must echo that operationId and be addressed to
716
- * the requesting agent: the SDK matches results by operationId, and event
717
- * forwarding routes them by payload.agentId. Before this parameter existed,
718
- * agent-scope results were emitted with a freshly generated operationId under
719
- * SYSTEM_AGENT — no SDK save round-trip could ever observe its own result, so
720
- * every awaited save hung forever and every fire-and-forget save leaked its
721
- * result listener.
722
- *
723
983
  * @param pAgentId Agent ID
724
984
  * @param updates Memory updates
725
- * @param requestContext Requester identity for result routing (wire requests only)
726
985
  * @returns Observable of updated agent memory
727
986
  */
728
987
  public updateAgentMemory(
729
988
  pAgentId: string,
730
- updates: Partial<IEnhancedAgentMemory>,
731
- requestContext?: { operationId: string; requesterAgentId: AgentId; requesterChannelId: ChannelId }
989
+ updates: Partial<IEnhancedAgentMemory>
732
990
  ): Observable<IEnhancedAgentMemory> {
733
991
  this.validator.assertIsNonEmptyString(pAgentId, 'Agent ID must be a non-empty string');
734
992
  this.validator.assertIsObject(updates, 'Updates must be an object');
735
-
736
- // Get existing memory or create new one
993
+
737
994
  return new Observable<IEnhancedAgentMemory>(observer => {
738
- this.getAgentMemory(pAgentId).subscribe(originalAgentMemory => {
739
- // Apply updates
740
- const updatedMemory: IEnhancedAgentMemory = {
741
- ...originalAgentMemory,
742
- ...updates,
743
- updatedAt: new Date(),
744
- // Ensure these fields can't be overridden
745
- id: originalAgentMemory.id,
746
- agentId: originalAgentMemory.agentId,
747
- createdAt: originalAgentMemory.createdAt
748
- };
749
-
750
- // Deep merge for nested objects
751
- if (updates.notes) {
752
- updatedMemory.notes = { ...originalAgentMemory.notes, ...updates.notes };
753
- }
754
-
755
- if (updates.customData) {
756
- updatedMemory.customData = { ...originalAgentMemory.customData, ...updates.customData };
757
- }
758
-
759
- if (updates.cognitiveMemory) {
760
- updatedMemory.cognitiveMemory = {
761
- ...originalAgentMemory.cognitiveMemory,
762
- ...updates.cognitiveMemory
763
- };
764
- }
765
-
766
- // Replace conversation history if provided (SDK sends full array, not incremental)
767
- if (updates.conversationHistory !== undefined) {
768
- updatedMemory.conversationHistory = updates.conversationHistory;
769
- }
770
-
771
- // Store updated memory in cache
772
- this.agentMemory.set(pAgentId, updatedMemory);
773
-
774
- // Persist to MongoDB if persistence service is available (async, non-blocking)
775
- if (this.persistenceService) {
776
- this.persistenceService.saveAgentMemory(updatedMemory)
777
- .subscribe({
778
- next: () => null,
779
- error: (err: any) => this.logger.warn(`Failed to persist agent memory to MongoDB for ${pAgentId}: ${err.message}`)
780
- });
781
- }
995
+ let cancelled = false;
996
+ void (async (): Promise<void> => {
997
+ try {
998
+ const enhancedStoredMemory = await this.serializeAgentMutation(
999
+ pAgentId,
1000
+ async (): Promise<IEnhancedAgentMemory> => {
1001
+ const originalAgentMemory = await firstValueFrom(
1002
+ this.getAgentMemory(pAgentId)
1003
+ );
1004
+ const updatedMemory: IEnhancedAgentMemory = {
1005
+ ...originalAgentMemory,
1006
+ ...updates,
1007
+ updatedAt: new Date(),
1008
+ id: originalAgentMemory.id,
1009
+ agentId: originalAgentMemory.agentId,
1010
+ createdAt: originalAgentMemory.createdAt,
1011
+ notes: updates.notes
1012
+ ? { ...originalAgentMemory.notes, ...updates.notes }
1013
+ : originalAgentMemory.notes,
1014
+ customData: updates.customData
1015
+ ? { ...originalAgentMemory.customData, ...updates.customData }
1016
+ : originalAgentMemory.customData,
1017
+ cognitiveMemory: updates.cognitiveMemory
1018
+ ? {
1019
+ ...originalAgentMemory.cognitiveMemory,
1020
+ ...updates.cognitiveMemory
1021
+ }
1022
+ : originalAgentMemory.cognitiveMemory
1023
+ };
782
1024
 
783
- // Trigger entity extraction from conversation history if Knowledge Graph is enabled
784
- // This extracts entities and relationships for the Knowledge Graph
785
- if (updates.conversationHistory && updates.conversationHistory.length > 0) {
786
- const lastMessages = updates.conversationHistory.slice(-3);
787
- const contentToExtract = lastMessages
788
- .filter((msg): msg is typeof msg & { content: string } =>
789
- typeof msg.content === 'string' && msg.content.length > 0)
790
- .map(msg => msg.content)
791
- .join('\n\n');
792
-
793
- if (contentToExtract.length > 0) {
794
- // Use agent ID as channel context for agent-level memories
795
- // Entities extracted from agent memory are scoped to a pseudo-channel
796
- const channelContext = `agent-memory-${pAgentId}`;
797
- const memoryId = `agent-${pAgentId}-${Date.now()}`;
798
- this.triggerEntityExtraction(channelContext, memoryId, contentToExtract)
799
- .catch(err => this.logger.warn(`Entity extraction failed: ${err.message}`));
1025
+ const storedMemory = this.persistenceService
1026
+ ? await firstValueFrom(
1027
+ this.persistenceService.saveAgentMemory(updatedMemory)
1028
+ )
1029
+ : updatedMemory;
1030
+ const enhancedMemory: IEnhancedAgentMemory = {
1031
+ ...storedMemory,
1032
+ cognitiveMemory: updatedMemory.cognitiveMemory
1033
+ };
1034
+ this.agentMemory.set(pAgentId, enhancedMemory);
1035
+ return enhancedMemory;
1036
+ }
1037
+ );
1038
+
1039
+ if (updates.conversationHistory && updates.conversationHistory.length > 0) {
1040
+ const contentToExtract = updates.conversationHistory
1041
+ .slice(-3)
1042
+ .filter((message): message is typeof message & { content: string } =>
1043
+ typeof message.content === 'string' && message.content.length > 0)
1044
+ .map(message => message.content)
1045
+ .join('\n\n');
1046
+ if (contentToExtract.length > 0) {
1047
+ const channelContext = `agent-memory-${pAgentId}`;
1048
+ const memoryId = `agent-${pAgentId}-${Date.now()}`;
1049
+ this.triggerEntityExtraction(channelContext, memoryId, contentToExtract)
1050
+ .catch(error => this.logger.warn(
1051
+ `Entity extraction failed: ${error instanceof Error ? error.message : String(error)}`
1052
+ ));
1053
+ }
800
1054
  }
801
- }
802
1055
 
803
- // Emit update event through EventBus. Echo the requester's
804
- // operationId and address the result to the requesting agent so
805
- // the SDK's pending save resolves; internal callers (no
806
- // requestContext) keep the system-level identity.
807
- const operationId = requestContext?.operationId ?? uuidv4();
808
- const updateResultData: MemoryUpdateResultEventData = {
809
- operationId,
810
- scope: MemoryScope.AGENT,
811
- id: pAgentId,
812
- memory: updatedMemory
813
- };
814
-
815
- const resultAgentId: AgentId = requestContext?.requesterAgentId ?? 'SYSTEM_AGENT';
816
- const resultChannelId: ChannelId = requestContext?.requesterChannelId ?? 'NO_CHANNEL';
817
-
818
- const payload = createMemoryUpdateResultEventPayload(
819
- Events.Memory.UPDATE_RESULT,
820
- resultAgentId,
821
- resultChannelId,
822
- updateResultData
823
- );
824
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, payload);
825
-
826
- observer.next(updatedMemory);
827
- observer.complete();
828
- }, error => {
829
- // Errors must reach the requester too — a save whose failure is
830
- // only logged server-side leaves the requesting SDK waiting forever.
831
- const updateResultData_agent_update_error: MemoryUpdateResultEventData = {
832
- operationId: requestContext?.operationId ?? uuidv4(),
833
- scope: MemoryScope.AGENT,
834
- id: pAgentId,
835
- memory: null,
836
- error: (error as Error).message
837
- };
838
- EventBus.server.emit(
839
- Events.Memory.UPDATE_RESULT,
840
- createMemoryUpdateResultEventPayload(
841
- Events.Memory.UPDATE_RESULT,
842
- requestContext?.requesterAgentId ?? 'SYSTEM_AGENT',
843
- requestContext?.requesterChannelId ?? 'NO_CHANNEL',
844
- updateResultData_agent_update_error
845
- )
846
- );
847
- observer.error(error);
848
- });
1056
+ if (!cancelled) {
1057
+ observer.next(enhancedStoredMemory);
1058
+ observer.complete();
1059
+ }
1060
+ } catch (error) {
1061
+ if (!cancelled) {
1062
+ observer.error(error);
1063
+ }
1064
+ }
1065
+ })();
1066
+ return () => {
1067
+ cancelled = true;
1068
+ };
849
1069
  });
850
1070
  }
851
1071
 
@@ -1147,7 +1367,7 @@ export class MemoryService {
1147
1367
  * @param options Query options
1148
1368
  * @returns Observable of cognitive memory entries
1149
1369
  */
1150
- public queryCognitiveMemory(agentId: AgentId, channelId: ChannelId, options: CognitiveMemoryQueryOptions = {}): Observable<CognitiveMemoryEntry<any>[]> {
1370
+ public queryCognitiveMemory(agentId: AgentId, channelId: ChannelId, options: CognitiveMemoryQueryOptions = {}): Observable<CognitiveMemoryEntry<unknown>[]> {
1151
1371
  this.validator.assertIsNonEmptyString(agentId, 'Agent ID must be a non-empty string');
1152
1372
  this.validator.assertIsNonEmptyString(channelId, 'Channel ID must be a non-empty string');
1153
1373
 
@@ -1201,18 +1421,38 @@ export class MemoryService {
1201
1421
  * @returns Observable of channel memory
1202
1422
  */
1203
1423
  public getChannelMemory(channelId: string): Observable<IEnhancedChannelMemory> {
1204
- // ;
1205
1424
  this.validator.assertIsNonEmptyString(channelId, 'Channel ID must be a non-empty string');
1206
-
1207
- // Return from cache if available
1208
- if (this.channelMemory.has(channelId)) {
1209
- const memory = this.channelMemory.get(channelId)!;
1210
- // ;
1211
- return of(memory);
1425
+
1426
+ const existingMemory = this.channelMemory.get(channelId);
1427
+ if (existingMemory) {
1428
+ return of(existingMemory);
1212
1429
  }
1213
-
1214
-
1215
- // Create new memory
1430
+
1431
+ const getPersistedChannelMemory = this.persistenceService?.getChannelMemory;
1432
+ if (this.persistenceService && !getPersistedChannelMemory) {
1433
+ return throwError(() => new Error('Channel memory persistence is not available'));
1434
+ }
1435
+ if (getPersistedChannelMemory) {
1436
+ return new Observable<IEnhancedChannelMemory>(observer => {
1437
+ getPersistedChannelMemory.call(this.persistenceService, channelId).subscribe({
1438
+ next: (loadedMemory: IChannelMemory) => {
1439
+ const enhancedMemory: IEnhancedChannelMemory = {
1440
+ ...loadedMemory,
1441
+ sharedCognitiveInsights: {
1442
+ systemSummaries: [],
1443
+ topicExtractions: [],
1444
+ collaborativeReflections: []
1445
+ }
1446
+ };
1447
+ this.channelMemory.set(channelId, enhancedMemory);
1448
+ observer.next(enhancedMemory);
1449
+ observer.complete();
1450
+ },
1451
+ error: (error: unknown) => observer.error(error)
1452
+ });
1453
+ });
1454
+ }
1455
+
1216
1456
  const newMemory: IEnhancedChannelMemory = {
1217
1457
  id: uuidv4(),
1218
1458
  channelId,
@@ -1234,28 +1474,7 @@ export class MemoryService {
1234
1474
  collaborativeReflections: []
1235
1475
  }
1236
1476
  };
1237
-
1238
1477
  this.channelMemory.set(channelId, newMemory);
1239
-
1240
- const operationId_channel_get_new = uuidv4();
1241
- const systemAgentId_channel_get_new: AgentId = 'SYSTEM_AGENT';
1242
- const noChannelId_channel_get_new: ChannelId = 'NO_CHANNEL';
1243
- const updateResultData_channel_get_new: MemoryUpdateResultEventData = {
1244
- operationId: operationId_channel_get_new,
1245
- scope: MemoryScope.CHANNEL,
1246
- id: channelId,
1247
- memory: newMemory
1248
- };
1249
- EventBus.server.emit(
1250
- Events.Memory.UPDATE_RESULT,
1251
- createMemoryUpdateResultEventPayload(
1252
- Events.Memory.UPDATE_RESULT,
1253
- systemAgentId_channel_get_new,
1254
- noChannelId_channel_get_new,
1255
- updateResultData_channel_get_new
1256
- )
1257
- );
1258
-
1259
1478
  return of(newMemory);
1260
1479
  }
1261
1480
 
@@ -1267,85 +1486,85 @@ export class MemoryService {
1267
1486
  */
1268
1487
  public updateChannelMemory(channelId: ChannelId, updates: Partial<IEnhancedChannelMemory>): Observable<IEnhancedChannelMemory> {
1269
1488
  this.validator.assertIsNonEmptyString(channelId, 'Channel ID must be a non-empty string');
1489
+ this.validator.assertIsObject(updates, 'Channel memory updates must be an object');
1490
+ if (
1491
+ this.ownsPathOrDescendant(updates, 'conversationHistory') ||
1492
+ this.ownsPathOrDescendant(updates, 'sharedState.context') ||
1493
+ this.ownsPathOrDescendant(updates, 'customData.contextHistory') ||
1494
+ this.ownsPathOrDescendant(updates.sharedState, 'context') ||
1495
+ this.ownsPathOrDescendant(updates.customData, 'contextHistory')
1496
+ ) {
1497
+ throw new Error(
1498
+ 'Reserved channel memory fields must use the atomic keyed-memory operations'
1499
+ );
1500
+ }
1270
1501
 
1271
1502
  return new Observable<IEnhancedChannelMemory>(observer => {
1272
- this.getChannelMemory(channelId).subscribe(originalChannelMemory => {
1273
- // Create updated memory by merging with original
1274
- const updatedMemory: IEnhancedChannelMemory = {
1275
- ...originalChannelMemory, // This spreads all base properties
1276
- channelId,
1277
- lastActivity: updates.lastActivity || originalChannelMemory.lastActivity || Date.now(),
1278
- messageCount: updates.messageCount !== undefined ? updates.messageCount : originalChannelMemory.messageCount,
1279
- participants: updates.participants
1280
- ? [...new Set([...(originalChannelMemory.participants || []), ...updates.participants])]
1281
- : originalChannelMemory.participants,
1282
- topics: updates.topics
1283
- ? [...new Set([...(originalChannelMemory.topics || []), ...updates.topics])]
1284
- : originalChannelMemory.topics,
1285
- summary: updates.summary || originalChannelMemory.summary,
1286
- conversationHistory: [...(originalChannelMemory.conversationHistory || [])],
1287
- sharedCognitiveInsights: {
1288
- ...originalChannelMemory.sharedCognitiveInsights,
1289
- ...updates.sharedCognitiveInsights
1290
- }
1291
- };
1503
+ let cancelled = false;
1504
+ void (async (): Promise<void> => {
1505
+ try {
1506
+ const enhancedStoredMemory = await this.serializeChannelMutation(
1507
+ channelId,
1508
+ async (): Promise<IEnhancedChannelMemory> => {
1509
+ const originalMemory = await firstValueFrom(this.getChannelMemory(channelId));
1510
+ const updatedMemory: IEnhancedChannelMemory = {
1511
+ ...originalMemory,
1512
+ ...updates,
1513
+ id: originalMemory.id,
1514
+ channelId,
1515
+ createdAt: originalMemory.createdAt,
1516
+ updatedAt: new Date(),
1517
+ notes: updates.notes
1518
+ ? { ...originalMemory.notes, ...updates.notes }
1519
+ : originalMemory.notes,
1520
+ sharedState: updates.sharedState
1521
+ ? { ...originalMemory.sharedState, ...updates.sharedState }
1522
+ : originalMemory.sharedState,
1523
+ customData: updates.customData
1524
+ ? { ...originalMemory.customData, ...updates.customData }
1525
+ : originalMemory.customData,
1526
+ participants: updates.participants
1527
+ ? [...new Set([...(originalMemory.participants ?? []), ...updates.participants])]
1528
+ : originalMemory.participants,
1529
+ topics: updates.topics
1530
+ ? [...new Set([...(originalMemory.topics ?? []), ...updates.topics])]
1531
+ : originalMemory.topics,
1532
+ conversationHistory: updates.conversationHistory
1533
+ ? [
1534
+ ...(originalMemory.conversationHistory ?? []),
1535
+ ...updates.conversationHistory
1536
+ ]
1537
+ : originalMemory.conversationHistory,
1538
+ sharedCognitiveInsights: {
1539
+ ...originalMemory.sharedCognitiveInsights,
1540
+ ...updates.sharedCognitiveInsights
1541
+ }
1542
+ };
1292
1543
 
1293
- // Handle conversation history updates
1294
- if (updates.conversationHistory && updates.conversationHistory.length > 0) {
1295
- updatedMemory.conversationHistory = [
1296
- ...(originalChannelMemory.conversationHistory || []),
1297
- ...updates.conversationHistory
1298
- ];
1544
+ const storedMemory = this.persistenceService
1545
+ ? await firstValueFrom(this.persistenceService.saveChannelMemory(updatedMemory))
1546
+ : updatedMemory;
1547
+ const enhancedMemory: IEnhancedChannelMemory = {
1548
+ ...storedMemory,
1549
+ sharedCognitiveInsights: updatedMemory.sharedCognitiveInsights
1550
+ };
1551
+ this.channelMemory.set(channelId, enhancedMemory);
1552
+ return enhancedMemory;
1553
+ }
1554
+ );
1555
+ if (!cancelled) {
1556
+ observer.next(enhancedStoredMemory);
1557
+ observer.complete();
1558
+ }
1559
+ } catch (error) {
1560
+ if (!cancelled) {
1561
+ observer.error(error);
1562
+ }
1299
1563
  }
1300
-
1301
- // Store updated memory in cache
1302
- this.channelMemory.set(channelId, updatedMemory);
1303
-
1304
- // Emit update event through EventBus
1305
- const operationId = uuidv4();
1306
- const updateResultData: MemoryUpdateResultEventData = {
1307
- operationId,
1308
- scope: MemoryScope.CHANNEL,
1309
- id: channelId,
1310
- memory: updatedMemory
1311
- };
1312
-
1313
- // Define standard agentId and channelId for system-level memory events
1314
- const systemAgentId: AgentId = 'SYSTEM_AGENT';
1315
- const systemChannelId: ChannelId = channelId; // Use the actual channel ID for channel operations
1316
-
1317
- const payload = createMemoryUpdateResultEventPayload(
1318
- Events.Memory.UPDATE_RESULT,
1319
- systemAgentId,
1320
- systemChannelId,
1321
- updateResultData
1322
- );
1323
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, payload);
1324
-
1325
- observer.next(updatedMemory);
1326
- observer.complete();
1327
- }, error => {
1328
- const operationId_channel_update_error = uuidv4();
1329
- const updateResultData_channel_update_error: MemoryUpdateResultEventData = {
1330
- operationId: operationId_channel_update_error,
1331
- scope: MemoryScope.CHANNEL,
1332
- id: channelId,
1333
- memory: null,
1334
- error: (error as Error).message
1335
- };
1336
- const systemAgentId_channel_update_error: AgentId = 'SYSTEM_AGENT';
1337
- const systemChannelId_channel_update_error: ChannelId = channelId;
1338
- EventBus.server.emit(
1339
- Events.Memory.UPDATE_RESULT,
1340
- createMemoryUpdateResultEventPayload(
1341
- Events.Memory.UPDATE_RESULT,
1342
- systemAgentId_channel_update_error,
1343
- systemChannelId_channel_update_error,
1344
- updateResultData_channel_update_error
1345
- )
1346
- );
1347
- observer.error(error);
1348
- });
1564
+ })();
1565
+ return () => {
1566
+ cancelled = true;
1567
+ };
1349
1568
  });
1350
1569
  }
1351
1570
 
@@ -1374,7 +1593,28 @@ export class MemoryService {
1374
1593
  return of(existingMemory);
1375
1594
  }
1376
1595
 
1377
- // Create new memory
1596
+ const getPersistedRelationshipMemory = this.persistenceService?.getRelationshipMemory;
1597
+ if (this.persistenceService && !getPersistedRelationshipMemory) {
1598
+ return throwError(() => new Error('Relationship memory persistence is not available'));
1599
+ }
1600
+ if (channelId && getPersistedRelationshipMemory) {
1601
+ return new Observable<IRelationshipMemory>(observer => {
1602
+ getPersistedRelationshipMemory.call(
1603
+ this.persistenceService,
1604
+ sortedId1,
1605
+ sortedId2,
1606
+ channelId
1607
+ ).subscribe({
1608
+ next: (loadedMemory: IRelationshipMemory) => {
1609
+ this.relationshipMemory.set(relationshipKey, loadedMemory);
1610
+ observer.next(loadedMemory);
1611
+ observer.complete();
1612
+ },
1613
+ error: (error: unknown) => observer.error(error)
1614
+ });
1615
+ });
1616
+ }
1617
+
1378
1618
  const newMemory: IRelationshipMemory = {
1379
1619
  id: uuidv4(),
1380
1620
  agentId1: sortedId1,
@@ -1387,28 +1627,7 @@ export class MemoryService {
1387
1627
  interactionHistory: [],
1388
1628
  customData: {}
1389
1629
  };
1390
-
1391
1630
  this.relationshipMemory.set(relationshipKey, newMemory);
1392
-
1393
- const operationId_rel_get_new = uuidv4();
1394
- const systemAgentId_rel_get_new: AgentId = 'SYSTEM_AGENT';
1395
- const noChannelId_rel_get_new: ChannelId = 'NO_CHANNEL';
1396
- const updateResultData_rel_get_new: MemoryUpdateResultEventData = {
1397
- operationId: operationId_rel_get_new,
1398
- scope: MemoryScope.RELATIONSHIP,
1399
- id: relationshipKey,
1400
- memory: newMemory
1401
- };
1402
- EventBus.server.emit(
1403
- Events.Memory.UPDATE_RESULT,
1404
- createMemoryUpdateResultEventPayload(
1405
- Events.Memory.UPDATE_RESULT,
1406
- systemAgentId_rel_get_new,
1407
- noChannelId_rel_get_new,
1408
- updateResultData_rel_get_new
1409
- )
1410
- );
1411
-
1412
1631
  return of(newMemory);
1413
1632
  }
1414
1633
 
@@ -1428,123 +1647,195 @@ export class MemoryService {
1428
1647
 
1429
1648
  const relationshipKey = this.getRelationshipKey(pAgentId1, pAgentId2, pChannelId);
1430
1649
 
1431
- // Get existing memory or create new one
1432
1650
  return new Observable<IRelationshipMemory>(observer => {
1433
- this.getRelationshipMemory(pAgentId1, pAgentId2, pChannelId).subscribe(originalRelationshipMemory => {
1434
- // Apply updates
1435
- const updatedMemory: IRelationshipMemory = {
1436
- ...originalRelationshipMemory,
1437
- ...updates,
1438
- updatedAt: new Date(),
1439
- // Ensure these fields can't be overridden
1440
- id: originalRelationshipMemory.id,
1441
- agentId1: originalRelationshipMemory.agentId1,
1442
- agentId2: originalRelationshipMemory.agentId2,
1443
- channelId: originalRelationshipMemory.channelId,
1444
- createdAt: originalRelationshipMemory.createdAt
1445
- };
1446
-
1447
- // Deep merge for nested objects (if any)
1448
- // Example: if (updates.customData) { updatedMemory.customData = { ...originalRelationshipMemory.customData, ...updates.customData }; }
1449
-
1450
- // Update in-memory store
1451
- this.relationshipMemory.set(relationshipKey, updatedMemory);
1452
-
1453
- const operationId_rel_update_success = uuidv4();
1454
- const systemAgentId_rel_update_success: AgentId = 'SYSTEM_AGENT';
1455
- const noChannelId_rel_update_success: ChannelId = 'NO_CHANNEL'; // General system event
1456
- const updateResultData_rel_update_success: MemoryUpdateResultEventData = {
1457
- operationId: operationId_rel_update_success,
1458
- scope: MemoryScope.RELATIONSHIP,
1459
- id: relationshipKey,
1460
- memory: updatedMemory
1461
- };
1462
- EventBus.server.emit(
1463
- Events.Memory.UPDATE_RESULT,
1464
- createMemoryUpdateResultEventPayload(
1465
- Events.Memory.UPDATE_RESULT,
1466
- systemAgentId_rel_update_success,
1467
- noChannelId_rel_update_success,
1468
- updateResultData_rel_update_success
1469
- )
1470
- );
1471
-
1472
- // Return updated memory
1473
- observer.next(updatedMemory);
1474
- observer.complete();
1475
- }, error => { // This 'error' is from getRelationshipMemory()
1476
- const operationId_rel_update_error = uuidv4();
1477
- const systemAgentId_rel_update_error: AgentId = 'SYSTEM_AGENT';
1478
- const noChannelId_rel_update_error: ChannelId = 'NO_CHANNEL';
1479
- // Reconstruct the key for the 'id' field as it was the one attempted for the update.
1480
- const attemptedRelationshipKey = this.getRelationshipKey(pAgentId1, pAgentId2, pChannelId);
1481
- const updateResultData_rel_update_error: MemoryUpdateResultEventData = {
1482
- operationId: operationId_rel_update_error,
1483
- scope: MemoryScope.RELATIONSHIP,
1484
- id: attemptedRelationshipKey, // Use the key that was attempted
1485
- memory: null,
1486
- error: (error as Error).message
1487
- };
1488
- EventBus.server.emit(
1489
- Events.Memory.UPDATE_RESULT,
1490
- createMemoryUpdateResultEventPayload(
1491
- Events.Memory.UPDATE_RESULT,
1492
- systemAgentId_rel_update_error,
1493
- noChannelId_rel_update_error,
1494
- updateResultData_rel_update_error
1495
- )
1496
- );
1497
- observer.error(error);
1498
- });
1651
+ let cancelled = false;
1652
+ void (async (): Promise<void> => {
1653
+ try {
1654
+ const storedMemory = await this.serializeRelationshipMutation(
1655
+ pAgentId1,
1656
+ pAgentId2,
1657
+ pChannelId,
1658
+ async (): Promise<IRelationshipMemory> => {
1659
+ const originalMemory = await firstValueFrom(
1660
+ this.getRelationshipMemory(pAgentId1, pAgentId2, pChannelId)
1661
+ );
1662
+ const updatedMemory: IRelationshipMemory = {
1663
+ ...originalMemory,
1664
+ ...updates,
1665
+ id: originalMemory.id,
1666
+ agentId1: originalMemory.agentId1,
1667
+ agentId2: originalMemory.agentId2,
1668
+ channelId: originalMemory.channelId,
1669
+ createdAt: originalMemory.createdAt,
1670
+ updatedAt: new Date(),
1671
+ notes: updates.notes
1672
+ ? { ...originalMemory.notes, ...updates.notes }
1673
+ : originalMemory.notes,
1674
+ customData: updates.customData
1675
+ ? { ...originalMemory.customData, ...updates.customData }
1676
+ : originalMemory.customData
1677
+ };
1678
+ const saveRelationshipMemory = this.persistenceService?.saveRelationshipMemory;
1679
+ if (this.persistenceService && !saveRelationshipMemory) {
1680
+ throw new Error('Relationship memory persistence is not available');
1681
+ }
1682
+ const persistedMemory = saveRelationshipMemory
1683
+ ? await firstValueFrom(saveRelationshipMemory.call(
1684
+ this.persistenceService,
1685
+ updatedMemory
1686
+ ))
1687
+ : updatedMemory;
1688
+ this.relationshipMemory.set(relationshipKey, persistedMemory);
1689
+ return persistedMemory;
1690
+ }
1691
+ );
1692
+ if (!cancelled) {
1693
+ observer.next(storedMemory);
1694
+ observer.complete();
1695
+ }
1696
+ } catch (error) {
1697
+ if (!cancelled) {
1698
+ observer.error(error);
1699
+ }
1700
+ }
1701
+ })();
1702
+ return () => {
1703
+ cancelled = true;
1704
+ };
1499
1705
  });
1500
1706
  }
1501
1707
 
1502
1708
  /**
1503
1709
  * Delete memory by scope and ID
1504
1710
  * @param scope Memory scope
1505
- * @param id Entity ID
1711
+ * @param id Entity ID or relationship composite ID
1506
1712
  * @returns Observable of success status
1507
1713
  */
1508
- public deleteMemory(scope: MemoryScope, id: string): Observable<boolean> {
1714
+ public deleteMemory(scope: MemoryScope, id: string | string[]): Observable<boolean> {
1509
1715
  this.validator.validateMemoryScope(scope);
1510
- this.validator.assertIsNonEmptyString(id, 'ID must be a non-empty string');
1511
-
1512
- let success = false;
1513
- const operationId = uuidv4(); // Generate operationId for the event data
1514
-
1515
- switch (scope) {
1516
- case MemoryScope.AGENT:
1517
- success = this.agentMemory.delete(id);
1518
- break;
1519
- case MemoryScope.CHANNEL:
1520
- success = this.channelMemory.delete(id);
1521
- break;
1522
- case MemoryScope.RELATIONSHIP:
1523
- success = this.relationshipMemory.delete(id);
1524
- break;
1716
+ if (scope === MemoryScope.RELATIONSHIP) {
1717
+ if (!Array.isArray(id) || id.length !== 3) {
1718
+ throw new Error('Relationship memory deletion requires agentId1, agentId2, and channelId');
1719
+ }
1720
+ id.forEach((part, index) => {
1721
+ this.validator.assertIsNonEmptyString(part, `Relationship delete ID part ${index}`);
1722
+ });
1723
+ } else {
1724
+ this.validator.assertIsNonEmptyString(id, 'Memory ID must be a non-empty string');
1525
1725
  }
1526
-
1527
- // Emit delete event through EventBus
1528
- const deleteResultData: MemoryDeleteResultEventData = {
1529
- operationId,
1530
- scope,
1531
- id,
1532
- success
1533
- };
1534
1726
 
1535
- // Define standard agentId and channelId for system-level memory events
1536
- const systemAgentId: AgentId = 'SYSTEM_AGENT'; // Or a more specific system agent ID
1537
- const noChannelId: ChannelId = 'NO_CHANNEL'; // Or a more specific system channel ID or null if appropriate
1727
+ return new Observable<boolean>(observer => {
1728
+ let cancelled = false;
1729
+ void (async (): Promise<void> => {
1730
+ try {
1731
+ if (
1732
+ scope === MemoryScope.CHANNEL &&
1733
+ typeof id === 'string' &&
1734
+ id.startsWith('channel:')
1735
+ ) {
1736
+ const success = await this.deleteKeyedChannelMemory(id);
1737
+ if (!cancelled) {
1738
+ observer.next(success);
1739
+ observer.complete();
1740
+ }
1741
+ return;
1742
+ }
1743
+ const deleteAuthoritatively = async (): Promise<boolean> => {
1744
+ const deletePersistentMemory = this.persistenceService?.deleteMemory;
1745
+ if (this.persistenceService && !deletePersistentMemory) {
1746
+ throw new Error('Memory deletion persistence is not available');
1747
+ }
1748
+ const persisted = deletePersistentMemory
1749
+ ? await firstValueFrom(deletePersistentMemory.call(
1750
+ this.persistenceService,
1751
+ scope,
1752
+ id
1753
+ ))
1754
+ : false;
1755
+ if (this.persistenceService && !persisted) {
1756
+ return false;
1757
+ }
1758
+ let cached = false;
1759
+
1760
+ switch (scope) {
1761
+ case MemoryScope.AGENT: {
1762
+ const agentId = id as string;
1763
+ cached = this.agentMemory.delete(agentId);
1764
+ for (const [key, memory] of this.relationshipMemory.entries()) {
1765
+ if (memory.agentId1 === agentId || memory.agentId2 === agentId) {
1766
+ cached = this.relationshipMemory.delete(key) || cached;
1767
+ }
1768
+ }
1769
+ for (const [key, memory] of this.cognitiveMemory.entries()) {
1770
+ if (memory.agentId === agentId) {
1771
+ cached = this.cognitiveMemory.delete(key) || cached;
1772
+ }
1773
+ }
1774
+ break;
1775
+ }
1776
+ case MemoryScope.CHANNEL: {
1777
+ const channelId = id as string;
1778
+ cached = this.channelMemory.has(channelId);
1779
+ cached = this.channelMemory.delete(channelId) || cached;
1780
+ for (const key of this.generalData.keys()) {
1781
+ if (key.endsWith(`:${channelId}`)) {
1782
+ cached = this.generalData.delete(key) || cached;
1783
+ }
1784
+ }
1785
+ break;
1786
+ }
1787
+ case MemoryScope.RELATIONSHIP: {
1788
+ const [agentId1, agentId2, channelId] = id as string[];
1789
+ cached = this.relationshipMemory.delete(
1790
+ this.getRelationshipKey(agentId1, agentId2, channelId)
1791
+ );
1792
+ break;
1793
+ }
1794
+ }
1795
+
1796
+ return this.persistenceService ? persisted : cached;
1797
+ };
1538
1798
 
1539
- const payload = createMemoryDeleteResultEventPayload(
1540
- Events.Memory.DELETE_RESULT,
1541
- systemAgentId,
1542
- noChannelId,
1543
- deleteResultData
1544
- );
1545
- EventBus.server.emit(Events.Memory.DELETE_RESULT, payload);
1546
-
1547
- return of(success);
1799
+ let deleted: boolean;
1800
+ switch (scope) {
1801
+ case MemoryScope.AGENT:
1802
+ deleted = await this.serializeAgentMutation(
1803
+ id as string,
1804
+ deleteAuthoritatively
1805
+ );
1806
+ break;
1807
+ case MemoryScope.CHANNEL:
1808
+ deleted = await this.serializeChannelMutation(
1809
+ id as string,
1810
+ deleteAuthoritatively
1811
+ );
1812
+ break;
1813
+ case MemoryScope.RELATIONSHIP: {
1814
+ const [agentId1, agentId2, channelId] = id as string[];
1815
+ deleted = await this.serializeRelationshipMutation(
1816
+ agentId1,
1817
+ agentId2,
1818
+ channelId,
1819
+ deleteAuthoritatively
1820
+ );
1821
+ break;
1822
+ }
1823
+ }
1824
+
1825
+ if (!cancelled) {
1826
+ observer.next(deleted);
1827
+ observer.complete();
1828
+ }
1829
+ } catch (error) {
1830
+ if (!cancelled) {
1831
+ observer.error(error);
1832
+ }
1833
+ }
1834
+ })();
1835
+ return () => {
1836
+ cancelled = true;
1837
+ };
1838
+ });
1548
1839
  }
1549
1840
 
1550
1841
  /**
@@ -1599,15 +1890,15 @@ export class MemoryService {
1599
1890
  * Get general key-value data
1600
1891
  * Used for tool-level key-value storage
1601
1892
  */
1602
- public getGeneralData(key: string): any {
1603
- return this.generalData.get(key);
1893
+ public getGeneralData<T = GeneralDataRecord>(key: string): T | undefined {
1894
+ return this.generalData.get(key) as T | undefined;
1604
1895
  }
1605
1896
 
1606
1897
  /**
1607
1898
  * Set general key-value data
1608
1899
  * Used for tool-level key-value storage
1609
1900
  */
1610
- public setGeneralData(key: string, value: any): void {
1901
+ public setGeneralData(key: string, value: unknown): void {
1611
1902
  this.generalData.set(key, value);
1612
1903
  }
1613
1904
 
@@ -1857,9 +2148,9 @@ export class MemoryService {
1857
2148
  `${result.relationshipsExtracted} relationships from memory ${memoryId}`
1858
2149
  );
1859
2150
  }
1860
- } catch (error: any) {
2151
+ } catch (error: unknown) {
1861
2152
  this.logger.warn(
1862
- `[MemoryService] Entity extraction failed for memory ${memoryId}: ${error.message}`
2153
+ `[MemoryService] Entity extraction failed for memory ${memoryId}: ${error instanceof Error ? error.message : String(error)}`
1863
2154
  );
1864
2155
  }
1865
2156
  }
@@ -1907,7 +2198,7 @@ export class MemoryService {
1907
2198
  * Compare two data objects to determine if they are equal
1908
2199
  * Uses deep comparison for objects and arrays
1909
2200
  */
1910
- private isDataEqual(data1: any, data2: any): boolean {
2201
+ private isDataEqual(data1: unknown, data2: unknown): boolean {
1911
2202
  // Handle null/undefined cases
1912
2203
  if (data1 === data2) return true;
1913
2204
  if (data1 == null || data2 == null) return false;
@@ -1926,13 +2217,15 @@ export class MemoryService {
1926
2217
  // Handle objects
1927
2218
  if (Array.isArray(data1) || Array.isArray(data2)) return false;
1928
2219
 
1929
- const keys1 = Object.keys(data1);
1930
- const keys2 = Object.keys(data2);
2220
+ const record1 = data1 as Record<string, unknown>;
2221
+ const record2 = data2 as Record<string, unknown>;
2222
+ const keys1 = Object.keys(record1);
2223
+ const keys2 = Object.keys(record2);
1931
2224
 
1932
2225
  if (keys1.length !== keys2.length) return false;
1933
2226
 
1934
2227
  return keys1.every(key =>
1935
- keys2.includes(key) && this.isDataEqual(data1[key], data2[key])
2228
+ keys2.includes(key) && this.isDataEqual(record1[key], record2[key])
1936
2229
  );
1937
2230
  }
1938
2231
  }