@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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, InputType, Mutation, ObjectType, registerEnumType, Resolver, PubSub, PubSubEngine } from 'type-graphql';
|
|
2
2
|
import { AppContext } from '../types.js';
|
|
3
|
-
import { LogError, UserInfo, CompositeKey, DatabaseProviderBase, LogStatus } from '@memberjunction/core';
|
|
3
|
+
import { AssertClientInputWritableForUser, LogError, UserInfo, CompositeKey, DatabaseProviderBase, LogStatus } from '@memberjunction/core';
|
|
4
4
|
import { MJQueryCategoryEntity, MJQueryPermissionEntity, MJQueryFieldEntity, MJQueryParameterEntity, MJQueryEntityEntity, QueryEngine } from '@memberjunction/core-entities';
|
|
5
5
|
import { MJQueryResolver, MJQuery_, MJQueryField_, MJQueryParameter_, MJQueryEntity_, MJQueryPermission_ } from '../generated/generated.js';
|
|
6
6
|
import { GetReadWriteProvider } from '../util.js';
|
|
@@ -301,6 +301,8 @@ export class MJQueryResolverExtended extends MJQueryResolver {
|
|
|
301
301
|
CacheMaxSize: input.CacheMaxSize || null
|
|
302
302
|
};
|
|
303
303
|
|
|
304
|
+
// Field-level security: refuse a key the caller may not read, or that names no field
|
|
305
|
+
AssertClientInputWritableForUser(record.EntityInfo, fieldsToSet, context.userPayload.userRecord);
|
|
304
306
|
record.SetMany(fieldsToSet, true);
|
|
305
307
|
|
|
306
308
|
// Pass caller-provided parameter sample values to override LLM guesses
|
|
@@ -324,7 +326,7 @@ export class MJQueryResolverExtended extends MJQueryResolver {
|
|
|
324
326
|
}
|
|
325
327
|
|
|
326
328
|
|
|
327
|
-
return await this.buildSuccessResult(record);
|
|
329
|
+
return await this.buildSuccessResult(record, context.userPayload.userRecord, provider);
|
|
328
330
|
}
|
|
329
331
|
else {
|
|
330
332
|
// Save failed - check if another request created the same query (race condition)
|
|
@@ -337,7 +339,7 @@ export class MJQueryResolverExtended extends MJQueryResolver {
|
|
|
337
339
|
LogStatus(`[CreateQuery] Unique constraint detected for query '${input.Name}'. Using existing query (ID: ${existingQuery.ID}) created by concurrent request.`);
|
|
338
340
|
const existingEntity = await provider.GetEntityObject<MJQueryEntityServer>('MJ: Queries', context.userPayload.userRecord);
|
|
339
341
|
if (await existingEntity.Load(existingQuery.ID)) {
|
|
340
|
-
return await this.buildSuccessResult(existingEntity);
|
|
342
|
+
return await this.buildSuccessResult(existingEntity, context.userPayload.userRecord, provider);
|
|
341
343
|
}
|
|
342
344
|
// Entity load failed after confirming the row exists — extremely rare
|
|
343
345
|
return {
|
|
@@ -367,11 +369,16 @@ export class MJQueryResolverExtended extends MJQueryResolver {
|
|
|
367
369
|
* Maps an MJQueryEntityServer (with loaded related metadata) to a QueryMutationResultType.
|
|
368
370
|
* Uses entity.GetAll() for scalar fields so that new CodeGen-generated fields are included
|
|
369
371
|
* automatically without manual updates. Related entity arrays are mapped explicitly.
|
|
372
|
+
*
|
|
373
|
+
* @param contextUser The caller the result is for. Field security projects the record for them.
|
|
370
374
|
*/
|
|
371
|
-
private async buildSuccessResult(entity: MJQueryEntityServer): Promise<QueryMutationResultType> {
|
|
375
|
+
private async buildSuccessResult(entity: MJQueryEntityServer, contextUser: UserInfo, provider: DatabaseProviderBase): Promise<QueryMutationResultType> {
|
|
372
376
|
return {
|
|
373
377
|
Success: true,
|
|
374
|
-
|
|
378
|
+
// Mapped for the caller, so the field-security projection applies: the record was just
|
|
379
|
+
// saved, and a save re-reads the whole row.
|
|
380
|
+
// fls-guard: projected for contextUser by MapFieldNamesToCodeNames
|
|
381
|
+
Query: await this.MapFieldNamesToCodeNames('MJ: Queries', entity.GetAll(), contextUser, provider) as MJQuery_,
|
|
375
382
|
Fields: this.mapFields(entity.QueryFields),
|
|
376
383
|
Parameters: this.mapParameters(entity.QueryParameters),
|
|
377
384
|
Entities: this.mapEntities(entity.QueryEntities),
|
|
@@ -523,6 +530,8 @@ export class MJQueryResolverExtended extends MJQueryResolver {
|
|
|
523
530
|
if (input.CacheTTLMinutes !== undefined) updateFields.CacheTTLMinutes = input.CacheTTLMinutes;
|
|
524
531
|
if (input.CacheMaxSize !== undefined) updateFields.CacheMaxSize = input.CacheMaxSize;
|
|
525
532
|
|
|
533
|
+
// Field-level security: refuse a key the caller may not read
|
|
534
|
+
AssertClientInputWritableForUser(queryEntity.EntityInfo, updateFields, context.userPayload.userRecord);
|
|
526
535
|
// Use SetMany to update all fields at once
|
|
527
536
|
queryEntity.SetMany(updateFields);
|
|
528
537
|
|
|
@@ -554,7 +563,7 @@ export class MJQueryResolverExtended extends MJQueryResolver {
|
|
|
554
563
|
await this.createPermissions(provider, input.Permissions, queryID, context.userPayload.userRecord);
|
|
555
564
|
}
|
|
556
565
|
|
|
557
|
-
return await this.buildSuccessResult(queryEntity);
|
|
566
|
+
return await this.buildSuccessResult(queryEntity, context.userPayload.userRecord, provider);
|
|
558
567
|
|
|
559
568
|
} catch (err) {
|
|
560
569
|
LogError(err);
|
|
@@ -318,6 +318,18 @@ export class RSUResolver {
|
|
|
318
318
|
SkipRestart: input.SkipRestart ?? undefined,
|
|
319
319
|
}));
|
|
320
320
|
|
|
321
|
+
// MJ-APPLY-6 — deliberately the BARE call, not RunPipelineBatchWithRetry. Everywhere else
|
|
322
|
+
// the MigrationSQL was generated by SchemaBuilder, so the manager knows what a replay would
|
|
323
|
+
// re-execute. Here it is arbitrary SQL handed in by the caller, and `executeMigration` is
|
|
324
|
+
// NOT transactional: it splits on GO/statement boundaries and issues one ExecuteSQL per
|
|
325
|
+
// chunk, so a migration that fails on chunk 3 leaves chunks 1-2 committed while the step is
|
|
326
|
+
// recorded `failed` — which is exactly the state `canSafelyRetry` reads as "nothing was
|
|
327
|
+
// applied, safe to replay". The replay then re-runs the committed chunks and reports THEIR
|
|
328
|
+
// "already exists" error in place of the real one. For generated DDL that risk is accepted
|
|
329
|
+
// upstream (SchemaBuilder.RunSchemaPipeline); for caller-authored DDL it is not ours to
|
|
330
|
+
// take. This is also an attended operator mutation with no in-repo caller — the human on
|
|
331
|
+
// the other end sees the failure and decides. Keep it in step with the singular
|
|
332
|
+
// RunRuntimeSchemaUpdate above, which uses bare RunPipeline for the same reason.
|
|
321
333
|
const batchResult = await rsm.RunPipelineBatch(pipelineInputs);
|
|
322
334
|
|
|
323
335
|
return {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
*/
|
|
34
34
|
import { Resolver, Mutation, Arg, Ctx, Int, Float, ObjectType, Field, PubSub, PubSubEngine } from 'type-graphql';
|
|
35
35
|
import { AppContext, UserPayload } from '../types.js';
|
|
36
|
-
import { AuthorizationEvaluator, UserInfo, IMetadataProvider, LogError, LogErrorEx, LogStatus, RunView, BaseEntity } from '@memberjunction/core';
|
|
36
|
+
import { AuthorizationEvaluator, UserInfo, IMetadataProvider, DatabaseProviderBase, LogError, LogErrorEx, LogStatus, RunView, BaseEntity } from '@memberjunction/core';
|
|
37
37
|
import { UUIDsEqual, IsValidUUID } from '@memberjunction/global';
|
|
38
38
|
import {
|
|
39
39
|
MJAIAgentEntity,
|
|
@@ -44,6 +44,8 @@ import {
|
|
|
44
44
|
MJConversationDetailArtifactEntity,
|
|
45
45
|
MJConversationDetailEntity,
|
|
46
46
|
ConversationEngine,
|
|
47
|
+
MJConversationDetailEntityExtended,
|
|
48
|
+
MJConversationEntity,
|
|
47
49
|
} from '@memberjunction/core-entities';
|
|
48
50
|
import { AIEngine } from '@memberjunction/aiengine';
|
|
49
51
|
import { AIAgentPermissionHelper, AIEngineBase, HasRealtimeUsage, ParseRealtimeUsageRecord, type RealtimeUsageRecord } from '@memberjunction/ai-engine-base';
|
|
@@ -62,6 +64,7 @@ import {
|
|
|
62
64
|
RealtimeAllowedAgent,
|
|
63
65
|
RealtimeDirectActionsConfig,
|
|
64
66
|
REALTIME_ADVANCED_SESSION_CONTROLS_AUTHORIZATION,
|
|
67
|
+
SqlRealtimeRecordingLedger,
|
|
65
68
|
resolveRecordingStorageAccountID,
|
|
66
69
|
storeRealtimeRecording,
|
|
67
70
|
writeRealtimeRecordingSegment,
|
|
@@ -87,6 +90,8 @@ import { ResolveWidgetGuestRunContext, ResolveScopedAnonymousRunUser, ResolveRec
|
|
|
87
90
|
import { RunWithTrustedSessionConfigWrites } from '@memberjunction/core-entities-server';
|
|
88
91
|
import { BuildMintConfigStamps, LoadInheritedVerifiedIdentity } from '../realtimeSessions/sessionConfigStamps.js';
|
|
89
92
|
import { ParseConfigObject } from '../realtimeSessions/verificationCore.js';
|
|
93
|
+
import { LoadOwnedRealtimeSession } from '../realtimeSessions/ownedRealtimeSession.js';
|
|
94
|
+
import { AuthorizeSessionAccess, LoadSessionForAccess } from '../realtimeSessions/sessionAccess.js';
|
|
90
95
|
|
|
91
96
|
/**
|
|
92
97
|
* Progress steps worth narrating to the realtime model — mirrors the normal agent-run path's filter
|
|
@@ -102,7 +107,6 @@ const SIGNIFICANT_PROGRESS_STEPS = ['prompt_execution', 'action_execution', 'sub
|
|
|
102
107
|
const MAX_USAGE_DETAILS_JSON_LENGTH = 4096;
|
|
103
108
|
|
|
104
109
|
/** Entity name — centralised so the `MJ:`-prefix convention is applied in exactly one place. */
|
|
105
|
-
const SESSION_ENTITY = 'MJ: AI Agent Sessions';
|
|
106
110
|
const CO_AGENT_ENTITY = 'MJ: AI Agent Co Agents';
|
|
107
111
|
const CONVERSATION_DETAIL_ENTITY = 'MJ: Conversation Details';
|
|
108
112
|
const CHANNEL_ENTITY = 'MJ: AI Agent Channels';
|
|
@@ -415,7 +419,7 @@ export class CancelRealtimeSessionToolResult {
|
|
|
415
419
|
* Result of {@link RealtimeClientSessionResolver.UploadRealtimeRecording} — a structured
|
|
416
420
|
* success/failure envelope. A recording-storage failure must never throw to the browser (the
|
|
417
421
|
* session it belongs to has already ended), so problems come back as `Success: false` with a
|
|
418
|
-
* human-readable reason; only ownership/authn violations (from `
|
|
422
|
+
* human-readable reason; only ownership/authn violations (from `LoadOwnedRealtimeSession`) still throw.
|
|
419
423
|
*/
|
|
420
424
|
@ObjectType()
|
|
421
425
|
export class UploadRealtimeRecordingResult {
|
|
@@ -595,7 +599,7 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
595
599
|
);
|
|
596
600
|
|
|
597
601
|
// Best-effort: stamp recording-start metadata when the browser captured (with consent) at start.
|
|
598
|
-
await this.stampRecordingStart(session, recordingConsent, recordingStartedAt);
|
|
602
|
+
await this.stampRecordingStart(session, recordingConsent, recordingStartedAt, contextUser, provider);
|
|
599
603
|
|
|
600
604
|
const clientTools = this.parseClientTools(clientToolsJson);
|
|
601
605
|
const channelCandidates = this.parseChannelCandidates(channelCandidatesJson);
|
|
@@ -664,10 +668,18 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
664
668
|
contextUser: UserInfo,
|
|
665
669
|
provider: IMetadataProvider,
|
|
666
670
|
): Promise<void> {
|
|
671
|
+
let inheritedVerified: Awaited<ReturnType<typeof LoadInheritedVerifiedIdentity>> = undefined;
|
|
672
|
+
try {
|
|
673
|
+
inheritedVerified = await LoadInheritedVerifiedIdentity(lastSessionId, contextUser, provider);
|
|
674
|
+
} catch (error) {
|
|
675
|
+
LogError(
|
|
676
|
+
`StartRealtimeClientSession: failed to load inherited verified identity for prior session ${lastSessionId}: ${(error as Error).message}`,
|
|
677
|
+
);
|
|
678
|
+
}
|
|
667
679
|
const plan = BuildMintConfigStamps({
|
|
668
680
|
EffectiveRealtime: this.readEffectiveRealtime(effectiveConfigJson),
|
|
669
681
|
ExistingConfigRaw: session.Config_,
|
|
670
|
-
InheritedVerified:
|
|
682
|
+
InheritedVerified: inheritedVerified,
|
|
671
683
|
NowMs: Date.now(),
|
|
672
684
|
});
|
|
673
685
|
if (!plan) {
|
|
@@ -902,12 +914,15 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
902
914
|
): Promise<boolean> {
|
|
903
915
|
const { contextUser, provider } = this.requireUserAndProvider(userPayload, providers);
|
|
904
916
|
const session = await this.loadOwnedActiveSession(agentSessionId, contextUser, provider);
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
917
|
+
const persistDetail =
|
|
918
|
+
this.mapTranscriptRole(role) === 'User' || (await this.callerOwnsConversation(session, contextUser, provider));
|
|
919
|
+
if (persistDetail) {
|
|
920
|
+
const saved = replacesPrevious
|
|
921
|
+
? await this.replacePreviousTranscriptTurn(session, role, text, contextUser, provider, utteranceStartMs, utteranceEndMs)
|
|
922
|
+
: await this.persistTranscriptTurn(session, role, text, contextUser, provider, utteranceStartMs, utteranceEndMs);
|
|
923
|
+
if (!saved) {
|
|
924
|
+
return false;
|
|
925
|
+
}
|
|
911
926
|
}
|
|
912
927
|
// Mirror the turn onto the co-agent's long-lived prompt run so its Messages capture the full
|
|
913
928
|
// conversation (run-viewer observability parity). Best-effort — never fails the transcript relay.
|
|
@@ -926,7 +941,7 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
926
941
|
);
|
|
927
942
|
}
|
|
928
943
|
await this.sessionManager.Heartbeat(agentSessionId, contextUser, provider);
|
|
929
|
-
return
|
|
944
|
+
return persistDetail;
|
|
930
945
|
}
|
|
931
946
|
|
|
932
947
|
/**
|
|
@@ -944,7 +959,7 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
944
959
|
* the call and uploads the assembled blob (base64) once the session ends.
|
|
945
960
|
*
|
|
946
961
|
* Hard gates (in order):
|
|
947
|
-
* 1. Ownership — `
|
|
962
|
+
* 1. Ownership — `LoadOwnedRealtimeSession` enforces `UserID === contextUser.ID` (throws on violation).
|
|
948
963
|
* 2. Consent — `consent !== true` is a hard refusal: no audio is ever stored without it.
|
|
949
964
|
* 3. Storage configuration — the session's agent must resolve a recording storage account (the
|
|
950
965
|
* agent's `RecordingStorageProviderID`, else `AttachmentStorageProviderID`).
|
|
@@ -973,7 +988,7 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
973
988
|
@Arg('peaks', () => [Float], { nullable: true }) peaks?: number[],
|
|
974
989
|
): Promise<UploadRealtimeRecordingResult> {
|
|
975
990
|
const { contextUser, provider } = this.requireUserAndProvider(ctx.userPayload, ctx.providers);
|
|
976
|
-
const session = await
|
|
991
|
+
const session = await LoadOwnedRealtimeSession(agentSessionId, contextUser, provider);
|
|
977
992
|
|
|
978
993
|
// HARD consent gate — no audio is ever stored without an explicit grant.
|
|
979
994
|
if (consent !== true) {
|
|
@@ -1015,16 +1030,21 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
1015
1030
|
});
|
|
1016
1031
|
|
|
1017
1032
|
// Canonical consolidated file written — drop the crash-recovery shards (best-effort).
|
|
1018
|
-
|
|
1033
|
+
// A FileID with an ErrorMessage is an uploaded file the session was not stamped with: the
|
|
1034
|
+
// shards are then the only recording the janitor could still recover, so keep them.
|
|
1035
|
+
const storedAndStamped = !!stored.FileID && !stored.ErrorMessage;
|
|
1036
|
+
if (storedAndStamped) {
|
|
1019
1037
|
await deleteRealtimeRecordingSegments(agentSessionId, accountID, runUser);
|
|
1038
|
+
} else if (stored.FileID) {
|
|
1039
|
+
LogError(`RealtimeClientSessionResolver.UploadRealtimeRecording: session ${agentSessionId} has file ${stored.FileID} but it is not stamped (${stored.ErrorMessage}); shards kept`);
|
|
1020
1040
|
}
|
|
1021
1041
|
|
|
1022
1042
|
return {
|
|
1023
|
-
Success:
|
|
1043
|
+
Success: storedAndStamped,
|
|
1024
1044
|
FileID: stored.FileID ?? undefined,
|
|
1025
1045
|
// Report the reason the storage layer knew (e.g. Drive's "Service Accounts do not have
|
|
1026
1046
|
// storage quota"); the generic sentence is only for when no layer supplied one.
|
|
1027
|
-
ErrorMessage:
|
|
1047
|
+
ErrorMessage: storedAndStamped ? undefined : (stored.ErrorMessage ?? 'Storage upload failed.'),
|
|
1028
1048
|
};
|
|
1029
1049
|
} catch (error) {
|
|
1030
1050
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1060,7 +1080,7 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
1060
1080
|
): Promise<boolean> {
|
|
1061
1081
|
try {
|
|
1062
1082
|
const { contextUser, provider } = this.requireUserAndProvider(ctx.userPayload, ctx.providers);
|
|
1063
|
-
const session = await
|
|
1083
|
+
const session = await LoadOwnedRealtimeSession(agentSessionId, contextUser, provider);
|
|
1064
1084
|
// The consolidated recording already landed and its upload deleted the shards; a shard
|
|
1065
1085
|
// arriving now (one still on the wire at hang-up) would be an orphan nothing deletes.
|
|
1066
1086
|
if (session.RecordingFileID) {
|
|
@@ -1183,7 +1203,7 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
1183
1203
|
@Arg('callId', () => String, { nullable: true }) callId?: string,
|
|
1184
1204
|
): Promise<CancelRealtimeSessionToolResult> {
|
|
1185
1205
|
const { contextUser, provider } = this.requireUserAndProvider(userPayload, providers);
|
|
1186
|
-
await
|
|
1206
|
+
await LoadOwnedRealtimeSession(agentSessionId, contextUser, provider);
|
|
1187
1207
|
try {
|
|
1188
1208
|
const aborted = this.clientSessionService.CancelInFlightDelegations(agentSessionId, callId);
|
|
1189
1209
|
return { AbortedCount: aborted, Success: true };
|
|
@@ -1230,7 +1250,7 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
1230
1250
|
@Arg('usageDetailsJson', () => String, { nullable: true }) usageDetailsJson?: string,
|
|
1231
1251
|
): Promise<boolean> {
|
|
1232
1252
|
const { contextUser, provider } = this.requireUserAndProvider(userPayload, providers);
|
|
1233
|
-
const session = await
|
|
1253
|
+
const session = await LoadOwnedRealtimeSession(agentSessionId, contextUser, provider);
|
|
1234
1254
|
|
|
1235
1255
|
const inputDelta = this.clampTokenDelta(inputTokens);
|
|
1236
1256
|
const outputDelta = this.clampTokenDelta(outputTokens);
|
|
@@ -1358,7 +1378,7 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
1358
1378
|
@Ctx() { userPayload, providers }: AppContext,
|
|
1359
1379
|
): Promise<boolean> {
|
|
1360
1380
|
const { contextUser, provider } = this.requireUserAndProvider(userPayload, providers);
|
|
1361
|
-
const session = await
|
|
1381
|
+
const session = await LoadOwnedRealtimeSession(agentSessionId, contextUser, provider);
|
|
1362
1382
|
|
|
1363
1383
|
if (!this.isChannelInSessionScope(session, channelName)) {
|
|
1364
1384
|
LogError(`SaveSessionChannelState: channel '${channelName}' is not in session ${agentSessionId}'s resolved scope — state not saved.`);
|
|
@@ -1441,7 +1461,7 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
1441
1461
|
@Ctx() { userPayload, providers }: AppContext,
|
|
1442
1462
|
): Promise<SaveSessionChannelArtifactResult> {
|
|
1443
1463
|
const { contextUser, provider } = this.requireUserAndProvider(userPayload, providers);
|
|
1444
|
-
const session = await
|
|
1464
|
+
const session = await LoadOwnedRealtimeSession(agentSessionId, contextUser, provider);
|
|
1445
1465
|
|
|
1446
1466
|
if (!this.isChannelInSessionScope(session, channelName)) {
|
|
1447
1467
|
const message = `SaveSessionChannelArtifact: channel '${channelName}' is not in session ${agentSessionId}'s resolved scope — nothing saved.`;
|
|
@@ -1476,7 +1496,7 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
1476
1496
|
private requireUserAndProvider(
|
|
1477
1497
|
userPayload: AppContext['userPayload'],
|
|
1478
1498
|
providers: AppContext['providers'],
|
|
1479
|
-
): { contextUser: UserInfo; provider:
|
|
1499
|
+
): { contextUser: UserInfo; provider: DatabaseProviderBase } {
|
|
1480
1500
|
const contextUser = this.GetUserFromPayload(userPayload);
|
|
1481
1501
|
if (!contextUser) {
|
|
1482
1502
|
throw new Error('Not authenticated: no user context for realtime session operation');
|
|
@@ -1954,37 +1974,13 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
1954
1974
|
contextUser: UserInfo,
|
|
1955
1975
|
provider: IMetadataProvider,
|
|
1956
1976
|
): Promise<MJAIAgentSessionEntity> {
|
|
1957
|
-
const session = await
|
|
1977
|
+
const session = await LoadOwnedRealtimeSession(agentSessionId, contextUser, provider);
|
|
1958
1978
|
if (session.Status === 'Closed') {
|
|
1959
1979
|
throw new Error(`Realtime session ${agentSessionId} is closed`);
|
|
1960
1980
|
}
|
|
1961
1981
|
return session;
|
|
1962
1982
|
}
|
|
1963
1983
|
|
|
1964
|
-
/**
|
|
1965
|
-
* Loads a session and enforces inbound ownership (`UserID === contextUser.ID`) WITHOUT
|
|
1966
|
-
* rejecting `Closed` sessions — {@link SaveSessionChannelState}'s final on-end flush
|
|
1967
|
-
* legitimately arrives after the session closed. Throws when not found / not owned.
|
|
1968
|
-
*/
|
|
1969
|
-
private async loadOwnedSession(
|
|
1970
|
-
agentSessionId: string,
|
|
1971
|
-
contextUser: UserInfo,
|
|
1972
|
-
provider: IMetadataProvider,
|
|
1973
|
-
): Promise<MJAIAgentSessionEntity> {
|
|
1974
|
-
const session = await provider.GetEntityObject<MJAIAgentSessionEntity>(SESSION_ENTITY, contextUser);
|
|
1975
|
-
const loaded = await session.Load(agentSessionId);
|
|
1976
|
-
if (!loaded) {
|
|
1977
|
-
throw new Error(`Realtime session ${agentSessionId} not found`);
|
|
1978
|
-
}
|
|
1979
|
-
if (!UUIDsEqual(session.UserID, contextUser.ID)) {
|
|
1980
|
-
LogError(
|
|
1981
|
-
`RealtimeClientSessionResolver: ownership check failed — user ${contextUser.ID} attempted to operate on session ${agentSessionId} owned by ${session.UserID}`,
|
|
1982
|
-
);
|
|
1983
|
-
throw new Error('Not authorized: you do not own this realtime session');
|
|
1984
|
-
}
|
|
1985
|
-
return session;
|
|
1986
|
-
}
|
|
1987
|
-
|
|
1988
1984
|
/**
|
|
1989
1985
|
* Resolves an ACTIVE channel definition (`MJ: AI Agent Channels`) by name from
|
|
1990
1986
|
* {@link AIEngineBase}'s cached `AgentChannels` (provider-scoped engine instance, lazy
|
|
@@ -2087,14 +2083,18 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
2087
2083
|
return null;
|
|
2088
2084
|
}
|
|
2089
2085
|
try {
|
|
2090
|
-
const
|
|
2091
|
-
if (!
|
|
2086
|
+
const loaded = await LoadSessionForAccess(lastSessionId, contextUser, provider);
|
|
2087
|
+
if (!loaded) {
|
|
2092
2088
|
LogError(`StartRealtimeClientSession: prior session ${lastSessionId} not found — skipping channel-state restore.`);
|
|
2093
2089
|
return null;
|
|
2094
2090
|
}
|
|
2095
|
-
|
|
2091
|
+
const access = AuthorizeSessionAccess(
|
|
2092
|
+
{ SessionUserID: loaded.Session.UserID, ConversationExternalID: loaded.ConversationExternalID, ConversationReadable: loaded.ConversationReadable },
|
|
2093
|
+
contextUser,
|
|
2094
|
+
);
|
|
2095
|
+
if (!access.Allowed) {
|
|
2096
2096
|
LogError(
|
|
2097
|
-
`StartRealtimeClientSession: prior session ${lastSessionId} is not owned by user ${contextUser.ID} — ` +
|
|
2097
|
+
`StartRealtimeClientSession: prior session ${lastSessionId} is not owned by user ${contextUser.ID} (${access.Reason}) — ` +
|
|
2098
2098
|
'skipping channel-state restore.',
|
|
2099
2099
|
);
|
|
2100
2100
|
return null;
|
|
@@ -2301,24 +2301,28 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
2301
2301
|
break;
|
|
2302
2302
|
}
|
|
2303
2303
|
visited.add(key);
|
|
2304
|
-
const
|
|
2305
|
-
if (!
|
|
2304
|
+
const loaded = await LoadSessionForAccess(cursor, contextUser, provider);
|
|
2305
|
+
if (!loaded) {
|
|
2306
2306
|
if (legIDs.length === 0) {
|
|
2307
2307
|
LogError(`StartRealtimeClientSession: prior session ${cursor} not found — skipping transcript hydration.`);
|
|
2308
2308
|
}
|
|
2309
2309
|
break;
|
|
2310
2310
|
}
|
|
2311
|
-
|
|
2311
|
+
const access = AuthorizeSessionAccess(
|
|
2312
|
+
{ SessionUserID: loaded.Session.UserID, ConversationExternalID: loaded.ConversationExternalID, ConversationReadable: loaded.ConversationReadable },
|
|
2313
|
+
contextUser,
|
|
2314
|
+
);
|
|
2315
|
+
if (!access.Allowed) {
|
|
2312
2316
|
if (legIDs.length === 0) {
|
|
2313
2317
|
LogError(
|
|
2314
|
-
`StartRealtimeClientSession: prior session ${cursor} is not owned by user ${contextUser.ID} — ` +
|
|
2318
|
+
`StartRealtimeClientSession: prior session ${cursor} is not owned by user ${contextUser.ID} (${access.Reason}) — ` +
|
|
2315
2319
|
'skipping transcript hydration.',
|
|
2316
2320
|
);
|
|
2317
2321
|
}
|
|
2318
2322
|
break;
|
|
2319
2323
|
}
|
|
2320
|
-
legIDs.push(
|
|
2321
|
-
cursor =
|
|
2324
|
+
legIDs.push(loaded.Session.ID);
|
|
2325
|
+
cursor = loaded.Session.LastSessionID ?? null;
|
|
2322
2326
|
}
|
|
2323
2327
|
return legIDs;
|
|
2324
2328
|
}
|
|
@@ -2599,8 +2603,9 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
2599
2603
|
callerUser: UserInfo,
|
|
2600
2604
|
provider: IMetadataProvider,
|
|
2601
2605
|
): Promise<string | null> {
|
|
2602
|
-
const detail = await provider.GetEntityObject<
|
|
2606
|
+
const detail = await provider.GetEntityObject<MJConversationDetailEntityExtended>(CONVERSATION_DETAIL_ENTITY, callerUser);
|
|
2603
2607
|
detail.NewRecord();
|
|
2608
|
+
detail.MarkServerAuthoredReply(); // a server-written system anchor, not the caller's words
|
|
2604
2609
|
detail.ConversationID = session.ConversationID;
|
|
2605
2610
|
detail.BranchID = this.sessionBranchIdOf(session);
|
|
2606
2611
|
detail.Role = 'AI';
|
|
@@ -2868,17 +2873,26 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
2868
2873
|
|
|
2869
2874
|
/**
|
|
2870
2875
|
* Stamps `RecordingStartedAt` (the recording `t0` alignment origin) + `RecordingMedia` on a
|
|
2871
|
-
* just-started session when the browser captured WITH consent.
|
|
2872
|
-
*
|
|
2876
|
+
* just-started session when the browser captured WITH consent. `RecordingStartedAt` goes through
|
|
2877
|
+
* the entity save (and stays set on the in-memory session, so a later save of it cannot clear it);
|
|
2878
|
+
* `RecordingMedia` is a recording-ledger column that an entity save cannot write (#6010), so it goes
|
|
2879
|
+
* through the ledger's `spStampAIAgentSessionRecordingFile` proc. The proc stamps `t0` as well, so it
|
|
2880
|
+
* lands even when the entity save fails: the janitor recovers only sessions that carry a
|
|
2881
|
+
* `RecordingStartedAt`. Best-effort: a parse/save/stamp failure is logged and swallowed — a
|
|
2882
|
+
* recording-metadata problem must never fail the session start.
|
|
2873
2883
|
*
|
|
2874
2884
|
* @param session The freshly created/loaded session.
|
|
2875
2885
|
* @param recordingConsent Whether the user consented to recording — only `true` stamps anything.
|
|
2876
2886
|
* @param recordingStartedAt ISO-8601 recording start timestamp from the browser.
|
|
2887
|
+
* @param contextUser The caller, on whose behalf the proc runs.
|
|
2888
|
+
* @param provider The server-side database provider the proc runs through.
|
|
2877
2889
|
*/
|
|
2878
2890
|
private async stampRecordingStart(
|
|
2879
2891
|
session: MJAIAgentSessionEntity,
|
|
2880
2892
|
recordingConsent: boolean | undefined,
|
|
2881
2893
|
recordingStartedAt: string | undefined,
|
|
2894
|
+
contextUser: UserInfo,
|
|
2895
|
+
provider: DatabaseProviderBase,
|
|
2882
2896
|
): Promise<void> {
|
|
2883
2897
|
if (recordingConsent !== true || !recordingStartedAt) {
|
|
2884
2898
|
return;
|
|
@@ -2889,12 +2903,19 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
2889
2903
|
return;
|
|
2890
2904
|
}
|
|
2891
2905
|
session.RecordingStartedAt = startedAt;
|
|
2892
|
-
session.RecordingMedia = 'Audio';
|
|
2893
2906
|
if (!(await session.Save())) {
|
|
2894
2907
|
LogError(
|
|
2895
2908
|
`RealtimeClientSessionResolver.stampRecordingStart save failed for session ${session.ID}: ${this.describeSaveFailure(session)}`,
|
|
2896
2909
|
);
|
|
2897
2910
|
}
|
|
2911
|
+
try {
|
|
2912
|
+
await new SqlRealtimeRecordingLedger(provider, contextUser).StampFile(session.ID, { media: 'Audio', startedAt });
|
|
2913
|
+
} catch (error) {
|
|
2914
|
+
LogError(
|
|
2915
|
+
`RealtimeClientSessionResolver.stampRecordingStart media stamp failed for session ${session.ID}: ` +
|
|
2916
|
+
`${error instanceof Error ? error.message : String(error)}`,
|
|
2917
|
+
);
|
|
2918
|
+
}
|
|
2898
2919
|
}
|
|
2899
2920
|
|
|
2900
2921
|
/**
|
|
@@ -2913,11 +2934,14 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
2913
2934
|
utteranceStartMs?: number,
|
|
2914
2935
|
utteranceEndMs?: number,
|
|
2915
2936
|
): Promise<boolean> {
|
|
2916
|
-
const detail = await provider.GetEntityObject<
|
|
2937
|
+
const detail = await provider.GetEntityObject<MJConversationDetailEntityExtended>(
|
|
2917
2938
|
CONVERSATION_DETAIL_ENTITY,
|
|
2918
2939
|
contextUser,
|
|
2919
2940
|
);
|
|
2920
2941
|
detail.NewRecord();
|
|
2942
|
+
// The agent's side of the session's transcript is written here, on the server, for the session's owner
|
|
2943
|
+
// (the user's side is theirs and the marker does not touch it).
|
|
2944
|
+
detail.MarkServerAuthoredReply();
|
|
2921
2945
|
detail.ConversationID = session.ConversationID;
|
|
2922
2946
|
detail.BranchID = this.sessionBranchIdOf(session);
|
|
2923
2947
|
detail.Role = this.mapTranscriptRole(role);
|
|
@@ -3006,10 +3030,11 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
3006
3030
|
// failure here looked like before the re-load. The insert path beside this one has
|
|
3007
3031
|
// always used `GetEntityObject`; this now matches it, which is also why they now succeed
|
|
3008
3032
|
// and fail for the same reasons.
|
|
3009
|
-
const previous = await provider.GetEntityObject<
|
|
3033
|
+
const previous = await provider.GetEntityObject<MJConversationDetailEntityExtended>(
|
|
3010
3034
|
CONVERSATION_DETAIL_ENTITY,
|
|
3011
3035
|
writeUser,
|
|
3012
3036
|
);
|
|
3037
|
+
previous.MarkServerAuthoredReply(); // as persistTranscriptTurn: the session's own transcript turn
|
|
3013
3038
|
if (!(await previous.Load(found.ID))) {
|
|
3014
3039
|
LogError(
|
|
3015
3040
|
`RealtimeClientSessionResolver.replacePreviousTranscriptTurn could not re-load turn `
|
|
@@ -3050,6 +3075,28 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
3050
3075
|
return role.trim().toLowerCase() === 'user' ? 'User' : 'AI';
|
|
3051
3076
|
}
|
|
3052
3077
|
|
|
3078
|
+
/**
|
|
3079
|
+
* True when the session's conversation belongs to the caller. In client-direct mode the agent's
|
|
3080
|
+
* words and tool facts reach the server only from the browser, so the server can't vouch for them:
|
|
3081
|
+
* they are stored as the agent's reply only in the caller's own conversation (A19). In a
|
|
3082
|
+
* conversation shared with the caller, only the caller's own side of the session is kept.
|
|
3083
|
+
*/
|
|
3084
|
+
private async callerOwnsConversation(
|
|
3085
|
+
session: MJAIAgentSessionEntity,
|
|
3086
|
+
contextUser: UserInfo,
|
|
3087
|
+
provider: IMetadataProvider,
|
|
3088
|
+
): Promise<boolean> {
|
|
3089
|
+
if (!session.ConversationID) {
|
|
3090
|
+
return false;
|
|
3091
|
+
}
|
|
3092
|
+
const conversation = await provider.GetEntityObject<MJConversationEntity>('MJ: Conversations', contextUser);
|
|
3093
|
+
const owned = (await conversation.Load(session.ConversationID)) && UUIDsEqual(conversation.UserID, contextUser.ID);
|
|
3094
|
+
if (!owned) {
|
|
3095
|
+
LogStatus(`RealtimeClientSessionResolver: session ${session.ID} relays the agent's side only into the caller's own conversation; conversation ${session.ConversationID} is not the caller's, so the agent's turn is not stored.`);
|
|
3096
|
+
}
|
|
3097
|
+
return owned;
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3053
3100
|
/**
|
|
3054
3101
|
* Persists a direct action or channel tool execution as a hidden ConversationDetail turn.
|
|
3055
3102
|
* Stored as stable facts (Role: 'AI', HiddenToUser: true, ExternalID: callId, CompletionTime: durationMs,
|
|
@@ -3083,15 +3130,16 @@ export class RealtimeClientSessionResolver extends ResolverBase {
|
|
|
3083
3130
|
contextUser: UserInfo,
|
|
3084
3131
|
provider: IMetadataProvider,
|
|
3085
3132
|
): Promise<boolean> {
|
|
3086
|
-
if (!session
|
|
3133
|
+
if (!(await this.callerOwnsConversation(session, contextUser, provider))) {
|
|
3087
3134
|
return false;
|
|
3088
3135
|
}
|
|
3089
3136
|
try {
|
|
3090
|
-
const detail = await provider.GetEntityObject<
|
|
3137
|
+
const detail = await provider.GetEntityObject<MJConversationDetailEntityExtended>(
|
|
3091
3138
|
CONVERSATION_DETAIL_ENTITY,
|
|
3092
3139
|
contextUser,
|
|
3093
3140
|
);
|
|
3094
3141
|
detail.NewRecord();
|
|
3142
|
+
detail.MarkServerAuthoredReply(); // the tool's facts are recorded by the server, as the session's owner
|
|
3095
3143
|
detail.ConversationID = session.ConversationID;
|
|
3096
3144
|
detail.BranchID = this.sessionBranchIdOf(session);
|
|
3097
3145
|
detail.Role = 'AI';
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
import { Resolver, Mutation, Query, Arg, Ctx, Float, Int, ObjectType, Field, PubSub, PubSubEngine } from 'type-graphql';
|
|
20
20
|
import { AppContext, UserPayload } from '../types.js';
|
|
21
21
|
import { UserInfo, IMetadataProvider, LogError } from '@memberjunction/core';
|
|
22
|
-
import { UUIDsEqual } from '@memberjunction/global';
|
|
23
22
|
import { MJAIAgentSessionEntity, MJAIAgentEntity } from '@memberjunction/core-entities';
|
|
24
23
|
import { NormalizeInstanceKey, RemoteBrowserEngine } from '@memberjunction/remote-browser-server';
|
|
25
24
|
import { BeginBrowserGoalStep, FinalizeBrowserGoalStep, ExtractCoAgentRunID } from '../agentSessions/remoteBrowserGoalEngine.js';
|
|
@@ -35,13 +34,16 @@ import {
|
|
|
35
34
|
} from '@memberjunction/remote-browser-base';
|
|
36
35
|
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
37
36
|
import { GetReadWriteProvider } from '../util.js';
|
|
37
|
+
import {
|
|
38
|
+
LoadOwnedRealtimeSession,
|
|
39
|
+
RealtimeSessionNotFoundError,
|
|
40
|
+
RealtimeSessionOwnershipError,
|
|
41
|
+
} from '../realtimeSessions/ownedRealtimeSession.js';
|
|
38
42
|
import { PUSH_STATUS_UPDATES_TOPIC } from '../generic/PushStatusResolver.js';
|
|
39
43
|
import { AIEngine } from '@memberjunction/aiengine';
|
|
40
44
|
import { AIPromptRunner } from '@memberjunction/ai-prompts';
|
|
41
45
|
import { AIPromptParams } from '@memberjunction/ai-core-plus';
|
|
42
46
|
|
|
43
|
-
/** Entity name — centralised so the `MJ:`-prefix convention is applied in exactly one place. */
|
|
44
|
-
const SESSION_ENTITY = 'MJ: AI Agent Sessions';
|
|
45
47
|
/** Entity name for the agent whose `TypeConfiguration` carries the remote-browser provider preference. */
|
|
46
48
|
const AGENT_ENTITY = 'MJ: AI Agents';
|
|
47
49
|
/**
|
|
@@ -1084,14 +1086,17 @@ export class RemoteBrowserActionResolver extends ResolverBase {
|
|
|
1084
1086
|
* @returns The loaded, owned session entity.
|
|
1085
1087
|
*/
|
|
1086
1088
|
protected async loadOwnedSession(agentSessionID: string, contextUser: UserInfo, provider: IMetadataProvider): Promise<MJAIAgentSessionEntity> {
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1089
|
+
try {
|
|
1090
|
+
return await LoadOwnedRealtimeSession(agentSessionID, contextUser, provider);
|
|
1091
|
+
} catch (err) {
|
|
1092
|
+
if (err instanceof RealtimeSessionNotFoundError) {
|
|
1093
|
+
throw new Error(`Remote-browser session ${agentSessionID} not found.`);
|
|
1094
|
+
}
|
|
1095
|
+
if (err instanceof RealtimeSessionOwnershipError) {
|
|
1096
|
+
throw new Error(`Not authorized: remote-browser session ${agentSessionID} is not owned by you.`);
|
|
1097
|
+
}
|
|
1098
|
+
throw err;
|
|
1093
1099
|
}
|
|
1094
|
-
return session;
|
|
1095
1100
|
}
|
|
1096
1101
|
|
|
1097
1102
|
/**
|