@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,448 @@
1
+ import 'reflect-metadata';
2
+
3
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
4
+ import type { IMetadataProvider, UserInfo } from '@memberjunction/core';
5
+ import type {
6
+ MJAIAgentSessionEntity,
7
+ MJMeetingEntity,
8
+ MJMeetingParticipantEntity,
9
+ MJPhoneNumberEntity,
10
+ MJInteractionEntity,
11
+ MJInteractionEventEntity,
12
+ } from '@memberjunction/core-entities';
13
+ import type { StartAgentRoomSessionParams } from '@memberjunction/livekit-room-server';
14
+
15
+ const mocks = vi.hoisted(() => ({
16
+ mintClientToken: vi.fn(async (roomName: string, identity: string, name?: string) => ({
17
+ Token: `token-for-${roomName}-${identity}`,
18
+ Identity: identity,
19
+ ServerUrl: 'wss://livekit.example.com',
20
+ })),
21
+ startAgentRoomSession: vi.fn(async (_params: StartAgentRoomSessionParams) => ({
22
+ SessionBridgeID: 'bridge-123',
23
+ RoomName: 'room-123',
24
+ })),
25
+ stopAllAgentsInRoom: vi.fn(async () => undefined),
26
+ startRoomRecording: vi.fn(async (params: { RoomName: string }) => ({
27
+ EgressID: 'egress-456',
28
+ RoomName: params.RoomName,
29
+ Status: 'EGRESS_STARTING',
30
+ })),
31
+ stopRecording: vi.fn(async (egressID: string) => ({
32
+ EgressID: egressID,
33
+ RoomName: 'room-123',
34
+ Status: 'EGRESS_COMPLETE',
35
+ })),
36
+ sendNotification: vi.fn(async () => ({ success: true })),
37
+ notificationConfig: vi.fn(async () => undefined),
38
+ createSession: vi.fn(async () => ({ ID: 'agent-session-789' })),
39
+ }));
40
+
41
+ vi.mock('@memberjunction/livekit-room-server', () => ({
42
+ LiveKitTokenService: class {
43
+ MintClientToken = mocks.mintClientToken;
44
+ },
45
+ LiveKitAgentRoomCoordinator: {
46
+ Instance: {
47
+ StartAgentRoomSession: mocks.startAgentRoomSession,
48
+ StopAllAgentsInRoom: mocks.stopAllAgentsInRoom,
49
+ },
50
+ },
51
+ LiveKitEgressService: class {
52
+ StartRoomRecording = mocks.startRoomRecording;
53
+ StopRecording = mocks.stopRecording;
54
+ },
55
+ LiveKitUserIdentity: (id: string) => `user_${id.toLowerCase()}`,
56
+ }));
57
+
58
+ vi.mock('@memberjunction/notifications', () => ({
59
+ NotificationEngine: {
60
+ Instance: {
61
+ Config: mocks.notificationConfig,
62
+ SendNotification: mocks.sendNotification,
63
+ },
64
+ },
65
+ }));
66
+
67
+ import {
68
+ MeetingResolver,
69
+ type CreateMeetingInput,
70
+ type UpdateMeetingInput,
71
+ type RSVPMeetingInput,
72
+ } from '../resolvers/MeetingResolver.js';
73
+ import type { AppContext } from '../types.js';
74
+ import type { SessionManager } from '../agentSessions/SessionManager.js';
75
+
76
+ class MockEntityBase {
77
+ public ID: string = `mock-${Date.now()}-${Math.random()}`;
78
+ public LatestResult?: { CompleteMessage?: string };
79
+ public async Save(): Promise<boolean> {
80
+ return true;
81
+ }
82
+ }
83
+
84
+ class MockMeetingEntity extends MockEntityBase {
85
+ public Title: string = '';
86
+ public Description: string | null = null;
87
+ public HostUserID: string = '';
88
+ public HostUser: string = 'Host User';
89
+ public RoomName: string = '';
90
+ public Status: MJMeetingEntity['Status'] = 'Scheduled';
91
+ public ScheduledStartAt: Date | null = null;
92
+ public ScheduledEndAt: Date | null = null;
93
+ public StartedAt: Date | null = null;
94
+ public EndedAt: Date | null = null;
95
+ public AllowPhoneDialIn: boolean = false;
96
+ public DialInPhoneNumberID: string | null = null;
97
+ public DialInCode: string | null = null;
98
+ public RecordingPolicy: MJMeetingEntity['RecordingPolicy'] = 'Off';
99
+ public ConversationID: string | null = null;
100
+ public __mj_CreatedAt: Date = new Date();
101
+ public __mj_UpdatedAt: Date = new Date();
102
+ }
103
+
104
+ class MockMeetingParticipantEntity extends MockEntityBase {
105
+ public MeetingID: string = '';
106
+ public UserID: string | null = null;
107
+ public User: string | null = null;
108
+ public AgentID: string | null = null;
109
+ public Agent: string | null = null;
110
+ public ExternalName: string | null = null;
111
+ public ExternalEmail: string | null = null;
112
+ public ExternalPhone: string | null = null;
113
+ public Role: MJMeetingParticipantEntity['Role'] = 'Attendee';
114
+ public InviteStatus: MJMeetingParticipantEntity['InviteStatus'] = 'Invited';
115
+ public JoinedAt: Date | null = null;
116
+ public LeftAt: Date | null = null;
117
+ }
118
+
119
+ class MockPhoneNumberEntity extends MockEntityBase {
120
+ public Number: string = '+15551234567';
121
+ public Status: MJPhoneNumberEntity['Status'] = 'Active';
122
+ public Label: string | null = 'Main Dial-In';
123
+ public __mj_CreatedAt: Date = new Date();
124
+ }
125
+
126
+ class MockInteractionEntity extends MockEntityBase {
127
+ public Channel: MJInteractionEntity['Channel'] = 'Meeting';
128
+ public Direction: MJInteractionEntity['Direction'] = 'Inbound';
129
+ public Status: MJInteractionEntity['Status'] = 'Active';
130
+ public RoomName: string | null = null;
131
+ public StartedAt: Date = new Date();
132
+ public AnsweredAt: Date | null = new Date();
133
+ public EndedAt: Date | null = null;
134
+ public RecordingEnabled: boolean = false;
135
+ }
136
+
137
+ class MockInteractionEventEntity extends MockEntityBase {
138
+ public InteractionID: string = '';
139
+ public EventType: MJInteractionEventEntity['EventType'] = 'Created';
140
+ public ActorUserID: string | null = null;
141
+ public OccurredAt: Date = new Date();
142
+ public Details: string | null = null;
143
+ }
144
+
145
+ class TestableMeetingResolver extends MeetingResolver {
146
+ public user: UserInfo | undefined = { ID: 'user-host-1', Name: 'Alice Host', Email: 'alice@example.com' } as unknown as UserInfo;
147
+
148
+ public mockMeetings: MockMeetingEntity[] = [];
149
+ public mockParticipants: MockMeetingParticipantEntity[] = [];
150
+ public mockPhoneNumbers: MockPhoneNumberEntity[] = [];
151
+ public mockInteractions: MockInteractionEntity[] = [];
152
+ public mockEvents: MockInteractionEventEntity[] = [];
153
+
154
+ protected override GetUserFromPayload(): UserInfo | undefined {
155
+ return this.user;
156
+ }
157
+
158
+ public getMockProvider(): IMetadataProvider {
159
+ return {
160
+ RunView: async () => ({ Success: true, Results: [] }),
161
+ GetEntityObject: async <T>(entityName: string) => {
162
+ if (entityName === 'MJ: Meetings') {
163
+ const m = new MockMeetingEntity() as unknown as T;
164
+ this.mockMeetings.push(m as unknown as MockMeetingEntity);
165
+ return m;
166
+ }
167
+ if (entityName === 'MJ: Meeting Participants') {
168
+ const p = new MockMeetingParticipantEntity() as unknown as T;
169
+ this.mockParticipants.push(p as unknown as MockMeetingParticipantEntity);
170
+ return p;
171
+ }
172
+ if (entityName === 'MJ: Interactions') {
173
+ const i = new MockInteractionEntity() as unknown as T;
174
+ this.mockInteractions.push(i as unknown as MockInteractionEntity);
175
+ return i;
176
+ }
177
+ if (entityName === 'MJ: Interaction Events') {
178
+ const e = new MockInteractionEventEntity() as unknown as T;
179
+ this.mockEvents.push(e as unknown as MockInteractionEventEntity);
180
+ return e;
181
+ }
182
+ throw new Error(`Unknown entity: ${entityName}`);
183
+ },
184
+ } as unknown as IMetadataProvider;
185
+ }
186
+ }
187
+
188
+ describe('MeetingResolver', () => {
189
+ let resolver: TestableMeetingResolver;
190
+ let mockProvider: IMetadataProvider;
191
+ let ctx: AppContext;
192
+
193
+ beforeEach(() => {
194
+ resolver = new TestableMeetingResolver();
195
+ mockProvider = resolver.getMockProvider();
196
+ ctx = {
197
+ providers: [{ type: 'Read-Write', provider: mockProvider }],
198
+ } as unknown as AppContext;
199
+ mocks.mintClientToken.mockClear();
200
+ mocks.startAgentRoomSession.mockClear();
201
+ mocks.stopAllAgentsInRoom.mockClear();
202
+ mocks.startRoomRecording.mockClear();
203
+ mocks.sendNotification.mockClear();
204
+ });
205
+
206
+ describe('CreateMeeting', () => {
207
+ it('creates a scheduled meeting with generated unguessable room name and adds host participant', async () => {
208
+ const input: CreateMeetingInput = {
209
+ Title: 'Sprint Planning',
210
+ Description: 'Bi-weekly sprint planning meeting',
211
+ ScheduledStartAt: new Date(Date.now() + 3600000),
212
+ ScheduledEndAt: new Date(Date.now() + 7200000),
213
+ Participants: [
214
+ { UserID: 'user-guest-2', Role: 'Attendee' },
215
+ { AgentID: 'agent-bot-1', Role: 'Agent' },
216
+ ],
217
+ };
218
+
219
+ const result = await resolver.CreateMeeting(input, ctx);
220
+ expect(result.Success).toBe(true);
221
+ expect(result.Meeting).toBeDefined();
222
+ expect(result.Meeting?.Title).toBe('Sprint Planning');
223
+ expect(result.Meeting?.RoomName).toMatch(/^mj-mtg-[a-f0-9-]+$/);
224
+ expect(result.Meeting?.Status).toBe('Scheduled');
225
+ expect(result.Meeting?.HostUserID).toBe('user-host-1');
226
+
227
+ // Verify participants were created: host + 2 invitees
228
+ expect(resolver.mockParticipants.length).toBe(3);
229
+ const hostPart = resolver.mockParticipants.find((p) => p.UserID === 'user-host-1');
230
+ expect(hostPart).toBeDefined();
231
+ expect(hostPart?.Role).toBe('Host');
232
+ expect(hostPart?.InviteStatus).toBe('Accepted');
233
+
234
+ const agentPart = resolver.mockParticipants.find((p) => p.AgentID === 'agent-bot-1');
235
+ expect(agentPart).toBeDefined();
236
+ expect(agentPart?.Role).toBe('Agent');
237
+
238
+ // Notification sent to invited user
239
+ expect(mocks.sendNotification).toHaveBeenCalled();
240
+ });
241
+
242
+ it('validates required title', async () => {
243
+ const result = await resolver.CreateMeeting({ Title: ' ' }, ctx);
244
+ expect(result.Success).toBe(false);
245
+ expect(result.ErrorMessage).toContain('title is required');
246
+ });
247
+
248
+ it('validates scheduled end time is after scheduled start time', async () => {
249
+ const start = new Date(Date.now() + 7200000);
250
+ const end = new Date(Date.now() + 3600000);
251
+ const result = await resolver.CreateMeeting({ Title: 'Invalid Times', ScheduledStartAt: start, ScheduledEndAt: end }, ctx);
252
+ expect(result.Success).toBe(false);
253
+ expect(result.ErrorMessage).toContain('must be after');
254
+ });
255
+ });
256
+
257
+ describe('UpdateMeeting authorization and validation', () => {
258
+ it('refuses update from non-host/co-host users', async () => {
259
+ // Mock existing meeting where HostUserID is different
260
+ const m = new MockMeetingEntity();
261
+ m.ID = 'mtg-existing-1';
262
+ m.HostUserID = 'other-user';
263
+ m.Title = 'Existing';
264
+ resolver.mockMeetings.push(m);
265
+
266
+ // Spy on loadMeetingEntity and isUserHostOrCoHost
267
+ vi.spyOn(resolver as unknown as { loadMeetingEntity: Function }, 'loadMeetingEntity').mockResolvedValue(m);
268
+ vi.spyOn(resolver as unknown as { isUserHostOrCoHost: Function }, 'isUserHostOrCoHost').mockResolvedValue(false);
269
+
270
+ const updateInput: UpdateMeetingInput = {
271
+ MeetingID: 'mtg-existing-1',
272
+ Title: 'Hacked Title',
273
+ };
274
+
275
+ const result = await resolver.UpdateMeeting(updateInput, ctx);
276
+ expect(result.Success).toBe(false);
277
+ expect(result.ErrorMessage).toContain('Unauthorized');
278
+ });
279
+
280
+ it('allows host to update title and details', async () => {
281
+ const m = new MockMeetingEntity();
282
+ m.ID = 'mtg-existing-1';
283
+ m.HostUserID = 'user-host-1';
284
+ m.Title = 'Old Title';
285
+ resolver.mockMeetings.push(m);
286
+
287
+ vi.spyOn(resolver as unknown as { loadMeetingEntity: Function }, 'loadMeetingEntity').mockResolvedValue(m);
288
+ vi.spyOn(resolver as unknown as { isUserHostOrCoHost: Function }, 'isUserHostOrCoHost').mockResolvedValue(true);
289
+ vi.spyOn(resolver as unknown as { loadParticipants: Function }, 'loadParticipants').mockResolvedValue([]);
290
+
291
+ const updateInput: UpdateMeetingInput = {
292
+ MeetingID: 'mtg-existing-1',
293
+ Title: 'Updated Title',
294
+ Description: 'New agenda',
295
+ };
296
+
297
+ const result = await resolver.UpdateMeeting(updateInput, ctx);
298
+ expect(result.Success).toBe(true);
299
+ expect(m.Title).toBe('Updated Title');
300
+ expect(m.Description).toBe('New agenda');
301
+ });
302
+ });
303
+
304
+ describe('StartMeeting and EndMeeting lifecycle', () => {
305
+ it('starts meeting, creates interaction, spins up agent participants, and mints token', async () => {
306
+ const m = new MockMeetingEntity();
307
+ m.ID = 'mtg-live-1';
308
+ m.HostUserID = 'user-host-1';
309
+ m.Title = 'Team Standup';
310
+ m.RoomName = 'mj-mtg-standup-1';
311
+ m.Status = 'Scheduled';
312
+ m.RecordingPolicy = 'Automatic';
313
+ resolver.mockMeetings.push(m);
314
+
315
+ const agentPart = new MockMeetingParticipantEntity();
316
+ agentPart.Role = 'Agent';
317
+ agentPart.AgentID = 'agent-co-1';
318
+
319
+ vi.spyOn(resolver as unknown as { loadMeetingEntity: Function }, 'loadMeetingEntity').mockResolvedValue(m);
320
+ vi.spyOn(resolver as unknown as { isUserHostOrCoHost: Function }, 'isUserHostOrCoHost').mockResolvedValue(true);
321
+ vi.spyOn(resolver as unknown as { loadParticipants: Function }, 'loadParticipants').mockResolvedValue([
322
+ { ID: 'p-1', MeetingID: m.ID, Role: 'Agent', AgentID: 'agent-co-1', InviteStatus: 'Accepted' },
323
+ ]);
324
+ vi.spyOn((resolver as unknown as { sessionManager: { CreateSession: Function } }).sessionManager, 'CreateSession').mockResolvedValue({
325
+ ID: 'agent-session-789',
326
+ });
327
+
328
+ const result = await resolver.StartMeeting(m.ID, ctx);
329
+ expect(result.Success).toBe(true);
330
+ expect(result.RoomName).toBe('mj-mtg-standup-1');
331
+ expect(result.ClientToken).toBeDefined();
332
+ expect(m.Status).toBe('Live');
333
+ expect(m.StartedAt).toBeDefined();
334
+
335
+ // Check agent session coordinator was called
336
+ expect(mocks.startAgentRoomSession).toHaveBeenCalledWith(
337
+ expect.objectContaining({
338
+ RoomName: 'mj-mtg-standup-1',
339
+ AgentID: 'agent-co-1',
340
+ }),
341
+ );
342
+
343
+ // Check automatic recording initiated
344
+ expect(mocks.startRoomRecording).toHaveBeenCalledWith({ RoomName: 'mj-mtg-standup-1' });
345
+
346
+ // Check client token minted
347
+ expect(mocks.mintClientToken).toHaveBeenCalled();
348
+ });
349
+
350
+ it('ends meeting, stops agents in room, and marks status Ended', async () => {
351
+ const m = new MockMeetingEntity();
352
+ m.ID = 'mtg-live-1';
353
+ m.HostUserID = 'user-host-1';
354
+ m.RoomName = 'mj-mtg-standup-1';
355
+ m.Status = 'Live';
356
+ resolver.mockMeetings.push(m);
357
+
358
+ vi.spyOn(resolver as unknown as { loadMeetingEntity: Function }, 'loadMeetingEntity').mockResolvedValue(m);
359
+ vi.spyOn(resolver as unknown as { isUserHostOrCoHost: Function }, 'isUserHostOrCoHost').mockResolvedValue(true);
360
+ vi.spyOn(resolver as unknown as { loadParticipants: Function }, 'loadParticipants').mockResolvedValue([]);
361
+
362
+ const result = await resolver.EndMeeting(m.ID, ctx);
363
+ expect(result.Success).toBe(true);
364
+ expect(m.Status).toBe('Ended');
365
+ expect(m.EndedAt).toBeDefined();
366
+ expect(mocks.stopAllAgentsInRoom).toHaveBeenCalledWith('mj-mtg-standup-1', 'Explicit', resolver.user, mockProvider);
367
+ });
368
+
369
+ it("closes an agent participant's session when its agent leaves the room (#5356)", async () => {
370
+ const m = new MockMeetingEntity();
371
+ m.ID = 'mtg-live-2';
372
+ m.HostUserID = 'user-host-1';
373
+ m.RoomName = 'mj-mtg-standup-2';
374
+ m.Status = 'Scheduled';
375
+ resolver.mockMeetings.push(m);
376
+
377
+ // The resolver's protected seams this test stands in for.
378
+ const seams = resolver as unknown as {
379
+ loadMeetingEntity: () => Promise<MockMeetingEntity>;
380
+ isUserHostOrCoHost: () => Promise<boolean>;
381
+ loadParticipants: () => Promise<object[]>;
382
+ sessionManager: SessionManager;
383
+ };
384
+ vi.spyOn(seams, 'loadMeetingEntity').mockResolvedValue(m);
385
+ vi.spyOn(seams, 'isUserHostOrCoHost').mockResolvedValue(true);
386
+ vi.spyOn(seams, 'loadParticipants').mockResolvedValue([
387
+ { ID: 'p-1', MeetingID: m.ID, Role: 'Agent', AgentID: 'agent-co-1', InviteStatus: 'Accepted' },
388
+ ]);
389
+ vi.spyOn(seams.sessionManager, 'CreateSession').mockResolvedValue({ ID: 'agent-session-789' } as unknown as MJAIAgentSessionEntity);
390
+ const closeSession = vi.spyOn(seams.sessionManager, 'CloseSession').mockResolvedValue(true);
391
+
392
+ await resolver.StartMeeting(m.ID, ctx);
393
+ const started = mocks.startAgentRoomSession.mock.calls[0][0];
394
+ expect(started.AgentSessionID).toBe('agent-session-789');
395
+ expect(closeSession).not.toHaveBeenCalled();
396
+
397
+ // The agent leaves (the meeting was ended, or everyone left): the coordinator runs the hook once its bridge has ended.
398
+ await started.Host?.OnSessionEnded?.('Explicit');
399
+
400
+ expect(closeSession).toHaveBeenCalledWith('agent-session-789', resolver.user, mockProvider, 'Explicit');
401
+ });
402
+
403
+ it("closes an agent participant's session at once, as Error, when its agent fails to start (#5308)", async () => {
404
+ const m = new MockMeetingEntity();
405
+ m.ID = 'mtg-live-3';
406
+ m.HostUserID = 'user-host-1';
407
+ m.RoomName = 'mj-mtg-standup-3';
408
+ m.Status = 'Scheduled';
409
+ resolver.mockMeetings.push(m);
410
+
411
+ // The resolver's protected seams this test stands in for.
412
+ const seams = resolver as unknown as {
413
+ loadMeetingEntity: () => Promise<MockMeetingEntity>;
414
+ isUserHostOrCoHost: () => Promise<boolean>;
415
+ loadParticipants: () => Promise<object[]>;
416
+ sessionManager: SessionManager;
417
+ };
418
+ vi.spyOn(seams, 'loadMeetingEntity').mockResolvedValue(m);
419
+ vi.spyOn(seams, 'isUserHostOrCoHost').mockResolvedValue(true);
420
+ vi.spyOn(seams, 'loadParticipants').mockResolvedValue([
421
+ { ID: 'p-1', MeetingID: m.ID, Role: 'Agent', AgentID: 'agent-fails', InviteStatus: 'Accepted' },
422
+ { ID: 'p-2', MeetingID: m.ID, Role: 'Agent', AgentID: 'agent-joins', InviteStatus: 'Accepted' },
423
+ ]);
424
+ vi.spyOn(seams.sessionManager, 'CreateSession')
425
+ .mockResolvedValueOnce({ ID: 'agent-session-fails' } as unknown as MJAIAgentSessionEntity)
426
+ .mockResolvedValueOnce({ ID: 'agent-session-joins' } as unknown as MJAIAgentSessionEntity);
427
+ const closeSession = vi.spyOn(seams.sessionManager, 'CloseSession').mockResolvedValue(true);
428
+ // The first agent's bridge can't start (the coordinator has closed its model session by the time this throws).
429
+ mocks.startAgentRoomSession.mockRejectedValueOnce(new Error('Failed to create AIAgentSessionBridge: permission denied'));
430
+
431
+ const result = await resolver.StartMeeting(m.ID, ctx);
432
+
433
+ // The meeting still starts, with the agent that joined; only the failed agent's session is closed.
434
+ expect(result.Success).toBe(true);
435
+ expect(mocks.startAgentRoomSession).toHaveBeenCalledTimes(2);
436
+ expect(closeSession).toHaveBeenCalledTimes(1);
437
+ expect(closeSession).toHaveBeenCalledWith('agent-session-fails', resolver.user, mockProvider, 'Error');
438
+ });
439
+ });
440
+
441
+ describe('RSVPMeeting', () => {
442
+ it('validates RSVP response values', async () => {
443
+ const result = await resolver.RSVPMeeting({ MeetingID: 'mtg-1', InviteStatus: 'Maybe' }, ctx);
444
+ expect(result.Success).toBe(false);
445
+ expect(result.ErrorMessage).toContain('Invalid RSVP status');
446
+ });
447
+ });
448
+ });