@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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/ReturningVisitorRecap.d.ts +2 -0
- package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
- package/dist/agentSessions/ReturningVisitorRecap.js +5 -1
- package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
- package/dist/agentSessions/SessionManager.js +2 -2
- package/dist/agentSessions/remoteBrowserGoalEngine.d.ts +8 -0
- package/dist/agentSessions/remoteBrowserGoalEngine.d.ts.map +1 -1
- package/dist/agentSessions/remoteBrowserGoalEngine.js +21 -5
- package/dist/agentSessions/remoteBrowserGoalEngine.js.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.d.ts +2 -0
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.js +5 -1
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
- package/dist/auth/exampleNewUserSubClass.js +2 -1
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/index.d.ts +20 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +20 -10
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +8 -0
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +21 -5
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.d.ts +9 -0
- package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +22 -10
- package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.d.ts +17 -15
- package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +65 -51
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/magicLink/index.d.ts +2 -2
- package/dist/auth/magicLink/index.d.ts.map +1 -1
- package/dist/auth/magicLink/index.js +2 -2
- package/dist/auth/magicLink/index.js.map +1 -1
- package/dist/auth/magicLink/magicLinkCore.d.ts +54 -33
- package/dist/auth/magicLink/magicLinkCore.d.ts.map +1 -1
- package/dist/auth/magicLink/magicLinkCore.js +61 -61
- package/dist/auth/magicLink/magicLinkCore.js.map +1 -1
- package/dist/auth/magicLink/redeemLanding.d.ts +4 -0
- package/dist/auth/magicLink/redeemLanding.d.ts.map +1 -1
- package/dist/auth/magicLink/redeemLanding.js +12 -4
- package/dist/auth/magicLink/redeemLanding.js.map +1 -1
- package/dist/auth/magicLink/types.d.ts +4 -4
- package/dist/auth/principals.d.ts +2 -0
- package/dist/auth/principals.d.ts.map +1 -1
- package/dist/auth/principals.js +6 -2
- package/dist/auth/principals.js.map +1 -1
- package/dist/cache.d.ts +2 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +3 -1
- package/dist/cache.js.map +1 -1
- package/dist/config.d.ts +293 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -4
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +20 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +27 -19
- package/dist/context.js.map +1 -1
- package/dist/directives/Public.d.ts +2 -0
- package/dist/directives/Public.d.ts.map +1 -1
- package/dist/directives/Public.js +3 -1
- package/dist/directives/Public.js.map +1 -1
- package/dist/directives/RequireSystemUser.d.ts +2 -0
- package/dist/directives/RequireSystemUser.d.ts.map +1 -1
- package/dist/directives/RequireSystemUser.js +3 -1
- package/dist/directives/RequireSystemUser.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts +266 -4
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +1304 -0
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +8 -2
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +7 -3
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/FireAndForgetHeartbeat.d.ts +3 -1
- package/dist/generic/FireAndForgetHeartbeat.d.ts.map +1 -1
- package/dist/generic/FireAndForgetHeartbeat.js +8 -4
- package/dist/generic/FireAndForgetHeartbeat.js.map +1 -1
- package/dist/generic/PushStatusResolver.d.ts +10 -1
- package/dist/generic/PushStatusResolver.d.ts.map +1 -1
- package/dist/generic/PushStatusResolver.js +11 -3
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +27 -1
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +64 -6
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -6
- package/dist/index.js.map +1 -1
- package/dist/integration/CustomColumnPromoter.d.ts +2 -0
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +5 -1
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/integration/EntityMapLifecycle.d.ts +4 -0
- package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
- package/dist/integration/EntityMapLifecycle.js +10 -2
- package/dist/integration/EntityMapLifecycle.js.map +1 -1
- package/dist/logging/NoLog.d.ts +4 -0
- package/dist/logging/NoLog.d.ts.map +1 -1
- package/dist/logging/NoLog.js +10 -2
- package/dist/logging/NoLog.js.map +1 -1
- package/dist/logging/StartupLogger.d.ts +2 -0
- package/dist/logging/StartupLogger.d.ts.map +1 -1
- package/dist/logging/StartupLogger.js +5 -1
- package/dist/logging/StartupLogger.js.map +1 -1
- package/dist/logging/bootAudit.d.ts +11 -7
- package/dist/logging/bootAudit.d.ts.map +1 -1
- package/dist/logging/bootAudit.js +15 -7
- package/dist/logging/bootAudit.js.map +1 -1
- package/dist/logging/boundaryLogPayload.d.ts +4 -0
- package/dist/logging/boundaryLogPayload.d.ts.map +1 -1
- package/dist/logging/boundaryLogPayload.js +5 -1
- package/dist/logging/boundaryLogPayload.js.map +1 -1
- package/dist/logging/secretRedactor.d.ts +2 -0
- package/dist/logging/secretRedactor.d.ts.map +1 -1
- package/dist/logging/secretRedactor.js +8 -4
- package/dist/logging/secretRedactor.js.map +1 -1
- package/dist/logging/shortenForLog.d.ts +2 -0
- package/dist/logging/shortenForLog.d.ts.map +1 -1
- package/dist/logging/shortenForLog.js +7 -3
- package/dist/logging/shortenForLog.js.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.d.ts +2 -0
- package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.js +8 -6
- package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
- package/dist/metadataRefreshSignal.d.ts +19 -0
- package/dist/metadataRefreshSignal.d.ts.map +1 -0
- package/dist/metadataRefreshSignal.js +45 -0
- package/dist/metadataRefreshSignal.js.map +1 -0
- package/dist/middleware/MJTenantFilterMiddleware.js +4 -4
- package/dist/multiTenancy/index.d.ts +8 -0
- package/dist/multiTenancy/index.d.ts.map +1 -1
- package/dist/multiTenancy/index.js +21 -5
- package/dist/multiTenancy/index.js.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.d.ts +5 -0
- package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.js +14 -10
- package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts +6 -6
- package/dist/realtimeWidget/WidgetSessionService.js +27 -27
- package/dist/realtimeWidget/host-identity.d.ts +5 -1
- package/dist/realtimeWidget/host-identity.d.ts.map +1 -1
- package/dist/realtimeWidget/host-identity.js +11 -3
- package/dist/realtimeWidget/host-identity.js.map +1 -1
- package/dist/realtimeWidget/index.d.ts +2 -2
- package/dist/realtimeWidget/index.d.ts.map +1 -1
- package/dist/realtimeWidget/index.js +2 -2
- package/dist/realtimeWidget/index.js.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.d.ts +21 -1
- package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.js +16 -4
- package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
- package/dist/realtimeWidget/widgetCore.d.ts +48 -0
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetCore.js +38 -10
- package/dist/realtimeWidget/widgetCore.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.d.ts +10 -6
- package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +14 -6
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.js +3 -3
- package/dist/resolvers/FetchEntityVectorsResolver.js +2 -2
- package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.js +3 -3
- package/dist/resolvers/GeoResolver.d.ts +2 -2
- package/dist/resolvers/GeoResolver.js +4 -4
- package/dist/resolvers/GetDataResolver.d.ts +14 -0
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +43 -15
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +2 -2
- package/dist/resolvers/ListOperationsResolver.d.ts +20 -0
- package/dist/resolvers/ListOperationsResolver.d.ts.map +1 -1
- package/dist/resolvers/ListOperationsResolver.js +68 -28
- package/dist/resolvers/ListOperationsResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts +11 -1
- package/dist/resolvers/MCPResolver.d.ts.map +1 -1
- package/dist/resolvers/MCPResolver.js +7 -3
- package/dist/resolvers/MCPResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +2 -1
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +3 -3
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +37 -0
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +101 -11
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +5 -5
- package/dist/resolvers/RunAIAgentResolver.d.ts +10 -4
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +74 -42
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +2 -2
- package/dist/resolvers/RunTestResolver.js +5 -5
- package/dist/resolvers/SearchEntitiesResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchEntitiesResolver.js +3 -1
- package/dist/resolvers/SearchEntitiesResolver.js.map +1 -1
- package/dist/resolvers/SearchKnowledgeResolver.d.ts +1 -0
- package/dist/resolvers/SearchKnowledgeResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeResolver.js +5 -0
- package/dist/resolvers/SearchKnowledgeResolver.js.map +1 -1
- package/dist/resolvers/SearchKnowledgeSystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeSystemUserResolver.js +1 -0
- package/dist/resolvers/SearchKnowledgeSystemUserResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts +8 -4
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +5 -5
- package/dist/resolvers/TaskGraphFrameResolver.d.ts +8 -1
- package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.js +6 -2
- package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +53 -4
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/adhoc-query-helpers.d.ts +6 -0
- package/dist/resolvers/adhoc-query-helpers.d.ts.map +1 -1
- package/dist/resolvers/adhoc-query-helpers.js +10 -2
- package/dist/resolvers/adhoc-query-helpers.js.map +1 -1
- package/dist/resolvers/artifact-routing.d.ts +8 -8
- package/dist/resolvers/artifact-routing.js +2 -2
- package/dist/resolvers/artifact-routing.js.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.d.ts +10 -2
- package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.js +24 -8
- package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
- package/dist/resolvers/peaksSidecar.d.ts +4 -0
- package/dist/resolvers/peaksSidecar.d.ts.map +1 -1
- package/dist/resolvers/peaksSidecar.js +10 -2
- package/dist/resolvers/peaksSidecar.js.map +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts +28 -0
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +20 -4
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/MediaStreamHandler.d.ts +2 -0
- package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
- package/dist/rest/MediaStreamHandler.js +10 -6
- package/dist/rest/MediaStreamHandler.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts +9 -0
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
- package/dist/rest/OAuthCallbackHandler.js +15 -3
- package/dist/rest/OAuthCallbackHandler.js.map +1 -1
- package/dist/rest/RESTEndpointHandler.d.ts +6 -4
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +15 -11
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/RealtimeSdpBrokerHandler.d.ts +5 -1
- package/dist/rest/RealtimeSdpBrokerHandler.d.ts.map +1 -1
- package/dist/rest/RealtimeSdpBrokerHandler.js +12 -4
- package/dist/rest/RealtimeSdpBrokerHandler.js.map +1 -1
- package/dist/rest/SignatureWebhookHandler.d.ts +2 -0
- package/dist/rest/SignatureWebhookHandler.d.ts.map +1 -1
- package/dist/rest/SignatureWebhookHandler.js +5 -1
- package/dist/rest/SignatureWebhookHandler.js.map +1 -1
- package/dist/rest/UploadTokenManager.d.ts +24 -8
- package/dist/rest/UploadTokenManager.d.ts.map +1 -1
- package/dist/rest/UploadTokenManager.js +53 -21
- package/dist/rest/UploadTokenManager.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +20 -0
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +20 -4
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/mediaRange.d.ts +4 -0
- package/dist/rest/mediaRange.d.ts.map +1 -1
- package/dist/rest/mediaRange.js +10 -2
- package/dist/rest/mediaRange.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +4 -0
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +13 -7
- package/dist/rest/setupRESTEndpoints.js.map +1 -1
- package/dist/serverExtensionReservedRoots.d.ts +2 -0
- package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
- package/dist/serverExtensionReservedRoots.js +5 -1
- package/dist/serverExtensionReservedRoots.js.map +1 -1
- package/dist/services/MJStorageBlobStore.d.ts +41 -0
- package/dist/services/MJStorageBlobStore.d.ts.map +1 -0
- package/dist/services/MJStorageBlobStore.js +160 -0
- package/dist/services/MJStorageBlobStore.js.map +1 -0
- package/dist/services/TaskGraphActionRunner.d.ts +13 -8
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphActionRunner.js +16 -15
- package/dist/services/TaskGraphActionRunner.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +7 -3
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +12 -3
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +19 -8
- package/dist/util.js.map +1 -1
- package/package.json +92 -92
- package/src/__tests__/FileResolverPeaks.test.ts +13 -13
- package/src/__tests__/ListOperationsResolver.test.ts +17 -17
- package/src/__tests__/MediaStreamHandler.test.ts +28 -28
- package/src/__tests__/NoLog.test.ts +11 -11
- package/src/__tests__/PrimaryKeyAlwaysMapped.test.ts +10 -10
- package/src/__tests__/RESTEndpointHandler.test.ts +14 -14
- package/src/__tests__/RealtimeBridgeResolver.test.ts +4 -2
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +229 -0
- package/src/__tests__/RealtimeSdpBrokerHandler.test.ts +6 -6
- package/src/__tests__/RefreshAdoptsNewColumns.test.ts +8 -8
- package/src/__tests__/RemoteBrowserGoalEngine.test.ts +18 -18
- package/src/__tests__/ResolverBase.isaPromotionCreate.test.ts +412 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +228 -0
- package/src/__tests__/SearchEntitiesResolver.readOnlyFallback.test.ts +78 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +129 -0
- package/src/__tests__/TaskGraphFrameResolver.test.ts +2 -2
- package/src/__tests__/TransactionGroupResolver.refusals.test.ts +290 -0
- package/src/__tests__/WidgetSessionService.test.ts +8 -4
- package/src/__tests__/adhoc-query-helpers.test.ts +21 -21
- package/src/__tests__/bootAudit.test.ts +11 -11
- package/src/__tests__/boundaryLogPayload.test.ts +6 -6
- package/src/__tests__/databaseAbstraction.test.ts +12 -6
- package/src/__tests__/getDataTokenRedaction.test.ts +7 -7
- package/src/__tests__/initializeProviders.refresh.test.ts +4 -4
- package/src/__tests__/magicLink.test.ts +73 -134
- package/src/__tests__/magicLinkService.consume.test.ts +224 -0
- package/src/__tests__/meetingRecordingRegistration.test.ts +12 -12
- package/src/__tests__/metadataRefreshSignal.test.ts +78 -0
- package/src/__tests__/multiTenancy.security.test.ts +40 -40
- package/src/__tests__/multiTenancy.test.ts +18 -18
- package/src/__tests__/newUsers.test.ts +24 -23
- package/src/__tests__/principals.test.ts +22 -22
- package/src/__tests__/pushStatusResolver.filter.test.ts +8 -8
- package/src/__tests__/secretRedactor.failOpen.test.ts +12 -12
- package/src/__tests__/secretRedactor.test.ts +12 -12
- package/src/__tests__/serverExtensionReservedRoots.test.ts +7 -7
- package/src/__tests__/subscriptionRedaction.test.ts +5 -5
- package/src/__tests__/unifiedAuth.test.ts +15 -9
- package/src/__tests__/visitorIdentity.resolve.test.ts +6 -6
- package/src/__tests__/widget.test.ts +45 -45
- package/src/__tests__/widgetGuestElevation.test.ts +7 -7
- package/src/__tests__/widgetHostIdentity.test.ts +14 -14
- package/src/agentSessions/ReturningVisitorRecap.ts +12 -1
- package/src/agentSessions/SessionManager.ts +2 -2
- package/src/agentSessions/remoteBrowserGoalEngine.ts +30 -5
- package/src/auth/AuthProviderCatalogRouter.ts +6 -1
- package/src/auth/__tests__/backward-compatibility.test.ts +3 -3
- package/src/auth/exampleNewUserSubClass.ts +2 -2
- package/src/auth/index.ts +43 -28
- package/src/auth/initializeProviders.ts +25 -5
- package/src/auth/magicLink/MagicLinkRouter.ts +28 -10
- package/src/auth/magicLink/MagicLinkService.ts +71 -52
- package/src/auth/magicLink/index.ts +7 -7
- package/src/auth/magicLink/magicLinkCore.ts +96 -64
- package/src/auth/magicLink/redeemLanding.ts +14 -4
- package/src/auth/magicLink/types.ts +54 -54
- package/src/auth/newUsers.ts +1 -1
- package/src/auth/principals.ts +11 -2
- package/src/cache.ts +4 -1
- package/src/config.ts +14 -4
- package/src/context.ts +37 -24
- package/src/directives/Public.ts +4 -1
- package/src/directives/RequireSystemUser.ts +4 -1
- package/src/generated/graphql-schemas/__mj.ts +933 -5
- package/src/generic/CacheInvalidationResolver.ts +12 -4
- package/src/generic/FireAndForgetHeartbeat.ts +19 -14
- package/src/generic/PushStatusResolver.ts +21 -7
- package/src/generic/ResolverBase.ts +66 -5
- package/src/generic/RunViewResolver.ts +22 -22
- package/src/generic/__tests__/FireAndForgetHeartbeat.test.ts +7 -7
- package/src/index.ts +34 -7
- package/src/integration/CustomColumnPromoter.ts +6 -1
- package/src/integration/EntityMapLifecycle.ts +20 -2
- package/src/logging/NoLog.ts +16 -2
- package/src/logging/StartupLogger.ts +6 -1
- package/src/logging/bootAudit.ts +26 -16
- package/src/logging/boundaryLogPayload.ts +8 -1
- package/src/logging/secretRedactor.ts +14 -9
- package/src/logging/shortenForLog.ts +8 -3
- package/src/logging/variablesLoggingMiddleware.ts +9 -6
- package/src/metadataRefreshSignal.ts +45 -0
- package/src/middleware/MJTenantFilterMiddleware.ts +4 -4
- package/src/multiTenancy/index.ts +29 -5
- package/src/realtimeWidget/WidgetRouter.ts +15 -10
- package/src/realtimeWidget/WidgetSessionService.ts +76 -76
- package/src/realtimeWidget/host-identity.ts +24 -10
- package/src/realtimeWidget/index.ts +3 -3
- package/src/realtimeWidget/visitorIdentity.ts +39 -8
- package/src/realtimeWidget/widgetCore.ts +75 -10
- package/src/realtimeWidget/widgetGuestElevation.ts +25 -12
- package/src/resolvers/AdhocQueryResolver.ts +3 -3
- package/src/resolvers/AgentSessionResolver.ts +3 -3
- package/src/resolvers/ColorResolver.ts +6 -6
- package/src/resolvers/ComponentRegistryResolver.ts +36 -36
- package/src/resolvers/EntityCommunicationsResolver.ts +4 -4
- package/src/resolvers/ExecuteRemoteOperationResolver.ts +9 -9
- package/src/resolvers/FetchEntityVectorsResolver.ts +2 -2
- package/src/resolvers/FileResolver.ts +42 -42
- package/src/resolvers/GeoResolver.ts +4 -4
- package/src/resolvers/GetDataResolver.ts +50 -15
- package/src/resolvers/IntegrationDiscoveryResolver.ts +2 -2
- package/src/resolvers/ListOperationsResolver.ts +78 -28
- package/src/resolvers/MCPResolver.ts +30 -15
- package/src/resolvers/QueryResolver.ts +13 -13
- package/src/resolvers/QuerySystemUserResolver.ts +2 -1
- package/src/resolvers/RealtimeBridgeResolver.ts +3 -3
- package/src/resolvers/RealtimeClientSessionResolver.ts +126 -13
- package/src/resolvers/RemoteBrowserActionResolver.ts +5 -5
- package/src/resolvers/RunAIAgentResolver.ts +118 -76
- package/src/resolvers/RunAIPromptResolver.ts +22 -22
- package/src/resolvers/RunTemplateResolver.ts +4 -4
- package/src/resolvers/RunTestResolver.ts +25 -25
- package/src/resolvers/SearchEntitiesResolver.ts +3 -1
- package/src/resolvers/SearchKnowledgeResolver.ts +4 -0
- package/src/resolvers/SearchKnowledgeSystemUserResolver.ts +1 -0
- package/src/resolvers/SqlLoggingConfigResolver.ts +56 -56
- package/src/resolvers/TaskGraphFrameResolver.ts +37 -28
- package/src/resolvers/TelemetryResolver.ts +79 -79
- package/src/resolvers/TransactionGroupResolver.ts +57 -4
- package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +40 -38
- package/src/resolvers/__tests__/artifact-routing.test.ts +23 -23
- package/src/resolvers/adhoc-query-helpers.ts +19 -2
- package/src/resolvers/artifact-routing.ts +19 -19
- package/src/resolvers/meetingRecordingRegistration.ts +44 -10
- package/src/resolvers/peaksSidecar.ts +12 -2
- package/src/rest/EntityCRUDHandler.ts +24 -4
- package/src/rest/MediaStreamHandler.ts +11 -6
- package/src/rest/OAuthCallbackHandler.ts +25 -7
- package/src/rest/RESTEndpointHandler.ts +20 -15
- package/src/rest/RealtimeSdpBrokerHandler.ts +14 -4
- package/src/rest/SignatureWebhookHandler.ts +6 -1
- package/src/rest/UploadTokenManager.ts +66 -30
- package/src/rest/ViewOperationsHandler.ts +24 -4
- package/src/rest/mediaRange.ts +16 -6
- package/src/rest/setupRESTEndpoints.ts +24 -12
- package/src/serverExtensionReservedRoots.ts +6 -1
- package/src/services/MJStorageBlobStore.ts +209 -0
- package/src/services/TaskGraphActionRunner.ts +16 -15
- package/src/types.ts +21 -16
- 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({
|
|
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({
|
|
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({
|
|
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({
|
|
207
|
+
const lowercase = makeHandler({ ExcludeEntities: ['secrets'] });
|
|
208
208
|
expect(lowercase.isEntityAllowed('Secrets')).toBe(false);
|
|
209
209
|
|
|
210
|
-
const wildcard = makeHandler({
|
|
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({
|
|
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({
|
|
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({
|
|
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({
|
|
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({
|
|
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({
|
|
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({
|
|
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({
|
|
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({
|
|
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
|
-
|
|
54
|
-
|
|
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 {
|
|
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
|
|
70
|
+
let router: ReturnType<typeof CreateRealtimeSdpBrokerRouter>;
|
|
71
71
|
|
|
72
72
|
beforeEach(() => {
|
|
73
|
-
router =
|
|
73
|
+
router = CreateRealtimeSdpBrokerRouter();
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
it('createOpenAILiveBrokerRouter is backwards-compatible alias', () => {
|
|
77
|
-
expect(createOpenAILiveBrokerRouter).toBe(
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
8
|
+
BuildMJGoalParams,
|
|
9
9
|
BindRemoteBrowserGoalEngine,
|
|
10
10
|
MJProgressComputerUseEngine,
|
|
11
|
-
|
|
12
|
-
|
|
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 =
|
|
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(
|
|
32
|
+
expect(BuildMJGoalParams(baseParams(), USER).ContextUser).toBe(USER);
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
it('leaves ContextUser undefined when none is supplied', () => {
|
|
36
|
-
expect(
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
58
|
-
expect(
|
|
59
|
-
expect(
|
|
60
|
-
expect(
|
|
61
|
-
expect(
|
|
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(
|
|
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
|
|
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
|
|
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(
|
|
96
|
+
await expect(FinalizeBrowserGoalStep(null, { Success: true })).resolves.toBeUndefined();
|
|
97
97
|
});
|
|
98
98
|
});
|
|
99
99
|
|