@memberjunction/server 6.2.0-edge.4 → 6.2.0-edge.6
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/README.md +47 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/SessionJanitor.d.ts +91 -30
- package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
- package/dist/agentSessions/SessionJanitor.js +311 -81
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/agentSessions/SessionManager.d.ts +17 -3
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +44 -10
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/apiRoot.d.ts +32 -0
- package/dist/apiRoot.d.ts.map +1 -0
- package/dist/apiRoot.js +67 -0
- package/dist/apiRoot.js.map +1 -0
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.js +27 -0
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
- package/dist/auth/LoginScreenEngine.d.ts +22 -0
- package/dist/auth/LoginScreenEngine.d.ts.map +1 -0
- package/dist/auth/LoginScreenEngine.js +57 -0
- package/dist/auth/LoginScreenEngine.js.map +1 -0
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +52 -10
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +10 -0
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +37 -1
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/localDevAuth.d.ts +79 -0
- package/dist/auth/localDevAuth.d.ts.map +1 -0
- package/dist/auth/localDevAuth.js +439 -0
- package/dist/auth/localDevAuth.js.map +1 -0
- package/dist/auth/magicLink/MagicLinkKeys.d.ts +2 -2
- package/dist/auth/magicLink/MagicLinkKeys.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkKeys.js +1 -1
- package/dist/auth/magicLink/MagicLinkKeys.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +3 -2
- package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
- package/dist/auth/magicLink/types.d.ts +12 -0
- package/dist/auth/magicLink/types.d.ts.map +1 -1
- package/dist/auth/sessionUserClone.d.ts +1 -1
- package/dist/auth/sessionUserClone.d.ts.map +1 -1
- package/dist/auth/sessionUserClone.js +3 -2
- package/dist/auth/sessionUserClone.js.map +1 -1
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts +292 -0
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js +442 -0
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js.map +1 -0
- package/dist/broadcast/index.d.ts +6 -0
- package/dist/broadcast/index.d.ts.map +1 -0
- package/dist/broadcast/index.js +6 -0
- package/dist/broadcast/index.js.map +1 -0
- package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.d.ts +43 -0
- package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.js +144 -0
- package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.js.map +1 -0
- package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.d.ts +46 -0
- package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.js +149 -0
- package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.js.map +1 -0
- package/dist/broadcast/providers/GCPPubSubBroadcastProvider.d.ts +49 -0
- package/dist/broadcast/providers/GCPPubSubBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/providers/GCPPubSubBroadcastProvider.js +131 -0
- package/dist/broadcast/providers/GCPPubSubBroadcastProvider.js.map +1 -0
- package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.d.ts +24 -0
- package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.js +51 -0
- package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.js.map +1 -0
- package/dist/cache.d.ts +3 -2
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js.map +1 -1
- package/dist/config.d.ts +632 -22
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +104 -4
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +3 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +29 -8
- package/dist/context.js.map +1 -1
- package/dist/coreRoutes.d.ts +29 -0
- package/dist/coreRoutes.d.ts.map +1 -0
- package/dist/coreRoutes.js +156 -0
- package/dist/coreRoutes.js.map +1 -0
- package/dist/generated/graphql-schemas/__mj.d.ts +1016 -29
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +5125 -434
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +85 -30
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +175 -60
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js +2 -0
- package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
- package/dist/generic/PubSubManager.d.ts +10 -0
- package/dist/generic/PubSubManager.d.ts.map +1 -1
- package/dist/generic/PubSubManager.js +44 -1
- package/dist/generic/PubSubManager.js.map +1 -1
- package/dist/generic/PushStatusResolver.d.ts +39 -6
- package/dist/generic/PushStatusResolver.d.ts.map +1 -1
- package/dist/generic/PushStatusResolver.js +94 -12
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +168 -69
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +464 -405
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +11 -3
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +91 -13
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/generic/actionOutputFieldSecurity.d.ts +26 -0
- package/dist/generic/actionOutputFieldSecurity.d.ts.map +1 -0
- package/dist/generic/actionOutputFieldSecurity.js +47 -0
- package/dist/generic/actionOutputFieldSecurity.js.map +1 -0
- package/dist/generic/fieldSecurityTransport.d.ts +30 -0
- package/dist/generic/fieldSecurityTransport.d.ts.map +1 -0
- package/dist/generic/fieldSecurityTransport.js +30 -0
- package/dist/generic/fieldSecurityTransport.js.map +1 -0
- package/dist/globalCors.d.ts +33 -0
- package/dist/globalCors.d.ts.map +1 -0
- package/dist/globalCors.js +58 -0
- package/dist/globalCors.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +230 -222
- package/dist/index.js.map +1 -1
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +6 -1
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.d.ts +12 -0
- package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.js +50 -1
- package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
- package/dist/multiTenancy/index.d.ts.map +1 -1
- package/dist/multiTenancy/index.js +22 -2
- package/dist/multiTenancy/index.js.map +1 -1
- package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -1
- package/dist/realtimeSessions/RealtimeSessionVerificationService.js +2 -1
- package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -1
- package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -1
- package/dist/realtimeSessions/RealtimeVerifyRouter.js +2 -1
- package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -1
- package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts +100 -0
- package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts.map +1 -0
- package/dist/realtimeSessions/RecordingAssemblyScheduler.js +173 -0
- package/dist/realtimeSessions/RecordingAssemblyScheduler.js.map +1 -0
- package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -1
- package/dist/realtimeSessions/SessionVerificationPortsBase.js +1 -0
- package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -1
- package/dist/realtimeSessions/index.d.ts +2 -0
- package/dist/realtimeSessions/index.d.ts.map +1 -1
- package/dist/realtimeSessions/index.js +2 -0
- package/dist/realtimeSessions/index.js.map +1 -1
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts +32 -0
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -0
- package/dist/realtimeSessions/ownedRealtimeSession.js +56 -0
- package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -0
- package/dist/realtimeSessions/sessionAccess.d.ts +91 -8
- package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
- package/dist/realtimeSessions/sessionAccess.js +127 -20
- package/dist/realtimeSessions/sessionAccess.js.map +1 -1
- package/dist/realtimeSessions/sessionConfigStamps.js +1 -1
- package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -1
- package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -1
- package/dist/realtimeSessions/subscriptionAuthorization.js +5 -2
- package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -1
- package/dist/realtimeSessions/verificationWorkflow.d.ts +2 -0
- package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -1
- package/dist/realtimeSessions/verificationWorkflow.js +1 -1
- package/dist/realtimeSessions/verificationWorkflow.js.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.js +19 -3
- package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts +67 -7
- package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.js +201 -19
- package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
- package/dist/realtimeWidget/host-identity.d.ts +1 -1
- package/dist/realtimeWidget/host-identity.js +1 -1
- package/dist/realtimeWidget/widgetCore.d.ts +20 -1
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetCore.js +17 -1
- package/dist/realtimeWidget/widgetCore.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.d.ts +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +2 -1
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts +19 -1
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +63 -12
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.js +1 -0
- package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
- package/dist/resolvers/AgentRunStatusPublisher.d.ts +18 -4
- package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -1
- package/dist/resolvers/AgentRunStatusPublisher.js +32 -8
- package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -1
- package/dist/resolvers/AgentSessionResolver.d.ts +10 -4
- package/dist/resolvers/AgentSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/AgentSessionResolver.js +40 -17
- package/dist/resolvers/AgentSessionResolver.js.map +1 -1
- package/dist/resolvers/ArtifactFileResolver.d.ts +5 -1
- package/dist/resolvers/ArtifactFileResolver.d.ts.map +1 -1
- package/dist/resolvers/ArtifactFileResolver.js +9 -7
- package/dist/resolvers/ArtifactFileResolver.js.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.d.ts +8 -4
- package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.js +6 -6
- package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
- package/dist/resolvers/DatasetResolver.d.ts +24 -3
- package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
- package/dist/resolvers/DatasetResolver.js +57 -8
- package/dist/resolvers/DatasetResolver.js.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts +13 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.js +50 -14
- package/dist/resolvers/EntityCommunicationsResolver.js.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts +2 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js +3 -2
- package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts +46 -3
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js +211 -50
- package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +1 -0
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +87 -11
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +292 -105
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts +33 -7
- package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.js +117 -38
- package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +6 -3
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +49 -9
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts +8 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +31 -3
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/PipelineProgressResolver.d.ts +6 -0
- package/dist/resolvers/PipelineProgressResolver.d.ts.map +1 -1
- package/dist/resolvers/PipelineProgressResolver.js +5 -3
- package/dist/resolvers/PipelineProgressResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts +2 -0
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +33 -6
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +2 -0
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +15 -6
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RSUResolver.d.ts.map +1 -1
- package/dist/resolvers/RSUResolver.js +12 -0
- package/dist/resolvers/RSUResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +18 -10
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +92 -54
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +11 -9
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +56 -8
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +241 -67
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +4 -4
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/RunTestResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTestResolver.js +3 -1
- package/dist/resolvers/RunTestResolver.js.map +1 -1
- package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts +12 -1
- package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeStreamResolver.js +15 -2
- package/dist/resolvers/SearchKnowledgeStreamResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +2 -3
- package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +4 -0
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.d.ts +2 -1
- package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.js +28 -1
- package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.d.ts +24 -0
- package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.js +66 -13
- package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts +34 -2
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +150 -27
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.d.ts +1 -1
- package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
- package/dist/resolvers/UserViewResolver.js +2 -1
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/resolvers/agent-run-data-guard.d.ts +31 -0
- package/dist/resolvers/agent-run-data-guard.d.ts.map +1 -0
- package/dist/resolvers/agent-run-data-guard.js +72 -0
- package/dist/resolvers/agent-run-data-guard.js.map +1 -0
- package/dist/rest/EntityCRUDHandler.d.ts +6 -0
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +19 -5
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +8 -5
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/RealtimeRecordingHandler.d.ts +49 -0
- package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -0
- package/dist/rest/RealtimeRecordingHandler.js +383 -0
- package/dist/rest/RealtimeRecordingHandler.js.map +1 -0
- package/dist/rest/ViewOperationsHandler.d.ts +9 -1
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +43 -17
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +6 -0
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +6 -0
- package/dist/rest/setupRESTEndpoints.js.map +1 -1
- package/dist/serverExtensionReservedRoots.d.ts +12 -10
- package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
- package/dist/serverExtensionReservedRoots.js +14 -17
- package/dist/serverExtensionReservedRoots.js.map +1 -1
- package/dist/serverRoleConfigUnits.d.ts +29 -0
- package/dist/serverRoleConfigUnits.d.ts.map +1 -0
- package/dist/serverRoleConfigUnits.js +33 -0
- package/dist/serverRoleConfigUnits.js.map +1 -0
- package/dist/services/MJStorageBlobStore.d.ts +8 -1
- package/dist/services/MJStorageBlobStore.d.ts.map +1 -1
- package/dist/services/MJStorageBlobStore.js +25 -19
- package/dist/services/MJStorageBlobStore.js.map +1 -1
- package/dist/services/StartTaskGraphDispatcher.js +2 -2
- package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
- package/dist/services/TaskGraphActionRunner.d.ts +5 -3
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphActionRunner.js +27 -5
- package/dist/services/TaskGraphActionRunner.js.map +1 -1
- package/dist/services/TaskGraphAgentRunner.d.ts +14 -2
- package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphAgentRunner.js +157 -9
- package/dist/services/TaskGraphAgentRunner.js.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.d.ts +59 -2
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +626 -16
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/sharedCache.d.ts.map +1 -1
- package/dist/sharedCache.js +3 -0
- package/dist/sharedCache.js.map +1 -1
- package/dist/types.d.ts +23 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +99 -98
- package/src/__tests__/ActionResolver.fieldSecurity.test.ts +237 -0
- package/src/__tests__/AdhocQueryResolver.dialect.test.ts +137 -0
- package/src/__tests__/AgentRunStatusPublisher.test.ts +49 -0
- package/src/__tests__/AgentSessionResolver.ownership.test.ts +137 -0
- package/src/__tests__/CustomColumnPromoterOnePass.test.ts +15 -1
- package/src/__tests__/DatasetResolver.itemFilters.test.ts +201 -0
- package/src/__tests__/EntityCommunicationsResolver.actingUser.test.ts +151 -0
- package/src/__tests__/EntityRecordNameResolver.rowSecurity.test.ts +152 -0
- package/src/__tests__/EvolutionActsOnWhatItDetects.test.ts +113 -0
- package/src/__tests__/FetchEntityVectorsResolver.test.ts +369 -18
- package/src/__tests__/FileResolver.fieldSecurity.test.ts +82 -0
- package/src/__tests__/FileResolver.storageAccess.test.ts +562 -0
- package/src/__tests__/GetDataContextDataResolver.sqlItems.test.ts +416 -0
- package/src/__tests__/ListOperationsResolver.adhocScreen.test.ts +137 -0
- package/src/__tests__/LoginScreenEngine.test.ts +86 -0
- package/src/__tests__/MJStorageBlobStore.storageGate.test.ts +63 -0
- package/src/__tests__/PipelineProgressResolver.filter.test.ts +58 -0
- package/src/__tests__/QuerySystemUserResolver.fieldSecurity.test.ts +49 -0
- package/src/__tests__/RESTEndpointHandler.test.ts +25 -0
- package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +23 -3
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +324 -46
- package/src/__tests__/RecordingAssemblyScheduler.test.ts +178 -0
- package/src/__tests__/RemoteBrowserActionResolver.ownership.test.ts +98 -0
- package/src/__tests__/ResolverBase.adhocReadScope.test.ts +133 -2
- package/src/__tests__/ResolverBase.balancedClause.test.ts +155 -0
- package/src/__tests__/ResolverBase.clauseUnscopedRead.test.ts +127 -0
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +243 -7
- package/src/__tests__/ResolverBase.deleteReturnProjection.test.ts +52 -0
- package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +176 -0
- package/src/__tests__/ResolverBase.filterEscaping.test.ts +5 -2
- package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +23 -1
- package/src/__tests__/ResolverBase.publishStatusUpdate.test.ts +68 -0
- package/src/__tests__/ResolverBase.userViewCacheAndDedup.test.ts +130 -0
- package/src/__tests__/RunAIAgentResolver.branch.test.ts +69 -13
- package/src/__tests__/RunAIAgentResolver.conversationWriter.test.ts +210 -0
- package/src/__tests__/RunAIAgentResolver.fireAndForgetCompletion.test.ts +209 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +20 -28
- package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +264 -0
- package/src/__tests__/RunAIAgentResolver.serverReply.test.ts +358 -0
- package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +4 -1
- package/src/__tests__/RunTemplateResolver.test.ts +35 -2
- package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +11 -0
- package/src/__tests__/RunViewResolver.cacheCheckScreen.test.ts +165 -0
- package/src/__tests__/SearchKnowledgeStreamResolver.test.ts +161 -0
- package/src/__tests__/SessionJanitor.test.ts +365 -10
- package/src/__tests__/SessionManager.test.ts +122 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +25 -0
- package/src/__tests__/TaskGraphAgentRunner.test.ts +266 -0
- package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +468 -23
- package/src/__tests__/TaskGraphFrameResolver.test.ts +22 -0
- package/src/__tests__/TestQuerySQLResolver.test.ts +274 -0
- package/src/__tests__/TransactionGroupResolver.fieldSecurity.test.ts +199 -0
- package/src/__tests__/TransactionGroupResolver.refusals.test.ts +98 -1
- package/src/__tests__/UpdateMJDataContextItem.oldValues.test.ts +220 -0
- package/src/__tests__/UserViewResolver.updateWhereClause.test.ts +15 -0
- package/src/__tests__/ViewOperationsHandler.clauseScreen.test.ts +157 -0
- package/src/__tests__/ViewOperationsHandler.test.ts +7 -2
- package/src/__tests__/WidgetSessionService.test.ts +583 -4
- package/src/__tests__/agent-run-data-guard.test.ts +130 -0
- package/src/__tests__/apiRootBoot.test.ts +202 -0
- package/src/__tests__/buildMagicLinkSessionUser.test.ts +96 -0
- package/src/__tests__/cacheBroadcastProviders.test.ts +403 -0
- package/src/__tests__/cacheInvalidationRecordData.test.ts +109 -0
- package/src/__tests__/conversationRunEvents.test.ts +56 -14
- package/src/__tests__/fieldSecurityFixtures.ts +91 -0
- package/src/__tests__/globalCors.test.ts +217 -0
- package/src/__tests__/localDevAuth.test.ts +196 -0
- package/src/__tests__/multiTenancy.postgresRewrite.test.ts +181 -0
- package/src/__tests__/multiTenancy.security.test.ts +51 -0
- package/src/__tests__/multiTenancy.test.ts +1 -1
- package/src/__tests__/orphanedConversationDetailReconciler.test.ts +10 -0
- package/src/__tests__/ownedRealtimeSession.test.ts +39 -0
- package/src/__tests__/pushStatusResolver.filter.test.ts +64 -1
- package/src/__tests__/realtimeRecordingHandler.test.ts +669 -0
- package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +29 -1
- package/src/__tests__/realtimeSessions/ownedRealtimeSession.anonymous.test.ts +31 -0
- package/src/__tests__/realtimeSessions/ownedRealtimeSession.namedScoped.test.ts +37 -0
- package/src/__tests__/realtimeSessions/sessionAccess.test.ts +146 -7
- package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +1 -1
- package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +25 -4
- package/src/__tests__/resolverBase.cloudEventChangedFields.test.ts +157 -0
- package/src/__tests__/resolverBase.fieldSecurityTransport.test.ts +222 -0
- package/src/__tests__/resolverBase.fls.test.ts +146 -97
- package/src/__tests__/restTransport.fieldSecurity.test.ts +148 -0
- package/src/__tests__/runParamsTimeZone.test.ts +179 -0
- package/src/__tests__/runStreams.fieldSecurity.test.ts +100 -0
- package/src/__tests__/runViewProperties.test.ts +114 -0
- package/src/__tests__/scalabilityBenchmarks.test.ts +765 -0
- package/src/__tests__/scalabilityDatabaseIntegration.test.ts +207 -0
- package/src/__tests__/serverExtensionHostOverlay.test.ts +66 -0
- package/src/__tests__/serverExtensionReservedRoots.test.ts +11 -98
- package/src/__tests__/sessionUserClone.test.ts +5 -1
- package/src/__tests__/sharedCache.test.ts +5 -3
- package/src/__tests__/startupSweepOrder.test.ts +40 -0
- package/src/__tests__/unifiedAuth.test.ts +28 -0
- package/src/__tests__/widgetGuestElevation.test.ts +2 -0
- package/src/agentSessions/SessionJanitor.ts +369 -93
- package/src/agentSessions/SessionManager.ts +45 -10
- package/src/apiRoot.ts +78 -0
- package/src/auth/AuthProviderCatalogRouter.ts +29 -0
- package/src/auth/LoginScreenEngine.ts +50 -0
- package/src/auth/index.ts +57 -12
- package/src/auth/initializeProviders.ts +43 -1
- package/src/auth/localDevAuth.ts +528 -0
- package/src/auth/magicLink/MagicLinkKeys.ts +2 -2
- package/src/auth/magicLink/MagicLinkRouter.ts +3 -2
- package/src/auth/magicLink/types.ts +10 -0
- package/src/auth/sessionUserClone.ts +3 -2
- package/src/broadcast/BaseCacheInvalidationBroadcastProvider.ts +674 -0
- package/src/broadcast/index.ts +5 -0
- package/src/broadcast/providers/AWSIoTCoreBroadcastProvider.ts +180 -0
- package/src/broadcast/providers/AzureWebPubSubBroadcastProvider.ts +182 -0
- package/src/broadcast/providers/GCPPubSubBroadcastProvider.ts +169 -0
- package/src/broadcast/providers/SequencedRoleBucketBroadcastProvider.ts +57 -0
- package/src/cache.ts +2 -1
- package/src/config.ts +115 -5
- package/src/context.ts +32 -8
- package/src/coreRoutes.ts +181 -0
- package/src/generated/graphql-schemas/__mj.ts +3684 -284
- package/src/generic/CacheInvalidationResolver.ts +172 -60
- package/src/generic/OrphanedConversationDetailReconciler.ts +4 -2
- package/src/generic/PubSubManager.ts +54 -1
- package/src/generic/PushStatusResolver.ts +109 -12
- package/src/generic/ResolverBase.ts +540 -431
- package/src/generic/RunViewResolver.ts +97 -15
- package/src/generic/actionOutputFieldSecurity.ts +75 -0
- package/src/generic/fieldSecurityTransport.ts +62 -0
- package/src/globalCors.ts +71 -0
- package/src/index.ts +239 -238
- package/src/integration/CustomColumnPromoter.ts +6 -1
- package/src/logging/variablesLoggingMiddleware.ts +59 -3
- package/src/multiTenancy/index.ts +24 -2
- package/src/realtimeSessions/README.md +7 -3
- package/src/realtimeSessions/RealtimeSessionVerificationService.ts +2 -1
- package/src/realtimeSessions/RealtimeVerifyRouter.ts +2 -1
- package/src/realtimeSessions/RecordingAssemblyScheduler.ts +234 -0
- package/src/realtimeSessions/SessionVerificationPortsBase.ts +1 -0
- package/src/realtimeSessions/index.ts +2 -0
- package/src/realtimeSessions/ownedRealtimeSession.ts +69 -0
- package/src/realtimeSessions/sessionAccess.ts +183 -23
- package/src/realtimeSessions/sessionConfigStamps.ts +1 -1
- package/src/realtimeSessions/subscriptionAuthorization.ts +4 -2
- package/src/realtimeSessions/verificationWorkflow.ts +3 -1
- package/src/realtimeWidget/WidgetRouter.ts +22 -4
- package/src/realtimeWidget/WidgetSessionService.ts +252 -17
- package/src/realtimeWidget/host-identity.ts +1 -1
- package/src/realtimeWidget/widgetCore.ts +30 -1
- package/src/realtimeWidget/widgetGuestElevation.ts +2 -1
- package/src/resolvers/ActionResolver.ts +78 -15
- package/src/resolvers/AdhocQueryResolver.ts +1 -0
- package/src/resolvers/AgentRunStatusPublisher.ts +36 -8
- package/src/resolvers/AgentSessionResolver.ts +46 -18
- package/src/resolvers/ArtifactFileResolver.ts +9 -8
- package/src/resolvers/ConversationRunEventsResolver.ts +15 -11
- package/src/resolvers/DatasetResolver.ts +70 -10
- package/src/resolvers/EntityCommunicationsResolver.ts +56 -15
- package/src/resolvers/EntityRecordNameResolver.ts +3 -2
- package/src/resolvers/FetchEntityVectorsResolver.ts +248 -55
- package/src/resolvers/FileCategoryResolver.ts +1 -0
- package/src/resolvers/FileResolver.ts +334 -109
- package/src/resolvers/GetDataContextDataResolver.ts +139 -41
- package/src/resolvers/GetDataResolver.ts +6 -3
- package/src/resolvers/IntegrationDiscoveryResolver.ts +53 -9
- package/src/resolvers/MergeRecordsResolver.ts +23 -2
- package/src/resolvers/PipelineProgressResolver.ts +12 -3
- package/src/resolvers/QueryResolver.ts +31 -6
- package/src/resolvers/QuerySystemUserResolver.ts +15 -6
- package/src/resolvers/RSUResolver.ts +12 -0
- package/src/resolvers/RealtimeClientSessionResolver.ts +114 -66
- package/src/resolvers/RemoteBrowserActionResolver.ts +15 -10
- package/src/resolvers/RunAIAgentResolver.ts +296 -85
- package/src/resolvers/RunTemplateResolver.ts +6 -4
- package/src/resolvers/RunTestResolver.ts +3 -1
- package/src/resolvers/SearchKnowledgeStreamResolver.ts +19 -3
- package/src/resolvers/SqlLoggingConfigResolver.ts +2 -4
- package/src/resolvers/SyncDataResolver.ts +4 -0
- package/src/resolvers/TaskGraphFrameResolver.ts +33 -1
- package/src/resolvers/TestQuerySQLResolver.ts +69 -13
- package/src/resolvers/TransactionGroupResolver.ts +185 -30
- package/src/resolvers/UserViewResolver.ts +2 -1
- package/src/resolvers/__tests__/GetDataResolver.validation.test.ts +95 -0
- package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +43 -0
- package/src/resolvers/agent-run-data-guard.ts +89 -0
- package/src/rest/EntityCRUDHandler.ts +22 -5
- package/src/rest/RESTEndpointHandler.ts +8 -5
- package/src/rest/RealtimeRecordingHandler.ts +467 -0
- package/src/rest/ViewOperationsHandler.ts +52 -18
- package/src/rest/setupRESTEndpoints.ts +6 -0
- package/src/serverExtensionReservedRoots.ts +14 -17
- package/src/serverRoleConfigUnits.ts +48 -0
- package/src/services/MJStorageBlobStore.ts +31 -30
- package/src/services/StartTaskGraphDispatcher.ts +2 -2
- package/src/services/TaskGraphActionRunner.ts +25 -5
- package/src/services/TaskGraphAgentRunner.ts +188 -11
- package/src/services/TaskGraphContinuationDeliverer.ts +738 -16
- package/src/sharedCache.ts +3 -0
- package/src/types.ts +23 -1
|
@@ -158,7 +158,7 @@ describe('IncludeBinaryFields forwarding — batch resolver path', () => {
|
|
|
158
158
|
it('RunViewsGeneric → RunViewsGenericInternal forwards the per-view flag to provider.RunViews', async () => {
|
|
159
159
|
const { provider, runViewsCalls } = recordingProvider();
|
|
160
160
|
const inputs = [
|
|
161
|
-
{ EntityName: ENTITY_NAME, ExtraFilter: '', OrderBy: '', IncludeBinaryFields: true },
|
|
161
|
+
{ EntityName: ENTITY_NAME, ExtraFilter: '', OrderBy: '', IncludeBinaryFields: true, AlternateBaseView: 'Active Vectors' },
|
|
162
162
|
{ EntityName: ENTITY_NAME, ExtraFilter: '', OrderBy: '' },
|
|
163
163
|
] as (RunViewByNameInput & RunViewByIDInput & RunDynamicViewInput)[];
|
|
164
164
|
|
|
@@ -167,7 +167,29 @@ describe('IncludeBinaryFields forwarding — batch resolver path', () => {
|
|
|
167
167
|
expect(runViewsCalls).toHaveLength(1);
|
|
168
168
|
expect(runViewsCalls[0]).toHaveLength(2);
|
|
169
169
|
expect(runViewsCalls[0][0].IncludeBinaryFields).toBe(true);
|
|
170
|
+
expect(runViewsCalls[0][0].AlternateBaseView).toBe('Active Vectors');
|
|
170
171
|
expect(runViewsCalls[0][1].IncludeBinaryFields).toBeUndefined();
|
|
172
|
+
expect(runViewsCalls[0][1].AlternateBaseView).toBeUndefined();
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('RunDynamicViewGeneric, RunViewByNameGeneric, and RunViewByIDGeneric forward AlternateBaseView to provider.RunView', async () => {
|
|
176
|
+
const { provider, runViewCalls } = recordingProvider();
|
|
177
|
+
const probe = new Probe();
|
|
178
|
+
|
|
179
|
+
await probe.RunDynamicViewGeneric(
|
|
180
|
+
{ EntityName: ENTITY_NAME, ExtraFilter: '', OrderBy: '', AlternateBaseView: 'Active Vectors' } as RunDynamicViewInput,
|
|
181
|
+
provider, fakePayload(), undefined as never,
|
|
182
|
+
);
|
|
183
|
+
await probe.RunViewByNameGeneric(
|
|
184
|
+
{ ViewName: 'Saved View', ExtraFilter: '', OrderBy: '', AlternateBaseView: '' } as RunViewByNameInput,
|
|
185
|
+
provider, fakePayload(), undefined as never,
|
|
186
|
+
);
|
|
187
|
+
await probe.RunViewByIDGeneric(
|
|
188
|
+
{ ViewID: 'view-1', ExtraFilter: '', OrderBy: '', AlternateBaseView: 'Draft Vectors' } as RunViewByIDInput,
|
|
189
|
+
provider, fakePayload(), undefined as never,
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
expect(runViewCalls.map(c => c.AlternateBaseView)).toEqual(['Active Vectors', '', 'Draft Vectors']);
|
|
171
193
|
});
|
|
172
194
|
});
|
|
173
195
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// ResolverBase transitively pulls in type-graphql decorators, which need the
|
|
2
|
+
// Reflect.metadata polyfill at import time.
|
|
3
|
+
import 'reflect-metadata';
|
|
4
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
5
|
+
import type { PubSubEngine } from 'type-graphql';
|
|
6
|
+
import { UserInfo } from '@memberjunction/core';
|
|
7
|
+
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
8
|
+
import { PUSH_STATUS_UPDATES_TOPIC, StatusUpdateOwnerID } from '../generic/PushStatusResolver.js';
|
|
9
|
+
import type { UserPayload } from '../types.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `ResolverBase.PublishStatusUpdate` stamps the owner the caller's socket is authenticated as. For a widget guest
|
|
13
|
+
* whose run is elevated to the system user, that is the guest's owner key: a push stamped with the elevated user's ID
|
|
14
|
+
* never passes the subscription filter on the guest's socket.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const ANONYMOUS_USER_ID = 'AAAAAAAA-0000-4000-8000-0000000000A0';
|
|
18
|
+
const SYSTEM_USER_ID = 'BBBBBBBB-0000-4000-8000-0000000000B0';
|
|
19
|
+
|
|
20
|
+
/** Reaches the protected publish wrapper. */
|
|
21
|
+
class Probe extends ResolverBase {
|
|
22
|
+
public Publish(pubSub: PubSubEngine, userPayload: UserPayload): void {
|
|
23
|
+
this.PublishStatusUpdate(pubSub, 'session-1', 'progress', userPayload);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function elevatedGuestPayload(): UserPayload {
|
|
28
|
+
const guest = new UserInfo(null, { ID: ANONYMOUS_USER_ID, Email: 'anonymous@magic-link.local' });
|
|
29
|
+
guest.IsMagicLinkAnonymous = true;
|
|
30
|
+
guest.AnonymousVisitorID = 'sid-guest-1';
|
|
31
|
+
return {
|
|
32
|
+
sessionId: 'session-1',
|
|
33
|
+
email: 'system@example.com',
|
|
34
|
+
userRecord: new UserInfo(null, { ID: SYSTEM_USER_ID, Email: 'system@example.com' }),
|
|
35
|
+
ElevatedFrom: guest,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe('ResolverBase.PublishStatusUpdate — the owner it stamps', () => {
|
|
40
|
+
it("stamps an elevated widget guest's own owner key, not the system user it was elevated to", () => {
|
|
41
|
+
const publish = vi.fn().mockResolvedValue(undefined);
|
|
42
|
+
const pubSub: PubSubEngine = { publish, subscribe: vi.fn(), unsubscribe: vi.fn(), asyncIterator: vi.fn() };
|
|
43
|
+
const userPayload = elevatedGuestPayload();
|
|
44
|
+
|
|
45
|
+
new Probe().Publish(pubSub, userPayload);
|
|
46
|
+
|
|
47
|
+
expect(publish).toHaveBeenCalledOnce();
|
|
48
|
+
expect(publish.mock.calls[0][0]).toBe(PUSH_STATUS_UPDATES_TOPIC);
|
|
49
|
+
const payload = publish.mock.calls[0][1] as { sessionId: string; ownerUserId: string; message: string };
|
|
50
|
+
expect(payload).toMatchObject({ sessionId: 'session-1', message: 'progress' });
|
|
51
|
+
expect(payload.ownerUserId).toBe(StatusUpdateOwnerID(userPayload));
|
|
52
|
+
expect(payload.ownerUserId).toBe(`${ANONYMOUS_USER_ID.toLowerCase()}|sid-guest-1`);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('stamps a signed-in user with their user ID', () => {
|
|
56
|
+
const publish = vi.fn().mockResolvedValue(undefined);
|
|
57
|
+
const pubSub: PubSubEngine = { publish, subscribe: vi.fn(), unsubscribe: vi.fn(), asyncIterator: vi.fn() };
|
|
58
|
+
const userPayload: UserPayload = {
|
|
59
|
+
sessionId: 'session-1',
|
|
60
|
+
email: 'user@example.com',
|
|
61
|
+
userRecord: new UserInfo(null, { ID: 'CCCCCCCC-0000-4000-8000-0000000000C0', Email: 'user@example.com' }),
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
new Probe().Publish(pubSub, userPayload);
|
|
65
|
+
|
|
66
|
+
expect((publish.mock.calls[0][1] as { ownerUserId: string }).ownerUserId).toBe('CCCCCCCC-0000-4000-8000-0000000000C0');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
3
|
+
import { UserViewEngine } from '@memberjunction/core-entities';
|
|
4
|
+
import type { MJUserViewEntityExtended } from '@memberjunction/core-entities';
|
|
5
|
+
import { RunView } from '@memberjunction/core';
|
|
6
|
+
import type { IMetadataProvider, IRunViewProvider, RunViewParams, UserInfo } from '@memberjunction/core';
|
|
7
|
+
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
8
|
+
import { RunViewResolver, RunViewByNameInput, RunViewByIDInput } from '../generic/RunViewResolver.js';
|
|
9
|
+
|
|
10
|
+
class UserViewProbe extends ResolverBase {
|
|
11
|
+
public async TestRunViewByID(
|
|
12
|
+
viewInput: RunViewByIDInput,
|
|
13
|
+
provider: IMetadataProvider,
|
|
14
|
+
userPayload: { userRecord: UserInfo; email: string }
|
|
15
|
+
) {
|
|
16
|
+
return this.RunViewByIDGeneric(viewInput, provider, userPayload as never);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public async TestRunViewByName(
|
|
20
|
+
viewInput: RunViewByNameInput,
|
|
21
|
+
provider: IMetadataProvider,
|
|
22
|
+
userPayload: { userRecord: UserInfo; email: string }
|
|
23
|
+
) {
|
|
24
|
+
return this.RunViewByNameGeneric(viewInput, provider, userPayload as never);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe('ResolverBase & RunViewResolver UserViewEngine cache and ViewEntity forwarding (MJ-CORE-9)', () => {
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
vi.restoreAllMocks();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('resolves MJ: User Views from UserViewEngine cache first, forwards ViewEntity into RunViewParams, and reuses _resolvedViewEntity in RunViewResolver', async () => {
|
|
34
|
+
const mockViewEntity = {
|
|
35
|
+
ID: 'view-123',
|
|
36
|
+
Name: 'Active Widgets',
|
|
37
|
+
EntityID: 'entity-widgets',
|
|
38
|
+
Entity: 'Widgets',
|
|
39
|
+
WhereClause: 'Status = 1',
|
|
40
|
+
GridState: null,
|
|
41
|
+
SortState: null,
|
|
42
|
+
} as unknown as MJUserViewEntityExtended;
|
|
43
|
+
|
|
44
|
+
vi.spyOn(UserViewEngine.Instance, 'Loaded', 'get').mockReturnValue(true);
|
|
45
|
+
const getViewByIdSpy = vi.spyOn(UserViewEngine.Instance, 'GetViewById').mockReturnValue(mockViewEntity);
|
|
46
|
+
const getViewByNameSpy = vi.spyOn(UserViewEngine.Instance, 'GetViewByName').mockReturnValue(mockViewEntity);
|
|
47
|
+
|
|
48
|
+
const capturedRunViewParams: RunViewParams[] = [];
|
|
49
|
+
const providerRunViewSpy = vi.fn().mockImplementation(async (params: RunViewParams) => {
|
|
50
|
+
capturedRunViewParams.push(params);
|
|
51
|
+
return {
|
|
52
|
+
Success: true,
|
|
53
|
+
Results: [{ ID: 'w-1', Name: 'Widget A' }],
|
|
54
|
+
RowCount: 1,
|
|
55
|
+
TotalRowCount: 1,
|
|
56
|
+
ExecutionTime: 2,
|
|
57
|
+
ErrorMessage: '',
|
|
58
|
+
UserViewRunID: '',
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
const fakeProvider = {
|
|
62
|
+
Entities: [
|
|
63
|
+
{
|
|
64
|
+
ID: 'entity-widgets',
|
|
65
|
+
Name: 'Widgets',
|
|
66
|
+
PrimaryKeys: [{ Name: 'ID', CodeName: 'ID' }],
|
|
67
|
+
Fields: [
|
|
68
|
+
{ Name: 'ID', CodeName: 'ID', AllowInView: true, DefaultInView: true, IsBinaryFieldType: false },
|
|
69
|
+
{ Name: 'Name', CodeName: 'Name', AllowInView: true, DefaultInView: true, IsBinaryFieldType: false },
|
|
70
|
+
],
|
|
71
|
+
EncryptedFields: [],
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
EntityByName: () => ({
|
|
75
|
+
ID: 'entity-widgets',
|
|
76
|
+
Name: 'Widgets',
|
|
77
|
+
PrimaryKeys: [{ Name: 'ID', CodeName: 'ID' }],
|
|
78
|
+
Fields: [
|
|
79
|
+
{ Name: 'ID', CodeName: 'ID', AllowInView: true, DefaultInView: true, IsBinaryFieldType: false },
|
|
80
|
+
{ Name: 'Name', CodeName: 'Name', AllowInView: true, DefaultInView: true, IsBinaryFieldType: false },
|
|
81
|
+
],
|
|
82
|
+
EncryptedFields: [],
|
|
83
|
+
}),
|
|
84
|
+
EntityByID: () => ({
|
|
85
|
+
ID: 'entity-widgets',
|
|
86
|
+
Name: 'Widgets',
|
|
87
|
+
PrimaryKeys: [{ Name: 'ID', CodeName: 'ID' }],
|
|
88
|
+
Fields: [
|
|
89
|
+
{ Name: 'ID', CodeName: 'ID', AllowInView: true, DefaultInView: true, IsBinaryFieldType: false },
|
|
90
|
+
{ Name: 'Name', CodeName: 'Name', AllowInView: true, DefaultInView: true, IsBinaryFieldType: false },
|
|
91
|
+
],
|
|
92
|
+
EncryptedFields: [],
|
|
93
|
+
}),
|
|
94
|
+
RunView: providerRunViewSpy,
|
|
95
|
+
} as unknown as IMetadataProvider & IRunViewProvider;
|
|
96
|
+
|
|
97
|
+
const userPayload = {
|
|
98
|
+
email: 'tester@example.com',
|
|
99
|
+
userRecord: { ID: 'u-1', Email: 'tester@example.com' } as unknown as UserInfo,
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const resolver = new RunViewResolver();
|
|
103
|
+
const findBySpy = vi.spyOn(
|
|
104
|
+
resolver as unknown as { findBy: (...args: unknown[]) => Promise<unknown> },
|
|
105
|
+
'findBy'
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
const byIdResult = await resolver.RunViewByID(
|
|
109
|
+
{ ViewID: 'view-123' } as RunViewByIDInput,
|
|
110
|
+
{ providers: [{ provider: fakeProvider, type: 'Read-Only' }], userPayload } as never
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
expect(getViewByIdSpy).toHaveBeenCalledWith('view-123');
|
|
114
|
+
expect(findBySpy).not.toHaveBeenCalled();
|
|
115
|
+
expect(capturedRunViewParams).toHaveLength(1);
|
|
116
|
+
expect(capturedRunViewParams[0].ViewEntity).toBe(mockViewEntity);
|
|
117
|
+
expect(byIdResult?.Results).toHaveLength(1);
|
|
118
|
+
|
|
119
|
+
const byNameResult = await resolver.RunViewByName(
|
|
120
|
+
{ ViewName: 'Active Widgets' } as RunViewByNameInput,
|
|
121
|
+
{ providers: [{ provider: fakeProvider, type: 'Read-Only' }], userPayload } as never
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
expect(getViewByNameSpy).toHaveBeenCalledWith('Active Widgets');
|
|
125
|
+
expect(findBySpy).not.toHaveBeenCalled();
|
|
126
|
+
expect(capturedRunViewParams).toHaveLength(2);
|
|
127
|
+
expect(capturedRunViewParams[1].ViewEntity).toBe(mockViewEntity);
|
|
128
|
+
expect(byNameResult?.Results).toHaveLength(1);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview The conversation branch on `RunAIAgentFromConversationDetail`.
|
|
3
3
|
*
|
|
4
|
-
* The branch
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The branch defaults to the person's message the mutation is given, or — when `replyBranchId` is supplied
|
|
5
|
+
* (such as Regenerate forking from an earlier message) — is validated to be a branch of the conversation
|
|
6
|
+
* whose path holds the person's message. These tests pin that the mutation loads history along that branch's
|
|
7
|
+
* path, creates the reply on that branch, hands the branch to the agent run on both the synchronous and
|
|
8
|
+
* fire-and-forget paths, and reads the trunk when the message has no branch; and that `executeAIAgent` puts
|
|
9
|
+
* the branch on the run's params only when there is one.
|
|
8
10
|
*/
|
|
9
11
|
import 'reflect-metadata'; // must precede any type-graphql decorator evaluation
|
|
10
12
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
@@ -26,6 +28,7 @@ vi.mock('type-graphql', () => {
|
|
|
26
28
|
|
|
27
29
|
const hoisted = vi.hoisted(() => ({
|
|
28
30
|
runAgentInConversation: vi.fn(),
|
|
31
|
+
createAgentReplyDetail: vi.fn(),
|
|
29
32
|
}));
|
|
30
33
|
|
|
31
34
|
vi.mock('@memberjunction/ai-agents', () => ({
|
|
@@ -33,6 +36,9 @@ vi.mock('@memberjunction/ai-agents', () => ({
|
|
|
33
36
|
RunAgentInConversation(...args: unknown[]) {
|
|
34
37
|
return hoisted.runAgentInConversation(...args);
|
|
35
38
|
}
|
|
39
|
+
CreateAgentReplyDetail(...args: unknown[]) {
|
|
40
|
+
return hoisted.createAgentReplyDetail(...args);
|
|
41
|
+
}
|
|
36
42
|
},
|
|
37
43
|
ArtifactToolManager: class {},
|
|
38
44
|
}));
|
|
@@ -70,11 +76,12 @@ function makeResolver(): { resolver: RunAIAgentResolver; seams: ResolverSeams }
|
|
|
70
76
|
return { resolver, seams };
|
|
71
77
|
}
|
|
72
78
|
|
|
73
|
-
function makeContext(branchId: string | null): AppContext {
|
|
79
|
+
function makeContext(branchId: string | null, sequence = 3): AppContext {
|
|
74
80
|
const provider = {
|
|
75
81
|
GetEntityObject: vi.fn().mockResolvedValue({
|
|
76
82
|
ConversationID: 'conv-1',
|
|
77
83
|
BranchID: branchId,
|
|
84
|
+
Sequence: sequence,
|
|
78
85
|
Load: vi.fn().mockResolvedValue(true),
|
|
79
86
|
}),
|
|
80
87
|
};
|
|
@@ -87,11 +94,18 @@ function makeContext(branchId: string | null): AppContext {
|
|
|
87
94
|
|
|
88
95
|
const pubSub = { publish: vi.fn() } as unknown as PubSubEngine;
|
|
89
96
|
|
|
90
|
-
async function runMutation(
|
|
97
|
+
async function runMutation(
|
|
98
|
+
resolver: RunAIAgentResolver,
|
|
99
|
+
branchId: string | null,
|
|
100
|
+
fireAndForget?: boolean,
|
|
101
|
+
replyBranchId?: string,
|
|
102
|
+
sequence = 3
|
|
103
|
+
) {
|
|
91
104
|
return resolver.RunAIAgentFromConversationDetail(
|
|
92
|
-
'detail-1', 'agent-1', makeContext(branchId), 'session-1', pubSub,
|
|
105
|
+
'detail-1', 'agent-1', makeContext(branchId, sequence), 'session-1', pubSub,
|
|
93
106
|
undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
|
|
94
|
-
undefined, undefined, fireAndForget, undefined, undefined, undefined
|
|
107
|
+
undefined, undefined, fireAndForget, undefined, undefined, undefined,
|
|
108
|
+
undefined, undefined, replyBranchId
|
|
95
109
|
);
|
|
96
110
|
}
|
|
97
111
|
|
|
@@ -108,23 +122,64 @@ describe('RunAIAgentFromConversationDetail — branch', () => {
|
|
|
108
122
|
seams.loadConversationHistoryWithAttachments = vi.fn().mockResolvedValue([]);
|
|
109
123
|
seams.executeAIAgent = vi.fn().mockResolvedValue({ success: true, result: '{}' });
|
|
110
124
|
seams.executeAgentInBackground = vi.fn();
|
|
125
|
+
hoisted.createAgentReplyDetail.mockReset().mockResolvedValue({ ID: 'reply-1', __mj_CreatedAt: new Date() });
|
|
111
126
|
});
|
|
112
127
|
|
|
113
|
-
|
|
128
|
+
// executeAIAgent / executeAgentInBackground end with (..., branchId, replyDetail).
|
|
129
|
+
it('loads history on the message\'s branch, creates the reply there, and hands the branch to the run', async () => {
|
|
114
130
|
await runMutation(resolver, 'branch-b');
|
|
115
131
|
expect(seams.loadConversationHistoryWithAttachments.mock.calls[0][6]).toBe('branch-b');
|
|
116
|
-
expect(
|
|
132
|
+
expect(hoisted.createAgentReplyDetail).toHaveBeenCalledWith(expect.objectContaining({ branchId: 'branch-b' }));
|
|
133
|
+
expect(seams.executeAIAgent.mock.calls[0].at(-2)).toBe('branch-b');
|
|
117
134
|
});
|
|
118
135
|
|
|
119
136
|
it('passes the branch to the background path too', async () => {
|
|
120
137
|
await runMutation(resolver, 'branch-b', true);
|
|
121
|
-
expect(seams.executeAgentInBackground.mock.calls[0].at(-
|
|
138
|
+
expect(seams.executeAgentInBackground.mock.calls[0].at(-2)).toBe('branch-b');
|
|
122
139
|
});
|
|
123
140
|
|
|
124
|
-
it('reads the trunk when the
|
|
141
|
+
it('reads the trunk when the message has no branch (control)', async () => {
|
|
125
142
|
await runMutation(resolver, null);
|
|
126
143
|
expect(seams.loadConversationHistoryWithAttachments.mock.calls[0][6]).toBeNull();
|
|
127
|
-
expect(
|
|
144
|
+
expect(hoisted.createAgentReplyDetail).toHaveBeenCalledWith(expect.objectContaining({ branchId: null }));
|
|
145
|
+
expect(seams.executeAIAgent.mock.calls[0].at(-2)).toBeNull();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('places the reply and history on replyBranchId when a regeneration forks from a message on its ancestor path', async () => {
|
|
149
|
+
vi.spyOn(ConversationEngine, 'LoadBranchesFresh').mockResolvedValue([
|
|
150
|
+
{
|
|
151
|
+
ID: 'branch-regen',
|
|
152
|
+
ConversationID: 'conv-1',
|
|
153
|
+
ParentBranchID: null,
|
|
154
|
+
ForkFromSequence: 5,
|
|
155
|
+
} as never,
|
|
156
|
+
]);
|
|
157
|
+
|
|
158
|
+
const result = await runMutation(resolver, null, false, 'branch-regen', 3);
|
|
159
|
+
|
|
160
|
+
expect(result.success).toBe(true);
|
|
161
|
+
expect(seams.loadConversationHistoryWithAttachments.mock.calls[0][6]).toBe('branch-regen');
|
|
162
|
+
expect(hoisted.createAgentReplyDetail).toHaveBeenCalledWith(expect.objectContaining({ branchId: 'branch-regen' }));
|
|
163
|
+
expect(seams.executeAIAgent.mock.calls[0].at(-2)).toBe('branch-regen');
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('refuses a replyBranchId whose path does not include the user message, and creates nothing', async () => {
|
|
167
|
+
vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
168
|
+
vi.spyOn(ConversationEngine, 'LoadBranchesFresh').mockResolvedValue([
|
|
169
|
+
{
|
|
170
|
+
ID: 'branch-regen',
|
|
171
|
+
ConversationID: 'conv-1',
|
|
172
|
+
ParentBranchID: null,
|
|
173
|
+
ForkFromSequence: 5,
|
|
174
|
+
} as never,
|
|
175
|
+
]);
|
|
176
|
+
|
|
177
|
+
const result = await runMutation(resolver, null, false, 'branch-regen', 8);
|
|
178
|
+
|
|
179
|
+
expect(result.success).toBe(false);
|
|
180
|
+
expect(result.errorMessage).toContain('branch-regen');
|
|
181
|
+
expect(hoisted.createAgentReplyDetail).not.toHaveBeenCalled();
|
|
182
|
+
expect(seams.executeAIAgent).not.toHaveBeenCalled();
|
|
128
183
|
});
|
|
129
184
|
});
|
|
130
185
|
|
|
@@ -159,6 +214,7 @@ describe('executeAIAgent — ConversationBranchID', () => {
|
|
|
159
214
|
{}, {}, 'agent-1', userPayload, '[{"role":"user","content":"hi"}]', 'session-1', pubSub,
|
|
160
215
|
undefined, undefined, undefined, undefined, undefined, undefined, 'detail-1', false, false,
|
|
161
216
|
undefined, undefined, 'conv-1', undefined, undefined, undefined, undefined, undefined,
|
|
217
|
+
false, // trustReservedRunData
|
|
162
218
|
];
|
|
163
219
|
await execute(...base, 'branch-b');
|
|
164
220
|
await execute(...base, null);
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview A widget guest's agent run executes as the system user, but the conversation belongs to the guest,
|
|
3
|
+
* and only the owner (or a grantee) may write a conversation's messages (MJConversationDetailEntityExtended, MJ#4791).
|
|
4
|
+
* So the resolver names the guest as `ConversationWriter`: AgentRunner then writes the reply as the guest and the
|
|
5
|
+
* run's own records as the system user. Before this, every reply save of a widget guest was refused and the widget
|
|
6
|
+
* never showed the agent's answer.
|
|
7
|
+
*/
|
|
8
|
+
import 'reflect-metadata'; // must precede any type-graphql decorator evaluation
|
|
9
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
10
|
+
import type { PubSubEngine } from 'type-graphql';
|
|
11
|
+
|
|
12
|
+
// type-graphql's real decorators need emitDecoratorMetadata, which vitest's esbuild transform
|
|
13
|
+
// does not emit; the schema is irrelevant here, so every decorator is a no-op.
|
|
14
|
+
vi.mock('type-graphql', () => {
|
|
15
|
+
const decoratorFactory = (..._args: unknown[]) => (..._decorated: unknown[]) => undefined;
|
|
16
|
+
const exportNames = [
|
|
17
|
+
'Resolver', 'Query', 'Mutation', 'Subscription', 'Arg', 'Args', 'ArgsType', 'Ctx', 'Root',
|
|
18
|
+
'Info', 'Field', 'FieldResolver', 'ObjectType', 'InputType', 'InterfaceType', 'Authorized',
|
|
19
|
+
'UseMiddleware', 'Extensions', 'Directive', 'ID', 'Int', 'Float', 'GraphQLISODateTime',
|
|
20
|
+
'GraphQLTimestamp', 'registerEnumType', 'createMethodDecorator', 'createParamDecorator',
|
|
21
|
+
'buildSchema', 'buildSchemaSync', 'PubSub',
|
|
22
|
+
];
|
|
23
|
+
return Object.fromEntries(exportNames.map((name) => [name, decoratorFactory]));
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const hoisted = vi.hoisted(() => ({
|
|
27
|
+
runAgentInConversation: vi.fn(),
|
|
28
|
+
createAgentReplyDetail: vi.fn(),
|
|
29
|
+
resolveWidgetGuestRunContext: vi.fn(),
|
|
30
|
+
authorize: vi.fn(),
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
// Only the key engine is stubbed: Authorize allows `agent:trusted` for the key whose hash is 'hash-trusted'.
|
|
34
|
+
vi.mock('@memberjunction/api-keys', async (importOriginal) => ({
|
|
35
|
+
...(await importOriginal<typeof import('@memberjunction/api-keys')>()),
|
|
36
|
+
GetAPIKeyEngine: () => ({ Authorize: hoisted.authorize }),
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
vi.mock('@memberjunction/ai-agents', () => ({
|
|
40
|
+
AgentRunner: class {
|
|
41
|
+
RunAgentInConversation(...args: unknown[]) {
|
|
42
|
+
return hoisted.runAgentInConversation(...args);
|
|
43
|
+
}
|
|
44
|
+
CreateAgentReplyDetail(...args: unknown[]) {
|
|
45
|
+
return hoisted.createAgentReplyDetail(...args);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
ArtifactToolManager: class {},
|
|
49
|
+
}));
|
|
50
|
+
|
|
51
|
+
// Only the widget lookup is stubbed; ElevateUserPayload is the real one, so the widget-guest test runs
|
|
52
|
+
// against the elevated system-user payload the resolver really builds.
|
|
53
|
+
vi.mock('../realtimeWidget/widgetGuestElevation.js', async (importOriginal) => ({
|
|
54
|
+
...(await importOriginal<typeof import('../realtimeWidget/widgetGuestElevation.js')>()),
|
|
55
|
+
ResolveWidgetGuestRunContext: hoisted.resolveWidgetGuestRunContext,
|
|
56
|
+
}));
|
|
57
|
+
|
|
58
|
+
import { UserCache } from '@memberjunction/generic-database-provider';
|
|
59
|
+
import type { UserInfo } from '@memberjunction/core';
|
|
60
|
+
import { RunAIAgentResolver } from '../resolvers/RunAIAgentResolver.js';
|
|
61
|
+
import type { AppContext, UserPayload } from '../types.js';
|
|
62
|
+
|
|
63
|
+
const SCOPE_RECORD_ID = 'B1A2C3D4-0000-4000-8000-00000000A115';
|
|
64
|
+
const ORDINARY = { conversationId: 'conv-1', latestMessageId: 'detail-1', invocationReason: 'user-message' };
|
|
65
|
+
const CLIENT_DATA = JSON.stringify({
|
|
66
|
+
...ORDINARY,
|
|
67
|
+
PrimaryScopeRecordID: SCOPE_RECORD_ID,
|
|
68
|
+
PrimaryScopeEntityName: 'MJ: Companies',
|
|
69
|
+
SecondaryScopes: { TeamID: 'team-other' },
|
|
70
|
+
__agentTypePromptParams: { enableTaskGraphs: true },
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const USER = { ID: 'user-1', Email: 'browser.user@example.com' };
|
|
74
|
+
const SYSTEM_USER = { ID: 'system-user', Email: 'system@example.com' };
|
|
75
|
+
// A widget guest always carries its per-visitor scope id (mj_sid) as its MagicLinkScope.ResourceID, and its
|
|
76
|
+
// conversation is stamped with the same value as ExternalID: that stamp is what tells one guest from another
|
|
77
|
+
// under the shared Anonymous user (MJ#6032), so the fake conversation below carries it.
|
|
78
|
+
const GUEST = { ID: 'guest-1', Email: 'anonymous@magic-link.local', IsMagicLinkAnonymous: true, AnonymousVisitorID: 'sid-1', MagicLinkScope: { ResourceID: 'sid-1' } };
|
|
79
|
+
|
|
80
|
+
type Fn = ReturnType<typeof vi.fn>;
|
|
81
|
+
|
|
82
|
+
/** The private members this test reaches, through an explicit shape (no `any`). */
|
|
83
|
+
interface ResolverSeams {
|
|
84
|
+
CheckAPIKeyScopeAuthorization: Fn;
|
|
85
|
+
GetUserFromPayload: Fn;
|
|
86
|
+
loadConversationHistoryWithAttachments: Fn;
|
|
87
|
+
validateAgent: Fn;
|
|
88
|
+
persistInFlightAgentFailure: Fn;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const pubSub = { publish: vi.fn().mockResolvedValue(undefined) } as unknown as PubSubEngine;
|
|
92
|
+
|
|
93
|
+
function makeResolver(): { resolver: RunAIAgentResolver; seams: ResolverSeams } {
|
|
94
|
+
const resolver = new RunAIAgentResolver();
|
|
95
|
+
const seams = resolver as unknown as ResolverSeams;
|
|
96
|
+
seams.CheckAPIKeyScopeAuthorization = vi.fn().mockResolvedValue(undefined);
|
|
97
|
+
seams.GetUserFromPayload = vi.fn((payload: UserPayload) => payload.userRecord);
|
|
98
|
+
seams.loadConversationHistoryWithAttachments = vi.fn().mockResolvedValue([{ role: 'user', content: 'hi' }]);
|
|
99
|
+
seams.validateAgent = vi.fn().mockResolvedValue({ ID: 'agent-1', Name: 'Test Agent' });
|
|
100
|
+
seams.persistInFlightAgentFailure = vi.fn().mockResolvedValue(undefined);
|
|
101
|
+
return { resolver, seams };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function makeContext(userPayload: Partial<UserPayload>): AppContext {
|
|
105
|
+
const provider = {
|
|
106
|
+
GetEntityObject: vi.fn().mockResolvedValue({ ConversationID: 'conv-1', UserID: GUEST.ID, ExternalID: 'sid-1', Load: vi.fn().mockResolvedValue(true) }),
|
|
107
|
+
};
|
|
108
|
+
return {
|
|
109
|
+
userPayload: { sessionId: 'session-1', email: USER.Email, userRecord: USER, ...userPayload } as UserPayload,
|
|
110
|
+
providers: [{ type: 'Read-Write', provider }],
|
|
111
|
+
dataSource: {},
|
|
112
|
+
} as unknown as AppContext;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** The params the n-th run was handed by the real executeAIAgent (what AgentRunner.RunAgentInConversation received). */
|
|
116
|
+
interface HandedParams {
|
|
117
|
+
data: Record<string, unknown>;
|
|
118
|
+
TrustReservedRunData?: boolean;
|
|
119
|
+
contextUser: { ID: string };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Waits for the n-th run to start (the fire-and-forget path starts it after the resolver has returned). */
|
|
123
|
+
async function handedParams(n = 0): Promise<HandedParams> {
|
|
124
|
+
await vi.waitFor(() => expect(hoisted.runAgentInConversation.mock.calls.length).toBeGreaterThan(n));
|
|
125
|
+
return hoisted.runAgentInConversation.mock.calls[n][0] as HandedParams;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function runAIAgent(resolver: RunAIAgentResolver, ctx: AppContext, fireAndForget?: boolean) {
|
|
129
|
+
return resolver.RunAIAgent(
|
|
130
|
+
'agent-1', ctx, '[{"role":"user","content":"hi"}]', 'session-1', pubSub, CLIENT_DATA,
|
|
131
|
+
undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
|
|
132
|
+
fireAndForget
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function runFromDetail(resolver: RunAIAgentResolver, ctx: AppContext, fireAndForget?: boolean) {
|
|
137
|
+
return resolver.RunAIAgentFromConversationDetail(
|
|
138
|
+
'detail-1', 'agent-1', ctx, 'session-1', pubSub, undefined, CLIENT_DATA,
|
|
139
|
+
undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, fireAndForget
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
beforeEach(() => {
|
|
144
|
+
hoisted.resolveWidgetGuestRunContext.mockReset().mockResolvedValue(null);
|
|
145
|
+
// Stop right after the run's params are captured — the rest of the run is out of scope.
|
|
146
|
+
hoisted.runAgentInConversation.mockReset().mockRejectedValue(new Error('stop here'));
|
|
147
|
+
hoisted.createAgentReplyDetail.mockReset().mockResolvedValue({ ID: 'reply-1', __mj_CreatedAt: new Date() });
|
|
148
|
+
hoisted.authorize.mockReset().mockImplementation(async (apiKeyHash: string, _app: string, scopePath: string) =>
|
|
149
|
+
apiKeyHash === 'hash-trusted' && scopePath === 'agent:trusted'
|
|
150
|
+
? { Allowed: true, MatchedKeyRule: { ScopePath: scopePath }, EvaluatedRules: [] }
|
|
151
|
+
: { Allowed: false, Reason: 'No matching key scope rules', EvaluatedRules: [] });
|
|
152
|
+
vi.spyOn(UserCache.Instance, 'GetSystemUser').mockReturnValue(SYSTEM_USER as UserInfo);
|
|
153
|
+
vi.spyOn(console, 'log').mockImplementation(() => undefined);
|
|
154
|
+
vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
afterEach(() => {
|
|
158
|
+
vi.restoreAllMocks();
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
/** The options the n-th run was handed (the second argument of AgentRunner.RunAgentInConversation). */
|
|
162
|
+
async function handedOptions(n = 0): Promise<{ ConversationWriter?: { ID: string } }> {
|
|
163
|
+
await vi.waitFor(() => expect(hoisted.runAgentInConversation.mock.calls.length).toBeGreaterThan(n));
|
|
164
|
+
return hoisted.runAgentInConversation.mock.calls[n][1] as { ConversationWriter?: { ID: string } };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
describe('RunAIAgentFromConversationDetail — who writes the conversation', () => {
|
|
168
|
+
it('runs a widget guest as the system user but writes its conversation as the guest, on both paths', async () => {
|
|
169
|
+
const { resolver } = makeResolver();
|
|
170
|
+
hoisted.resolveWidgetGuestRunContext.mockResolvedValue({ ElevatedUser: SYSTEM_USER, Widget: {}, PinnedAgentId: 'pinned-agent' });
|
|
171
|
+
const ctx = makeContext({ email: GUEST.Email, userRecord: GUEST });
|
|
172
|
+
|
|
173
|
+
await runFromDetail(resolver, ctx);
|
|
174
|
+
await runFromDetail(resolver, ctx, true);
|
|
175
|
+
|
|
176
|
+
expect((await handedParams(0)).contextUser.ID).toBe(SYSTEM_USER.ID);
|
|
177
|
+
expect((await handedOptions(0)).ConversationWriter?.ID).toBe(GUEST.ID);
|
|
178
|
+
expect((await handedParams(1)).contextUser.ID).toBe(SYSTEM_USER.ID);
|
|
179
|
+
expect((await handedOptions(1)).ConversationWriter?.ID).toBe(GUEST.ID);
|
|
180
|
+
// The server-created reply row (A19) is written as the guest too, never as the elevated system user.
|
|
181
|
+
for (const [args] of hoisted.createAgentReplyDetail.mock.calls) {
|
|
182
|
+
expect((args as { contextUser: { ID: string } }).contextUser.ID).toBe(GUEST.ID);
|
|
183
|
+
}
|
|
184
|
+
expect(hoisted.createAgentReplyDetail).toHaveBeenCalledTimes(2);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('refuses a widget guest on another visitor\'s conversation before any row is written (MJ#6032)', async () => {
|
|
188
|
+
const { resolver } = makeResolver();
|
|
189
|
+
hoisted.resolveWidgetGuestRunContext.mockResolvedValue({ ElevatedUser: SYSTEM_USER, Widget: {}, PinnedAgentId: 'pinned-agent' });
|
|
190
|
+
// The conversation is stamped sid-1; this guest's scope is sid-2, so the shared Anonymous user must not be
|
|
191
|
+
// enough. Without the AuthorizeConversationTurn gate the run would proceed and the reply row below be created.
|
|
192
|
+
const ctx = makeContext({ email: GUEST.Email, userRecord: { ...GUEST, AnonymousVisitorID: 'sid-2', MagicLinkScope: { ResourceID: 'sid-2' } } as UserPayload['userRecord'] });
|
|
193
|
+
|
|
194
|
+
const result = await runFromDetail(resolver, ctx);
|
|
195
|
+
|
|
196
|
+
expect(result.success).toBe(false);
|
|
197
|
+
expect(result.errorMessage).toContain('Not authorized: you do not own this conversation');
|
|
198
|
+
expect(hoisted.createAgentReplyDetail).not.toHaveBeenCalled();
|
|
199
|
+
expect(hoisted.runAgentInConversation).not.toHaveBeenCalled();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('names no separate writer for an ordinary user (it runs and writes as itself)', async () => {
|
|
203
|
+
const { resolver } = makeResolver();
|
|
204
|
+
|
|
205
|
+
await runFromDetail(resolver, makeContext({}));
|
|
206
|
+
|
|
207
|
+
expect((await handedOptions()).ConversationWriter).toBeUndefined();
|
|
208
|
+
expect((await handedParams()).contextUser.ID).toBe(USER.ID);
|
|
209
|
+
});
|
|
210
|
+
});
|