@memberjunction/server 6.2.0-edge.2 → 6.2.0-edge.4

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 (435) hide show
  1. package/README.md +30 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentSessions/BridgeHostInstance.d.ts +25 -0
  4. package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -0
  5. package/dist/agentSessions/BridgeHostInstance.js +30 -0
  6. package/dist/agentSessions/BridgeHostInstance.js.map +1 -0
  7. package/dist/agentSessions/HostInstance.d.ts +75 -11
  8. package/dist/agentSessions/HostInstance.d.ts.map +1 -1
  9. package/dist/agentSessions/HostInstance.js +99 -28
  10. package/dist/agentSessions/HostInstance.js.map +1 -1
  11. package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
  12. package/dist/agentSessions/ReturningVisitorRecap.js +7 -3
  13. package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
  14. package/dist/agentSessions/SessionJanitor.d.ts +173 -25
  15. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  16. package/dist/agentSessions/SessionJanitor.js +452 -54
  17. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  18. package/dist/agentSessions/SessionManager.d.ts +43 -2
  19. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  20. package/dist/agentSessions/SessionManager.js +99 -8
  21. package/dist/agentSessions/SessionManager.js.map +1 -1
  22. package/dist/agentSessions/SessionRunIDVerifier.d.ts +63 -0
  23. package/dist/agentSessions/SessionRunIDVerifier.d.ts.map +1 -0
  24. package/dist/agentSessions/SessionRunIDVerifier.js +129 -0
  25. package/dist/agentSessions/SessionRunIDVerifier.js.map +1 -0
  26. package/dist/agentSessions/index.d.ts +2 -0
  27. package/dist/agentSessions/index.d.ts.map +1 -1
  28. package/dist/agentSessions/index.js +10 -3
  29. package/dist/agentSessions/index.js.map +1 -1
  30. package/dist/auth/actionAuthorization.d.ts +40 -0
  31. package/dist/auth/actionAuthorization.d.ts.map +1 -0
  32. package/dist/auth/actionAuthorization.js +94 -0
  33. package/dist/auth/actionAuthorization.js.map +1 -0
  34. package/dist/auth/index.d.ts.map +1 -1
  35. package/dist/auth/index.js +3 -10
  36. package/dist/auth/index.js.map +1 -1
  37. package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
  38. package/dist/auth/magicLink/MagicLinkService.js +6 -3
  39. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  40. package/dist/auth/newUsers.d.ts +10 -0
  41. package/dist/auth/newUsers.d.ts.map +1 -1
  42. package/dist/auth/newUsers.js +80 -11
  43. package/dist/auth/newUsers.js.map +1 -1
  44. package/dist/config.d.ts +4567 -71
  45. package/dist/config.d.ts.map +1 -1
  46. package/dist/config.js +246 -3
  47. package/dist/config.js.map +1 -1
  48. package/dist/context.d.ts +8 -0
  49. package/dist/context.d.ts.map +1 -1
  50. package/dist/context.js +25 -34
  51. package/dist/context.js.map +1 -1
  52. package/dist/generated/graphql-schemas/__mj.d.ts +1073 -10
  53. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  54. package/dist/generated/graphql-schemas/__mj.js +9188 -3649
  55. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  56. package/dist/generic/OrphanedConversationDetailReconciler.js +3 -3
  57. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
  58. package/dist/generic/ResolverBase.d.ts +62 -6
  59. package/dist/generic/ResolverBase.d.ts.map +1 -1
  60. package/dist/generic/ResolverBase.js +179 -35
  61. package/dist/generic/ResolverBase.js.map +1 -1
  62. package/dist/generic/RunViewResolver.d.ts +4 -0
  63. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  64. package/dist/generic/RunViewResolver.js +37 -1
  65. package/dist/generic/RunViewResolver.js.map +1 -1
  66. package/dist/index.d.ts +7 -0
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +214 -159
  69. package/dist/index.js.map +1 -1
  70. package/dist/isolatedProvider.d.ts +20 -0
  71. package/dist/isolatedProvider.d.ts.map +1 -0
  72. package/dist/isolatedProvider.js +22 -0
  73. package/dist/isolatedProvider.js.map +1 -0
  74. package/dist/postgresqlCompat.d.ts +8 -0
  75. package/dist/postgresqlCompat.d.ts.map +1 -0
  76. package/dist/postgresqlCompat.js +19 -0
  77. package/dist/postgresqlCompat.js.map +1 -0
  78. package/dist/postgresqlPoolSettings.d.ts +108 -0
  79. package/dist/postgresqlPoolSettings.d.ts.map +1 -0
  80. package/dist/postgresqlPoolSettings.js +134 -0
  81. package/dist/postgresqlPoolSettings.js.map +1 -0
  82. package/dist/realtimeProxy/RealtimeProxyServer.d.ts +44 -4
  83. package/dist/realtimeProxy/RealtimeProxyServer.d.ts.map +1 -1
  84. package/dist/realtimeProxy/RealtimeProxyServer.js +121 -16
  85. package/dist/realtimeProxy/RealtimeProxyServer.js.map +1 -1
  86. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts +171 -0
  87. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts.map +1 -0
  88. package/dist/realtimeProxy/RealtimeRelayTunnel.js +532 -0
  89. package/dist/realtimeProxy/RealtimeRelayTunnel.js.map +1 -0
  90. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts +148 -0
  91. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts.map +1 -0
  92. package/dist/realtimeSessions/RealtimeSessionEventService.js +191 -0
  93. package/dist/realtimeSessions/RealtimeSessionEventService.js.map +1 -0
  94. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts +66 -0
  95. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -0
  96. package/dist/realtimeSessions/RealtimeSessionVerificationService.js +138 -0
  97. package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -0
  98. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts +38 -0
  99. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -0
  100. package/dist/realtimeSessions/RealtimeVerifyRouter.js +98 -0
  101. package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -0
  102. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts +61 -0
  103. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -0
  104. package/dist/realtimeSessions/SessionVerificationPortsBase.js +149 -0
  105. package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -0
  106. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts +57 -0
  107. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts.map +1 -0
  108. package/dist/realtimeSessions/SlidingWindowRateLimiter.js +69 -0
  109. package/dist/realtimeSessions/SlidingWindowRateLimiter.js.map +1 -0
  110. package/dist/realtimeSessions/index.d.ts +17 -0
  111. package/dist/realtimeSessions/index.d.ts.map +1 -0
  112. package/dist/realtimeSessions/index.js +17 -0
  113. package/dist/realtimeSessions/index.js.map +1 -0
  114. package/dist/realtimeSessions/sessionAccess.d.ts +86 -0
  115. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -0
  116. package/dist/realtimeSessions/sessionAccess.js +90 -0
  117. package/dist/realtimeSessions/sessionAccess.js.map +1 -0
  118. package/dist/realtimeSessions/sessionConfigStamps.d.ts +70 -0
  119. package/dist/realtimeSessions/sessionConfigStamps.d.ts.map +1 -0
  120. package/dist/realtimeSessions/sessionConfigStamps.js +93 -0
  121. package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -0
  122. package/dist/realtimeSessions/subscriptionAuthorization.d.ts +65 -0
  123. package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -0
  124. package/dist/realtimeSessions/subscriptionAuthorization.js +71 -0
  125. package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -0
  126. package/dist/realtimeSessions/verificationCore.d.ts +243 -0
  127. package/dist/realtimeSessions/verificationCore.d.ts.map +1 -0
  128. package/dist/realtimeSessions/verificationCore.js +356 -0
  129. package/dist/realtimeSessions/verificationCore.js.map +1 -0
  130. package/dist/realtimeSessions/verificationPages.d.ts +66 -0
  131. package/dist/realtimeSessions/verificationPages.d.ts.map +1 -0
  132. package/dist/realtimeSessions/verificationPages.js +110 -0
  133. package/dist/realtimeSessions/verificationPages.js.map +1 -0
  134. package/dist/realtimeSessions/verificationPolicy.d.ts +147 -0
  135. package/dist/realtimeSessions/verificationPolicy.d.ts.map +1 -0
  136. package/dist/realtimeSessions/verificationPolicy.js +249 -0
  137. package/dist/realtimeSessions/verificationPolicy.js.map +1 -0
  138. package/dist/realtimeSessions/verificationWorkflow.d.ts +263 -0
  139. package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -0
  140. package/dist/realtimeSessions/verificationWorkflow.js +435 -0
  141. package/dist/realtimeSessions/verificationWorkflow.js.map +1 -0
  142. package/dist/realtimeWidget/widgetGuestElevation.d.ts +20 -2
  143. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  144. package/dist/realtimeWidget/widgetGuestElevation.js +31 -2
  145. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  146. package/dist/resolvers/ActionResolver.d.ts +31 -5
  147. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  148. package/dist/resolvers/ActionResolver.js +75 -14
  149. package/dist/resolvers/ActionResolver.js.map +1 -1
  150. package/dist/resolvers/AdhocQueryResolver.d.ts +35 -17
  151. package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
  152. package/dist/resolvers/AdhocQueryResolver.js +92 -166
  153. package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
  154. package/dist/resolvers/CacheStatsResolver.d.ts +27 -0
  155. package/dist/resolvers/CacheStatsResolver.d.ts.map +1 -1
  156. package/dist/resolvers/CacheStatsResolver.js +113 -2
  157. package/dist/resolvers/CacheStatsResolver.js.map +1 -1
  158. package/dist/resolvers/ClientToolRequestResolver.d.ts +4 -2
  159. package/dist/resolvers/ClientToolRequestResolver.d.ts.map +1 -1
  160. package/dist/resolvers/ClientToolRequestResolver.js +28 -10
  161. package/dist/resolvers/ClientToolRequestResolver.js.map +1 -1
  162. package/dist/resolvers/EntityRecordNameResolver.d.ts +7 -23
  163. package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
  164. package/dist/resolvers/EntityRecordNameResolver.js +9 -47
  165. package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
  166. package/dist/resolvers/FetchEntityVectorsResolver.d.ts +12 -1
  167. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  168. package/dist/resolvers/FetchEntityVectorsResolver.js +83 -2
  169. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  170. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  171. package/dist/resolvers/GetDataResolver.js +9 -0
  172. package/dist/resolvers/GetDataResolver.js.map +1 -1
  173. package/dist/resolvers/HumanHandoffResolver.d.ts +107 -0
  174. package/dist/resolvers/HumanHandoffResolver.d.ts.map +1 -0
  175. package/dist/resolvers/HumanHandoffResolver.js +330 -0
  176. package/dist/resolvers/HumanHandoffResolver.js.map +1 -0
  177. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  178. package/dist/resolvers/MCPResolver.js +9 -4
  179. package/dist/resolvers/MCPResolver.js.map +1 -1
  180. package/dist/resolvers/MeetingResolver.d.ts +69 -0
  181. package/dist/resolvers/MeetingResolver.d.ts.map +1 -0
  182. package/dist/resolvers/MeetingResolver.js +381 -0
  183. package/dist/resolvers/MeetingResolver.js.map +1 -0
  184. package/dist/resolvers/RealtimeBridgeResolver.d.ts +88 -3
  185. package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
  186. package/dist/resolvers/RealtimeBridgeResolver.js +352 -12
  187. package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
  188. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +156 -108
  189. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  190. package/dist/resolvers/RealtimeClientSessionResolver.js +395 -293
  191. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  192. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts +61 -0
  193. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts.map +1 -0
  194. package/dist/resolvers/RealtimeSessionEventsResolver.js +130 -0
  195. package/dist/resolvers/RealtimeSessionEventsResolver.js.map +1 -0
  196. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts +85 -0
  197. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts.map +1 -0
  198. package/dist/resolvers/RealtimeSessionVerificationResolver.js +188 -0
  199. package/dist/resolvers/RealtimeSessionVerificationResolver.js.map +1 -0
  200. package/dist/resolvers/RemoteBrowserActionResolver.d.ts +2 -0
  201. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  202. package/dist/resolvers/RemoteBrowserActionResolver.js +5 -1
  203. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  204. package/dist/resolvers/RunAIAgentResolver.d.ts +10 -0
  205. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  206. package/dist/resolvers/RunAIAgentResolver.js +68 -11
  207. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  208. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  209. package/dist/resolvers/RunTemplateResolver.js +12 -11
  210. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  211. package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
  212. package/dist/resolvers/SyncDataResolver.js +6 -2
  213. package/dist/resolvers/SyncDataResolver.js.map +1 -1
  214. package/dist/resolvers/SyncRolesUsersResolver.d.ts +2 -0
  215. package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
  216. package/dist/resolvers/SyncRolesUsersResolver.js +23 -6
  217. package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
  218. package/dist/resolvers/UserAvatarResolver.d.ts +16 -0
  219. package/dist/resolvers/UserAvatarResolver.d.ts.map +1 -0
  220. package/dist/resolvers/UserAvatarResolver.js +124 -0
  221. package/dist/resolvers/UserAvatarResolver.js.map +1 -0
  222. package/dist/resolvers/UserResolver.d.ts.map +1 -1
  223. package/dist/resolvers/UserResolver.js +2 -17
  224. package/dist/resolvers/UserResolver.js.map +1 -1
  225. package/dist/resolvers/adhocTimeout.d.ts +7 -0
  226. package/dist/resolvers/adhocTimeout.d.ts.map +1 -0
  227. package/dist/resolvers/adhocTimeout.js +12 -0
  228. package/dist/resolvers/adhocTimeout.js.map +1 -0
  229. package/dist/resolvers/agentVisionConsentAudit.d.ts +37 -0
  230. package/dist/resolvers/agentVisionConsentAudit.d.ts.map +1 -0
  231. package/dist/resolvers/agentVisionConsentAudit.js +63 -0
  232. package/dist/resolvers/agentVisionConsentAudit.js.map +1 -0
  233. package/dist/resolvers/avatarInputValidation.d.ts +40 -0
  234. package/dist/resolvers/avatarInputValidation.d.ts.map +1 -0
  235. package/dist/resolvers/avatarInputValidation.js +97 -0
  236. package/dist/resolvers/avatarInputValidation.js.map +1 -0
  237. package/dist/resolvers/currentUserRoles.d.ts +29 -0
  238. package/dist/resolvers/currentUserRoles.d.ts.map +1 -1
  239. package/dist/resolvers/currentUserRoles.js +30 -0
  240. package/dist/resolvers/currentUserRoles.js.map +1 -1
  241. package/dist/resolvers/meetings/index.d.ts +5 -0
  242. package/dist/resolvers/meetings/index.d.ts.map +1 -0
  243. package/dist/resolvers/meetings/index.js +5 -0
  244. package/dist/resolvers/meetings/index.js.map +1 -0
  245. package/dist/resolvers/meetings/meetingHelpers.d.ts +17 -0
  246. package/dist/resolvers/meetings/meetingHelpers.d.ts.map +1 -0
  247. package/dist/resolvers/meetings/meetingHelpers.js +212 -0
  248. package/dist/resolvers/meetings/meetingHelpers.js.map +1 -0
  249. package/dist/resolvers/meetings/meetingMutations.d.ts +18 -0
  250. package/dist/resolvers/meetings/meetingMutations.d.ts.map +1 -0
  251. package/dist/resolvers/meetings/meetingMutations.js +439 -0
  252. package/dist/resolvers/meetings/meetingMutations.js.map +1 -0
  253. package/dist/resolvers/meetings/meetingQueries.d.ts +7 -0
  254. package/dist/resolvers/meetings/meetingQueries.d.ts.map +1 -0
  255. package/dist/resolvers/meetings/meetingQueries.js +113 -0
  256. package/dist/resolvers/meetings/meetingQueries.js.map +1 -0
  257. package/dist/resolvers/meetings/meetingTypes.d.ts +89 -0
  258. package/dist/resolvers/meetings/meetingTypes.d.ts.map +1 -0
  259. package/dist/resolvers/meetings/meetingTypes.js +345 -0
  260. package/dist/resolvers/meetings/meetingTypes.js.map +1 -0
  261. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  262. package/dist/rest/ViewOperationsHandler.js +8 -5
  263. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  264. package/dist/services/TaskGraphActionRunner.d.ts +8 -0
  265. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  266. package/dist/services/TaskGraphActionRunner.js +27 -1
  267. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  268. package/dist/services/TaskGraphContinuationDeliverer.d.ts +4 -3
  269. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  270. package/dist/services/TaskGraphContinuationDeliverer.js +13 -7
  271. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  272. package/dist/services/WorkQueueHostService.d.ts +36 -0
  273. package/dist/services/WorkQueueHostService.d.ts.map +1 -0
  274. package/dist/services/WorkQueueHostService.js +97 -0
  275. package/dist/services/WorkQueueHostService.js.map +1 -0
  276. package/dist/services/workQueueConfig.d.ts +103 -0
  277. package/dist/services/workQueueConfig.d.ts.map +1 -0
  278. package/dist/services/workQueueConfig.js +48 -0
  279. package/dist/services/workQueueConfig.js.map +1 -0
  280. package/dist/sharedCache.d.ts +105 -0
  281. package/dist/sharedCache.d.ts.map +1 -0
  282. package/dist/sharedCache.js +276 -0
  283. package/dist/sharedCache.js.map +1 -0
  284. package/dist/types.d.ts +11 -0
  285. package/dist/types.d.ts.map +1 -1
  286. package/dist/types.js.map +1 -1
  287. package/package.json +97 -94
  288. package/src/__tests__/ActionResolver.authorization.test.ts +353 -0
  289. package/src/__tests__/AdhocQueryResolver.bugs.test.ts +14 -35
  290. package/src/__tests__/AdhocQueryResolver.pagination.test.ts +6 -2
  291. package/src/__tests__/AdhocQueryResolver.scopeGuard.test.ts +3 -3
  292. package/src/__tests__/AdhocQueryResolver.sqlAuthorizer.test.ts +104 -0
  293. package/src/__tests__/BridgeHostInstance.test.ts +232 -0
  294. package/src/__tests__/ClientToolRequestResolver.test.ts +116 -0
  295. package/src/__tests__/EntityRecordNameResolver.fieldSecurity.test.ts +27 -72
  296. package/src/__tests__/FetchEntityVectorsResolver.test.ts +285 -0
  297. package/src/__tests__/HostInstance.test.ts +84 -0
  298. package/src/__tests__/HumanHandoffResolver.test.ts +250 -0
  299. package/src/__tests__/MeetingResolver.test.ts +448 -0
  300. package/src/__tests__/RealtimeBridgeResolver.test.ts +651 -4
  301. package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +383 -0
  302. package/src/__tests__/RealtimeClientSessionResolver.test.ts +682 -58
  303. package/src/__tests__/RealtimeProxyServer.test.ts +16 -1
  304. package/src/__tests__/RealtimeRelay.test.ts +876 -0
  305. package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +129 -0
  306. package/src/__tests__/ResolverBase.adhocReadScope.test.ts +96 -0
  307. package/src/__tests__/ResolverBase.aggregateScreen.test.ts +174 -0
  308. package/src/__tests__/ResolverBase.clientOldValues.test.ts +6 -3
  309. package/src/__tests__/ResolverBase.filterEscaping.test.ts +21 -2
  310. package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +291 -0
  311. package/src/__tests__/ReturningVisitorRecap.test.ts +115 -0
  312. package/src/__tests__/RunAIAgentResolver.branch.test.ts +169 -0
  313. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +4 -4
  314. package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +166 -0
  315. package/src/__tests__/RunTemplateResolver.test.ts +132 -0
  316. package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +63 -0
  317. package/src/__tests__/SessionJanitor.test.ts +845 -18
  318. package/src/__tests__/SessionManager.test.ts +213 -17
  319. package/src/__tests__/SessionRunIDVerifier.test.ts +251 -0
  320. package/src/__tests__/SyncRolesUsersResolver.userRoles.test.ts +97 -0
  321. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +41 -0
  322. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +50 -3
  323. package/src/__tests__/UserAvatarResolver.test.ts +255 -0
  324. package/src/__tests__/UserResolver.currentUser.test.ts +16 -1
  325. package/src/__tests__/WorkQueueHostService.test.ts +133 -0
  326. package/src/__tests__/actionAuthorization.test.ts +130 -0
  327. package/src/__tests__/adhocTimeoutClamp.test.ts +26 -0
  328. package/src/__tests__/agentVisionConsentAudit.test.ts +118 -0
  329. package/src/__tests__/avatarInputValidation.test.ts +160 -0
  330. package/src/__tests__/isolatedProviderTransactions.test.ts +169 -0
  331. package/src/__tests__/magicLinkService.consume.test.ts +6 -0
  332. package/src/__tests__/magicLinkService.provisionLog.test.ts +5 -0
  333. package/src/__tests__/newUsers.template.test.ts +151 -0
  334. package/src/__tests__/newUsers.test.ts +74 -5
  335. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +17 -2
  336. package/src/__tests__/postgresqlPoolSettings.test.ts +131 -0
  337. package/src/__tests__/realtimeSessions/RealtimeSessionEventService.test.ts +201 -0
  338. package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +215 -0
  339. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationResolver.test.ts +102 -0
  340. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationService.test.ts +349 -0
  341. package/src/__tests__/realtimeSessions/RealtimeVerifyRouter.test.ts +131 -0
  342. package/src/__tests__/realtimeSessions/SlidingWindowRateLimiter.test.ts +56 -0
  343. package/src/__tests__/realtimeSessions/helpers.ts +4 -0
  344. package/src/__tests__/realtimeSessions/sessionAccess.test.ts +129 -0
  345. package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +124 -0
  346. package/src/__tests__/realtimeSessions/verificationCore.test.ts +355 -0
  347. package/src/__tests__/realtimeSessions/verificationPages.test.ts +84 -0
  348. package/src/__tests__/realtimeSessions/verificationPolicy.test.ts +226 -0
  349. package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +633 -0
  350. package/src/__tests__/resolverBase.fls.test.ts +87 -4
  351. package/src/__tests__/serverExtensionReservedRoots.test.ts +2 -0
  352. package/src/__tests__/sharedCache.test.ts +310 -0
  353. package/src/__tests__/translateBracketsToPG.test.ts +20 -0
  354. package/src/__tests__/widgetGuestElevation.test.ts +44 -0
  355. package/src/agentSessions/BridgeHostInstance.ts +32 -0
  356. package/src/agentSessions/HostInstance.ts +124 -28
  357. package/src/agentSessions/ReturningVisitorRecap.ts +7 -3
  358. package/src/agentSessions/SessionJanitor.ts +543 -57
  359. package/src/agentSessions/SessionManager.ts +125 -25
  360. package/src/agentSessions/SessionRunIDVerifier.ts +171 -0
  361. package/src/agentSessions/index.ts +10 -3
  362. package/src/auth/actionAuthorization.ts +116 -0
  363. package/src/auth/index.ts +3 -8
  364. package/src/auth/magicLink/MagicLinkService.ts +6 -3
  365. package/src/auth/newUsers.ts +99 -11
  366. package/src/config.ts +255 -3
  367. package/src/context.ts +26 -34
  368. package/src/generated/graphql-schemas/__mj.ts +22701 -18838
  369. package/src/generic/OrphanedConversationDetailReconciler.ts +3 -3
  370. package/src/generic/ResolverBase.ts +210 -36
  371. package/src/generic/RunViewResolver.ts +37 -2
  372. package/src/index.ts +236 -170
  373. package/src/isolatedProvider.ts +22 -0
  374. package/src/postgresqlCompat.ts +21 -0
  375. package/src/postgresqlPoolSettings.ts +213 -0
  376. package/src/realtimeProxy/RealtimeProxyServer.ts +148 -16
  377. package/src/realtimeProxy/RealtimeRelayTunnel.ts +645 -0
  378. package/src/realtimeSessions/README.md +179 -0
  379. package/src/realtimeSessions/RealtimeSessionEventService.ts +274 -0
  380. package/src/realtimeSessions/RealtimeSessionVerificationService.ts +167 -0
  381. package/src/realtimeSessions/RealtimeVerifyRouter.ts +108 -0
  382. package/src/realtimeSessions/SessionVerificationPortsBase.ts +189 -0
  383. package/src/realtimeSessions/SlidingWindowRateLimiter.ts +92 -0
  384. package/src/realtimeSessions/index.ts +16 -0
  385. package/src/realtimeSessions/sessionAccess.ts +141 -0
  386. package/src/realtimeSessions/sessionConfigStamps.ts +123 -0
  387. package/src/realtimeSessions/subscriptionAuthorization.ts +116 -0
  388. package/src/realtimeSessions/verificationCore.ts +502 -0
  389. package/src/realtimeSessions/verificationPages.ts +149 -0
  390. package/src/realtimeSessions/verificationPolicy.ts +321 -0
  391. package/src/realtimeSessions/verificationWorkflow.ts +702 -0
  392. package/src/realtimeWidget/widgetGuestElevation.ts +34 -2
  393. package/src/resolvers/ActionResolver.ts +84 -21
  394. package/src/resolvers/AdhocQueryResolver.ts +105 -187
  395. package/src/resolvers/CacheStatsResolver.ts +89 -2
  396. package/src/resolvers/ClientToolRequestResolver.ts +25 -7
  397. package/src/resolvers/EntityRecordNameResolver.ts +9 -51
  398. package/src/resolvers/FetchEntityVectorsResolver.ts +97 -2
  399. package/src/resolvers/GetDataResolver.ts +10 -0
  400. package/src/resolvers/HumanHandoffResolver.ts +312 -0
  401. package/src/resolvers/MCPResolver.ts +8 -5
  402. package/src/resolvers/MeetingResolver.ts +438 -0
  403. package/src/resolvers/RealtimeBridgeResolver.ts +385 -19
  404. package/src/resolvers/RealtimeClientSessionResolver.ts +503 -344
  405. package/src/resolvers/RealtimeSessionEventsResolver.ts +133 -0
  406. package/src/resolvers/RealtimeSessionVerificationResolver.ts +174 -0
  407. package/src/resolvers/RemoteBrowserActionResolver.ts +11 -1
  408. package/src/resolvers/RunAIAgentResolver.ts +78 -11
  409. package/src/resolvers/RunTemplateResolver.ts +13 -12
  410. package/src/resolvers/SyncDataResolver.ts +6 -2
  411. package/src/resolvers/SyncRolesUsersResolver.ts +24 -6
  412. package/src/resolvers/UserAvatarResolver.ts +111 -0
  413. package/src/resolvers/UserResolver.ts +2 -16
  414. package/src/resolvers/adhocTimeout.ts +12 -0
  415. package/src/resolvers/agentVisionConsentAudit.ts +82 -0
  416. package/src/resolvers/avatarInputValidation.ts +123 -0
  417. package/src/resolvers/currentUserRoles.ts +32 -1
  418. package/src/resolvers/meetings/index.ts +4 -0
  419. package/src/resolvers/meetings/meetingHelpers.ts +307 -0
  420. package/src/resolvers/meetings/meetingMutations.ts +556 -0
  421. package/src/resolvers/meetings/meetingQueries.ts +172 -0
  422. package/src/resolvers/meetings/meetingTypes.ts +238 -0
  423. package/src/rest/ViewOperationsHandler.ts +8 -5
  424. package/src/services/TaskGraphActionRunner.ts +29 -1
  425. package/src/services/TaskGraphContinuationDeliverer.ts +13 -7
  426. package/src/services/WorkQueueHostService.ts +129 -0
  427. package/src/services/workQueueConfig.ts +52 -0
  428. package/src/sharedCache.ts +302 -0
  429. package/src/types.ts +12 -0
  430. package/dist/resolvers/adhoc-query-helpers.d.ts +0 -33
  431. package/dist/resolvers/adhoc-query-helpers.d.ts.map +0 -1
  432. package/dist/resolvers/adhoc-query-helpers.js +0 -50
  433. package/dist/resolvers/adhoc-query-helpers.js.map +0 -1
  434. package/src/__tests__/adhoc-query-helpers.test.ts +0 -50
  435. package/src/resolvers/adhoc-query-helpers.ts +0 -67
@@ -0,0 +1,312 @@
1
+ import { Resolver, Mutation, Query, Subscription, Arg, Ctx, Root, ObjectType, Field, ResolverFilterData } from 'type-graphql';
2
+ import { IMetadataProvider, LogError, UserInfo } from '@memberjunction/core';
3
+ import { MJGlobal, UUIDsEqual } from '@memberjunction/global';
4
+ import { NotificationEngine } from '@memberjunction/notifications';
5
+ import { UserCache } from '@memberjunction/generic-database-provider';
6
+ import {
7
+ LiveKitSipService,
8
+ RoomHandoffEngine,
9
+ HandoffOfferRegistry,
10
+ type HandoffOfferEvent,
11
+ type HandoffOfferView,
12
+ type IHandoffNotifier,
13
+ type IHandoffPublisher,
14
+ } from '@memberjunction/livekit-room-server';
15
+ import { AppContext } from '../types.js';
16
+ import { ResolverBase } from '../generic/ResolverBase.js';
17
+ import { PubSubManager } from '../generic/PubSubManager.js';
18
+
19
+ /**
20
+ * GraphQL surface for the human side of a room handoff: a person at an Explorer console is OFFERED a conversation an AI
21
+ * agent is having (a phone call that arrived through LiveKit SIP, or a web room), and accepts or declines it. Thin by the
22
+ * Transport-Layer rule: the offer lifecycle, the room watching and the AI's leave step live in `RoomHandoffEngine`
23
+ * (`@memberjunction/livekit-room-server`); this file only authenticates, delegates and shapes the answer.
24
+ *
25
+ * Every operation is scoped to the signed-in user: a person lists, accepts and declines only their OWN offers, and the live
26
+ * subscription delivers only theirs. Accepting returns the room name; the console then joins the room through the same
27
+ * LiveKit token path the Meet room uses (`MintLiveKitClientToken`), under the same identity the engine watches for.
28
+ */
29
+
30
+ /** The pub/sub topic offer changes are published on. */
31
+ export const HANDOFF_OFFER_TOPIC = 'HANDOFF_OFFER_CHANGES';
32
+
33
+ /** One offer, as the console sees it. */
34
+ @ObjectType()
35
+ export class HandoffOffer {
36
+ @Field(() => String)
37
+ OfferID: string;
38
+
39
+ @Field(() => String)
40
+ RoomName: string;
41
+
42
+ /** `warm` (the AI introduces you, then leaves) or `blind` (the AI leaves as soon as you join). */
43
+ @Field(() => String)
44
+ Mode: string;
45
+
46
+ /** The AI's summary of the conversation so far. */
47
+ @Field(() => String)
48
+ Summary: string;
49
+
50
+ /** Who is on the other end (a masked number, "Web visitor"). */
51
+ @Field(() => String)
52
+ CallerLabel: string;
53
+
54
+ /** The AI agent that is in the room. */
55
+ @Field(() => String)
56
+ AgentName: string;
57
+
58
+ /** `Pending`, `Accepted`, `Declined`, `Expired` or `Cancelled`. */
59
+ @Field(() => String)
60
+ Status: string;
61
+
62
+ @Field(() => String)
63
+ CreatedAt: string;
64
+
65
+ /** After this the offer can no longer be accepted. */
66
+ @Field(() => String)
67
+ ExpiresAt: string;
68
+
69
+ /** The MJ interaction ID associated with this conversation/room, if known. */
70
+ @Field(() => String, { nullable: true })
71
+ InteractionID?: string | null;
72
+ }
73
+
74
+ /** One change to an offer, pushed to the person it belongs to. */
75
+ @ObjectType()
76
+ export class HandoffOfferChange {
77
+ /** `offered` for a new offer; `updated` when it was accepted, declined, expired or cancelled. */
78
+ @Field(() => String)
79
+ Kind: string;
80
+
81
+ @Field(() => HandoffOffer)
82
+ Offer: HandoffOffer;
83
+ }
84
+
85
+ @ObjectType()
86
+ export class AcceptHandoffOfferResult {
87
+ @Field(() => Boolean)
88
+ Success: boolean;
89
+
90
+ @Field(() => String, { nullable: true })
91
+ ErrorMessage?: string;
92
+
93
+ /** The room to join (through `MintLiveKitClientToken`). Empty on failure. */
94
+ @Field(() => String)
95
+ RoomName: string;
96
+
97
+ @Field(() => HandoffOffer, { nullable: true })
98
+ Offer?: HandoffOffer;
99
+ }
100
+
101
+ @ObjectType()
102
+ export class DeclineHandoffOfferResult {
103
+ @Field(() => Boolean)
104
+ Success: boolean;
105
+
106
+ @Field(() => String, { nullable: true })
107
+ ErrorMessage?: string;
108
+ }
109
+
110
+ /** What the subscription filter reads off the connection. */
111
+ interface HandoffSubscriptionContext {
112
+ userPayload?: { userRecord?: { ID?: string } };
113
+ }
114
+
115
+ /**
116
+ * Delivery predicate for {@link HumanHandoffResolver.HandoffOfferChanges}: a change reaches only the person it belongs to.
117
+ * **Fails closed**: a missing identity on either side never matches.
118
+ */
119
+ export function HandoffOfferChangeFilter(data: { payload: HandoffOfferEvent; context: HandoffSubscriptionContext | undefined }): boolean {
120
+ const connectionUserID = data.context?.userPayload?.userRecord?.ID;
121
+ if (!connectionUserID || !data.payload?.UserID) {
122
+ return false;
123
+ }
124
+ return UUIDsEqual(data.payload.UserID, connectionUserID);
125
+ }
126
+
127
+ /** Redis channel carrying replicated handoff offer updates between server instances. */
128
+ export const HANDOFF_OFFER_FANOUT_CHANNEL = 'handoff-offer-changes';
129
+
130
+ export interface HandoffOfferFanOutPayload {
131
+ UserID: string;
132
+ Kind: 'offered' | 'updated';
133
+ Offer: HandoffOfferView;
134
+ SourceServerId?: string;
135
+ }
136
+
137
+ export type HandoffOfferPublishHook = (payload: HandoffOfferFanOutPayload) => void;
138
+
139
+ let _handoffPublishHook: HandoffOfferPublishHook | undefined;
140
+
141
+ export function SetHandoffOfferPublishHook(hook?: HandoffOfferPublishHook): void {
142
+ _handoffPublishHook = hook;
143
+ }
144
+
145
+ export function ParseReplicatedHandoffOfferUpdate(raw: string, localServerId: string): HandoffOfferFanOutPayload | null {
146
+ let parsed: unknown;
147
+ try {
148
+ parsed = JSON.parse(raw);
149
+ } catch (err) {
150
+ LogError('Failed to parse replicated handoff offer update payload', undefined, err);
151
+ return null;
152
+ }
153
+ if (typeof parsed !== 'object' || parsed === null) {
154
+ return null;
155
+ }
156
+ const candidate = parsed as Record<string, unknown>;
157
+ if (typeof candidate.SourceServerId === 'string' && candidate.SourceServerId === localServerId) {
158
+ return null; // echo suppression
159
+ }
160
+ if (typeof candidate.UserID !== 'string' || typeof candidate.Kind !== 'string' || !candidate.Offer) {
161
+ return null;
162
+ }
163
+ const offer = candidate.Offer as Record<string, unknown>;
164
+ if (typeof offer.OfferID !== 'string' || typeof offer.RoomName !== 'string' || typeof offer.Status !== 'string') {
165
+ return null;
166
+ }
167
+ return {
168
+ UserID: candidate.UserID,
169
+ Kind: candidate.Kind as 'offered' | 'updated',
170
+ Offer: offer as unknown as HandoffOfferView,
171
+ SourceServerId: typeof candidate.SourceServerId === 'string' ? candidate.SourceServerId : undefined,
172
+ };
173
+ }
174
+
175
+ /** Publishes offer changes onto the GraphQL subscription topic and forwards across instances. */
176
+ export class PubSubHandoffPublisher implements IHandoffPublisher {
177
+ public Publish(event: HandoffOfferEvent): void {
178
+ PubSubManager.Instance.Publish(HANDOFF_OFFER_TOPIC, { UserID: event.UserID, Kind: event.Kind, Offer: event.Offer });
179
+ _handoffPublishHook?.({
180
+ UserID: event.UserID,
181
+ Kind: event.Kind,
182
+ Offer: event.Offer,
183
+ SourceServerId: MJGlobal.Instance.ProcessUUID,
184
+ });
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Tells the person about a new offer outside the live subscription, through the unified notification engine (in-app, and
190
+ * MJ Comms when the type is configured for it), using the dedicated "Conversation Handoff Offer" notification type.
191
+ * The `handoff-offer` resource configuration is what Explorer routes to the Conversation Console.
192
+ */
193
+ export class NotificationHandoffNotifier implements IHandoffNotifier {
194
+ public async NotifyOffer(offer: HandoffOfferView, targetUserID: string, contextUser: UserInfo, provider: IMetadataProvider): Promise<void> {
195
+ await NotificationEngine.Instance.Config(false, contextUser, provider);
196
+ const result = await NotificationEngine.Instance.SendNotification(
197
+ {
198
+ userId: targetUserID,
199
+ typeNameOrId: 'Conversation Handoff Offer',
200
+ title: `Incoming conversation: ${offer.CallerLabel}`,
201
+ message: `${offer.AgentName} is asking you to take over a conversation. ${offer.Summary}`,
202
+ resourceConfiguration: { type: 'handoff-offer', offerId: offer.OfferID, room: offer.RoomName },
203
+ },
204
+ contextUser,
205
+ );
206
+ if (!result.success) {
207
+ throw new Error(`the notification engine could not deliver it: ${(result.errors ?? []).join('; ') || 'unknown error'}`);
208
+ }
209
+ }
210
+ }
211
+
212
+ // The registry's background sweep and list queries run outside any request, so they need a server identity. Resolve the
213
+ // system user lazily: the user cache may not have loaded when this module does.
214
+ HandoffOfferRegistry.Instance.Configure({
215
+ ResolveContextUser: () => UserCache.Instance.GetSystemUser(),
216
+ });
217
+
218
+ /**
219
+ * Binds the handoff engine's collaborators that only the server host can supply (same module-load rationale as the other
220
+ * realtime bindings): the pub/sub publisher, the notification sender, and a room-presence check over the LiveKit credentials
221
+ * the Meet room already uses. Idempotent (latest-wins). The telephony extension adds the collaborators that need a carrier
222
+ * (dialing a number into a room, starting another agent).
223
+ */
224
+ RoomHandoffEngine.Instance.Configure({
225
+ Presence: new LiveKitSipService(),
226
+ Publisher: new PubSubHandoffPublisher(),
227
+ Notifier: new NotificationHandoffNotifier(),
228
+ });
229
+
230
+ @Resolver()
231
+ export class HumanHandoffResolver extends ResolverBase {
232
+ /** The signed-in user's offers: pending ones, plus ones that resolved recently enough to still be shown. */
233
+ @Query(() => [HandoffOffer])
234
+ async MyHandoffOffers(@Ctx() context: AppContext = {} as AppContext): Promise<HandoffOffer[]> {
235
+ const user = this.GetUserFromPayload(context.userPayload);
236
+ if (!user) {
237
+ return [];
238
+ }
239
+ const offers = await RoomHandoffEngine.Instance.ListOffersForUser(user.ID, user);
240
+ return offers.map(toGraphQLOffer);
241
+ }
242
+
243
+ /**
244
+ * Accepts an offer. The engine authorises it against the offer's target; a stranger's attempt and a missing offer answer
245
+ * identically. On success the console should join the room, and the AI leaves once the person is actually there.
246
+ */
247
+ @Mutation(() => AcceptHandoffOfferResult)
248
+ async AcceptHandoffOffer(
249
+ @Arg('offerID', () => String) offerID: string,
250
+ @Ctx() context: AppContext = {} as AppContext,
251
+ ): Promise<AcceptHandoffOfferResult> {
252
+ const failure = (message: string): AcceptHandoffOfferResult => ({ Success: false, ErrorMessage: message, RoomName: '' });
253
+ try {
254
+ const user = this.GetUserFromPayload(context.userPayload);
255
+ if (!user) {
256
+ return failure('Unable to determine current user.');
257
+ }
258
+ const result = await RoomHandoffEngine.Instance.AcceptOffer(offerID, user.ID, user);
259
+ if ('Reason' in result) {
260
+ return failure(result.Reason);
261
+ }
262
+ return { Success: true, RoomName: result.Offer.RoomName, Offer: toGraphQLOffer(result.Offer) };
263
+ } catch (error) {
264
+ LogError(`AcceptHandoffOffer failed: ${error instanceof Error ? error.message : String(error)}`);
265
+ return failure('The offer could not be accepted.');
266
+ }
267
+ }
268
+
269
+ /** Declines an offer, so the AI can fall back (the person's phone, or carrying on). */
270
+ @Mutation(() => DeclineHandoffOfferResult)
271
+ async DeclineHandoffOffer(
272
+ @Arg('offerID', () => String) offerID: string,
273
+ @Ctx() context: AppContext = {} as AppContext,
274
+ ): Promise<DeclineHandoffOfferResult> {
275
+ try {
276
+ const user = this.GetUserFromPayload(context.userPayload);
277
+ if (!user) {
278
+ return { Success: false, ErrorMessage: 'Unable to determine current user.' };
279
+ }
280
+ const result = await RoomHandoffEngine.Instance.DeclineOffer(offerID, user.ID, user);
281
+ return 'Reason' in result ? { Success: false, ErrorMessage: result.Reason } : { Success: true };
282
+ } catch (error) {
283
+ LogError(`DeclineHandoffOffer failed: ${error instanceof Error ? error.message : String(error)}`);
284
+ return { Success: false, ErrorMessage: 'The offer could not be declined.' };
285
+ }
286
+ }
287
+
288
+ /** Live changes to the signed-in user's offers (a new offer, or one that was accepted, declined, expired or cancelled). */
289
+ @Subscription(() => HandoffOfferChange, {
290
+ topics: HANDOFF_OFFER_TOPIC,
291
+ filter: (data: ResolverFilterData<HandoffOfferEvent, Record<string, never>, HandoffSubscriptionContext>) => HandoffOfferChangeFilter(data),
292
+ })
293
+ HandoffOfferChanges(@Root() payload: HandoffOfferEvent): HandoffOfferChange {
294
+ // UserID is a server-side delivery key and is intentionally not returned.
295
+ return { Kind: payload.Kind, Offer: toGraphQLOffer(payload.Offer) };
296
+ }
297
+ }
298
+
299
+ function toGraphQLOffer(offer: HandoffOfferView): HandoffOffer {
300
+ return {
301
+ OfferID: offer.OfferID,
302
+ RoomName: offer.RoomName,
303
+ Mode: offer.Mode,
304
+ Summary: offer.Summary,
305
+ CallerLabel: offer.CallerLabel,
306
+ AgentName: offer.AgentName,
307
+ Status: offer.Status,
308
+ CreatedAt: offer.CreatedAt,
309
+ ExpiresAt: offer.ExpiresAt,
310
+ InteractionID: offer.InteractionID ?? null,
311
+ };
312
+ }
@@ -639,11 +639,14 @@ export class MCPResolver extends ResolverBase {
639
639
  // Publish syncing progress
640
640
  this.publishProgress(pubSub, sessionId, user.ID, ConnectionID, 'syncing', 'Synchronizing tools to database...');
641
641
 
642
- // Perform the sync
643
- const syncResult: MCPSyncToolsResult = await manager.syncTools(ConnectionID, { contextUser: user });
644
-
645
- // Remove event listener
646
- manager.removeEventListener('toolsSynced', eventHandler);
642
+ // Perform the sync; always detach the listener, even if syncTools throws, so failed
643
+ // syncs don't stack handlers on the shared manager.
644
+ let syncResult: MCPSyncToolsResult;
645
+ try {
646
+ syncResult = await manager.syncTools(ConnectionID, { contextUser: user });
647
+ } finally {
648
+ manager.removeEventListener('toolsSynced', eventHandler);
649
+ }
647
650
 
648
651
  if (!syncResult.success) {
649
652
  this.publishProgress(pubSub, sessionId, user.ID, ConnectionID, 'error', `Sync failed: ${syncResult.error}`);