@memberjunction/server 6.1.4 → 6.2.0-edge.1

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/dist/.tsbuildinfo +1 -1
  2. package/dist/agentSessions/ReturningVisitorRecap.d.ts +2 -0
  3. package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
  4. package/dist/agentSessions/ReturningVisitorRecap.js +5 -1
  5. package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
  6. package/dist/agentSessions/SessionManager.js +2 -2
  7. package/dist/agentSessions/remoteBrowserGoalEngine.d.ts +8 -0
  8. package/dist/agentSessions/remoteBrowserGoalEngine.d.ts.map +1 -1
  9. package/dist/agentSessions/remoteBrowserGoalEngine.js +21 -5
  10. package/dist/agentSessions/remoteBrowserGoalEngine.js.map +1 -1
  11. package/dist/auth/AuthProviderCatalogRouter.d.ts +2 -0
  12. package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
  13. package/dist/auth/AuthProviderCatalogRouter.js +5 -1
  14. package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
  15. package/dist/auth/exampleNewUserSubClass.js +2 -1
  16. package/dist/auth/exampleNewUserSubClass.js.map +1 -1
  17. package/dist/auth/index.d.ts +20 -1
  18. package/dist/auth/index.d.ts.map +1 -1
  19. package/dist/auth/index.js +20 -10
  20. package/dist/auth/index.js.map +1 -1
  21. package/dist/auth/initializeProviders.d.ts +8 -0
  22. package/dist/auth/initializeProviders.d.ts.map +1 -1
  23. package/dist/auth/initializeProviders.js +21 -5
  24. package/dist/auth/initializeProviders.js.map +1 -1
  25. package/dist/auth/magicLink/MagicLinkRouter.d.ts +9 -0
  26. package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
  27. package/dist/auth/magicLink/MagicLinkRouter.js +22 -10
  28. package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
  29. package/dist/auth/magicLink/MagicLinkService.d.ts +17 -15
  30. package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
  31. package/dist/auth/magicLink/MagicLinkService.js +65 -51
  32. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  33. package/dist/auth/magicLink/index.d.ts +2 -2
  34. package/dist/auth/magicLink/index.d.ts.map +1 -1
  35. package/dist/auth/magicLink/index.js +2 -2
  36. package/dist/auth/magicLink/index.js.map +1 -1
  37. package/dist/auth/magicLink/magicLinkCore.d.ts +54 -33
  38. package/dist/auth/magicLink/magicLinkCore.d.ts.map +1 -1
  39. package/dist/auth/magicLink/magicLinkCore.js +61 -61
  40. package/dist/auth/magicLink/magicLinkCore.js.map +1 -1
  41. package/dist/auth/magicLink/redeemLanding.d.ts +4 -0
  42. package/dist/auth/magicLink/redeemLanding.d.ts.map +1 -1
  43. package/dist/auth/magicLink/redeemLanding.js +12 -4
  44. package/dist/auth/magicLink/redeemLanding.js.map +1 -1
  45. package/dist/auth/magicLink/types.d.ts +4 -4
  46. package/dist/auth/principals.d.ts +2 -0
  47. package/dist/auth/principals.d.ts.map +1 -1
  48. package/dist/auth/principals.js +6 -2
  49. package/dist/auth/principals.js.map +1 -1
  50. package/dist/cache.d.ts +2 -0
  51. package/dist/cache.d.ts.map +1 -1
  52. package/dist/cache.js +3 -1
  53. package/dist/cache.js.map +1 -1
  54. package/dist/config.d.ts +293 -2
  55. package/dist/config.d.ts.map +1 -1
  56. package/dist/config.js +11 -4
  57. package/dist/config.js.map +1 -1
  58. package/dist/context.d.ts +20 -0
  59. package/dist/context.d.ts.map +1 -1
  60. package/dist/context.js +27 -19
  61. package/dist/context.js.map +1 -1
  62. package/dist/directives/Public.d.ts +2 -0
  63. package/dist/directives/Public.d.ts.map +1 -1
  64. package/dist/directives/Public.js +3 -1
  65. package/dist/directives/Public.js.map +1 -1
  66. package/dist/directives/RequireSystemUser.d.ts +2 -0
  67. package/dist/directives/RequireSystemUser.d.ts.map +1 -1
  68. package/dist/directives/RequireSystemUser.js +3 -1
  69. package/dist/directives/RequireSystemUser.js.map +1 -1
  70. package/dist/generated/graphql-schemas/__mj.d.ts +266 -4
  71. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  72. package/dist/generated/graphql-schemas/__mj.js +1304 -0
  73. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  74. package/dist/generic/CacheInvalidationResolver.d.ts +8 -2
  75. package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
  76. package/dist/generic/CacheInvalidationResolver.js +7 -3
  77. package/dist/generic/CacheInvalidationResolver.js.map +1 -1
  78. package/dist/generic/FireAndForgetHeartbeat.d.ts +3 -1
  79. package/dist/generic/FireAndForgetHeartbeat.d.ts.map +1 -1
  80. package/dist/generic/FireAndForgetHeartbeat.js +8 -4
  81. package/dist/generic/FireAndForgetHeartbeat.js.map +1 -1
  82. package/dist/generic/PushStatusResolver.d.ts +10 -1
  83. package/dist/generic/PushStatusResolver.d.ts.map +1 -1
  84. package/dist/generic/PushStatusResolver.js +11 -3
  85. package/dist/generic/PushStatusResolver.js.map +1 -1
  86. package/dist/generic/ResolverBase.d.ts +27 -1
  87. package/dist/generic/ResolverBase.d.ts.map +1 -1
  88. package/dist/generic/ResolverBase.js +64 -6
  89. package/dist/generic/ResolverBase.js.map +1 -1
  90. package/dist/index.d.ts +6 -0
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +29 -6
  93. package/dist/index.js.map +1 -1
  94. package/dist/integration/CustomColumnPromoter.d.ts +2 -0
  95. package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
  96. package/dist/integration/CustomColumnPromoter.js +5 -1
  97. package/dist/integration/CustomColumnPromoter.js.map +1 -1
  98. package/dist/integration/EntityMapLifecycle.d.ts +4 -0
  99. package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
  100. package/dist/integration/EntityMapLifecycle.js +10 -2
  101. package/dist/integration/EntityMapLifecycle.js.map +1 -1
  102. package/dist/logging/NoLog.d.ts +4 -0
  103. package/dist/logging/NoLog.d.ts.map +1 -1
  104. package/dist/logging/NoLog.js +10 -2
  105. package/dist/logging/NoLog.js.map +1 -1
  106. package/dist/logging/StartupLogger.d.ts +2 -0
  107. package/dist/logging/StartupLogger.d.ts.map +1 -1
  108. package/dist/logging/StartupLogger.js +5 -1
  109. package/dist/logging/StartupLogger.js.map +1 -1
  110. package/dist/logging/bootAudit.d.ts +11 -7
  111. package/dist/logging/bootAudit.d.ts.map +1 -1
  112. package/dist/logging/bootAudit.js +15 -7
  113. package/dist/logging/bootAudit.js.map +1 -1
  114. package/dist/logging/boundaryLogPayload.d.ts +4 -0
  115. package/dist/logging/boundaryLogPayload.d.ts.map +1 -1
  116. package/dist/logging/boundaryLogPayload.js +5 -1
  117. package/dist/logging/boundaryLogPayload.js.map +1 -1
  118. package/dist/logging/secretRedactor.d.ts +2 -0
  119. package/dist/logging/secretRedactor.d.ts.map +1 -1
  120. package/dist/logging/secretRedactor.js +8 -4
  121. package/dist/logging/secretRedactor.js.map +1 -1
  122. package/dist/logging/shortenForLog.d.ts +2 -0
  123. package/dist/logging/shortenForLog.d.ts.map +1 -1
  124. package/dist/logging/shortenForLog.js +7 -3
  125. package/dist/logging/shortenForLog.js.map +1 -1
  126. package/dist/logging/variablesLoggingMiddleware.d.ts +2 -0
  127. package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
  128. package/dist/logging/variablesLoggingMiddleware.js +8 -6
  129. package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
  130. package/dist/metadataRefreshSignal.d.ts +19 -0
  131. package/dist/metadataRefreshSignal.d.ts.map +1 -0
  132. package/dist/metadataRefreshSignal.js +45 -0
  133. package/dist/metadataRefreshSignal.js.map +1 -0
  134. package/dist/middleware/MJTenantFilterMiddleware.js +4 -4
  135. package/dist/multiTenancy/index.d.ts +8 -0
  136. package/dist/multiTenancy/index.d.ts.map +1 -1
  137. package/dist/multiTenancy/index.js +21 -5
  138. package/dist/multiTenancy/index.js.map +1 -1
  139. package/dist/realtimeWidget/WidgetRouter.d.ts +5 -0
  140. package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
  141. package/dist/realtimeWidget/WidgetRouter.js +14 -10
  142. package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
  143. package/dist/realtimeWidget/WidgetSessionService.d.ts +6 -6
  144. package/dist/realtimeWidget/WidgetSessionService.js +27 -27
  145. package/dist/realtimeWidget/host-identity.d.ts +5 -1
  146. package/dist/realtimeWidget/host-identity.d.ts.map +1 -1
  147. package/dist/realtimeWidget/host-identity.js +11 -3
  148. package/dist/realtimeWidget/host-identity.js.map +1 -1
  149. package/dist/realtimeWidget/index.d.ts +2 -2
  150. package/dist/realtimeWidget/index.d.ts.map +1 -1
  151. package/dist/realtimeWidget/index.js +2 -2
  152. package/dist/realtimeWidget/index.js.map +1 -1
  153. package/dist/realtimeWidget/visitorIdentity.d.ts +21 -1
  154. package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
  155. package/dist/realtimeWidget/visitorIdentity.js +16 -4
  156. package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
  157. package/dist/realtimeWidget/widgetCore.d.ts +48 -0
  158. package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
  159. package/dist/realtimeWidget/widgetCore.js +38 -10
  160. package/dist/realtimeWidget/widgetCore.js.map +1 -1
  161. package/dist/realtimeWidget/widgetGuestElevation.d.ts +10 -6
  162. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  163. package/dist/realtimeWidget/widgetGuestElevation.js +14 -6
  164. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  165. package/dist/resolvers/AdhocQueryResolver.js +3 -3
  166. package/dist/resolvers/FetchEntityVectorsResolver.js +2 -2
  167. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  168. package/dist/resolvers/FileResolver.js +3 -3
  169. package/dist/resolvers/GeoResolver.d.ts +2 -2
  170. package/dist/resolvers/GeoResolver.js +4 -4
  171. package/dist/resolvers/GetDataResolver.d.ts +14 -0
  172. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  173. package/dist/resolvers/GetDataResolver.js +43 -15
  174. package/dist/resolvers/GetDataResolver.js.map +1 -1
  175. package/dist/resolvers/IntegrationDiscoveryResolver.js +2 -2
  176. package/dist/resolvers/ListOperationsResolver.d.ts +20 -0
  177. package/dist/resolvers/ListOperationsResolver.d.ts.map +1 -1
  178. package/dist/resolvers/ListOperationsResolver.js +68 -28
  179. package/dist/resolvers/ListOperationsResolver.js.map +1 -1
  180. package/dist/resolvers/MCPResolver.d.ts +11 -1
  181. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  182. package/dist/resolvers/MCPResolver.js +7 -3
  183. package/dist/resolvers/MCPResolver.js.map +1 -1
  184. package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
  185. package/dist/resolvers/QuerySystemUserResolver.js +2 -1
  186. package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
  187. package/dist/resolvers/RealtimeBridgeResolver.js +3 -3
  188. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +37 -0
  189. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  190. package/dist/resolvers/RealtimeClientSessionResolver.js +101 -11
  191. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  192. package/dist/resolvers/RemoteBrowserActionResolver.js +5 -5
  193. package/dist/resolvers/RunAIAgentResolver.d.ts +10 -4
  194. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  195. package/dist/resolvers/RunAIAgentResolver.js +74 -42
  196. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  197. package/dist/resolvers/RunAIPromptResolver.d.ts +1 -1
  198. package/dist/resolvers/RunAIPromptResolver.js +2 -2
  199. package/dist/resolvers/RunTestResolver.js +5 -5
  200. package/dist/resolvers/SearchEntitiesResolver.d.ts.map +1 -1
  201. package/dist/resolvers/SearchEntitiesResolver.js +3 -1
  202. package/dist/resolvers/SearchEntitiesResolver.js.map +1 -1
  203. package/dist/resolvers/SearchKnowledgeResolver.d.ts +1 -0
  204. package/dist/resolvers/SearchKnowledgeResolver.d.ts.map +1 -1
  205. package/dist/resolvers/SearchKnowledgeResolver.js +5 -0
  206. package/dist/resolvers/SearchKnowledgeResolver.js.map +1 -1
  207. package/dist/resolvers/SearchKnowledgeSystemUserResolver.d.ts.map +1 -1
  208. package/dist/resolvers/SearchKnowledgeSystemUserResolver.js +1 -0
  209. package/dist/resolvers/SearchKnowledgeSystemUserResolver.js.map +1 -1
  210. package/dist/resolvers/SqlLoggingConfigResolver.d.ts +8 -4
  211. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  212. package/dist/resolvers/SqlLoggingConfigResolver.js +5 -5
  213. package/dist/resolvers/TaskGraphFrameResolver.d.ts +8 -1
  214. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
  215. package/dist/resolvers/TaskGraphFrameResolver.js +6 -2
  216. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
  217. package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
  218. package/dist/resolvers/TransactionGroupResolver.js +53 -4
  219. package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
  220. package/dist/resolvers/adhoc-query-helpers.d.ts +6 -0
  221. package/dist/resolvers/adhoc-query-helpers.d.ts.map +1 -1
  222. package/dist/resolvers/adhoc-query-helpers.js +10 -2
  223. package/dist/resolvers/adhoc-query-helpers.js.map +1 -1
  224. package/dist/resolvers/artifact-routing.d.ts +8 -8
  225. package/dist/resolvers/artifact-routing.js +2 -2
  226. package/dist/resolvers/artifact-routing.js.map +1 -1
  227. package/dist/resolvers/meetingRecordingRegistration.d.ts +10 -2
  228. package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
  229. package/dist/resolvers/meetingRecordingRegistration.js +24 -8
  230. package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
  231. package/dist/resolvers/peaksSidecar.d.ts +4 -0
  232. package/dist/resolvers/peaksSidecar.d.ts.map +1 -1
  233. package/dist/resolvers/peaksSidecar.js +10 -2
  234. package/dist/resolvers/peaksSidecar.js.map +1 -1
  235. package/dist/rest/EntityCRUDHandler.d.ts +28 -0
  236. package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
  237. package/dist/rest/EntityCRUDHandler.js +20 -4
  238. package/dist/rest/EntityCRUDHandler.js.map +1 -1
  239. package/dist/rest/MediaStreamHandler.d.ts +2 -0
  240. package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
  241. package/dist/rest/MediaStreamHandler.js +10 -6
  242. package/dist/rest/MediaStreamHandler.js.map +1 -1
  243. package/dist/rest/OAuthCallbackHandler.d.ts +9 -0
  244. package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
  245. package/dist/rest/OAuthCallbackHandler.js +15 -3
  246. package/dist/rest/OAuthCallbackHandler.js.map +1 -1
  247. package/dist/rest/RESTEndpointHandler.d.ts +6 -4
  248. package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
  249. package/dist/rest/RESTEndpointHandler.js +15 -11
  250. package/dist/rest/RESTEndpointHandler.js.map +1 -1
  251. package/dist/rest/RealtimeSdpBrokerHandler.d.ts +5 -1
  252. package/dist/rest/RealtimeSdpBrokerHandler.d.ts.map +1 -1
  253. package/dist/rest/RealtimeSdpBrokerHandler.js +12 -4
  254. package/dist/rest/RealtimeSdpBrokerHandler.js.map +1 -1
  255. package/dist/rest/SignatureWebhookHandler.d.ts +2 -0
  256. package/dist/rest/SignatureWebhookHandler.d.ts.map +1 -1
  257. package/dist/rest/SignatureWebhookHandler.js +5 -1
  258. package/dist/rest/SignatureWebhookHandler.js.map +1 -1
  259. package/dist/rest/UploadTokenManager.d.ts +24 -8
  260. package/dist/rest/UploadTokenManager.d.ts.map +1 -1
  261. package/dist/rest/UploadTokenManager.js +53 -21
  262. package/dist/rest/UploadTokenManager.js.map +1 -1
  263. package/dist/rest/ViewOperationsHandler.d.ts +20 -0
  264. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  265. package/dist/rest/ViewOperationsHandler.js +20 -4
  266. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  267. package/dist/rest/mediaRange.d.ts +4 -0
  268. package/dist/rest/mediaRange.d.ts.map +1 -1
  269. package/dist/rest/mediaRange.js +10 -2
  270. package/dist/rest/mediaRange.js.map +1 -1
  271. package/dist/rest/setupRESTEndpoints.d.ts +4 -0
  272. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  273. package/dist/rest/setupRESTEndpoints.js +13 -7
  274. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  275. package/dist/serverExtensionReservedRoots.d.ts +2 -0
  276. package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
  277. package/dist/serverExtensionReservedRoots.js +5 -1
  278. package/dist/serverExtensionReservedRoots.js.map +1 -1
  279. package/dist/services/MJStorageBlobStore.d.ts +41 -0
  280. package/dist/services/MJStorageBlobStore.d.ts.map +1 -0
  281. package/dist/services/MJStorageBlobStore.js +160 -0
  282. package/dist/services/MJStorageBlobStore.js.map +1 -0
  283. package/dist/services/TaskGraphActionRunner.d.ts +13 -8
  284. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  285. package/dist/services/TaskGraphActionRunner.js +16 -15
  286. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  287. package/dist/types.d.ts +2 -0
  288. package/dist/types.d.ts.map +1 -1
  289. package/dist/types.js +7 -3
  290. package/dist/types.js.map +1 -1
  291. package/dist/util.d.ts +12 -3
  292. package/dist/util.d.ts.map +1 -1
  293. package/dist/util.js +19 -8
  294. package/dist/util.js.map +1 -1
  295. package/package.json +92 -92
  296. package/src/__tests__/FileResolverPeaks.test.ts +13 -13
  297. package/src/__tests__/ListOperationsResolver.test.ts +17 -17
  298. package/src/__tests__/MediaStreamHandler.test.ts +28 -28
  299. package/src/__tests__/NoLog.test.ts +11 -11
  300. package/src/__tests__/PrimaryKeyAlwaysMapped.test.ts +10 -10
  301. package/src/__tests__/RESTEndpointHandler.test.ts +14 -14
  302. package/src/__tests__/RealtimeBridgeResolver.test.ts +4 -2
  303. package/src/__tests__/RealtimeClientSessionResolver.test.ts +229 -0
  304. package/src/__tests__/RealtimeSdpBrokerHandler.test.ts +6 -6
  305. package/src/__tests__/RefreshAdoptsNewColumns.test.ts +8 -8
  306. package/src/__tests__/RemoteBrowserGoalEngine.test.ts +18 -18
  307. package/src/__tests__/ResolverBase.isaPromotionCreate.test.ts +412 -0
  308. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +228 -0
  309. package/src/__tests__/SearchEntitiesResolver.readOnlyFallback.test.ts +78 -0
  310. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +129 -0
  311. package/src/__tests__/TaskGraphFrameResolver.test.ts +2 -2
  312. package/src/__tests__/TransactionGroupResolver.refusals.test.ts +290 -0
  313. package/src/__tests__/WidgetSessionService.test.ts +8 -4
  314. package/src/__tests__/adhoc-query-helpers.test.ts +21 -21
  315. package/src/__tests__/bootAudit.test.ts +11 -11
  316. package/src/__tests__/boundaryLogPayload.test.ts +6 -6
  317. package/src/__tests__/databaseAbstraction.test.ts +12 -6
  318. package/src/__tests__/getDataTokenRedaction.test.ts +7 -7
  319. package/src/__tests__/initializeProviders.refresh.test.ts +4 -4
  320. package/src/__tests__/magicLink.test.ts +73 -134
  321. package/src/__tests__/magicLinkService.consume.test.ts +224 -0
  322. package/src/__tests__/meetingRecordingRegistration.test.ts +12 -12
  323. package/src/__tests__/metadataRefreshSignal.test.ts +78 -0
  324. package/src/__tests__/multiTenancy.security.test.ts +40 -40
  325. package/src/__tests__/multiTenancy.test.ts +18 -18
  326. package/src/__tests__/newUsers.test.ts +24 -23
  327. package/src/__tests__/principals.test.ts +22 -22
  328. package/src/__tests__/pushStatusResolver.filter.test.ts +8 -8
  329. package/src/__tests__/secretRedactor.failOpen.test.ts +12 -12
  330. package/src/__tests__/secretRedactor.test.ts +12 -12
  331. package/src/__tests__/serverExtensionReservedRoots.test.ts +7 -7
  332. package/src/__tests__/subscriptionRedaction.test.ts +5 -5
  333. package/src/__tests__/unifiedAuth.test.ts +15 -9
  334. package/src/__tests__/visitorIdentity.resolve.test.ts +6 -6
  335. package/src/__tests__/widget.test.ts +45 -45
  336. package/src/__tests__/widgetGuestElevation.test.ts +7 -7
  337. package/src/__tests__/widgetHostIdentity.test.ts +14 -14
  338. package/src/agentSessions/ReturningVisitorRecap.ts +12 -1
  339. package/src/agentSessions/SessionManager.ts +2 -2
  340. package/src/agentSessions/remoteBrowserGoalEngine.ts +30 -5
  341. package/src/auth/AuthProviderCatalogRouter.ts +6 -1
  342. package/src/auth/__tests__/backward-compatibility.test.ts +3 -3
  343. package/src/auth/exampleNewUserSubClass.ts +2 -2
  344. package/src/auth/index.ts +43 -28
  345. package/src/auth/initializeProviders.ts +25 -5
  346. package/src/auth/magicLink/MagicLinkRouter.ts +28 -10
  347. package/src/auth/magicLink/MagicLinkService.ts +71 -52
  348. package/src/auth/magicLink/index.ts +7 -7
  349. package/src/auth/magicLink/magicLinkCore.ts +96 -64
  350. package/src/auth/magicLink/redeemLanding.ts +14 -4
  351. package/src/auth/magicLink/types.ts +54 -54
  352. package/src/auth/newUsers.ts +1 -1
  353. package/src/auth/principals.ts +11 -2
  354. package/src/cache.ts +4 -1
  355. package/src/config.ts +14 -4
  356. package/src/context.ts +37 -24
  357. package/src/directives/Public.ts +4 -1
  358. package/src/directives/RequireSystemUser.ts +4 -1
  359. package/src/generated/graphql-schemas/__mj.ts +933 -5
  360. package/src/generic/CacheInvalidationResolver.ts +12 -4
  361. package/src/generic/FireAndForgetHeartbeat.ts +19 -14
  362. package/src/generic/PushStatusResolver.ts +21 -7
  363. package/src/generic/ResolverBase.ts +66 -5
  364. package/src/generic/RunViewResolver.ts +22 -22
  365. package/src/generic/__tests__/FireAndForgetHeartbeat.test.ts +7 -7
  366. package/src/index.ts +34 -7
  367. package/src/integration/CustomColumnPromoter.ts +6 -1
  368. package/src/integration/EntityMapLifecycle.ts +20 -2
  369. package/src/logging/NoLog.ts +16 -2
  370. package/src/logging/StartupLogger.ts +6 -1
  371. package/src/logging/bootAudit.ts +26 -16
  372. package/src/logging/boundaryLogPayload.ts +8 -1
  373. package/src/logging/secretRedactor.ts +14 -9
  374. package/src/logging/shortenForLog.ts +8 -3
  375. package/src/logging/variablesLoggingMiddleware.ts +9 -6
  376. package/src/metadataRefreshSignal.ts +45 -0
  377. package/src/middleware/MJTenantFilterMiddleware.ts +4 -4
  378. package/src/multiTenancy/index.ts +29 -5
  379. package/src/realtimeWidget/WidgetRouter.ts +15 -10
  380. package/src/realtimeWidget/WidgetSessionService.ts +76 -76
  381. package/src/realtimeWidget/host-identity.ts +24 -10
  382. package/src/realtimeWidget/index.ts +3 -3
  383. package/src/realtimeWidget/visitorIdentity.ts +39 -8
  384. package/src/realtimeWidget/widgetCore.ts +75 -10
  385. package/src/realtimeWidget/widgetGuestElevation.ts +25 -12
  386. package/src/resolvers/AdhocQueryResolver.ts +3 -3
  387. package/src/resolvers/AgentSessionResolver.ts +3 -3
  388. package/src/resolvers/ColorResolver.ts +6 -6
  389. package/src/resolvers/ComponentRegistryResolver.ts +36 -36
  390. package/src/resolvers/EntityCommunicationsResolver.ts +4 -4
  391. package/src/resolvers/ExecuteRemoteOperationResolver.ts +9 -9
  392. package/src/resolvers/FetchEntityVectorsResolver.ts +2 -2
  393. package/src/resolvers/FileResolver.ts +42 -42
  394. package/src/resolvers/GeoResolver.ts +4 -4
  395. package/src/resolvers/GetDataResolver.ts +50 -15
  396. package/src/resolvers/IntegrationDiscoveryResolver.ts +2 -2
  397. package/src/resolvers/ListOperationsResolver.ts +78 -28
  398. package/src/resolvers/MCPResolver.ts +30 -15
  399. package/src/resolvers/QueryResolver.ts +13 -13
  400. package/src/resolvers/QuerySystemUserResolver.ts +2 -1
  401. package/src/resolvers/RealtimeBridgeResolver.ts +3 -3
  402. package/src/resolvers/RealtimeClientSessionResolver.ts +126 -13
  403. package/src/resolvers/RemoteBrowserActionResolver.ts +5 -5
  404. package/src/resolvers/RunAIAgentResolver.ts +118 -76
  405. package/src/resolvers/RunAIPromptResolver.ts +22 -22
  406. package/src/resolvers/RunTemplateResolver.ts +4 -4
  407. package/src/resolvers/RunTestResolver.ts +25 -25
  408. package/src/resolvers/SearchEntitiesResolver.ts +3 -1
  409. package/src/resolvers/SearchKnowledgeResolver.ts +4 -0
  410. package/src/resolvers/SearchKnowledgeSystemUserResolver.ts +1 -0
  411. package/src/resolvers/SqlLoggingConfigResolver.ts +56 -56
  412. package/src/resolvers/TaskGraphFrameResolver.ts +37 -28
  413. package/src/resolvers/TelemetryResolver.ts +79 -79
  414. package/src/resolvers/TransactionGroupResolver.ts +57 -4
  415. package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +40 -38
  416. package/src/resolvers/__tests__/artifact-routing.test.ts +23 -23
  417. package/src/resolvers/adhoc-query-helpers.ts +19 -2
  418. package/src/resolvers/artifact-routing.ts +19 -19
  419. package/src/resolvers/meetingRecordingRegistration.ts +44 -10
  420. package/src/resolvers/peaksSidecar.ts +12 -2
  421. package/src/rest/EntityCRUDHandler.ts +24 -4
  422. package/src/rest/MediaStreamHandler.ts +11 -6
  423. package/src/rest/OAuthCallbackHandler.ts +25 -7
  424. package/src/rest/RESTEndpointHandler.ts +20 -15
  425. package/src/rest/RealtimeSdpBrokerHandler.ts +14 -4
  426. package/src/rest/SignatureWebhookHandler.ts +6 -1
  427. package/src/rest/UploadTokenManager.ts +66 -30
  428. package/src/rest/ViewOperationsHandler.ts +24 -4
  429. package/src/rest/mediaRange.ts +16 -6
  430. package/src/rest/setupRESTEndpoints.ts +24 -12
  431. package/src/serverExtensionReservedRoots.ts +6 -1
  432. package/src/services/MJStorageBlobStore.ts +209 -0
  433. package/src/services/TaskGraphActionRunner.ts +16 -15
  434. package/src/types.ts +21 -16
  435. package/src/util.ts +22 -9
@@ -188,26 +188,26 @@ describe('RESTEndpointHandler.isEntityAllowed', () => {
188
188
  });
189
189
 
190
190
  it('blocks entities in excluded schemas (case-insensitive), with schema exclusion taking top precedence', () => {
191
- const schemaOnly = makeHandler({ excludeSchemas: ['VAULT'] });
191
+ const schemaOnly = makeHandler({ ExcludeSchemas: ['VAULT'] });
192
192
  expect(schemaOnly.isEntityAllowed('Secrets')).toBe(false);
193
193
  expect(schemaOnly.isEntityAllowed('Users')).toBe(true); // other schemas unaffected
194
194
 
195
195
  // Even an explicit entity include cannot override a schema exclusion
196
- const withInclude = makeHandler({ excludeSchemas: ['vault'], includeEntities: ['secrets'] });
196
+ const withInclude = makeHandler({ ExcludeSchemas: ['vault'], IncludeEntities: ['secrets'] });
197
197
  expect(withInclude.isEntityAllowed('Secrets')).toBe(false);
198
198
  });
199
199
 
200
200
  it('restricts to included schemas when includeSchemas is set', () => {
201
- const handler = makeHandler({ includeSchemas: ['crm'] });
201
+ const handler = makeHandler({ IncludeSchemas: ['crm'] });
202
202
  expect(handler.isEntityAllowed('Users')).toBe(true);
203
203
  expect(handler.isEntityAllowed('Secrets')).toBe(false);
204
204
  });
205
205
 
206
206
  it('blocks lowercase exact-name exclusions and wildcard exclusions of any case', () => {
207
- const lowercase = makeHandler({ excludeEntities: ['secrets'] });
207
+ const lowercase = makeHandler({ ExcludeEntities: ['secrets'] });
208
208
  expect(lowercase.isEntityAllowed('Secrets')).toBe(false);
209
209
 
210
- const wildcard = makeHandler({ excludeEntities: ['Secret*'] });
210
+ const wildcard = makeHandler({ ExcludeEntities: ['Secret*'] });
211
211
  expect(wildcard.isEntityAllowed('Secrets')).toBe(false);
212
212
  expect(wildcard.isEntityAllowed('Users')).toBe(true);
213
213
  });
@@ -217,25 +217,25 @@ describe('RESTEndpointHandler.isEntityAllowed', () => {
217
217
  // the RAW configured pattern (only the wildcard branch lowercases patterns).
218
218
  // An operator writing excludeEntities: ['Secrets'] — the natural casing —
219
219
  // gets NO exclusion. Pinned so a normalization fix flips this test.
220
- const handler = makeHandler({ excludeEntities: ['Secrets'] });
220
+ const handler = makeHandler({ ExcludeEntities: ['Secrets'] });
221
221
  expect(handler.isEntityAllowed('Secrets')).toBe(true); // exclusion ineffective!
222
222
  });
223
223
 
224
224
  it('exclusions override inclusions for the same entity', () => {
225
- const handler = makeHandler({ includeEntities: ['user*'], excludeEntities: ['userroles'] });
225
+ const handler = makeHandler({ IncludeEntities: ['user*'], ExcludeEntities: ['userroles'] });
226
226
  expect(handler.isEntityAllowed('Users')).toBe(true);
227
227
  expect(handler.isEntityAllowed('UserRoles')).toBe(false);
228
228
  });
229
229
 
230
230
  it('an include list denies everything not on it, with wildcard support', () => {
231
- const handler = makeHandler({ includeEntities: ['user*'] });
231
+ const handler = makeHandler({ IncludeEntities: ['user*'] });
232
232
  expect(handler.isEntityAllowed('Users')).toBe(true);
233
233
  expect(handler.isEntityAllowed('UserRoles')).toBe(true);
234
234
  expect(handler.isEntityAllowed('Secrets')).toBe(false);
235
235
  });
236
236
 
237
237
  it('SECURITY GAP: a mixed-case exact inclusion fails to include (same raw-pattern comparison)', () => {
238
- const handler = makeHandler({ includeEntities: ['Users'] });
238
+ const handler = makeHandler({ IncludeEntities: ['Users'] });
239
239
  expect(handler.isEntityAllowed('Users')).toBe(false); // include list active, but never matches
240
240
  });
241
241
  });
@@ -271,7 +271,7 @@ describe('RESTEndpointHandler middleware', () => {
271
271
 
272
272
  describe('checkEntityAccess', () => {
273
273
  it('rejects blocked entities with 403 before any handler runs', () => {
274
- const handler = makeHandler({ excludeEntities: ['secrets'] });
274
+ const handler = makeHandler({ ExcludeEntities: ['secrets'] });
275
275
  const req = makeReq({ params: { entityName: 'Secrets' } });
276
276
  const { res, statusCode, jsonBody } = makeRes();
277
277
  const next = vi.fn();
@@ -286,7 +286,7 @@ describe('RESTEndpointHandler middleware', () => {
286
286
  });
287
287
 
288
288
  it('passes allowed entities through', () => {
289
- const handler = makeHandler({ excludeEntities: ['secrets'] });
289
+ const handler = makeHandler({ ExcludeEntities: ['secrets'] });
290
290
  const next = vi.fn();
291
291
 
292
292
  handler.checkEntityAccess(makeReq({ params: { entityName: 'Users' } }), makeRes().res, next);
@@ -295,7 +295,7 @@ describe('RESTEndpointHandler middleware', () => {
295
295
  });
296
296
 
297
297
  it('passes through when no entityName param is present', () => {
298
- const handler = makeHandler({ includeEntities: ['nothing'] });
298
+ const handler = makeHandler({ IncludeEntities: ['nothing'] });
299
299
  const next = vi.fn();
300
300
 
301
301
  handler.checkEntityAccess(makeReq({ params: {} }), makeRes().res, next);
@@ -565,7 +565,7 @@ describe('RESTEndpointHandler view routes', () => {
565
565
  });
566
566
 
567
567
  it('returns 403 WITHOUT invoking the view layer when every requested entity is blocked', async () => {
568
- const handler = makeHandler({ includeEntities: ['users'] });
568
+ const handler = makeHandler({ IncludeEntities: ['users'] });
569
569
  const { res, statusCode } = makeRes();
570
570
 
571
571
  await handler.runViews(
@@ -579,7 +579,7 @@ describe('RESTEndpointHandler view routes', () => {
579
579
 
580
580
  it('silently drops blocked entities and executes only the allowed remainder', async () => {
581
581
  mockOpsRunViews.mockResolvedValue({ success: true, results: [{ Success: true, Results: [] }] });
582
- const handler = makeHandler({ excludeEntities: ['secrets'] });
582
+ const handler = makeHandler({ ExcludeEntities: ['secrets'] });
583
583
  const req = makeReq({ body: { params: [{ EntityName: 'Users' }, { EntityName: 'Secrets' }] } });
584
584
  const { res, jsonBody } = makeRes();
585
585
 
@@ -50,8 +50,10 @@ vi.mock('@memberjunction/ai-agents', () => ({
50
50
  // Mock the meeting-recording registration so the thin resolver is tested in isolation (no MJStorage /
51
51
  // core-entities graph). Its own behavior is covered by meetingRecordingRegistration.test.ts.
52
52
  vi.mock('../resolvers/meetingRecordingRegistration', () => ({
53
- registerMeetingRecordingFile: vi.fn(async () => ({ Success: true, RecordingFileID: 'file-1', ConversationID: 'conv-1' })),
54
- correlateRecordingStart: vi.fn(async () => true),
53
+ RegisterMeetingRecordingFile: vi.fn(async () => ({ Success: true, RecordingFileID: 'file-1', ConversationID: 'conv-1' })),
54
+ get registerMeetingRecordingFile() { return this.RegisterMeetingRecordingFile; },
55
+ CorrelateRecordingStart: vi.fn(async () => true),
56
+ get correlateRecordingStart() { return this.CorrelateRecordingStart; },
55
57
  }));
56
58
 
57
59
  import { RealtimeBridgeResolver, MintLiveKitClientTokenInput, LiveKitRecordingInput } from '../resolvers/RealtimeBridgeResolver';
@@ -3196,3 +3196,232 @@ describe('RealtimeClientSessionResolver — colleague authorization (allowedAgen
3196
3196
  expect(hasPermissionMock).not.toHaveBeenCalled();
3197
3197
  });
3198
3198
  });
3199
+
3200
+ /**
3201
+ * The other half of the voice/text context flow.
3202
+ *
3203
+ * Voice turns were always persisted as `MJ: Conversation Details`, so anything SAID reached a later
3204
+ * typed turn. Nothing TYPED reached a voice session: `ConversationMessages` was a hardcoded `[]`
3205
+ * with an MVP note. A call started mid-thread therefore opened with no idea what the thread was
3206
+ * about — and the symptom is not an error, it is the agent asking the user to repeat something they
3207
+ * just wrote.
3208
+ */
3209
+ describe('RealtimeClientSessionResolver — conversation-history hydration', () => {
3210
+ /** A `MJ: Conversation Details` row as the history query reads it. */
3211
+ interface HistoryRow {
3212
+ ID: string;
3213
+ Role: string;
3214
+ Message: string | null;
3215
+ HiddenToUser: boolean;
3216
+ AgentSessionID: string | null;
3217
+ }
3218
+
3219
+ function row(
3220
+ role: 'User' | 'AI' | 'Error',
3221
+ message: string | null,
3222
+ over: Partial<HistoryRow> = {},
3223
+ ): HistoryRow {
3224
+ return { ID: `h-${message ?? 'x'}`, Role: role, Message: message, HiddenToUser: false, AgentSessionID: null, ...over };
3225
+ }
3226
+
3227
+ /**
3228
+ * Provider that answers BOTH Conversation Details queries separately: the prior-leg transcript
3229
+ * (filtered by `AgentSessionID IN (…)`) and the conversation history (`ConversationID=…`).
3230
+ * Routing on the filter is what keeps the two from being confused for one another.
3231
+ */
3232
+ function makeProvider(opts: {
3233
+ chain?: Record<string, { UserID: string; LastSessionID?: string | null }>;
3234
+ legRows?: Array<{ ID: string; Role: string; Message: string | null; HiddenToUser: boolean }>;
3235
+ historyRows?: HistoryRow[];
3236
+ historyFails?: boolean;
3237
+ }): { provider: unknown; runView: ReturnType<typeof vi.fn> } {
3238
+ const runView = vi.fn(async (params: { EntityName: string; ExtraFilter?: string }) => {
3239
+ if (params.EntityName === 'MJ: Conversation Details') {
3240
+ if (params.ExtraFilter?.startsWith('AgentSessionID IN')) {
3241
+ return { Success: true, Results: opts.legRows ?? [] };
3242
+ }
3243
+ return opts.historyFails
3244
+ ? { Success: false, ErrorMessage: 'db down', Results: [] }
3245
+ : { Success: true, Results: opts.historyRows ?? [] };
3246
+ }
3247
+ return { Success: true, Results: [] };
3248
+ });
3249
+ const provider = {
3250
+ GetEntityObject: vi.fn(async () => {
3251
+ const entity = makeSessionEntity();
3252
+ entity.Load = vi.fn(async (id: string) => {
3253
+ const r = opts.chain?.[id];
3254
+ if (!r) return false;
3255
+ entity.ID = id;
3256
+ entity.UserID = r.UserID;
3257
+ entity.LastSessionID = r.LastSessionID ?? null;
3258
+ return true;
3259
+ });
3260
+ return entity;
3261
+ }),
3262
+ RunView: runView,
3263
+ };
3264
+ return { provider, runView };
3265
+ }
3266
+
3267
+ function historyArg(): Array<{ role: string; content: unknown }> {
3268
+ return (prepareClientSessionMock.mock.calls[0][0] as { ConversationMessages: Array<{ role: string; content: unknown }> })
3269
+ .ConversationMessages;
3270
+ }
3271
+
3272
+ /** A successful prepare, so the start reaches the point where the history is threaded. */
3273
+ const prepOk = {
3274
+ Success: true,
3275
+ ClientConfig: {
3276
+ Provider: 'openai',
3277
+ Model: 'gpt-realtime',
3278
+ EphemeralToken: 'ek_abc',
3279
+ ExpiresAt: '2026-01-01T00:00:00Z',
3280
+ SessionConfig: {},
3281
+ },
3282
+ };
3283
+
3284
+ beforeEach(() => {
3285
+ hasPermissionMock.mockResolvedValue(true);
3286
+ createSessionMock.mockResolvedValue(makeSessionEntity({ ID: 'session-new' }));
3287
+ prepareClientSessionMock.mockResolvedValue(prepOk);
3288
+ });
3289
+
3290
+ it('hydrates the typed conversation as role-mapped chat messages', async () => {
3291
+ const { provider } = makeProvider({
3292
+ historyRows: [row('User', 'what does my pipeline look like'), row('AI', 'eleven open deals')],
3293
+ });
3294
+ currentProvider = provider;
3295
+
3296
+ await makeResolver().StartRealtimeClientSession('target-1', makeCtx(), 'conv-1');
3297
+
3298
+ expect(historyArg()).toEqual([
3299
+ { role: 'user', content: 'what does my pipeline look like' },
3300
+ { role: 'assistant', content: 'eleven open deals' },
3301
+ ]);
3302
+ });
3303
+
3304
+ it('scopes the read to the session\'s conversation', async () => {
3305
+ const { provider, runView } = makeProvider({ historyRows: [row('User', 'hi')] });
3306
+ currentProvider = provider;
3307
+
3308
+ await makeResolver().StartRealtimeClientSession('target-1', makeCtx(), "conv-o'brien");
3309
+
3310
+ const call = runView.mock.calls.find(
3311
+ (c) => (c[0] as { ExtraFilter?: string }).ExtraFilter?.startsWith('ConversationID='),
3312
+ );
3313
+ // The apostrophe must be doubled, not passed through — this string is concatenated into SQL.
3314
+ expect((call![0] as { ExtraFilter: string }).ExtraFilter).toBe("ConversationID='conv-o''brien'");
3315
+ });
3316
+
3317
+ it('skips hidden rows, error rows, and empty messages', async () => {
3318
+ const { provider } = makeProvider({
3319
+ historyRows: [
3320
+ row('User', 'kept'),
3321
+ row('User', 'system anchor', { HiddenToUser: true }),
3322
+ row('Error', 'the agent blew up'),
3323
+ row('AI', ' '),
3324
+ row('AI', null),
3325
+ ],
3326
+ });
3327
+ currentProvider = provider;
3328
+
3329
+ await makeResolver().StartRealtimeClientSession('target-1', makeCtx(), 'conv-1');
3330
+
3331
+ expect(historyArg()).toEqual([{ role: 'user', content: 'kept' }]);
3332
+ });
3333
+
3334
+ it('KEEPS turns from an earlier voice call that is not being resumed', async () => {
3335
+ // A call the user had last week is part of this conversation. The model should know it —
3336
+ // only the legs framed as the resumed transcript are removed, and there are none here.
3337
+ const { provider } = makeProvider({
3338
+ historyRows: [row('User', 'said last week', { AgentSessionID: 'sess-old' }), row('User', 'typed today')],
3339
+ });
3340
+ currentProvider = provider;
3341
+
3342
+ await makeResolver().StartRealtimeClientSession('target-1', makeCtx(), 'conv-1');
3343
+
3344
+ expect(historyArg().map((m) => m.content)).toEqual(['said last week', 'typed today']);
3345
+ });
3346
+
3347
+ it('DROPS turns the resumed transcript already framed, so the prompt carries one account of them', async () => {
3348
+ // The whole reason the leg ids travel with the prior transcript. A voice turn is an ordinary
3349
+ // Conversation Detail, so without this the resumed leg arrives twice in one prompt.
3350
+ const { provider } = makeProvider({
3351
+ chain: { 'prior-1': { UserID: 'user-1' } },
3352
+ legRows: [{ ID: 'l-1', Role: 'User', Message: 'said on the last call', HiddenToUser: false }],
3353
+ historyRows: [
3354
+ row('User', 'said on the last call', { AgentSessionID: 'prior-1' }),
3355
+ row('User', 'typed afterwards'),
3356
+ ],
3357
+ });
3358
+ currentProvider = provider;
3359
+
3360
+ await makeResolver().StartRealtimeClientSession('target-1', makeCtx(), 'conv-1', 'prior-1');
3361
+
3362
+ expect(historyArg().map((m) => m.content)).toEqual(['typed afterwards']);
3363
+ const prior = (prepareClientSessionMock.mock.calls[0][0] as { PriorTranscript?: string }).PriorTranscript;
3364
+ expect(prior).toBe('User: said on the last call');
3365
+ });
3366
+
3367
+ it('matches covered session ids case-insensitively', async () => {
3368
+ // SQL Server returns uppercase ids and PostgreSQL lowercase; a case-sensitive compare would
3369
+ // double-inject the resumed leg on one of the two.
3370
+ const { provider } = makeProvider({
3371
+ chain: { 'PRIOR-1': { UserID: 'user-1' } },
3372
+ legRows: [{ ID: 'l-1', Role: 'User', Message: 'said on the last call', HiddenToUser: false }],
3373
+ historyRows: [row('User', 'said on the last call', { AgentSessionID: 'prior-1' })],
3374
+ });
3375
+ currentProvider = provider;
3376
+
3377
+ await makeResolver().StartRealtimeClientSession('target-1', makeCtx(), 'conv-1', 'PRIOR-1');
3378
+
3379
+ expect(historyArg()).toEqual([]);
3380
+ });
3381
+
3382
+ it('keeps only the NEWEST turns when the conversation is long', async () => {
3383
+ const many = Array.from({ length: 45 }, (_, i) => row('User', `turn ${i}`, { ID: `h-${i}` }));
3384
+ const { provider } = makeProvider({ historyRows: many });
3385
+ currentProvider = provider;
3386
+
3387
+ await makeResolver().StartRealtimeClientSession('target-1', makeCtx(), 'conv-1');
3388
+
3389
+ const history = historyArg();
3390
+ expect(history).toHaveLength(30);
3391
+ expect(history[0].content).toBe('turn 15');
3392
+ expect(history[29].content).toBe('turn 44');
3393
+ });
3394
+
3395
+ it('drops the OLDEST turns first when the character budget is exceeded', async () => {
3396
+ // 5 turns x 3000 chars = 15000, over the 8000 budget: the freshest context is what survives.
3397
+ const big = Array.from({ length: 5 }, (_, i) => row('User', `${i}`.repeat(3000), { ID: `h-${i}` }));
3398
+ const { provider } = makeProvider({ historyRows: big });
3399
+ currentProvider = provider;
3400
+
3401
+ await makeResolver().StartRealtimeClientSession('target-1', makeCtx(), 'conv-1');
3402
+
3403
+ const history = historyArg();
3404
+ expect(history).toHaveLength(2);
3405
+ expect(String(history[1].content).startsWith('4')).toBe(true);
3406
+ });
3407
+
3408
+ it('starts the session COLD rather than failing when the history read fails', async () => {
3409
+ const { provider } = makeProvider({ historyFails: true });
3410
+ currentProvider = provider;
3411
+
3412
+ const result = await makeResolver().StartRealtimeClientSession('target-1', makeCtx(), 'conv-1');
3413
+
3414
+ expect(result.AgentSessionId).toBe('session-new');
3415
+ expect(historyArg()).toEqual([]);
3416
+ });
3417
+
3418
+ it('passes an empty history, and runs no query, when the session has no conversation', async () => {
3419
+ const { provider, runView } = makeProvider({ historyRows: [row('User', 'should never be read')] });
3420
+ currentProvider = provider;
3421
+
3422
+ await makeResolver().StartRealtimeClientSession('target-1', makeCtx());
3423
+
3424
+ expect(historyArg()).toEqual([]);
3425
+ expect(runView.mock.calls.some((c) => (c[0] as { ExtraFilter?: string }).ExtraFilter?.startsWith('ConversationID='))).toBe(false);
3426
+ });
3427
+ });
@@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest';
2
2
  import type { Request, Response, NextFunction } from 'express';
3
3
  import { MJGlobal, RegisterClass } from '@memberjunction/global';
4
4
  import { BaseRealtimeModel, RealtimeProxyRegistry, IRealtimeSession, RealtimeSessionParams } from '@memberjunction/ai';
5
- import { createRealtimeSdpBrokerRouter, createOpenAILiveBrokerRouter, requireTicket } from '../rest/RealtimeSdpBrokerHandler.js';
5
+ import { CreateRealtimeSdpBrokerRouter, createOpenAILiveBrokerRouter, RequireTicket } from '../rest/RealtimeSdpBrokerHandler.js';
6
6
 
7
7
  @RegisterClass(BaseRealtimeModel, 'MockOpenAILiveForBrokerTest', 10)
8
8
  class MockOpenAILiveForBrokerTest extends BaseRealtimeModel {
@@ -67,20 +67,20 @@ function makeMockReqRes(query: Record<string, string>, body: unknown): {
67
67
  }
68
68
 
69
69
  describe('RealtimeSdpBrokerHandler', () => {
70
- let router: ReturnType<typeof createRealtimeSdpBrokerRouter>;
70
+ let router: ReturnType<typeof CreateRealtimeSdpBrokerRouter>;
71
71
 
72
72
  beforeEach(() => {
73
- router = createRealtimeSdpBrokerRouter();
73
+ router = CreateRealtimeSdpBrokerRouter();
74
74
  });
75
75
 
76
76
  it('createOpenAILiveBrokerRouter is backwards-compatible alias', () => {
77
- expect(createOpenAILiveBrokerRouter).toBe(createRealtimeSdpBrokerRouter);
77
+ expect(createOpenAILiveBrokerRouter).toBe(CreateRealtimeSdpBrokerRouter);
78
78
  });
79
79
 
80
80
  it('requireTicket middleware rejects missing ticket without calling next()', () => {
81
81
  const { req, res, getStatus, getJson } = makeMockReqRes({}, {});
82
82
  const next = vi.fn();
83
- requireTicket(req, res, next as NextFunction);
83
+ RequireTicket(req, res, next as NextFunction);
84
84
  expect(getStatus()).toBe(401);
85
85
  expect(getJson().error).toContain('missing ticket');
86
86
  expect(next).not.toHaveBeenCalled();
@@ -89,7 +89,7 @@ describe('RealtimeSdpBrokerHandler', () => {
89
89
  it('requireTicket middleware rejects invalid ticket without calling next()', () => {
90
90
  const { req, res, getStatus, getJson } = makeMockReqRes({ ticket: 'non-existent-ticket' }, {});
91
91
  const next = vi.fn();
92
- requireTicket(req, res, next as NextFunction);
92
+ RequireTicket(req, res, next as NextFunction);
93
93
  expect(getStatus()).toBe(401);
94
94
  expect(getJson().error).toContain('invalid or expired ticket');
95
95
  expect(next).not.toHaveBeenCalled();
@@ -1,7 +1,7 @@
1
1
  import { describe, it, expect } from 'vitest';
2
2
  import { readFileSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
- import { decideFieldMapReconcile } from '../integration/EntityMapLifecycle.js';
4
+ import { DecideFieldMapReconcile } from '../integration/EntityMapLifecycle.js';
5
5
 
6
6
  /**
7
7
  * A REFRESH adopts the source's current shape: new objects and new columns both arrive ENABLED.
@@ -17,20 +17,20 @@ const fm = (SourceFieldName: string, Status: string) => ({ SourceFieldName, Stat
17
17
 
18
18
  describe('decideFieldMapReconcile — a refresh adopts new columns', () => {
19
19
  it('creates a new column ENABLED on an enabled map, by default', () => {
20
- const plan = decideFieldMapReconcile(['id', 'brand_new_col'], [fm('id', 'Active')], true);
20
+ const plan = DecideFieldMapReconcile(['id', 'brand_new_col'], [fm('id', 'Active')], true);
21
21
  expect(plan.Create).toEqual([{ SourceFieldName: 'brand_new_col', Status: 'Active' }]);
22
22
  expect(plan.Enable).toEqual([]);
23
23
  expect(plan.Disable).toEqual([]);
24
24
  });
25
25
 
26
26
  it('autoEnableNewColumns:false gates it for a connection that wants to review first', () => {
27
- const plan = decideFieldMapReconcile(['id', 'brand_new_col'], [fm('id', 'Active')], true, false);
27
+ const plan = DecideFieldMapReconcile(['id', 'brand_new_col'], [fm('id', 'Active')], true, false);
28
28
  expect(plan.Create).toEqual([{ SourceFieldName: 'brand_new_col', Status: 'Inactive' }]);
29
29
  });
30
30
 
31
31
  it('a DISABLED map never gets an Active column — the map always bounds the column', () => {
32
32
  // Adopting new columns must not resurrect a map the user switched off.
33
- const plan = decideFieldMapReconcile(['brand_new_col'], [], false, true);
33
+ const plan = DecideFieldMapReconcile(['brand_new_col'], [], false, true);
34
34
  expect(plan.Create).toEqual([{ SourceFieldName: 'brand_new_col', Status: 'Inactive' }]);
35
35
  });
36
36
  });
@@ -40,24 +40,24 @@ describe('decideFieldMapReconcile — retiring and restoring are both non-destru
40
40
  // That row is not new — it was disabled because the source stopped reporting the column, so
41
41
  // it returns to the state it had. Gating it would silently demote a column the user chose to
42
42
  // sync whenever the source flickered.
43
- const plan = decideFieldMapReconcile(['came_back'], [fm('came_back', 'Inactive')], true, false);
43
+ const plan = DecideFieldMapReconcile(['came_back'], [fm('came_back', 'Inactive')], true, false);
44
44
  expect(plan.Enable).toEqual(['came_back']);
45
45
  expect(plan.Create).toEqual([]); // reuses the row, never mints a second one
46
46
  });
47
47
 
48
48
  it('a column absent from the resolution is DISABLED, never deleted', () => {
49
- const plan = decideFieldMapReconcile(['kept'], [fm('kept', 'Active'), fm('vanished', 'Active')], true);
49
+ const plan = DecideFieldMapReconcile(['kept'], [fm('kept', 'Active'), fm('vanished', 'Active')], true);
50
50
  expect(plan.Disable).toEqual(['vanished']);
51
51
  expect(plan.Enable).toEqual([]); // survivor untouched
52
52
  });
53
53
 
54
54
  it('does not re-enable anything while the map itself is disabled', () => {
55
- const plan = decideFieldMapReconcile(['came_back'], [fm('came_back', 'Inactive')], false);
55
+ const plan = DecideFieldMapReconcile(['came_back'], [fm('came_back', 'Inactive')], false);
56
56
  expect(plan.Enable).toEqual([]);
57
57
  });
58
58
 
59
59
  it('matches source field names case-insensitively on both sides', () => {
60
- const plan = decideFieldMapReconcile(['ID', 'Name'], [fm('id', 'Active'), fm('name', 'Active')], true);
60
+ const plan = DecideFieldMapReconcile(['ID', 'Name'], [fm('id', 'Active'), fm('name', 'Active')], true);
61
61
  expect(plan.Create).toEqual([]);
62
62
  expect(plan.Disable).toEqual([]);
63
63
  });
@@ -5,11 +5,11 @@ import { MJComputerUseEngine, MJRunComputerUseParams } from '@memberjunction/com
5
5
  import { CdpRemoteBrowserSession, type ComputerUseGoalRun } from '@memberjunction/remote-browser-cdp';
6
6
  import type { MJAIAgentRunStepEntity } from '@memberjunction/core-entities';
7
7
  import {
8
- buildMJGoalParams,
8
+ BuildMJGoalParams,
9
9
  BindRemoteBrowserGoalEngine,
10
10
  MJProgressComputerUseEngine,
11
- extractCoAgentRunID,
12
- finalizeBrowserGoalStep,
11
+ ExtractCoAgentRunID,
12
+ FinalizeBrowserGoalStep,
13
13
  } from '../agentSessions/remoteBrowserGoalEngine.js';
14
14
 
15
15
  const USER = { ID: 'u-1', Email: 'amith@bluecypress.io' } as unknown as UserInfo;
@@ -21,7 +21,7 @@ function baseParams(): RunComputerUseParams {
21
21
 
22
22
  describe('buildMJGoalParams', () => {
23
23
  it('produces MJ-aware params that carry over the base goal/step/url fields', () => {
24
- const mj = buildMJGoalParams(baseParams(), USER);
24
+ const mj = BuildMJGoalParams(baseParams(), USER);
25
25
  expect(mj).toBeInstanceOf(MJRunComputerUseParams);
26
26
  expect(mj.Goal).toBe('log in');
27
27
  expect(mj.MaxSteps).toBe(7);
@@ -29,21 +29,21 @@ describe('buildMJGoalParams', () => {
29
29
  });
30
30
 
31
31
  it('injects the acting ContextUser so MJ prompts run as that user', () => {
32
- expect(buildMJGoalParams(baseParams(), USER).ContextUser).toBe(USER);
32
+ expect(BuildMJGoalParams(baseParams(), USER).ContextUser).toBe(USER);
33
33
  });
34
34
 
35
35
  it('leaves ContextUser undefined when none is supplied', () => {
36
- expect(buildMJGoalParams(baseParams()).ContextUser).toBeUndefined();
36
+ expect(BuildMJGoalParams(baseParams()).ContextUser).toBeUndefined();
37
37
  });
38
38
 
39
39
  it('threads the parent run + step ids for observability nesting', () => {
40
- const mj = buildMJGoalParams(baseParams(), USER, 'coagent-run-1', 'goal-step-1');
40
+ const mj = BuildMJGoalParams(baseParams(), USER, 'coagent-run-1', 'goal-step-1');
41
41
  expect(mj.AgentRunId).toBe('coagent-run-1');
42
42
  expect(mj.AgentRunStepID).toBe('goal-step-1');
43
43
  });
44
44
 
45
45
  it('leaves the run/step ids undefined when not supplied', () => {
46
- const mj = buildMJGoalParams(baseParams(), USER);
46
+ const mj = BuildMJGoalParams(baseParams(), USER);
47
47
  expect(mj.AgentRunId).toBeUndefined();
48
48
  expect(mj.AgentRunStepID).toBeUndefined();
49
49
  });
@@ -51,17 +51,17 @@ describe('buildMJGoalParams', () => {
51
51
 
52
52
  describe('extractCoAgentRunID', () => {
53
53
  it('pulls coAgentRunID out of a session Config_ blob', () => {
54
- expect(extractCoAgentRunID(JSON.stringify({ coAgentRunID: 'run-9', promptRunID: 'p' }))).toBe('run-9');
54
+ expect(ExtractCoAgentRunID(JSON.stringify({ coAgentRunID: 'run-9', promptRunID: 'p' }))).toBe('run-9');
55
55
  });
56
56
  it('returns undefined for a missing key, null/empty config, or non-string value', () => {
57
- expect(extractCoAgentRunID(JSON.stringify({ promptRunID: 'p' }))).toBeUndefined();
58
- expect(extractCoAgentRunID(null)).toBeUndefined();
59
- expect(extractCoAgentRunID(undefined)).toBeUndefined();
60
- expect(extractCoAgentRunID('')).toBeUndefined();
61
- expect(extractCoAgentRunID(JSON.stringify({ coAgentRunID: 123 }))).toBeUndefined();
57
+ expect(ExtractCoAgentRunID(JSON.stringify({ promptRunID: 'p' }))).toBeUndefined();
58
+ expect(ExtractCoAgentRunID(null)).toBeUndefined();
59
+ expect(ExtractCoAgentRunID(undefined)).toBeUndefined();
60
+ expect(ExtractCoAgentRunID('')).toBeUndefined();
61
+ expect(ExtractCoAgentRunID(JSON.stringify({ coAgentRunID: 123 }))).toBeUndefined();
62
62
  });
63
63
  it('returns undefined for malformed JSON (best-effort)', () => {
64
- expect(extractCoAgentRunID('{not json')).toBeUndefined();
64
+ expect(ExtractCoAgentRunID('{not json')).toBeUndefined();
65
65
  });
66
66
  });
67
67
 
@@ -76,7 +76,7 @@ describe('finalizeBrowserGoalStep', () => {
76
76
 
77
77
  it('finalizes the parent step Completed from a successful goal result + saves', async () => {
78
78
  const step = fakeStep();
79
- await finalizeBrowserGoalStep(step, { Success: true, Strategy: 'ComputerUse', Status: 'Completed', StepCount: 4, CurrentUrl: 'https://done/' });
79
+ await FinalizeBrowserGoalStep(step, { Success: true, Strategy: 'ComputerUse', Status: 'Completed', StepCount: 4, CurrentUrl: 'https://done/' });
80
80
  expect(step.Status).toBe('Completed');
81
81
  expect(step.Success).toBe(true);
82
82
  expect((step as unknown as { Save: ReturnType<typeof vi.fn> }).Save).toHaveBeenCalledOnce();
@@ -87,13 +87,13 @@ describe('finalizeBrowserGoalStep', () => {
87
87
 
88
88
  it('finalizes Failed and carries the detail as the error message', async () => {
89
89
  const step = fakeStep();
90
- await finalizeBrowserGoalStep(step, { Success: false, Status: 'Error', Detail: 'login blocked' });
90
+ await FinalizeBrowserGoalStep(step, { Success: false, Status: 'Error', Detail: 'login blocked' });
91
91
  expect(step.Status).toBe('Failed');
92
92
  expect(step.ErrorMessage).toBe('login blocked');
93
93
  });
94
94
 
95
95
  it('is a no-op when the step is null (no co-agent run to nest under)', async () => {
96
- await expect(finalizeBrowserGoalStep(null, { Success: true })).resolves.toBeUndefined();
96
+ await expect(FinalizeBrowserGoalStep(null, { Success: true })).resolves.toBeUndefined();
97
97
  });
98
98
  });
99
99