@memberjunction/server 6.2.0-edge.3 → 6.2.0-edge.5

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 (543) hide show
  1. package/README.md +20 -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 +236 -27
  15. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  16. package/dist/agentSessions/SessionJanitor.js +682 -54
  17. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  18. package/dist/agentSessions/SessionManager.d.ts +48 -3
  19. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  20. package/dist/agentSessions/SessionManager.js +112 -9
  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/apiRoot.d.ts +32 -0
  31. package/dist/apiRoot.d.ts.map +1 -0
  32. package/dist/apiRoot.js +67 -0
  33. package/dist/apiRoot.js.map +1 -0
  34. package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
  35. package/dist/auth/AuthProviderCatalogRouter.js +25 -0
  36. package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
  37. package/dist/auth/LoginScreenEngine.d.ts +22 -0
  38. package/dist/auth/LoginScreenEngine.d.ts.map +1 -0
  39. package/dist/auth/LoginScreenEngine.js +57 -0
  40. package/dist/auth/LoginScreenEngine.js.map +1 -0
  41. package/dist/auth/actionAuthorization.d.ts +40 -0
  42. package/dist/auth/actionAuthorization.d.ts.map +1 -0
  43. package/dist/auth/actionAuthorization.js +94 -0
  44. package/dist/auth/actionAuthorization.js.map +1 -0
  45. package/dist/auth/index.d.ts +1 -0
  46. package/dist/auth/index.d.ts.map +1 -1
  47. package/dist/auth/index.js +4 -10
  48. package/dist/auth/index.js.map +1 -1
  49. package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
  50. package/dist/auth/magicLink/MagicLinkRouter.js +3 -2
  51. package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
  52. package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
  53. package/dist/auth/magicLink/MagicLinkService.js +6 -3
  54. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  55. package/dist/auth/newUsers.d.ts +10 -0
  56. package/dist/auth/newUsers.d.ts.map +1 -1
  57. package/dist/auth/newUsers.js +80 -11
  58. package/dist/auth/newUsers.js.map +1 -1
  59. package/dist/config.d.ts +2514 -22
  60. package/dist/config.d.ts.map +1 -1
  61. package/dist/config.js +166 -4
  62. package/dist/config.js.map +1 -1
  63. package/dist/context.d.ts +8 -0
  64. package/dist/context.d.ts.map +1 -1
  65. package/dist/context.js +14 -11
  66. package/dist/context.js.map +1 -1
  67. package/dist/coreRoutes.d.ts +29 -0
  68. package/dist/coreRoutes.d.ts.map +1 -0
  69. package/dist/coreRoutes.js +142 -0
  70. package/dist/coreRoutes.js.map +1 -0
  71. package/dist/generated/graphql-schemas/__mj.d.ts +504 -3
  72. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  73. package/dist/generated/graphql-schemas/__mj.js +2456 -7
  74. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  75. package/dist/generic/CacheInvalidationResolver.d.ts +43 -8
  76. package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
  77. package/dist/generic/CacheInvalidationResolver.js +59 -19
  78. package/dist/generic/CacheInvalidationResolver.js.map +1 -1
  79. package/dist/generic/OrphanedConversationDetailReconciler.js +3 -3
  80. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
  81. package/dist/generic/PushStatusResolver.js +1 -1
  82. package/dist/generic/PushStatusResolver.js.map +1 -1
  83. package/dist/generic/ResolverBase.d.ts +123 -48
  84. package/dist/generic/ResolverBase.d.ts.map +1 -1
  85. package/dist/generic/ResolverBase.js +293 -305
  86. package/dist/generic/ResolverBase.js.map +1 -1
  87. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  88. package/dist/generic/RunViewResolver.js +16 -0
  89. package/dist/generic/RunViewResolver.js.map +1 -1
  90. package/dist/globalCors.d.ts +33 -0
  91. package/dist/globalCors.d.ts.map +1 -0
  92. package/dist/globalCors.js +58 -0
  93. package/dist/globalCors.js.map +1 -0
  94. package/dist/index.d.ts +17 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +219 -278
  97. package/dist/index.js.map +1 -1
  98. package/dist/isolatedProvider.d.ts +20 -0
  99. package/dist/isolatedProvider.d.ts.map +1 -0
  100. package/dist/isolatedProvider.js +22 -0
  101. package/dist/isolatedProvider.js.map +1 -0
  102. package/dist/multiTenancy/index.d.ts.map +1 -1
  103. package/dist/multiTenancy/index.js +22 -2
  104. package/dist/multiTenancy/index.js.map +1 -1
  105. package/dist/realtimeProxy/RealtimeProxyServer.d.ts +44 -4
  106. package/dist/realtimeProxy/RealtimeProxyServer.d.ts.map +1 -1
  107. package/dist/realtimeProxy/RealtimeProxyServer.js +121 -16
  108. package/dist/realtimeProxy/RealtimeProxyServer.js.map +1 -1
  109. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts +171 -0
  110. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts.map +1 -0
  111. package/dist/realtimeProxy/RealtimeRelayTunnel.js +532 -0
  112. package/dist/realtimeProxy/RealtimeRelayTunnel.js.map +1 -0
  113. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts +148 -0
  114. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts.map +1 -0
  115. package/dist/realtimeSessions/RealtimeSessionEventService.js +191 -0
  116. package/dist/realtimeSessions/RealtimeSessionEventService.js.map +1 -0
  117. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts +66 -0
  118. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -0
  119. package/dist/realtimeSessions/RealtimeSessionVerificationService.js +139 -0
  120. package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -0
  121. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts +38 -0
  122. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -0
  123. package/dist/realtimeSessions/RealtimeVerifyRouter.js +99 -0
  124. package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -0
  125. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts +100 -0
  126. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts.map +1 -0
  127. package/dist/realtimeSessions/RecordingAssemblyScheduler.js +173 -0
  128. package/dist/realtimeSessions/RecordingAssemblyScheduler.js.map +1 -0
  129. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts +61 -0
  130. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -0
  131. package/dist/realtimeSessions/SessionVerificationPortsBase.js +149 -0
  132. package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -0
  133. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts +57 -0
  134. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts.map +1 -0
  135. package/dist/realtimeSessions/SlidingWindowRateLimiter.js +69 -0
  136. package/dist/realtimeSessions/SlidingWindowRateLimiter.js.map +1 -0
  137. package/dist/realtimeSessions/index.d.ts +19 -0
  138. package/dist/realtimeSessions/index.d.ts.map +1 -0
  139. package/dist/realtimeSessions/index.js +19 -0
  140. package/dist/realtimeSessions/index.js.map +1 -0
  141. package/dist/realtimeSessions/ownedRealtimeSession.d.ts +30 -0
  142. package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -0
  143. package/dist/realtimeSessions/ownedRealtimeSession.js +47 -0
  144. package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -0
  145. package/dist/realtimeSessions/sessionAccess.d.ts +92 -0
  146. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -0
  147. package/dist/realtimeSessions/sessionAccess.js +94 -0
  148. package/dist/realtimeSessions/sessionAccess.js.map +1 -0
  149. package/dist/realtimeSessions/sessionConfigStamps.d.ts +70 -0
  150. package/dist/realtimeSessions/sessionConfigStamps.d.ts.map +1 -0
  151. package/dist/realtimeSessions/sessionConfigStamps.js +93 -0
  152. package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -0
  153. package/dist/realtimeSessions/subscriptionAuthorization.d.ts +65 -0
  154. package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -0
  155. package/dist/realtimeSessions/subscriptionAuthorization.js +71 -0
  156. package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -0
  157. package/dist/realtimeSessions/verificationCore.d.ts +243 -0
  158. package/dist/realtimeSessions/verificationCore.d.ts.map +1 -0
  159. package/dist/realtimeSessions/verificationCore.js +356 -0
  160. package/dist/realtimeSessions/verificationCore.js.map +1 -0
  161. package/dist/realtimeSessions/verificationPages.d.ts +66 -0
  162. package/dist/realtimeSessions/verificationPages.d.ts.map +1 -0
  163. package/dist/realtimeSessions/verificationPages.js +110 -0
  164. package/dist/realtimeSessions/verificationPages.js.map +1 -0
  165. package/dist/realtimeSessions/verificationPolicy.d.ts +147 -0
  166. package/dist/realtimeSessions/verificationPolicy.d.ts.map +1 -0
  167. package/dist/realtimeSessions/verificationPolicy.js +249 -0
  168. package/dist/realtimeSessions/verificationPolicy.js.map +1 -0
  169. package/dist/realtimeSessions/verificationWorkflow.d.ts +263 -0
  170. package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -0
  171. package/dist/realtimeSessions/verificationWorkflow.js +435 -0
  172. package/dist/realtimeSessions/verificationWorkflow.js.map +1 -0
  173. package/dist/realtimeWidget/widgetGuestElevation.d.ts +20 -2
  174. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  175. package/dist/realtimeWidget/widgetGuestElevation.js +31 -2
  176. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  177. package/dist/resolvers/ActionResolver.d.ts +31 -5
  178. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  179. package/dist/resolvers/ActionResolver.js +75 -14
  180. package/dist/resolvers/ActionResolver.js.map +1 -1
  181. package/dist/resolvers/AdhocQueryResolver.d.ts +14 -1
  182. package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
  183. package/dist/resolvers/AdhocQueryResolver.js +21 -5
  184. package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
  185. package/dist/resolvers/ArtifactFileResolver.d.ts +5 -1
  186. package/dist/resolvers/ArtifactFileResolver.d.ts.map +1 -1
  187. package/dist/resolvers/ArtifactFileResolver.js +9 -7
  188. package/dist/resolvers/ArtifactFileResolver.js.map +1 -1
  189. package/dist/resolvers/CacheStatsResolver.d.ts +27 -0
  190. package/dist/resolvers/CacheStatsResolver.d.ts.map +1 -1
  191. package/dist/resolvers/CacheStatsResolver.js +113 -2
  192. package/dist/resolvers/CacheStatsResolver.js.map +1 -1
  193. package/dist/resolvers/ClientToolRequestResolver.d.ts +4 -2
  194. package/dist/resolvers/ClientToolRequestResolver.d.ts.map +1 -1
  195. package/dist/resolvers/ClientToolRequestResolver.js +28 -10
  196. package/dist/resolvers/ClientToolRequestResolver.js.map +1 -1
  197. package/dist/resolvers/ConversationRunEventsResolver.d.ts +8 -4
  198. package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
  199. package/dist/resolvers/ConversationRunEventsResolver.js +6 -6
  200. package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
  201. package/dist/resolvers/DatasetResolver.d.ts +24 -3
  202. package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
  203. package/dist/resolvers/DatasetResolver.js +57 -8
  204. package/dist/resolvers/DatasetResolver.js.map +1 -1
  205. package/dist/resolvers/EntityRecordNameResolver.d.ts +2 -1
  206. package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
  207. package/dist/resolvers/EntityRecordNameResolver.js +3 -2
  208. package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
  209. package/dist/resolvers/FetchEntityVectorsResolver.d.ts +27 -1
  210. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  211. package/dist/resolvers/FetchEntityVectorsResolver.js +148 -2
  212. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  213. package/dist/resolvers/FileResolver.d.ts +82 -11
  214. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  215. package/dist/resolvers/FileResolver.js +279 -101
  216. package/dist/resolvers/FileResolver.js.map +1 -1
  217. package/dist/resolvers/GetDataContextDataResolver.d.ts +33 -7
  218. package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
  219. package/dist/resolvers/GetDataContextDataResolver.js +117 -38
  220. package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
  221. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  222. package/dist/resolvers/GetDataResolver.js +6 -3
  223. package/dist/resolvers/GetDataResolver.js.map +1 -1
  224. package/dist/resolvers/HumanHandoffResolver.d.ts.map +1 -1
  225. package/dist/resolvers/HumanHandoffResolver.js +7 -1
  226. package/dist/resolvers/HumanHandoffResolver.js.map +1 -1
  227. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  228. package/dist/resolvers/IntegrationDiscoveryResolver.js +4 -2
  229. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  230. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  231. package/dist/resolvers/MCPResolver.js +9 -4
  232. package/dist/resolvers/MCPResolver.js.map +1 -1
  233. package/dist/resolvers/QueryResolver.d.ts +2 -0
  234. package/dist/resolvers/QueryResolver.d.ts.map +1 -1
  235. package/dist/resolvers/QueryResolver.js +13 -0
  236. package/dist/resolvers/QueryResolver.js.map +1 -1
  237. package/dist/resolvers/RealtimeBridgeResolver.d.ts +54 -2
  238. package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
  239. package/dist/resolvers/RealtimeBridgeResolver.js +155 -10
  240. package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
  241. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +157 -33
  242. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  243. package/dist/resolvers/RealtimeClientSessionResolver.js +404 -116
  244. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  245. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts +61 -0
  246. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts.map +1 -0
  247. package/dist/resolvers/RealtimeSessionEventsResolver.js +130 -0
  248. package/dist/resolvers/RealtimeSessionEventsResolver.js.map +1 -0
  249. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts +85 -0
  250. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts.map +1 -0
  251. package/dist/resolvers/RealtimeSessionVerificationResolver.js +188 -0
  252. package/dist/resolvers/RealtimeSessionVerificationResolver.js.map +1 -0
  253. package/dist/resolvers/RemoteBrowserActionResolver.d.ts +2 -0
  254. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  255. package/dist/resolvers/RemoteBrowserActionResolver.js +5 -1
  256. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  257. package/dist/resolvers/RunAIAgentResolver.d.ts +10 -0
  258. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  259. package/dist/resolvers/RunAIAgentResolver.js +100 -14
  260. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  261. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  262. package/dist/resolvers/RunTemplateResolver.js +12 -11
  263. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  264. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts +12 -1
  265. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts.map +1 -1
  266. package/dist/resolvers/SearchKnowledgeStreamResolver.js +15 -2
  267. package/dist/resolvers/SearchKnowledgeStreamResolver.js.map +1 -1
  268. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  269. package/dist/resolvers/SqlLoggingConfigResolver.js +2 -3
  270. package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
  271. package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
  272. package/dist/resolvers/SyncDataResolver.js +6 -2
  273. package/dist/resolvers/SyncDataResolver.js.map +1 -1
  274. package/dist/resolvers/SyncRolesUsersResolver.d.ts +2 -0
  275. package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
  276. package/dist/resolvers/SyncRolesUsersResolver.js +23 -6
  277. package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
  278. package/dist/resolvers/TaskGraphFrameResolver.d.ts +2 -1
  279. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
  280. package/dist/resolvers/TaskGraphFrameResolver.js +28 -1
  281. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
  282. package/dist/resolvers/TestQuerySQLResolver.d.ts +24 -0
  283. package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
  284. package/dist/resolvers/TestQuerySQLResolver.js +65 -13
  285. package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
  286. package/dist/resolvers/TransactionGroupResolver.d.ts +19 -2
  287. package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
  288. package/dist/resolvers/TransactionGroupResolver.js +102 -24
  289. package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
  290. package/dist/resolvers/UserAvatarResolver.d.ts +16 -0
  291. package/dist/resolvers/UserAvatarResolver.d.ts.map +1 -0
  292. package/dist/resolvers/UserAvatarResolver.js +124 -0
  293. package/dist/resolvers/UserAvatarResolver.js.map +1 -0
  294. package/dist/resolvers/UserResolver.d.ts.map +1 -1
  295. package/dist/resolvers/UserResolver.js +2 -17
  296. package/dist/resolvers/UserResolver.js.map +1 -1
  297. package/dist/resolvers/agent-run-data-guard.d.ts +31 -0
  298. package/dist/resolvers/agent-run-data-guard.d.ts.map +1 -0
  299. package/dist/resolvers/agent-run-data-guard.js +72 -0
  300. package/dist/resolvers/agent-run-data-guard.js.map +1 -0
  301. package/dist/resolvers/agentVisionConsentAudit.d.ts +37 -0
  302. package/dist/resolvers/agentVisionConsentAudit.d.ts.map +1 -0
  303. package/dist/resolvers/agentVisionConsentAudit.js +63 -0
  304. package/dist/resolvers/agentVisionConsentAudit.js.map +1 -0
  305. package/dist/resolvers/avatarInputValidation.d.ts +40 -0
  306. package/dist/resolvers/avatarInputValidation.d.ts.map +1 -0
  307. package/dist/resolvers/avatarInputValidation.js +97 -0
  308. package/dist/resolvers/avatarInputValidation.js.map +1 -0
  309. package/dist/resolvers/currentUserRoles.d.ts +29 -0
  310. package/dist/resolvers/currentUserRoles.d.ts.map +1 -1
  311. package/dist/resolvers/currentUserRoles.js +30 -0
  312. package/dist/resolvers/currentUserRoles.js.map +1 -1
  313. package/dist/resolvers/meetings/meetingMutations.d.ts +6 -0
  314. package/dist/resolvers/meetings/meetingMutations.d.ts.map +1 -1
  315. package/dist/resolvers/meetings/meetingMutations.js +21 -0
  316. package/dist/resolvers/meetings/meetingMutations.js.map +1 -1
  317. package/dist/rest/RealtimeRecordingHandler.d.ts +49 -0
  318. package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -0
  319. package/dist/rest/RealtimeRecordingHandler.js +383 -0
  320. package/dist/rest/RealtimeRecordingHandler.js.map +1 -0
  321. package/dist/rest/ViewOperationsHandler.d.ts +3 -1
  322. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  323. package/dist/rest/ViewOperationsHandler.js +21 -12
  324. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  325. package/dist/rest/setupRESTEndpoints.d.ts +6 -0
  326. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  327. package/dist/rest/setupRESTEndpoints.js +6 -0
  328. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  329. package/dist/serverExtensionReservedRoots.d.ts +12 -10
  330. package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
  331. package/dist/serverExtensionReservedRoots.js +14 -17
  332. package/dist/serverExtensionReservedRoots.js.map +1 -1
  333. package/dist/services/MJStorageBlobStore.d.ts +8 -1
  334. package/dist/services/MJStorageBlobStore.d.ts.map +1 -1
  335. package/dist/services/MJStorageBlobStore.js +25 -19
  336. package/dist/services/MJStorageBlobStore.js.map +1 -1
  337. package/dist/services/StartTaskGraphDispatcher.js +2 -2
  338. package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
  339. package/dist/services/TaskGraphActionRunner.d.ts +5 -3
  340. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  341. package/dist/services/TaskGraphActionRunner.js +27 -5
  342. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  343. package/dist/services/TaskGraphAgentRunner.d.ts +14 -2
  344. package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
  345. package/dist/services/TaskGraphAgentRunner.js +157 -9
  346. package/dist/services/TaskGraphAgentRunner.js.map +1 -1
  347. package/dist/services/TaskGraphContinuationDeliverer.d.ts +57 -4
  348. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  349. package/dist/services/TaskGraphContinuationDeliverer.js +607 -18
  350. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  351. package/dist/sharedCache.d.ts +105 -0
  352. package/dist/sharedCache.d.ts.map +1 -0
  353. package/dist/sharedCache.js +279 -0
  354. package/dist/sharedCache.js.map +1 -0
  355. package/dist/types.d.ts +6 -0
  356. package/dist/types.d.ts.map +1 -1
  357. package/dist/types.js.map +1 -1
  358. package/package.json +99 -96
  359. package/src/__tests__/ActionResolver.authorization.test.ts +353 -0
  360. package/src/__tests__/AdhocQueryResolver.sqlAuthorizer.test.ts +104 -0
  361. package/src/__tests__/BridgeHostInstance.test.ts +232 -0
  362. package/src/__tests__/ClientToolRequestResolver.test.ts +116 -0
  363. package/src/__tests__/DatasetResolver.itemFilters.test.ts +201 -0
  364. package/src/__tests__/EntityRecordNameResolver.rowSecurity.test.ts +152 -0
  365. package/src/__tests__/FetchEntityVectorsResolver.test.ts +433 -0
  366. package/src/__tests__/FileResolver.storageAccess.test.ts +562 -0
  367. package/src/__tests__/GetDataContextDataResolver.sqlItems.test.ts +416 -0
  368. package/src/__tests__/HostInstance.test.ts +84 -0
  369. package/src/__tests__/HumanHandoffResolver.test.ts +17 -0
  370. package/src/__tests__/ListOperationsResolver.adhocScreen.test.ts +137 -0
  371. package/src/__tests__/LoginScreenEngine.test.ts +86 -0
  372. package/src/__tests__/MJStorageBlobStore.storageGate.test.ts +63 -0
  373. package/src/__tests__/MeetingResolver.test.ts +75 -1
  374. package/src/__tests__/RealtimeBridgeResolver.test.ts +415 -6
  375. package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +383 -0
  376. package/src/__tests__/RealtimeClientSessionResolver.test.ts +682 -58
  377. package/src/__tests__/RealtimeProxyServer.test.ts +16 -1
  378. package/src/__tests__/RealtimeRelay.test.ts +876 -0
  379. package/src/__tests__/RecordingAssemblyScheduler.test.ts +178 -0
  380. package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +129 -0
  381. package/src/__tests__/ResolverBase.adhocReadScope.test.ts +133 -2
  382. package/src/__tests__/ResolverBase.aggregateScreen.test.ts +174 -0
  383. package/src/__tests__/ResolverBase.balancedClause.test.ts +155 -0
  384. package/src/__tests__/ResolverBase.clauseUnscopedRead.test.ts +127 -0
  385. package/src/__tests__/ResolverBase.clientOldValues.test.ts +212 -6
  386. package/src/__tests__/ResolverBase.filterEscaping.test.ts +5 -2
  387. package/src/__tests__/ReturningVisitorRecap.test.ts +115 -0
  388. package/src/__tests__/RunAIAgentResolver.branch.test.ts +170 -0
  389. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +6 -4
  390. package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +258 -0
  391. package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +166 -0
  392. package/src/__tests__/RunTemplateResolver.test.ts +132 -0
  393. package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +63 -0
  394. package/src/__tests__/RunViewResolver.cacheCheckScreen.test.ts +165 -0
  395. package/src/__tests__/SearchKnowledgeStreamResolver.test.ts +161 -0
  396. package/src/__tests__/SessionJanitor.test.ts +1203 -21
  397. package/src/__tests__/SessionManager.test.ts +240 -17
  398. package/src/__tests__/SessionRunIDVerifier.test.ts +251 -0
  399. package/src/__tests__/SyncRolesUsersResolver.userRoles.test.ts +97 -0
  400. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +25 -0
  401. package/src/__tests__/TaskGraphAgentRunner.test.ts +266 -0
  402. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +403 -22
  403. package/src/__tests__/TaskGraphFrameResolver.test.ts +22 -0
  404. package/src/__tests__/TestQuerySQLResolver.test.ts +274 -0
  405. package/src/__tests__/TransactionGroupResolver.refusals.test.ts +98 -1
  406. package/src/__tests__/UpdateMJDataContextItem.oldValues.test.ts +220 -0
  407. package/src/__tests__/UserAvatarResolver.test.ts +255 -0
  408. package/src/__tests__/UserResolver.currentUser.test.ts +16 -1
  409. package/src/__tests__/ViewOperationsHandler.clauseScreen.test.ts +157 -0
  410. package/src/__tests__/actionAuthorization.test.ts +130 -0
  411. package/src/__tests__/agent-run-data-guard.test.ts +130 -0
  412. package/src/__tests__/agentVisionConsentAudit.test.ts +118 -0
  413. package/src/__tests__/apiRootBoot.test.ts +202 -0
  414. package/src/__tests__/avatarInputValidation.test.ts +160 -0
  415. package/src/__tests__/cacheInvalidationRecordData.test.ts +64 -0
  416. package/src/__tests__/conversationRunEvents.test.ts +56 -14
  417. package/src/__tests__/globalCors.test.ts +217 -0
  418. package/src/__tests__/isolatedProviderTransactions.test.ts +169 -0
  419. package/src/__tests__/magicLinkService.consume.test.ts +6 -0
  420. package/src/__tests__/magicLinkService.provisionLog.test.ts +5 -0
  421. package/src/__tests__/multiTenancy.postgresRewrite.test.ts +181 -0
  422. package/src/__tests__/multiTenancy.security.test.ts +51 -0
  423. package/src/__tests__/multiTenancy.test.ts +1 -1
  424. package/src/__tests__/newUsers.template.test.ts +151 -0
  425. package/src/__tests__/newUsers.test.ts +74 -5
  426. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +17 -2
  427. package/src/__tests__/ownedRealtimeSession.test.ts +39 -0
  428. package/src/__tests__/pushStatusResolver.filter.test.ts +7 -0
  429. package/src/__tests__/realtimeRecordingHandler.test.ts +652 -0
  430. package/src/__tests__/realtimeSessions/RealtimeSessionEventService.test.ts +201 -0
  431. package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +215 -0
  432. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationResolver.test.ts +102 -0
  433. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationService.test.ts +349 -0
  434. package/src/__tests__/realtimeSessions/RealtimeVerifyRouter.test.ts +131 -0
  435. package/src/__tests__/realtimeSessions/SlidingWindowRateLimiter.test.ts +56 -0
  436. package/src/__tests__/realtimeSessions/helpers.ts +4 -0
  437. package/src/__tests__/realtimeSessions/sessionAccess.test.ts +129 -0
  438. package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +124 -0
  439. package/src/__tests__/realtimeSessions/verificationCore.test.ts +355 -0
  440. package/src/__tests__/realtimeSessions/verificationPages.test.ts +84 -0
  441. package/src/__tests__/realtimeSessions/verificationPolicy.test.ts +226 -0
  442. package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +633 -0
  443. package/src/__tests__/resolverBase.fls.test.ts +87 -4
  444. package/src/__tests__/serverExtensionHostOverlay.test.ts +66 -0
  445. package/src/__tests__/serverExtensionReservedRoots.test.ts +11 -96
  446. package/src/__tests__/sharedCache.test.ts +312 -0
  447. package/src/__tests__/widgetGuestElevation.test.ts +44 -0
  448. package/src/agentSessions/BridgeHostInstance.ts +32 -0
  449. package/src/agentSessions/HostInstance.ts +124 -28
  450. package/src/agentSessions/ReturningVisitorRecap.ts +7 -3
  451. package/src/agentSessions/SessionJanitor.ts +821 -59
  452. package/src/agentSessions/SessionManager.ts +138 -26
  453. package/src/agentSessions/SessionRunIDVerifier.ts +171 -0
  454. package/src/agentSessions/index.ts +10 -3
  455. package/src/apiRoot.ts +78 -0
  456. package/src/auth/AuthProviderCatalogRouter.ts +26 -0
  457. package/src/auth/LoginScreenEngine.ts +50 -0
  458. package/src/auth/actionAuthorization.ts +116 -0
  459. package/src/auth/index.ts +4 -8
  460. package/src/auth/magicLink/MagicLinkRouter.ts +3 -2
  461. package/src/auth/magicLink/MagicLinkService.ts +6 -3
  462. package/src/auth/newUsers.ts +99 -11
  463. package/src/config.ts +171 -5
  464. package/src/context.ts +15 -10
  465. package/src/coreRoutes.ts +166 -0
  466. package/src/generated/graphql-schemas/__mj.ts +1815 -57
  467. package/src/generic/CacheInvalidationResolver.ts +73 -18
  468. package/src/generic/OrphanedConversationDetailReconciler.ts +3 -3
  469. package/src/generic/PushStatusResolver.ts +1 -1
  470. package/src/generic/ResolverBase.ts +335 -326
  471. package/src/generic/RunViewResolver.ts +21 -0
  472. package/src/globalCors.ts +71 -0
  473. package/src/index.ts +231 -300
  474. package/src/isolatedProvider.ts +22 -0
  475. package/src/multiTenancy/index.ts +24 -2
  476. package/src/realtimeProxy/RealtimeProxyServer.ts +148 -16
  477. package/src/realtimeProxy/RealtimeRelayTunnel.ts +645 -0
  478. package/src/realtimeSessions/README.md +179 -0
  479. package/src/realtimeSessions/RealtimeSessionEventService.ts +274 -0
  480. package/src/realtimeSessions/RealtimeSessionVerificationService.ts +168 -0
  481. package/src/realtimeSessions/RealtimeVerifyRouter.ts +109 -0
  482. package/src/realtimeSessions/RecordingAssemblyScheduler.ts +234 -0
  483. package/src/realtimeSessions/SessionVerificationPortsBase.ts +189 -0
  484. package/src/realtimeSessions/SlidingWindowRateLimiter.ts +92 -0
  485. package/src/realtimeSessions/index.ts +18 -0
  486. package/src/realtimeSessions/ownedRealtimeSession.ts +55 -0
  487. package/src/realtimeSessions/sessionAccess.ts +145 -0
  488. package/src/realtimeSessions/sessionConfigStamps.ts +123 -0
  489. package/src/realtimeSessions/subscriptionAuthorization.ts +116 -0
  490. package/src/realtimeSessions/verificationCore.ts +502 -0
  491. package/src/realtimeSessions/verificationPages.ts +149 -0
  492. package/src/realtimeSessions/verificationPolicy.ts +321 -0
  493. package/src/realtimeSessions/verificationWorkflow.ts +702 -0
  494. package/src/realtimeWidget/widgetGuestElevation.ts +34 -2
  495. package/src/resolvers/ActionResolver.ts +84 -21
  496. package/src/resolvers/AdhocQueryResolver.ts +24 -6
  497. package/src/resolvers/ArtifactFileResolver.ts +9 -8
  498. package/src/resolvers/CacheStatsResolver.ts +89 -2
  499. package/src/resolvers/ClientToolRequestResolver.ts +25 -7
  500. package/src/resolvers/ConversationRunEventsResolver.ts +15 -11
  501. package/src/resolvers/DatasetResolver.ts +70 -10
  502. package/src/resolvers/EntityRecordNameResolver.ts +3 -2
  503. package/src/resolvers/FetchEntityVectorsResolver.ts +179 -2
  504. package/src/resolvers/FileResolver.ts +321 -106
  505. package/src/resolvers/GetDataContextDataResolver.ts +139 -41
  506. package/src/resolvers/GetDataResolver.ts +6 -3
  507. package/src/resolvers/HumanHandoffResolver.ts +8 -0
  508. package/src/resolvers/IntegrationDiscoveryResolver.ts +4 -2
  509. package/src/resolvers/MCPResolver.ts +8 -5
  510. package/src/resolvers/QueryResolver.ts +11 -0
  511. package/src/resolvers/RealtimeBridgeResolver.ts +163 -11
  512. package/src/resolvers/RealtimeClientSessionResolver.ts +511 -129
  513. package/src/resolvers/RealtimeSessionEventsResolver.ts +133 -0
  514. package/src/resolvers/RealtimeSessionVerificationResolver.ts +174 -0
  515. package/src/resolvers/RemoteBrowserActionResolver.ts +11 -1
  516. package/src/resolvers/RunAIAgentResolver.ts +116 -14
  517. package/src/resolvers/RunTemplateResolver.ts +13 -12
  518. package/src/resolvers/SearchKnowledgeStreamResolver.ts +19 -3
  519. package/src/resolvers/SqlLoggingConfigResolver.ts +2 -4
  520. package/src/resolvers/SyncDataResolver.ts +6 -2
  521. package/src/resolvers/SyncRolesUsersResolver.ts +24 -6
  522. package/src/resolvers/TaskGraphFrameResolver.ts +33 -1
  523. package/src/resolvers/TestQuerySQLResolver.ts +68 -13
  524. package/src/resolvers/TransactionGroupResolver.ts +131 -27
  525. package/src/resolvers/UserAvatarResolver.ts +111 -0
  526. package/src/resolvers/UserResolver.ts +2 -16
  527. package/src/resolvers/__tests__/GetDataResolver.validation.test.ts +95 -0
  528. package/src/resolvers/agent-run-data-guard.ts +89 -0
  529. package/src/resolvers/agentVisionConsentAudit.ts +82 -0
  530. package/src/resolvers/avatarInputValidation.ts +123 -0
  531. package/src/resolvers/currentUserRoles.ts +32 -1
  532. package/src/resolvers/meetings/meetingMutations.ts +21 -0
  533. package/src/rest/RealtimeRecordingHandler.ts +464 -0
  534. package/src/rest/ViewOperationsHandler.ts +29 -13
  535. package/src/rest/setupRESTEndpoints.ts +6 -0
  536. package/src/serverExtensionReservedRoots.ts +14 -17
  537. package/src/services/MJStorageBlobStore.ts +31 -30
  538. package/src/services/StartTaskGraphDispatcher.ts +2 -2
  539. package/src/services/TaskGraphActionRunner.ts +25 -5
  540. package/src/services/TaskGraphAgentRunner.ts +188 -11
  541. package/src/services/TaskGraphContinuationDeliverer.ts +713 -17
  542. package/src/sharedCache.ts +305 -0
  543. package/src/types.ts +7 -0
@@ -0,0 +1,170 @@
1
+ /**
2
+ * @fileoverview The conversation branch on `RunAIAgentFromConversationDetail`.
3
+ *
4
+ * The branch comes from the placeholder row the mutation is given, never from a request argument.
5
+ * These tests pin that the mutation loads history along that branch's path, hands the branch to the
6
+ * agent run on both the synchronous and fire-and-forget paths, and reads the trunk when the row has
7
+ * no branch; and that `executeAIAgent` puts the branch on the run's params only when there is one.
8
+ */
9
+ import 'reflect-metadata'; // must precede any type-graphql decorator evaluation
10
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
11
+ import type { PubSubEngine } from 'type-graphql';
12
+
13
+ // type-graphql's real decorators need emitDecoratorMetadata, which vitest's esbuild transform
14
+ // does not emit; the schema is irrelevant here, so every decorator is a no-op.
15
+ vi.mock('type-graphql', () => {
16
+ const decoratorFactory = (..._args: unknown[]) => (..._decorated: unknown[]) => undefined;
17
+ const exportNames = [
18
+ 'Resolver', 'Query', 'Mutation', 'Subscription', 'Arg', 'Args', 'ArgsType', 'Ctx', 'Root',
19
+ 'Info', 'Field', 'FieldResolver', 'ObjectType', 'InputType', 'InterfaceType', 'Authorized',
20
+ 'UseMiddleware', 'Extensions', 'Directive', 'ID', 'Int', 'Float', 'GraphQLISODateTime',
21
+ 'GraphQLTimestamp', 'registerEnumType', 'createMethodDecorator', 'createParamDecorator',
22
+ 'buildSchema', 'buildSchemaSync', 'PubSub',
23
+ ];
24
+ return Object.fromEntries(exportNames.map((name) => [name, decoratorFactory]));
25
+ });
26
+
27
+ const hoisted = vi.hoisted(() => ({
28
+ runAgentInConversation: vi.fn(),
29
+ }));
30
+
31
+ vi.mock('@memberjunction/ai-agents', () => ({
32
+ AgentRunner: class {
33
+ RunAgentInConversation(...args: unknown[]) {
34
+ return hoisted.runAgentInConversation(...args);
35
+ }
36
+ },
37
+ ArtifactToolManager: class {},
38
+ }));
39
+
40
+ vi.mock('../realtimeWidget/widgetGuestElevation.js', () => ({
41
+ ResolveWidgetGuestRunContext: vi.fn().mockResolvedValue(null),
42
+ ElevateUserPayload: vi.fn(),
43
+ }));
44
+
45
+ import { ConversationEngine } from '@memberjunction/core-entities';
46
+ import { RunAIAgentResolver } from '../resolvers/RunAIAgentResolver.js';
47
+ import type { AppContext, UserPayload } from '../types.js';
48
+
49
+ const USER = { ID: 'user-1', Email: 'user@example.com' };
50
+
51
+ type Fn = ReturnType<typeof vi.fn>;
52
+
53
+ /** The private members this test reaches, through an explicit shape (no `any`). */
54
+ interface ResolverSeams {
55
+ CheckAPIKeyScopeAuthorization: Fn;
56
+ GetUserFromPayload: Fn;
57
+ loadConversationHistoryWithAttachments: Fn;
58
+ executeAIAgent: Fn;
59
+ executeAgentInBackground: Fn;
60
+ loadInputArtifactsBatch: Fn;
61
+ validateAgent: Fn;
62
+ persistInFlightAgentFailure: Fn;
63
+ }
64
+
65
+ function makeResolver(): { resolver: RunAIAgentResolver; seams: ResolverSeams } {
66
+ const resolver = new RunAIAgentResolver();
67
+ const seams = resolver as unknown as ResolverSeams;
68
+ seams.CheckAPIKeyScopeAuthorization = vi.fn().mockResolvedValue(undefined);
69
+ seams.GetUserFromPayload = vi.fn().mockReturnValue(USER);
70
+ return { resolver, seams };
71
+ }
72
+
73
+ function makeContext(branchId: string | null): AppContext {
74
+ const provider = {
75
+ GetEntityObject: vi.fn().mockResolvedValue({
76
+ ConversationID: 'conv-1',
77
+ BranchID: branchId,
78
+ Load: vi.fn().mockResolvedValue(true),
79
+ }),
80
+ };
81
+ return {
82
+ userPayload: { sessionId: 'session-1', userRecord: USER } as unknown as UserPayload,
83
+ providers: [{ type: 'Read-Write', provider }],
84
+ dataSource: {},
85
+ } as unknown as AppContext;
86
+ }
87
+
88
+ const pubSub = { publish: vi.fn() } as unknown as PubSubEngine;
89
+
90
+ async function runMutation(resolver: RunAIAgentResolver, branchId: string | null, fireAndForget?: boolean) {
91
+ return resolver.RunAIAgentFromConversationDetail(
92
+ 'detail-1', 'agent-1', makeContext(branchId), 'session-1', pubSub,
93
+ undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
94
+ undefined, undefined, fireAndForget, undefined, undefined, undefined
95
+ );
96
+ }
97
+
98
+ afterEach(() => {
99
+ vi.restoreAllMocks();
100
+ });
101
+
102
+ describe('RunAIAgentFromConversationDetail — branch', () => {
103
+ let resolver: RunAIAgentResolver;
104
+ let seams: ResolverSeams;
105
+
106
+ beforeEach(() => {
107
+ ({ resolver, seams } = makeResolver());
108
+ seams.loadConversationHistoryWithAttachments = vi.fn().mockResolvedValue([]);
109
+ seams.executeAIAgent = vi.fn().mockResolvedValue({ success: true, result: '{}' });
110
+ seams.executeAgentInBackground = vi.fn();
111
+ });
112
+
113
+ it('loads history on the placeholder row\'s branch and hands the branch to the run', async () => {
114
+ await runMutation(resolver, 'branch-b');
115
+ expect(seams.loadConversationHistoryWithAttachments.mock.calls[0][6]).toBe('branch-b');
116
+ expect(seams.executeAIAgent.mock.calls[0].at(-1)).toBe('branch-b');
117
+ });
118
+
119
+ it('passes the branch to the background path too', async () => {
120
+ await runMutation(resolver, 'branch-b', true);
121
+ expect(seams.executeAgentInBackground.mock.calls[0].at(-1)).toBe('branch-b');
122
+ });
123
+
124
+ it('reads the trunk when the placeholder has no branch (control)', async () => {
125
+ await runMutation(resolver, null);
126
+ expect(seams.loadConversationHistoryWithAttachments.mock.calls[0][6]).toBeNull();
127
+ expect(seams.executeAIAgent.mock.calls[0].at(-1)).toBeNull();
128
+ });
129
+ });
130
+
131
+ describe('loadConversationHistoryWithAttachments — branch', () => {
132
+ it('passes the branch to the fresh loader', async () => {
133
+ const { resolver, seams } = makeResolver();
134
+ seams.loadInputArtifactsBatch = vi.fn().mockResolvedValue(new Map());
135
+ const loadRows = vi.spyOn(ConversationEngine, 'LoadWindowRowsFresh').mockResolvedValue([]);
136
+ const provider = {};
137
+ const load = (resolver as unknown as {
138
+ loadConversationHistoryWithAttachments(
139
+ conversationId: string, user: unknown, max: number, provider: unknown,
140
+ exclude?: string[], historyFrom?: Date, branchId?: string | null
141
+ ): Promise<unknown[]>;
142
+ }).loadConversationHistoryWithAttachments.bind(resolver);
143
+ await load('conv-1', USER, 20, provider, ['detail-1'], undefined, 'branch-b');
144
+ expect(loadRows).toHaveBeenCalledWith('conv-1', USER, provider, undefined, 'branch-b');
145
+ });
146
+ });
147
+
148
+ describe('executeAIAgent — ConversationBranchID', () => {
149
+ it('puts the branch on the run\'s params, and leaves it unset for the trunk', async () => {
150
+ const { resolver, seams } = makeResolver();
151
+ seams.validateAgent = vi.fn().mockResolvedValue({ ID: 'agent-1', Name: 'Test Agent' });
152
+ seams.persistInFlightAgentFailure = vi.fn().mockResolvedValue(undefined);
153
+ hoisted.runAgentInConversation.mockReset().mockRejectedValue(new Error('stop here'));
154
+ vi.spyOn(console, 'error').mockImplementation(() => undefined);
155
+ vi.spyOn(console, 'log').mockImplementation(() => undefined);
156
+ const execute = (resolver as unknown as { executeAIAgent(...args: unknown[]): Promise<unknown> }).executeAIAgent.bind(resolver);
157
+ const userPayload = { sessionId: 'session-1', userRecord: USER };
158
+ const base = [
159
+ {}, {}, 'agent-1', userPayload, '[{"role":"user","content":"hi"}]', 'session-1', pubSub,
160
+ undefined, undefined, undefined, undefined, undefined, undefined, 'detail-1', false, false,
161
+ undefined, undefined, 'conv-1', undefined, undefined, undefined, undefined, undefined,
162
+ false, // trustReservedRunData
163
+ ];
164
+ await execute(...base, 'branch-b');
165
+ await execute(...base, null);
166
+ const [withBranch, trunk] = hoisted.runAgentInConversation.mock.calls.map(c => c[0] as Record<string, unknown>);
167
+ expect(withBranch.ConversationBranchID).toBe('branch-b');
168
+ expect(trunk).not.toHaveProperty('ConversationBranchID');
169
+ });
170
+ });
@@ -108,6 +108,8 @@ afterEach(() => {
108
108
  describe('RunAIAgentFromConversationDetail — agentHistoryFrom', () => {
109
109
  let resolver: RunAIAgentResolver;
110
110
  let seams: ResolverSeams;
111
+ /** The floor's position in executeAIAgent / executeAgentInBackground: third from last, before TrustReservedRunData and the branch. */
112
+ const FLOOR_ARG = -3;
111
113
 
112
114
  beforeEach(() => {
113
115
  ({ resolver, seams } = makeResolver());
@@ -124,7 +126,7 @@ describe('RunAIAgentFromConversationDetail — agentHistoryFrom', () => {
124
126
  expect(loaderArgs[0]).toBe('conv-1');
125
127
  expect(loaderArgs[4]).toEqual(['detail-1']);
126
128
  expect((loaderArgs[5] as Date).toISOString()).toBe(FLOOR_ISO);
127
- const runFloor = seams.executeAIAgent.mock.calls[0].at(-1) as Date;
129
+ const runFloor = seams.executeAIAgent.mock.calls[0].at(FLOOR_ARG) as Date;
128
130
  expect(runFloor.toISOString()).toBe(FLOOR_ISO);
129
131
  });
130
132
 
@@ -133,7 +135,7 @@ describe('RunAIAgentFromConversationDetail — agentHistoryFrom', () => {
133
135
 
134
136
  expect(result.success).toBe(true);
135
137
  expect(seams.executeAIAgent).not.toHaveBeenCalled();
136
- const runFloor = seams.executeAgentInBackground.mock.calls[0].at(-1) as Date;
138
+ const runFloor = seams.executeAgentInBackground.mock.calls[0].at(FLOOR_ARG) as Date;
137
139
  expect(runFloor.toISOString()).toBe(FLOOR_ISO);
138
140
  });
139
141
 
@@ -141,7 +143,7 @@ describe('RunAIAgentFromConversationDetail — agentHistoryFrom', () => {
141
143
  await runMutation(resolver, {});
142
144
 
143
145
  expect(seams.loadConversationHistoryWithAttachments.mock.calls[0][5]).toBeUndefined();
144
- expect(seams.executeAIAgent.mock.calls[0].at(-1)).toBeUndefined();
146
+ expect(seams.executeAIAgent.mock.calls[0].at(FLOOR_ARG)).toBeUndefined();
145
147
  });
146
148
 
147
149
  it('fails the request on an unreadable floor, before loading or running anything', async () => {
@@ -178,7 +180,7 @@ describe('loadConversationHistoryWithAttachments — history floor', () => {
178
180
  }).loadConversationHistoryWithAttachments.bind(resolver);
179
181
  await load('conv-1', USER, 20, provider, ['detail-1'], floor);
180
182
 
181
- expect(loadRows).toHaveBeenCalledWith('conv-1', USER, provider, floor);
183
+ expect(loadRows).toHaveBeenCalledWith('conv-1', USER, provider, floor, undefined);
182
184
  expect(assemble.mock.calls[0][1]).toEqual({ maxTailMessages: 20, excludeDetailIds: ['detail-1'], historyFrom: floor });
183
185
  });
184
186
  });
@@ -0,0 +1,258 @@
1
+ /**
2
+ * @fileoverview Every agent-run entry of `RunAIAgentResolver` tells the run whether it may read the reserved scope
3
+ * and agent-type keys from a client's `data` (`ExecuteAgentParams.TrustReservedRunData`, A12.15).
4
+ *
5
+ * The decision is pinned by `agent-run-data-guard.test.ts`, and what an untrusted run loses by the ai-core-plus and
6
+ * ai-agents suites (`BaseAgent.Execute` drops the keys). These tests pin the call sites: the synchronous and
7
+ * fire-and-forget paths of `RunAIAgent` and `RunAIAgentFromConversationDetail`, the widget-guest path (judged on
8
+ * the guest's own payload, not the system principal it is elevated to), the trusted callers, and an API key with and
9
+ * without the `agent:trusted` scope — each through the real `executeAIAgent`, up to the params handed to
10
+ * `AgentRunner`. The resolver forwards `data` as sent.
11
+ */
12
+ import 'reflect-metadata'; // must precede any type-graphql decorator evaluation
13
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
14
+ import type { PubSubEngine } from 'type-graphql';
15
+
16
+ // type-graphql's real decorators need emitDecoratorMetadata, which vitest's esbuild transform
17
+ // does not emit; the schema is irrelevant here, so every decorator is a no-op.
18
+ vi.mock('type-graphql', () => {
19
+ const decoratorFactory = (..._args: unknown[]) => (..._decorated: unknown[]) => undefined;
20
+ const exportNames = [
21
+ 'Resolver', 'Query', 'Mutation', 'Subscription', 'Arg', 'Args', 'ArgsType', 'Ctx', 'Root',
22
+ 'Info', 'Field', 'FieldResolver', 'ObjectType', 'InputType', 'InterfaceType', 'Authorized',
23
+ 'UseMiddleware', 'Extensions', 'Directive', 'ID', 'Int', 'Float', 'GraphQLISODateTime',
24
+ 'GraphQLTimestamp', 'registerEnumType', 'createMethodDecorator', 'createParamDecorator',
25
+ 'buildSchema', 'buildSchemaSync', 'PubSub',
26
+ ];
27
+ return Object.fromEntries(exportNames.map((name) => [name, decoratorFactory]));
28
+ });
29
+
30
+ const hoisted = vi.hoisted(() => ({
31
+ runAgentInConversation: vi.fn(),
32
+ resolveWidgetGuestRunContext: vi.fn(),
33
+ authorize: vi.fn(),
34
+ }));
35
+
36
+ // Only the key engine is stubbed: Authorize allows `agent:trusted` for the key whose hash is 'hash-trusted'.
37
+ vi.mock('@memberjunction/api-keys', async (importOriginal) => ({
38
+ ...(await importOriginal<typeof import('@memberjunction/api-keys')>()),
39
+ GetAPIKeyEngine: () => ({ Authorize: hoisted.authorize }),
40
+ }));
41
+
42
+ vi.mock('@memberjunction/ai-agents', () => ({
43
+ AgentRunner: class {
44
+ RunAgentInConversation(...args: unknown[]) {
45
+ return hoisted.runAgentInConversation(...args);
46
+ }
47
+ },
48
+ ArtifactToolManager: class {},
49
+ }));
50
+
51
+ // Only the widget lookup is stubbed; ElevateUserPayload is the real one, so the widget-guest test runs
52
+ // against the elevated system-user payload the resolver really builds.
53
+ vi.mock('../realtimeWidget/widgetGuestElevation.js', async (importOriginal) => ({
54
+ ...(await importOriginal<typeof import('../realtimeWidget/widgetGuestElevation.js')>()),
55
+ ResolveWidgetGuestRunContext: hoisted.resolveWidgetGuestRunContext,
56
+ }));
57
+
58
+ import { UserCache } from '@memberjunction/generic-database-provider';
59
+ import type { UserInfo } from '@memberjunction/core';
60
+ import { RunAIAgentResolver } from '../resolvers/RunAIAgentResolver.js';
61
+ import type { AppContext, UserPayload } from '../types.js';
62
+
63
+ const SCOPE_RECORD_ID = 'B1A2C3D4-0000-4000-8000-00000000A115';
64
+ const ORDINARY = { conversationId: 'conv-1', latestMessageId: 'detail-1', invocationReason: 'user-message' };
65
+ const CLIENT_DATA = JSON.stringify({
66
+ ...ORDINARY,
67
+ PrimaryScopeRecordID: SCOPE_RECORD_ID,
68
+ PrimaryScopeEntityName: 'MJ: Companies',
69
+ SecondaryScopes: { TeamID: 'team-other' },
70
+ __agentTypePromptParams: { enableTaskGraphs: true },
71
+ });
72
+
73
+ const USER = { ID: 'user-1', Email: 'browser.user@example.com' };
74
+ const SYSTEM_USER = { ID: 'system-user', Email: 'system@example.com' };
75
+ const GUEST = { ID: 'guest-1', Email: 'anonymous@magic-link.local', IsMagicLinkAnonymous: true };
76
+
77
+ type Fn = ReturnType<typeof vi.fn>;
78
+
79
+ /** The private members this test reaches, through an explicit shape (no `any`). */
80
+ interface ResolverSeams {
81
+ CheckAPIKeyScopeAuthorization: Fn;
82
+ GetUserFromPayload: Fn;
83
+ loadConversationHistoryWithAttachments: Fn;
84
+ validateAgent: Fn;
85
+ persistInFlightAgentFailure: Fn;
86
+ }
87
+
88
+ const pubSub = { publish: vi.fn().mockResolvedValue(undefined) } as unknown as PubSubEngine;
89
+
90
+ function makeResolver(): { resolver: RunAIAgentResolver; seams: ResolverSeams } {
91
+ const resolver = new RunAIAgentResolver();
92
+ const seams = resolver as unknown as ResolverSeams;
93
+ seams.CheckAPIKeyScopeAuthorization = vi.fn().mockResolvedValue(undefined);
94
+ seams.GetUserFromPayload = vi.fn((payload: UserPayload) => payload.userRecord);
95
+ seams.loadConversationHistoryWithAttachments = vi.fn().mockResolvedValue([{ role: 'user', content: 'hi' }]);
96
+ seams.validateAgent = vi.fn().mockResolvedValue({ ID: 'agent-1', Name: 'Test Agent' });
97
+ seams.persistInFlightAgentFailure = vi.fn().mockResolvedValue(undefined);
98
+ return { resolver, seams };
99
+ }
100
+
101
+ function makeContext(userPayload: Partial<UserPayload>): AppContext {
102
+ const provider = {
103
+ GetEntityObject: vi.fn().mockResolvedValue({ ConversationID: 'conv-1', Load: vi.fn().mockResolvedValue(true) }),
104
+ };
105
+ return {
106
+ userPayload: { sessionId: 'session-1', email: USER.Email, userRecord: USER, ...userPayload } as UserPayload,
107
+ providers: [{ type: 'Read-Write', provider }],
108
+ dataSource: {},
109
+ } as unknown as AppContext;
110
+ }
111
+
112
+ /** The params the n-th run was handed by the real executeAIAgent (what AgentRunner.RunAgentInConversation received). */
113
+ interface HandedParams {
114
+ data: Record<string, unknown>;
115
+ TrustReservedRunData?: boolean;
116
+ contextUser: { ID: string };
117
+ }
118
+
119
+ /** Waits for the n-th run to start (the fire-and-forget path starts it after the resolver has returned). */
120
+ async function handedParams(n = 0): Promise<HandedParams> {
121
+ await vi.waitFor(() => expect(hoisted.runAgentInConversation.mock.calls.length).toBeGreaterThan(n));
122
+ return hoisted.runAgentInConversation.mock.calls[n][0] as HandedParams;
123
+ }
124
+
125
+ function runAIAgent(resolver: RunAIAgentResolver, ctx: AppContext, fireAndForget?: boolean) {
126
+ return resolver.RunAIAgent(
127
+ 'agent-1', ctx, '[{"role":"user","content":"hi"}]', 'session-1', pubSub, CLIENT_DATA,
128
+ undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
129
+ fireAndForget
130
+ );
131
+ }
132
+
133
+ function runFromDetail(resolver: RunAIAgentResolver, ctx: AppContext, fireAndForget?: boolean) {
134
+ return resolver.RunAIAgentFromConversationDetail(
135
+ 'detail-1', 'agent-1', ctx, 'session-1', pubSub, undefined, CLIENT_DATA,
136
+ undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, fireAndForget
137
+ );
138
+ }
139
+
140
+ beforeEach(() => {
141
+ hoisted.resolveWidgetGuestRunContext.mockReset().mockResolvedValue(null);
142
+ // Stop right after the run's params are captured — the rest of the run is out of scope.
143
+ hoisted.runAgentInConversation.mockReset().mockRejectedValue(new Error('stop here'));
144
+ hoisted.authorize.mockReset().mockImplementation(async (apiKeyHash: string, _app: string, scopePath: string) =>
145
+ apiKeyHash === 'hash-trusted' && scopePath === 'agent:trusted'
146
+ ? { Allowed: true, MatchedKeyRule: { ScopePath: scopePath }, EvaluatedRules: [] }
147
+ : { Allowed: false, Reason: 'No matching key scope rules', EvaluatedRules: [] });
148
+ vi.spyOn(UserCache.Instance, 'GetSystemUser').mockReturnValue(SYSTEM_USER as UserInfo);
149
+ vi.spyOn(console, 'log').mockImplementation(() => undefined);
150
+ vi.spyOn(console, 'error').mockImplementation(() => undefined);
151
+ });
152
+
153
+ afterEach(() => {
154
+ vi.restoreAllMocks();
155
+ });
156
+
157
+ describe('RunAIAgent — reserved run-data keys', () => {
158
+ it('marks the run untrusted for an interactive user and forwards data as sent', async () => {
159
+ const { resolver } = makeResolver();
160
+
161
+ await runAIAgent(resolver, makeContext({}));
162
+
163
+ const params = await handedParams();
164
+ expect(params.TrustReservedRunData).toBe(false);
165
+ expect(params.data).toEqual(JSON.parse(CLIENT_DATA));
166
+ });
167
+
168
+ it('marks it untrusted on the fire-and-forget path too', async () => {
169
+ const { resolver } = makeResolver();
170
+
171
+ await runAIAgent(resolver, makeContext({}), true);
172
+
173
+ expect((await handedParams()).TrustReservedRunData).toBe(false);
174
+ });
175
+
176
+ it('marks it trusted for an API key holding agent:trusted, on both paths', async () => {
177
+ const { resolver } = makeResolver();
178
+ const ctx = makeContext({ apiKeyId: 'key-1', apiKeyHash: 'hash-trusted' });
179
+
180
+ await runAIAgent(resolver, ctx);
181
+ await runAIAgent(resolver, ctx, true);
182
+
183
+ expect((await handedParams(0)).TrustReservedRunData).toBe(true);
184
+ expect((await handedParams(1)).TrustReservedRunData).toBe(true);
185
+ });
186
+
187
+ it('marks it untrusted for an API key without agent:trusted, on both paths', async () => {
188
+ const { resolver } = makeResolver();
189
+ const ctx = makeContext({ apiKeyId: 'key-2', apiKeyHash: 'hash-plain' });
190
+
191
+ await runAIAgent(resolver, ctx);
192
+ await runAIAgent(resolver, ctx, true);
193
+
194
+ expect((await handedParams(0)).TrustReservedRunData).toBe(false);
195
+ expect((await handedParams(1)).TrustReservedRunData).toBe(false);
196
+ });
197
+ });
198
+
199
+ describe('RunAIAgentFromConversationDetail — reserved run-data keys', () => {
200
+ it('marks the run untrusted for an interactive user on both paths', async () => {
201
+ const { resolver } = makeResolver();
202
+
203
+ await runFromDetail(resolver, makeContext({}));
204
+ await runFromDetail(resolver, makeContext({}), true);
205
+
206
+ expect((await handedParams(0)).TrustReservedRunData).toBe(false);
207
+ expect((await handedParams(1)).TrustReservedRunData).toBe(false);
208
+ });
209
+
210
+ it('marks a widget-guest run untrusted although it executes as the system user', async () => {
211
+ const { resolver } = makeResolver();
212
+ hoisted.resolveWidgetGuestRunContext.mockResolvedValue({
213
+ ElevatedUser: SYSTEM_USER,
214
+ Widget: {},
215
+ PinnedAgentId: 'pinned-agent',
216
+ });
217
+
218
+ await runFromDetail(resolver, makeContext({ email: GUEST.Email, userRecord: GUEST }));
219
+
220
+ const params = await handedParams();
221
+ expect(params.contextUser.ID).toBe(SYSTEM_USER.ID); // the premise: the run is elevated
222
+ expect(params.TrustReservedRunData).toBe(false);
223
+ });
224
+
225
+ it('marks it trusted for the system user, on both paths', async () => {
226
+ const { resolver } = makeResolver();
227
+ const ctx = makeContext({ isSystemUser: true, email: SYSTEM_USER.Email, userRecord: SYSTEM_USER });
228
+
229
+ await runFromDetail(resolver, ctx);
230
+ await runFromDetail(resolver, ctx, true);
231
+
232
+ expect((await handedParams(0)).TrustReservedRunData).toBe(true);
233
+ expect((await handedParams(1)).TrustReservedRunData).toBe(true);
234
+ });
235
+
236
+ it('marks it trusted for an API key holding agent:trusted, and untrusted for one without', async () => {
237
+ const { resolver } = makeResolver();
238
+
239
+ await runFromDetail(resolver, makeContext({ apiKeyId: 'key-1', apiKeyHash: 'hash-trusted' }));
240
+ await runFromDetail(resolver, makeContext({ apiKeyId: 'key-2', apiKeyHash: 'hash-plain' }));
241
+
242
+ expect((await handedParams(0)).TrustReservedRunData).toBe(true);
243
+ expect((await handedParams(1)).TrustReservedRunData).toBe(false);
244
+ });
245
+ });
246
+
247
+ describe('RunAIAgentSystemUser — reserved run-data keys', () => {
248
+ it('marks the run trusted for the system user it admits, and forwards data as sent', async () => {
249
+ const { resolver } = makeResolver();
250
+ const ctx = makeContext({ isSystemUser: true, email: SYSTEM_USER.Email, userRecord: SYSTEM_USER });
251
+
252
+ await resolver.RunAIAgentSystemUser('agent-1', ctx, '[]', 'session-1', pubSub, CLIENT_DATA);
253
+
254
+ const params = await handedParams();
255
+ expect(params.TrustReservedRunData).toBe(true);
256
+ expect(params.data).toEqual(JSON.parse(CLIENT_DATA));
257
+ });
258
+ });
@@ -0,0 +1,166 @@
1
+ /**
2
+ * @fileoverview Continuing from a user-stopped run on `RunAIAgentFromConversationDetail`.
3
+ *
4
+ * The chat client never sends `lastRunId`, so the turn after a Stop used to start a fresh,
5
+ * unchained run. The mutation now looks for a user-stopped newest root run for the agent in the
6
+ * conversation and, when it finds one, chains the new run to it by LastRunID and rolls its
7
+ * FinalPayload in when the caller supplied no payload. These tests pin that on both dispatch
8
+ * paths, that a caller-supplied lastRunId wins, and that no predecessor changes nothing.
9
+ * Harness as in `RunAIAgentResolver.historyFrom.test.ts`.
10
+ */
11
+ import 'reflect-metadata';
12
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
13
+ import type { PubSubEngine } from 'type-graphql';
14
+
15
+ vi.mock('type-graphql', () => {
16
+ const decoratorFactory = (..._args: unknown[]) => (..._decorated: unknown[]) => undefined;
17
+ const exportNames = [
18
+ 'Resolver', 'Query', 'Mutation', 'Subscription', 'Arg', 'Args', 'ArgsType', 'Ctx', 'Root',
19
+ 'Info', 'Field', 'FieldResolver', 'ObjectType', 'InputType', 'InterfaceType', 'Authorized',
20
+ 'UseMiddleware', 'Extensions', 'Directive', 'ID', 'Int', 'Float', 'GraphQLISODateTime',
21
+ 'GraphQLTimestamp', 'registerEnumType', 'createMethodDecorator', 'createParamDecorator',
22
+ 'buildSchema', 'buildSchemaSync', 'PubSub',
23
+ ];
24
+ return Object.fromEntries(exportNames.map((name) => [name, decoratorFactory]));
25
+ });
26
+
27
+ vi.mock('@memberjunction/ai-agents', () => ({
28
+ AgentRunner: class {
29
+ RunAgentInConversation() {
30
+ return Promise.resolve({ agentResult: { success: true } });
31
+ }
32
+ },
33
+ ArtifactToolManager: class {},
34
+ }));
35
+
36
+ vi.mock('../realtimeWidget/widgetGuestElevation.js', () => ({
37
+ ResolveWidgetGuestRunContext: vi.fn().mockResolvedValue(null),
38
+ ElevateUserPayload: vi.fn(),
39
+ }));
40
+
41
+ import { RunAIAgentResolver } from '../resolvers/RunAIAgentResolver.js';
42
+ import type { AppContext, UserPayload } from '../types.js';
43
+
44
+ const USER = { ID: 'user-1', Email: 'user@example.com' };
45
+ const STOPPED_RUN = '16787b44-29f6-44a5-8bd4-fc1538e79275';
46
+
47
+ type Fn = ReturnType<typeof vi.fn>;
48
+
49
+ interface ResolverSeams {
50
+ CheckAPIKeyScopeAuthorization: Fn;
51
+ GetUserFromPayload: Fn;
52
+ loadConversationHistoryWithAttachments: Fn;
53
+ executeAIAgent: Fn;
54
+ executeAgentInBackground: Fn;
55
+ findUserStoppedPredecessorRunId: Fn;
56
+ }
57
+
58
+ /** Argument positions of lastRunId / autoPopulateLastRunPayload on the two dispatch seams. */
59
+ const SYNC_LAST_RUN = 10, SYNC_AUTO = 11, BG_LAST_RUN = 9, BG_AUTO = 10;
60
+
61
+ function makeResolver(): { resolver: RunAIAgentResolver; seams: ResolverSeams } {
62
+ const resolver = new RunAIAgentResolver();
63
+ const seams = resolver as unknown as ResolverSeams;
64
+ seams.CheckAPIKeyScopeAuthorization = vi.fn().mockResolvedValue(undefined);
65
+ seams.GetUserFromPayload = vi.fn().mockReturnValue(USER);
66
+ seams.loadConversationHistoryWithAttachments = vi.fn().mockResolvedValue([]);
67
+ seams.executeAIAgent = vi.fn().mockResolvedValue({ success: true, result: '{}' });
68
+ seams.executeAgentInBackground = vi.fn();
69
+ seams.findUserStoppedPredecessorRunId = vi.fn().mockResolvedValue(null);
70
+ return { resolver, seams };
71
+ }
72
+
73
+ function makeContext(branchId: string | null = null): AppContext {
74
+ const provider = {
75
+ GetEntityObject: vi.fn().mockResolvedValue({ ConversationID: 'conv-1', BranchID: branchId, Load: vi.fn().mockResolvedValue(true) }),
76
+ };
77
+ return {
78
+ userPayload: { sessionId: 'session-1', userRecord: USER } as unknown as UserPayload,
79
+ providers: [{ type: 'Read-Write', provider }],
80
+ dataSource: {},
81
+ } as unknown as AppContext;
82
+ }
83
+
84
+ const pubSub = { publish: vi.fn() } as unknown as PubSubEngine;
85
+
86
+ async function runMutation(
87
+ resolver: RunAIAgentResolver,
88
+ options: { payload?: string; lastRunId?: string; autoPopulate?: boolean; fireAndForget?: boolean; branchId?: string | null }
89
+ ) {
90
+ return resolver.RunAIAgentFromConversationDetail(
91
+ 'detail-1', 'agent-1', makeContext(options.branchId ?? null), 'session-1', pubSub,
92
+ undefined, undefined, options.payload, options.lastRunId, options.autoPopulate, undefined, undefined, undefined,
93
+ undefined, undefined, options.fireAndForget, undefined, undefined,
94
+ undefined
95
+ );
96
+ }
97
+
98
+ afterEach(() => {
99
+ vi.restoreAllMocks();
100
+ });
101
+
102
+ describe('RunAIAgentFromConversationDetail — continuing from a user-stopped run', () => {
103
+ let resolver: RunAIAgentResolver;
104
+ let seams: ResolverSeams;
105
+
106
+ beforeEach(() => {
107
+ ({ resolver, seams } = makeResolver());
108
+ });
109
+
110
+ it('chains the new run to the stopped predecessor and rolls its payload in when none was supplied', async () => {
111
+ seams.findUserStoppedPredecessorRunId.mockResolvedValue(STOPPED_RUN);
112
+
113
+ const result = await runMutation(resolver, {});
114
+
115
+ expect(result.success).toBe(true);
116
+ expect(seams.findUserStoppedPredecessorRunId).toHaveBeenCalledWith('conv-1', 'agent-1', null, USER, expect.anything());
117
+ const args = seams.executeAIAgent.mock.calls[0];
118
+ expect(args[SYNC_LAST_RUN]).toBe(STOPPED_RUN);
119
+ expect(args[SYNC_AUTO]).toBe(true);
120
+ });
121
+
122
+ it('keeps the caller\'s payload as the start when one was supplied (chains, but does not roll the old one in)', async () => {
123
+ seams.findUserStoppedPredecessorRunId.mockResolvedValue(STOPPED_RUN);
124
+
125
+ await runMutation(resolver, { payload: '{"fromArtifact":true}' });
126
+
127
+ const args = seams.executeAIAgent.mock.calls[0];
128
+ expect(args[SYNC_LAST_RUN]).toBe(STOPPED_RUN);
129
+ expect(args[SYNC_AUTO]).toBeUndefined();
130
+ });
131
+
132
+ it('hands the chain to a fire-and-forget run too', async () => {
133
+ seams.findUserStoppedPredecessorRunId.mockResolvedValue(STOPPED_RUN);
134
+
135
+ await runMutation(resolver, { fireAndForget: true });
136
+
137
+ expect(seams.executeAIAgent).not.toHaveBeenCalled();
138
+ const args = seams.executeAgentInBackground.mock.calls[0];
139
+ expect(args[BG_LAST_RUN]).toBe(STOPPED_RUN);
140
+ expect(args[BG_AUTO]).toBe(true);
141
+ });
142
+
143
+ it('looks up the predecessor on the branch the reply row was created on', async () => {
144
+ await runMutation(resolver, { branchId: 'B' });
145
+ expect(seams.findUserStoppedPredecessorRunId).toHaveBeenCalledWith('conv-1', 'agent-1', 'B', expect.anything(), expect.anything());
146
+ await runMutation(resolver, {});
147
+ expect(seams.findUserStoppedPredecessorRunId).toHaveBeenLastCalledWith('conv-1', 'agent-1', null, expect.anything(), expect.anything());
148
+ });
149
+
150
+ it('a caller-supplied lastRunId wins and the lookup is skipped', async () => {
151
+ await runMutation(resolver, { lastRunId: 'caller-run', autoPopulate: false });
152
+
153
+ expect(seams.findUserStoppedPredecessorRunId).not.toHaveBeenCalled();
154
+ const args = seams.executeAIAgent.mock.calls[0];
155
+ expect(args[SYNC_LAST_RUN]).toBe('caller-run');
156
+ expect(args[SYNC_AUTO]).toBe(false);
157
+ });
158
+
159
+ it('with no stopped predecessor the run is dispatched unchained, as before', async () => {
160
+ await runMutation(resolver, {});
161
+
162
+ const args = seams.executeAIAgent.mock.calls[0];
163
+ expect(args[SYNC_LAST_RUN]).toBeUndefined();
164
+ expect(args[SYNC_AUTO]).toBeUndefined();
165
+ });
166
+ });