@memberjunction/server 6.2.0-edge.3 → 6.2.0-edge.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/BridgeHostInstance.d.ts +25 -0
- package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -0
- package/dist/agentSessions/BridgeHostInstance.js +30 -0
- package/dist/agentSessions/BridgeHostInstance.js.map +1 -0
- package/dist/agentSessions/HostInstance.d.ts +75 -11
- package/dist/agentSessions/HostInstance.d.ts.map +1 -1
- package/dist/agentSessions/HostInstance.js +99 -28
- package/dist/agentSessions/HostInstance.js.map +1 -1
- package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
- package/dist/agentSessions/ReturningVisitorRecap.js +7 -3
- package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
- package/dist/agentSessions/SessionJanitor.d.ts +236 -27
- package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
- package/dist/agentSessions/SessionJanitor.js +682 -54
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/agentSessions/SessionManager.d.ts +48 -3
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +112 -9
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/agentSessions/SessionRunIDVerifier.d.ts +63 -0
- package/dist/agentSessions/SessionRunIDVerifier.d.ts.map +1 -0
- package/dist/agentSessions/SessionRunIDVerifier.js +129 -0
- package/dist/agentSessions/SessionRunIDVerifier.js.map +1 -0
- package/dist/agentSessions/index.d.ts +2 -0
- package/dist/agentSessions/index.d.ts.map +1 -1
- package/dist/agentSessions/index.js +10 -3
- package/dist/agentSessions/index.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 +25 -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/actionAuthorization.d.ts +40 -0
- package/dist/auth/actionAuthorization.d.ts.map +1 -0
- package/dist/auth/actionAuthorization.js +94 -0
- package/dist/auth/actionAuthorization.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 +4 -10
- package/dist/auth/index.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/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +6 -3
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/newUsers.d.ts +10 -0
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +80 -11
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/config.d.ts +2514 -22
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +166 -4
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +8 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +14 -11
- 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 +142 -0
- package/dist/coreRoutes.js.map +1 -0
- package/dist/generated/graphql-schemas/__mj.d.ts +504 -3
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +2456 -7
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +43 -8
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +59 -19
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js +3 -3
- package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
- package/dist/generic/PushStatusResolver.js +1 -1
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +123 -48
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +293 -305
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +16 -0
- package/dist/generic/RunViewResolver.js.map +1 -1
- 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 +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +219 -278
- package/dist/index.js.map +1 -1
- package/dist/isolatedProvider.d.ts +20 -0
- package/dist/isolatedProvider.d.ts.map +1 -0
- package/dist/isolatedProvider.js +22 -0
- package/dist/isolatedProvider.js.map +1 -0
- 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/realtimeProxy/RealtimeProxyServer.d.ts +44 -4
- package/dist/realtimeProxy/RealtimeProxyServer.d.ts.map +1 -1
- package/dist/realtimeProxy/RealtimeProxyServer.js +121 -16
- package/dist/realtimeProxy/RealtimeProxyServer.js.map +1 -1
- package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts +171 -0
- package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts.map +1 -0
- package/dist/realtimeProxy/RealtimeRelayTunnel.js +532 -0
- package/dist/realtimeProxy/RealtimeRelayTunnel.js.map +1 -0
- package/dist/realtimeSessions/RealtimeSessionEventService.d.ts +148 -0
- package/dist/realtimeSessions/RealtimeSessionEventService.d.ts.map +1 -0
- package/dist/realtimeSessions/RealtimeSessionEventService.js +191 -0
- package/dist/realtimeSessions/RealtimeSessionEventService.js.map +1 -0
- package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts +66 -0
- package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -0
- package/dist/realtimeSessions/RealtimeSessionVerificationService.js +139 -0
- package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -0
- package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts +38 -0
- package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -0
- package/dist/realtimeSessions/RealtimeVerifyRouter.js +99 -0
- package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -0
- 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 +61 -0
- package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -0
- package/dist/realtimeSessions/SessionVerificationPortsBase.js +149 -0
- package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -0
- package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts +57 -0
- package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts.map +1 -0
- package/dist/realtimeSessions/SlidingWindowRateLimiter.js +69 -0
- package/dist/realtimeSessions/SlidingWindowRateLimiter.js.map +1 -0
- package/dist/realtimeSessions/index.d.ts +19 -0
- package/dist/realtimeSessions/index.d.ts.map +1 -0
- package/dist/realtimeSessions/index.js +19 -0
- package/dist/realtimeSessions/index.js.map +1 -0
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts +30 -0
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -0
- package/dist/realtimeSessions/ownedRealtimeSession.js +47 -0
- package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -0
- package/dist/realtimeSessions/sessionAccess.d.ts +92 -0
- package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -0
- package/dist/realtimeSessions/sessionAccess.js +94 -0
- package/dist/realtimeSessions/sessionAccess.js.map +1 -0
- package/dist/realtimeSessions/sessionConfigStamps.d.ts +70 -0
- package/dist/realtimeSessions/sessionConfigStamps.d.ts.map +1 -0
- package/dist/realtimeSessions/sessionConfigStamps.js +93 -0
- package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -0
- package/dist/realtimeSessions/subscriptionAuthorization.d.ts +65 -0
- package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -0
- package/dist/realtimeSessions/subscriptionAuthorization.js +71 -0
- package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -0
- package/dist/realtimeSessions/verificationCore.d.ts +243 -0
- package/dist/realtimeSessions/verificationCore.d.ts.map +1 -0
- package/dist/realtimeSessions/verificationCore.js +356 -0
- package/dist/realtimeSessions/verificationCore.js.map +1 -0
- package/dist/realtimeSessions/verificationPages.d.ts +66 -0
- package/dist/realtimeSessions/verificationPages.d.ts.map +1 -0
- package/dist/realtimeSessions/verificationPages.js +110 -0
- package/dist/realtimeSessions/verificationPages.js.map +1 -0
- package/dist/realtimeSessions/verificationPolicy.d.ts +147 -0
- package/dist/realtimeSessions/verificationPolicy.d.ts.map +1 -0
- package/dist/realtimeSessions/verificationPolicy.js +249 -0
- package/dist/realtimeSessions/verificationPolicy.js.map +1 -0
- package/dist/realtimeSessions/verificationWorkflow.d.ts +263 -0
- package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -0
- package/dist/realtimeSessions/verificationWorkflow.js +435 -0
- package/dist/realtimeSessions/verificationWorkflow.js.map +1 -0
- package/dist/realtimeWidget/widgetGuestElevation.d.ts +20 -2
- package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +31 -2
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts +31 -5
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +75 -14
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.d.ts +14 -1
- package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.js +21 -5
- package/dist/resolvers/AdhocQueryResolver.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/CacheStatsResolver.d.ts +27 -0
- package/dist/resolvers/CacheStatsResolver.d.ts.map +1 -1
- package/dist/resolvers/CacheStatsResolver.js +113 -2
- package/dist/resolvers/CacheStatsResolver.js.map +1 -1
- package/dist/resolvers/ClientToolRequestResolver.d.ts +4 -2
- package/dist/resolvers/ClientToolRequestResolver.d.ts.map +1 -1
- package/dist/resolvers/ClientToolRequestResolver.js +28 -10
- package/dist/resolvers/ClientToolRequestResolver.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/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 +27 -1
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js +148 -2
- package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +82 -11
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +279 -101
- 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/HumanHandoffResolver.d.ts.map +1 -1
- package/dist/resolvers/HumanHandoffResolver.js +7 -1
- package/dist/resolvers/HumanHandoffResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +4 -2
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts.map +1 -1
- package/dist/resolvers/MCPResolver.js +9 -4
- package/dist/resolvers/MCPResolver.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 +13 -0
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.d.ts +54 -2
- package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +155 -10
- package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +157 -33
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +404 -116
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RealtimeSessionEventsResolver.d.ts +61 -0
- package/dist/resolvers/RealtimeSessionEventsResolver.d.ts.map +1 -0
- package/dist/resolvers/RealtimeSessionEventsResolver.js +130 -0
- package/dist/resolvers/RealtimeSessionEventsResolver.js.map +1 -0
- package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts +85 -0
- package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts.map +1 -0
- package/dist/resolvers/RealtimeSessionVerificationResolver.js +188 -0
- package/dist/resolvers/RealtimeSessionVerificationResolver.js.map +1 -0
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts +2 -0
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +5 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +10 -0
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +100 -14
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +12 -11
- package/dist/resolvers/RunTemplateResolver.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 +6 -2
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts +2 -0
- package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +23 -6
- package/dist/resolvers/SyncRolesUsersResolver.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 +65 -13
- package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts +19 -2
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +102 -24
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/UserAvatarResolver.d.ts +16 -0
- package/dist/resolvers/UserAvatarResolver.d.ts.map +1 -0
- package/dist/resolvers/UserAvatarResolver.js +124 -0
- package/dist/resolvers/UserAvatarResolver.js.map +1 -0
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +2 -17
- package/dist/resolvers/UserResolver.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/resolvers/agentVisionConsentAudit.d.ts +37 -0
- package/dist/resolvers/agentVisionConsentAudit.d.ts.map +1 -0
- package/dist/resolvers/agentVisionConsentAudit.js +63 -0
- package/dist/resolvers/agentVisionConsentAudit.js.map +1 -0
- package/dist/resolvers/avatarInputValidation.d.ts +40 -0
- package/dist/resolvers/avatarInputValidation.d.ts.map +1 -0
- package/dist/resolvers/avatarInputValidation.js +97 -0
- package/dist/resolvers/avatarInputValidation.js.map +1 -0
- package/dist/resolvers/currentUserRoles.d.ts +29 -0
- package/dist/resolvers/currentUserRoles.d.ts.map +1 -1
- package/dist/resolvers/currentUserRoles.js +30 -0
- package/dist/resolvers/currentUserRoles.js.map +1 -1
- package/dist/resolvers/meetings/meetingMutations.d.ts +6 -0
- package/dist/resolvers/meetings/meetingMutations.d.ts.map +1 -1
- package/dist/resolvers/meetings/meetingMutations.js +21 -0
- package/dist/resolvers/meetings/meetingMutations.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 +3 -1
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +21 -12
- 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/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 +57 -4
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +607 -18
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/sharedCache.d.ts +105 -0
- package/dist/sharedCache.d.ts.map +1 -0
- package/dist/sharedCache.js +279 -0
- package/dist/sharedCache.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +99 -96
- package/src/__tests__/ActionResolver.authorization.test.ts +353 -0
- package/src/__tests__/AdhocQueryResolver.sqlAuthorizer.test.ts +104 -0
- package/src/__tests__/BridgeHostInstance.test.ts +232 -0
- package/src/__tests__/ClientToolRequestResolver.test.ts +116 -0
- package/src/__tests__/DatasetResolver.itemFilters.test.ts +201 -0
- package/src/__tests__/EntityRecordNameResolver.rowSecurity.test.ts +152 -0
- package/src/__tests__/FetchEntityVectorsResolver.test.ts +433 -0
- package/src/__tests__/FileResolver.storageAccess.test.ts +562 -0
- package/src/__tests__/GetDataContextDataResolver.sqlItems.test.ts +416 -0
- package/src/__tests__/HostInstance.test.ts +84 -0
- package/src/__tests__/HumanHandoffResolver.test.ts +17 -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__/MeetingResolver.test.ts +75 -1
- package/src/__tests__/RealtimeBridgeResolver.test.ts +415 -6
- package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +383 -0
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +682 -58
- package/src/__tests__/RealtimeProxyServer.test.ts +16 -1
- package/src/__tests__/RealtimeRelay.test.ts +876 -0
- package/src/__tests__/RecordingAssemblyScheduler.test.ts +178 -0
- package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +129 -0
- package/src/__tests__/ResolverBase.adhocReadScope.test.ts +133 -2
- package/src/__tests__/ResolverBase.aggregateScreen.test.ts +174 -0
- 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 +212 -6
- package/src/__tests__/ResolverBase.filterEscaping.test.ts +5 -2
- package/src/__tests__/ReturningVisitorRecap.test.ts +115 -0
- package/src/__tests__/RunAIAgentResolver.branch.test.ts +170 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +6 -4
- package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +258 -0
- package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +166 -0
- package/src/__tests__/RunTemplateResolver.test.ts +132 -0
- package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +63 -0
- package/src/__tests__/RunViewResolver.cacheCheckScreen.test.ts +165 -0
- package/src/__tests__/SearchKnowledgeStreamResolver.test.ts +161 -0
- package/src/__tests__/SessionJanitor.test.ts +1203 -21
- package/src/__tests__/SessionManager.test.ts +240 -17
- package/src/__tests__/SessionRunIDVerifier.test.ts +251 -0
- package/src/__tests__/SyncRolesUsersResolver.userRoles.test.ts +97 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +25 -0
- package/src/__tests__/TaskGraphAgentRunner.test.ts +266 -0
- package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +403 -22
- package/src/__tests__/TaskGraphFrameResolver.test.ts +22 -0
- package/src/__tests__/TestQuerySQLResolver.test.ts +274 -0
- package/src/__tests__/TransactionGroupResolver.refusals.test.ts +98 -1
- package/src/__tests__/UpdateMJDataContextItem.oldValues.test.ts +220 -0
- package/src/__tests__/UserAvatarResolver.test.ts +255 -0
- package/src/__tests__/UserResolver.currentUser.test.ts +16 -1
- package/src/__tests__/ViewOperationsHandler.clauseScreen.test.ts +157 -0
- package/src/__tests__/actionAuthorization.test.ts +130 -0
- package/src/__tests__/agent-run-data-guard.test.ts +130 -0
- package/src/__tests__/agentVisionConsentAudit.test.ts +118 -0
- package/src/__tests__/apiRootBoot.test.ts +202 -0
- package/src/__tests__/avatarInputValidation.test.ts +160 -0
- package/src/__tests__/cacheInvalidationRecordData.test.ts +64 -0
- package/src/__tests__/conversationRunEvents.test.ts +56 -14
- package/src/__tests__/globalCors.test.ts +217 -0
- package/src/__tests__/isolatedProviderTransactions.test.ts +169 -0
- package/src/__tests__/magicLinkService.consume.test.ts +6 -0
- package/src/__tests__/magicLinkService.provisionLog.test.ts +5 -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__/newUsers.template.test.ts +151 -0
- package/src/__tests__/newUsers.test.ts +74 -5
- package/src/__tests__/orphanedConversationDetailReconciler.test.ts +17 -2
- package/src/__tests__/ownedRealtimeSession.test.ts +39 -0
- package/src/__tests__/pushStatusResolver.filter.test.ts +7 -0
- package/src/__tests__/realtimeRecordingHandler.test.ts +652 -0
- package/src/__tests__/realtimeSessions/RealtimeSessionEventService.test.ts +201 -0
- package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +215 -0
- package/src/__tests__/realtimeSessions/RealtimeSessionVerificationResolver.test.ts +102 -0
- package/src/__tests__/realtimeSessions/RealtimeSessionVerificationService.test.ts +349 -0
- package/src/__tests__/realtimeSessions/RealtimeVerifyRouter.test.ts +131 -0
- package/src/__tests__/realtimeSessions/SlidingWindowRateLimiter.test.ts +56 -0
- package/src/__tests__/realtimeSessions/helpers.ts +4 -0
- package/src/__tests__/realtimeSessions/sessionAccess.test.ts +129 -0
- package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +124 -0
- package/src/__tests__/realtimeSessions/verificationCore.test.ts +355 -0
- package/src/__tests__/realtimeSessions/verificationPages.test.ts +84 -0
- package/src/__tests__/realtimeSessions/verificationPolicy.test.ts +226 -0
- package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +633 -0
- package/src/__tests__/resolverBase.fls.test.ts +87 -4
- package/src/__tests__/serverExtensionHostOverlay.test.ts +66 -0
- package/src/__tests__/serverExtensionReservedRoots.test.ts +11 -96
- package/src/__tests__/sharedCache.test.ts +312 -0
- package/src/__tests__/widgetGuestElevation.test.ts +44 -0
- package/src/agentSessions/BridgeHostInstance.ts +32 -0
- package/src/agentSessions/HostInstance.ts +124 -28
- package/src/agentSessions/ReturningVisitorRecap.ts +7 -3
- package/src/agentSessions/SessionJanitor.ts +821 -59
- package/src/agentSessions/SessionManager.ts +138 -26
- package/src/agentSessions/SessionRunIDVerifier.ts +171 -0
- package/src/agentSessions/index.ts +10 -3
- package/src/apiRoot.ts +78 -0
- package/src/auth/AuthProviderCatalogRouter.ts +26 -0
- package/src/auth/LoginScreenEngine.ts +50 -0
- package/src/auth/actionAuthorization.ts +116 -0
- package/src/auth/index.ts +4 -8
- package/src/auth/magicLink/MagicLinkRouter.ts +3 -2
- package/src/auth/magicLink/MagicLinkService.ts +6 -3
- package/src/auth/newUsers.ts +99 -11
- package/src/config.ts +171 -5
- package/src/context.ts +15 -10
- package/src/coreRoutes.ts +166 -0
- package/src/generated/graphql-schemas/__mj.ts +1815 -57
- package/src/generic/CacheInvalidationResolver.ts +73 -18
- package/src/generic/OrphanedConversationDetailReconciler.ts +3 -3
- package/src/generic/PushStatusResolver.ts +1 -1
- package/src/generic/ResolverBase.ts +335 -326
- package/src/generic/RunViewResolver.ts +21 -0
- package/src/globalCors.ts +71 -0
- package/src/index.ts +231 -300
- package/src/isolatedProvider.ts +22 -0
- package/src/multiTenancy/index.ts +24 -2
- package/src/realtimeProxy/RealtimeProxyServer.ts +148 -16
- package/src/realtimeProxy/RealtimeRelayTunnel.ts +645 -0
- package/src/realtimeSessions/README.md +179 -0
- package/src/realtimeSessions/RealtimeSessionEventService.ts +274 -0
- package/src/realtimeSessions/RealtimeSessionVerificationService.ts +168 -0
- package/src/realtimeSessions/RealtimeVerifyRouter.ts +109 -0
- package/src/realtimeSessions/RecordingAssemblyScheduler.ts +234 -0
- package/src/realtimeSessions/SessionVerificationPortsBase.ts +189 -0
- package/src/realtimeSessions/SlidingWindowRateLimiter.ts +92 -0
- package/src/realtimeSessions/index.ts +18 -0
- package/src/realtimeSessions/ownedRealtimeSession.ts +55 -0
- package/src/realtimeSessions/sessionAccess.ts +145 -0
- package/src/realtimeSessions/sessionConfigStamps.ts +123 -0
- package/src/realtimeSessions/subscriptionAuthorization.ts +116 -0
- package/src/realtimeSessions/verificationCore.ts +502 -0
- package/src/realtimeSessions/verificationPages.ts +149 -0
- package/src/realtimeSessions/verificationPolicy.ts +321 -0
- package/src/realtimeSessions/verificationWorkflow.ts +702 -0
- package/src/realtimeWidget/widgetGuestElevation.ts +34 -2
- package/src/resolvers/ActionResolver.ts +84 -21
- package/src/resolvers/AdhocQueryResolver.ts +24 -6
- package/src/resolvers/ArtifactFileResolver.ts +9 -8
- package/src/resolvers/CacheStatsResolver.ts +89 -2
- package/src/resolvers/ClientToolRequestResolver.ts +25 -7
- package/src/resolvers/ConversationRunEventsResolver.ts +15 -11
- package/src/resolvers/DatasetResolver.ts +70 -10
- package/src/resolvers/EntityRecordNameResolver.ts +3 -2
- package/src/resolvers/FetchEntityVectorsResolver.ts +179 -2
- package/src/resolvers/FileResolver.ts +321 -106
- package/src/resolvers/GetDataContextDataResolver.ts +139 -41
- package/src/resolvers/GetDataResolver.ts +6 -3
- package/src/resolvers/HumanHandoffResolver.ts +8 -0
- package/src/resolvers/IntegrationDiscoveryResolver.ts +4 -2
- package/src/resolvers/MCPResolver.ts +8 -5
- package/src/resolvers/QueryResolver.ts +11 -0
- package/src/resolvers/RealtimeBridgeResolver.ts +163 -11
- package/src/resolvers/RealtimeClientSessionResolver.ts +511 -129
- package/src/resolvers/RealtimeSessionEventsResolver.ts +133 -0
- package/src/resolvers/RealtimeSessionVerificationResolver.ts +174 -0
- package/src/resolvers/RemoteBrowserActionResolver.ts +11 -1
- package/src/resolvers/RunAIAgentResolver.ts +116 -14
- package/src/resolvers/RunTemplateResolver.ts +13 -12
- package/src/resolvers/SearchKnowledgeStreamResolver.ts +19 -3
- package/src/resolvers/SqlLoggingConfigResolver.ts +2 -4
- package/src/resolvers/SyncDataResolver.ts +6 -2
- package/src/resolvers/SyncRolesUsersResolver.ts +24 -6
- package/src/resolvers/TaskGraphFrameResolver.ts +33 -1
- package/src/resolvers/TestQuerySQLResolver.ts +68 -13
- package/src/resolvers/TransactionGroupResolver.ts +131 -27
- package/src/resolvers/UserAvatarResolver.ts +111 -0
- package/src/resolvers/UserResolver.ts +2 -16
- package/src/resolvers/__tests__/GetDataResolver.validation.test.ts +95 -0
- package/src/resolvers/agent-run-data-guard.ts +89 -0
- package/src/resolvers/agentVisionConsentAudit.ts +82 -0
- package/src/resolvers/avatarInputValidation.ts +123 -0
- package/src/resolvers/currentUserRoles.ts +32 -1
- package/src/resolvers/meetings/meetingMutations.ts +21 -0
- package/src/rest/RealtimeRecordingHandler.ts +464 -0
- package/src/rest/ViewOperationsHandler.ts +29 -13
- package/src/rest/setupRESTEndpoints.ts +6 -0
- package/src/serverExtensionReservedRoots.ts +14 -17
- 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 +713 -17
- package/src/sharedCache.ts +305 -0
- package/src/types.ts +7 -0
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, ObjectType, Query, Resolver } from "type-graphql";
|
|
2
|
+
import type { DatabaseProviderBase, UserInfo } from "@memberjunction/core";
|
|
3
|
+
import { IsValidUUID, UUIDsEqual } from "@memberjunction/global";
|
|
4
|
+
import { DataContext, DataContextItem } from "@memberjunction/data-context";
|
|
5
|
+
import { MJDataContextEntity, MJDataContextItemEntity } from "@memberjunction/core-entities";
|
|
6
|
+
import { RenderPipeline } from "@memberjunction/generic-database-provider";
|
|
2
7
|
import { AppContext } from "../types.js";
|
|
3
|
-
import {
|
|
4
|
-
import { GetReadOnlyDataSource, GetReadOnlyProvider } from "../util.js";
|
|
5
|
-
import { MJDataContextItemEntity } from "@memberjunction/core-entities";
|
|
8
|
+
import { GetReadOnlyProvider } from "../util.js";
|
|
6
9
|
import { ResolverBase } from "../generic/ResolverBase.js";
|
|
10
|
+
import { IsScopeLimitedPrincipal } from "../auth/scopeLimitedPrincipal.js";
|
|
7
11
|
|
|
8
12
|
@ObjectType()
|
|
9
13
|
export class GetDataContextItemDataOutputType {
|
|
@@ -39,6 +43,28 @@ export class GetDataContextDataOutputType {
|
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
|
|
46
|
+
/** The outcome of loading one data context item: its data as JSON, or why it has none. */
|
|
47
|
+
interface ItemOutcome {
|
|
48
|
+
Result: string | null;
|
|
49
|
+
Error: string | null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Which `sql` items of a data context may run: the read-only provider, and each refused item's reason. */
|
|
53
|
+
interface SQLItemGate {
|
|
54
|
+
Provider: DatabaseProviderBase | null;
|
|
55
|
+
Refusals: Map<DataContextItem, string>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Loads the data of data contexts and their items.
|
|
60
|
+
*
|
|
61
|
+
* Items of type `sql` hold raw SQL, which is held to the rules ExecuteAdhocQuery applies to
|
|
62
|
+
* caller-supplied SQL. It runs only for the data context's owner or an administrator (Owner-type
|
|
63
|
+
* user), never for a scope-limited session, only on the read-only provider, and only as a single read
|
|
64
|
+
* statement over entity base views the caller may read in full. A SQL item that may not run is
|
|
65
|
+
* refused on its own, and the other items still load. Items of the other types load through entity
|
|
66
|
+
* permissions for the calling user.
|
|
67
|
+
*/
|
|
42
68
|
@Resolver()
|
|
43
69
|
export class GetDataContextDataResolver extends ResolverBase {
|
|
44
70
|
/**
|
|
@@ -52,30 +78,25 @@ export class GetDataContextDataResolver extends ResolverBase {
|
|
|
52
78
|
) {
|
|
53
79
|
// Check API key scope authorization for data context read
|
|
54
80
|
await this.CheckAPIKeyScopeAuthorization('datacontext:read', DataContextItemID, appCtx.userPayload);
|
|
81
|
+
if (!IsValidUUID(DataContextItemID)) {
|
|
82
|
+
return { Success: false, ErrorMessage: 'DataContextItemID must be a UUID', Result: null };
|
|
83
|
+
}
|
|
55
84
|
|
|
56
85
|
try {
|
|
57
|
-
const
|
|
58
|
-
allowFallbackToReadWrite: true,
|
|
59
|
-
})
|
|
86
|
+
const user: UserInfo = appCtx.userPayload.userRecord;
|
|
60
87
|
const md = GetReadOnlyProvider(appCtx.providers, {allowFallbackToReadWrite: true});
|
|
61
|
-
const dciData = await md.GetEntityObject<MJDataContextItemEntity>("MJ: Data Context Items",
|
|
88
|
+
const dciData = await md.GetEntityObject<MJDataContextItemEntity>("MJ: Data Context Items", user);
|
|
62
89
|
if (await dciData.Load(DataContextItemID)) {
|
|
63
90
|
const dci = DataContext.CreateDataContextItem(); // use class factory to get whatever lowest level sub-class is registered
|
|
64
|
-
await dci.LoadMetadataFromEntityRecord(dciData, md,
|
|
91
|
+
await dci.LoadMetadataFromEntityRecord(dciData, md, user);
|
|
92
|
+
const ownerID = dci.Type === 'sql' ? await this.loadDataContextOwnerID(dciData.DataContextID, md, user) : null;
|
|
93
|
+
const gate = this.authorizeSQLItems([dci], ownerID, appCtx);
|
|
65
94
|
// now the metadata is loaded so we can call the regular load function
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
return {
|
|
75
|
-
Success: false,
|
|
76
|
-
ErrorMessage: 'Error loading data context item data',
|
|
77
|
-
Result: null,
|
|
78
|
-
}
|
|
95
|
+
const outcome = await this.loadItem(dci, gate, user, false);
|
|
96
|
+
return {
|
|
97
|
+
Success: outcome.Error === null,
|
|
98
|
+
ErrorMessage: outcome.Error,
|
|
99
|
+
Result: outcome.Result,
|
|
79
100
|
}
|
|
80
101
|
}
|
|
81
102
|
else {
|
|
@@ -89,14 +110,15 @@ export class GetDataContextDataResolver extends ResolverBase {
|
|
|
89
110
|
catch (e) {
|
|
90
111
|
return {
|
|
91
112
|
Success: false,
|
|
92
|
-
ErrorMessage: e,
|
|
113
|
+
ErrorMessage: e instanceof Error ? e.message : String(e),
|
|
93
114
|
Result: null,
|
|
94
115
|
}
|
|
95
116
|
}
|
|
96
117
|
}
|
|
97
118
|
|
|
98
119
|
/**
|
|
99
|
-
* Returns data for a given data context.
|
|
120
|
+
* Returns data for a given data context. `Results` and `ErrorMessages` hold one entry per item, in
|
|
121
|
+
* item order. `Success` is true, and `ErrorMessages` null, only when every item loaded.
|
|
100
122
|
* @param DataContextID
|
|
101
123
|
*/
|
|
102
124
|
@Query(() => GetDataContextDataOutputType)
|
|
@@ -106,38 +128,114 @@ export class GetDataContextDataResolver extends ResolverBase {
|
|
|
106
128
|
) {
|
|
107
129
|
// Check API key scope authorization for data context read
|
|
108
130
|
await this.CheckAPIKeyScopeAuthorization('datacontext:read', DataContextID, appCtx.userPayload);
|
|
131
|
+
// DataContext.LoadMetadata places this ID in the item filter, so it must be a plain UUID.
|
|
132
|
+
if (!IsValidUUID(DataContextID)) {
|
|
133
|
+
return { Success: false, ErrorMessages: ['DataContextID must be a UUID'], Results: null };
|
|
134
|
+
}
|
|
109
135
|
|
|
110
136
|
try {
|
|
111
137
|
// our job here is to load the entire data context, so we do that with the Data Context object
|
|
138
|
+
const user: UserInfo = appCtx.userPayload.userRecord;
|
|
139
|
+
const md = GetReadOnlyProvider(appCtx.providers, { allowFallbackToReadWrite: true });
|
|
112
140
|
const dc = new DataContext();
|
|
113
|
-
|
|
114
|
-
allowFallbackToReadWrite: true,
|
|
115
|
-
})
|
|
116
|
-
const success = await dc.Load(DataContextID, ds, true, false, 0, appCtx.userPayload.userRecord);
|
|
117
|
-
if (success) {
|
|
118
|
-
const retVal = {
|
|
119
|
-
Success: true,
|
|
120
|
-
ErrorMessages: null,
|
|
121
|
-
Results: dc.Items.map((item) => {
|
|
122
|
-
return JSON.stringify(item.Data);
|
|
123
|
-
}),
|
|
124
|
-
}
|
|
125
|
-
return retVal;
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
141
|
+
if (!(await dc.LoadMetadata(DataContextID, user, md))) {
|
|
128
142
|
return {
|
|
129
143
|
Success: false,
|
|
130
144
|
ErrorMessages: ['Error loading data context'],
|
|
131
|
-
Results: null,
|
|
145
|
+
Results: null,
|
|
132
146
|
}
|
|
133
147
|
}
|
|
148
|
+
const gate = this.authorizeSQLItems(dc.Items, dc.MJDataContextEntity.UserID, appCtx);
|
|
149
|
+
const outcomes = await Promise.all(dc.Items.map((item) => this.loadItem(item, gate, user, true)));
|
|
150
|
+
const allLoaded = outcomes.every((outcome) => outcome.Error === null);
|
|
151
|
+
return {
|
|
152
|
+
Success: allLoaded,
|
|
153
|
+
ErrorMessages: allLoaded ? null : outcomes.map((outcome) => outcome.Error),
|
|
154
|
+
Results: outcomes.map((outcome) => outcome.Result),
|
|
155
|
+
}
|
|
134
156
|
}
|
|
135
157
|
catch (e) {
|
|
136
158
|
return {
|
|
137
159
|
Success: false,
|
|
138
|
-
ErrorMessages: [e],
|
|
160
|
+
ErrorMessages: [e instanceof Error ? e.message : String(e)],
|
|
139
161
|
Results: null,
|
|
140
162
|
}
|
|
141
163
|
}
|
|
142
164
|
}
|
|
143
|
-
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Decides which `sql` items among `items` may run. Returns the read-only provider they run on, and
|
|
168
|
+
* the reason for each SQL item that may not run.
|
|
169
|
+
*/
|
|
170
|
+
private authorizeSQLItems(items: DataContextItem[], ownerID: string | null, appCtx: AppContext): SQLItemGate {
|
|
171
|
+
const refusals = new Map<DataContextItem, string>();
|
|
172
|
+
const sqlItems = items.filter((item) => item.Type === 'sql');
|
|
173
|
+
if (sqlItems.length === 0) {
|
|
174
|
+
return { Provider: null, Refusals: refusals };
|
|
175
|
+
}
|
|
176
|
+
const user: UserInfo | undefined = appCtx.userPayload?.userRecord;
|
|
177
|
+
const provider = GetReadOnlyProvider(appCtx.providers, { allowFallbackToReadWrite: false });
|
|
178
|
+
for (const item of sqlItems) {
|
|
179
|
+
const refusal = this.sqlItemRefusal(item, ownerID, user, provider);
|
|
180
|
+
if (refusal !== null) {
|
|
181
|
+
refusals.set(item, refusal);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return { Provider: provider, Refusals: refusals };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Returns why `item` may not run for `user`, or null when it may. */
|
|
188
|
+
private sqlItemRefusal(item: DataContextItem, ownerID: string | null, user: UserInfo | undefined, provider: DatabaseProviderBase | null): string | null {
|
|
189
|
+
if (!user || IsScopeLimitedPrincipal(user)) {
|
|
190
|
+
return 'SQL data context items cannot be run by a scope-limited or unidentified session.';
|
|
191
|
+
}
|
|
192
|
+
if (!this.mayRunDataContextSQL(ownerID, user)) {
|
|
193
|
+
return 'Only the owner of this data context, or an administrator, may run its SQL items.';
|
|
194
|
+
}
|
|
195
|
+
if (!provider) {
|
|
196
|
+
return 'No read-only data source is configured, so SQL data context items cannot run.';
|
|
197
|
+
}
|
|
198
|
+
return this.screenItemSQL(item.SQL ?? '', provider, user);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** True when `user` owns the data context or is an administrator (Owner-type user). */
|
|
202
|
+
private mayRunDataContextSQL(ownerID: string | null, user: UserInfo): boolean {
|
|
203
|
+
const isOwner = !!ownerID && UUIDsEqual(ownerID, user.ID);
|
|
204
|
+
return isOwner || user.Type?.trim().toLowerCase() === 'owner';
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Returns why `sqlText` may not run, or null when it is a single read statement whose every table
|
|
209
|
+
* reference is an entity base view `user` may read without row-level or field-level narrowing. It is
|
|
210
|
+
* the check ExecuteAdhocQuery makes on the rendered SQL.
|
|
211
|
+
*/
|
|
212
|
+
private screenItemSQL(sqlText: string, provider: DatabaseProviderBase, user: UserInfo): string | null {
|
|
213
|
+
try {
|
|
214
|
+
const rendered = RenderPipeline.Run(sqlText, { Platform: provider.PlatformKey, ContextUser: user, RequireReadStatement: true });
|
|
215
|
+
this.assertFullQueryUsesReadableEntityViews(rendered.Trace.AfterTemplates, provider, user, 'data context SQL');
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
catch (e) {
|
|
219
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
220
|
+
return reason || 'The SQL of this item did not pass the read-only check.';
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** Loads one item's data unless `gate` refused it. Returns the data as JSON, or why there is none. */
|
|
225
|
+
private async loadItem(item: DataContextItem, gate: SQLItemGate, user: UserInfo, forceRefresh: boolean): Promise<ItemOutcome> {
|
|
226
|
+
const refusal = gate.Refusals.get(item);
|
|
227
|
+
if (refusal !== undefined) {
|
|
228
|
+
return { Result: null, Error: refusal };
|
|
229
|
+
}
|
|
230
|
+
if (await item.LoadData(gate.Provider, forceRefresh, false, 0, user)) {
|
|
231
|
+
return { Result: JSON.stringify(item.Data), Error: null };
|
|
232
|
+
}
|
|
233
|
+
return { Result: null, Error: item.DataLoadingError || 'Error loading data context item data' };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Returns the owner (`UserID`) of a data context, or null when the caller cannot load it. */
|
|
237
|
+
private async loadDataContextOwnerID(dataContextID: string, provider: DatabaseProviderBase, user: UserInfo): Promise<string | null> {
|
|
238
|
+
const dataContext = await provider.GetEntityObject<MJDataContextEntity>('MJ: Data Contexts', user);
|
|
239
|
+
return (await dataContext.Load(dataContextID)) ? dataContext.UserID : null;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
@@ -158,14 +158,17 @@ export class GetDataResolver {
|
|
|
158
158
|
// Defense-in-depth: even system-token holders get SELECT-only SQL here.
|
|
159
159
|
// The read-only pool is the primary control, but if it is ever
|
|
160
160
|
// misconfigured to a read-write login this validator still refuses DML/DDL
|
|
161
|
-
// (mirrors AdhocQueryResolver).
|
|
162
|
-
|
|
161
|
+
// (mirrors AdhocQueryResolver). The validator reads exactly the text that
|
|
162
|
+
// runs: it is trimmed here as validate() trims it, and literal \n sequences
|
|
163
|
+
// are not rewritten as ValidateFullQuery would.
|
|
164
|
+
const sqlToRun = resolvedSQL.trim();
|
|
165
|
+
const validation = SQLExpressionValidator.Instance.validate(sqlToRun, { context: 'full_query', Dialect: platform });
|
|
163
166
|
if (!validation.valid) {
|
|
164
167
|
return { result: null, error: validation.error || 'SQL validation failed' };
|
|
165
168
|
}
|
|
166
169
|
|
|
167
170
|
const request = new sql.Request(readOnlyDataSource);
|
|
168
|
-
const result = await request.query(
|
|
171
|
+
const result = await request.query(sqlToRun);
|
|
169
172
|
return { result: result.recordset, error: null };
|
|
170
173
|
} catch (err) {
|
|
171
174
|
// Extract clean SQL error message
|
|
@@ -2,9 +2,11 @@ import { Resolver, Mutation, Query, Subscription, Arg, Ctx, Root, ObjectType, Fi
|
|
|
2
2
|
import { IMetadataProvider, LogError, UserInfo } from '@memberjunction/core';
|
|
3
3
|
import { MJGlobal, UUIDsEqual } from '@memberjunction/global';
|
|
4
4
|
import { NotificationEngine } from '@memberjunction/notifications';
|
|
5
|
+
import { UserCache } from '@memberjunction/generic-database-provider';
|
|
5
6
|
import {
|
|
6
7
|
LiveKitSipService,
|
|
7
8
|
RoomHandoffEngine,
|
|
9
|
+
HandoffOfferRegistry,
|
|
8
10
|
type HandoffOfferEvent,
|
|
9
11
|
type HandoffOfferView,
|
|
10
12
|
type IHandoffNotifier,
|
|
@@ -207,6 +209,12 @@ export class NotificationHandoffNotifier implements IHandoffNotifier {
|
|
|
207
209
|
}
|
|
208
210
|
}
|
|
209
211
|
|
|
212
|
+
// The registry's background sweep and list queries run outside any request, so they need a server identity. Resolve the
|
|
213
|
+
// system user lazily: the user cache may not have loaded when this module does.
|
|
214
|
+
HandoffOfferRegistry.Instance.Configure({
|
|
215
|
+
ResolveContextUser: () => UserCache.Instance.GetSystemUser(),
|
|
216
|
+
});
|
|
217
|
+
|
|
210
218
|
/**
|
|
211
219
|
* Binds the handoff engine's collaborators that only the server host can supply (same module-load rationale as the other
|
|
212
220
|
* realtime bindings): the pub/sub publisher, the notification sender, and a room-presence check over the LiveKit credentials
|
|
@@ -3,7 +3,7 @@ import { CompositeKey, DatabaseProviderBase, EntityInfo, LocalCacheManager, Meta
|
|
|
3
3
|
import { GetReadOnlyProvider, GetReadWriteProvider } from "../util.js";
|
|
4
4
|
import { NoLog } from "../logging/NoLog.js";
|
|
5
5
|
import { UUIDsEqual } from "@memberjunction/global";
|
|
6
|
-
import { DrainResponseBody } from "@memberjunction/network-utils";
|
|
6
|
+
import { DrainResponseBody, SafeFetch } from "@memberjunction/network-utils";
|
|
7
7
|
import { CronExpressionHelper } from "@memberjunction/scheduling-engine";
|
|
8
8
|
import {
|
|
9
9
|
MJCompanyIntegrationEntity,
|
|
@@ -6467,7 +6467,9 @@ export class IntegrationDiscoveryResolver extends ResolverBase {
|
|
|
6467
6467
|
|
|
6468
6468
|
private async sendWebhook(url: string, payload: Record<string, unknown>): Promise<void> {
|
|
6469
6469
|
try {
|
|
6470
|
-
|
|
6470
|
+
// SECURITY: the webhook URL is caller-supplied, so go through the SSRF guard —
|
|
6471
|
+
// SafeFetch validates the URL (and every redirect hop) resolves to a public address.
|
|
6472
|
+
const response = await SafeFetch(url, {
|
|
6471
6473
|
method: 'POST',
|
|
6472
6474
|
headers: { 'Content-Type': 'application/json' },
|
|
6473
6475
|
body: JSON.stringify(payload)
|
|
@@ -639,11 +639,14 @@ export class MCPResolver extends ResolverBase {
|
|
|
639
639
|
// Publish syncing progress
|
|
640
640
|
this.publishProgress(pubSub, sessionId, user.ID, ConnectionID, 'syncing', 'Synchronizing tools to database...');
|
|
641
641
|
|
|
642
|
-
// Perform the sync
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
642
|
+
// Perform the sync; always detach the listener, even if syncTools throws, so failed
|
|
643
|
+
// syncs don't stack handlers on the shared manager.
|
|
644
|
+
let syncResult: MCPSyncToolsResult;
|
|
645
|
+
try {
|
|
646
|
+
syncResult = await manager.syncTools(ConnectionID, { contextUser: user });
|
|
647
|
+
} finally {
|
|
648
|
+
manager.removeEventListener('toolsSynced', eventHandler);
|
|
649
|
+
}
|
|
647
650
|
|
|
648
651
|
if (!syncResult.success) {
|
|
649
652
|
this.publishProgress(pubSub, sessionId, user.ID, ConnectionID, 'error', `Sync failed: ${syncResult.error}`);
|
|
@@ -101,6 +101,12 @@ export class RunQueryCacheStatusInput {
|
|
|
101
101
|
|
|
102
102
|
@Field(() => Int, { description: 'The number of rows in cached results' })
|
|
103
103
|
rowCount: number; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
104
|
+
|
|
105
|
+
@Field(() => String, {
|
|
106
|
+
nullable: true,
|
|
107
|
+
description: "The query definition hash the cached results were written under, as this server returned it. When it differs from the server's, the result is 'stale' with fresh rows. Empty string for a slot with no hash; omit to skip the definition check."
|
|
108
|
+
})
|
|
109
|
+
definitionHash?: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name, matching its siblings
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
@InputType()
|
|
@@ -140,6 +146,9 @@ export class RunQueryWithCacheCheckResultOutput {
|
|
|
140
146
|
|
|
141
147
|
@Field(() => String, { nullable: true, description: 'Error message if status is error' })
|
|
142
148
|
errorMessage?: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
149
|
+
|
|
150
|
+
@Field(() => String, { nullable: true, description: "The server's definition hash for the query; store it with the cached results and send it back in cacheStatus.definitionHash" })
|
|
151
|
+
definitionHash?: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name, matching its siblings
|
|
143
152
|
}
|
|
144
153
|
|
|
145
154
|
@ObjectType()
|
|
@@ -558,6 +567,7 @@ export class RunQueryResolver extends ResolverBase {
|
|
|
558
567
|
cacheStatus: item.cacheStatus ? {
|
|
559
568
|
maxUpdatedAt: item.cacheStatus.maxUpdatedAt,
|
|
560
569
|
rowCount: item.cacheStatus.rowCount,
|
|
570
|
+
definitionHash: item.cacheStatus.definitionHash ?? undefined,
|
|
561
571
|
} : undefined,
|
|
562
572
|
}));
|
|
563
573
|
|
|
@@ -572,6 +582,7 @@ export class RunQueryResolver extends ResolverBase {
|
|
|
572
582
|
maxUpdatedAt: result.maxUpdatedAt,
|
|
573
583
|
rowCount: result.rowCount,
|
|
574
584
|
errorMessage: result.errorMessage,
|
|
585
|
+
definitionHash: result.definitionHash,
|
|
575
586
|
}));
|
|
576
587
|
|
|
577
588
|
return {
|
|
@@ -7,8 +7,13 @@ import {
|
|
|
7
7
|
LiveKitTokenService,
|
|
8
8
|
LiveKitAgentRoomCoordinator,
|
|
9
9
|
LiveKitEgressService,
|
|
10
|
+
LiveKitParticipantService,
|
|
10
11
|
LiveKitUserIdentity,
|
|
11
12
|
RoomHandoffEngine,
|
|
13
|
+
type AgentRoomHostOptions,
|
|
14
|
+
type AgentRoomSession,
|
|
15
|
+
type ParticipantUpdateResult,
|
|
16
|
+
type StartAgentRoomSessionParams,
|
|
12
17
|
} from '@memberjunction/livekit-room-server';
|
|
13
18
|
import { AppContext } from '../types.js';
|
|
14
19
|
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
@@ -18,7 +23,8 @@ import { AIBridgeEngine } from '@memberjunction/ai-bridge-server';
|
|
|
18
23
|
import { SessionManager } from '../agentSessions/SessionManager.js';
|
|
19
24
|
import { NotificationEngine } from '@memberjunction/notifications';
|
|
20
25
|
import { RegisterMeetingRecordingFile, CorrelateRecordingStart } from './meetingRecordingRegistration.js';
|
|
21
|
-
import {
|
|
26
|
+
import { WriteAgentVisionConsentAudit } from './agentVisionConsentAudit.js';
|
|
27
|
+
import { RoomAuthorizationService, type RoomAuthorizationResult } from '@memberjunction/livekit-room-server';
|
|
22
28
|
|
|
23
29
|
/**
|
|
24
30
|
* Binds the agent realtime-session factory onto the LiveKit room coordinator's model-session creation seam.
|
|
@@ -44,6 +50,23 @@ LiveKitAgentRoomCoordinator.Instance.SetTurnToolBinder((session, handler) => {
|
|
|
44
50
|
runtime.SetLocalToolHandler(handler);
|
|
45
51
|
});
|
|
46
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Binds whether an agent watches meetings (same module-load rationale as the factory above). The coordinator asks per
|
|
55
|
+
* model session; the answer is the agent's `realtime.video.watchMeetings` setting, which the session runtime read from
|
|
56
|
+
* its effective configuration (`@memberjunction/ai-agents`). The coordinator also requires a model that takes video.
|
|
57
|
+
*/
|
|
58
|
+
LiveKitAgentRoomCoordinator.Instance.SetAgentVisionResolver((session) => GetBridgeRealtimeRuntime(session)?.WatchesMeetingVideo === true);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Binds how a failed agent start is recorded on the agent's co-agent run (same module-load rationale as the factory
|
|
62
|
+
* above). The coordinator closes the model session of a start that fails before the bridge engine takes it; that close
|
|
63
|
+
* alone finalizes the run as Completed, so the coordinator first has the session's runtime finalize it as Failed, with the
|
|
64
|
+
* start's error.
|
|
65
|
+
*/
|
|
66
|
+
LiveKitAgentRoomCoordinator.Instance.SetFailedStartRecorder(async (session, error) => {
|
|
67
|
+
await GetBridgeRealtimeRuntime(session)?.Finalize(false, error);
|
|
68
|
+
});
|
|
69
|
+
|
|
47
70
|
/**
|
|
48
71
|
* Binds the co-agent run finalizer onto the bridge engine (same module-load rationale as the factory above).
|
|
49
72
|
* Lets the engine finalize a session's dangling co-agent observability run when it reaps a bridge WITHOUT a
|
|
@@ -233,7 +256,30 @@ export class LiveKitRecordingResult {
|
|
|
233
256
|
RecordingFileID?: string;
|
|
234
257
|
}
|
|
235
258
|
|
|
236
|
-
/** A
|
|
259
|
+
/** A person's choice of whether agents may see their camera and shared screen in a room. */
|
|
260
|
+
@InputType()
|
|
261
|
+
export class SetLiveKitAgentVisionInput {
|
|
262
|
+
@Field(() => String)
|
|
263
|
+
RoomName: string;
|
|
264
|
+
|
|
265
|
+
/** `true` to let agents see, `false` to stop. */
|
|
266
|
+
@Field(() => Boolean)
|
|
267
|
+
Allow: boolean;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
@ObjectType()
|
|
271
|
+
export class LiveKitAgentVisionResult {
|
|
272
|
+
@Field(() => Boolean)
|
|
273
|
+
Success: boolean;
|
|
274
|
+
|
|
275
|
+
@Field(() => String, { nullable: true })
|
|
276
|
+
ErrorMessage?: string;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* A selectable provider-native voice for the dev voice picker: one per persona, or one per voice only the driver declares.
|
|
281
|
+
* Two personas can share an `ID` (a voice, and the same voice with a face); `PersonaID` tells them apart.
|
|
282
|
+
*/
|
|
237
283
|
@ObjectType()
|
|
238
284
|
export class RealtimeVoiceOptionResult {
|
|
239
285
|
@Field(() => String)
|
|
@@ -241,6 +287,22 @@ export class RealtimeVoiceOptionResult {
|
|
|
241
287
|
|
|
242
288
|
@Field(() => String)
|
|
243
289
|
Name: string;
|
|
290
|
+
|
|
291
|
+
/** The persona this voice belongs to (`MJ: AI Personas.ID`). Null for a voice only the driver declares. */
|
|
292
|
+
@Field(() => String, { nullable: true })
|
|
293
|
+
PersonaID?: string;
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* The avatar that comes with this voice: the `APIName` of its persona's preset Video binding on the model's vendor,
|
|
297
|
+
* which is what `realtime.video.avatarId` takes. Null for a voice without one, and for every voice only the driver
|
|
298
|
+
* declares.
|
|
299
|
+
*/
|
|
300
|
+
@Field(() => String, { nullable: true })
|
|
301
|
+
AvatarID?: string;
|
|
302
|
+
|
|
303
|
+
/** The persona's preview image URL, or null when it has none. */
|
|
304
|
+
@Field(() => String, { nullable: true })
|
|
305
|
+
PreviewImageURL?: string;
|
|
244
306
|
}
|
|
245
307
|
|
|
246
308
|
/** An active Realtime model with the voices its driver supports — feeds the dev model/voice picker. */
|
|
@@ -300,7 +362,9 @@ export class RealtimeBridgeResolver extends ResolverBase {
|
|
|
300
362
|
|
|
301
363
|
/**
|
|
302
364
|
* Starts (or reuses) an agent's presence in a LiveKit room and returns a client token so the calling
|
|
303
|
-
* user can immediately join the same room.
|
|
365
|
+
* user can immediately join the same room. The token is minted before anything starts, so a start that can't give the
|
|
366
|
+
* user one fails with nothing started. When no `AgentSessionID` is passed, an agent session is created for the
|
|
367
|
+
* agent; if the agent then fails to start, that session is closed (`Error`) before the failure is returned.
|
|
304
368
|
*/
|
|
305
369
|
@Mutation(() => LiveKitAgentRoomSessionResult)
|
|
306
370
|
async StartLiveKitAgentRoomSession(
|
|
@@ -331,18 +395,22 @@ export class RealtimeBridgeResolver extends ResolverBase {
|
|
|
331
395
|
}
|
|
332
396
|
}
|
|
333
397
|
|
|
398
|
+
// The user's token first: a start that can't let the user into the room fails before anything starts there. Minted
|
|
399
|
+
// after the agent joined, a failure left the agent in a room the user couldn't enter and gave the UI no bridge id to
|
|
400
|
+
// stop it by.
|
|
401
|
+
const clientToken = await new LiveKitTokenService().MintClientToken(roomName, this.participantIdentity(user), user.Name ?? user.Email);
|
|
402
|
+
|
|
334
403
|
// Opt-in: an agent that can bring a person, a number or another agent into this room (the same room, so a visitor
|
|
335
404
|
// is escalated without leaving it). Falls through to the standard start when the server cannot do handoffs.
|
|
336
405
|
const handoffSessionBridgeID = await this.startWithHandoff(input, roomName, user, provider);
|
|
337
406
|
if (handoffSessionBridgeID) {
|
|
338
|
-
const handoffToken = await new LiveKitTokenService().MintClientToken(roomName, this.participantIdentity(user), user.Name ?? user.Email);
|
|
339
407
|
return {
|
|
340
408
|
Success: true,
|
|
341
409
|
SessionBridgeID: handoffSessionBridgeID,
|
|
342
410
|
RoomName: roomName,
|
|
343
|
-
ServerUrl:
|
|
344
|
-
ClientToken:
|
|
345
|
-
Identity:
|
|
411
|
+
ServerUrl: clientToken.ServerUrl,
|
|
412
|
+
ClientToken: clientToken.Token,
|
|
413
|
+
Identity: clientToken.Identity,
|
|
346
414
|
};
|
|
347
415
|
}
|
|
348
416
|
|
|
@@ -351,6 +419,10 @@ export class RealtimeBridgeResolver extends ResolverBase {
|
|
|
351
419
|
// freshly-created one. Previously this minted a bare random UUID with no backing row, so the
|
|
352
420
|
// bridge INSERT failed the FK_AIAgentSessionBridge_Session constraint.
|
|
353
421
|
let agentSessionID = input.AgentSessionID?.trim();
|
|
422
|
+
// A session created here exists for this agent's time in the room alone, so it closes when the agent leaves, however
|
|
423
|
+
// it leaves, or at once if the agent fails to start (see startAgentInRoom). A session the caller supplied is the
|
|
424
|
+
// caller's to close.
|
|
425
|
+
let createdSessionID: string | undefined;
|
|
354
426
|
if (!agentSessionID) {
|
|
355
427
|
if (!input.AgentID?.trim()) {
|
|
356
428
|
return failure('An AgentID is required to start an agent room session.', roomName);
|
|
@@ -361,9 +433,10 @@ export class RealtimeBridgeResolver extends ResolverBase {
|
|
|
361
433
|
provider,
|
|
362
434
|
);
|
|
363
435
|
agentSessionID = createdSession.ID;
|
|
436
|
+
createdSessionID = createdSession.ID;
|
|
364
437
|
}
|
|
365
438
|
|
|
366
|
-
const session = await
|
|
439
|
+
const session = await this.startAgentInRoom(createdSessionID, user, provider, {
|
|
367
440
|
AgentSessionID: agentSessionID,
|
|
368
441
|
RoomName: roomName,
|
|
369
442
|
AgentID: input.AgentID,
|
|
@@ -377,9 +450,6 @@ export class RealtimeBridgeResolver extends ResolverBase {
|
|
|
377
450
|
MetadataProvider: provider,
|
|
378
451
|
});
|
|
379
452
|
|
|
380
|
-
const tokenService = new LiveKitTokenService();
|
|
381
|
-
const clientToken = await tokenService.MintClientToken(roomName, this.participantIdentity(user), user.Name ?? user.Email);
|
|
382
|
-
|
|
383
453
|
return {
|
|
384
454
|
Success: true,
|
|
385
455
|
SessionBridgeID: session.SessionBridgeID,
|
|
@@ -399,6 +469,7 @@ export class RealtimeBridgeResolver extends ResolverBase {
|
|
|
399
469
|
* Stops one agent's presence in a room (the bot leaves) — the remove half of in-room agent management.
|
|
400
470
|
* Identified by the `SessionBridgeID` returned from {@link StartLiveKitAgentRoomSession}. Returns `true`
|
|
401
471
|
* when the bridge was stopped. Best-effort: a missing/already-stopped bridge or any error resolves `false`.
|
|
472
|
+
* The agent session the start created for the agent is closed (`Explicit`) before this returns.
|
|
402
473
|
*
|
|
403
474
|
* @param sessionBridgeID The `MJ: AI Agent Session Bridges` row id of the agent to remove.
|
|
404
475
|
*/
|
|
@@ -433,6 +504,7 @@ export class RealtimeBridgeResolver extends ResolverBase {
|
|
|
433
504
|
* coordinator's server-side roster). This is the "End meeting" half of the Zoom-style leave control —
|
|
434
505
|
* usable by any participant, including one who only *joined* the room and never tracked the bridge ids.
|
|
435
506
|
* Returns `true` when the teardown ran (even if the room held zero agents). Best-effort: any error → `false`.
|
|
507
|
+
* The agent sessions the starts created for the agents are closed (`Explicit`) as each agent leaves.
|
|
436
508
|
*
|
|
437
509
|
* @param roomName The LiveKit room to end.
|
|
438
510
|
*/
|
|
@@ -672,6 +744,46 @@ export class RealtimeBridgeResolver extends ResolverBase {
|
|
|
672
744
|
}
|
|
673
745
|
}
|
|
674
746
|
|
|
747
|
+
/**
|
|
748
|
+
* Records whether the current user lets agents see their camera and shared screen in a room. The participant is
|
|
749
|
+
* worked out from the authenticated user, never sent by the client, so a person can only answer for themselves. To
|
|
750
|
+
* allow, the room must be one they may enter ({@link RoomAuthorizationService}, as for every room mutation). A
|
|
751
|
+
* withdrawal skips that check: a cancelled meeting or a failed lookup must not keep an agent watching someone who is
|
|
752
|
+
* still in the room, and the identity is always the caller's own. LiveKit refuses either way when they are not in it. The choice is set as their `mj.agentCanSee` attribute through LiveKit's server SDK (a
|
|
753
|
+
* participant's token can't change its own attributes) and audited, applied or not.
|
|
754
|
+
*/
|
|
755
|
+
@Mutation(() => LiveKitAgentVisionResult)
|
|
756
|
+
async SetLiveKitAgentVision(
|
|
757
|
+
@Arg('input', () => SetLiveKitAgentVisionInput) input: SetLiveKitAgentVisionInput,
|
|
758
|
+
@Ctx() context: AppContext = {} as AppContext,
|
|
759
|
+
): Promise<LiveKitAgentVisionResult> {
|
|
760
|
+
try {
|
|
761
|
+
const user = this.GetUserFromPayload(context.userPayload);
|
|
762
|
+
if (!user) {
|
|
763
|
+
return { Success: false, ErrorMessage: 'Unable to determine current user.' };
|
|
764
|
+
}
|
|
765
|
+
const provider = GetReadWriteProvider(context.providers) as unknown as IMetadataProvider;
|
|
766
|
+
const auth: RoomAuthorizationResult = input.Allow
|
|
767
|
+
? await RoomAuthorizationService.Instance.AuthorizeRoomAccess(input.RoomName, user, provider)
|
|
768
|
+
: { Authorized: true };
|
|
769
|
+
const result: ParticipantUpdateResult = auth.Authorized
|
|
770
|
+
? await new LiveKitParticipantService().SetAgentVision(input.RoomName, this.participantIdentity(user), input.Allow)
|
|
771
|
+
: { Success: false, ErrorMessage: auth.Reason ?? 'Unauthorized room access.' };
|
|
772
|
+
await WriteAgentVisionConsentAudit(
|
|
773
|
+
{ User: user, RoomName: input.RoomName, Allow: input.Allow, Applied: result.Success, ErrorMessage: result.ErrorMessage },
|
|
774
|
+
provider,
|
|
775
|
+
);
|
|
776
|
+
if (result.Success) {
|
|
777
|
+
return { Success: true };
|
|
778
|
+
}
|
|
779
|
+
return { Success: false, ErrorMessage: result.NotInRoom ? 'You are not in this room.' : result.ErrorMessage };
|
|
780
|
+
} catch (error) {
|
|
781
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
782
|
+
LogError(`SetLiveKitAgentVision failed: ${msg}`);
|
|
783
|
+
return { Success: false, ErrorMessage: msg };
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
675
787
|
/**
|
|
676
788
|
* Starts the agent through the handoff-capable room starter when the caller asked for it and the server can do it.
|
|
677
789
|
* Returns the bridge id, or `undefined` to mean "use the standard start" (not requested, no starter, no agent named).
|
|
@@ -704,6 +816,46 @@ export class RealtimeBridgeResolver extends ResolverBase {
|
|
|
704
816
|
return started.SessionBridgeID;
|
|
705
817
|
}
|
|
706
818
|
|
|
819
|
+
/**
|
|
820
|
+
* Starts the agent in the room through the coordinator. An agent session created for this agent's time in the room
|
|
821
|
+
* (`createdSessionID`) is this start's to close: once the agent has joined, through the end-of-session hook from
|
|
822
|
+
* {@link closeSessionWhenAgentLeaves}; when the start fails, at once, as `Error`, through
|
|
823
|
+
* {@link SessionManager.CloseSessionForFailedStart}, before the error propagates, since the agent never joined and that
|
|
824
|
+
* hook never runs (#5308). By then the coordinator has closed any model session the start opened, its co-agent run
|
|
825
|
+
* finalized as failed. A session the caller supplied gets neither: it is the caller's.
|
|
826
|
+
*/
|
|
827
|
+
private async startAgentInRoom(
|
|
828
|
+
createdSessionID: string | undefined,
|
|
829
|
+
user: UserInfo,
|
|
830
|
+
provider: IMetadataProvider,
|
|
831
|
+
params: Omit<StartAgentRoomSessionParams, 'Host'>,
|
|
832
|
+
): Promise<AgentRoomSession> {
|
|
833
|
+
const coordinator = LiveKitAgentRoomCoordinator.Instance;
|
|
834
|
+
if (!createdSessionID) {
|
|
835
|
+
return coordinator.StartAgentRoomSession(params);
|
|
836
|
+
}
|
|
837
|
+
try {
|
|
838
|
+
return await coordinator.StartAgentRoomSession({ ...params, Host: this.closeSessionWhenAgentLeaves(createdSessionID, user, provider) });
|
|
839
|
+
} catch (error) {
|
|
840
|
+
await this.sessionManager.CloseSessionForFailedStart(createdSessionID, user, provider);
|
|
841
|
+
throw error;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
/**
|
|
846
|
+
* What the coordinator is given for an agent session created for one agent's time in a room: its end-of-session hook
|
|
847
|
+
* closes the session once the agent's bridge has ended, whatever ended it (the agent stopped, the meeting ended, everyone
|
|
848
|
+
* left, the model session lost), through {@link SessionManager.CloseSessionForEndedBridge}. The close runs as the user
|
|
849
|
+
* who started the agent, whoever stops it: the session is theirs.
|
|
850
|
+
*/
|
|
851
|
+
private closeSessionWhenAgentLeaves(agentSessionID: string, user: UserInfo, provider: IMetadataProvider): AgentRoomHostOptions {
|
|
852
|
+
return {
|
|
853
|
+
OnSessionEnded: async (reason) => {
|
|
854
|
+
await this.sessionManager.CloseSessionForEndedBridge(agentSessionID, reason, user, provider);
|
|
855
|
+
},
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
|
|
707
859
|
/** Builds a stable, lowercased participant identity from the authenticated user (shared with the handoff engine, which watches for it). */
|
|
708
860
|
private participantIdentity(user: UserInfo): string {
|
|
709
861
|
return LiveKitUserIdentity(user.ID);
|