@memberjunction/server 6.2.0-edge.5 → 6.2.0-edge.7
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 +96 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/BridgeHostInstance.d.ts +8 -3
- package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -1
- package/dist/agentSessions/BridgeHostInstance.js +14 -4
- package/dist/agentSessions/BridgeHostInstance.js.map +1 -1
- package/dist/agentSessions/HandoffOfferExpiry.d.ts +10 -0
- package/dist/agentSessions/HandoffOfferExpiry.d.ts.map +1 -0
- package/dist/agentSessions/HandoffOfferExpiry.js +18 -0
- package/dist/agentSessions/HandoffOfferExpiry.js.map +1 -0
- package/dist/agentSessions/ReturningVisitorRecap.js +1 -0
- package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
- package/dist/agentSessions/SessionJanitor.d.ts +34 -11
- package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
- package/dist/agentSessions/SessionJanitor.js +88 -44
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/agentSessions/SessionManager.d.ts +29 -9
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +62 -16
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/agentSessions/conversationBrowsers.d.ts +61 -0
- package/dist/agentSessions/conversationBrowsers.d.ts.map +1 -0
- package/dist/agentSessions/conversationBrowsers.js +118 -0
- package/dist/agentSessions/conversationBrowsers.js.map +1 -0
- package/dist/agentSessions/sessionDeadline.d.ts +43 -0
- package/dist/agentSessions/sessionDeadline.d.ts.map +1 -0
- package/dist/agentSessions/sessionDeadline.js +68 -0
- package/dist/agentSessions/sessionDeadline.js.map +1 -0
- package/dist/auth/APIKeyScopeAuth.d.ts.map +1 -1
- package/dist/auth/APIKeyScopeAuth.js +5 -4
- package/dist/auth/APIKeyScopeAuth.js.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.js +2 -0
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +51 -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/loginEmailResolution.d.ts +41 -0
- package/dist/auth/loginEmailResolution.d.ts.map +1 -0
- package/dist/auth/loginEmailResolution.js +47 -0
- package/dist/auth/loginEmailResolution.js.map +1 -0
- package/dist/auth/magicLink/MagicLinkKeys.d.ts +51 -3
- package/dist/auth/magicLink/MagicLinkKeys.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkKeys.js +130 -13
- package/dist/auth/magicLink/MagicLinkKeys.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.d.ts +3 -0
- package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +23 -5
- package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.d.ts +39 -5
- package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +221 -9
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/magicLink/index.d.ts +1 -1
- package/dist/auth/magicLink/index.d.ts.map +1 -1
- package/dist/auth/magicLink/index.js +1 -1
- package/dist/auth/magicLink/index.js.map +1 -1
- package/dist/auth/magicLink/redeemLanding.d.ts +2 -2
- package/dist/auth/magicLink/redeemLanding.d.ts.map +1 -1
- package/dist/auth/magicLink/redeemLanding.js +7 -4
- package/dist/auth/magicLink/redeemLanding.js.map +1 -1
- package/dist/auth/magicLink/types.d.ts +39 -3
- package/dist/auth/magicLink/types.d.ts.map +1 -1
- package/dist/auth/magicLink/types.js +0 -4
- package/dist/auth/magicLink/types.js.map +1 -1
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +1 -0
- package/dist/auth/newUsers.js.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/backgroundSweepConfigUnits.d.ts +231 -0
- package/dist/backgroundSweepConfigUnits.d.ts.map +1 -0
- package/dist/backgroundSweepConfigUnits.js +180 -0
- package/dist/backgroundSweepConfigUnits.js.map +1 -0
- 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 +1402 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +120 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +5 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +64 -12
- package/dist/context.js.map +1 -1
- package/dist/coreRoutes.d.ts +3 -1
- package/dist/coreRoutes.d.ts.map +1 -1
- package/dist/coreRoutes.js +20 -4
- package/dist/coreRoutes.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts +863 -14
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +4167 -62
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +50 -30
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +154 -79
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts +11 -0
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js +29 -1
- 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 +93 -11
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +114 -29
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +509 -220
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +15 -3
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +126 -20
- 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/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +262 -84
- package/dist/index.js.map +1 -1
- package/dist/integration/ConnectionPause.d.ts +121 -0
- package/dist/integration/ConnectionPause.d.ts.map +1 -0
- package/dist/integration/ConnectionPause.js +183 -0
- package/dist/integration/ConnectionPause.js.map +1 -0
- package/dist/integration/CustomColumnPromoter.d.ts +72 -6
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +93 -47
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/integration/EntityMapLifecycle.d.ts +78 -4
- package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
- package/dist/integration/EntityMapLifecycle.js +199 -5
- package/dist/integration/EntityMapLifecycle.js.map +1 -1
- package/dist/integration/InactiveRowWarnings.d.ts +31 -0
- package/dist/integration/InactiveRowWarnings.d.ts.map +1 -1
- package/dist/integration/InactiveRowWarnings.js +29 -0
- package/dist/integration/InactiveRowWarnings.js.map +1 -1
- package/dist/integration/ObjectNamesByID.d.ts +28 -0
- package/dist/integration/ObjectNamesByID.d.ts.map +1 -0
- package/dist/integration/ObjectNamesByID.js +87 -0
- package/dist/integration/ObjectNamesByID.js.map +1 -0
- package/dist/integration/PostRestartIntrospect.d.ts +26 -0
- package/dist/integration/PostRestartIntrospect.d.ts.map +1 -0
- package/dist/integration/PostRestartIntrospect.js +27 -0
- package/dist/integration/PostRestartIntrospect.js.map +1 -0
- package/dist/integration/RSUPostRestartProgress.d.ts +176 -0
- package/dist/integration/RSUPostRestartProgress.d.ts.map +1 -0
- package/dist/integration/RSUPostRestartProgress.js +323 -0
- package/dist/integration/RSUPostRestartProgress.js.map +1 -0
- package/dist/integration/RSUProgressBridge.d.ts +41 -2
- package/dist/integration/RSUProgressBridge.d.ts.map +1 -1
- package/dist/integration/RSUProgressBridge.js +84 -1
- package/dist/integration/RSUProgressBridge.js.map +1 -1
- package/dist/integration/RunArtifactAuthorization.d.ts +39 -0
- package/dist/integration/RunArtifactAuthorization.d.ts.map +1 -0
- package/dist/integration/RunArtifactAuthorization.js +45 -0
- package/dist/integration/RunArtifactAuthorization.js.map +1 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts +9 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts.map +1 -1
- package/dist/integration/SchemaRefreshLaunch.js +3 -2
- package/dist/integration/SchemaRefreshLaunch.js.map +1 -1
- package/dist/integration/ScopedFieldsForBuild.d.ts +46 -0
- package/dist/integration/ScopedFieldsForBuild.d.ts.map +1 -0
- package/dist/integration/ScopedFieldsForBuild.js +91 -0
- package/dist/integration/ScopedFieldsForBuild.js.map +1 -0
- package/dist/integration/TargetConfigGuard.d.ts +40 -0
- package/dist/integration/TargetConfigGuard.d.ts.map +1 -0
- package/dist/integration/TargetConfigGuard.js +40 -0
- package/dist/integration/TargetConfigGuard.js.map +1 -0
- 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/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/ownedRealtimeSession.d.ts +8 -6
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -1
- package/dist/realtimeSessions/ownedRealtimeSession.js +14 -6
- package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -1
- package/dist/realtimeSessions/sessionAccess.d.ts +103 -11
- package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
- package/dist/realtimeSessions/sessionAccess.js +147 -22
- 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 +203 -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/visitorIdentity.d.ts.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.js +1 -0
- package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
- package/dist/realtimeWidget/widgetCore.d.ts +20 -1
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetCore.js +21 -8
- 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 +3 -1
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/requestOrigin.d.ts +22 -0
- package/dist/requestOrigin.d.ts.map +1 -0
- package/dist/requestOrigin.js +60 -0
- package/dist/requestOrigin.js.map +1 -0
- 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 +44 -17
- package/dist/resolvers/AgentSessionResolver.js.map +1 -1
- package/dist/resolvers/AutotagPipelineResolver.d.ts.map +1 -1
- package/dist/resolvers/AutotagPipelineResolver.js +2 -1
- package/dist/resolvers/AutotagPipelineResolver.js.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.js +2 -0
- package/dist/resolvers/ConversationRunEventsResolver.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/ExecuteRemoteOperationResolver.d.ts +6 -0
- package/dist/resolvers/ExecuteRemoteOperationResolver.d.ts.map +1 -1
- package/dist/resolvers/ExecuteRemoteOperationResolver.js +30 -7
- package/dist/resolvers/ExecuteRemoteOperationResolver.js.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts +28 -0
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js +117 -21
- 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 +5 -0
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +13 -4
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +34 -13
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +401 -11
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +2713 -1290
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts.map +1 -1
- package/dist/resolvers/MCPResolver.js +13 -2
- package/dist/resolvers/MCPResolver.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.map +1 -1
- package/dist/resolvers/QueryResolver.js +20 -6
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +38 -0
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +184 -88
- 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/RealtimeBridgeResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +1 -0
- package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +22 -2
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +118 -33
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts +62 -10
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +224 -39
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +80 -16
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +388 -125
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts +5 -3
- package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +19 -18
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +7 -5
- 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/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +4 -0
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.js +1 -0
- package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts +17 -2
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +60 -15
- 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/meetingRecordingRegistration.d.ts.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.js +2 -0
- package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
- 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/MediaAccessKeys.d.ts.map +1 -1
- package/dist/rest/MediaAccessKeys.js +6 -2
- package/dist/rest/MediaAccessKeys.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
- package/dist/rest/OAuthCallbackHandler.js +11 -5
- package/dist/rest/OAuthCallbackHandler.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 +3 -3
- package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -1
- package/dist/rest/RealtimeRecordingHandler.js +6 -8
- package/dist/rest/RealtimeRecordingHandler.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +6 -0
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +24 -6
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +3 -1
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +11 -2
- package/dist/rest/setupRESTEndpoints.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/DurableEntityActionTaskSubmitter.d.ts.map +1 -1
- package/dist/services/DurableEntityActionTaskSubmitter.js +6 -1
- package/dist/services/DurableEntityActionTaskSubmitter.js.map +1 -1
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphActionRunner.js +2 -26
- package/dist/services/TaskGraphActionRunner.js.map +1 -1
- package/dist/services/TaskGraphAgentRunner.d.ts +6 -0
- package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphAgentRunner.js +38 -0
- package/dist/services/TaskGraphAgentRunner.js.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.d.ts +5 -0
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +43 -15
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/services/WorkQueueHostService.d.ts +2 -1
- package/dist/services/WorkQueueHostService.d.ts.map +1 -1
- package/dist/services/WorkQueueHostService.js +19 -4
- package/dist/services/WorkQueueHostService.js.map +1 -1
- package/dist/services/workQueueConfig.d.ts +2 -2
- package/dist/services/workQueueConfig.js +5 -5
- package/dist/services/workQueueConfig.js.map +1 -1
- package/dist/sharedCache.js +1 -1
- package/dist/sharedCache.js.map +1 -1
- package/dist/types.d.ts +40 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +98 -98
- package/src/__tests__/APIKeyScopeAuth.test.ts +4 -8
- package/src/__tests__/ActionResolver.fieldSecurity.test.ts +237 -0
- package/src/__tests__/ActiveOperations.test.ts +68 -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 +150 -0
- package/src/__tests__/AssertTargetConfigs.test.ts +75 -0
- package/src/__tests__/BatchApplyParity.test.ts +109 -0
- package/src/__tests__/BridgeHostInstance.test.ts +42 -0
- package/src/__tests__/CollectInactiveRowWarnings.test.ts +115 -0
- package/src/__tests__/ConnectionPause.test.ts +192 -0
- package/src/__tests__/ConnectionPauseResolver.test.ts +166 -0
- package/src/__tests__/ConnectionPauseSave.test.ts +143 -0
- package/src/__tests__/CustomColumnPromoterCompletion.test.ts +142 -0
- package/src/__tests__/CustomColumnPromoterOnePass.test.ts +15 -1
- package/src/__tests__/DeleteConnectionRemovesPerConnectionCatalog.test.ts +51 -0
- package/src/__tests__/DetachedDiscoveryStart.test.ts +65 -0
- package/src/__tests__/DurableEntityActionTaskSubmitter.test.ts +73 -0
- package/src/__tests__/EntityCommunicationsResolver.actingUser.test.ts +151 -0
- package/src/__tests__/EntityMapLifecycle.rekey.test.ts +252 -0
- package/src/__tests__/EvolutionActsOnWhatItDetects.test.ts +113 -0
- package/src/__tests__/ExecuteRemoteOperationResolver.test.ts +213 -0
- package/src/__tests__/FetchEntityVectorsResolver.test.ts +206 -3
- package/src/__tests__/FileResolver.fieldSecurity.test.ts +82 -0
- package/src/__tests__/HandoffOfferExpiry.test.ts +40 -0
- package/src/__tests__/IntegrationRunArtifactAuthorization.test.ts +126 -0
- package/src/__tests__/MagicLinkKeys.test.ts +102 -0
- package/src/__tests__/MediaAccessKeys.test.ts +57 -10
- package/src/__tests__/NewArrivalsDefaultDisabled.test.ts +50 -0
- package/src/__tests__/ObjectNamesByID.test.ts +176 -0
- package/src/__tests__/PipelineProgressResolver.filter.test.ts +58 -0
- package/src/__tests__/PostRestartMapsInCatalogScope.test.ts +146 -0
- package/src/__tests__/QuerySystemUserResolver.childRows.test.ts +80 -0
- package/src/__tests__/QuerySystemUserResolver.collision.test.ts +200 -0
- package/src/__tests__/QuerySystemUserResolver.fieldSecurity.test.ts +49 -0
- package/src/__tests__/QuerySystemUserResolver.permissions.test.ts +132 -0
- package/src/__tests__/RESTEndpointHandler.test.ts +25 -0
- package/src/__tests__/RSUPostRestartProgress.test.ts +343 -0
- package/src/__tests__/RSUProgressBridge.test.ts +188 -5
- package/src/__tests__/RSUStartupSweepWiring.test.ts +30 -0
- package/src/__tests__/ReactivateRefreshMessage.test.ts +10 -3
- package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +23 -3
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +346 -46
- package/src/__tests__/{RefreshAdoptsNewColumns.test.ts → RefreshReportsNewColumns.test.ts} +25 -16
- package/src/__tests__/RemoteBrowserActionRecovery.test.ts +287 -0
- package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +3 -0
- package/src/__tests__/RemoteBrowserActionResolver.ownership.test.ts +100 -0
- package/src/__tests__/RemoteBrowserAudioStream.test.ts +3 -0
- package/src/__tests__/RemoteBrowserSnapshot.test.ts +3 -0
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +344 -14
- package/src/__tests__/ResolverBase.deleteReturnProjection.test.ts +52 -0
- package/src/__tests__/ResolverBase.encryptedApiZeroReencrypt.test.ts +307 -0
- package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +227 -0
- package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +83 -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 +72 -13
- package/src/__tests__/RunAIAgentResolver.consultPredecessor.test.ts +289 -0
- package/src/__tests__/RunAIAgentResolver.conversationWriter.test.ts +210 -0
- package/src/__tests__/RunAIAgentResolver.fireAndForgetCompletion.test.ts +209 -0
- package/src/__tests__/RunAIAgentResolver.handoff.test.ts +649 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +19 -27
- package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +10 -2
- package/src/__tests__/RunAIAgentResolver.serverReply.test.ts +358 -0
- package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +91 -13
- package/src/__tests__/RunTemplateResolver.test.ts +35 -2
- package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +11 -0
- package/src/__tests__/SchemaEvolutionCustomColumns.test.ts +119 -0
- package/src/__tests__/SchemaRefreshLaunch.test.ts +24 -2
- package/src/__tests__/ScopedFieldsForBuild.test.ts +192 -0
- package/src/__tests__/SessionJanitor.test.ts +195 -4
- package/src/__tests__/SessionManager.test.ts +164 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +2 -2
- package/src/__tests__/TaskGraphAgentRunner.test.ts +272 -16
- package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +114 -3
- package/src/__tests__/TransactionGroupResolver.fieldSecurity.test.ts +199 -0
- package/src/__tests__/UserViewResolver.updateWhereClause.test.ts +15 -0
- package/src/__tests__/ViewOperationsHandler.test.ts +9 -7
- package/src/__tests__/WidgetSessionService.test.ts +583 -4
- package/src/__tests__/WorkQueueHostService.test.ts +25 -7
- package/src/__tests__/apiRootBoot.test.ts +1 -1
- package/src/__tests__/backgroundSweepConfigUnits.test.ts +153 -0
- package/src/__tests__/buildMagicLinkSessionUser.test.ts +96 -0
- package/src/__tests__/cacheBroadcastProviders.test.ts +403 -0
- package/src/__tests__/cacheInvalidationRecordData.test.ts +45 -0
- package/src/__tests__/contextRequestOrigin.test.ts +105 -0
- package/src/__tests__/conversationBrowsers.test.ts +62 -0
- package/src/__tests__/fieldSecurityFixtures.ts +91 -0
- package/src/__tests__/globalCors.test.ts +3 -3
- package/src/__tests__/localDevAuth.test.ts +196 -0
- package/src/__tests__/magicLinkExtensionCapabilities.test.ts +413 -0
- package/src/__tests__/orphanedConversationDetailReconciler.start.test.ts +82 -0
- package/src/__tests__/orphanedConversationDetailReconciler.test.ts +10 -0
- package/src/__tests__/ownedRealtimeSession.test.ts +14 -0
- package/src/__tests__/pushStatusResolver.filter.test.ts +57 -1
- package/src/__tests__/realtimeRecordingHandler.test.ts +24 -2
- 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 +224 -7
- package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +1 -1
- package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +25 -4
- package/src/__tests__/requestOrigin.test.ts +104 -0
- 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__/securityHardeningPr6034.test.ts +120 -0
- package/src/__tests__/sessionDeadline.test.ts +51 -0
- package/src/__tests__/sessionUserClone.test.ts +5 -1
- package/src/__tests__/sharedCache.test.ts +11 -0
- package/src/__tests__/startupSweepOrder.test.ts +40 -0
- package/src/__tests__/unifiedAuth.test.ts +101 -1
- package/src/__tests__/widgetGuestElevation.test.ts +2 -0
- package/src/agentSessions/BridgeHostInstance.ts +20 -5
- package/src/agentSessions/HandoffOfferExpiry.ts +18 -0
- package/src/agentSessions/ReturningVisitorRecap.ts +1 -0
- package/src/agentSessions/SessionJanitor.ts +95 -45
- package/src/agentSessions/SessionManager.ts +73 -20
- package/src/agentSessions/conversationBrowsers.ts +143 -0
- package/src/agentSessions/sessionDeadline.ts +81 -0
- package/src/auth/APIKeyScopeAuth.ts +5 -4
- package/src/auth/AuthProviderCatalogRouter.ts +3 -0
- package/src/auth/__tests__/loginEmailResolution.test.ts +67 -0
- package/src/auth/index.ts +56 -12
- package/src/auth/initializeProviders.ts +43 -1
- package/src/auth/localDevAuth.ts +528 -0
- package/src/auth/loginEmailResolution.ts +67 -0
- package/src/auth/magicLink/MagicLinkKeys.ts +147 -15
- package/src/auth/magicLink/MagicLinkRouter.ts +33 -6
- package/src/auth/magicLink/MagicLinkService.ts +250 -10
- package/src/auth/magicLink/index.ts +1 -1
- package/src/auth/magicLink/redeemLanding.ts +7 -4
- package/src/auth/magicLink/types.ts +38 -3
- package/src/auth/newUsers.ts +1 -0
- package/src/auth/sessionUserClone.ts +3 -2
- package/src/backgroundSweepConfigUnits.ts +213 -0
- 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 +138 -0
- package/src/context.ts +71 -14
- package/src/coreRoutes.ts +29 -7
- package/src/generated/graphql-schemas/__mj.ts +4145 -1193
- package/src/generic/CacheInvalidationResolver.ts +135 -78
- package/src/generic/OrphanedConversationDetailReconciler.ts +36 -3
- package/src/generic/PubSubManager.ts +54 -1
- package/src/generic/PushStatusResolver.ts +108 -11
- package/src/generic/ResolverBase.ts +635 -234
- package/src/generic/RunViewResolver.ts +176 -64
- package/src/generic/actionOutputFieldSecurity.ts +75 -0
- package/src/generic/fieldSecurityTransport.ts +62 -0
- package/src/index.ts +310 -85
- package/src/integration/ConnectionPause.ts +222 -0
- package/src/integration/CustomColumnPromoter.ts +129 -54
- package/src/integration/EntityMapLifecycle.ts +229 -6
- package/src/integration/InactiveRowWarnings.ts +50 -0
- package/src/integration/ObjectNamesByID.ts +97 -0
- package/src/integration/PostRestartIntrospect.ts +49 -0
- package/src/integration/RSUPostRestartProgress.ts +359 -0
- package/src/integration/RSUProgressBridge.ts +85 -2
- package/src/integration/RunArtifactAuthorization.ts +65 -0
- package/src/integration/SchemaRefreshLaunch.ts +12 -2
- package/src/integration/ScopedFieldsForBuild.ts +113 -0
- package/src/integration/TargetConfigGuard.ts +71 -0
- package/src/logging/variablesLoggingMiddleware.ts +59 -3
- package/src/realtimeSessions/README.md +7 -3
- package/src/realtimeSessions/SessionVerificationPortsBase.ts +1 -0
- package/src/realtimeSessions/ownedRealtimeSession.ts +16 -6
- package/src/realtimeSessions/sessionAccess.ts +211 -25
- 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 +254 -17
- package/src/realtimeWidget/host-identity.ts +1 -1
- package/src/realtimeWidget/visitorIdentity.ts +1 -0
- package/src/realtimeWidget/widgetCore.ts +34 -9
- package/src/realtimeWidget/widgetGuestElevation.ts +3 -1
- package/src/requestOrigin.ts +64 -0
- 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 +50 -18
- package/src/resolvers/AutotagPipelineResolver.ts +2 -1
- package/src/resolvers/ConversationRunEventsResolver.ts +2 -0
- package/src/resolvers/EntityCommunicationsResolver.ts +56 -15
- package/src/resolvers/ExecuteRemoteOperationResolver.ts +41 -9
- package/src/resolvers/FetchEntityVectorsResolver.ts +132 -21
- package/src/resolvers/FileCategoryResolver.ts +1 -0
- package/src/resolvers/FileResolver.ts +14 -4
- package/src/resolvers/GetDataResolver.ts +35 -13
- package/src/resolvers/IntegrationDiscoveryResolver.ts +1570 -209
- package/src/resolvers/MCPResolver.ts +15 -2
- package/src/resolvers/MergeRecordsResolver.ts +23 -2
- package/src/resolvers/PipelineProgressResolver.ts +12 -3
- package/src/resolvers/QueryResolver.ts +20 -6
- package/src/resolvers/QuerySystemUserResolver.ts +207 -99
- package/src/resolvers/RSUResolver.ts +12 -0
- package/src/resolvers/RealtimeBridgeResolver.ts +1 -0
- package/src/resolvers/RealtimeClientSessionResolver.ts +144 -40
- package/src/resolvers/RemoteBrowserActionResolver.ts +252 -37
- package/src/resolvers/RunAIAgentResolver.ts +518 -163
- package/src/resolvers/RunAIPromptResolver.ts +18 -18
- package/src/resolvers/RunTemplateResolver.ts +9 -5
- package/src/resolvers/RunTestResolver.ts +3 -1
- package/src/resolvers/SyncDataResolver.ts +4 -0
- package/src/resolvers/TestQuerySQLResolver.ts +1 -0
- package/src/resolvers/TransactionGroupResolver.ts +66 -15
- package/src/resolvers/UserViewResolver.ts +2 -1
- package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +52 -0
- package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +43 -0
- package/src/resolvers/meetingRecordingRegistration.ts +2 -0
- package/src/rest/EntityCRUDHandler.ts +22 -5
- package/src/rest/MediaAccessKeys.ts +6 -2
- package/src/rest/OAuthCallbackHandler.ts +13 -5
- package/src/rest/RESTEndpointHandler.ts +8 -5
- package/src/rest/RealtimeRecordingHandler.ts +9 -10
- package/src/rest/ViewOperationsHandler.ts +26 -7
- package/src/rest/setupRESTEndpoints.ts +11 -2
- package/src/serverRoleConfigUnits.ts +48 -0
- package/src/services/DurableEntityActionTaskSubmitter.ts +10 -2
- package/src/services/TaskGraphActionRunner.ts +2 -23
- package/src/services/TaskGraphAgentRunner.ts +43 -0
- package/src/services/TaskGraphContinuationDeliverer.ts +53 -20
- package/src/services/WorkQueueHostService.ts +26 -4
- package/src/services/workQueueConfig.ts +5 -5
- package/src/sharedCache.ts +1 -1
- package/src/types.ts +41 -1
- package/src/services/TaskOrchestration-Integration.md +0 -188
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { HandoffOfferRegistry } from '@memberjunction/livekit-room-server';
|
|
2
|
+
import type { HandoffOfferSweepSettings } from '../backgroundSweepConfigUnits.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Applies `agentSessions.handoffOfferExpiry` to the process-wide handoff offer registry. The registry
|
|
6
|
+
* starts its expiry sweep (a read of `MJ: Interaction Offers` every 15 seconds) as soon as it loads, on
|
|
7
|
+
* every MJAPI whatever its role; this either stops that sweep, so an idle server sends no periodic
|
|
8
|
+
* query for it, or restarts it on the configured interval. Overdue offers still read as expired when
|
|
9
|
+
* the sweep is off. See the Serverless Database Auto-Pause guide.
|
|
10
|
+
*/
|
|
11
|
+
export function ApplyHandoffOfferExpirySettings(settings: HandoffOfferSweepSettings): void {
|
|
12
|
+
const registry = HandoffOfferRegistry.Instance;
|
|
13
|
+
if (settings.enabled) {
|
|
14
|
+
registry.StartPeriodicSweep(settings.sweepIntervalMs);
|
|
15
|
+
} else {
|
|
16
|
+
registry.StopPeriodicSweep();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -146,6 +146,7 @@ async function recapAlreadyExists(conversationId: string, contextUser: UserInfo)
|
|
|
146
146
|
ExtraFilter: `SourceConversationID = '${conversationId}' AND IsAutoGenerated = 1 AND Type = 'Context'`,
|
|
147
147
|
Fields: ['ID'],
|
|
148
148
|
MaxRows: 1,
|
|
149
|
+
SkipTotalRowCount: true,
|
|
149
150
|
ResultType: 'simple',
|
|
150
151
|
},
|
|
151
152
|
contextUser,
|
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
} from '@memberjunction/ai-agents';
|
|
20
20
|
import { GetCurrentHostInstance, GetHostInstanceID, HostInstanceIdentity } from './HostInstance.js';
|
|
21
21
|
import { SessionManager, SessionCloseReason } from './SessionManager.js';
|
|
22
|
+
import type { SessionJanitorSettings } from '../backgroundSweepConfigUnits.js';
|
|
23
|
+
import { ExpiryCloseReason, ExpiryReason } from './sessionDeadline.js';
|
|
22
24
|
|
|
23
25
|
/** Entity name for session rows (kept in sync with {@link SessionManager}). */
|
|
24
26
|
const SESSION_ENTITY = 'MJ: AI Agent Sessions';
|
|
@@ -195,6 +197,24 @@ interface RecoveryVisit {
|
|
|
195
197
|
Recovered: boolean;
|
|
196
198
|
}
|
|
197
199
|
|
|
200
|
+
/**
|
|
201
|
+
* The close reason for a row the staleness sweep's SQL already judged stale (`LastActiveAt < cutoff`).
|
|
202
|
+
* {@link ExpiryCloseReason} returns null for such a row only when `LastActiveAt` will not parse (or the
|
|
203
|
+
* threshold is non-finite); skipping it would leave it `Active` forever, so it closes as `'Idle'` and the
|
|
204
|
+
* fallback is logged with the session ID.
|
|
205
|
+
*/
|
|
206
|
+
function staleRowCloseReason(session: MJAIAgentSessionEntity, nowMs: number, thresholdMs: number): ExpiryReason {
|
|
207
|
+
const reason = ExpiryCloseReason(session, nowMs, thresholdMs);
|
|
208
|
+
if (reason !== null) {
|
|
209
|
+
return reason;
|
|
210
|
+
}
|
|
211
|
+
LogError(
|
|
212
|
+
`[SessionJanitor] Staleness sweep: session ${session.ID} has LastActiveAt ${String(session.LastActiveAt)}; ` +
|
|
213
|
+
'LastActiveAt unparseable; closing as Idle',
|
|
214
|
+
);
|
|
215
|
+
return 'Idle';
|
|
216
|
+
}
|
|
217
|
+
|
|
198
218
|
/**
|
|
199
219
|
* `BaseSingleton` background reconciler that keeps the durable `AIAgentSession` state from drifting
|
|
200
220
|
* away from volatile process reality. A crash/redeploy vaporizes a host's in-memory sockets but
|
|
@@ -212,9 +232,12 @@ interface RecoveryVisit {
|
|
|
212
232
|
* `closeThresholdMinutes`, regardless of host. Catches sessions whose owner died without a clean
|
|
213
233
|
* reboot (OOM, scaled-down pod).
|
|
214
234
|
* 3. **Max-duration sweep ({@link RunMaxDurationSweep})** — run on every periodic tick after the
|
|
215
|
-
* staleness sweep. Closes any session past its stored hard deadline (the public voice cost cap)
|
|
235
|
+
* staleness sweep. Closes any session past its stored hard deadline (the public voice cost cap), and
|
|
236
|
+
* any deadline-carrying session whose idle moment has passed; it stamps that row `'Idle'` when the idle
|
|
237
|
+
* moment came before the deadline.
|
|
216
238
|
*
|
|
217
|
-
*
|
|
239
|
+
* Startup recovery stamps `CloseReason = 'Janitor'`; the staleness and max-duration sweeps stamp `'Idle'` or
|
|
240
|
+
* `'TimeLimit'`, whichever expiry moment passed first ({@link ExpiryCloseReason}). A shutdown-time path — {@link RunShutdownDrain},
|
|
218
241
|
* invoked from {@link Shutdown} during the graceful ShutdownRegistry drain — closes this exact host
|
|
219
242
|
* instance's own live sessions with `CloseReason = 'Shutdown'`.
|
|
220
243
|
*
|
|
@@ -318,6 +341,39 @@ export class SessionJanitor extends BaseSingleton<SessionJanitor> implements ISh
|
|
|
318
341
|
this.scheduleSweep();
|
|
319
342
|
}
|
|
320
343
|
|
|
344
|
+
/**
|
|
345
|
+
* Starts the janitor the way the host's `agentSessions.janitor` settings ask: applies the interval
|
|
346
|
+
* and close threshold, then {@link Start} when enabled, or {@link StartRecoveryOnly} when not.
|
|
347
|
+
* Throws (before doing any work) on an invalid interval or threshold; see {@link Configure}.
|
|
348
|
+
*/
|
|
349
|
+
public async StartWithSettings(settings: SessionJanitorSettings, provider: DatabaseProviderBase, systemUser: UserInfo): Promise<void> {
|
|
350
|
+
this.Configure({ sweepIntervalMs: settings.sweepIntervalMs, closeThresholdMinutes: settings.closeThresholdMinutes });
|
|
351
|
+
if (settings.enabled) {
|
|
352
|
+
await this.Start(provider, systemUser);
|
|
353
|
+
} else {
|
|
354
|
+
await this.StartRecoveryOnly(provider, systemUser);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* {@link Start} without the periodic tick, for hosts that turned the janitor off: run own-host
|
|
360
|
+
* startup recovery once and register for the graceful-shutdown drain, but schedule nothing, so an
|
|
361
|
+
* idle process issues no periodic queries. Stale-session, max-duration and recording-recovery
|
|
362
|
+
* sweeps then do not run in this process. Stops a tick an earlier {@link Start} scheduled.
|
|
363
|
+
*/
|
|
364
|
+
public async StartRecoveryOnly(provider: DatabaseProviderBase, systemUser: UserInfo): Promise<void> {
|
|
365
|
+
this.Stop();
|
|
366
|
+
this._provider = provider;
|
|
367
|
+
this._systemUser = systemUser;
|
|
368
|
+
this.ensureRegistered();
|
|
369
|
+
await this.RunStartupRecovery(provider, systemUser);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** Whether the periodic tick is currently scheduled (diagnostics and tests). */
|
|
373
|
+
public get IsSweepScheduled(): boolean {
|
|
374
|
+
return this._sweepTimer !== null;
|
|
375
|
+
}
|
|
376
|
+
|
|
321
377
|
/**
|
|
322
378
|
* Stops the periodic tick and keeps any new recording recovery pass from starting until the next
|
|
323
379
|
* {@link Start}, including one a tick already in progress would have started. A pass that is already
|
|
@@ -335,7 +391,7 @@ export class SessionJanitor extends BaseSingleton<SessionJanitor> implements ISh
|
|
|
335
391
|
* {@link IShutdownable}: stop the timer, then drain this host's own live sessions so a
|
|
336
392
|
* graceful stop never strands `Active`/`Idle` rows for the next boot's janitor to mop up, then wait
|
|
337
393
|
* (at most {@link RECOVERY_SHUTDOWN_WAIT_MS}) for an in-flight recording recovery pass.
|
|
338
|
-
* Drained sessions are stamped `CloseReason = 'Shutdown'` (vs. `'Janitor'` for crash orphans),
|
|
394
|
+
* Drained sessions are stamped `CloseReason = 'Shutdown'` (vs. `'Janitor'` for crash orphans from an earlier boot),
|
|
339
395
|
* so the dashboards can tell a clean redeploy from a reconciled crash. Never throws; the drain
|
|
340
396
|
* is skipped when {@link Start} was never called (no captured provider/user).
|
|
341
397
|
*/
|
|
@@ -360,7 +416,7 @@ export class SessionJanitor extends BaseSingleton<SessionJanitor> implements ISh
|
|
|
360
416
|
public async RunShutdownDrain(provider: IMetadataProvider, systemUser: UserInfo): Promise<number> {
|
|
361
417
|
const current = GetHostInstanceID().replace(/'/g, "''");
|
|
362
418
|
const filter = `Status IN ('Active','Idle') AND HostInstanceID = '${current}'`;
|
|
363
|
-
const closed = await this.sweepAndClose(filter, provider, systemUser, 'Shutdown');
|
|
419
|
+
const closed = await this.sweepAndClose(filter, provider, systemUser, () => 'Shutdown');
|
|
364
420
|
if (closed > 0) {
|
|
365
421
|
LogStatus(`[SessionJanitor] Shutdown drain closed ${closed} live session(s) owned by this host instance`);
|
|
366
422
|
}
|
|
@@ -389,8 +445,9 @@ export class SessionJanitor extends BaseSingleton<SessionJanitor> implements ISh
|
|
|
389
445
|
`AND HostInstanceID LIKE '${prefix}%' ` +
|
|
390
446
|
`AND HostInstanceID <> '${current}'`;
|
|
391
447
|
// The LIKE narrows the read; the exact check decides, since LIKE reads a `_` in a host name as any character.
|
|
392
|
-
const
|
|
393
|
-
|
|
448
|
+
const reasonFor = (session: MJAIAgentSessionEntity): SessionCloseReason | null =>
|
|
449
|
+
hostInstance.IsPriorBoot(session.HostInstanceID) ? 'Janitor' : null;
|
|
450
|
+
const closed = await this.sweepAndClose(filter, provider, systemUser, reasonFor);
|
|
394
451
|
if (closed > 0) {
|
|
395
452
|
LogStatus(
|
|
396
453
|
`[SessionJanitor] Startup recovery closed ${closed} orphaned session(s) from an earlier boot of this instance ` +
|
|
@@ -402,12 +459,18 @@ export class SessionJanitor extends BaseSingleton<SessionJanitor> implements ISh
|
|
|
402
459
|
|
|
403
460
|
/**
|
|
404
461
|
* Force-close any `Active`/`Idle` session whose `LastActiveAt` is older than the configured
|
|
405
|
-
* close threshold, regardless of host.
|
|
462
|
+
* close threshold, regardless of host. Stamped `'Idle'`, or `'TimeLimit'` when the row's authored deadline
|
|
463
|
+
* passed before its idle moment ({@link ExpiryCloseReason}). A row the SQL judged stale is never skipped:
|
|
464
|
+
* when its `LastActiveAt` will not parse it closes as `'Idle'` with a `LogError` ({@link staleRowCloseReason}).
|
|
465
|
+
* Idempotent and concurrency-safe. Returns the count closed.
|
|
406
466
|
*/
|
|
407
467
|
public async RunStalenessSweep(provider: IMetadataProvider, systemUser: UserInfo): Promise<number> {
|
|
408
|
-
|
|
468
|
+
// One clock read feeds both the SQL cutoff and the per-row decision, so they cannot disagree.
|
|
469
|
+
const nowMs = Date.now();
|
|
470
|
+
const thresholdMs = this._config.closeThresholdMinutes * 60_000;
|
|
471
|
+
const cutoffIso = new Date(nowMs - thresholdMs).toISOString();
|
|
409
472
|
const filter = `Status IN ('Active','Idle') AND LastActiveAt < '${cutoffIso}'`;
|
|
410
|
-
const closed = await this.sweepAndClose(filter, provider, systemUser,
|
|
473
|
+
const closed = await this.sweepAndClose(filter, provider, systemUser, s => staleRowCloseReason(s, nowMs, thresholdMs));
|
|
411
474
|
if (closed > 0) {
|
|
412
475
|
LogStatus(`[SessionJanitor] Staleness sweep closed ${closed} stale session(s) (>${this._config.closeThresholdMinutes}m idle)`);
|
|
413
476
|
}
|
|
@@ -422,20 +485,18 @@ export class SessionJanitor extends BaseSingleton<SessionJanitor> implements ISh
|
|
|
422
485
|
*
|
|
423
486
|
* Only sessions that CARRY a deadline are loaded (a cheap `Config_ LIKE` pre-filter), then the exact
|
|
424
487
|
* ISO deadline is parsed and compared in JS (`Config_` is JSON, not a queryable column). Stamped
|
|
425
|
-
* `
|
|
488
|
+
* `'TimeLimit'`, or `'Idle'` when the row's idle moment passed before its deadline ({@link ExpiryCloseReason});
|
|
489
|
+
* idempotent + concurrency-safe like the other sweeps. Returns the count closed.
|
|
426
490
|
*/
|
|
427
491
|
public async RunMaxDurationSweep(provider: IMetadataProvider, systemUser: UserInfo): Promise<number> {
|
|
428
492
|
const nowMs = Date.now();
|
|
429
493
|
// Only consider sessions that carry a deadline marker — keeps this sweep cheap (it never touches
|
|
430
494
|
// the far-more-common uncapped sessions) while the JS check below enforces the exact deadline.
|
|
431
495
|
const filter = `Status IN ('Active','Idle') AND Config LIKE '%maxSessionDeadlineIso%'`;
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
return deadlineMs != null && deadlineMs <= nowMs;
|
|
435
|
-
};
|
|
436
|
-
const closed = await this.sweepAndClose(filter, provider, systemUser, 'Janitor', isExpired);
|
|
496
|
+
const thresholdMs = this._config.closeThresholdMinutes * 60_000;
|
|
497
|
+
const closed = await this.sweepAndClose(filter, provider, systemUser, s => ExpiryCloseReason(s, nowMs, thresholdMs));
|
|
437
498
|
if (closed > 0) {
|
|
438
|
-
LogStatus(`[SessionJanitor] Max-duration sweep closed ${closed} session(s) past their
|
|
499
|
+
LogStatus(`[SessionJanitor] Max-duration sweep closed ${closed} capped session(s) past their deadline or idle threshold`);
|
|
439
500
|
}
|
|
440
501
|
return closed;
|
|
441
502
|
}
|
|
@@ -647,9 +708,9 @@ export class SessionJanitor extends BaseSingleton<SessionJanitor> implements ISh
|
|
|
647
708
|
|
|
648
709
|
/**
|
|
649
710
|
* Gives a status-less session with ledger shards back a `Pending` status so it can be claimed (the
|
|
650
|
-
* claim only takes Pending/Partial/stale Assembling).
|
|
651
|
-
* the
|
|
652
|
-
*
|
|
711
|
+
* claim only takes Pending/Partial/stale Assembling). That is how statuses were lost before #6010
|
|
712
|
+
* made the ledger columns not updatable through an entity save (a stale `Save` of the session, e.g. its
|
|
713
|
+
* close, put back the NULL status and counts). The restore stays for rows hit before then.
|
|
653
714
|
*
|
|
654
715
|
* The terminal proc is the existing way to set a NULL status to `Pending`. It is stamped with the
|
|
655
716
|
* counts the session still stores, or 0 for a NULL count (the proc accepts any count over NULL), and
|
|
@@ -705,23 +766,6 @@ export class SessionJanitor extends BaseSingleton<SessionJanitor> implements ISh
|
|
|
705
766
|
}
|
|
706
767
|
}
|
|
707
768
|
|
|
708
|
-
/** Parses the absolute deadline (ms) from a session's `Config_` JSON, or null when absent/malformed. */
|
|
709
|
-
private parseSessionDeadlineMs(configJson: string | null | undefined): number | null {
|
|
710
|
-
if (!configJson) {
|
|
711
|
-
return null;
|
|
712
|
-
}
|
|
713
|
-
try {
|
|
714
|
-
const parsed = JSON.parse(configJson) as { maxSessionDeadlineIso?: string };
|
|
715
|
-
if (typeof parsed.maxSessionDeadlineIso !== 'string') {
|
|
716
|
-
return null;
|
|
717
|
-
}
|
|
718
|
-
const ms = Date.parse(parsed.maxSessionDeadlineIso);
|
|
719
|
-
return Number.isNaN(ms) ? null : ms;
|
|
720
|
-
} catch {
|
|
721
|
-
return null;
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
|
|
725
769
|
// ----- internals -------------------------------------------------------------------------
|
|
726
770
|
|
|
727
771
|
/** Register for graceful shutdown exactly once. */
|
|
@@ -993,7 +1037,9 @@ export class SessionJanitor extends BaseSingleton<SessionJanitor> implements ISh
|
|
|
993
1037
|
|
|
994
1038
|
/**
|
|
995
1039
|
* Page through every session matching `filter` with keyset (`AfterKey`) pagination and close each
|
|
996
|
-
* via {@link SessionManager.CloseSession}, stamping `
|
|
1040
|
+
* via {@link SessionManager.CloseSession}, stamping the reason `reasonFor` returns for that row.
|
|
1041
|
+
* A `null` reason skips the row (the SQL filter only narrows; `reasonFor` decides), and skipped rows
|
|
1042
|
+
* are dropped before the channel batch load so it covers only rows that will close.
|
|
997
1043
|
* Returns the number successfully closed. A `Closed`-by-now row (raced by another instance) is a
|
|
998
1044
|
* harmless no-op that keeps its original reason.
|
|
999
1045
|
*/
|
|
@@ -1001,30 +1047,34 @@ export class SessionJanitor extends BaseSingleton<SessionJanitor> implements ISh
|
|
|
1001
1047
|
filter: string,
|
|
1002
1048
|
provider: IMetadataProvider,
|
|
1003
1049
|
systemUser: UserInfo,
|
|
1004
|
-
|
|
1005
|
-
shouldClose?: (session: MJAIAgentSessionEntity) => boolean,
|
|
1050
|
+
reasonFor: (session: MJAIAgentSessionEntity) => SessionCloseReason | null,
|
|
1006
1051
|
): Promise<number> {
|
|
1007
1052
|
let closedCount = 0;
|
|
1008
1053
|
await this.forEachSessionPage(filter, provider, systemUser, async fetched => {
|
|
1009
|
-
|
|
1010
|
-
const
|
|
1011
|
-
|
|
1054
|
+
const toClose: Array<{ session: MJAIAgentSessionEntity; reason: SessionCloseReason }> = [];
|
|
1055
|
+
for (const session of fetched) {
|
|
1056
|
+
const reason = reasonFor(session);
|
|
1057
|
+
if (reason !== null) {
|
|
1058
|
+
toClose.push({ session, reason });
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
if (toClose.length === 0) {
|
|
1012
1062
|
return;
|
|
1013
1063
|
}
|
|
1014
1064
|
// Batch-load every channel for this whole page of sessions in ONE query, then hand each
|
|
1015
1065
|
// session its own slice to CloseSession — avoids the N+1 channel read (one RunView per
|
|
1016
1066
|
// closing session) that tripped the sequential / multiple-same-entity telemetry.
|
|
1017
1067
|
const channelsBySession = await this.sessionManager.LoadActiveChannelsBySession(
|
|
1018
|
-
|
|
1068
|
+
toClose.map(c => c.session.ID),
|
|
1019
1069
|
systemUser,
|
|
1020
1070
|
provider,
|
|
1021
1071
|
);
|
|
1022
|
-
for (const session of
|
|
1072
|
+
for (const { session, reason } of toClose) {
|
|
1023
1073
|
const closed = await this.sessionManager.CloseSession(
|
|
1024
1074
|
session.ID,
|
|
1025
1075
|
systemUser,
|
|
1026
1076
|
provider,
|
|
1027
|
-
|
|
1077
|
+
reason,
|
|
1028
1078
|
channelsBySession.get(session.ID.toLowerCase()) ?? [],
|
|
1029
1079
|
);
|
|
1030
1080
|
if (closed) {
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
import { IMetadataProvider, UserInfo, LogError, RunView } from '@memberjunction/core';
|
|
1
|
+
import { IMetadataProvider, UserInfo, LogError, LogStatus, RunView } from '@memberjunction/core';
|
|
2
2
|
import { MJLruCache } from '@memberjunction/global';
|
|
3
3
|
import {
|
|
4
4
|
MJAIAgentSessionEntity,
|
|
5
5
|
MJAIAgentSessionChannelEntity,
|
|
6
6
|
MJConversationEntity,
|
|
7
7
|
} from '@memberjunction/core-entities';
|
|
8
|
+
import { RunWithTrustedSessionConfigWrites } from '@memberjunction/core-entities-server';
|
|
8
9
|
import { AIAgentPermissionHelper } from '@memberjunction/ai-engine-base';
|
|
9
10
|
import { RealtimeClientSessionService, RealtimeChannelServerHost } from '@memberjunction/ai-agents';
|
|
10
11
|
import type { BridgeDisconnectReason } from '@memberjunction/ai-bridge-base';
|
|
12
|
+
import { ParseSessionDeadlineMs, VerifyTimeLimitClaim } from './sessionDeadline.js';
|
|
11
13
|
import { GetHostInstanceID } from './HostInstance.js';
|
|
12
14
|
import { WriteReturningVisitorRecap } from './ReturningVisitorRecap.js';
|
|
13
15
|
import { SessionRunIDVerifier, SessionRunIDs } from './SessionRunIDVerifier.js';
|
|
14
16
|
import { ResolveScopedAnonymousRunUser } from '../realtimeWidget/widgetGuestElevation.js';
|
|
15
17
|
import { RecordingAssemblyScheduler } from '../realtimeSessions/RecordingAssemblyScheduler.js';
|
|
18
|
+
import { ResolveSessionScopeIdentity } from '../realtimeSessions/sessionAccess.js';
|
|
16
19
|
|
|
17
20
|
/** Entity names — centralised so the `MJ:`-prefix convention is applied in exactly one place. */
|
|
18
21
|
const SESSION_ENTITY = 'MJ: AI Agent Sessions';
|
|
@@ -39,11 +42,14 @@ export interface CreateSessionInput {
|
|
|
39
42
|
/**
|
|
40
43
|
* Why a session was closed — persisted to `AIAgentSession.CloseReason` alongside the
|
|
41
44
|
* `Status = 'Closed'` transition so the admin dashboards can distinguish a user hanging up
|
|
42
|
-
* (`Explicit`) from janitor reconciliation (`Janitor
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
+
* (`Explicit`) from janitor reconciliation (`Janitor`, an orphan from an earlier boot), a graceful
|
|
46
|
+
* host drain (`Shutdown`), a failure-path teardown (`Error`), an expired authored deadline
|
|
47
|
+
* (`TimeLimit`) or a session left quiet past the idle threshold (`Idle`). `NULL` in the column means
|
|
48
|
+
* "legacy/unknown" — rows closed before this column existed.
|
|
49
|
+
*
|
|
50
|
+
* Derived from the generated entity so the column's CHECK constraint stays the single source of truth.
|
|
45
51
|
*/
|
|
46
|
-
export type SessionCloseReason = '
|
|
52
|
+
export type SessionCloseReason = NonNullable<MJAIAgentSessionEntity['CloseReason']>;
|
|
47
53
|
|
|
48
54
|
/**
|
|
49
55
|
* The {@link SessionCloseReason} for a session whose bridged agent has left (see
|
|
@@ -153,11 +159,13 @@ export class SessionManager {
|
|
|
153
159
|
/**
|
|
154
160
|
* Authorize and create a new session. Flow:
|
|
155
161
|
* 1. `CanRun` check on the agent — denied → {@link SessionAuthorizationError}, no row written.
|
|
156
|
-
* 2. Resolve the conversation (use the supplied one, or create+link a fresh Conversation).
|
|
162
|
+
* 2. Resolve the conversation (use the supplied one, or create+link a fresh Conversation). An anonymous
|
|
163
|
+
* caller may only supply a conversation stamped with its own scope identity.
|
|
157
164
|
* 3. Persist the `AIAgentSession` as `Active`, stamped with this host and `LastActiveAt = now`.
|
|
158
165
|
*
|
|
159
166
|
* @returns the saved {@link MJAIAgentSessionEntity}.
|
|
160
|
-
* @throws {SessionAuthorizationError} when the user may not run the agent
|
|
167
|
+
* @throws {SessionAuthorizationError} when the user may not run the agent, or an anonymous caller supplies a
|
|
168
|
+
* conversation that is not its own.
|
|
161
169
|
* @throws {Error} when conversation creation or session save fails.
|
|
162
170
|
*/
|
|
163
171
|
public async CreateSession(
|
|
@@ -166,6 +174,9 @@ export class SessionManager {
|
|
|
166
174
|
provider: IMetadataProvider,
|
|
167
175
|
): Promise<MJAIAgentSessionEntity> {
|
|
168
176
|
await this.assertCanRun(input.agentID, contextUser);
|
|
177
|
+
if (input.conversationID && contextUser.IsMagicLinkAnonymous) {
|
|
178
|
+
await this.assertAnonymousOwnsConversation(input.conversationID, contextUser, provider);
|
|
179
|
+
}
|
|
169
180
|
|
|
170
181
|
const conversationID = input.conversationID
|
|
171
182
|
?? await this.createConversation(input, contextUser, provider);
|
|
@@ -185,6 +196,8 @@ export class SessionManager {
|
|
|
185
196
|
* call sites (the user-initiated close mutations) stamp the common case without modification;
|
|
186
197
|
* background callers (janitor sweeps, shutdown drain, error teardowns) must pass their reason
|
|
187
198
|
* explicitly. `NULL` rows remain only for legacy data closed before the column existed.
|
|
199
|
+
* A `'TimeLimit'` is verified against the session's stored deadline ({@link VerifyTimeLimitClaim}); a claim the
|
|
200
|
+
* deadline does not back is recorded as `'Explicit'` and logged, never refused.
|
|
188
201
|
*
|
|
189
202
|
* @remarks P5 adds in-flight-run abort + `ClientToolRequestManager.ClearSession` here.
|
|
190
203
|
*/
|
|
@@ -209,7 +222,9 @@ export class SessionManager {
|
|
|
209
222
|
return true;
|
|
210
223
|
}
|
|
211
224
|
|
|
212
|
-
|
|
225
|
+
// Verified once: the stamped reason and the plugin notification must agree, so a client's unbacked claim steers neither.
|
|
226
|
+
const verifiedReason = this.verifiedCloseReason(session, closeReason);
|
|
227
|
+
const closed = await this.markSessionClosed(session, verifiedReason);
|
|
213
228
|
if (!closed) {
|
|
214
229
|
return false;
|
|
215
230
|
}
|
|
@@ -222,7 +237,7 @@ export class SessionManager {
|
|
|
222
237
|
}
|
|
223
238
|
await this.disconnectChannels(agentSessionID, contextUser, provider, preloadedChannels);
|
|
224
239
|
await this.finalizeObservabilityRuns(session, contextUser, provider);
|
|
225
|
-
await this.notifyChannelPluginsSessionClosed(agentSessionID,
|
|
240
|
+
await this.notifyChannelPluginsSessionClosed(agentSessionID, verifiedReason);
|
|
226
241
|
// Returning-visitor recap (RV2): if this session's conversation is returning-visitor-enabled,
|
|
227
242
|
// summarize it into an Active memory note so the visitor's next session opens with prior context.
|
|
228
243
|
// Best-effort + no-op for non-returning-visitor conversations; never blocks teardown.
|
|
@@ -230,6 +245,25 @@ export class SessionManager {
|
|
|
230
245
|
return true;
|
|
231
246
|
}
|
|
232
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Returns the reason to stamp: a `'TimeLimit'` claim the session's stored deadline does not back becomes
|
|
250
|
+
* `'Explicit'` (logged with the stored deadline); every other reason passes through.
|
|
251
|
+
*/
|
|
252
|
+
private verifiedCloseReason(session: MJAIAgentSessionEntity, closeReason: SessionCloseReason): SessionCloseReason {
|
|
253
|
+
if (closeReason !== 'TimeLimit') {
|
|
254
|
+
return closeReason;
|
|
255
|
+
}
|
|
256
|
+
const verified = VerifyTimeLimitClaim(session, Date.now());
|
|
257
|
+
if (verified === 'Explicit') {
|
|
258
|
+
const deadlineMs = ParseSessionDeadlineMs(session.Config_);
|
|
259
|
+
LogStatus(
|
|
260
|
+
`SessionManager.CloseSession: TimeLimit claim for session ${session.ID} not backed by its stored deadline ` +
|
|
261
|
+
`(${deadlineMs === null ? 'none stored' : new Date(deadlineMs).toISOString()}); closing as Explicit.`,
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
return verified;
|
|
265
|
+
}
|
|
266
|
+
|
|
233
267
|
/**
|
|
234
268
|
* Closes a session that was created for one bridged agent (a bot in a meeting room) once that agent's bridge has
|
|
235
269
|
* ended, whatever ended it: the agent was stopped, the meeting was ended, everyone left, the model session was lost.
|
|
@@ -448,6 +482,23 @@ export class SessionManager {
|
|
|
448
482
|
|
|
449
483
|
// ----- internals -------------------------------------------------------------------------
|
|
450
484
|
|
|
485
|
+
/**
|
|
486
|
+
* Throws {@link SessionAuthorizationError} unless the anonymous caller owns the conversation it wants to bind a
|
|
487
|
+
* new session to: the conversation, read as the caller, loads, and its `ExternalID` equals the caller's scope
|
|
488
|
+
* identity ({@link ResolveSessionScopeIdentity}). A caller with no scope identity is refused. Every anonymous
|
|
489
|
+
* visitor shares one Anonymous user, so row-level security alone may let one visitor read another's
|
|
490
|
+
* conversation; without this check the new session row and its relays would point into that conversation.
|
|
491
|
+
*/
|
|
492
|
+
private async assertAnonymousOwnsConversation(conversationID: string, contextUser: UserInfo, provider: IMetadataProvider): Promise<void> {
|
|
493
|
+
const conversation = await provider.GetEntityObject<MJConversationEntity>(CONVERSATION_ENTITY, contextUser);
|
|
494
|
+
const loaded = await conversation.Load(conversationID);
|
|
495
|
+
const scopeIdentity = ResolveSessionScopeIdentity(contextUser);
|
|
496
|
+
if (!loaded || !scopeIdentity || conversation.ExternalID !== scopeIdentity) {
|
|
497
|
+
LogError(`SessionManager.CreateSession: refused anonymous user ${contextUser.ID} binding a session to conversation ${conversationID} (${loaded ? 'not its own' : 'not readable'}).`);
|
|
498
|
+
throw new SessionAuthorizationError('Not authorized to start a session on this conversation.');
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
451
502
|
/** Throws {@link SessionAuthorizationError} unless the user has `CanRun` on the agent. */
|
|
452
503
|
private async assertCanRun(agentID: string, contextUser: UserInfo): Promise<void> {
|
|
453
504
|
const canRun = await AIAgentPermissionHelper.HasPermission(agentID, contextUser, 'run');
|
|
@@ -468,13 +519,13 @@ export class SessionManager {
|
|
|
468
519
|
conversation.NewRecord();
|
|
469
520
|
conversation.UserID = input.userID;
|
|
470
521
|
conversation.Name = 'Agent Session';
|
|
471
|
-
//
|
|
472
|
-
//
|
|
473
|
-
//
|
|
474
|
-
//
|
|
475
|
-
|
|
476
|
-
if (
|
|
477
|
-
conversation.ExternalID =
|
|
522
|
+
// Stamp the scope identity AuthorizeSessionAccess compares against (one rule, one place:
|
|
523
|
+
// ResolveSessionScopeIdentity) — the token's resource scope when it has one, else an anonymous
|
|
524
|
+
// visitor's mj_sid. This isolates anonymous visitors that share the Anonymous UserID, and keeps
|
|
525
|
+
// the {{ScopeResourceID}} RLS filters matching the visitor's own rows. No-op for unscoped named principals.
|
|
526
|
+
const scopeIdentity = ResolveSessionScopeIdentity(contextUser);
|
|
527
|
+
if (scopeIdentity) {
|
|
528
|
+
conversation.ExternalID = scopeIdentity;
|
|
478
529
|
}
|
|
479
530
|
|
|
480
531
|
// Returning-visitor memory (RV1/RV2/RV4) for the VOICE path: the widget guest token carries the
|
|
@@ -539,9 +590,9 @@ export class SessionManager {
|
|
|
539
590
|
}
|
|
540
591
|
|
|
541
592
|
/**
|
|
542
|
-
* Loads a session entity by ID, returning null when it cannot be loaded. The
|
|
543
|
-
*
|
|
544
|
-
*
|
|
593
|
+
* Loads a session entity by ID, returning null when it cannot be loaded. The lifecycle saves that
|
|
594
|
+
* follow cannot write back the recording ledger's columns: those have `AllowUpdateAPI=0`, so they are
|
|
595
|
+
* not parameters of `spUpdateAIAgentSession` (#5294, #6010).
|
|
545
596
|
*/
|
|
546
597
|
private async loadSession(
|
|
547
598
|
agentSessionID: string,
|
|
@@ -561,7 +612,9 @@ export class SessionManager {
|
|
|
561
612
|
session.Status = 'Closed';
|
|
562
613
|
session.ClosedAt = new Date();
|
|
563
614
|
session.CloseReason = closeReason;
|
|
564
|
-
|
|
615
|
+
// The session entity refuses a server-only CloseReason from an untrusted save; this is the server's own
|
|
616
|
+
// (already verified) close, so it saves inside the trusted session-write scope.
|
|
617
|
+
return RunWithTrustedSessionConfigWrites(() => this.saveOrLog(session, 'CloseSession'));
|
|
565
618
|
}
|
|
566
619
|
|
|
567
620
|
/** Marks every channel row of the session `Disconnected` (with `DisconnectedAt`), if not already. */
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The remote browsers this process holds for TEXT conversations: who owns each and when it
|
|
3
|
+
* was last used. Backs the caps (`realtime.conversationBrowser.maxPerUser` and `maxAnonymousTotal`) and ends browsers
|
|
4
|
+
* nobody uses any more, since a reloaded or closed tab never ends its own
|
|
5
|
+
* (`realtime.conversationBrowser.idleMinutes`). Realtime calls' browsers are not tracked here: they end
|
|
6
|
+
* with their session.
|
|
7
|
+
*
|
|
8
|
+
* @module @memberjunction/server/agentSessions
|
|
9
|
+
*/
|
|
10
|
+
import { GraphQLError } from 'graphql';
|
|
11
|
+
import { LogError, LogStatus } from '@memberjunction/core';
|
|
12
|
+
import { BaseSingleton, IShutdownable, ShutdownRegistry } from '@memberjunction/global';
|
|
13
|
+
import { RemoteBrowserEngine } from '@memberjunction/remote-browser-server';
|
|
14
|
+
import type { ConversationBrowserConfig } from '../config.js';
|
|
15
|
+
|
|
16
|
+
/** How often idle conversation browsers are looked for. */
|
|
17
|
+
const REAP_INTERVAL_MS = 60_000;
|
|
18
|
+
|
|
19
|
+
/** The `extensions.code` of a {@link RemoteBrowserRefusedError}, which a client reads to stop asking. */
|
|
20
|
+
export const REMOTE_BROWSER_REFUSED = 'REMOTE_BROWSER_REFUSED';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A remote-browser request this server refuses however often it is asked: browsers not enabled, a session
|
|
24
|
+
* that is not the caller's or does not exist, or a cap reached.
|
|
25
|
+
*/
|
|
26
|
+
export class RemoteBrowserRefusedError extends GraphQLError {
|
|
27
|
+
constructor(message: string) {
|
|
28
|
+
super(message, { extensions: { code: REMOTE_BROWSER_REFUSED } });
|
|
29
|
+
this.name = 'RemoteBrowserRefusedError';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Who a conversation browser counts against: a user, or an anonymous guest's own scope. */
|
|
34
|
+
export interface ConversationBrowserOwner {
|
|
35
|
+
Key: string;
|
|
36
|
+
Anonymous: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface HeldBrowser {
|
|
40
|
+
Owner: ConversationBrowserOwner;
|
|
41
|
+
LastUsedAt: number;
|
|
42
|
+
IdleMs: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class ConversationBrowserLedger extends BaseSingleton<ConversationBrowserLedger> implements IShutdownable {
|
|
46
|
+
public readonly ShutdownName = 'ConversationBrowserLedger';
|
|
47
|
+
private readonly held = new Map<string, HeldBrowser>();
|
|
48
|
+
private reapTimer: ReturnType<typeof setInterval> | null = null;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* How an idle browser is ended. The resolver points this at its own end path, so a reaped browser
|
|
52
|
+
* leaves no stream bookkeeping behind; until then the engine ends it directly.
|
|
53
|
+
*/
|
|
54
|
+
public EndBrowser: (conversationID: string) => Promise<unknown> = (conversationID) =>
|
|
55
|
+
RemoteBrowserEngine.Instance.EndSessionForAgentSession(conversationID);
|
|
56
|
+
|
|
57
|
+
protected constructor() {
|
|
58
|
+
super();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public static get Instance(): ConversationBrowserLedger {
|
|
62
|
+
return super.getInstance<ConversationBrowserLedger>();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Records that a conversation's browser is about to be used. A conversation the ledger does not hold
|
|
67
|
+
* yet counts against its owner's cap and, for an anonymous guest, against the cap all guests share: a
|
|
68
|
+
* guest can start a new scope cheaply, so its own cap alone bounds nothing.
|
|
69
|
+
*
|
|
70
|
+
* @throws RemoteBrowserRefusedError when the owner already holds `maxPerUser` conversation browsers, or
|
|
71
|
+
* guests together already hold `maxAnonymousTotal`.
|
|
72
|
+
*/
|
|
73
|
+
public Claim(conversationID: string, owner: ConversationBrowserOwner, limits: Pick<ConversationBrowserConfig, 'maxPerUser' | 'maxAnonymousTotal' | 'idleMinutes'>): void {
|
|
74
|
+
const key = conversationID.toLowerCase();
|
|
75
|
+
if (!this.held.has(key)) {
|
|
76
|
+
const held = Array.from(this.held.values());
|
|
77
|
+
const count = held.filter((b) => b.Owner.Key === owner.Key).length;
|
|
78
|
+
if (count >= limits.maxPerUser) {
|
|
79
|
+
throw new RemoteBrowserRefusedError(`You already have ${count} conversation browser(s) open, the most this server allows. Close one first.`);
|
|
80
|
+
}
|
|
81
|
+
if (owner.Anonymous && held.filter((b) => b.Owner.Anonymous).length >= limits.maxAnonymousTotal) {
|
|
82
|
+
throw new RemoteBrowserRefusedError('Every conversation browser this server allows for guests is in use. Try again later.');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
this.held.set(key, { Owner: owner, LastUsedAt: Date.now(), IdleMs: limits.idleMinutes * 60_000 });
|
|
86
|
+
this.startReaper();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Marks a held browser as used (an action, a snapshot poll, human input), which puts off its idle end. */
|
|
90
|
+
public Touch(conversationID: string): void {
|
|
91
|
+
const browser = this.held.get(conversationID.toLowerCase());
|
|
92
|
+
if (browser) {
|
|
93
|
+
browser.LastUsedAt = Date.now();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Forgets a conversation's browser once it has been ended. */
|
|
98
|
+
public Release(conversationID: string): void {
|
|
99
|
+
this.held.delete(conversationID.toLowerCase());
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Ends every held browser unused for longer than its idle limit. Returns how many were ended. */
|
|
103
|
+
public async ReapIdle(): Promise<number> {
|
|
104
|
+
const now = Date.now();
|
|
105
|
+
const idle = Array.from(this.held).filter(([, b]) => now - b.LastUsedAt > b.IdleMs).map(([id]) => id);
|
|
106
|
+
for (const conversationID of idle) {
|
|
107
|
+
this.held.delete(conversationID);
|
|
108
|
+
try {
|
|
109
|
+
await this.EndBrowser(conversationID);
|
|
110
|
+
} catch (err) {
|
|
111
|
+
LogError(`[ConversationBrowsers] Failed to end the idle browser of conversation ${conversationID}: ${err instanceof Error ? err.message : String(err)}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (idle.length > 0) {
|
|
115
|
+
LogStatus(`[ConversationBrowsers] Ended ${idle.length} idle conversation browser(s).`);
|
|
116
|
+
}
|
|
117
|
+
return idle.length;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Ends every held browser on a graceful shutdown, so none outlives the server. Idempotent. */
|
|
121
|
+
public async Shutdown(): Promise<void> {
|
|
122
|
+
if (this.reapTimer) {
|
|
123
|
+
clearInterval(this.reapTimer);
|
|
124
|
+
this.reapTimer = null;
|
|
125
|
+
}
|
|
126
|
+
const held = Array.from(this.held.keys());
|
|
127
|
+
this.held.clear();
|
|
128
|
+
await Promise.allSettled(held.map((conversationID) => this.EndBrowser(conversationID)));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* One unref'd timer per process, started with the first browser, so the reaper costs nothing until then.
|
|
133
|
+
* The ledger joins the graceful shutdown at the same time.
|
|
134
|
+
*/
|
|
135
|
+
private startReaper(): void {
|
|
136
|
+
if (this.reapTimer) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
this.reapTimer = setInterval(() => void this.ReapIdle(), REAP_INTERVAL_MS);
|
|
140
|
+
this.reapTimer.unref?.();
|
|
141
|
+
ShutdownRegistry.Instance.Register(this);
|
|
142
|
+
}
|
|
143
|
+
}
|