@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
@@ -27,7 +27,7 @@
27
27
  * CONSOLIDATED: Includes cognitive operations from AgentMemoryService
28
28
  * for LLM workflows (observations, reasoning, plans, reflections).
29
29
  */
30
- import { Observable, of } from 'rxjs';
30
+ import { firstValueFrom, Observable, of, throwError } from 'rxjs';
31
31
  import { MxfMeilisearchService } from './MxfMeilisearchService.js';
32
32
  import { v4 as uuidv4 } from 'uuid';
33
33
  import { MemoryScope, MemoryPersistenceLevel, createMemoryValidator } from '../types/MemoryTypes.js';
@@ -70,6 +70,9 @@ export class MemoryService {
70
70
  relationshipMemory = new Map();
71
71
  generalData = new Map();
72
72
  cognitiveMemory = new Map();
73
+ agentMutationTails = new Map();
74
+ channelMutationTails = new Map();
75
+ relationshipMutationTails = new Map();
73
76
  // Configuration
74
77
  config;
75
78
  // Optional persistence service (server-only)
@@ -85,10 +88,6 @@ export class MemoryService {
85
88
  constructor(config = {}) {
86
89
  this.config = { ...DEFAULT_CONFIG, ...config };
87
90
  this.persistenceService = config.persistenceService;
88
- if (this.persistenceService) {
89
- }
90
- else {
91
- }
92
91
  // Set up event listeners
93
92
  this.setupEventListeners();
94
93
  }
@@ -96,291 +95,464 @@ export class MemoryService {
96
95
  * Set up event listeners
97
96
  */
98
97
  setupEventListeners() {
99
- // Listen for memory update events to keep cache in sync
100
- EventBus.server.on(Events.Memory.UPDATE_RESULT, (data) => {
101
- if (data.scope === MemoryScope.AGENT && data.memory) {
102
- this.agentMemory.set(data.id, data.memory);
103
- // ;
104
- }
105
- else if (data.scope === MemoryScope.CHANNEL && data.memory) {
106
- this.channelMemory.set(data.id, data.memory);
107
- // ;
98
+ // Return each request promise so EventBus.drain() retains ownership of
99
+ // acknowledged memory work until persistence and the response event
100
+ // have both completed.
101
+ EventBus.server.on(Events.Memory.GET, (event) => this.handleMemoryGetRequest(event));
102
+ EventBus.server.on(Events.Memory.UPDATE, (event) => this.handleMemoryUpdateRequest(event));
103
+ EventBus.server.on(Events.Memory.DELETE, (event) => this.handleMemoryDeleteRequest(event));
104
+ }
105
+ validateMemoryRequestIdentity(event) {
106
+ this.validator.assertIsNonEmptyString(event.agentId, 'Memory request agentId is required');
107
+ this.validator.assertIsNonEmptyString(event.channelId, 'Memory request channelId is required');
108
+ this.validator.assertIsNonEmptyString(event.data.operationId, 'Memory operationId is required');
109
+ this.validator.validateMemoryScope(event.data.scope);
110
+ }
111
+ requireScalarMemoryId(id, scope) {
112
+ if (Array.isArray(id)) {
113
+ throw new Error(`${scope} memory requires a scalar ID`);
114
+ }
115
+ this.validator.assertIsNonEmptyString(id, `${scope} memory ID is required`);
116
+ return id;
117
+ }
118
+ /**
119
+ * Agent-scoped requests address the requesting agent's own memory. The
120
+ * socket gateway checks this too; the service checks it again so no other
121
+ * caller of the event bridge can read or change another agent's memory by
122
+ * naming it.
123
+ */
124
+ requireOwnAgentMemoryId(id, requestingAgentId) {
125
+ const agentId = this.requireScalarMemoryId(id, MemoryScope.AGENT);
126
+ if (agentId !== requestingAgentId) {
127
+ throw new Error('Agent memory requests are limited to the requesting agent');
128
+ }
129
+ return agentId;
130
+ }
131
+ /**
132
+ * Channel-scoped requests address the request's own channel: either the
133
+ * whole channel document (id equal to the request channel) or one of its
134
+ * keyed sub-resources (`channel:...:<channelId>`, validated where the key
135
+ * is resolved).
136
+ */
137
+ requireOwnChannelMemoryId(id, requestChannelId) {
138
+ const channelMemoryId = this.requireScalarMemoryId(id, MemoryScope.CHANNEL);
139
+ if (!channelMemoryId.startsWith('channel:') && channelMemoryId !== requestChannelId) {
140
+ throw new Error('Channel memory requests are limited to the request channel');
141
+ }
142
+ return channelMemoryId;
143
+ }
144
+ /**
145
+ * Relationship-scoped requests must come from one of the two agents in
146
+ * the relationship, and the channel component must match the request.
147
+ */
148
+ requireRelationshipMemoryId(id, channelId, requestingAgentId) {
149
+ if (!Array.isArray(id) || (id.length !== 2 && id.length !== 3)) {
150
+ throw new Error('Relationship memory requires two agent IDs and an optional channel ID');
151
+ }
152
+ id.forEach((part, index) => {
153
+ this.validator.assertIsNonEmptyString(part, `Relationship memory ID part ${index} is required`);
154
+ });
155
+ if (id.length === 3 && id[2] !== channelId) {
156
+ throw new Error('Relationship memory channel must match the request channel');
157
+ }
158
+ if (id[0] !== requestingAgentId && id[1] !== requestingAgentId) {
159
+ throw new Error('Relationship memory requests are limited to a participant of the relationship');
160
+ }
161
+ return [id[0], id[1], channelId];
162
+ }
163
+ ownsPathOrDescendant(value, reservedPath) {
164
+ if (!value || typeof value !== 'object') {
165
+ return false;
166
+ }
167
+ return Object.keys(value).some(key => key === reservedPath || key.startsWith(`${reservedPath}.`));
168
+ }
169
+ getChannelMemoryKey(key, expectedChannelId) {
170
+ const prefixes = [
171
+ { prefix: 'channel:context:history:', kind: 'history' },
172
+ { prefix: 'channel:messages:', kind: 'messages' },
173
+ { prefix: 'channel:context:', kind: 'context' }
174
+ ];
175
+ const matched = prefixes.find(({ prefix }) => key.startsWith(prefix));
176
+ if (!matched) {
177
+ throw new Error(`Unsupported channel memory key: ${key}`);
178
+ }
179
+ const channelId = key.slice(matched.prefix.length);
180
+ this.validator.assertIsNonEmptyString(channelId, 'Channel memory key channelId is required');
181
+ if (expectedChannelId && channelId !== expectedChannelId) {
182
+ throw new Error('Channel memory key must match the request channel');
183
+ }
184
+ return { channelId, kind: matched.kind };
185
+ }
186
+ async getKeyedChannelMemory(key, requestChannelId) {
187
+ const { channelId, kind } = this.getChannelMemoryKey(key, requestChannelId);
188
+ if (!this.persistenceService && this.generalData.has(key)) {
189
+ return this.generalData.get(key);
190
+ }
191
+ const channelMemory = this.persistenceService
192
+ ? await firstValueFrom(this.persistenceService.getChannelMemory(channelId))
193
+ : await firstValueFrom(this.getChannelMemory(channelId));
194
+ const value = kind === 'messages'
195
+ ? channelMemory.conversationHistory
196
+ : kind === 'context'
197
+ ? channelMemory.sharedState?.context
198
+ : channelMemory.customData?.contextHistory;
199
+ const cachedMemory = this.channelMemory.get(channelId);
200
+ this.channelMemory.set(channelId, {
201
+ ...channelMemory,
202
+ sharedCognitiveInsights: cachedMemory?.sharedCognitiveInsights ?? {
203
+ systemSummaries: [],
204
+ topicExtractions: [],
205
+ collaborativeReflections: []
108
206
  }
109
- else if (data.scope === MemoryScope.RELATIONSHIP && data.memory) {
110
- this.relationshipMemory.set(data.id, data.memory);
111
- // ;
207
+ });
208
+ if (value !== undefined) {
209
+ this.generalData.set(key, value);
210
+ }
211
+ else {
212
+ this.generalData.delete(key);
213
+ }
214
+ return value ?? null;
215
+ }
216
+ serializeChannelMutation(channelId, operation) {
217
+ const previousTail = this.channelMutationTails.get(channelId) ?? Promise.resolve();
218
+ const result = previousTail.then(operation);
219
+ const nextTail = result.then(() => undefined, () => undefined);
220
+ this.channelMutationTails.set(channelId, nextTail);
221
+ return result.finally(() => {
222
+ if (this.channelMutationTails.get(channelId) === nextTail) {
223
+ this.channelMutationTails.delete(channelId);
112
224
  }
113
225
  });
114
- // Set up EventBus bridge for Memory.UPDATE events
115
- // This bridges EventBus memory events to internal memory operations
116
- // Required for ChannelContextMemoryOperations to save data
117
- EventBus.server.on(Events.Memory.UPDATE, (event) => {
118
- try {
119
- // Extract memory operation data from the event (handle EventBus forwarding nesting)
120
- const memoryEventData = event.data.scope ? event.data : event.data.data;
121
- // Validate required fields
122
- this.validator.assertIsString(memoryEventData.scope, 'Memory scope is required');
123
- this.validator.assertIsString(memoryEventData.operationId, 'Operation ID is required');
124
- // Determine the action based on memory scope and handle UPDATE operations
125
- if (memoryEventData.scope === MemoryScope.CHANNEL) {
126
- // For channel data, store by key (e.g., "channel:context:${channelId}")
127
- const memoryKey = memoryEventData.id; // Use the id as the key
128
- const memoryData = memoryEventData.data;
129
- if (memoryKey && memoryData) {
130
- // Store the data in generalData map (in-memory cache)
131
- this.generalData.set(memoryKey, memoryData);
132
- // Also persist to MongoDB for durability (if persistence service available)
133
- // Extract actual context data - it's wrapped in another object with the key
134
- const actualContextData = memoryData[memoryKey];
135
- if (actualContextData && actualContextData.channelId && this.persistenceService) {
136
- try {
137
- // Convert to IChannelMemory format for persistence
138
- const channelMemoryUpdate = {
139
- id: `${actualContextData.channelId}-context`,
140
- channelId: actualContextData.channelId,
141
- createdAt: new Date(actualContextData.createdAt || Date.now()),
142
- updatedAt: new Date(),
143
- persistenceLevel: 'persistent',
144
- sharedState: { context: actualContextData },
145
- notes: { channelContext: 'Auto-saved from ChannelContextService' },
146
- conversationHistory: [],
147
- customData: { contextMetadata: memoryEventData.metadata || {} }
148
- };
149
- // Persist to MongoDB (fire and forget for performance)
150
- this.persistenceService.saveChannelMemory(channelMemoryUpdate)
151
- .subscribe({
152
- next: () => this.logger.info(`Channel context persisted to MongoDB for ${actualContextData.channelId}`),
153
- error: (err) => this.logger.warn(`Failed to persist channel context to MongoDB: ${err.message}`)
154
- });
155
- }
156
- catch (persistError) {
157
- this.logger.warn(`Error persisting channel context: ${persistError}`);
158
- }
159
- }
160
- // Create success result payload
161
- const updateResultData = {
162
- operationId: memoryEventData.operationId,
163
- scope: MemoryScope.CHANNEL,
164
- id: memoryKey,
165
- memory: memoryData
166
- };
167
- const systemAgentId = 'SYSTEM_AGENT';
168
- const channelId = event.channelId || 'NO_CHANNEL';
169
- const payload = createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, systemAgentId, channelId, updateResultData);
170
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, payload);
171
- }
172
- else {
173
- this.logger.warn(`Invalid UPDATE data - missing key or data: key=${memoryKey}, data=${!!memoryData}`);
174
- }
175
- }
226
+ }
227
+ serializeAgentMutation(agentId, operation) {
228
+ const previousTail = this.agentMutationTails.get(agentId) ?? Promise.resolve();
229
+ const result = previousTail.then(operation);
230
+ const nextTail = result.then(() => undefined, () => undefined);
231
+ this.agentMutationTails.set(agentId, nextTail);
232
+ return result.finally(() => {
233
+ if (this.agentMutationTails.get(agentId) === nextTail) {
234
+ this.agentMutationTails.delete(agentId);
176
235
  }
177
- catch (error) {
178
- this.logger.error(`Error handling Memory.UPDATE event: ${error instanceof Error ? error.message : String(error)}`);
236
+ });
237
+ }
238
+ serializeRelationshipMutation(agentId1, agentId2, channelId, operation) {
239
+ const relationshipKey = this.getRelationshipKey(agentId1, agentId2, channelId);
240
+ const previousTail = this.relationshipMutationTails.get(relationshipKey) ?? Promise.resolve();
241
+ const result = previousTail.then(operation);
242
+ const nextTail = result.then(() => undefined, () => undefined);
243
+ this.relationshipMutationTails.set(relationshipKey, nextTail);
244
+ return result.finally(() => {
245
+ if (this.relationshipMutationTails.get(relationshipKey) === nextTail) {
246
+ this.relationshipMutationTails.delete(relationshipKey);
179
247
  }
180
248
  });
181
- // Set up EventBus bridge for Memory.GET events
182
- // This bridges EventBus memory events to internal memory operations
183
- // Required for ChannelContextMessageOperations to work with the memory system
184
- EventBus.server.on(Events.Memory.GET, (event) => {
185
- try {
186
- // Extract memory operation data from the event (handle EventBus forwarding nesting)
187
- const memoryEventData = event.data.scope ? event.data : event.data.data;
188
- // Validate required fields
189
- this.validator.assertIsString(memoryEventData.scope, 'Memory scope is required');
190
- this.validator.assertIsString(memoryEventData.operationId, 'Operation ID is required');
191
- let memoryObservable = null;
192
- // Determine the action based on memory scope and handle GET operations
193
- switch (memoryEventData.scope) {
194
- case MemoryScope.CHANNEL:
195
- // Determine the memory key to look up - prioritize key field over id field
196
- const memoryKey = memoryEventData.key || (Array.isArray(memoryEventData.id) ? memoryEventData.id[0] : memoryEventData.id);
197
- if (memoryKey) {
198
- // For channel data, look up by key (e.g., "channel:messages:${channelId}" or "channel:context:${channelId}")
199
- const channelMemory = this.generalData.get(memoryKey);
200
- // Create result payload
201
- const getResultData = {
202
- operationId: memoryEventData.operationId,
203
- scope: MemoryScope.CHANNEL,
204
- id: memoryKey, // Use the memory key as the id for proper matching
205
- memory: channelMemory || null
206
- };
207
- const systemAgentId = 'SYSTEM_AGENT';
208
- const noChannelId = 'NO_CHANNEL';
209
- const payload = createMemoryGetResultEventPayload(Events.Memory.GET_RESULT, systemAgentId, noChannelId, getResultData);
210
- //// this.logger.info(`[CRITICAL] MemoryService emitting GET_RESULT:`, Object.keys(payload));
211
- EventBus.server.emit(Events.Memory.GET_RESULT, payload);
212
- }
213
- else {
214
- this.logger.warn(`[DEBUG] No memory key found in GET event data`);
215
- }
216
- break;
217
- case MemoryScope.AGENT:
218
- if (typeof memoryEventData.id === 'string') {
219
- // ;
220
- memoryObservable = this.getAgentMemory(memoryEventData.id);
221
- // Subscribe to the observable and emit result
222
- memoryObservable.subscribe({
223
- next: (agentMemory) => {
224
- // Create result payload
225
- const getResultData = {
226
- operationId: memoryEventData.operationId,
227
- scope: MemoryScope.AGENT,
228
- id: memoryEventData.id,
229
- memory: agentMemory || null
230
- };
231
- const payload = createMemoryGetResultEventPayload(Events.Memory.GET_RESULT, event.agentId, event.channelId, getResultData);
232
- EventBus.server.emit(Events.Memory.GET_RESULT, payload);
233
- },
234
- error: (error) => {
235
- this.logger.error(`Error getting agent memory: ${error}`);
236
- // Create error result payload
237
- const getResultData = {
238
- operationId: memoryEventData.operationId,
239
- scope: MemoryScope.AGENT,
240
- id: memoryEventData.id,
241
- memory: null
242
- };
243
- const payload = createMemoryGetResultEventPayload(Events.Memory.GET_RESULT, event.agentId, event.channelId, getResultData);
244
- EventBus.server.emit(Events.Memory.GET_RESULT, payload);
245
- }
246
- });
247
- }
248
- break;
249
- case MemoryScope.RELATIONSHIP:
250
- // Handle relationship memory GET
251
- break;
252
- default:
253
- this.logger.warn(`Unsupported memory scope: ${memoryEventData.scope}`);
249
+ }
250
+ getAtomicMutation(kind, value, expectedContextUpdatedAt) {
251
+ switch (kind) {
252
+ case 'messages':
253
+ if (!Array.isArray(value) || value.length === 0) {
254
+ throw new Error('Keyed channel message updates require a non-empty array');
254
255
  }
256
+ return { kind: 'append_messages', messages: value };
257
+ case 'context':
258
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
259
+ throw new Error('Keyed channel context updates require an object');
260
+ }
261
+ return {
262
+ kind: 'replace_context',
263
+ context: value,
264
+ expectedUpdatedAt: expectedContextUpdatedAt
265
+ };
266
+ case 'history':
267
+ if (!Array.isArray(value) || value.length === 0) {
268
+ throw new Error('Keyed channel history updates require a non-empty array');
269
+ }
270
+ return { kind: 'append_context_history', entries: value, retainLast: 100 };
271
+ }
272
+ }
273
+ getDeleteMutation(kind) {
274
+ switch (kind) {
275
+ case 'messages':
276
+ return { kind: 'delete_messages' };
277
+ case 'context':
278
+ return { kind: 'delete_context' };
279
+ case 'history':
280
+ return { kind: 'delete_context_history' };
281
+ }
282
+ }
283
+ async mutateLocalChannelMemory(channelId, mutation) {
284
+ const deleting = mutation.kind.startsWith('delete_');
285
+ const existingMemory = this.channelMemory.get(channelId);
286
+ if (deleting && !existingMemory) {
287
+ return { found: false, memory: null, value: null };
288
+ }
289
+ const originalMemory = existingMemory ?? await firstValueFrom(this.getChannelMemory(channelId));
290
+ if (mutation.kind === 'replace_context') {
291
+ const existingContext = originalMemory.sharedState?.context;
292
+ const actualUpdatedAt = existingContext?.updatedAt;
293
+ const versionMatches = mutation.expectedUpdatedAt === undefined
294
+ ? existingContext === undefined
295
+ : actualUpdatedAt === mutation.expectedUpdatedAt;
296
+ if (!versionMatches) {
297
+ return { found: false, memory: originalMemory, value: existingContext ?? null };
298
+ }
299
+ }
300
+ const targetExists = mutation.kind === 'delete_messages'
301
+ ? originalMemory.conversationHistory !== undefined
302
+ : mutation.kind === 'delete_context'
303
+ ? Object.prototype.hasOwnProperty.call(originalMemory.sharedState ?? {}, 'context')
304
+ : mutation.kind === 'delete_context_history'
305
+ ? Object.prototype.hasOwnProperty.call(originalMemory.customData ?? {}, 'contextHistory')
306
+ : true;
307
+ if (!targetExists) {
308
+ return { found: false, memory: originalMemory, value: null };
309
+ }
310
+ let updatedMemory;
311
+ let value;
312
+ switch (mutation.kind) {
313
+ case 'append_messages':
314
+ value = [...(originalMemory.conversationHistory ?? []), ...mutation.messages];
315
+ updatedMemory = { ...originalMemory, conversationHistory: value };
316
+ break;
317
+ case 'replace_context':
318
+ value = mutation.context;
319
+ updatedMemory = {
320
+ ...originalMemory,
321
+ sharedState: { ...originalMemory.sharedState, context: value }
322
+ };
323
+ break;
324
+ case 'append_context_history':
325
+ value = [
326
+ ...(originalMemory.customData?.contextHistory ?? []),
327
+ ...mutation.entries
328
+ ].slice(-mutation.retainLast);
329
+ updatedMemory = {
330
+ ...originalMemory,
331
+ customData: { ...originalMemory.customData, contextHistory: value }
332
+ };
333
+ break;
334
+ case 'delete_messages':
335
+ value = [];
336
+ updatedMemory = { ...originalMemory, conversationHistory: [] };
337
+ break;
338
+ case 'delete_context': {
339
+ const sharedState = { ...originalMemory.sharedState };
340
+ delete sharedState.context;
341
+ value = null;
342
+ updatedMemory = { ...originalMemory, sharedState };
343
+ break;
255
344
  }
256
- catch (error) {
257
- this.logger.error('[ERROR] Error processing EventBus Memory.GET:', error);
258
- // Log error details for debugging without creating fake event payloads
259
- const operationId = event.data?.operationId || '[NO_OPERATION_ID]';
260
- const memoryId = event.data?.id || event.data?.key || '[NO_MEMORY_ID]';
261
- this.logger.error(`Memory GET operation failed - OperationId: ${operationId}, MemoryId: ${memoryId}, Error: ${error.message}`);
262
- // Cannot emit GET_RESULT event without valid agentId and channelId from original request
263
- // Original event should have contained these required identifiers
264
- 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.');
345
+ case 'delete_context_history': {
346
+ const customData = { ...originalMemory.customData };
347
+ delete customData.contextHistory;
348
+ value = null;
349
+ updatedMemory = { ...originalMemory, customData };
350
+ break;
265
351
  }
352
+ }
353
+ updatedMemory.updatedAt = new Date();
354
+ this.channelMemory.set(channelId, updatedMemory);
355
+ return { found: true, memory: updatedMemory, value };
356
+ }
357
+ async executeKeyedChannelMutation(key, requestChannelId, mutation) {
358
+ const { channelId } = this.getChannelMemoryKey(key, requestChannelId);
359
+ return this.serializeChannelMutation(channelId, async () => {
360
+ const result = this.persistenceService
361
+ ? await firstValueFrom(this.persistenceService.mutateChannelMemory(channelId, mutation))
362
+ : await this.mutateLocalChannelMemory(channelId, mutation);
363
+ if (result.memory) {
364
+ const cachedMemory = this.channelMemory.get(channelId);
365
+ this.channelMemory.set(channelId, {
366
+ ...result.memory,
367
+ sharedCognitiveInsights: cachedMemory?.sharedCognitiveInsights ?? {
368
+ systemSummaries: [],
369
+ topicExtractions: [],
370
+ collaborativeReflections: []
371
+ }
372
+ });
373
+ }
374
+ if (result.found) {
375
+ this.generalData.set(key, result.value);
376
+ }
377
+ else {
378
+ this.generalData.delete(key);
379
+ }
380
+ return result;
266
381
  });
267
- // Set up EventBus bridge for Memory.UPDATE events
268
- EventBus.server.on(Events.Memory.UPDATE, (event) => {
269
- try {
270
- // Extract memory operation data from the event (handle EventBus forwarding nesting)
271
- const memoryEventData = event.data.scope ? event.data : event.data.data;
272
- // Validate required fields
273
- this.validator.assertIsString(memoryEventData.scope, 'Memory scope is required');
274
- this.validator.assertIsString(memoryEventData.operationId, 'Operation ID is required');
275
- // Handle UPDATE operations
276
- switch (memoryEventData.scope) {
277
- case MemoryScope.CHANNEL:
278
- // For UPDATE operations, the id field contains the memory key
279
- const updateMemoryKey = Array.isArray(memoryEventData.id) ? memoryEventData.id[0] : memoryEventData.id;
280
- // Handle the actual data structure from ChannelContextMessageOperations and ChannelContextMemoryOperations
281
- // Data comes in format:
282
- // - { "channel:messages:${channelId}": [...messages] } for messages
283
- // - { "channel:context:${channelId}": {...context} } for context
284
- if (memoryEventData.data && typeof memoryEventData.data === 'object') {
285
- // Check if the data is already properly keyed or needs to be keyed
286
- const dataKeys = Object.keys(memoryEventData.data);
287
- if (updateMemoryKey.startsWith('channel:')) {
288
- // Direct storage: id field is the memory key, data field contains the actual data
289
- // ;
290
- // If data has nested structure with the same key, extract the nested data
291
- const actualData = memoryEventData.data[updateMemoryKey] || memoryEventData.data;
292
- // Check if data has actually changed before updating
293
- const existingData = this.generalData.get(updateMemoryKey);
294
- const dataHasChanged = !this.isDataEqual(existingData, actualData);
295
- if (!dataHasChanged) {
296
- // ;
297
- return; // Skip update and event emission
298
- }
299
- // ;
300
- this.generalData.set(updateMemoryKey, actualData);
301
- // Create success result payload
302
- const updateResult = {
303
- operationId: memoryEventData.operationId,
304
- scope: MemoryScope.CHANNEL,
305
- id: updateMemoryKey, // Use the memory key as the id for proper matching
306
- memory: actualData
307
- };
308
- const systemAgentId = 'SYSTEM_AGENT';
309
- const noChannelId = 'NO_CHANNEL';
310
- const payload = createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, systemAgentId, noChannelId, updateResult);
311
- // ;
312
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, payload);
313
- }
314
- else {
315
- // Legacy format: Find any channel-related key and data in the data object
316
- const channelKey = dataKeys.find(key => key.startsWith('channel:messages:') || key.startsWith('channel:context:'));
317
- if (channelKey && memoryEventData.data[channelKey]) {
318
- // ;
319
- const newData = memoryEventData.data[channelKey];
320
- // Check if data has actually changed before updating
321
- const existingData = this.generalData.get(channelKey);
322
- const dataHasChanged = !this.isDataEqual(existingData, newData);
323
- if (!dataHasChanged) {
324
- // ;
325
- return; // Skip update and event emission
326
- }
327
- // Store the data by the key (messages array or context object)
328
- // ;
329
- this.generalData.set(channelKey, newData);
330
- // Create success result payload
331
- const updateResult = {
332
- operationId: memoryEventData.operationId,
333
- scope: MemoryScope.CHANNEL,
334
- id: channelKey, // Use the memory key as the id for proper matching
335
- memory: newData
336
- };
337
- const systemAgentId = 'SYSTEM_AGENT';
338
- const noChannelId = 'NO_CHANNEL';
339
- const payload = createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, systemAgentId, noChannelId, updateResult);
340
- // ;
341
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, payload);
342
- }
343
- else {
344
- this.logger.warn(`No recognized channel key found in data keys: ${dataKeys.join(', ')}`);
345
- }
346
- }
347
- }
348
- break;
349
- case MemoryScope.AGENT:
350
- // Handle agent memory UPDATE
351
- if (typeof memoryEventData.id === 'string' && memoryEventData.data) {
352
- // CRITICAL: Must subscribe to Observable to trigger execution!
353
- // The request context routes the UPDATE_RESULT back to the
354
- // requesting agent with its own operationId without it the
355
- // SDK's pending save can never observe its result.
356
- this.updateAgentMemory(memoryEventData.id, memoryEventData.data, {
357
- operationId: memoryEventData.operationId,
358
- requesterAgentId: event.agentId,
359
- requesterChannelId: event.channelId
360
- }).subscribe({
361
- next: () => null,
362
- error: (err) => this.logger.error(`Agent memory update failed for ${memoryEventData.id}: ${err}`)
363
- });
382
+ }
383
+ async updateKeyedChannelMemory(key, value, requestChannelId, expectedContextUpdatedAt) {
384
+ const { kind } = this.getChannelMemoryKey(key, requestChannelId);
385
+ const result = await this.executeKeyedChannelMutation(key, requestChannelId, this.getAtomicMutation(kind, value, expectedContextUpdatedAt));
386
+ if (!result.found) {
387
+ throw new Error(`Channel context changed concurrently while updating ${key}`);
388
+ }
389
+ return result.value;
390
+ }
391
+ async deleteKeyedChannelMemory(key) {
392
+ const { kind } = this.getChannelMemoryKey(key);
393
+ const result = await this.executeKeyedChannelMutation(key, undefined, this.getDeleteMutation(kind));
394
+ if (result.found) {
395
+ this.generalData.delete(key);
396
+ }
397
+ return result.found;
398
+ }
399
+ async handleMemoryGetRequest(event) {
400
+ let responseId = event.data.id;
401
+ try {
402
+ this.validateMemoryRequestIdentity(event);
403
+ let memory;
404
+ switch (event.data.scope) {
405
+ case MemoryScope.AGENT: {
406
+ const agentId = this.requireOwnAgentMemoryId(event.data.id, event.agentId);
407
+ responseId = agentId;
408
+ memory = await firstValueFrom(this.getAgentMemory(agentId));
409
+ break;
410
+ }
411
+ case MemoryScope.CHANNEL: {
412
+ const channelMemoryId = this.requireOwnChannelMemoryId(event.data.key ?? event.data.id, event.channelId);
413
+ responseId = channelMemoryId;
414
+ memory = channelMemoryId.startsWith('channel:')
415
+ ? await this.getKeyedChannelMemory(channelMemoryId, event.channelId)
416
+ : await firstValueFrom(this.getChannelMemory(channelMemoryId));
417
+ break;
418
+ }
419
+ case MemoryScope.RELATIONSHIP: {
420
+ const [agentId1, agentId2, channelId] = this.requireRelationshipMemoryId(event.data.id, event.channelId, event.agentId);
421
+ responseId = [agentId1, agentId2, channelId];
422
+ memory = await firstValueFrom(this.getRelationshipMemory(agentId1, agentId2, channelId));
423
+ break;
424
+ }
425
+ }
426
+ EventBus.server.emit(Events.Memory.GET_RESULT, createMemoryGetResultEventPayload(Events.Memory.GET_RESULT, event.agentId, event.channelId, {
427
+ operationId: event.data.operationId,
428
+ scope: event.data.scope,
429
+ id: responseId,
430
+ memory
431
+ }));
432
+ }
433
+ catch (error) {
434
+ this.emitMemoryGetError(event, responseId, error);
435
+ }
436
+ }
437
+ async handleMemoryUpdateRequest(event) {
438
+ let responseId = event.data.id;
439
+ try {
440
+ this.validateMemoryRequestIdentity(event);
441
+ this.validator.assertIsObject(event.data.data, 'Memory update data is required');
442
+ let memory;
443
+ switch (event.data.scope) {
444
+ case MemoryScope.AGENT: {
445
+ const agentId = this.requireOwnAgentMemoryId(event.data.id, event.agentId);
446
+ responseId = agentId;
447
+ memory = await firstValueFrom(this.updateAgentMemory(agentId, event.data.data));
448
+ break;
449
+ }
450
+ case MemoryScope.CHANNEL: {
451
+ const channelMemoryId = this.requireOwnChannelMemoryId(event.data.id, event.channelId);
452
+ responseId = channelMemoryId;
453
+ const embeddedMemoryKeys = Object.keys(event.data.data)
454
+ .filter(key => key.startsWith('channel:'));
455
+ const keyedMemoryId = channelMemoryId.startsWith('channel:')
456
+ ? channelMemoryId
457
+ : embeddedMemoryKeys.length === 1
458
+ ? embeddedMemoryKeys[0]
459
+ : undefined;
460
+ if (keyedMemoryId) {
461
+ responseId = keyedMemoryId;
462
+ const nestedValue = event.data.data[keyedMemoryId];
463
+ const value = nestedValue === undefined ? event.data.data : nestedValue;
464
+ const expectedContextUpdatedAt = event.data.metadata?.expectedContextUpdatedAt;
465
+ if (expectedContextUpdatedAt !== undefined &&
466
+ (typeof expectedContextUpdatedAt !== 'number' ||
467
+ !Number.isFinite(expectedContextUpdatedAt) ||
468
+ expectedContextUpdatedAt < 0)) {
469
+ throw new Error('Memory update expectedContextUpdatedAt must be a non-negative number');
364
470
  }
365
- break;
366
- case MemoryScope.RELATIONSHIP:
367
- // Handle relationship memory UPDATE
368
- break;
369
- default:
370
- this.logger.warn(`Unsupported memory scope: ${memoryEventData.scope}`);
471
+ memory = await this.updateKeyedChannelMemory(keyedMemoryId, value, event.channelId, expectedContextUpdatedAt);
472
+ }
473
+ else {
474
+ memory = await firstValueFrom(this.updateChannelMemory(channelMemoryId, event.data.data));
475
+ }
476
+ break;
477
+ }
478
+ case MemoryScope.RELATIONSHIP: {
479
+ const [agentId1, agentId2, channelId] = this.requireRelationshipMemoryId(event.data.id, event.channelId, event.agentId);
480
+ responseId = [agentId1, agentId2, channelId];
481
+ memory = await firstValueFrom(this.updateRelationshipMemory(agentId1, agentId2, channelId, event.data.data));
482
+ break;
371
483
  }
372
484
  }
373
- catch (error) {
374
- this.logger.error('[ERROR] Error processing EventBus Memory.UPDATE:', error);
375
- // Log error details for debugging without creating fake event payloads
376
- const operationId = event.data?.operationId || '[NO_OPERATION_ID]';
377
- const memoryId = event.data?.id || '[NO_MEMORY_ID]';
378
- this.logger.error(`Memory UPDATE operation failed - OperationId: ${operationId}, MemoryId: ${memoryId}, Error: ${error.message}`);
379
- // Cannot emit UPDATE_RESULT event without valid agentId and channelId from original request
380
- // Original event should have contained these required identifiers
381
- 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.');
485
+ EventBus.server.emit(Events.Memory.UPDATE_RESULT, createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, event.agentId, event.channelId, {
486
+ operationId: event.data.operationId,
487
+ scope: event.data.scope,
488
+ id: responseId,
489
+ memory
490
+ }));
491
+ }
492
+ catch (error) {
493
+ this.emitMemoryUpdateError(event, responseId, error);
494
+ }
495
+ }
496
+ async handleMemoryDeleteRequest(event) {
497
+ let responseId = event.data.id;
498
+ try {
499
+ this.validateMemoryRequestIdentity(event);
500
+ if (event.data.scope === MemoryScope.RELATIONSHIP) {
501
+ responseId = this.requireRelationshipMemoryId(event.data.id, event.channelId, event.agentId);
382
502
  }
383
- });
503
+ else if (event.data.scope === MemoryScope.AGENT) {
504
+ responseId = this.requireOwnAgentMemoryId(event.data.id, event.agentId);
505
+ }
506
+ else {
507
+ responseId = this.requireOwnChannelMemoryId(event.data.id, event.channelId);
508
+ if (responseId.startsWith('channel:')) {
509
+ this.getChannelMemoryKey(responseId, event.channelId);
510
+ }
511
+ }
512
+ const success = await firstValueFrom(this.deleteMemory(event.data.scope, responseId));
513
+ EventBus.server.emit(Events.Memory.DELETE_RESULT, createMemoryDeleteResultEventPayload(Events.Memory.DELETE_RESULT, event.agentId, event.channelId, {
514
+ operationId: event.data.operationId,
515
+ scope: event.data.scope,
516
+ id: responseId,
517
+ success
518
+ }));
519
+ }
520
+ catch (error) {
521
+ this.emitMemoryDeleteError(event, responseId, error);
522
+ }
523
+ }
524
+ emitMemoryGetError(event, id, error) {
525
+ const message = error instanceof Error ? error.message : String(error);
526
+ this.logger.error(`Memory GET failed: ${message}`);
527
+ EventBus.server.emit(Events.Memory.GET_RESULT, createMemoryGetResultEventPayload(Events.Memory.GET_RESULT, event.agentId, event.channelId, {
528
+ operationId: event.data.operationId,
529
+ scope: event.data.scope,
530
+ id,
531
+ memory: null,
532
+ error: message
533
+ }));
534
+ }
535
+ emitMemoryUpdateError(event, id, error) {
536
+ const message = error instanceof Error ? error.message : String(error);
537
+ this.logger.error(`Memory UPDATE failed: ${message}`);
538
+ EventBus.server.emit(Events.Memory.UPDATE_RESULT, createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, event.agentId, event.channelId, {
539
+ operationId: event.data.operationId,
540
+ scope: event.data.scope,
541
+ id,
542
+ memory: null,
543
+ error: message
544
+ }));
545
+ }
546
+ emitMemoryDeleteError(event, id, error) {
547
+ const message = error instanceof Error ? error.message : String(error);
548
+ this.logger.error(`Memory DELETE failed: ${message}`);
549
+ EventBus.server.emit(Events.Memory.DELETE_RESULT, createMemoryDeleteResultEventPayload(Events.Memory.DELETE_RESULT, event.agentId, event.channelId, {
550
+ operationId: event.data.operationId,
551
+ scope: event.data.scope,
552
+ id,
553
+ success: false,
554
+ error: message
555
+ }));
384
556
  }
385
557
  /**
386
558
  * Get the singleton instance
@@ -417,9 +589,10 @@ export class MemoryService {
417
589
  persistence.getAgentMemory(agentId).subscribe({
418
590
  next: (loadedMemory) => {
419
591
  // Enhance the loaded memory with cognitive memory structure
592
+ const loadedCognitiveMemory = loadedMemory.cognitiveMemory;
420
593
  const enhancedMemory = {
421
594
  ...loadedMemory,
422
- cognitiveMemory: loadedMemory.cognitiveMemory || {
595
+ cognitiveMemory: loadedCognitiveMemory ?? {
423
596
  observationIds: [],
424
597
  reasoningIds: [],
425
598
  planIds: [],
@@ -432,11 +605,9 @@ export class MemoryService {
432
605
  observer.complete();
433
606
  },
434
607
  error: (error) => {
435
- this.logger.warn(`Failed to load agent memory from MongoDB for ${agentId}: ${error.message}`);
436
- // Fall back to creating new memory
437
- const newMemory = this.createNewAgentMemory(agentId);
438
- observer.next(newMemory);
439
- observer.complete();
608
+ const message = error instanceof Error ? error.message : String(error);
609
+ this.logger.error(`Failed to load agent memory from MongoDB for ${agentId}: ${message}`);
610
+ observer.error(error);
440
611
  }
441
612
  });
442
613
  });
@@ -468,126 +639,81 @@ export class MemoryService {
468
639
  }
469
640
  };
470
641
  this.agentMemory.set(agentId, newMemory);
471
- const operationId_agent_get_new = uuidv4();
472
- const systemAgentId_agent_get_new = 'SYSTEM_AGENT';
473
- const noChannelId_agent_get_new = 'NO_CHANNEL';
474
- const updateResultData_agent_get_new = {
475
- operationId: operationId_agent_get_new,
476
- scope: MemoryScope.AGENT,
477
- id: agentId,
478
- memory: newMemory
479
- };
480
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, systemAgentId_agent_get_new, noChannelId_agent_get_new, updateResultData_agent_get_new));
481
642
  return newMemory;
482
643
  }
483
644
  /**
484
645
  * Update agent memory
485
646
  *
486
- * When the update was requested over the wire (SDK → Events.Memory.UPDATE),
487
- * requestContext carries the requester's operationId and identity. The
488
- * UPDATE_RESULT emitted here must echo that operationId and be addressed to
489
- * the requesting agent: the SDK matches results by operationId, and event
490
- * forwarding routes them by payload.agentId. Before this parameter existed,
491
- * agent-scope results were emitted with a freshly generated operationId under
492
- * SYSTEM_AGENT — no SDK save round-trip could ever observe its own result, so
493
- * every awaited save hung forever and every fire-and-forget save leaked its
494
- * result listener.
495
- *
496
647
  * @param pAgentId Agent ID
497
648
  * @param updates Memory updates
498
- * @param requestContext Requester identity for result routing (wire requests only)
499
649
  * @returns Observable of updated agent memory
500
650
  */
501
- updateAgentMemory(pAgentId, updates, requestContext) {
651
+ updateAgentMemory(pAgentId, updates) {
502
652
  this.validator.assertIsNonEmptyString(pAgentId, 'Agent ID must be a non-empty string');
503
653
  this.validator.assertIsObject(updates, 'Updates must be an object');
504
- // Get existing memory or create new one
505
654
  return new Observable(observer => {
506
- this.getAgentMemory(pAgentId).subscribe(originalAgentMemory => {
507
- // Apply updates
508
- const updatedMemory = {
509
- ...originalAgentMemory,
510
- ...updates,
511
- updatedAt: new Date(),
512
- // Ensure these fields can't be overridden
513
- id: originalAgentMemory.id,
514
- agentId: originalAgentMemory.agentId,
515
- createdAt: originalAgentMemory.createdAt
516
- };
517
- // Deep merge for nested objects
518
- if (updates.notes) {
519
- updatedMemory.notes = { ...originalAgentMemory.notes, ...updates.notes };
520
- }
521
- if (updates.customData) {
522
- updatedMemory.customData = { ...originalAgentMemory.customData, ...updates.customData };
523
- }
524
- if (updates.cognitiveMemory) {
525
- updatedMemory.cognitiveMemory = {
526
- ...originalAgentMemory.cognitiveMemory,
527
- ...updates.cognitiveMemory
528
- };
529
- }
530
- // Replace conversation history if provided (SDK sends full array, not incremental)
531
- if (updates.conversationHistory !== undefined) {
532
- updatedMemory.conversationHistory = updates.conversationHistory;
533
- }
534
- // Store updated memory in cache
535
- this.agentMemory.set(pAgentId, updatedMemory);
536
- // Persist to MongoDB if persistence service is available (async, non-blocking)
537
- if (this.persistenceService) {
538
- this.persistenceService.saveAgentMemory(updatedMemory)
539
- .subscribe({
540
- next: () => null,
541
- error: (err) => this.logger.warn(`Failed to persist agent memory to MongoDB for ${pAgentId}: ${err.message}`)
655
+ let cancelled = false;
656
+ void (async () => {
657
+ try {
658
+ const enhancedStoredMemory = await this.serializeAgentMutation(pAgentId, async () => {
659
+ const originalAgentMemory = await firstValueFrom(this.getAgentMemory(pAgentId));
660
+ const updatedMemory = {
661
+ ...originalAgentMemory,
662
+ ...updates,
663
+ updatedAt: new Date(),
664
+ id: originalAgentMemory.id,
665
+ agentId: originalAgentMemory.agentId,
666
+ createdAt: originalAgentMemory.createdAt,
667
+ notes: updates.notes
668
+ ? { ...originalAgentMemory.notes, ...updates.notes }
669
+ : originalAgentMemory.notes,
670
+ customData: updates.customData
671
+ ? { ...originalAgentMemory.customData, ...updates.customData }
672
+ : originalAgentMemory.customData,
673
+ cognitiveMemory: updates.cognitiveMemory
674
+ ? {
675
+ ...originalAgentMemory.cognitiveMemory,
676
+ ...updates.cognitiveMemory
677
+ }
678
+ : originalAgentMemory.cognitiveMemory
679
+ };
680
+ const storedMemory = this.persistenceService
681
+ ? await firstValueFrom(this.persistenceService.saveAgentMemory(updatedMemory))
682
+ : updatedMemory;
683
+ const enhancedMemory = {
684
+ ...storedMemory,
685
+ cognitiveMemory: updatedMemory.cognitiveMemory
686
+ };
687
+ this.agentMemory.set(pAgentId, enhancedMemory);
688
+ return enhancedMemory;
542
689
  });
690
+ if (updates.conversationHistory && updates.conversationHistory.length > 0) {
691
+ const contentToExtract = updates.conversationHistory
692
+ .slice(-3)
693
+ .filter((message) => typeof message.content === 'string' && message.content.length > 0)
694
+ .map(message => message.content)
695
+ .join('\n\n');
696
+ if (contentToExtract.length > 0) {
697
+ const channelContext = `agent-memory-${pAgentId}`;
698
+ const memoryId = `agent-${pAgentId}-${Date.now()}`;
699
+ this.triggerEntityExtraction(channelContext, memoryId, contentToExtract)
700
+ .catch(error => this.logger.warn(`Entity extraction failed: ${error instanceof Error ? error.message : String(error)}`));
701
+ }
702
+ }
703
+ if (!cancelled) {
704
+ observer.next(enhancedStoredMemory);
705
+ observer.complete();
706
+ }
543
707
  }
544
- // Trigger entity extraction from conversation history if Knowledge Graph is enabled
545
- // This extracts entities and relationships for the Knowledge Graph
546
- if (updates.conversationHistory && updates.conversationHistory.length > 0) {
547
- const lastMessages = updates.conversationHistory.slice(-3);
548
- const contentToExtract = lastMessages
549
- .filter((msg) => typeof msg.content === 'string' && msg.content.length > 0)
550
- .map(msg => msg.content)
551
- .join('\n\n');
552
- if (contentToExtract.length > 0) {
553
- // Use agent ID as channel context for agent-level memories
554
- // Entities extracted from agent memory are scoped to a pseudo-channel
555
- const channelContext = `agent-memory-${pAgentId}`;
556
- const memoryId = `agent-${pAgentId}-${Date.now()}`;
557
- this.triggerEntityExtraction(channelContext, memoryId, contentToExtract)
558
- .catch(err => this.logger.warn(`Entity extraction failed: ${err.message}`));
708
+ catch (error) {
709
+ if (!cancelled) {
710
+ observer.error(error);
559
711
  }
560
712
  }
561
- // Emit update event through EventBus. Echo the requester's
562
- // operationId and address the result to the requesting agent so
563
- // the SDK's pending save resolves; internal callers (no
564
- // requestContext) keep the system-level identity.
565
- const operationId = requestContext?.operationId ?? uuidv4();
566
- const updateResultData = {
567
- operationId,
568
- scope: MemoryScope.AGENT,
569
- id: pAgentId,
570
- memory: updatedMemory
571
- };
572
- const resultAgentId = requestContext?.requesterAgentId ?? 'SYSTEM_AGENT';
573
- const resultChannelId = requestContext?.requesterChannelId ?? 'NO_CHANNEL';
574
- const payload = createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, resultAgentId, resultChannelId, updateResultData);
575
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, payload);
576
- observer.next(updatedMemory);
577
- observer.complete();
578
- }, error => {
579
- // Errors must reach the requester too — a save whose failure is
580
- // only logged server-side leaves the requesting SDK waiting forever.
581
- const updateResultData_agent_update_error = {
582
- operationId: requestContext?.operationId ?? uuidv4(),
583
- scope: MemoryScope.AGENT,
584
- id: pAgentId,
585
- memory: null,
586
- error: error.message
587
- };
588
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, requestContext?.requesterAgentId ?? 'SYSTEM_AGENT', requestContext?.requesterChannelId ?? 'NO_CHANNEL', updateResultData_agent_update_error));
589
- observer.error(error);
590
- });
713
+ })();
714
+ return () => {
715
+ cancelled = true;
716
+ };
591
717
  });
592
718
  }
593
719
  /**
@@ -884,15 +1010,35 @@ export class MemoryService {
884
1010
  * @returns Observable of channel memory
885
1011
  */
886
1012
  getChannelMemory(channelId) {
887
- // ;
888
1013
  this.validator.assertIsNonEmptyString(channelId, 'Channel ID must be a non-empty string');
889
- // Return from cache if available
890
- if (this.channelMemory.has(channelId)) {
891
- const memory = this.channelMemory.get(channelId);
892
- // ;
893
- return of(memory);
1014
+ const existingMemory = this.channelMemory.get(channelId);
1015
+ if (existingMemory) {
1016
+ return of(existingMemory);
1017
+ }
1018
+ const getPersistedChannelMemory = this.persistenceService?.getChannelMemory;
1019
+ if (this.persistenceService && !getPersistedChannelMemory) {
1020
+ return throwError(() => new Error('Channel memory persistence is not available'));
1021
+ }
1022
+ if (getPersistedChannelMemory) {
1023
+ return new Observable(observer => {
1024
+ getPersistedChannelMemory.call(this.persistenceService, channelId).subscribe({
1025
+ next: (loadedMemory) => {
1026
+ const enhancedMemory = {
1027
+ ...loadedMemory,
1028
+ sharedCognitiveInsights: {
1029
+ systemSummaries: [],
1030
+ topicExtractions: [],
1031
+ collaborativeReflections: []
1032
+ }
1033
+ };
1034
+ this.channelMemory.set(channelId, enhancedMemory);
1035
+ observer.next(enhancedMemory);
1036
+ observer.complete();
1037
+ },
1038
+ error: (error) => observer.error(error)
1039
+ });
1040
+ });
894
1041
  }
895
- // Create new memory
896
1042
  const newMemory = {
897
1043
  id: uuidv4(),
898
1044
  channelId,
@@ -915,16 +1061,6 @@ export class MemoryService {
915
1061
  }
916
1062
  };
917
1063
  this.channelMemory.set(channelId, newMemory);
918
- const operationId_channel_get_new = uuidv4();
919
- const systemAgentId_channel_get_new = 'SYSTEM_AGENT';
920
- const noChannelId_channel_get_new = 'NO_CHANNEL';
921
- const updateResultData_channel_get_new = {
922
- operationId: operationId_channel_get_new,
923
- scope: MemoryScope.CHANNEL,
924
- id: channelId,
925
- memory: newMemory
926
- };
927
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, systemAgentId_channel_get_new, noChannelId_channel_get_new, updateResultData_channel_get_new));
928
1064
  return of(newMemory);
929
1065
  }
930
1066
  /**
@@ -935,65 +1071,77 @@ export class MemoryService {
935
1071
  */
936
1072
  updateChannelMemory(channelId, updates) {
937
1073
  this.validator.assertIsNonEmptyString(channelId, 'Channel ID must be a non-empty string');
1074
+ this.validator.assertIsObject(updates, 'Channel memory updates must be an object');
1075
+ if (this.ownsPathOrDescendant(updates, 'conversationHistory') ||
1076
+ this.ownsPathOrDescendant(updates, 'sharedState.context') ||
1077
+ this.ownsPathOrDescendant(updates, 'customData.contextHistory') ||
1078
+ this.ownsPathOrDescendant(updates.sharedState, 'context') ||
1079
+ this.ownsPathOrDescendant(updates.customData, 'contextHistory')) {
1080
+ throw new Error('Reserved channel memory fields must use the atomic keyed-memory operations');
1081
+ }
938
1082
  return new Observable(observer => {
939
- this.getChannelMemory(channelId).subscribe(originalChannelMemory => {
940
- // Create updated memory by merging with original
941
- const updatedMemory = {
942
- ...originalChannelMemory, // This spreads all base properties
943
- channelId,
944
- lastActivity: updates.lastActivity || originalChannelMemory.lastActivity || Date.now(),
945
- messageCount: updates.messageCount !== undefined ? updates.messageCount : originalChannelMemory.messageCount,
946
- participants: updates.participants
947
- ? [...new Set([...(originalChannelMemory.participants || []), ...updates.participants])]
948
- : originalChannelMemory.participants,
949
- topics: updates.topics
950
- ? [...new Set([...(originalChannelMemory.topics || []), ...updates.topics])]
951
- : originalChannelMemory.topics,
952
- summary: updates.summary || originalChannelMemory.summary,
953
- conversationHistory: [...(originalChannelMemory.conversationHistory || [])],
954
- sharedCognitiveInsights: {
955
- ...originalChannelMemory.sharedCognitiveInsights,
956
- ...updates.sharedCognitiveInsights
1083
+ let cancelled = false;
1084
+ void (async () => {
1085
+ try {
1086
+ const enhancedStoredMemory = await this.serializeChannelMutation(channelId, async () => {
1087
+ const originalMemory = await firstValueFrom(this.getChannelMemory(channelId));
1088
+ const updatedMemory = {
1089
+ ...originalMemory,
1090
+ ...updates,
1091
+ id: originalMemory.id,
1092
+ channelId,
1093
+ createdAt: originalMemory.createdAt,
1094
+ updatedAt: new Date(),
1095
+ notes: updates.notes
1096
+ ? { ...originalMemory.notes, ...updates.notes }
1097
+ : originalMemory.notes,
1098
+ sharedState: updates.sharedState
1099
+ ? { ...originalMemory.sharedState, ...updates.sharedState }
1100
+ : originalMemory.sharedState,
1101
+ customData: updates.customData
1102
+ ? { ...originalMemory.customData, ...updates.customData }
1103
+ : originalMemory.customData,
1104
+ participants: updates.participants
1105
+ ? [...new Set([...(originalMemory.participants ?? []), ...updates.participants])]
1106
+ : originalMemory.participants,
1107
+ topics: updates.topics
1108
+ ? [...new Set([...(originalMemory.topics ?? []), ...updates.topics])]
1109
+ : originalMemory.topics,
1110
+ conversationHistory: updates.conversationHistory
1111
+ ? [
1112
+ ...(originalMemory.conversationHistory ?? []),
1113
+ ...updates.conversationHistory
1114
+ ]
1115
+ : originalMemory.conversationHistory,
1116
+ sharedCognitiveInsights: {
1117
+ ...originalMemory.sharedCognitiveInsights,
1118
+ ...updates.sharedCognitiveInsights
1119
+ }
1120
+ };
1121
+ const storedMemory = this.persistenceService
1122
+ ? await firstValueFrom(this.persistenceService.saveChannelMemory(updatedMemory))
1123
+ : updatedMemory;
1124
+ const enhancedMemory = {
1125
+ ...storedMemory,
1126
+ sharedCognitiveInsights: updatedMemory.sharedCognitiveInsights
1127
+ };
1128
+ this.channelMemory.set(channelId, enhancedMemory);
1129
+ return enhancedMemory;
1130
+ });
1131
+ if (!cancelled) {
1132
+ observer.next(enhancedStoredMemory);
1133
+ observer.complete();
957
1134
  }
958
- };
959
- // Handle conversation history updates
960
- if (updates.conversationHistory && updates.conversationHistory.length > 0) {
961
- updatedMemory.conversationHistory = [
962
- ...(originalChannelMemory.conversationHistory || []),
963
- ...updates.conversationHistory
964
- ];
965
1135
  }
966
- // Store updated memory in cache
967
- this.channelMemory.set(channelId, updatedMemory);
968
- // Emit update event through EventBus
969
- const operationId = uuidv4();
970
- const updateResultData = {
971
- operationId,
972
- scope: MemoryScope.CHANNEL,
973
- id: channelId,
974
- memory: updatedMemory
975
- };
976
- // Define standard agentId and channelId for system-level memory events
977
- const systemAgentId = 'SYSTEM_AGENT';
978
- const systemChannelId = channelId; // Use the actual channel ID for channel operations
979
- const payload = createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, systemAgentId, systemChannelId, updateResultData);
980
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, payload);
981
- observer.next(updatedMemory);
982
- observer.complete();
983
- }, error => {
984
- const operationId_channel_update_error = uuidv4();
985
- const updateResultData_channel_update_error = {
986
- operationId: operationId_channel_update_error,
987
- scope: MemoryScope.CHANNEL,
988
- id: channelId,
989
- memory: null,
990
- error: error.message
991
- };
992
- const systemAgentId_channel_update_error = 'SYSTEM_AGENT';
993
- const systemChannelId_channel_update_error = channelId;
994
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, systemAgentId_channel_update_error, systemChannelId_channel_update_error, updateResultData_channel_update_error));
995
- observer.error(error);
996
- });
1136
+ catch (error) {
1137
+ if (!cancelled) {
1138
+ observer.error(error);
1139
+ }
1140
+ }
1141
+ })();
1142
+ return () => {
1143
+ cancelled = true;
1144
+ };
997
1145
  });
998
1146
  }
999
1147
  /**
@@ -1017,7 +1165,22 @@ export class MemoryService {
1017
1165
  if (existingMemory) {
1018
1166
  return of(existingMemory);
1019
1167
  }
1020
- // Create new memory
1168
+ const getPersistedRelationshipMemory = this.persistenceService?.getRelationshipMemory;
1169
+ if (this.persistenceService && !getPersistedRelationshipMemory) {
1170
+ return throwError(() => new Error('Relationship memory persistence is not available'));
1171
+ }
1172
+ if (channelId && getPersistedRelationshipMemory) {
1173
+ return new Observable(observer => {
1174
+ getPersistedRelationshipMemory.call(this.persistenceService, sortedId1, sortedId2, channelId).subscribe({
1175
+ next: (loadedMemory) => {
1176
+ this.relationshipMemory.set(relationshipKey, loadedMemory);
1177
+ observer.next(loadedMemory);
1178
+ observer.complete();
1179
+ },
1180
+ error: (error) => observer.error(error)
1181
+ });
1182
+ });
1183
+ }
1021
1184
  const newMemory = {
1022
1185
  id: uuidv4(),
1023
1186
  agentId1: sortedId1,
@@ -1031,16 +1194,6 @@ export class MemoryService {
1031
1194
  customData: {}
1032
1195
  };
1033
1196
  this.relationshipMemory.set(relationshipKey, newMemory);
1034
- const operationId_rel_get_new = uuidv4();
1035
- const systemAgentId_rel_get_new = 'SYSTEM_AGENT';
1036
- const noChannelId_rel_get_new = 'NO_CHANNEL';
1037
- const updateResultData_rel_get_new = {
1038
- operationId: operationId_rel_get_new,
1039
- scope: MemoryScope.RELATIONSHIP,
1040
- id: relationshipKey,
1041
- memory: newMemory
1042
- };
1043
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, systemAgentId_rel_get_new, noChannelId_rel_get_new, updateResultData_rel_get_new));
1044
1197
  return of(newMemory);
1045
1198
  }
1046
1199
  /**
@@ -1057,91 +1210,163 @@ export class MemoryService {
1057
1210
  this.validator.assertIsNonEmptyString(pChannelId, 'Channel ID must be a non-empty string');
1058
1211
  this.validator.assertIsObject(updates, 'Updates must be an object');
1059
1212
  const relationshipKey = this.getRelationshipKey(pAgentId1, pAgentId2, pChannelId);
1060
- // Get existing memory or create new one
1061
1213
  return new Observable(observer => {
1062
- this.getRelationshipMemory(pAgentId1, pAgentId2, pChannelId).subscribe(originalRelationshipMemory => {
1063
- // Apply updates
1064
- const updatedMemory = {
1065
- ...originalRelationshipMemory,
1066
- ...updates,
1067
- updatedAt: new Date(),
1068
- // Ensure these fields can't be overridden
1069
- id: originalRelationshipMemory.id,
1070
- agentId1: originalRelationshipMemory.agentId1,
1071
- agentId2: originalRelationshipMemory.agentId2,
1072
- channelId: originalRelationshipMemory.channelId,
1073
- createdAt: originalRelationshipMemory.createdAt
1074
- };
1075
- // Deep merge for nested objects (if any)
1076
- // Example: if (updates.customData) { updatedMemory.customData = { ...originalRelationshipMemory.customData, ...updates.customData }; }
1077
- // Update in-memory store
1078
- this.relationshipMemory.set(relationshipKey, updatedMemory);
1079
- const operationId_rel_update_success = uuidv4();
1080
- const systemAgentId_rel_update_success = 'SYSTEM_AGENT';
1081
- const noChannelId_rel_update_success = 'NO_CHANNEL'; // General system event
1082
- const updateResultData_rel_update_success = {
1083
- operationId: operationId_rel_update_success,
1084
- scope: MemoryScope.RELATIONSHIP,
1085
- id: relationshipKey,
1086
- memory: updatedMemory
1087
- };
1088
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, systemAgentId_rel_update_success, noChannelId_rel_update_success, updateResultData_rel_update_success));
1089
- // Return updated memory
1090
- observer.next(updatedMemory);
1091
- observer.complete();
1092
- }, error => {
1093
- const operationId_rel_update_error = uuidv4();
1094
- const systemAgentId_rel_update_error = 'SYSTEM_AGENT';
1095
- const noChannelId_rel_update_error = 'NO_CHANNEL';
1096
- // Reconstruct the key for the 'id' field as it was the one attempted for the update.
1097
- const attemptedRelationshipKey = this.getRelationshipKey(pAgentId1, pAgentId2, pChannelId);
1098
- const updateResultData_rel_update_error = {
1099
- operationId: operationId_rel_update_error,
1100
- scope: MemoryScope.RELATIONSHIP,
1101
- id: attemptedRelationshipKey, // Use the key that was attempted
1102
- memory: null,
1103
- error: error.message
1104
- };
1105
- EventBus.server.emit(Events.Memory.UPDATE_RESULT, createMemoryUpdateResultEventPayload(Events.Memory.UPDATE_RESULT, systemAgentId_rel_update_error, noChannelId_rel_update_error, updateResultData_rel_update_error));
1106
- observer.error(error);
1107
- });
1214
+ let cancelled = false;
1215
+ void (async () => {
1216
+ try {
1217
+ const storedMemory = await this.serializeRelationshipMutation(pAgentId1, pAgentId2, pChannelId, async () => {
1218
+ const originalMemory = await firstValueFrom(this.getRelationshipMemory(pAgentId1, pAgentId2, pChannelId));
1219
+ const updatedMemory = {
1220
+ ...originalMemory,
1221
+ ...updates,
1222
+ id: originalMemory.id,
1223
+ agentId1: originalMemory.agentId1,
1224
+ agentId2: originalMemory.agentId2,
1225
+ channelId: originalMemory.channelId,
1226
+ createdAt: originalMemory.createdAt,
1227
+ updatedAt: new Date(),
1228
+ notes: updates.notes
1229
+ ? { ...originalMemory.notes, ...updates.notes }
1230
+ : originalMemory.notes,
1231
+ customData: updates.customData
1232
+ ? { ...originalMemory.customData, ...updates.customData }
1233
+ : originalMemory.customData
1234
+ };
1235
+ const saveRelationshipMemory = this.persistenceService?.saveRelationshipMemory;
1236
+ if (this.persistenceService && !saveRelationshipMemory) {
1237
+ throw new Error('Relationship memory persistence is not available');
1238
+ }
1239
+ const persistedMemory = saveRelationshipMemory
1240
+ ? await firstValueFrom(saveRelationshipMemory.call(this.persistenceService, updatedMemory))
1241
+ : updatedMemory;
1242
+ this.relationshipMemory.set(relationshipKey, persistedMemory);
1243
+ return persistedMemory;
1244
+ });
1245
+ if (!cancelled) {
1246
+ observer.next(storedMemory);
1247
+ observer.complete();
1248
+ }
1249
+ }
1250
+ catch (error) {
1251
+ if (!cancelled) {
1252
+ observer.error(error);
1253
+ }
1254
+ }
1255
+ })();
1256
+ return () => {
1257
+ cancelled = true;
1258
+ };
1108
1259
  });
1109
1260
  }
1110
1261
  /**
1111
1262
  * Delete memory by scope and ID
1112
1263
  * @param scope Memory scope
1113
- * @param id Entity ID
1264
+ * @param id Entity ID or relationship composite ID
1114
1265
  * @returns Observable of success status
1115
1266
  */
1116
1267
  deleteMemory(scope, id) {
1117
1268
  this.validator.validateMemoryScope(scope);
1118
- this.validator.assertIsNonEmptyString(id, 'ID must be a non-empty string');
1119
- let success = false;
1120
- const operationId = uuidv4(); // Generate operationId for the event data
1121
- switch (scope) {
1122
- case MemoryScope.AGENT:
1123
- success = this.agentMemory.delete(id);
1124
- break;
1125
- case MemoryScope.CHANNEL:
1126
- success = this.channelMemory.delete(id);
1127
- break;
1128
- case MemoryScope.RELATIONSHIP:
1129
- success = this.relationshipMemory.delete(id);
1130
- break;
1269
+ if (scope === MemoryScope.RELATIONSHIP) {
1270
+ if (!Array.isArray(id) || id.length !== 3) {
1271
+ throw new Error('Relationship memory deletion requires agentId1, agentId2, and channelId');
1272
+ }
1273
+ id.forEach((part, index) => {
1274
+ this.validator.assertIsNonEmptyString(part, `Relationship delete ID part ${index}`);
1275
+ });
1131
1276
  }
1132
- // Emit delete event through EventBus
1133
- const deleteResultData = {
1134
- operationId,
1135
- scope,
1136
- id,
1137
- success
1138
- };
1139
- // Define standard agentId and channelId for system-level memory events
1140
- const systemAgentId = 'SYSTEM_AGENT'; // Or a more specific system agent ID
1141
- const noChannelId = 'NO_CHANNEL'; // Or a more specific system channel ID or null if appropriate
1142
- const payload = createMemoryDeleteResultEventPayload(Events.Memory.DELETE_RESULT, systemAgentId, noChannelId, deleteResultData);
1143
- EventBus.server.emit(Events.Memory.DELETE_RESULT, payload);
1144
- return of(success);
1277
+ else {
1278
+ this.validator.assertIsNonEmptyString(id, 'Memory ID must be a non-empty string');
1279
+ }
1280
+ return new Observable(observer => {
1281
+ let cancelled = false;
1282
+ void (async () => {
1283
+ try {
1284
+ if (scope === MemoryScope.CHANNEL &&
1285
+ typeof id === 'string' &&
1286
+ id.startsWith('channel:')) {
1287
+ const success = await this.deleteKeyedChannelMemory(id);
1288
+ if (!cancelled) {
1289
+ observer.next(success);
1290
+ observer.complete();
1291
+ }
1292
+ return;
1293
+ }
1294
+ const deleteAuthoritatively = async () => {
1295
+ const deletePersistentMemory = this.persistenceService?.deleteMemory;
1296
+ if (this.persistenceService && !deletePersistentMemory) {
1297
+ throw new Error('Memory deletion persistence is not available');
1298
+ }
1299
+ const persisted = deletePersistentMemory
1300
+ ? await firstValueFrom(deletePersistentMemory.call(this.persistenceService, scope, id))
1301
+ : false;
1302
+ if (this.persistenceService && !persisted) {
1303
+ return false;
1304
+ }
1305
+ let cached = false;
1306
+ switch (scope) {
1307
+ case MemoryScope.AGENT: {
1308
+ const agentId = id;
1309
+ cached = this.agentMemory.delete(agentId);
1310
+ for (const [key, memory] of this.relationshipMemory.entries()) {
1311
+ if (memory.agentId1 === agentId || memory.agentId2 === agentId) {
1312
+ cached = this.relationshipMemory.delete(key) || cached;
1313
+ }
1314
+ }
1315
+ for (const [key, memory] of this.cognitiveMemory.entries()) {
1316
+ if (memory.agentId === agentId) {
1317
+ cached = this.cognitiveMemory.delete(key) || cached;
1318
+ }
1319
+ }
1320
+ break;
1321
+ }
1322
+ case MemoryScope.CHANNEL: {
1323
+ const channelId = id;
1324
+ cached = this.channelMemory.has(channelId);
1325
+ cached = this.channelMemory.delete(channelId) || cached;
1326
+ for (const key of this.generalData.keys()) {
1327
+ if (key.endsWith(`:${channelId}`)) {
1328
+ cached = this.generalData.delete(key) || cached;
1329
+ }
1330
+ }
1331
+ break;
1332
+ }
1333
+ case MemoryScope.RELATIONSHIP: {
1334
+ const [agentId1, agentId2, channelId] = id;
1335
+ cached = this.relationshipMemory.delete(this.getRelationshipKey(agentId1, agentId2, channelId));
1336
+ break;
1337
+ }
1338
+ }
1339
+ return this.persistenceService ? persisted : cached;
1340
+ };
1341
+ let deleted;
1342
+ switch (scope) {
1343
+ case MemoryScope.AGENT:
1344
+ deleted = await this.serializeAgentMutation(id, deleteAuthoritatively);
1345
+ break;
1346
+ case MemoryScope.CHANNEL:
1347
+ deleted = await this.serializeChannelMutation(id, deleteAuthoritatively);
1348
+ break;
1349
+ case MemoryScope.RELATIONSHIP: {
1350
+ const [agentId1, agentId2, channelId] = id;
1351
+ deleted = await this.serializeRelationshipMutation(agentId1, agentId2, channelId, deleteAuthoritatively);
1352
+ break;
1353
+ }
1354
+ }
1355
+ if (!cancelled) {
1356
+ observer.next(deleted);
1357
+ observer.complete();
1358
+ }
1359
+ }
1360
+ catch (error) {
1361
+ if (!cancelled) {
1362
+ observer.error(error);
1363
+ }
1364
+ }
1365
+ })();
1366
+ return () => {
1367
+ cancelled = true;
1368
+ };
1369
+ });
1145
1370
  }
1146
1371
  /**
1147
1372
  * Clear all memory of a specific scope
@@ -1404,7 +1629,7 @@ export class MemoryService {
1404
1629
  }
1405
1630
  }
1406
1631
  catch (error) {
1407
- this.logger.warn(`[MemoryService] Entity extraction failed for memory ${memoryId}: ${error.message}`);
1632
+ this.logger.warn(`[MemoryService] Entity extraction failed for memory ${memoryId}: ${error instanceof Error ? error.message : String(error)}`);
1408
1633
  }
1409
1634
  }
1410
1635
  /**
@@ -1458,11 +1683,13 @@ export class MemoryService {
1458
1683
  // Handle objects
1459
1684
  if (Array.isArray(data1) || Array.isArray(data2))
1460
1685
  return false;
1461
- const keys1 = Object.keys(data1);
1462
- const keys2 = Object.keys(data2);
1686
+ const record1 = data1;
1687
+ const record2 = data2;
1688
+ const keys1 = Object.keys(record1);
1689
+ const keys2 = Object.keys(record2);
1463
1690
  if (keys1.length !== keys2.length)
1464
1691
  return false;
1465
- return keys1.every(key => keys2.includes(key) && this.isDataEqual(data1[key], data2[key]));
1692
+ return keys1.every(key => keys2.includes(key) && this.isDataEqual(record1[key], record2[key]));
1466
1693
  }
1467
1694
  }
1468
1695
  //# sourceMappingURL=MemoryService.js.map