@memberjunction/server 6.2.0-edge.6 → 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 +69 -0
- 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 +31 -8
- package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
- package/dist/agentSessions/SessionJanitor.js +85 -41
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/agentSessions/SessionManager.d.ts +14 -4
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +28 -4
- 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/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 +50 -2
- package/dist/auth/magicLink/MagicLinkKeys.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkKeys.js +129 -12
- 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 +27 -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/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/config.d.ts +906 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +59 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +35 -4
- 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 +6 -4
- package/dist/coreRoutes.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts +228 -0
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +1163 -6
- package/dist/generated/graphql-schemas/__mj.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 +27 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +50 -5
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +321 -132
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +4 -0
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +47 -7
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +157 -35
- 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 +87 -46
- 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/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -1
- package/dist/realtimeSessions/ownedRealtimeSession.js +2 -3
- package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -1
- package/dist/realtimeSessions/sessionAccess.d.ts +15 -0
- package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
- package/dist/realtimeSessions/sessionAccess.js +22 -0
- package/dist/realtimeSessions/sessionAccess.js.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.js +2 -0
- package/dist/realtimeWidget/WidgetSessionService.js.map +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.map +1 -1
- package/dist/realtimeWidget/widgetCore.js +4 -7
- package/dist/realtimeWidget/widgetCore.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +1 -0
- 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/AgentSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/AgentSessionResolver.js +6 -2
- 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/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/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 +2690 -1305
- 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/QuerySystemUserResolver.d.ts +36 -0
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +174 -87
- package/dist/resolvers/QuerySystemUserResolver.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 +6 -0
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +36 -5
- 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 +217 -34
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +24 -8
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +185 -67
- 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 +3 -1
- package/dist/resolvers/RunTemplateResolver.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/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/RealtimeRecordingHandler.d.ts +3 -3
- package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -1
- package/dist/rest/RealtimeRecordingHandler.js +2 -4
- package/dist/rest/RealtimeRecordingHandler.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +2 -1
- 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/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.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +1 -0
- 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 +17 -0
- 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__/ActiveOperations.test.ts +68 -0
- package/src/__tests__/AgentSessionResolver.ownership.test.ts +13 -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__/DeleteConnectionRemovesPerConnectionCatalog.test.ts +51 -0
- package/src/__tests__/DetachedDiscoveryStart.test.ts +65 -0
- package/src/__tests__/DurableEntityActionTaskSubmitter.test.ts +73 -0
- package/src/__tests__/EntityMapLifecycle.rekey.test.ts +252 -0
- package/src/__tests__/ExecuteRemoteOperationResolver.test.ts +213 -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__/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.permissions.test.ts +132 -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.test.ts +22 -0
- 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 +6 -4
- package/src/__tests__/RemoteBrowserAudioStream.test.ts +3 -0
- package/src/__tests__/RemoteBrowserSnapshot.test.ts +3 -0
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +323 -26
- package/src/__tests__/ResolverBase.encryptedApiZeroReencrypt.test.ts +307 -0
- package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +53 -2
- package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +60 -0
- package/src/__tests__/RunAIAgentResolver.branch.test.ts +4 -0
- package/src/__tests__/RunAIAgentResolver.consultPredecessor.test.ts +289 -0
- package/src/__tests__/RunAIAgentResolver.handoff.test.ts +649 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +2 -0
- package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +2 -0
- package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +87 -12
- 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 +69 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +2 -2
- package/src/__tests__/TaskGraphAgentRunner.test.ts +272 -16
- package/src/__tests__/ViewOperationsHandler.test.ts +2 -5
- package/src/__tests__/WorkQueueHostService.test.ts +25 -7
- package/src/__tests__/backgroundSweepConfigUnits.test.ts +153 -0
- package/src/__tests__/contextRequestOrigin.test.ts +105 -0
- package/src/__tests__/conversationBrowsers.test.ts +62 -0
- package/src/__tests__/magicLinkExtensionCapabilities.test.ts +413 -0
- package/src/__tests__/orphanedConversationDetailReconciler.start.test.ts +82 -0
- package/src/__tests__/ownedRealtimeSession.test.ts +14 -0
- package/src/__tests__/realtimeRecordingHandler.test.ts +7 -2
- package/src/__tests__/realtimeSessions/sessionAccess.test.ts +79 -1
- package/src/__tests__/requestOrigin.test.ts +104 -0
- package/src/__tests__/securityHardeningPr6034.test.ts +120 -0
- package/src/__tests__/sessionDeadline.test.ts +51 -0
- package/src/__tests__/sharedCache.test.ts +11 -0
- package/src/__tests__/unifiedAuth.test.ts +73 -1
- 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 +92 -42
- package/src/agentSessions/SessionManager.ts +38 -8
- package/src/agentSessions/conversationBrowsers.ts +143 -0
- package/src/agentSessions/sessionDeadline.ts +81 -0
- package/src/auth/APIKeyScopeAuth.ts +5 -4
- package/src/auth/__tests__/loginEmailResolution.test.ts +67 -0
- package/src/auth/loginEmailResolution.ts +67 -0
- package/src/auth/magicLink/MagicLinkKeys.ts +146 -14
- 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 +28 -3
- package/src/auth/newUsers.ts +1 -0
- package/src/backgroundSweepConfigUnits.ts +213 -0
- package/src/config.ts +69 -0
- package/src/context.ts +39 -6
- package/src/coreRoutes.ts +14 -7
- package/src/generated/graphql-schemas/__mj.ts +822 -7
- package/src/generic/OrphanedConversationDetailReconciler.ts +32 -1
- package/src/generic/ResolverBase.ts +414 -143
- package/src/generic/RunViewResolver.ts +96 -49
- package/src/index.ts +201 -35
- package/src/integration/ConnectionPause.ts +222 -0
- package/src/integration/CustomColumnPromoter.ts +123 -53
- 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/realtimeSessions/ownedRealtimeSession.ts +2 -6
- package/src/realtimeSessions/sessionAccess.ts +30 -0
- package/src/realtimeWidget/WidgetSessionService.ts +2 -0
- package/src/realtimeWidget/visitorIdentity.ts +1 -0
- package/src/realtimeWidget/widgetCore.ts +4 -8
- package/src/realtimeWidget/widgetGuestElevation.ts +1 -0
- package/src/requestOrigin.ts +64 -0
- package/src/resolvers/AgentSessionResolver.ts +6 -2
- package/src/resolvers/AutotagPipelineResolver.ts +2 -1
- package/src/resolvers/ConversationRunEventsResolver.ts +2 -0
- package/src/resolvers/ExecuteRemoteOperationResolver.ts +41 -9
- package/src/resolvers/GetDataResolver.ts +35 -13
- package/src/resolvers/IntegrationDiscoveryResolver.ts +1522 -203
- package/src/resolvers/MCPResolver.ts +15 -2
- package/src/resolvers/QuerySystemUserResolver.ts +197 -98
- package/src/resolvers/RealtimeBridgeResolver.ts +1 -0
- package/src/resolvers/RealtimeClientSessionResolver.ts +40 -7
- package/src/resolvers/RemoteBrowserActionResolver.ts +242 -32
- package/src/resolvers/RunAIAgentResolver.ts +265 -86
- package/src/resolvers/RunAIPromptResolver.ts +18 -18
- package/src/resolvers/RunTemplateResolver.ts +3 -1
- package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +52 -0
- package/src/resolvers/meetingRecordingRegistration.ts +2 -0
- package/src/rest/MediaAccessKeys.ts +6 -2
- package/src/rest/OAuthCallbackHandler.ts +13 -5
- package/src/rest/RealtimeRecordingHandler.ts +5 -9
- package/src/rest/ViewOperationsHandler.ts +2 -1
- package/src/rest/setupRESTEndpoints.ts +11 -2
- 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 +1 -0
- package/src/services/WorkQueueHostService.ts +26 -4
- package/src/services/workQueueConfig.ts +5 -5
- package/src/sharedCache.ts +1 -1
- package/src/types.ts +18 -0
- package/src/services/TaskOrchestration-Integration.md +0 -188
|
@@ -23,6 +23,8 @@ vi.mock('../../auth/index.js', () => ({ GetSystemUser: vi.fn(),
|
|
|
23
23
|
vi.mock('mssql', () => ({ default: { Request: vi.fn() } }));
|
|
24
24
|
|
|
25
25
|
import {
|
|
26
|
+
GetDataResolver,
|
|
27
|
+
GetDataInputType,
|
|
26
28
|
RegisterAccessToken,
|
|
27
29
|
DeleteAccessToken,
|
|
28
30
|
TokenExists,
|
|
@@ -31,6 +33,7 @@ import {
|
|
|
31
33
|
PruneExpiredTokens,
|
|
32
34
|
GetAccessTokenCount,
|
|
33
35
|
} from '../GetDataResolver.js';
|
|
36
|
+
import type { AppContext } from '../../types.js';
|
|
34
37
|
|
|
35
38
|
// ---------------------------------------------------------------------------
|
|
36
39
|
// Regression coverage for a memory leak (Memory Leak Audit Round 7, Critical):
|
|
@@ -137,4 +140,53 @@ describe('GetDataResolver access-token lifecycle', () => {
|
|
|
137
140
|
expect(GetAccessTokenCount()).toBeLessThan(before + 51);
|
|
138
141
|
expect(TokenExists(survivorToken)).toBe(true);
|
|
139
142
|
});
|
|
143
|
+
|
|
144
|
+
it('never leaks raw secret token values in thrown or returned error messages', async () => {
|
|
145
|
+
const duplicateSecret = `secret-dup-${uniqueToken()}`;
|
|
146
|
+
RegisterAccessToken(duplicateSecret, 60_000);
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
RegisterAccessToken(duplicateSecret, 60_000);
|
|
150
|
+
expect.unreachable('Expected duplicate registration to throw');
|
|
151
|
+
} catch (err) {
|
|
152
|
+
expect((err as Error).message).not.toContain(duplicateSecret);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const missingSecret = `secret-missing-${uniqueToken()}`;
|
|
156
|
+
try {
|
|
157
|
+
DeleteAccessToken(missingSecret);
|
|
158
|
+
expect.unreachable('Expected deleting unknown token to throw');
|
|
159
|
+
} catch (err) {
|
|
160
|
+
expect((err as Error).message).not.toContain(missingSecret);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
RecordTokenUse(missingSecret, {});
|
|
165
|
+
expect.unreachable('Expected recording unknown token use to throw');
|
|
166
|
+
} catch (err) {
|
|
167
|
+
expect((err as Error).message).not.toContain(missingSecret);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const resolver = new GetDataResolver();
|
|
171
|
+
const input = new GetDataInputType();
|
|
172
|
+
input.Token = missingSecret;
|
|
173
|
+
input.Queries = ['SELECT 1'];
|
|
174
|
+
const output = await resolver.GetData(input, { dataSources: [] } as Partial<AppContext> as AppContext);
|
|
175
|
+
expect(output.Success).toBe(false);
|
|
176
|
+
expect(JSON.stringify(output.ErrorMessages)).not.toContain(missingSecret);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('rejects empty tokens and near-miss prefix tokens across multiple active slots', () => {
|
|
180
|
+
const first = `slot-a-${uniqueToken()}`;
|
|
181
|
+
const second = `slot-b-${uniqueToken()}`;
|
|
182
|
+
RegisterAccessToken(first, 60_000);
|
|
183
|
+
RegisterAccessToken(second, 60_000);
|
|
184
|
+
|
|
185
|
+
expect(IsTokenValid('')).toBe(false);
|
|
186
|
+
expect(TokenExists('')).toBe(false);
|
|
187
|
+
expect(IsTokenValid(first.slice(0, -1))).toBe(false);
|
|
188
|
+
expect(IsTokenValid(`${second}-extra`)).toBe(false);
|
|
189
|
+
expect(IsTokenValid(first)).toBe(true);
|
|
190
|
+
expect(IsTokenValid(second)).toBe(true);
|
|
191
|
+
});
|
|
140
192
|
});
|
|
@@ -268,6 +268,7 @@ async function findConversationByEgressID(egressID: string, contextUser: UserInf
|
|
|
268
268
|
Fields: ['ID'],
|
|
269
269
|
OrderBy: '__mj_CreatedAt DESC',
|
|
270
270
|
MaxRows: 1,
|
|
271
|
+
SkipTotalRowCount: true,
|
|
271
272
|
ResultType: 'simple',
|
|
272
273
|
},
|
|
273
274
|
contextUser,
|
|
@@ -288,6 +289,7 @@ async function findConversationByRoomName(roomName: string, contextUser: UserInf
|
|
|
288
289
|
Fields: ['ID'],
|
|
289
290
|
OrderBy: '__mj_CreatedAt DESC',
|
|
290
291
|
MaxRows: 1,
|
|
292
|
+
SkipTotalRowCount: true,
|
|
291
293
|
ResultType: 'simple',
|
|
292
294
|
},
|
|
293
295
|
contextUser,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
import { BaseSingleton } from '@memberjunction/global';
|
|
20
20
|
import { LogStatus } from '@memberjunction/core';
|
|
21
|
-
import { randomBytes } from 'node:crypto';
|
|
21
|
+
import { createHmac, randomBytes } from 'node:crypto';
|
|
22
22
|
import jwt from 'jsonwebtoken';
|
|
23
23
|
|
|
24
24
|
/** The token's `typ` claim — the route rejects any token whose `typ` differs. */
|
|
@@ -78,7 +78,11 @@ export class MediaAccessKeyManager extends BaseSingleton<MediaAccessKeyManager>
|
|
|
78
78
|
}
|
|
79
79
|
const configured = process.env.MJ_BASE_ENCRYPTION_KEY?.trim();
|
|
80
80
|
if (configured) {
|
|
81
|
-
|
|
81
|
+
// Key separation: never sign tokens with the field-encryption master key itself. Derive a
|
|
82
|
+
// dedicated HS256 signing key (HKDF-style HMAC expand) so a token-signing compromise and the
|
|
83
|
+
// data-at-rest key stay decoupled. Tokens are short-lived, so changing the derivation only
|
|
84
|
+
// invalidates in-flight URLs, exactly like a restart on the ephemeral path below.
|
|
85
|
+
this.secret = createHmac('sha256', configured).update('mj-media-access-token-signing-v1').digest('base64');
|
|
82
86
|
} else {
|
|
83
87
|
this.secret = randomBytes(32).toString('base64');
|
|
84
88
|
LogStatus(
|
|
@@ -28,6 +28,15 @@ const ENTITY_MCP_SERVERS = 'MJ: MCP Servers';
|
|
|
28
28
|
/** Entity name for OAuth Authorization States */
|
|
29
29
|
const ENTITY_OAUTH_AUTHORIZATION_STATES = 'MJ: O Auth Authorization States';
|
|
30
30
|
|
|
31
|
+
const UUID_SHAPE = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
32
|
+
|
|
33
|
+
function sqlUuid(value: string, argName: string): string {
|
|
34
|
+
if (typeof value !== 'string' || !UUID_SHAPE.test(value)) {
|
|
35
|
+
throw new Error(`${argName} must be a UUID`);
|
|
36
|
+
}
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
|
|
31
40
|
/**
|
|
32
41
|
* Configuration for OAuth callback handler
|
|
33
42
|
*/
|
|
@@ -693,12 +702,11 @@ export class OAuthCallbackHandler {
|
|
|
693
702
|
const rv = new RunView();
|
|
694
703
|
|
|
695
704
|
// Get connection to get server ID.
|
|
696
|
-
// connectionId is caller-supplied (POST /oauth/initiate body)
|
|
697
|
-
//
|
|
698
|
-
// escaping used for stateParameter in loadAuthorizationState().
|
|
705
|
+
// connectionId is caller-supplied (POST /oauth/initiate body); enforce strict UUID shape
|
|
706
|
+
// (matching MCPResolver.getServerOAuthConfig) before interpolating into ExtraFilter.
|
|
699
707
|
const connResult = await rv.RunView<{ MCPServerID: string }>({
|
|
700
708
|
EntityName: ENTITY_MCP_SERVER_CONNECTIONS,
|
|
701
|
-
ExtraFilter: `ID='${connectionId
|
|
709
|
+
ExtraFilter: `ID='${sqlUuid(connectionId, 'connectionId')}'`,
|
|
702
710
|
Fields: ['MCPServerID'],
|
|
703
711
|
ResultType: 'simple'
|
|
704
712
|
}, contextUser);
|
|
@@ -719,7 +727,7 @@ export class OAuthCallbackHandler {
|
|
|
719
727
|
OAuthRequirePKCE: boolean | null;
|
|
720
728
|
}>({
|
|
721
729
|
EntityName: ENTITY_MCP_SERVERS,
|
|
722
|
-
ExtraFilter: `ID='${serverId}'`,
|
|
730
|
+
ExtraFilter: `ID='${sqlUuid(serverId, 'serverId')}'`,
|
|
723
731
|
Fields: [
|
|
724
732
|
'OAuthIssuerURL', 'OAuthScopes', 'OAuthMetadataCacheTTLMinutes',
|
|
725
733
|
'OAuthClientID', 'OAuthClientSecretEncrypted', 'OAuthRequirePKCE'
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
LoadOwnedRealtimeSession, RealtimeSessionNotFoundError, RealtimeSessionOwnershipError,
|
|
35
35
|
} from '../realtimeSessions/ownedRealtimeSession.js';
|
|
36
36
|
import type { IRecordingAssemblyScheduler } from '../realtimeSessions/RecordingAssemblyScheduler.js';
|
|
37
|
-
import {
|
|
37
|
+
import { AuthorizeLoadedSession } from '../realtimeSessions/sessionAccess.js';
|
|
38
38
|
|
|
39
39
|
/** Where {@link CreateRealtimeRecordingRouter} is mounted (under the reserved `/realtime` root). */
|
|
40
40
|
export const REALTIME_RECORDING_MOUNT_PATH = '/realtime/recording';
|
|
@@ -76,8 +76,8 @@ export interface RealtimeRecordingRouterDeps {
|
|
|
76
76
|
/** The authenticated caller, or null (answered 401). */
|
|
77
77
|
ResolveCaller(req: Request): RealtimeRecordingCaller | null;
|
|
78
78
|
LoadOwnedSession: typeof LoadOwnedRealtimeSession;
|
|
79
|
-
/** The session
|
|
80
|
-
|
|
79
|
+
/** The per-session scope rule of the access decision, applied to the session {@link LoadOwnedSession} returned. */
|
|
80
|
+
AuthorizeSession: typeof AuthorizeLoadedSession;
|
|
81
81
|
/** The ledger for one request; `contextUser` is the caller (used for logging by the procs). */
|
|
82
82
|
CreateLedger(provider: DatabaseProviderBase, contextUser: UserInfo): IRealtimeRecordingLedger;
|
|
83
83
|
Scheduler: IRecordingAssemblyScheduler;
|
|
@@ -258,7 +258,7 @@ async function handleTerminal(deps: RealtimeRecordingRouterDeps, req: Request, r
|
|
|
258
258
|
|
|
259
259
|
/**
|
|
260
260
|
* Loads the session through the shared ownership gate, then applies the per-session scope rule of
|
|
261
|
-
* {@link
|
|
261
|
+
* {@link AuthorizeLoadedSession}. The production gate (`LoadOwnedRealtimeSession`) already applies the same
|
|
262
262
|
* rule, so this is a deliberate second check at the HTTP boundary: `LoadOwnedSession` is an injected dependency,
|
|
263
263
|
* and without the scope rule one anonymous guest could write shards to another guest's recording (every guest
|
|
264
264
|
* shares the one Anonymous user), and a different-bytes shard would mark it Failed. It costs one extra
|
|
@@ -266,11 +266,7 @@ async function handleTerminal(deps: RealtimeRecordingRouterDeps, req: Request, r
|
|
|
266
266
|
*/
|
|
267
267
|
async function loadAuthorizedSession(deps: RealtimeRecordingRouterDeps, sessionID: string, caller: RealtimeRecordingCaller): Promise<MJAIAgentSessionEntity> {
|
|
268
268
|
const session = await deps.LoadOwnedSession(sessionID, caller.ContextUser, caller.Provider);
|
|
269
|
-
const
|
|
270
|
-
const decision = AuthorizeSessionAccess(
|
|
271
|
-
{ SessionUserID: session.UserID, ConversationExternalID: conversation.ExternalID, ConversationReadable: conversation.Readable },
|
|
272
|
-
caller.ContextUser,
|
|
273
|
-
);
|
|
269
|
+
const decision = await deps.AuthorizeSession(session, caller.ContextUser, caller.Provider);
|
|
274
270
|
if (decision.Allowed === false) {
|
|
275
271
|
LogError(`RealtimeRecordingHandler: refused user ${caller.ContextUser.ID} on session ${sessionID}: ${decision.Reason}`);
|
|
276
272
|
throw new RecordingRequestError(403, 'Not authorized for this realtime session');
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
BaseEntity, EntityInfo, LogError, Metadata, RunView, RunViewParams,
|
|
3
3
|
RunViewResult, UserInfo, type IRunViewProvider
|
|
4
4
|
} from '@memberjunction/core';
|
|
5
|
+
import { EscapeSQLString } from '@memberjunction/global';
|
|
5
6
|
import { ClientClauseScreen } from '@memberjunction/generic-database-provider';
|
|
6
7
|
import { ProjectRowsForCaller } from '../generic/fieldSecurityTransport.js';
|
|
7
8
|
|
|
@@ -163,7 +164,7 @@ export class ViewOperationsHandler {
|
|
|
163
164
|
// Run a view to get the available views
|
|
164
165
|
const params: RunViewParams = {
|
|
165
166
|
EntityName: 'MJ: User Views',
|
|
166
|
-
ExtraFilter: `Entity = '${
|
|
167
|
+
ExtraFilter: `Entity = '${EscapeSQLString(entity.Name)}'`
|
|
167
168
|
};
|
|
168
169
|
|
|
169
170
|
const runView = new RunView();
|
|
@@ -53,10 +53,12 @@ export interface RESTApiOptions {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
* Default REST API configuration
|
|
56
|
+
* Default REST API configuration. Disabled by default (matching the documented default and
|
|
57
|
+
* MJServer's own config default): mounting a full-entity REST API must be an explicit decision,
|
|
58
|
+
* never a side effect of calling SetupRESTEndpoints with no options.
|
|
57
59
|
*/
|
|
58
60
|
export const DEFAULT_REST_API_OPTIONS: RESTApiOptions = {
|
|
59
|
-
enabled:
|
|
61
|
+
enabled: false,
|
|
60
62
|
};
|
|
61
63
|
|
|
62
64
|
/**
|
|
@@ -95,6 +97,13 @@ export function SetupRESTEndpoints(
|
|
|
95
97
|
if (authMiddleware) {
|
|
96
98
|
app.use(basePath, BodyParser.json({ limit: '50mb' }), authMiddleware, restHandler.getRouter());
|
|
97
99
|
} else {
|
|
100
|
+
// MJServer itself is safe here (its unified auth middleware runs globally before this
|
|
101
|
+
// mount), but a third-party caller passing no authMiddleware may be mounting a fully
|
|
102
|
+
// UNauthenticated entity CRUD API — say so loudly.
|
|
103
|
+
LogStatusEx({
|
|
104
|
+
message: `REST API mounted at ${basePath} WITHOUT a route-level auth middleware. ` +
|
|
105
|
+
`Ensure an authentication middleware runs globally before this mount, or pass one to SetupRESTEndpoints.`,
|
|
106
|
+
});
|
|
98
107
|
app.use(basePath, BodyParser.json({ limit: '50mb' }), restHandler.getRouter());
|
|
99
108
|
}
|
|
100
109
|
|
|
@@ -15,7 +15,7 @@ import type {
|
|
|
15
15
|
DurableEntityActionSubmission,
|
|
16
16
|
DurableEntityActionSubmitter,
|
|
17
17
|
} from '@memberjunction/actions-base';
|
|
18
|
-
import { LogError } from '@memberjunction/core';
|
|
18
|
+
import { type IEntityDataProvider, type IMetadataProvider, LogError } from '@memberjunction/core';
|
|
19
19
|
import { TaskNode, type TaskGraphSpec } from '@memberjunction/ai-core-plus';
|
|
20
20
|
import { MJEnvironmentEntityExtended } from '@memberjunction/core-entities';
|
|
21
21
|
import { TaskGraphService, type ProviderFactory } from '@memberjunction/task-graph';
|
|
@@ -59,7 +59,9 @@ export class DurableEntityActionTaskSubmitter implements DurableEntityActionSubm
|
|
|
59
59
|
durable: true,
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
const provider =
|
|
62
|
+
const provider: IMetadataProvider = isMetadataProvider(request.Provider)
|
|
63
|
+
? request.Provider
|
|
64
|
+
: await this.providerFactory.CreateProvider();
|
|
63
65
|
const result = await new TaskGraphService().Submit(spec, {
|
|
64
66
|
EnvironmentID: this.environmentID,
|
|
65
67
|
ContextUser: request.ContextUser,
|
|
@@ -76,3 +78,9 @@ export class DurableEntityActionTaskSubmitter implements DurableEntityActionSubm
|
|
|
76
78
|
}
|
|
77
79
|
}
|
|
78
80
|
}
|
|
81
|
+
|
|
82
|
+
function isMetadataProvider(
|
|
83
|
+
provider: IMetadataProvider | IEntityDataProvider | undefined,
|
|
84
|
+
): provider is IMetadataProvider {
|
|
85
|
+
return !!provider && 'GetEntityObject' in provider && typeof provider.GetEntityObject === 'function';
|
|
86
|
+
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { ActionEngineServer } from '@memberjunction/actions';
|
|
13
13
|
import { ActionParam } from '@memberjunction/actions-base';
|
|
14
|
+
import { BuildActionOutputObject } from '@memberjunction/ai-core-plus';
|
|
14
15
|
import { LogError } from '@memberjunction/core';
|
|
15
16
|
import { UUIDsEqual } from '@memberjunction/global';
|
|
16
17
|
import type { TaskActionRunner, TaskActionRunParams, TaskActionRunResult } from '@memberjunction/task-graph';
|
|
@@ -97,29 +98,7 @@ export class TaskGraphActionRunner implements TaskActionRunner {
|
|
|
97
98
|
* produced.
|
|
98
99
|
*/
|
|
99
100
|
private buildOutput(actionParams: ActionParam[], resultMessage?: string | null): Record<string, unknown> {
|
|
100
|
-
|
|
101
|
-
if (typeof resultMessage === 'string') {
|
|
102
|
-
const trimmed = resultMessage.trim();
|
|
103
|
-
if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
|
|
104
|
-
try {
|
|
105
|
-
const parsed: unknown = JSON.parse(trimmed);
|
|
106
|
-
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
107
|
-
Object.assign(output, parsed as Record<string, unknown>);
|
|
108
|
-
}
|
|
109
|
-
} catch {
|
|
110
|
-
// Non-JSON prose message; ignore.
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
for (const p of actionParams ?? []) {
|
|
115
|
-
if (p.Type === 'Output' || p.Type === 'Both') output[p.Name] = p.Value;
|
|
116
|
-
}
|
|
117
|
-
if (typeof output.handle === 'string' && output.Handle === undefined) {
|
|
118
|
-
output.Handle = output.handle;
|
|
119
|
-
} else if (typeof output.Handle === 'string' && output.handle === undefined) {
|
|
120
|
-
output.handle = output.Handle;
|
|
121
|
-
}
|
|
122
|
-
return output;
|
|
101
|
+
return BuildActionOutputObject(actionParams, resultMessage);
|
|
123
102
|
}
|
|
124
103
|
|
|
125
104
|
/**
|
|
@@ -43,6 +43,25 @@ export class TaskGraphAgentRunner implements TaskAgentRunner {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
+
|
|
47
|
+
let configurationId: string | undefined;
|
|
48
|
+
const requestedPreset = params.ConfigurationPresetName?.trim();
|
|
49
|
+
if (requestedPreset) {
|
|
50
|
+
const matched = AIEngine.Instance.FindActiveAgentConfigurationPreset(agent.ID, requestedPreset);
|
|
51
|
+
if (!matched) {
|
|
52
|
+
const presets = AIEngine.Instance.GetAgentConfigurationPresets(agent.ID, true);
|
|
53
|
+
const available = presets.map((p) => p.Name).join(', ') || 'none';
|
|
54
|
+
return {
|
|
55
|
+
Success: false,
|
|
56
|
+
ErrorMessage: `Agent '${agent.Name || params.AgentID}' has no active preset '${requestedPreset}'. Available: ${available}.`,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
configurationId = matched.AIConfigurationID ?? undefined;
|
|
60
|
+
} else {
|
|
61
|
+
configurationId = parentRun?.ConfigurationID ?? undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const parentAgentHierarchy = this.buildParentAgentHierarchy(parentRun, params);
|
|
46
65
|
const taskContext = await this.resolveTaskContext(params);
|
|
47
66
|
const conversationDetailId =
|
|
48
67
|
parentRun?.ConversationDetailID ?? taskContext.conversationDetailId ?? undefined;
|
|
@@ -66,6 +85,8 @@ export class TaskGraphAgentRunner implements TaskAgentRunner {
|
|
|
66
85
|
// rather than starting the chain over. Without it MAX_REINVOKE_DEPTH never fires.
|
|
67
86
|
continuationDepth: params.ContinuationDepth ?? 0,
|
|
68
87
|
parentRun,
|
|
88
|
+
parentAgentHierarchy,
|
|
89
|
+
configurationId,
|
|
69
90
|
// The bridge from the agent's own progress stream up to graph-level observers: the
|
|
70
91
|
// dispatcher turns these into rate-limited `NodeProgress` frames, which is how a
|
|
71
92
|
// running Agent step shows "what it is doing right now" on the workflow canvas.
|
|
@@ -221,6 +242,28 @@ export class TaskGraphAgentRunner implements TaskAgentRunner {
|
|
|
221
242
|
}
|
|
222
243
|
}
|
|
223
244
|
|
|
245
|
+
/**
|
|
246
|
+
* Reads the root-first ancestor agent name hierarchy carried on the task from when its graph was
|
|
247
|
+
* submitted (`params.ParentAgentHierarchy`), falling back to the submitting run's own agent name
|
|
248
|
+
* when no hierarchy was persisted on the parent task.
|
|
249
|
+
*/
|
|
250
|
+
private buildParentAgentHierarchy(
|
|
251
|
+
parentRun: MJAIAgentRunEntityExtended | undefined,
|
|
252
|
+
params: TaskAgentRunParams,
|
|
253
|
+
): string[] | undefined {
|
|
254
|
+
if (Array.isArray(params.ParentAgentHierarchy)) {
|
|
255
|
+
const carried = params.ParentAgentHierarchy
|
|
256
|
+
.filter((name): name is string => typeof name === 'string')
|
|
257
|
+
.map((name) => name.trim())
|
|
258
|
+
.filter((name) => name.length > 0);
|
|
259
|
+
if (carried.length > 0) {
|
|
260
|
+
return carried;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
const submittingAgentName = parentRun?.Agent?.trim();
|
|
264
|
+
return submittingAgentName ? [submittingAgentName] : undefined;
|
|
265
|
+
}
|
|
266
|
+
|
|
224
267
|
/**
|
|
225
268
|
* Builds the agent's instruction from the task's name/description, its structured input payload,
|
|
226
269
|
* and its dependencies' outputs.
|
|
@@ -28,13 +28,25 @@ export interface StartableWorkQueueHost {
|
|
|
28
28
|
export interface WorkQueueHostStartDependencies {
|
|
29
29
|
Env: EnvironmentVariables;
|
|
30
30
|
FindUserByEmail(email: string): UserInfo | undefined;
|
|
31
|
+
FindSystemUser?(): UserInfo | undefined;
|
|
31
32
|
ConfigureEngine(user: UserInfo, provider: DatabaseProviderBase): Promise<WorkQueueEngine>;
|
|
32
33
|
CreateHost(config: WorkQueueHostConfig, engine: WorkQueueEngine, user: UserInfo, provider: DatabaseProviderBase, providerSource: WorkQueueProviderSource): StartableWorkQueueHost;
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
const DEFAULT_SYSTEM_USER_EMAILS = new Set(['system@memberjunction.org', 'not.set@nowhere.com']);
|
|
37
|
+
|
|
38
|
+
type IndependentProviderCapable = IMetadataProvider & {
|
|
39
|
+
CreateIndependentInstance(): Promise<IMetadataProvider>;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
function hasCreateIndependentInstance(provider: IMetadataProvider): provider is IndependentProviderCapable {
|
|
43
|
+
return 'CreateIndependentInstance' in provider && typeof provider.CreateIndependentInstance === 'function';
|
|
44
|
+
}
|
|
45
|
+
|
|
35
46
|
export const DEFAULT_WORK_QUEUE_HOST_START_DEPENDENCIES: WorkQueueHostStartDependencies = {
|
|
36
47
|
Env: process.env,
|
|
37
48
|
FindUserByEmail: email => UserCache.Users.find(user => user.Email?.trim().toLowerCase() === email.trim().toLowerCase()),
|
|
49
|
+
FindSystemUser: () => UserCache.Instance.GetSystemUser(),
|
|
38
50
|
ConfigureEngine: async (user, provider) => {
|
|
39
51
|
await WorkQueueEngine.Instance.Config(false, user, provider);
|
|
40
52
|
await ReportTopologyIssues(WorkQueueEngine.Instance);
|
|
@@ -89,7 +101,7 @@ export function BuildWorkQueueHostConfig(config: WorkQueueConfig, instanceID: st
|
|
|
89
101
|
};
|
|
90
102
|
}
|
|
91
103
|
|
|
92
|
-
/** A fresh SQL Server provider per delivery over the shared pool; the server provider otherwise. */
|
|
104
|
+
/** A fresh SQL Server or PostgreSQL provider per delivery over the shared pool; the server provider otherwise. */
|
|
93
105
|
export class MJServerWorkQueueProviderSource implements WorkQueueProviderSource {
|
|
94
106
|
private readonly factory: TaskGraphProviderFactory | null;
|
|
95
107
|
|
|
@@ -97,8 +109,14 @@ export class MJServerWorkQueueProviderSource implements WorkQueueProviderSource
|
|
|
97
109
|
this.factory = pool ? new TaskGraphProviderFactory(pool) : null;
|
|
98
110
|
}
|
|
99
111
|
|
|
100
|
-
public CreateProvider(): Promise<IMetadataProvider> {
|
|
101
|
-
|
|
112
|
+
public async CreateProvider(): Promise<IMetadataProvider> {
|
|
113
|
+
if (this.factory) {
|
|
114
|
+
return this.factory.CreateProvider();
|
|
115
|
+
}
|
|
116
|
+
if (hasCreateIndependentInstance(this.fallback)) {
|
|
117
|
+
return this.fallback.CreateIndependentInstance();
|
|
118
|
+
}
|
|
119
|
+
return this.fallback;
|
|
102
120
|
}
|
|
103
121
|
}
|
|
104
122
|
|
|
@@ -116,7 +134,11 @@ export async function StartWorkQueueHost(
|
|
|
116
134
|
LogStatus(`[WorkQueue] Host disabled by ${WORK_QUEUE_DISABLE_ENV}=1 — this process publishes but runs no subscriptions.`);
|
|
117
135
|
return null;
|
|
118
136
|
}
|
|
119
|
-
const
|
|
137
|
+
const configuredEmail = config.systemUserEmail?.trim() ?? '';
|
|
138
|
+
let user = configuredEmail ? dependencies.FindUserByEmail(configuredEmail) : undefined;
|
|
139
|
+
if (!user && (!configuredEmail || DEFAULT_SYSTEM_USER_EMAILS.has(configuredEmail.toLowerCase()))) {
|
|
140
|
+
user = dependencies.FindSystemUser?.();
|
|
141
|
+
}
|
|
120
142
|
if (!user) {
|
|
121
143
|
throw new Error(`[WorkQueue] System user not found with email: ${config.systemUserEmail} — set workQueue.systemUserEmail in mj.config.cjs`);
|
|
122
144
|
}
|
|
@@ -18,7 +18,7 @@ export const WorkQueueSubscriptionEntrySchema = z.object({
|
|
|
18
18
|
*/
|
|
19
19
|
export const WorkQueueSchema = z
|
|
20
20
|
.object({
|
|
21
|
-
enabled: z.boolean().optional().default(
|
|
21
|
+
enabled: z.boolean().optional().default(true),
|
|
22
22
|
systemUserEmail: z.string().optional().default('system@memberjunction.org'),
|
|
23
23
|
subscriptions: z.array(WorkQueueSubscriptionEntrySchema).optional().default([{ name: '*', concurrency: 4 }]),
|
|
24
24
|
idlePollMinMs: z.number().int().positive().optional().default(250),
|
|
@@ -36,12 +36,12 @@ export const WorkQueueSchema = z
|
|
|
36
36
|
export type WorkQueueConfig = z.infer<typeof WorkQueueSchema>;
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* The merge base for mj.config.cjs.
|
|
40
|
-
*
|
|
39
|
+
* The merge base for mj.config.cjs. Enabled by default with the Database transport out of the box; StartWorkQueueHost
|
|
40
|
+
* resolves `systemUserEmail` first and falls back to `UserCache.Instance.GetSystemUser()` when the default is unchanged.
|
|
41
41
|
*/
|
|
42
42
|
export const DEFAULT_WORK_QUEUE_CONFIG: WorkQueueConfig = {
|
|
43
|
-
enabled:
|
|
44
|
-
systemUserEmail: '
|
|
43
|
+
enabled: true,
|
|
44
|
+
systemUserEmail: 'system@memberjunction.org',
|
|
45
45
|
subscriptions: [{ name: '*', concurrency: 4 }],
|
|
46
46
|
idlePollMinMs: 250,
|
|
47
47
|
idlePollMaxMs: 5000,
|
package/src/sharedCache.ts
CHANGED
|
@@ -238,7 +238,7 @@ function relayRunViewChangeToBrowsers(event: CacheChangedEvent): void {
|
|
|
238
238
|
PubSubManager.Instance.Publish(CACHE_INVALIDATION_TOPIC, {
|
|
239
239
|
entityName,
|
|
240
240
|
primaryKeyValues: null, // entity-level invalidation
|
|
241
|
-
action: event.Action,
|
|
241
|
+
action: event.Action === 'row_delta' ? 'set' : event.Action,
|
|
242
242
|
sourceServerId: event.SourceServerId || 'unknown',
|
|
243
243
|
timestamp: new Date(),
|
|
244
244
|
});
|
package/src/types.ts
CHANGED
|
@@ -73,6 +73,19 @@ export type AppContext = {
|
|
|
73
73
|
* Used only to key abuse limits (e.g. realtime verification sends) — never as an identity.
|
|
74
74
|
*/
|
|
75
75
|
ClientIp?: string;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The request's `Origin` header as a normalized origin — scheme, host and port, lowercased, no
|
|
79
|
+
* trailing slash (e.g. `https://app.example.com:8443`). Normalized by `NormalizeOrigin`, the same
|
|
80
|
+
* helper the realtime widget allowlist uses, so it compares to allowlist entries normalized the
|
|
81
|
+
* same way with plain string equality. Ports are kept as sent; browsers omit default ports.
|
|
82
|
+
*
|
|
83
|
+
* Undefined when the request sent no `Origin` (server-to-server calls, many same-origin GETs),
|
|
84
|
+
* sent the opaque `null` origin, or sent a value that is not an http(s) origin. Always absent on
|
|
85
|
+
* WebSocket (subscription) contexts. Treat undefined as "origin unknown": an allowlist check
|
|
86
|
+
* must fail closed on it.
|
|
87
|
+
*/
|
|
88
|
+
RequestOrigin?: string;
|
|
76
89
|
};
|
|
77
90
|
|
|
78
91
|
export class ProviderInfo {
|
|
@@ -145,6 +158,11 @@ export type RunViewGenericParams = {
|
|
|
145
158
|
* Propagated to `RunViewParams.IncludeBinaryFields`.
|
|
146
159
|
*/
|
|
147
160
|
includeBinaryFields?: boolean;
|
|
161
|
+
/**
|
|
162
|
+
* When true, no count runs to populate `TotalRowCount`, which comes back undefined.
|
|
163
|
+
* Propagated to `RunViewParams.SkipTotalRowCount`.
|
|
164
|
+
*/
|
|
165
|
+
skipTotalRowCount?: boolean;
|
|
148
166
|
/**
|
|
149
167
|
* Optional registered Alternate Base View logical Name (from `EntityAlternateBaseView.Name`)
|
|
150
168
|
* for this entity. Propagated to `RunViewParams.AlternateBaseView`.
|