@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
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import { Resolver, Mutation, Query, Arg, Ctx, ObjectType, Field, PubSub, PubSubEngine, Subscription, Root, ResolverFilterData, ID, Int } from 'type-graphql';
|
|
2
2
|
import { AppContext, UserPayload } from '../types.js';
|
|
3
3
|
import { DatabaseProviderBase, LogError, LogStatus, Metadata, RunView, UserInfo, IMetadataProvider } from '@memberjunction/core';
|
|
4
|
-
import { MJConversationDetailEntity, MJConversationDetailAttachmentEntity, MJConversationDetailArtifactEntity, MJArtifactVersionEntity, MJAIAgentRequestEntity, ArtifactMetadataEngine, ConversationEngine } from '@memberjunction/core-entities';
|
|
4
|
+
import { MJConversationDetailEntity, MJConversationDetailEntityExtended, MJConversationDetailAttachmentEntity, MJConversationDetailArtifactEntity, MJArtifactVersionEntity, MJAIAgentRequestEntity, ArtifactMetadataEngine, ConversationEngine } from '@memberjunction/core-entities';
|
|
5
5
|
import { RouteArtifact } from './artifact-routing.js';
|
|
6
|
-
import { AgentRunner, ArtifactToolManager } from '@memberjunction/ai-agents';
|
|
7
|
-
import { MJAIAgentEntityExtended, MJAIAgentRunEntityExtended, ExecuteAgentResult, ConversationUtility, AttachmentData } from '@memberjunction/ai-core-plus';
|
|
6
|
+
import { AgentRunner, ArtifactToolManager, CanAgentOwnSubAgentConsults, LoadOpenSubAgentConsults, HostAllowedAgentIDs } from '@memberjunction/ai-agents';
|
|
7
|
+
import { MJAIAgentEntityExtended, MJAIAgentRunEntityExtended, ExecuteAgentResult, ConversationUtility, AttachmentData, ContinuationAnnouncementText } from '@memberjunction/ai-core-plus';
|
|
8
8
|
import { AIEngine } from '@memberjunction/aiengine';
|
|
9
9
|
import { ChatMessage, ChatMessageContent } from '@memberjunction/ai';
|
|
10
10
|
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
11
11
|
import { AgentRunStatusPublisher } from './AgentRunStatusPublisher.js';
|
|
12
|
+
import { ProjectEntityObjectForCaller } from '../generic/fieldSecurityTransport.js';
|
|
12
13
|
import { StartLivenessPulse } from '../generic/FireAndForgetHeartbeat.js';
|
|
14
|
+
import { StatusUpdateOwnerID } from '../generic/PushStatusResolver.js';
|
|
13
15
|
import { RequireSystemUser } from '../directives/RequireSystemUser.js';
|
|
14
16
|
import { GetReadWriteProvider } from '../util.js';
|
|
15
17
|
import { ResolveWidgetGuestRunContext, ElevateUserPayload } from '../realtimeWidget/widgetGuestElevation.js';
|
|
18
|
+
import { AuthorizeConversationTurn } from '../realtimeSessions/sessionAccess.js';
|
|
16
19
|
import { IsTrustedAgentRunCaller } from './agent-run-data-guard.js';
|
|
17
|
-
import { SafeJSONParse, UUIDsEqual } from '@memberjunction/global';
|
|
20
|
+
import { EscapeSQLString, IsValidUUID, SafeJSONParse, UUIDsEqual } from '@memberjunction/global';
|
|
18
21
|
import { GetAttachmentService } from '@memberjunction/aiengine';
|
|
19
22
|
import { NotificationEngine } from '@memberjunction/notifications';
|
|
20
23
|
|
|
@@ -32,6 +35,17 @@ function isAgentRunEntity(value: unknown): value is MJAIAgentRunEntityExtended {
|
|
|
32
35
|
return typeof value === 'object' && value !== null && 'ID' in value;
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
/** What a conversation turn asks for, before its agent runs (see `RunAIAgentFromConversationDetail`). */
|
|
39
|
+
interface ConversationTurnRequest {
|
|
40
|
+
UserMessageId: string;
|
|
41
|
+
AgentId: string;
|
|
42
|
+
MaxHistoryMessages: number;
|
|
43
|
+
HistoryFrom?: Date;
|
|
44
|
+
ReplyParentId?: string;
|
|
45
|
+
AnnouncedByAgentId?: string;
|
|
46
|
+
ReplyBranchId?: string | null;
|
|
47
|
+
}
|
|
48
|
+
|
|
35
49
|
@ObjectType()
|
|
36
50
|
export class AIAgentRunResult {
|
|
37
51
|
@Field()
|
|
@@ -169,11 +183,18 @@ export class AgentExecutionStreamMessage {
|
|
|
169
183
|
|
|
170
184
|
@Resolver()
|
|
171
185
|
export class RunAIAgentResolver extends ResolverBase {
|
|
186
|
+
/**
|
|
187
|
+
* Tracks `userPayload` instances originating from interactive user mutations (`RunAIAgent` and
|
|
188
|
+
* `RunAIAgentFromConversationDetail` without API key or widget guest elevation) that may expose
|
|
189
|
+
* `Handoff` and follow returned handoff decisions.
|
|
190
|
+
*/
|
|
191
|
+
private readonly handoffEligiblePayloads = new WeakSet<object>();
|
|
192
|
+
|
|
172
193
|
/**
|
|
173
194
|
* Sanitize ExecuteAgentResult for JSON serialization
|
|
174
195
|
* Removes circular references and non-serializable objects
|
|
175
196
|
*/
|
|
176
|
-
private sanitizeAgentResult(result: ExecuteAgentResult): any {
|
|
197
|
+
private sanitizeAgentResult(result: ExecuteAgentResult, recipient?: UserInfo): any {
|
|
177
198
|
const sanitized: any = {
|
|
178
199
|
success: result.success,
|
|
179
200
|
payload: result.payload,
|
|
@@ -184,13 +205,15 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
184
205
|
finalStep: result.agentRun?.FinalStep,
|
|
185
206
|
cancelled: result.agentRun?.Status === 'Cancelled',
|
|
186
207
|
cancellationReason: result.agentRun?.CancellationReason,
|
|
187
|
-
feedbackRequestId: result.feedbackRequestId
|
|
208
|
+
feedbackRequestId: result.feedbackRequestId,
|
|
209
|
+
handoff: result.handoff
|
|
188
210
|
};
|
|
189
211
|
|
|
190
212
|
// Safely extract agent run data using GetAll() for proper serialization
|
|
191
213
|
if (result.agentRun && typeof result.agentRun.GetAll === 'function') {
|
|
192
|
-
//
|
|
193
|
-
|
|
214
|
+
// GetAll() for the full serialized object including extended properties, projected for
|
|
215
|
+
// the recipient: the run comes from the agent engine, not from a load bound to them
|
|
216
|
+
sanitized.agentRun = ProjectEntityObjectForCaller(result.agentRun, recipient);
|
|
194
217
|
}
|
|
195
218
|
else {
|
|
196
219
|
// shouldn't ever get here
|
|
@@ -306,7 +329,12 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
306
329
|
/** ExecuteAgentParams.TrustReservedRunData: true only for a caller IsTrustedAgentRunCaller accepts. */
|
|
307
330
|
trustReservedRunData: boolean = false,
|
|
308
331
|
/** The conversation branch of the run — threaded into ExecuteAgentParams.ConversationBranchID. */
|
|
309
|
-
conversationBranchId?: string | null
|
|
332
|
+
conversationBranchId?: string | null,
|
|
333
|
+
/** The reply row this request created on the server for the run (`conversationDetailId` is its ID). The run
|
|
334
|
+
* writes into this instance, so its writes carry the server-authored marker and the user it was made as. */
|
|
335
|
+
replyDetail?: MJConversationDetailEntityExtended,
|
|
336
|
+
/** Optional explicit handoff override; defaults to whether the caller registered `userPayload` as interactive. */
|
|
337
|
+
followHandoffs?: boolean
|
|
310
338
|
): Promise<AIAgentRunResult> {
|
|
311
339
|
const startTime = Date.now();
|
|
312
340
|
// Best-effort handle for persistInFlightAgentFailure. Populated from a
|
|
@@ -315,6 +343,8 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
315
343
|
// run is not marked Failed — the early-failure case we most want to
|
|
316
344
|
// persist, but we have no run object yet.
|
|
317
345
|
const agentRunRef = runRef ?? { current: null as MJAIAgentRunEntityExtended | null };
|
|
346
|
+
// The publisher owns every status message, including the failure completion the catch below sends.
|
|
347
|
+
const statusPublisher = new AgentRunStatusPublisher(pubSub, userPayload, sessionId, conversationDetailId);
|
|
318
348
|
|
|
319
349
|
try {
|
|
320
350
|
LogStatus(`=== RUNNING AI AGENT FOR ID: ${agentId} ===`);
|
|
@@ -350,24 +380,34 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
350
380
|
|
|
351
381
|
// The publisher owns every status message. The resolver still copies the run into
|
|
352
382
|
// agentRunRef, including noise steps, for the fire-and-forget liveness pulse.
|
|
353
|
-
const
|
|
354
|
-
|
|
383
|
+
const sourcePublisher = statusPublisher;
|
|
384
|
+
let currentPublisher = sourcePublisher;
|
|
385
|
+
|
|
386
|
+
// A widget- or guest-hosted run must not get a handoffChain unless the host also passes an
|
|
387
|
+
// allow-list under trusted run data.
|
|
388
|
+
const effectiveFollowHandoffs = followHandoffs ?? this.handoffEligiblePayloads.has(userPayload);
|
|
389
|
+
const isGuestOrWidgetUser = Boolean(
|
|
390
|
+
currentUser.IsMagicLinkAnonymous || currentUser.WidgetGuestContext
|
|
391
|
+
);
|
|
392
|
+
const allowHandoff = effectiveFollowHandoffs && (
|
|
393
|
+
!isGuestOrWidgetUser
|
|
394
|
+
|| (trustReservedRunData && HostAllowedAgentIDs(parsedData) !== undefined)
|
|
395
|
+
);
|
|
355
396
|
|
|
356
|
-
|
|
357
|
-
const conversationResult = await agentRunner.RunAgentInConversation({
|
|
397
|
+
const sourceParams = {
|
|
358
398
|
agent: agentEntity,
|
|
359
|
-
conversationMessages: parsedMessages,
|
|
399
|
+
conversationMessages: [...parsedMessages],
|
|
360
400
|
payload: payload ? SafeJSONParse(payload) : undefined,
|
|
361
401
|
contextUser: currentUser,
|
|
362
402
|
sessionID: sessionId,
|
|
363
|
-
onProgress: (progress) => {
|
|
403
|
+
onProgress: (progress: Parameters<AgentRunStatusPublisher['OnProgress']>[0]) => {
|
|
364
404
|
const fromEvent = progress.metadata?.agentRun;
|
|
365
405
|
if (isAgentRunEntity(fromEvent)) {
|
|
366
406
|
agentRunRef.current = fromEvent;
|
|
367
407
|
}
|
|
368
|
-
|
|
408
|
+
sourcePublisher.OnProgress(progress);
|
|
369
409
|
},
|
|
370
|
-
onStreaming:
|
|
410
|
+
onStreaming: sourcePublisher.OnStreaming,
|
|
371
411
|
lastRunId: lastRunId,
|
|
372
412
|
autoPopulateLastRunPayload: autoPopulateLastRunPayload,
|
|
373
413
|
configurationId: configurationId,
|
|
@@ -376,21 +416,28 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
376
416
|
taskGraphDebug: parseTaskGraphDebug(taskGraphDebug),
|
|
377
417
|
ConversationHistoryFrom: conversationHistoryFrom,
|
|
378
418
|
...(conversationBranchId ? { ConversationBranchID: conversationBranchId } : {}),
|
|
419
|
+
...(allowHandoff ? { handoffChain: [] as string[] } : {}),
|
|
379
420
|
data: parsedData,
|
|
380
421
|
// Whether the run may read the reserved data keys (scope, agent-type params); BaseAgent drops them otherwise.
|
|
381
422
|
TrustReservedRunData: trustReservedRunData,
|
|
382
423
|
context: {
|
|
383
424
|
dataSource: dataSource
|
|
384
425
|
}
|
|
385
|
-
}
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
// Execute the agent in conversation context - handles conversation, artifacts, etc.
|
|
429
|
+
const conversationResult = await agentRunner.RunAgentInConversation(sourceParams, {
|
|
386
430
|
conversationDetailId: conversationDetailId, // Use existing if provided
|
|
431
|
+
agentResponseDetail: replyDetail, // the reply row this request created, when it did
|
|
387
432
|
conversationId: conversationId, // LATENCY OPT #2: pre-resolved to skip redundant load in AgentRunner
|
|
388
433
|
userMessage: userMessage, // Provide user message when conversationDetailId not provided
|
|
389
434
|
createArtifacts: createArtifacts || false,
|
|
390
|
-
sourceArtifactId: sourceArtifactId
|
|
435
|
+
sourceArtifactId: sourceArtifactId,
|
|
436
|
+
// A widget guest runs as the system user, but its conversation stays the guest's to write (MJ#4791).
|
|
437
|
+
ConversationWriter: userPayload.ElevatedFrom,
|
|
391
438
|
});
|
|
392
439
|
|
|
393
|
-
|
|
440
|
+
let result = conversationResult.agentResult;
|
|
394
441
|
// Use agent response detail ID if available, otherwise fall back to user message detail ID
|
|
395
442
|
const finalConversationDetailId = conversationResult.agentResponseDetailId || conversationResult.userMessageDetailId;
|
|
396
443
|
const artifactInfo = conversationResult.artifactInfo;
|
|
@@ -400,61 +447,111 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
400
447
|
agentRunRef.current = result.agentRun;
|
|
401
448
|
}
|
|
402
449
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
const postExecutionOps: Promise<void>[] = [];
|
|
417
|
-
|
|
418
|
-
if (lastRunId && result.agentRun?.ID) {
|
|
419
|
-
postExecutionOps.push(
|
|
420
|
-
this.syncFeedbackRequestFromConversation(lastRunId, result.agentRun.ID, userMessage, currentUser, p)
|
|
421
|
-
);
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
if (result.feedbackRequestId) {
|
|
425
|
-
postExecutionOps.push(
|
|
426
|
-
this.sendFeedbackRequestNotification(result, currentUser, pubSub, userPayload)
|
|
427
|
-
);
|
|
428
|
-
}
|
|
450
|
+
await this.runPostExecutionNotifications(
|
|
451
|
+
result,
|
|
452
|
+
artifactInfo,
|
|
453
|
+
conversationResult.conversationId,
|
|
454
|
+
finalConversationDetailId,
|
|
455
|
+
lastRunId,
|
|
456
|
+
userMessage,
|
|
457
|
+
createNotification,
|
|
458
|
+
currentUser,
|
|
459
|
+
pubSub,
|
|
460
|
+
userPayload,
|
|
461
|
+
p
|
|
462
|
+
);
|
|
429
463
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
464
|
+
let handoffPublishedFinal = false;
|
|
465
|
+
if (allowHandoff && result.handoff && conversationResult.conversationId && conversationResult.agentResponseDetailId) {
|
|
466
|
+
const outcomes = await agentRunner.FollowHandoffs({
|
|
467
|
+
params: { ...sourceParams, conversationMessages: parsedMessages },
|
|
468
|
+
sourceResult: result,
|
|
469
|
+
conversationId: conversationResult.conversationId,
|
|
470
|
+
sourceConversationDetailId: conversationResult.agentResponseDetailId,
|
|
471
|
+
createArtifacts: createArtifacts || false,
|
|
472
|
+
ConversationWriter: userPayload.ElevatedFrom,
|
|
473
|
+
sourceConversationDetail: replyDetail,
|
|
474
|
+
hooks: {
|
|
475
|
+
OnHopStart: (hop, previousRun) => {
|
|
476
|
+
const prevSanitized = JSON.stringify(this.sanitizeAgentResult(previousRun.agentResult, currentUser));
|
|
477
|
+
currentPublisher.PublishFinal(
|
|
478
|
+
previousRun.agentResult,
|
|
479
|
+
previousRun.agentResult.agentRun?.ConversationDetailID ?? previousRun.conversationDetailId,
|
|
480
|
+
prevSanitized
|
|
481
|
+
);
|
|
482
|
+
currentPublisher = new AgentRunStatusPublisher(
|
|
483
|
+
pubSub,
|
|
484
|
+
userPayload,
|
|
485
|
+
sessionId,
|
|
486
|
+
hop.targetConversationDetailId
|
|
487
|
+
);
|
|
488
|
+
return {
|
|
489
|
+
onProgress: (progress) => {
|
|
490
|
+
const fromEvent = progress.metadata?.agentRun;
|
|
491
|
+
if (isAgentRunEntity(fromEvent)) {
|
|
492
|
+
agentRunRef.current = fromEvent;
|
|
493
|
+
}
|
|
494
|
+
currentPublisher.OnProgress(progress);
|
|
495
|
+
},
|
|
496
|
+
onStreaming: currentPublisher.OnStreaming,
|
|
497
|
+
};
|
|
438
498
|
},
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
499
|
+
OnHopEnd: async (_hop, outcome) => {
|
|
500
|
+
if (!outcome.agentResult) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
if (outcome.agentResult.agentRun) {
|
|
504
|
+
agentRunRef.current = outcome.agentResult.agentRun;
|
|
505
|
+
}
|
|
506
|
+
await this.runPostExecutionNotifications(
|
|
507
|
+
outcome.agentResult,
|
|
508
|
+
outcome.artifactInfo,
|
|
509
|
+
conversationResult.conversationId,
|
|
510
|
+
outcome.targetConversationDetailId,
|
|
511
|
+
undefined,
|
|
512
|
+
undefined,
|
|
513
|
+
createNotification,
|
|
514
|
+
currentUser,
|
|
515
|
+
pubSub,
|
|
516
|
+
userPayload,
|
|
517
|
+
p
|
|
518
|
+
);
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
});
|
|
522
|
+
const lastOutcome = outcomes[outcomes.length - 1];
|
|
523
|
+
if (lastOutcome?.error) {
|
|
524
|
+
const executionTime = Date.now() - startTime;
|
|
525
|
+
currentPublisher.PublishFailure(lastOutcome.targetConversationDetailId, lastOutcome.error);
|
|
526
|
+
LogError(`AI Agent handoff hop failed: ${lastOutcome.error}`);
|
|
527
|
+
return {
|
|
528
|
+
success: false,
|
|
529
|
+
errorMessage: lastOutcome.error,
|
|
530
|
+
executionTimeMs: executionTime,
|
|
531
|
+
result: JSON.stringify({ success: false, errorMessage: lastOutcome.error })
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
if (lastOutcome?.agentResult) {
|
|
535
|
+
const lastHopSanitized = JSON.stringify(this.sanitizeAgentResult(lastOutcome.agentResult, currentUser));
|
|
536
|
+
currentPublisher.PublishFinal(
|
|
537
|
+
lastOutcome.agentResult,
|
|
538
|
+
lastOutcome.agentResult.agentRun?.ConversationDetailID ?? lastOutcome.targetConversationDetailId,
|
|
539
|
+
lastHopSanitized
|
|
540
|
+
);
|
|
541
|
+
handoffPublishedFinal = true;
|
|
542
|
+
}
|
|
446
543
|
}
|
|
447
544
|
|
|
448
|
-
|
|
449
|
-
await Promise.all(postExecutionOps);
|
|
450
|
-
}
|
|
545
|
+
const executionTime = Date.now() - startTime;
|
|
451
546
|
|
|
452
|
-
// Create sanitized payload for JSON serialization
|
|
453
|
-
const sanitizedResult = this.sanitizeAgentResult(result);
|
|
547
|
+
// Create sanitized payload for JSON serialization (always tied to the source detail)
|
|
548
|
+
const sanitizedResult = this.sanitizeAgentResult(result, currentUser);
|
|
454
549
|
const returnResult = JSON.stringify(sanitizedResult);
|
|
455
550
|
|
|
456
|
-
// Publish final events with enriched result data
|
|
457
|
-
|
|
551
|
+
// Publish final events with enriched result data when no handoff hop already finalized via OnHopStart
|
|
552
|
+
if (!handoffPublishedFinal) {
|
|
553
|
+
currentPublisher.PublishFinal(result, result.agentRun?.ConversationDetailID, returnResult);
|
|
554
|
+
}
|
|
458
555
|
|
|
459
556
|
// Log completion
|
|
460
557
|
if (result.success) {
|
|
@@ -473,11 +570,18 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
473
570
|
} catch (error) {
|
|
474
571
|
const executionTime = Date.now() - startTime;
|
|
475
572
|
LogError(`AI Agent run failed:`, undefined, error);
|
|
476
|
-
|
|
573
|
+
// Never dereference a non-Error throw: this catch must not itself throw, since executeAIAgent resolves on
|
|
574
|
+
// every failure (executeAgentInBackground relies on it).
|
|
575
|
+
const errorMessage = (error instanceof Error && error.message) || 'Unknown error occurred';
|
|
477
576
|
|
|
478
577
|
// Fire-and-forget clients otherwise leave the run Running and the
|
|
479
578
|
// conversation detail In-Progress (Explorer red-pill timer).
|
|
480
|
-
await this.persistInFlightAgentFailure(p, userPayload, agentRunRef.current, conversationDetailId, errorMessage);
|
|
579
|
+
await this.persistInFlightAgentFailure(p, userPayload, agentRunRef.current, conversationDetailId, errorMessage, replyDetail);
|
|
580
|
+
// A fire-and-forget client has only this message to learn the run ended: without it, it waits out its
|
|
581
|
+
// idle timeout and then reconciles the run as a success. Published after the rows are closed, so a
|
|
582
|
+
// client that reloads the reply on this message reads the error. PublishFinal is the try's last step
|
|
583
|
+
// that can throw, so a run gets one completion or the other, never both.
|
|
584
|
+
statusPublisher.PublishFailure(conversationDetailId, errorMessage);
|
|
481
585
|
|
|
482
586
|
const errorResult = {
|
|
483
587
|
success: false,
|
|
@@ -494,6 +598,71 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
494
598
|
}
|
|
495
599
|
}
|
|
496
600
|
|
|
601
|
+
/**
|
|
602
|
+
* LATENCY OPTIMIZATION (Opt #6): Runs the three independent post-execution notification/sync
|
|
603
|
+
* operations in parallel via `Promise.all` (shared by the initial run and each handoff hop):
|
|
604
|
+
* 1. `syncFeedbackRequestFromConversation` — links a prior Chat-step feedback request to the new run.
|
|
605
|
+
* 2. `sendFeedbackRequestNotification` — sends an in-app/email/SMS notification when paused for human input.
|
|
606
|
+
* 3. `createCompletionNotification` — sends an in-app/email/SMS notification when an artifact was created.
|
|
607
|
+
*/
|
|
608
|
+
private async runPostExecutionNotifications(
|
|
609
|
+
result: ExecuteAgentResult,
|
|
610
|
+
artifactInfo: { artifactId: string; versionId: string; versionNumber: number } | undefined,
|
|
611
|
+
conversationId: string,
|
|
612
|
+
conversationDetailId: string | undefined,
|
|
613
|
+
lastRunId: string | undefined,
|
|
614
|
+
userMessage: string | undefined,
|
|
615
|
+
createNotification: boolean,
|
|
616
|
+
currentUser: UserInfo,
|
|
617
|
+
pubSub: PubSubEngine,
|
|
618
|
+
userPayload: UserPayload,
|
|
619
|
+
provider: IMetadataProvider
|
|
620
|
+
): Promise<void> {
|
|
621
|
+
const postExecutionOps: Promise<void>[] = [];
|
|
622
|
+
|
|
623
|
+
if (lastRunId && result.agentRun?.ID) {
|
|
624
|
+
postExecutionOps.push(
|
|
625
|
+
this.syncFeedbackRequestFromConversation(lastRunId, result.agentRun.ID, userMessage, currentUser, provider)
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
if (result.feedbackRequestId) {
|
|
630
|
+
postExecutionOps.push(
|
|
631
|
+
this.sendFeedbackRequestNotification(result, currentUser, pubSub, userPayload)
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
if (
|
|
636
|
+
createNotification
|
|
637
|
+
&& result.success
|
|
638
|
+
&& artifactInfo
|
|
639
|
+
&& artifactInfo.artifactId
|
|
640
|
+
&& artifactInfo.versionId
|
|
641
|
+
&& artifactInfo.versionNumber
|
|
642
|
+
&& conversationDetailId
|
|
643
|
+
) {
|
|
644
|
+
postExecutionOps.push(
|
|
645
|
+
this.createCompletionNotification(
|
|
646
|
+
result.agentRun,
|
|
647
|
+
{
|
|
648
|
+
artifactId: artifactInfo.artifactId,
|
|
649
|
+
versionId: artifactInfo.versionId,
|
|
650
|
+
versionNumber: artifactInfo.versionNumber
|
|
651
|
+
},
|
|
652
|
+
conversationId,
|
|
653
|
+
conversationDetailId,
|
|
654
|
+
currentUser,
|
|
655
|
+
pubSub,
|
|
656
|
+
userPayload
|
|
657
|
+
)
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
if (postExecutionOps.length > 0) {
|
|
662
|
+
await Promise.all(postExecutionOps);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
497
666
|
/**
|
|
498
667
|
* When executeAIAgent throws after the run/detail exist, close them so Explorer
|
|
499
668
|
* does not leave a red-pill timer on Status=Running / ConversationDetail In-Progress.
|
|
@@ -503,7 +672,9 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
503
672
|
userPayload: UserPayload,
|
|
504
673
|
run: MJAIAgentRunEntityExtended | null | undefined,
|
|
505
674
|
conversationDetailId: string | undefined,
|
|
506
|
-
errorMessage: string
|
|
675
|
+
errorMessage: string,
|
|
676
|
+
/** The run's reply row, when this request created it: written in place, as the server. */
|
|
677
|
+
replyDetail?: MJConversationDetailEntityExtended
|
|
507
678
|
): Promise<void> {
|
|
508
679
|
try {
|
|
509
680
|
if (run && run.Status === 'Running') {
|
|
@@ -520,10 +691,11 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
520
691
|
return;
|
|
521
692
|
}
|
|
522
693
|
if (conversationDetailId) {
|
|
523
|
-
const detail = await provider.GetEntityObject<MJConversationDetailEntity>(
|
|
694
|
+
const detail = replyDetail ?? await provider.GetEntityObject<MJConversationDetailEntity>(
|
|
524
695
|
'MJ: Conversation Details',
|
|
525
696
|
user
|
|
526
697
|
);
|
|
698
|
+
await detail.EnsureSaveComplete(); // the run may still be saving into the same reply instance
|
|
527
699
|
if (await detail.Load(conversationDetailId) && detail.Status === 'In-Progress') {
|
|
528
700
|
await detail.EnsureSaveComplete();
|
|
529
701
|
detail.Status = 'Error';
|
|
@@ -580,6 +752,9 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
580
752
|
// Only the system user or an API key holding the agent:trusted scope may set a run's scope and agent-type
|
|
581
753
|
// params through data; for anyone else BaseAgent drops those keys (ExecuteAgentParams.TrustReservedRunData).
|
|
582
754
|
const trustRunData = await IsTrustedAgentRunCaller({ UserPayload: userPayload, IsWidgetGuestRun: false, AgentID: agentId });
|
|
755
|
+
if (!userPayload.apiKeyHash) {
|
|
756
|
+
this.handoffEligiblePayloads.add(userPayload);
|
|
757
|
+
}
|
|
583
758
|
|
|
584
759
|
if (fireAndForget) {
|
|
585
760
|
// Fire-and-forget mode: start execution in background, return immediately.
|
|
@@ -781,40 +956,60 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
781
956
|
}
|
|
782
957
|
|
|
783
958
|
/**
|
|
784
|
-
*
|
|
785
|
-
*
|
|
786
|
-
*
|
|
787
|
-
*
|
|
788
|
-
*
|
|
789
|
-
*
|
|
790
|
-
*
|
|
959
|
+
* Discovers whether this agent's newest root run on this conversation/branch path should be
|
|
960
|
+
* chained by `LastRunID` on a chat-thread reply — either because the user stopped it
|
|
961
|
+
* (`reason: 'stopped'`) or because it paused on `FinalStep === 'Chat'` with one or more
|
|
962
|
+
* unanswered sub-agent consultations (`reason: 'open-consult'`).
|
|
963
|
+
*
|
|
964
|
+
* The query spans the runs that could be the predecessor (settled, or stopped by the user)
|
|
965
|
+
* and the newest decides, so a stopped or paused-consult run that a later settled run already
|
|
966
|
+
* followed is not chained to again. Fail-soft: a lookup failure means no chaining, never a
|
|
967
|
+
* failed turn.
|
|
791
968
|
*/
|
|
792
|
-
private async
|
|
969
|
+
private async findChainablePredecessor(
|
|
793
970
|
conversationId: string,
|
|
794
971
|
agentId: string,
|
|
795
972
|
branchId: string | null,
|
|
796
973
|
contextUser: UserInfo,
|
|
797
974
|
provider: IMetadataProvider
|
|
798
|
-
): Promise<string | null> {
|
|
975
|
+
): Promise<{ runId: string; reason: 'stopped' | 'open-consult' } | null> {
|
|
799
976
|
try {
|
|
800
977
|
// The run must have replied on this turn's branch path: a run stopped on a sibling branch is not
|
|
801
978
|
// this path's history. The trunk needs no branch rows; a branch needs them to walk its ancestry.
|
|
802
979
|
const branches = branchId ? await ConversationEngine.LoadBranchesFresh(conversationId, contextUser, provider) : [];
|
|
803
980
|
const rv = RunView.FromMetadataProvider(provider);
|
|
804
|
-
const newest = await rv.RunView<{
|
|
981
|
+
const newest = await rv.RunView<{
|
|
982
|
+
ID: string;
|
|
983
|
+
Status: string;
|
|
984
|
+
CancellationReason: string | null;
|
|
985
|
+
FinalStep: string | null;
|
|
986
|
+
}>({
|
|
805
987
|
EntityName: 'MJ: AI Agent Runs',
|
|
806
988
|
ExtraFilter: MJAIAgentRunEntityExtended.BuildStoppedPredecessorFilter(conversationId, agentId, branchId, branches),
|
|
807
989
|
OrderBy: '__mj_CreatedAt DESC',
|
|
808
990
|
MaxRows: 1,
|
|
809
|
-
|
|
991
|
+
SkipTotalRowCount: true,
|
|
992
|
+
Fields: ['ID', 'Status', 'CancellationReason', 'FinalStep'],
|
|
810
993
|
ResultType: 'simple',
|
|
811
|
-
// The row this looks for was written by the Stop button moments ago; read the database, not a cache.
|
|
994
|
+
// The row this looks for was written by the Stop button or a Chat pause moments ago; read the database, not a cache.
|
|
812
995
|
BypassCache: true,
|
|
813
996
|
}, contextUser);
|
|
814
997
|
const run = newest.Success ? newest.Results?.[0] : undefined;
|
|
815
|
-
|
|
998
|
+
if (!run) {
|
|
999
|
+
return null;
|
|
1000
|
+
}
|
|
1001
|
+
if (MJAIAgentRunEntityExtended.IsUserStopped(run.Status, run.CancellationReason)) {
|
|
1002
|
+
return { runId: run.ID, reason: 'stopped' };
|
|
1003
|
+
}
|
|
1004
|
+
if (run.FinalStep === 'Chat' && CanAgentOwnSubAgentConsults(agentId)) {
|
|
1005
|
+
const open = await LoadOpenSubAgentConsults(provider, run.ID, contextUser);
|
|
1006
|
+
if (open.length > 0) {
|
|
1007
|
+
return { runId: run.ID, reason: 'open-consult' };
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
return null;
|
|
816
1011
|
} catch (error) {
|
|
817
|
-
LogError(`
|
|
1012
|
+
LogError(`findChainablePredecessor failed; the turn runs unchained: ${error instanceof Error ? error.message : String(error)}`);
|
|
818
1013
|
return null;
|
|
819
1014
|
}
|
|
820
1015
|
}
|
|
@@ -834,11 +1029,16 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
834
1029
|
provider: IMetadataProvider
|
|
835
1030
|
): Promise<void> {
|
|
836
1031
|
try {
|
|
1032
|
+
const trimmedLastRunId = typeof lastRunId === 'string' ? lastRunId.trim() : '';
|
|
1033
|
+
if (!IsValidUUID(trimmedLastRunId)) {
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
837
1036
|
const rv = RunView.FromMetadataProvider(provider);
|
|
838
1037
|
const result = await rv.RunView<MJAIAgentRequestEntity>({
|
|
839
1038
|
EntityName: 'MJ: AI Agent Requests',
|
|
840
|
-
ExtraFilter: `OriginatingAgentRunID='${
|
|
1039
|
+
ExtraFilter: `OriginatingAgentRunID='${EscapeSQLString(trimmedLastRunId)}' AND Status='Requested'`,
|
|
841
1040
|
MaxRows: 1,
|
|
1041
|
+
SkipTotalRowCount: true,
|
|
842
1042
|
ResultType: 'entity_object'
|
|
843
1043
|
}, contextUser);
|
|
844
1044
|
|
|
@@ -925,16 +1125,27 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
925
1125
|
}
|
|
926
1126
|
|
|
927
1127
|
/**
|
|
928
|
-
*
|
|
929
|
-
*
|
|
1128
|
+
* Runs an agent's turn in a conversation: the server loads the history (attachments included, so the client never
|
|
1129
|
+
* sends them), creates the agent's reply row, and runs the agent into it.
|
|
930
1130
|
*
|
|
931
|
-
*
|
|
1131
|
+
* Only the server writes agent replies (A19). The reply row (`Role` `AI`, In-Progress, its `ParentID` the user's
|
|
1132
|
+
* message) is created here, as the person asking, before the run starts. In fire-and-forget mode the
|
|
1133
|
+
* acknowledgement names it, `{ accepted, fireAndForget, conversationDetailId, createdAt }`, and is returned before
|
|
1134
|
+
* the run publishes anything; every progress, streaming and completion message carries the same
|
|
1135
|
+
* `conversationDetailId`. In synchronous mode the result's `agentRun.ConversationDetailID` names it.
|
|
1136
|
+
*
|
|
1137
|
+
* Threading, both optional: `replyParentId` puts the reply under another message of the same conversation the
|
|
1138
|
+
* caller can read (MJ's chat threads a delegate's reply under the manager's); `announcedByAgentId` has the server
|
|
1139
|
+
* first post that agent's fixed line "Continuing with **{agent}** for refinement..." and thread the reply under
|
|
1140
|
+
* it, and the acknowledgement then also carries `announcementDetailId`.
|
|
1141
|
+
*
|
|
1142
|
+
* @param userMessageId - The person's message this turn answers, already saved.
|
|
932
1143
|
* @param agentId - The agent to execute
|
|
933
1144
|
* @param maxHistoryMessages - Maximum number of history messages to include (default: 20)
|
|
934
1145
|
*/
|
|
935
1146
|
@Mutation(() => AIAgentRunResult)
|
|
936
1147
|
async RunAIAgentFromConversationDetail(
|
|
937
|
-
@Arg('
|
|
1148
|
+
@Arg('userMessageId') userMessageId: string,
|
|
938
1149
|
@Arg('agentId') agentId: string,
|
|
939
1150
|
@Ctx() { userPayload, providers, dataSource }: AppContext,
|
|
940
1151
|
@Arg('sessionId') sessionId: string,
|
|
@@ -957,11 +1168,17 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
957
1168
|
* run's own conversation reads honour it too. Omitted (clients send it only when set, so an
|
|
958
1169
|
* older client never does), the run reads the whole conversation as before. An unreadable
|
|
959
1170
|
* value fails the request rather than being dropped. */
|
|
960
|
-
@Arg('agentHistoryFrom', { nullable: true }) agentHistoryFrom?: string
|
|
1171
|
+
@Arg('agentHistoryFrom', { nullable: true }) agentHistoryFrom?: string,
|
|
1172
|
+
/** The message the reply threads under, when not the user's message: one in the same conversation the
|
|
1173
|
+
* caller can read. */
|
|
1174
|
+
@Arg('replyParentId', { nullable: true }) replyParentId?: string,
|
|
1175
|
+
/** An active agent (MJ's chat passes its conversation manager) whose fixed line "Continuing with
|
|
1176
|
+
* **{agent}** for refinement..." the server posts before the reply, which then threads under it. */
|
|
1177
|
+
@Arg('announcedByAgentId', { nullable: true }) announcedByAgentId?: string,
|
|
1178
|
+
/** The fork the reply and history run on, when the turn forks from `userMessageId` (such as Regenerate).
|
|
1179
|
+
* Checked to be a branch of the conversation whose path holds `userMessageId`. */
|
|
1180
|
+
@Arg('replyBranchId', { nullable: true }) replyBranchId?: string
|
|
961
1181
|
): Promise<AIAgentRunResult> {
|
|
962
|
-
// Check API key scope authorization for agent execution
|
|
963
|
-
await this.CheckAPIKeyScopeAuthorization('agent:execute', agentId, userPayload);
|
|
964
|
-
|
|
965
1182
|
const p = GetReadWriteProvider(providers);
|
|
966
1183
|
const currentUser = this.GetUserFromPayload(userPayload);
|
|
967
1184
|
|
|
@@ -978,10 +1195,20 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
978
1195
|
// AUTHORITATIVELY from the widget instance (never the client-supplied arg) — so a guest needs
|
|
979
1196
|
// no grants to WRITE the AI run entities and cannot run an arbitrary agent under elevation.
|
|
980
1197
|
// Conversation OWNERSHIP is still enforced under the guest principal below: the guest loads its
|
|
981
|
-
// own ConversationDetail through
|
|
982
|
-
//
|
|
1198
|
+
// own ConversationDetail through its role's RLS filters, and startConversationTurn then checks
|
|
1199
|
+
// the conversation's scope stamp against the visitor (MJ#6032), so a detail id from another
|
|
1200
|
+
// visitor's session is refused before any elevated work happens. The reply row is written
|
|
1201
|
+
// as the guest too, never as the elevated principal, which owns no guest's conversation.
|
|
983
1202
|
const widgetElevation = await ResolveWidgetGuestRunContext(userPayload, p);
|
|
984
1203
|
const effectiveAgentId = widgetElevation ? widgetElevation.PinnedAgentId : agentId;
|
|
1204
|
+
// Check API key scope authorization for agent execution against the resolved agent id.
|
|
1205
|
+
await this.CheckAPIKeyScopeAuthorization('agent:execute', effectiveAgentId, userPayload);
|
|
1206
|
+
// A widget guest has one pinned agent and never posts a continuation announcement as another agent;
|
|
1207
|
+
// an API-key caller must hold agent:execute for the announcing agent as well as the running agent.
|
|
1208
|
+
const effectiveAnnouncedByAgentId = widgetElevation ? undefined : announcedByAgentId;
|
|
1209
|
+
if (effectiveAnnouncedByAgentId) {
|
|
1210
|
+
await this.CheckAPIKeyScopeAuthorization('agent:execute', effectiveAnnouncedByAgentId, userPayload);
|
|
1211
|
+
}
|
|
985
1212
|
const effectiveUserPayload = widgetElevation ? ElevateUserPayload(userPayload, widgetElevation.ElevatedUser) : userPayload;
|
|
986
1213
|
// Only the system user or an API key holding the agent:trusted scope may set a run's scope and agent-type
|
|
987
1214
|
// params through data (ExecuteAgentParams.TrustReservedRunData). Judged on the caller's own payload: a widget
|
|
@@ -989,78 +1216,74 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
989
1216
|
const trustRunData = await IsTrustedAgentRunCaller({
|
|
990
1217
|
UserPayload: userPayload, IsWidgetGuestRun: widgetElevation !== null, AgentID: agentId,
|
|
991
1218
|
});
|
|
1219
|
+
if (!userPayload.apiKeyHash && !widgetElevation) {
|
|
1220
|
+
this.handoffEligiblePayloads.add(effectiveUserPayload);
|
|
1221
|
+
}
|
|
992
1222
|
|
|
993
1223
|
try {
|
|
994
1224
|
// Parsed before anything loads: a floor the caller asked for must never be dropped.
|
|
995
1225
|
const historyFrom = parseAgentHistoryFrom(agentHistoryFrom);
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
//
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
//
|
|
1014
|
-
// over: chain it by LastRunID (the chat client never sends one) and, when the caller
|
|
1015
|
-
// supplied no payload, roll the stopped run's FinalPayload into this run's start.
|
|
1226
|
+
const turn = await this.startConversationTurn(p, currentUser, {
|
|
1227
|
+
UserMessageId: userMessageId,
|
|
1228
|
+
AgentId: effectiveAgentId,
|
|
1229
|
+
MaxHistoryMessages: maxHistoryMessages || 20,
|
|
1230
|
+
HistoryFrom: historyFrom,
|
|
1231
|
+
ReplyParentId: replyParentId,
|
|
1232
|
+
AnnouncedByAgentId: effectiveAnnouncedByAgentId,
|
|
1233
|
+
ReplyBranchId: replyBranchId
|
|
1234
|
+
});
|
|
1235
|
+
const reply = turn.Reply;
|
|
1236
|
+
// The turn's branch (the message's own branch, or a validated fork whose path holds the message)
|
|
1237
|
+
// decides which path the run reads.
|
|
1238
|
+
const branchId = turn.BranchId;
|
|
1239
|
+
|
|
1240
|
+
// A turn that follows a run the user STOPPED or a run paused on FinalStep === 'Chat'
|
|
1241
|
+
// with an open sub-agent consult continues that run rather than starting over: chain it
|
|
1242
|
+
// by LastRunID (the chat client never sends one) and, when the caller supplied no
|
|
1243
|
+
// payload, roll the prior run's FinalPayload into this run's start.
|
|
1016
1244
|
let effectiveLastRunId = lastRunId;
|
|
1017
1245
|
let effectiveAutoPopulate = autoPopulateLastRunPayload;
|
|
1018
1246
|
if (!effectiveLastRunId) {
|
|
1019
|
-
const
|
|
1020
|
-
if (
|
|
1021
|
-
effectiveLastRunId =
|
|
1247
|
+
const chainable = await this.findChainablePredecessor(turn.ConversationId, effectiveAgentId, branchId, currentUser, p);
|
|
1248
|
+
if (chainable) {
|
|
1249
|
+
effectiveLastRunId = chainable.runId;
|
|
1022
1250
|
if (effectiveAutoPopulate === undefined && payload == null) {
|
|
1023
1251
|
effectiveAutoPopulate = true;
|
|
1024
1252
|
}
|
|
1025
|
-
|
|
1253
|
+
if (chainable.reason === 'stopped') {
|
|
1254
|
+
LogStatus(`↩️ Continuing from user-stopped run ${chainable.runId} (chained by LastRunID)`);
|
|
1255
|
+
} else {
|
|
1256
|
+
LogStatus(`Resuming open sub-agent consult(s) from run ${chainable.runId} (chained by LastRunID)`);
|
|
1257
|
+
}
|
|
1026
1258
|
}
|
|
1027
1259
|
}
|
|
1028
1260
|
|
|
1029
|
-
// Load conversation history with attachments from DB
|
|
1030
|
-
const messages = await this.loadConversationHistoryWithAttachments(
|
|
1031
|
-
conversationId,
|
|
1032
|
-
currentUser,
|
|
1033
|
-
maxHistoryMessages || 20,
|
|
1034
|
-
p,
|
|
1035
|
-
// The UI creates the agent-response placeholder row ('⏳ ...') before invoking
|
|
1036
|
-
// this mutation — exclude it so the model never sees an empty assistant turn.
|
|
1037
|
-
[conversationDetailId],
|
|
1038
|
-
historyFrom,
|
|
1039
|
-
branchId
|
|
1040
|
-
);
|
|
1041
|
-
|
|
1042
|
-
// Convert to JSON string for the existing executeAIAgent method
|
|
1043
|
-
const messagesJson = JSON.stringify(messages);
|
|
1044
|
-
|
|
1045
1261
|
if (fireAndForget) {
|
|
1046
1262
|
// Fire-and-forget mode: start execution in background, return immediately.
|
|
1047
1263
|
// The client will receive the result via WebSocket PubSub completion event.
|
|
1048
1264
|
this.executeAgentInBackground(
|
|
1049
|
-
p, dataSource, effectiveAgentId, effectiveUserPayload,
|
|
1265
|
+
p, dataSource, effectiveAgentId, effectiveUserPayload, turn.MessagesJson, sessionId, pubSub,
|
|
1050
1266
|
data, payload, effectiveLastRunId, effectiveAutoPopulate, configurationId,
|
|
1051
|
-
|
|
1052
|
-
sourceArtifactId, sourceArtifactVersionId,
|
|
1267
|
+
reply.ID, createArtifacts || false, createNotification || false,
|
|
1268
|
+
sourceArtifactId, sourceArtifactVersionId, turn.ConversationId, planMode, requestedSkillIDs,
|
|
1053
1269
|
undefined, // taskGraphDebug
|
|
1054
1270
|
historyFrom,
|
|
1055
1271
|
trustRunData,
|
|
1056
|
-
branchId
|
|
1272
|
+
branchId,
|
|
1273
|
+
reply
|
|
1057
1274
|
);
|
|
1058
1275
|
|
|
1059
1276
|
LogStatus(`🔥 Fire-and-forget: Agent ${effectiveAgentId} execution started in background for session ${sessionId}`);
|
|
1060
1277
|
|
|
1061
1278
|
return {
|
|
1062
1279
|
success: true,
|
|
1063
|
-
result: JSON.stringify({
|
|
1280
|
+
result: JSON.stringify({
|
|
1281
|
+
accepted: true,
|
|
1282
|
+
fireAndForget: true,
|
|
1283
|
+
conversationDetailId: reply.ID,
|
|
1284
|
+
createdAt: reply.__mj_CreatedAt,
|
|
1285
|
+
...(turn.Announcement ? { announcementDetailId: turn.Announcement.ID } : {})
|
|
1286
|
+
})
|
|
1064
1287
|
};
|
|
1065
1288
|
}
|
|
1066
1289
|
|
|
@@ -1070,7 +1293,7 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
1070
1293
|
dataSource,
|
|
1071
1294
|
effectiveAgentId,
|
|
1072
1295
|
effectiveUserPayload,
|
|
1073
|
-
|
|
1296
|
+
turn.MessagesJson,
|
|
1074
1297
|
sessionId,
|
|
1075
1298
|
pubSub,
|
|
1076
1299
|
data,
|
|
@@ -1079,19 +1302,20 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
1079
1302
|
effectiveLastRunId,
|
|
1080
1303
|
effectiveAutoPopulate,
|
|
1081
1304
|
configurationId,
|
|
1082
|
-
|
|
1305
|
+
reply.ID,
|
|
1083
1306
|
createArtifacts || false,
|
|
1084
1307
|
createNotification || false,
|
|
1085
1308
|
sourceArtifactId,
|
|
1086
1309
|
sourceArtifactVersionId,
|
|
1087
|
-
|
|
1310
|
+
turn.ConversationId, // LATENCY OPT #2: pass pre-resolved conversationId
|
|
1088
1311
|
undefined, // runRef
|
|
1089
1312
|
planMode,
|
|
1090
1313
|
requestedSkillIDs,
|
|
1091
1314
|
undefined, // taskGraphDebug
|
|
1092
1315
|
historyFrom,
|
|
1093
1316
|
trustRunData,
|
|
1094
|
-
branchId
|
|
1317
|
+
branchId,
|
|
1318
|
+
reply
|
|
1095
1319
|
);
|
|
1096
1320
|
} catch (error) {
|
|
1097
1321
|
const errorMessage = (error as Error).message || 'Unknown error loading conversation history';
|
|
@@ -1104,6 +1328,137 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
1104
1328
|
}
|
|
1105
1329
|
}
|
|
1106
1330
|
|
|
1331
|
+
/**
|
|
1332
|
+
* Everything a conversation turn needs before its agent runs: the user's message (read as the caller, so a
|
|
1333
|
+
* message they can't see is "not found", and for an anonymous visitor also checked against the conversation's
|
|
1334
|
+
* scope stamp), the conversation history, the optional announcement line, and the reply
|
|
1335
|
+
* row, created last so the history never holds the empty reply. Every row is written as `user`, the person asking,
|
|
1336
|
+
* and marked as server-authored by {@link AgentRunner.CreateAgentReplyDetail}.
|
|
1337
|
+
*/
|
|
1338
|
+
private async startConversationTurn(
|
|
1339
|
+
p: DatabaseProviderBase,
|
|
1340
|
+
user: UserInfo,
|
|
1341
|
+
request: ConversationTurnRequest
|
|
1342
|
+
): Promise<{ ConversationId: string; BranchId: string | null; MessagesJson: string; Reply: MJConversationDetailEntityExtended; Announcement?: MJConversationDetailEntityExtended }> {
|
|
1343
|
+
// LATENCY OPTIMIZATION (Opt #2 + #3): the user's message is loaded once here for its conversation and
|
|
1344
|
+
// branch, which are threaded through the call chain rather than reloaded downstream.
|
|
1345
|
+
const placement = await this.loadPlacementOf(p, user, request.UserMessageId);
|
|
1346
|
+
const conversationId = placement.ConversationId;
|
|
1347
|
+
// Loading the message as the caller is the whole ownership check for a named user. It is not for an
|
|
1348
|
+
// anonymous visitor: every visitor is the one shared Anonymous user, so under a guest role whose row
|
|
1349
|
+
// filters key on UserID another visitor's message loads fine (MJ#6032). The conversation's scope stamp
|
|
1350
|
+
// decides instead, exactly as it does for the realtime gates — and before any row is written.
|
|
1351
|
+
const access = await AuthorizeConversationTurn(conversationId, user, p);
|
|
1352
|
+
if (!access.Allowed) {
|
|
1353
|
+
LogError(`RunAIAgentFromConversationDetail: anonymous visitor ${user.AnonymousVisitorID ?? '(no visitor id)'} refused a turn in conversation ${conversationId} (${access.Reason})`);
|
|
1354
|
+
throw new Error('Not authorized: you do not own this conversation');
|
|
1355
|
+
}
|
|
1356
|
+
const branchId = request.ReplyBranchId
|
|
1357
|
+
? await this.validateReplyBranch(p, user, conversationId, placement, request.ReplyBranchId)
|
|
1358
|
+
: placement.BranchId;
|
|
1359
|
+
const parentId = request.ReplyParentId
|
|
1360
|
+
? await this.validateReplyParent(p, user, request.ReplyParentId, conversationId)
|
|
1361
|
+
: request.UserMessageId;
|
|
1362
|
+
const messages = await this.loadConversationHistoryWithAttachments(conversationId, user, request.MaxHistoryMessages, p, undefined, request.HistoryFrom, branchId);
|
|
1363
|
+
const runner = new AgentRunner(p);
|
|
1364
|
+
const announcement = request.AnnouncedByAgentId
|
|
1365
|
+
? await this.postContinuationAnnouncement(runner, user, conversationId, branchId, parentId, request.AnnouncedByAgentId, request.AgentId)
|
|
1366
|
+
: undefined;
|
|
1367
|
+
const reply = await runner.CreateAgentReplyDetail({
|
|
1368
|
+
conversationId,
|
|
1369
|
+
branchId,
|
|
1370
|
+
agentId: request.AgentId,
|
|
1371
|
+
contextUser: user,
|
|
1372
|
+
parentId: announcement?.ID ?? parentId,
|
|
1373
|
+
provider: p
|
|
1374
|
+
});
|
|
1375
|
+
return { ConversationId: conversationId, BranchId: branchId, MessagesJson: JSON.stringify(messages), Reply: reply, Announcement: announcement };
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
/** The conversation, branch (null is Main) and sequence of a message, read as `user`; throws when they can't read it. */
|
|
1379
|
+
private async loadPlacementOf(
|
|
1380
|
+
p: DatabaseProviderBase,
|
|
1381
|
+
user: UserInfo,
|
|
1382
|
+
messageId: string
|
|
1383
|
+
): Promise<{ ConversationId: string; BranchId: string | null; Sequence: number }> {
|
|
1384
|
+
const message = await p.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', user);
|
|
1385
|
+
if (!await message.Load(messageId)) {
|
|
1386
|
+
throw new Error(`Conversation detail ${messageId} not found`);
|
|
1387
|
+
}
|
|
1388
|
+
return { ConversationId: message.ConversationID, BranchId: message.BranchID ?? null, Sequence: message.Sequence ?? -1 };
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
/**
|
|
1392
|
+
* When a turn forks from an earlier message (such as Regenerate), the reply and history run on the fork while the
|
|
1393
|
+
* user's message stays on the branch it was written on. Checks that `replyBranchId` is a branch of the turn's
|
|
1394
|
+
* conversation whose path holds the user's message (`IsRowOnBranchPath` rather than exact `ForkFromSequence`
|
|
1395
|
+
* equality is deliberate: `ConversationEngine.ForkPointFrom` sets `ForkFromSequence = message.Sequence` and the
|
|
1396
|
+
* fork belongs to this conversation); returns `replyBranchId`, or throws before any row is created.
|
|
1397
|
+
*/
|
|
1398
|
+
private async validateReplyBranch(
|
|
1399
|
+
p: DatabaseProviderBase,
|
|
1400
|
+
user: UserInfo,
|
|
1401
|
+
conversationId: string,
|
|
1402
|
+
userMessage: { BranchId: string | null; Sequence: number },
|
|
1403
|
+
replyBranchId: string
|
|
1404
|
+
): Promise<string> {
|
|
1405
|
+
if (UUIDsEqual(replyBranchId, userMessage.BranchId)) {
|
|
1406
|
+
return replyBranchId;
|
|
1407
|
+
}
|
|
1408
|
+
if (userMessage.Sequence < 0) {
|
|
1409
|
+
throw new Error(`Conversation detail is not on branch ${replyBranchId}'s path, so the reply cannot be written on that branch`);
|
|
1410
|
+
}
|
|
1411
|
+
const branches = await ConversationEngine.LoadBranchesFresh(conversationId, user, p);
|
|
1412
|
+
const chain = ConversationEngine.BuildBranchChain(branches, replyBranchId);
|
|
1413
|
+
if (!ConversationEngine.IsRowOnBranchPath({ BranchID: userMessage.BranchId, Sequence: userMessage.Sequence }, chain)) {
|
|
1414
|
+
throw new Error(`Conversation detail is not on branch ${replyBranchId}'s path, so the reply cannot be written on that branch`);
|
|
1415
|
+
}
|
|
1416
|
+
return replyBranchId;
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
/**
|
|
1420
|
+
* A reply's parent is part of what the reply says, so the server sets it, from a checked input: a message the
|
|
1421
|
+
* caller can read, in the turn's own conversation. Returns its ID; throws otherwise.
|
|
1422
|
+
*/
|
|
1423
|
+
private async validateReplyParent(p: DatabaseProviderBase, user: UserInfo, parentId: string, conversationId: string): Promise<string> {
|
|
1424
|
+
const { ConversationId: parentConversationId } = await this.loadPlacementOf(p, user, parentId);
|
|
1425
|
+
if (!UUIDsEqual(parentConversationId, conversationId)) {
|
|
1426
|
+
throw new Error(`Conversation detail ${parentId} is not in this turn's conversation, so the reply cannot thread under it`);
|
|
1427
|
+
}
|
|
1428
|
+
return parentId;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
/**
|
|
1432
|
+
* Posts the announcing agent's line, "Continuing with **{agent}** for refinement...", as a completed reply of the
|
|
1433
|
+
* announcing agent. Its text is fixed and names the agent from metadata, so a caller chooses only whether it is
|
|
1434
|
+
* posted and by which active agent, never what it says.
|
|
1435
|
+
*/
|
|
1436
|
+
private async postContinuationAnnouncement(
|
|
1437
|
+
runner: AgentRunner,
|
|
1438
|
+
user: UserInfo,
|
|
1439
|
+
conversationId: string,
|
|
1440
|
+
branchId: string | null,
|
|
1441
|
+
parentId: string,
|
|
1442
|
+
announcerId: string,
|
|
1443
|
+
agentId: string
|
|
1444
|
+
): Promise<MJConversationDetailEntityExtended> {
|
|
1445
|
+
await AIEngine.Instance.Config(false, user);
|
|
1446
|
+
const announcer = AIEngine.Instance.GetAgentByID(announcerId);
|
|
1447
|
+
if (!announcer || announcer.Status !== 'Active') {
|
|
1448
|
+
throw new Error(`Agent ${announcerId} cannot announce the turn: it is not an active agent`);
|
|
1449
|
+
}
|
|
1450
|
+
const agentName = AIEngine.Instance.GetAgentByID(agentId)?.Name ?? 'the agent';
|
|
1451
|
+
return runner.CreateAgentReplyDetail({
|
|
1452
|
+
conversationId,
|
|
1453
|
+
branchId,
|
|
1454
|
+
agentId: announcer.ID,
|
|
1455
|
+
contextUser: user,
|
|
1456
|
+
parentId,
|
|
1457
|
+
message: ContinuationAnnouncementText(agentName),
|
|
1458
|
+
status: 'Complete'
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1107
1462
|
/**
|
|
1108
1463
|
* Respond to a pending AIAgentRequest from the dashboard or API.
|
|
1109
1464
|
* Updates the request record with the response and optionally spawns a
|
|
@@ -1283,9 +1638,8 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
1283
1638
|
|
|
1284
1639
|
/**
|
|
1285
1640
|
* Execute agent in background (fire-and-forget).
|
|
1286
|
-
*
|
|
1287
|
-
*
|
|
1288
|
-
* has already been sent.
|
|
1641
|
+
* The client learns the outcome only from the run's completion status message (executeAIAgent publishes it,
|
|
1642
|
+
* failure included), since the HTTP response has already been sent. A liveness pulse runs until the run ends.
|
|
1289
1643
|
*/
|
|
1290
1644
|
private executeAgentInBackground(
|
|
1291
1645
|
p: DatabaseProviderBase,
|
|
@@ -1317,36 +1671,34 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
1317
1671
|
/** ExecuteAgentParams.TrustReservedRunData — see executeAIAgent. */
|
|
1318
1672
|
trustReservedRunData: boolean = false,
|
|
1319
1673
|
/** The conversation branch of the run — threaded through to ExecuteAgentParams.ConversationBranchID. */
|
|
1320
|
-
conversationBranchId?: string | null
|
|
1674
|
+
conversationBranchId?: string | null,
|
|
1675
|
+
/** The reply row this request created for the run — see executeAIAgent. */
|
|
1676
|
+
replyDetail?: MJConversationDetailEntityExtended
|
|
1321
1677
|
): void {
|
|
1322
1678
|
// Ref the liveness pulse reads to enrich heartbeats once the run is created.
|
|
1323
1679
|
const runRef: { current: MJAIAgentRunEntityExtended | null } = { current: null };
|
|
1324
1680
|
const pulse = StartLivenessPulse({
|
|
1325
1681
|
pubSub,
|
|
1326
1682
|
sessionId,
|
|
1327
|
-
ownerUserId: userPayload
|
|
1683
|
+
ownerUserId: StatusUpdateOwnerID(userPayload),
|
|
1328
1684
|
resolver: 'RunAIAgentResolver',
|
|
1329
1685
|
readStatus: () => runRef.current
|
|
1330
1686
|
? { runId: runRef.current.ID, status: runRef.current.Status }
|
|
1331
1687
|
: undefined,
|
|
1332
1688
|
});
|
|
1333
1689
|
|
|
1334
|
-
//
|
|
1690
|
+
// executeAIAgent resolves on every failure and publishes the run's completion itself (PublishFinal, or
|
|
1691
|
+
// PublishFailure from its catch), so nothing here publishes one.
|
|
1335
1692
|
this.executeAIAgent(
|
|
1336
1693
|
p, dataSource, agentId, userPayload, messagesJson, sessionId, pubSub,
|
|
1337
1694
|
data, payload, undefined, lastRunId, autoPopulateLastRunPayload,
|
|
1338
1695
|
configurationId, conversationDetailId, createArtifacts, createNotification,
|
|
1339
1696
|
sourceArtifactId, sourceArtifactVersionId, conversationId, runRef, planMode, requestedSkillIDs, taskGraphDebug,
|
|
1340
|
-
conversationHistoryFrom, trustReservedRunData, conversationBranchId
|
|
1697
|
+
conversationHistoryFrom, trustReservedRunData, conversationBranchId, replyDetail
|
|
1341
1698
|
).catch((error: unknown) => {
|
|
1342
|
-
//
|
|
1343
|
-
//
|
|
1344
|
-
|
|
1345
|
-
LogError(`🔥 Fire-and-forget background execution failed: ${errorMessage}`, undefined, error);
|
|
1346
|
-
|
|
1347
|
-
// Publish error completion event so the client knows the agent failed.
|
|
1348
|
-
// The publisher is created inside executeAIAgent, which rejected before returning one.
|
|
1349
|
-
new AgentRunStatusPublisher(pubSub, userPayload, sessionId).PublishFailure(conversationDetailId, errorMessage);
|
|
1699
|
+
// Only a broken executeAIAgent contract lands here. Logged rather than left as an unhandled rejection;
|
|
1700
|
+
// no completion is published, because executeAIAgent may already have sent one.
|
|
1701
|
+
LogError(`🔥 Fire-and-forget run of agent ${agentId} for session ${sessionId} rejected, which executeAIAgent never should`, undefined, error);
|
|
1350
1702
|
}).finally(() => pulse.Stop());
|
|
1351
1703
|
}
|
|
1352
1704
|
|
|
@@ -1379,7 +1731,9 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
1379
1731
|
/** History floor: only rows written at or after it are loaded, and no summary is used. */
|
|
1380
1732
|
historyFrom?: Date,
|
|
1381
1733
|
/** The branch whose path to load; null reads the trunk. */
|
|
1382
|
-
branchId?: string | null
|
|
1734
|
+
branchId?: string | null,
|
|
1735
|
+
/** Speaker attribution mode forwarded to `ConversationEngine.AssembleContextWindow`. */
|
|
1736
|
+
speakerAttribution?: 'off' | 'auto' | 'always'
|
|
1383
1737
|
): Promise<ChatMessage[]> {
|
|
1384
1738
|
// Context windowing (summary boundary + raw tail, or legacy last-N when no
|
|
1385
1739
|
// summary exists) shares ONE fold implementation with all other callers —
|
|
@@ -1400,7 +1754,8 @@ export class RunAIAgentResolver extends ResolverBase {
|
|
|
1400
1754
|
const window = ConversationEngine.AssembleContextWindow(rows, {
|
|
1401
1755
|
maxTailMessages: maxMessages,
|
|
1402
1756
|
excludeDetailIds,
|
|
1403
|
-
historyFrom
|
|
1757
|
+
historyFrom,
|
|
1758
|
+
speakerAttribution
|
|
1404
1759
|
});
|
|
1405
1760
|
|
|
1406
1761
|
// Batch load input artifacts for the windowed messages. Since the backfill migration
|