@memberjunction/server 6.2.0-edge.0 → 6.2.0-edge.2
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/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/ReturningVisitorRecap.d.ts +2 -0
- package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
- package/dist/agentSessions/ReturningVisitorRecap.js +5 -1
- package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
- package/dist/agentSessions/SessionManager.js +2 -2
- package/dist/agentSessions/remoteBrowserGoalEngine.d.ts +8 -0
- package/dist/agentSessions/remoteBrowserGoalEngine.d.ts.map +1 -1
- package/dist/agentSessions/remoteBrowserGoalEngine.js +21 -5
- package/dist/agentSessions/remoteBrowserGoalEngine.js.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.d.ts +2 -0
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.js +5 -1
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
- package/dist/auth/index.d.ts +20 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +20 -10
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +8 -0
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +21 -5
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.d.ts +9 -0
- package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +22 -10
- package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.d.ts +17 -15
- package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +65 -51
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/magicLink/index.d.ts +2 -2
- package/dist/auth/magicLink/index.d.ts.map +1 -1
- package/dist/auth/magicLink/index.js +2 -2
- package/dist/auth/magicLink/index.js.map +1 -1
- package/dist/auth/magicLink/magicLinkCore.d.ts +54 -33
- package/dist/auth/magicLink/magicLinkCore.d.ts.map +1 -1
- package/dist/auth/magicLink/magicLinkCore.js +61 -61
- package/dist/auth/magicLink/magicLinkCore.js.map +1 -1
- package/dist/auth/magicLink/redeemLanding.d.ts +4 -0
- package/dist/auth/magicLink/redeemLanding.d.ts.map +1 -1
- package/dist/auth/magicLink/redeemLanding.js +12 -4
- package/dist/auth/magicLink/redeemLanding.js.map +1 -1
- package/dist/auth/magicLink/types.d.ts +4 -4
- package/dist/auth/principals.d.ts +2 -0
- package/dist/auth/principals.d.ts.map +1 -1
- package/dist/auth/principals.js +6 -2
- package/dist/auth/principals.js.map +1 -1
- package/dist/cache.d.ts +2 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +3 -1
- package/dist/cache.js.map +1 -1
- package/dist/config.d.ts +346 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +34 -4
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +20 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +27 -19
- package/dist/context.js.map +1 -1
- package/dist/directives/Public.d.ts +2 -0
- package/dist/directives/Public.d.ts.map +1 -1
- package/dist/directives/Public.js +3 -1
- package/dist/directives/Public.js.map +1 -1
- package/dist/directives/RequireSystemUser.d.ts +2 -0
- package/dist/directives/RequireSystemUser.d.ts.map +1 -1
- package/dist/directives/RequireSystemUser.js +3 -1
- package/dist/directives/RequireSystemUser.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts +1021 -0
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +7368 -2145
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +94 -4
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +122 -3
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/DeleteOptionsInput.d.ts +8 -1
- package/dist/generic/DeleteOptionsInput.d.ts.map +1 -1
- package/dist/generic/DeleteOptionsInput.js +1 -1
- package/dist/generic/DeleteOptionsInput.js.map +1 -1
- package/dist/generic/FireAndForgetHeartbeat.d.ts +18 -2
- package/dist/generic/FireAndForgetHeartbeat.d.ts.map +1 -1
- package/dist/generic/FireAndForgetHeartbeat.js +24 -6
- package/dist/generic/FireAndForgetHeartbeat.js.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts +31 -0
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -0
- package/dist/generic/OrphanedConversationDetailReconciler.js +215 -0
- package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -0
- package/dist/generic/PushStatusResolver.d.ts +48 -1
- package/dist/generic/PushStatusResolver.d.ts.map +1 -1
- package/dist/generic/PushStatusResolver.js +95 -4
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +18 -2
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +64 -55
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +120 -11
- package/dist/index.js.map +1 -1
- package/dist/integration/CustomColumnPromoter.d.ts +2 -0
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +5 -1
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/integration/EntityMapLifecycle.d.ts +4 -0
- package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
- package/dist/integration/EntityMapLifecycle.js +10 -2
- package/dist/integration/EntityMapLifecycle.js.map +1 -1
- package/dist/logging/NoLog.d.ts +4 -0
- package/dist/logging/NoLog.d.ts.map +1 -1
- package/dist/logging/NoLog.js +10 -2
- package/dist/logging/NoLog.js.map +1 -1
- package/dist/logging/StartupLogger.d.ts +2 -0
- package/dist/logging/StartupLogger.d.ts.map +1 -1
- package/dist/logging/StartupLogger.js +5 -1
- package/dist/logging/StartupLogger.js.map +1 -1
- package/dist/logging/bootAudit.d.ts +11 -7
- package/dist/logging/bootAudit.d.ts.map +1 -1
- package/dist/logging/bootAudit.js +15 -7
- package/dist/logging/bootAudit.js.map +1 -1
- package/dist/logging/boundaryLogPayload.d.ts +4 -0
- package/dist/logging/boundaryLogPayload.d.ts.map +1 -1
- package/dist/logging/boundaryLogPayload.js +5 -1
- package/dist/logging/boundaryLogPayload.js.map +1 -1
- package/dist/logging/secretRedactor.d.ts +2 -0
- package/dist/logging/secretRedactor.d.ts.map +1 -1
- package/dist/logging/secretRedactor.js +8 -4
- package/dist/logging/secretRedactor.js.map +1 -1
- package/dist/logging/shortenForLog.d.ts +2 -0
- package/dist/logging/shortenForLog.d.ts.map +1 -1
- package/dist/logging/shortenForLog.js +7 -3
- package/dist/logging/shortenForLog.js.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.d.ts +2 -0
- package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.js +8 -6
- package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
- package/dist/metadataRefreshSignal.d.ts +19 -0
- package/dist/metadataRefreshSignal.d.ts.map +1 -0
- package/dist/metadataRefreshSignal.js +45 -0
- package/dist/metadataRefreshSignal.js.map +1 -0
- package/dist/middleware/MJTenantFilterMiddleware.js +4 -4
- package/dist/multiTenancy/index.d.ts +8 -0
- package/dist/multiTenancy/index.d.ts.map +1 -1
- package/dist/multiTenancy/index.js +21 -5
- package/dist/multiTenancy/index.js.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.d.ts +5 -0
- package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.js +14 -10
- package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts +6 -6
- package/dist/realtimeWidget/WidgetSessionService.js +27 -27
- package/dist/realtimeWidget/host-identity.d.ts +5 -1
- package/dist/realtimeWidget/host-identity.d.ts.map +1 -1
- package/dist/realtimeWidget/host-identity.js +11 -3
- package/dist/realtimeWidget/host-identity.js.map +1 -1
- package/dist/realtimeWidget/index.d.ts +2 -2
- package/dist/realtimeWidget/index.d.ts.map +1 -1
- package/dist/realtimeWidget/index.js +2 -2
- package/dist/realtimeWidget/index.js.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.d.ts +21 -1
- package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.js +16 -4
- package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
- package/dist/realtimeWidget/widgetCore.d.ts +48 -0
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetCore.js +38 -10
- package/dist/realtimeWidget/widgetCore.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.d.ts +10 -6
- package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +14 -6
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.js +3 -3
- package/dist/resolvers/AgentRunStatusPublisher.d.ts +55 -0
- package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -0
- package/dist/resolvers/AgentRunStatusPublisher.js +141 -0
- package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -0
- package/dist/resolvers/ConversationRunEventsResolver.d.ts +90 -0
- package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -0
- package/dist/resolvers/ConversationRunEventsResolver.js +283 -0
- package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -0
- package/dist/resolvers/DuplicateEntryCheckResolver.d.ts +98 -0
- package/dist/resolvers/DuplicateEntryCheckResolver.d.ts.map +1 -0
- package/dist/resolvers/DuplicateEntryCheckResolver.js +227 -0
- package/dist/resolvers/DuplicateEntryCheckResolver.js.map +1 -0
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js +2 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.js +3 -3
- package/dist/resolvers/GeoResolver.d.ts +2 -2
- package/dist/resolvers/GeoResolver.js +4 -4
- package/dist/resolvers/GetDataResolver.d.ts +14 -0
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +43 -15
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +2 -2
- package/dist/resolvers/ListOperationsResolver.d.ts +20 -0
- package/dist/resolvers/ListOperationsResolver.d.ts.map +1 -1
- package/dist/resolvers/ListOperationsResolver.js +68 -28
- package/dist/resolvers/ListOperationsResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts +11 -1
- package/dist/resolvers/MCPResolver.d.ts.map +1 -1
- package/dist/resolvers/MCPResolver.js +7 -3
- package/dist/resolvers/MCPResolver.js.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts +7 -0
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +16 -2
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +3 -3
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +44 -6
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +93 -37
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +5 -5
- package/dist/resolvers/RunAIAgentResolver.d.ts +8 -18
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +85 -184
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +2 -2
- package/dist/resolvers/RunDecisionResolver.d.ts +149 -0
- package/dist/resolvers/RunDecisionResolver.d.ts.map +1 -0
- package/dist/resolvers/RunDecisionResolver.js +396 -0
- package/dist/resolvers/RunDecisionResolver.js.map +1 -0
- package/dist/resolvers/RunTestResolver.js +5 -5
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts +8 -4
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +5 -5
- package/dist/resolvers/TaskGraphFrameResolver.d.ts +8 -1
- package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.js +6 -2
- package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
- package/dist/resolvers/VectorizeEntityResolver.d.ts +1 -1
- package/dist/resolvers/VectorizeEntityResolver.d.ts.map +1 -1
- package/dist/resolvers/VectorizeEntityResolver.js +14 -10
- package/dist/resolvers/VectorizeEntityResolver.js.map +1 -1
- package/dist/resolvers/adhoc-query-helpers.d.ts +6 -0
- package/dist/resolvers/adhoc-query-helpers.d.ts.map +1 -1
- package/dist/resolvers/adhoc-query-helpers.js +10 -2
- package/dist/resolvers/adhoc-query-helpers.js.map +1 -1
- package/dist/resolvers/artifact-routing.d.ts +8 -8
- package/dist/resolvers/artifact-routing.js +2 -2
- package/dist/resolvers/artifact-routing.js.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.d.ts +10 -2
- package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.js +24 -8
- package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
- package/dist/resolvers/peaksSidecar.d.ts +4 -0
- package/dist/resolvers/peaksSidecar.d.ts.map +1 -1
- package/dist/resolvers/peaksSidecar.js +10 -2
- package/dist/resolvers/peaksSidecar.js.map +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts +28 -0
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +20 -4
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/MediaStreamHandler.d.ts +2 -0
- package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
- package/dist/rest/MediaStreamHandler.js +10 -6
- package/dist/rest/MediaStreamHandler.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts +9 -0
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
- package/dist/rest/OAuthCallbackHandler.js +15 -3
- package/dist/rest/OAuthCallbackHandler.js.map +1 -1
- package/dist/rest/RESTEndpointHandler.d.ts +6 -4
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +15 -11
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/RealtimeSdpBrokerHandler.d.ts +5 -1
- package/dist/rest/RealtimeSdpBrokerHandler.d.ts.map +1 -1
- package/dist/rest/RealtimeSdpBrokerHandler.js +12 -4
- package/dist/rest/RealtimeSdpBrokerHandler.js.map +1 -1
- package/dist/rest/SignatureWebhookHandler.d.ts +2 -0
- package/dist/rest/SignatureWebhookHandler.d.ts.map +1 -1
- package/dist/rest/SignatureWebhookHandler.js +5 -1
- package/dist/rest/SignatureWebhookHandler.js.map +1 -1
- package/dist/rest/UploadTokenManager.d.ts +24 -8
- package/dist/rest/UploadTokenManager.d.ts.map +1 -1
- package/dist/rest/UploadTokenManager.js +53 -21
- package/dist/rest/UploadTokenManager.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +20 -0
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +20 -4
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/mediaRange.d.ts +4 -0
- package/dist/rest/mediaRange.d.ts.map +1 -1
- package/dist/rest/mediaRange.js +10 -2
- package/dist/rest/mediaRange.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +4 -0
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +13 -7
- package/dist/rest/setupRESTEndpoints.js.map +1 -1
- package/dist/serverExtensionReservedRoots.d.ts +2 -0
- package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
- package/dist/serverExtensionReservedRoots.js +5 -1
- package/dist/serverExtensionReservedRoots.js.map +1 -1
- package/dist/services/TaskGraphActionRunner.d.ts +13 -8
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphActionRunner.js +16 -15
- package/dist/services/TaskGraphActionRunner.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +7 -3
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +6 -0
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +13 -5
- package/dist/util.js.map +1 -1
- package/package.json +94 -92
- package/src/__tests__/AgentRunStatusPublisher.test.ts +175 -0
- package/src/__tests__/DeleteOptionsInput.wireShape.test.ts +62 -0
- package/src/__tests__/DuplicateEntryCheckResolver.test.ts +300 -0
- package/src/__tests__/FileResolverPeaks.test.ts +13 -13
- package/src/__tests__/ListOperationsResolver.test.ts +17 -17
- package/src/__tests__/MediaStreamHandler.test.ts +28 -28
- package/src/__tests__/NoLog.test.ts +11 -11
- package/src/__tests__/PrimaryKeyAlwaysMapped.test.ts +10 -10
- package/src/__tests__/RESTEndpointHandler.test.ts +14 -14
- package/src/__tests__/RealtimeBridgeResolver.test.ts +4 -2
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +216 -2
- package/src/__tests__/RealtimeSdpBrokerHandler.test.ts +6 -6
- package/src/__tests__/RefreshAdoptsNewColumns.test.ts +8 -8
- package/src/__tests__/RemoteBrowserActionRecovery.test.ts +7 -1
- package/src/__tests__/RemoteBrowserAudioStream.test.ts +7 -1
- package/src/__tests__/RemoteBrowserGoalEngine.test.ts +18 -18
- package/src/__tests__/RemoteBrowserSnapshot.test.ts +7 -1
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +52 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +398 -0
- package/src/__tests__/RunAIAgentResolver.streaming.test.ts +18 -27
- package/src/__tests__/RunDecisionResolver.test.ts +699 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +131 -0
- package/src/__tests__/TaskGraphFrameResolver.test.ts +2 -2
- package/src/__tests__/VectorizeEntityResolver.test.ts +106 -0
- package/src/__tests__/WidgetSessionService.test.ts +8 -4
- package/src/__tests__/adhoc-query-helpers.test.ts +21 -21
- package/src/__tests__/bootAudit.test.ts +11 -11
- package/src/__tests__/boundaryLogPayload.test.ts +6 -6
- package/src/__tests__/cacheInvalidationRecordData.test.ts +177 -0
- package/src/__tests__/conversationRunEvents.test.ts +399 -0
- package/src/__tests__/databaseAbstraction.test.ts +12 -6
- package/src/__tests__/getDataTokenRedaction.test.ts +7 -7
- package/src/__tests__/initializeProviders.refresh.test.ts +4 -4
- package/src/__tests__/magicLink.test.ts +73 -134
- package/src/__tests__/magicLinkService.consume.test.ts +224 -0
- package/src/__tests__/meetingRecordingRegistration.test.ts +12 -12
- package/src/__tests__/metadataRefreshSignal.test.ts +78 -0
- package/src/__tests__/multiTenancy.security.test.ts +40 -40
- package/src/__tests__/multiTenancy.test.ts +18 -18
- package/src/__tests__/newUsers.test.ts +24 -23
- package/src/__tests__/orphanedConversationDetailReconciler.test.ts +283 -0
- package/src/__tests__/principals.test.ts +22 -22
- package/src/__tests__/pushStatusFanOut.test.ts +206 -0
- package/src/__tests__/pushStatusResolver.filter.test.ts +8 -8
- package/src/__tests__/secretRedactor.failOpen.test.ts +12 -12
- package/src/__tests__/secretRedactor.test.ts +12 -12
- package/src/__tests__/serverExtensionReservedRoots.test.ts +7 -7
- package/src/__tests__/subscriptionRedaction.test.ts +5 -5
- package/src/__tests__/unifiedAuth.test.ts +15 -9
- package/src/__tests__/visitorIdentity.resolve.test.ts +6 -6
- package/src/__tests__/widget.test.ts +45 -45
- package/src/__tests__/widgetGuestElevation.test.ts +7 -7
- package/src/__tests__/widgetHostIdentity.test.ts +14 -14
- package/src/agentSessions/ReturningVisitorRecap.ts +12 -1
- package/src/agentSessions/SessionManager.ts +2 -2
- package/src/agentSessions/remoteBrowserGoalEngine.ts +30 -5
- package/src/auth/AuthProviderCatalogRouter.ts +6 -1
- package/src/auth/__tests__/backward-compatibility.test.ts +4 -3
- package/src/auth/index.ts +43 -28
- package/src/auth/initializeProviders.ts +25 -5
- package/src/auth/magicLink/MagicLinkRouter.ts +28 -10
- package/src/auth/magicLink/MagicLinkService.ts +71 -52
- package/src/auth/magicLink/index.ts +7 -7
- package/src/auth/magicLink/magicLinkCore.ts +96 -64
- package/src/auth/magicLink/redeemLanding.ts +14 -4
- package/src/auth/magicLink/types.ts +54 -54
- package/src/auth/newUsers.ts +1 -1
- package/src/auth/principals.ts +11 -2
- package/src/cache.ts +4 -1
- package/src/config.ts +37 -4
- package/src/context.ts +37 -24
- package/src/directives/Public.ts +4 -1
- package/src/directives/RequireSystemUser.ts +4 -1
- package/src/generated/graphql-schemas/__mj.ts +3674 -4
- package/src/generic/CacheInvalidationResolver.ts +148 -4
- package/src/generic/DeleteOptionsInput.ts +9 -2
- package/src/generic/FireAndForgetHeartbeat.ts +35 -16
- package/src/generic/OrphanedConversationDetailReconciler.ts +267 -0
- package/src/generic/PushStatusResolver.ts +118 -8
- package/src/generic/ResolverBase.ts +65 -57
- package/src/generic/RunViewResolver.ts +22 -22
- package/src/generic/__tests__/FireAndForgetHeartbeat.test.ts +7 -7
- package/src/index.ts +137 -11
- package/src/integration/CustomColumnPromoter.ts +6 -1
- package/src/integration/EntityMapLifecycle.ts +20 -2
- package/src/logging/NoLog.ts +16 -2
- package/src/logging/StartupLogger.ts +6 -1
- package/src/logging/bootAudit.ts +26 -16
- package/src/logging/boundaryLogPayload.ts +8 -1
- package/src/logging/secretRedactor.ts +14 -9
- package/src/logging/shortenForLog.ts +8 -3
- package/src/logging/variablesLoggingMiddleware.ts +9 -6
- package/src/metadataRefreshSignal.ts +45 -0
- package/src/middleware/MJTenantFilterMiddleware.ts +4 -4
- package/src/multiTenancy/index.ts +29 -5
- package/src/realtimeWidget/WidgetRouter.ts +15 -10
- package/src/realtimeWidget/WidgetSessionService.ts +76 -76
- package/src/realtimeWidget/host-identity.ts +24 -10
- package/src/realtimeWidget/index.ts +3 -3
- package/src/realtimeWidget/visitorIdentity.ts +39 -8
- package/src/realtimeWidget/widgetCore.ts +75 -10
- package/src/realtimeWidget/widgetGuestElevation.ts +25 -12
- package/src/resolvers/AdhocQueryResolver.ts +3 -3
- package/src/resolvers/AgentRunStatusPublisher.ts +175 -0
- package/src/resolvers/AgentSessionResolver.ts +3 -3
- package/src/resolvers/ColorResolver.ts +6 -6
- package/src/resolvers/ComponentRegistryResolver.ts +36 -36
- package/src/resolvers/ConversationRunEventsResolver.ts +308 -0
- package/src/resolvers/DuplicateEntryCheckResolver.ts +232 -0
- package/src/resolvers/EntityCommunicationsResolver.ts +4 -4
- package/src/resolvers/ExecuteRemoteOperationResolver.ts +9 -9
- package/src/resolvers/FetchEntityVectorsResolver.ts +2 -1
- package/src/resolvers/FileResolver.ts +42 -42
- package/src/resolvers/GeoResolver.ts +4 -4
- package/src/resolvers/GetDataResolver.ts +50 -15
- package/src/resolvers/IntegrationDiscoveryResolver.ts +2 -2
- package/src/resolvers/ListOperationsResolver.ts +78 -28
- package/src/resolvers/MCPResolver.ts +30 -15
- package/src/resolvers/MergeRecordsResolver.ts +14 -2
- package/src/resolvers/QueryResolver.ts +13 -13
- package/src/resolvers/RealtimeBridgeResolver.ts +3 -3
- package/src/resolvers/RealtimeClientSessionResolver.ts +96 -38
- package/src/resolvers/RemoteBrowserActionResolver.ts +5 -5
- package/src/resolvers/RunAIAgentResolver.ts +134 -239
- package/src/resolvers/RunAIPromptResolver.ts +22 -22
- package/src/resolvers/RunDecisionResolver.ts +435 -0
- package/src/resolvers/RunTemplateResolver.ts +4 -4
- package/src/resolvers/RunTestResolver.ts +25 -25
- package/src/resolvers/SqlLoggingConfigResolver.ts +56 -56
- package/src/resolvers/TaskGraphFrameResolver.ts +37 -28
- package/src/resolvers/TelemetryResolver.ts +79 -79
- package/src/resolvers/VectorizeEntityResolver.ts +16 -11
- package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +40 -38
- package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +93 -0
- package/src/resolvers/__tests__/artifact-routing.test.ts +23 -23
- package/src/resolvers/adhoc-query-helpers.ts +19 -2
- package/src/resolvers/artifact-routing.ts +19 -19
- package/src/resolvers/meetingRecordingRegistration.ts +44 -10
- package/src/resolvers/peaksSidecar.ts +12 -2
- package/src/rest/EntityCRUDHandler.ts +24 -4
- package/src/rest/MediaStreamHandler.ts +11 -6
- package/src/rest/OAuthCallbackHandler.ts +25 -7
- package/src/rest/RESTEndpointHandler.ts +20 -15
- package/src/rest/RealtimeSdpBrokerHandler.ts +14 -4
- package/src/rest/SignatureWebhookHandler.ts +6 -1
- package/src/rest/UploadTokenManager.ts +66 -30
- package/src/rest/ViewOperationsHandler.ts +24 -4
- package/src/rest/mediaRange.ts +16 -6
- package/src/rest/setupRESTEndpoints.ts +24 -12
- package/src/serverExtensionReservedRoots.ts +6 -1
- package/src/services/TaskGraphActionRunner.ts +16 -15
- package/src/types.ts +21 -16
- package/src/util.ts +16 -6
|
@@ -5,11 +5,11 @@ import { MJComputerUseEngine, MJRunComputerUseParams } from '@memberjunction/com
|
|
|
5
5
|
import { CdpRemoteBrowserSession, type ComputerUseGoalRun } from '@memberjunction/remote-browser-cdp';
|
|
6
6
|
import type { MJAIAgentRunStepEntity } from '@memberjunction/core-entities';
|
|
7
7
|
import {
|
|
8
|
-
|
|
8
|
+
BuildMJGoalParams,
|
|
9
9
|
BindRemoteBrowserGoalEngine,
|
|
10
10
|
MJProgressComputerUseEngine,
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
ExtractCoAgentRunID,
|
|
12
|
+
FinalizeBrowserGoalStep,
|
|
13
13
|
} from '../agentSessions/remoteBrowserGoalEngine.js';
|
|
14
14
|
|
|
15
15
|
const USER = { ID: 'u-1', Email: 'amith@bluecypress.io' } as unknown as UserInfo;
|
|
@@ -21,7 +21,7 @@ function baseParams(): RunComputerUseParams {
|
|
|
21
21
|
|
|
22
22
|
describe('buildMJGoalParams', () => {
|
|
23
23
|
it('produces MJ-aware params that carry over the base goal/step/url fields', () => {
|
|
24
|
-
const mj =
|
|
24
|
+
const mj = BuildMJGoalParams(baseParams(), USER);
|
|
25
25
|
expect(mj).toBeInstanceOf(MJRunComputerUseParams);
|
|
26
26
|
expect(mj.Goal).toBe('log in');
|
|
27
27
|
expect(mj.MaxSteps).toBe(7);
|
|
@@ -29,21 +29,21 @@ describe('buildMJGoalParams', () => {
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
it('injects the acting ContextUser so MJ prompts run as that user', () => {
|
|
32
|
-
expect(
|
|
32
|
+
expect(BuildMJGoalParams(baseParams(), USER).ContextUser).toBe(USER);
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
it('leaves ContextUser undefined when none is supplied', () => {
|
|
36
|
-
expect(
|
|
36
|
+
expect(BuildMJGoalParams(baseParams()).ContextUser).toBeUndefined();
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
it('threads the parent run + step ids for observability nesting', () => {
|
|
40
|
-
const mj =
|
|
40
|
+
const mj = BuildMJGoalParams(baseParams(), USER, 'coagent-run-1', 'goal-step-1');
|
|
41
41
|
expect(mj.AgentRunId).toBe('coagent-run-1');
|
|
42
42
|
expect(mj.AgentRunStepID).toBe('goal-step-1');
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
it('leaves the run/step ids undefined when not supplied', () => {
|
|
46
|
-
const mj =
|
|
46
|
+
const mj = BuildMJGoalParams(baseParams(), USER);
|
|
47
47
|
expect(mj.AgentRunId).toBeUndefined();
|
|
48
48
|
expect(mj.AgentRunStepID).toBeUndefined();
|
|
49
49
|
});
|
|
@@ -51,17 +51,17 @@ describe('buildMJGoalParams', () => {
|
|
|
51
51
|
|
|
52
52
|
describe('extractCoAgentRunID', () => {
|
|
53
53
|
it('pulls coAgentRunID out of a session Config_ blob', () => {
|
|
54
|
-
expect(
|
|
54
|
+
expect(ExtractCoAgentRunID(JSON.stringify({ coAgentRunID: 'run-9', promptRunID: 'p' }))).toBe('run-9');
|
|
55
55
|
});
|
|
56
56
|
it('returns undefined for a missing key, null/empty config, or non-string value', () => {
|
|
57
|
-
expect(
|
|
58
|
-
expect(
|
|
59
|
-
expect(
|
|
60
|
-
expect(
|
|
61
|
-
expect(
|
|
57
|
+
expect(ExtractCoAgentRunID(JSON.stringify({ promptRunID: 'p' }))).toBeUndefined();
|
|
58
|
+
expect(ExtractCoAgentRunID(null)).toBeUndefined();
|
|
59
|
+
expect(ExtractCoAgentRunID(undefined)).toBeUndefined();
|
|
60
|
+
expect(ExtractCoAgentRunID('')).toBeUndefined();
|
|
61
|
+
expect(ExtractCoAgentRunID(JSON.stringify({ coAgentRunID: 123 }))).toBeUndefined();
|
|
62
62
|
});
|
|
63
63
|
it('returns undefined for malformed JSON (best-effort)', () => {
|
|
64
|
-
expect(
|
|
64
|
+
expect(ExtractCoAgentRunID('{not json')).toBeUndefined();
|
|
65
65
|
});
|
|
66
66
|
});
|
|
67
67
|
|
|
@@ -76,7 +76,7 @@ describe('finalizeBrowserGoalStep', () => {
|
|
|
76
76
|
|
|
77
77
|
it('finalizes the parent step Completed from a successful goal result + saves', async () => {
|
|
78
78
|
const step = fakeStep();
|
|
79
|
-
await
|
|
79
|
+
await FinalizeBrowserGoalStep(step, { Success: true, Strategy: 'ComputerUse', Status: 'Completed', StepCount: 4, CurrentUrl: 'https://done/' });
|
|
80
80
|
expect(step.Status).toBe('Completed');
|
|
81
81
|
expect(step.Success).toBe(true);
|
|
82
82
|
expect((step as unknown as { Save: ReturnType<typeof vi.fn> }).Save).toHaveBeenCalledOnce();
|
|
@@ -87,13 +87,13 @@ describe('finalizeBrowserGoalStep', () => {
|
|
|
87
87
|
|
|
88
88
|
it('finalizes Failed and carries the detail as the error message', async () => {
|
|
89
89
|
const step = fakeStep();
|
|
90
|
-
await
|
|
90
|
+
await FinalizeBrowserGoalStep(step, { Success: false, Status: 'Error', Detail: 'login blocked' });
|
|
91
91
|
expect(step.Status).toBe('Failed');
|
|
92
92
|
expect(step.ErrorMessage).toBe('login blocked');
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
it('is a no-op when the step is null (no co-agent run to nest under)', async () => {
|
|
96
|
-
await expect(
|
|
96
|
+
await expect(FinalizeBrowserGoalStep(null, { Success: true })).resolves.toBeUndefined();
|
|
97
97
|
});
|
|
98
98
|
});
|
|
99
99
|
|
|
@@ -62,7 +62,13 @@ vi.mock('@memberjunction/remote-browser-server', () => ({
|
|
|
62
62
|
|
|
63
63
|
// Keep the AI imports (visual interpreter) inert — they aren't exercised by the snapshot path.
|
|
64
64
|
vi.mock('@memberjunction/aiengine', () => ({ AIEngine: { Instance: { Config: vi.fn(), Prompts: [] } } }));
|
|
65
|
-
|
|
65
|
+
// Spread the real module, as for ai-core-plus below, so transitively-loaded modules resolve: runners such as
|
|
66
|
+
// AIRerankerRunner (which extends BaseModelRunner), and RunDecisionResolver's AIDecisionRunner. Only
|
|
67
|
+
// AIPromptRunner is overridden for the test.
|
|
68
|
+
vi.mock('@memberjunction/ai-prompts', async (importOriginal) => ({
|
|
69
|
+
...(await importOriginal<typeof import('@memberjunction/ai-prompts')>()),
|
|
70
|
+
AIPromptRunner: class {},
|
|
71
|
+
}));
|
|
66
72
|
// Spread the real module so transitively-loaded code still resolves with its REAL base classes; only
|
|
67
73
|
// AIPromptParams is overridden for the test.
|
|
68
74
|
vi.mock('@memberjunction/ai-core-plus', async (importOriginal) => ({
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Reflect.metadata polyfill at import time.
|
|
2
|
+
import 'reflect-metadata';
|
|
3
|
+
import { describe, it, expect } from 'vitest';
|
|
4
|
+
import { EntityFieldTSType, type EntityFieldInfo, type EntityInfo } from '@memberjunction/core';
|
|
5
|
+
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Client old values arrive as strings, with dates as epoch milliseconds (the GraphQL Timestamp form).
|
|
9
|
+
* Loading them as-is made an unchanged date field an Invalid Date, so it read as edited: a
|
|
10
|
+
* Comments-only update to an MJ: Record Changes row was refused for "changing" ChangedAt.
|
|
11
|
+
*/
|
|
12
|
+
class Probe extends ResolverBase {
|
|
13
|
+
public Convert(field: Partial<EntityFieldInfo>, raw: unknown) {
|
|
14
|
+
return this.ClientOldValueToFieldValue(field as EntityFieldInfo, raw);
|
|
15
|
+
}
|
|
16
|
+
public MustLoad(entity: Partial<EntityInfo>, oldValues: boolean) {
|
|
17
|
+
return this.MustLoadTruthFromDatabase(entity as EntityInfo, { OldValues___: oldValues ? [{ Key: 'Comments', Value: null }] : undefined }, false, false);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const probe = new Probe();
|
|
21
|
+
const dateField = { Name: 'ChangedAt', TSType: EntityFieldTSType.Date, Type: 'datetimeoffset', AllowsNull: false, DefaultValue: 'getutcdate()' };
|
|
22
|
+
|
|
23
|
+
describe('ResolverBase.ClientOldValueToFieldValue', () => {
|
|
24
|
+
it('reads an epoch-milliseconds string as the same instant', () => {
|
|
25
|
+
const value = probe.Convert(dateField, '1790365634563') as Date;
|
|
26
|
+
expect(value).toBeInstanceOf(Date);
|
|
27
|
+
expect(value.getTime()).toBe(1790365634563);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('reads an ISO date string too, and keeps null as null for a nullable date', () => {
|
|
31
|
+
expect((probe.Convert(dateField, '2026-09-25T19:47:14.563Z') as Date).toISOString()).toBe('2026-09-25T19:47:14.563Z');
|
|
32
|
+
expect(probe.Convert({ ...dateField, AllowsNull: true, DefaultValue: null }, null)).toBeNull();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('types numbers and booleans like the field', () => {
|
|
36
|
+
expect(probe.Convert({ Name: 'N', TSType: EntityFieldTSType.Number, Type: 'int' }, '42')).toBe(42);
|
|
37
|
+
expect(probe.Convert({ Name: 'B', TSType: EntityFieldTSType.Boolean, Type: 'bit' }, 'false')).toBe(false);
|
|
38
|
+
expect(probe.Convert({ Name: 'B', TSType: EntityFieldTSType.Boolean, Type: 'bit', AllowsNull: true }, null)).toBe(false);
|
|
39
|
+
expect(probe.Convert({ Name: 'B', TSType: EntityFieldTSType.Boolean, Type: 'bit' }, '1')).toBe(true);
|
|
40
|
+
expect(probe.Convert({ Name: 'M', TSType: EntityFieldTSType.Number, Type: 'money' }, '1.5')).toBe(1.5);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('ResolverBase.MustLoadTruthFromDatabase', () => {
|
|
45
|
+
it('always loads a Record Change from the database, so client OldValues cannot pin forged audit columns', () => {
|
|
46
|
+
expect(probe.MustLoad({ Name: 'MJ: Record Changes', TrackRecordChanges: false }, true)).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('still trusts OldValues on other untracked entities without field security', () => {
|
|
50
|
+
expect(probe.MustLoad({ Name: 'MJ: Tags', TrackRecordChanges: false, EnableFieldLevelSecurity: false }, true)).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The agent's history floor on `RunAIAgentFromConversationDetail`.
|
|
3
|
+
*
|
|
4
|
+
* `agentHistoryFrom` is the one server change behind the conversations host rules: an optional
|
|
5
|
+
* ISO-8601 timestamp, the first moment of the conversation a run may read. These tests pin that
|
|
6
|
+
* the mutation parses it before anything loads, fails the request on an unreadable value instead
|
|
7
|
+
* of dropping it, loads history from it (in the query AND in the window assembly), and hands it to
|
|
8
|
+
* the agent run as `ConversationHistoryFrom` on both the synchronous and fire-and-forget paths —
|
|
9
|
+
* and that leaving it out changes nothing.
|
|
10
|
+
*/
|
|
11
|
+
import 'reflect-metadata'; // must precede any type-graphql decorator evaluation
|
|
12
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
13
|
+
import type { PubSubEngine } from 'type-graphql';
|
|
14
|
+
|
|
15
|
+
// type-graphql's real decorators need emitDecoratorMetadata, which vitest's esbuild transform
|
|
16
|
+
// does not emit; the schema is irrelevant here, so every decorator is a no-op.
|
|
17
|
+
vi.mock('type-graphql', () => {
|
|
18
|
+
const decoratorFactory = (..._args: unknown[]) => (..._decorated: unknown[]) => undefined;
|
|
19
|
+
const exportNames = [
|
|
20
|
+
'Resolver', 'Query', 'Mutation', 'Subscription', 'Arg', 'Args', 'ArgsType', 'Ctx', 'Root',
|
|
21
|
+
'Info', 'Field', 'FieldResolver', 'ObjectType', 'InputType', 'InterfaceType', 'Authorized',
|
|
22
|
+
'UseMiddleware', 'Extensions', 'Directive', 'ID', 'Int', 'Float', 'GraphQLISODateTime',
|
|
23
|
+
'GraphQLTimestamp', 'registerEnumType', 'createMethodDecorator', 'createParamDecorator',
|
|
24
|
+
'buildSchema', 'buildSchemaSync', 'PubSub',
|
|
25
|
+
];
|
|
26
|
+
return Object.fromEntries(exportNames.map((name) => [name, decoratorFactory]));
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const hoisted = vi.hoisted(() => ({
|
|
30
|
+
runAgentInConversation: vi.fn(),
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
vi.mock('@memberjunction/ai-agents', () => ({
|
|
34
|
+
AgentRunner: class {
|
|
35
|
+
RunAgentInConversation(...args: unknown[]) {
|
|
36
|
+
return hoisted.runAgentInConversation(...args);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
ArtifactToolManager: class {},
|
|
40
|
+
}));
|
|
41
|
+
|
|
42
|
+
vi.mock('../realtimeWidget/widgetGuestElevation.js', () => ({
|
|
43
|
+
ResolveWidgetGuestRunContext: vi.fn().mockResolvedValue(null),
|
|
44
|
+
ElevateUserPayload: vi.fn(),
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
import { ConversationEngine } from '@memberjunction/core-entities';
|
|
48
|
+
import { RunAIAgentResolver } from '../resolvers/RunAIAgentResolver.js';
|
|
49
|
+
import type { AppContext, UserPayload } from '../types.js';
|
|
50
|
+
|
|
51
|
+
const FLOOR_ISO = '2026-09-01T12:00:00.000Z';
|
|
52
|
+
const USER = { ID: 'user-1', Email: 'user@example.com' };
|
|
53
|
+
|
|
54
|
+
type Fn = ReturnType<typeof vi.fn>;
|
|
55
|
+
|
|
56
|
+
/** The private members this test reaches, through an explicit shape (no `any`). */
|
|
57
|
+
interface ResolverSeams {
|
|
58
|
+
CheckAPIKeyScopeAuthorization: Fn;
|
|
59
|
+
GetUserFromPayload: Fn;
|
|
60
|
+
loadConversationHistoryWithAttachments: Fn;
|
|
61
|
+
executeAIAgent: Fn;
|
|
62
|
+
executeAgentInBackground: Fn;
|
|
63
|
+
loadInputArtifactsBatch: Fn;
|
|
64
|
+
validateAgent: Fn;
|
|
65
|
+
persistInFlightAgentFailure: Fn;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function makeResolver(): { resolver: RunAIAgentResolver; seams: ResolverSeams } {
|
|
69
|
+
const resolver = new RunAIAgentResolver();
|
|
70
|
+
const seams = resolver as unknown as ResolverSeams;
|
|
71
|
+
seams.CheckAPIKeyScopeAuthorization = vi.fn().mockResolvedValue(undefined);
|
|
72
|
+
seams.GetUserFromPayload = vi.fn().mockReturnValue(USER);
|
|
73
|
+
return { resolver, seams };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function makeContext(): AppContext {
|
|
77
|
+
const provider = {
|
|
78
|
+
GetEntityObject: vi.fn().mockResolvedValue({
|
|
79
|
+
ConversationID: 'conv-1',
|
|
80
|
+
Load: vi.fn().mockResolvedValue(true),
|
|
81
|
+
}),
|
|
82
|
+
};
|
|
83
|
+
return {
|
|
84
|
+
userPayload: { sessionId: 'session-1', userRecord: USER } as unknown as UserPayload,
|
|
85
|
+
providers: [{ type: 'Read-Write', provider }],
|
|
86
|
+
dataSource: {},
|
|
87
|
+
} as unknown as AppContext;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const pubSub = { publish: vi.fn() } as unknown as PubSubEngine;
|
|
91
|
+
|
|
92
|
+
async function runMutation(
|
|
93
|
+
resolver: RunAIAgentResolver,
|
|
94
|
+
options: { agentHistoryFrom?: string; fireAndForget?: boolean }
|
|
95
|
+
) {
|
|
96
|
+
return resolver.RunAIAgentFromConversationDetail(
|
|
97
|
+
'detail-1', 'agent-1', makeContext(), 'session-1', pubSub,
|
|
98
|
+
undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
|
|
99
|
+
undefined, undefined, options.fireAndForget, undefined, undefined,
|
|
100
|
+
options.agentHistoryFrom
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
afterEach(() => {
|
|
105
|
+
vi.restoreAllMocks();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('RunAIAgentFromConversationDetail — agentHistoryFrom', () => {
|
|
109
|
+
let resolver: RunAIAgentResolver;
|
|
110
|
+
let seams: ResolverSeams;
|
|
111
|
+
|
|
112
|
+
beforeEach(() => {
|
|
113
|
+
({ resolver, seams } = makeResolver());
|
|
114
|
+
seams.loadConversationHistoryWithAttachments = vi.fn().mockResolvedValue([]);
|
|
115
|
+
seams.executeAIAgent = vi.fn().mockResolvedValue({ success: true, result: '{}' });
|
|
116
|
+
seams.executeAgentInBackground = vi.fn();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('loads history from the floor and hands the floor to the run', async () => {
|
|
120
|
+
const result = await runMutation(resolver, { agentHistoryFrom: FLOOR_ISO });
|
|
121
|
+
|
|
122
|
+
expect(result.success).toBe(true);
|
|
123
|
+
const loaderArgs = seams.loadConversationHistoryWithAttachments.mock.calls[0];
|
|
124
|
+
expect(loaderArgs[0]).toBe('conv-1');
|
|
125
|
+
expect(loaderArgs[4]).toEqual(['detail-1']);
|
|
126
|
+
expect((loaderArgs[5] as Date).toISOString()).toBe(FLOOR_ISO);
|
|
127
|
+
const runFloor = seams.executeAIAgent.mock.calls[0].at(-1) as Date;
|
|
128
|
+
expect(runFloor.toISOString()).toBe(FLOOR_ISO);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('hands the floor to a fire-and-forget run too', async () => {
|
|
132
|
+
const result = await runMutation(resolver, { agentHistoryFrom: FLOOR_ISO, fireAndForget: true });
|
|
133
|
+
|
|
134
|
+
expect(result.success).toBe(true);
|
|
135
|
+
expect(seams.executeAIAgent).not.toHaveBeenCalled();
|
|
136
|
+
const runFloor = seams.executeAgentInBackground.mock.calls[0].at(-1) as Date;
|
|
137
|
+
expect(runFloor.toISOString()).toBe(FLOOR_ISO);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('left out, reads the whole conversation as before', async () => {
|
|
141
|
+
await runMutation(resolver, {});
|
|
142
|
+
|
|
143
|
+
expect(seams.loadConversationHistoryWithAttachments.mock.calls[0][5]).toBeUndefined();
|
|
144
|
+
expect(seams.executeAIAgent.mock.calls[0].at(-1)).toBeUndefined();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('fails the request on an unreadable floor, before loading or running anything', async () => {
|
|
148
|
+
const result = await runMutation(resolver, { agentHistoryFrom: 'last tuesday' });
|
|
149
|
+
|
|
150
|
+
expect(result.success).toBe(false);
|
|
151
|
+
expect(result.errorMessage).toContain('agentHistoryFrom');
|
|
152
|
+
expect(seams.loadConversationHistoryWithAttachments).not.toHaveBeenCalled();
|
|
153
|
+
expect(seams.executeAIAgent).not.toHaveBeenCalled();
|
|
154
|
+
expect(seams.executeAgentInBackground).not.toHaveBeenCalled();
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('treats an empty string as unreadable too, never as "no floor"', async () => {
|
|
158
|
+
const result = await runMutation(resolver, { agentHistoryFrom: '' });
|
|
159
|
+
|
|
160
|
+
expect(result.success).toBe(false);
|
|
161
|
+
expect(seams.executeAIAgent).not.toHaveBeenCalled();
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe('loadConversationHistoryWithAttachments — history floor', () => {
|
|
166
|
+
it('passes the floor to the fresh loader and to the window assembly', async () => {
|
|
167
|
+
const { resolver, seams } = makeResolver();
|
|
168
|
+
seams.loadInputArtifactsBatch = vi.fn().mockResolvedValue(new Map());
|
|
169
|
+
const loadRows = vi.spyOn(ConversationEngine, 'LoadWindowRowsFresh').mockResolvedValue([]);
|
|
170
|
+
const assemble = vi.spyOn(ConversationEngine, 'AssembleContextWindow');
|
|
171
|
+
const floor = new Date(FLOOR_ISO);
|
|
172
|
+
const provider = {};
|
|
173
|
+
|
|
174
|
+
const load = (resolver as unknown as {
|
|
175
|
+
loadConversationHistoryWithAttachments(
|
|
176
|
+
conversationId: string, user: unknown, max: number, provider: unknown, exclude?: string[], historyFrom?: Date
|
|
177
|
+
): Promise<unknown[]>;
|
|
178
|
+
}).loadConversationHistoryWithAttachments.bind(resolver);
|
|
179
|
+
await load('conv-1', USER, 20, provider, ['detail-1'], floor);
|
|
180
|
+
|
|
181
|
+
expect(loadRows).toHaveBeenCalledWith('conv-1', USER, provider, floor);
|
|
182
|
+
expect(assemble.mock.calls[0][1]).toEqual({ maxTailMessages: 20, excludeDetailIds: ['detail-1'], historyFrom: floor });
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
function executeArgs(conversationHistoryFrom?: Date): unknown[] {
|
|
187
|
+
const userPayload = { sessionId: 'session-1', userRecord: USER };
|
|
188
|
+
return [
|
|
189
|
+
{}, {}, 'agent-1', userPayload, '[{"role":"user","content":"hi"}]', 'session-1', pubSub,
|
|
190
|
+
undefined, undefined, undefined, undefined, undefined, undefined, 'detail-1', false, false,
|
|
191
|
+
undefined, undefined, 'conv-1', undefined, undefined, undefined, undefined,
|
|
192
|
+
conversationHistoryFrom,
|
|
193
|
+
];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
describe('executeAIAgent — ConversationHistoryFrom', () => {
|
|
197
|
+
function wire() {
|
|
198
|
+
const { resolver, seams } = makeResolver();
|
|
199
|
+
seams.validateAgent = vi.fn().mockResolvedValue({ ID: 'agent-1', Name: 'Test Agent' });
|
|
200
|
+
seams.persistInFlightAgentFailure = vi.fn().mockResolvedValue(undefined);
|
|
201
|
+
// Stop right after the params are captured — the rest of the run is out of scope, and so
|
|
202
|
+
// is the failure it logs.
|
|
203
|
+
hoisted.runAgentInConversation.mockReset().mockRejectedValue(new Error('stop here'));
|
|
204
|
+
vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
205
|
+
vi.spyOn(console, 'log').mockImplementation(() => undefined);
|
|
206
|
+
const execute = (resolver as unknown as {
|
|
207
|
+
executeAIAgent(...args: unknown[]): Promise<{ success: boolean }>;
|
|
208
|
+
}).executeAIAgent.bind(resolver);
|
|
209
|
+
return execute;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
it('puts the floor on the run\'s params', async () => {
|
|
213
|
+
const execute = wire();
|
|
214
|
+
const floor = new Date(FLOOR_ISO);
|
|
215
|
+
await execute(...executeArgs(floor));
|
|
216
|
+
|
|
217
|
+
const params = hoisted.runAgentInConversation.mock.calls[0][0] as Record<string, unknown>;
|
|
218
|
+
expect(params.ConversationHistoryFrom).toBe(floor);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('leaves it unset without a floor', async () => {
|
|
222
|
+
const execute = wire();
|
|
223
|
+
await execute(...executeArgs());
|
|
224
|
+
|
|
225
|
+
const params = hoisted.runAgentInConversation.mock.calls[0][0] as Record<string, unknown>;
|
|
226
|
+
expect(params.ConversationHistoryFrom).toBeUndefined();
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
describe('executeAIAgent — status publishing', () => {
|
|
231
|
+
const agentRun = {
|
|
232
|
+
ID: 'run-1',
|
|
233
|
+
ConversationDetailID: 'detail-1',
|
|
234
|
+
Steps: [{ StepName: 'Answer' }],
|
|
235
|
+
GetAll: () => ({ ID: 'run-1', ConversationDetailID: 'detail-1', Agent: 'Betty' }),
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
function envelopes(publish: ReturnType<typeof vi.fn>): Array<Record<string, unknown>> {
|
|
239
|
+
return publish.mock.calls.map((call) => JSON.parse((call[1] as { message: string }).message) as Record<string, unknown>);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
it('publishes progress, streamed text, the partial result, and the completion from the runner callbacks', async () => {
|
|
243
|
+
const { resolver, seams } = makeResolver();
|
|
244
|
+
seams.validateAgent = vi.fn().mockResolvedValue({ ID: 'agent-1', Name: 'Test Agent' });
|
|
245
|
+
seams.persistInFlightAgentFailure = vi.fn().mockResolvedValue(undefined);
|
|
246
|
+
vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
247
|
+
vi.spyOn(console, 'log').mockImplementation(() => undefined);
|
|
248
|
+
const publish = vi.fn().mockResolvedValue(undefined);
|
|
249
|
+
(pubSub as unknown as { publish: Fn }).publish = publish;
|
|
250
|
+
hoisted.runAgentInConversation.mockReset().mockImplementation(async (params: {
|
|
251
|
+
onProgress?: (progress: { step: string; message?: string; percentage?: number; metadata?: Record<string, unknown> }) => void;
|
|
252
|
+
onStreaming?: (chunk: { content: string; isComplete: boolean; stepType?: string; kind?: string }) => void;
|
|
253
|
+
}) => {
|
|
254
|
+
params.onProgress?.({ step: 'initialization', message: 'noise', metadata: { agentRun } });
|
|
255
|
+
params.onProgress?.({
|
|
256
|
+
step: 'prompt_execution',
|
|
257
|
+
message: 'Writing',
|
|
258
|
+
percentage: 40,
|
|
259
|
+
metadata: { agentRun, agentName: 'Betty' },
|
|
260
|
+
});
|
|
261
|
+
params.onStreaming?.({ content: 'Hel', isComplete: false, stepType: 'prompt', kind: 'final-response' });
|
|
262
|
+
return {
|
|
263
|
+
agentResult: { success: true, agentRun, payload: { text: 'Hello' } },
|
|
264
|
+
agentResponseDetailId: 'detail-1',
|
|
265
|
+
conversationId: 'conv-1',
|
|
266
|
+
};
|
|
267
|
+
});
|
|
268
|
+
const execute = (resolver as unknown as {
|
|
269
|
+
executeAIAgent(...args: unknown[]): Promise<{ success: boolean }>;
|
|
270
|
+
}).executeAIAgent.bind(resolver);
|
|
271
|
+
|
|
272
|
+
const result = await execute(...executeArgs());
|
|
273
|
+
|
|
274
|
+
expect(result.success).toBe(true);
|
|
275
|
+
const sent = envelopes(publish);
|
|
276
|
+
expect(sent.map((row) => (row.data as { type: string }).type)).toEqual([
|
|
277
|
+
'progress',
|
|
278
|
+
'streaming',
|
|
279
|
+
'partial_result',
|
|
280
|
+
'complete',
|
|
281
|
+
]);
|
|
282
|
+
expect(sent[0].type).toBe('ExecutionProgress');
|
|
283
|
+
expect(sent[0].resolver).toBe('RunAIAgentResolver');
|
|
284
|
+
expect((sent[1].data as { streaming: { content: string } }).streaming.content).toBe('Hel');
|
|
285
|
+
const completion = sent[3].data as { conversationDetailId: string; agentRunId: string; success: boolean };
|
|
286
|
+
expect(completion.conversationDetailId).toBe('detail-1');
|
|
287
|
+
expect(completion.agentRunId).toBe('run-1');
|
|
288
|
+
expect(completion.success).toBe(true);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('publishes a failure completion when a fire-and-forget run rejects', async () => {
|
|
292
|
+
const { resolver, seams } = makeResolver();
|
|
293
|
+
seams.executeAIAgent = vi.fn().mockRejectedValue(new Error('background blew up'));
|
|
294
|
+
vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
295
|
+
vi.spyOn(console, 'log').mockImplementation(() => undefined);
|
|
296
|
+
const publish = vi.fn().mockResolvedValue(undefined);
|
|
297
|
+
const localPubSub = { publish } as unknown as PubSubEngine;
|
|
298
|
+
const userPayload = { sessionId: 'session-1', userRecord: USER };
|
|
299
|
+
const runInBackground = (resolver as unknown as {
|
|
300
|
+
executeAgentInBackground(...args: unknown[]): void;
|
|
301
|
+
}).executeAgentInBackground.bind(resolver);
|
|
302
|
+
|
|
303
|
+
runInBackground(
|
|
304
|
+
{}, {}, 'agent-1', userPayload, '[]', 'session-1', localPubSub,
|
|
305
|
+
undefined, undefined, undefined, undefined, undefined, 'detail-1',
|
|
306
|
+
);
|
|
307
|
+
await vi.waitFor(() => expect(publish).toHaveBeenCalled());
|
|
308
|
+
|
|
309
|
+
const sent = envelopes(publish);
|
|
310
|
+
expect(sent).toHaveLength(1);
|
|
311
|
+
expect(sent[0].type).toBe('StreamingContent');
|
|
312
|
+
expect(sent[0].resolver).toBe('RunAIAgentResolver');
|
|
313
|
+
const completion = sent[0].data as {
|
|
314
|
+
type: string;
|
|
315
|
+
agentRunId: string;
|
|
316
|
+
conversationDetailId: string;
|
|
317
|
+
success: boolean;
|
|
318
|
+
errorMessage: string;
|
|
319
|
+
result: string;
|
|
320
|
+
};
|
|
321
|
+
expect(completion).toMatchObject({
|
|
322
|
+
type: 'complete',
|
|
323
|
+
agentRunId: 'unknown',
|
|
324
|
+
conversationDetailId: 'detail-1',
|
|
325
|
+
success: false,
|
|
326
|
+
errorMessage: 'background blew up',
|
|
327
|
+
result: JSON.stringify({ success: false, errorMessage: 'background blew up' }),
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('saves a Running run reported by progress as Failed when the agent throws', async () => {
|
|
332
|
+
const { resolver, seams } = makeResolver();
|
|
333
|
+
seams.validateAgent = vi.fn().mockResolvedValue({ ID: 'agent-1', Name: 'Test Agent' });
|
|
334
|
+
vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
335
|
+
vi.spyOn(console, 'log').mockImplementation(() => undefined);
|
|
336
|
+
const runningRun = {
|
|
337
|
+
ID: 'run-1',
|
|
338
|
+
Status: 'Running',
|
|
339
|
+
ErrorMessage: '',
|
|
340
|
+
CompletedAt: null as Date | null,
|
|
341
|
+
EnsureSaveComplete: vi.fn().mockResolvedValue(undefined),
|
|
342
|
+
Save: vi.fn().mockResolvedValue(true),
|
|
343
|
+
};
|
|
344
|
+
const detail = {
|
|
345
|
+
Status: 'Complete',
|
|
346
|
+
Load: vi.fn().mockResolvedValue(true),
|
|
347
|
+
Save: vi.fn().mockResolvedValue(true),
|
|
348
|
+
};
|
|
349
|
+
const provider = { GetEntityObject: vi.fn().mockResolvedValue(detail) };
|
|
350
|
+
hoisted.runAgentInConversation.mockReset().mockImplementation(async (params: {
|
|
351
|
+
onProgress?: (progress: { step: string; metadata?: Record<string, unknown> }) => void;
|
|
352
|
+
}) => {
|
|
353
|
+
params.onProgress?.({ step: 'prompt_execution', metadata: { agentRun: runningRun } });
|
|
354
|
+
throw new Error('agent threw mid-run');
|
|
355
|
+
});
|
|
356
|
+
const execute = (resolver as unknown as {
|
|
357
|
+
executeAIAgent(...args: unknown[]): Promise<{ success: boolean; errorMessage?: string }>;
|
|
358
|
+
}).executeAIAgent.bind(resolver);
|
|
359
|
+
const args = executeArgs();
|
|
360
|
+
args[0] = provider;
|
|
361
|
+
|
|
362
|
+
const result = await execute(...args);
|
|
363
|
+
|
|
364
|
+
expect(result.success).toBe(false);
|
|
365
|
+
expect(result.errorMessage).toBe('agent threw mid-run');
|
|
366
|
+
expect(runningRun.Status).toBe('Failed');
|
|
367
|
+
expect(runningRun.ErrorMessage).toBe('agent threw mid-run');
|
|
368
|
+
expect(runningRun.CompletedAt).toBeInstanceOf(Date);
|
|
369
|
+
expect(runningRun.EnsureSaveComplete).toHaveBeenCalled();
|
|
370
|
+
expect(runningRun.Save).toHaveBeenCalled();
|
|
371
|
+
expect(detail.Save).not.toHaveBeenCalled();
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
describe('persistInFlightAgentFailure — a refused conversation-detail save logs the reason (MJ#4791)', () => {
|
|
376
|
+
it('includes LatestResult.CompleteMessage when the Error-status save is refused', async () => {
|
|
377
|
+
const { resolver } = makeResolver();
|
|
378
|
+
const errSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
379
|
+
const detail = {
|
|
380
|
+
Status: 'In-Progress',
|
|
381
|
+
LatestResult: { CompleteMessage: 'You do not have access to this conversation.' },
|
|
382
|
+
Load: vi.fn().mockResolvedValue(true),
|
|
383
|
+
EnsureSaveComplete: vi.fn().mockResolvedValue(undefined),
|
|
384
|
+
Save: vi.fn().mockResolvedValue(false),
|
|
385
|
+
};
|
|
386
|
+
const provider = { GetEntityObject: vi.fn().mockResolvedValue(detail) };
|
|
387
|
+
const persist = (resolver as unknown as {
|
|
388
|
+
persistInFlightAgentFailure(...args: unknown[]): Promise<void>;
|
|
389
|
+
}).persistInFlightAgentFailure.bind(resolver);
|
|
390
|
+
|
|
391
|
+
await persist(provider, { sessionId: 'session-1', userRecord: USER }, null, 'detail-1', 'agent threw');
|
|
392
|
+
|
|
393
|
+
const lines = errSpy.mock.calls.map((call) => String(call[0]));
|
|
394
|
+
const line = lines.find((l) => l.includes('Failed to persist Error on conversation detail detail-1'));
|
|
395
|
+
expect(line).toBeDefined();
|
|
396
|
+
expect(line).toContain('You do not have access to this conversation.');
|
|
397
|
+
});
|
|
398
|
+
});
|
|
@@ -29,31 +29,27 @@ vi.mock('type-graphql', () => {
|
|
|
29
29
|
});
|
|
30
30
|
import type { AgentExecutionStreamingCallback } from '@memberjunction/ai-core-plus';
|
|
31
31
|
|
|
32
|
-
import {
|
|
32
|
+
import { AgentRunStatusPublisher } from '../resolvers/AgentRunStatusPublisher.js';
|
|
33
33
|
import type { UserPayload } from '../types.js';
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
sessionId: string,
|
|
40
|
-
userPayload: UserPayload,
|
|
41
|
-
agentRunRef: { current: unknown }
|
|
42
|
-
): AgentExecutionStreamingCallback;
|
|
43
|
-
}
|
|
35
|
+
const agentRun = {
|
|
36
|
+
ID: 'run-1',
|
|
37
|
+
GetAll: () => ({ ID: 'run-1', ConversationDetailID: 'detail-1', Agent: 'Betty' }),
|
|
38
|
+
};
|
|
44
39
|
|
|
45
40
|
function buildHarness() {
|
|
46
41
|
const publish = vi.fn().mockResolvedValue(undefined);
|
|
47
42
|
const pubSub = { publish } as unknown as PubSubEngine;
|
|
48
|
-
const userPayload = { sessionId: 'session-1' } as UserPayload;
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
43
|
+
const userPayload = { sessionId: 'session-1', userRecord: { ID: 'user-1' } } as UserPayload;
|
|
44
|
+
const publisher = new AgentRunStatusPublisher(pubSub, userPayload, 'session-1');
|
|
45
|
+
// A progress event, even a noise step, is how the publisher learns the run.
|
|
46
|
+
publisher.OnProgress({
|
|
47
|
+
step: 'initialization',
|
|
48
|
+
message: 'starting',
|
|
49
|
+
metadata: { agentRun },
|
|
50
|
+
});
|
|
51
|
+
publish.mockClear();
|
|
52
|
+
const callback: AgentExecutionStreamingCallback = publisher.OnStreaming;
|
|
57
53
|
return { publish, callback };
|
|
58
54
|
}
|
|
59
55
|
|
|
@@ -67,7 +63,7 @@ function publishedData(publish: ReturnType<typeof vi.fn>): Record<string, unknow
|
|
|
67
63
|
return parsed.data as Record<string, unknown>;
|
|
68
64
|
}
|
|
69
65
|
|
|
70
|
-
describe('
|
|
66
|
+
describe('AgentRunStatusPublisher streaming wire shape', () => {
|
|
71
67
|
it('publishes the streaming wire shape the conversation client parses', () => {
|
|
72
68
|
const { publish, callback } = buildHarness();
|
|
73
69
|
|
|
@@ -110,13 +106,8 @@ describe('RunAIAgentResolver.createStreamingCallback', () => {
|
|
|
110
106
|
it('does not publish when no agent run is available yet', () => {
|
|
111
107
|
const publish = vi.fn();
|
|
112
108
|
const pubSub = { publish } as unknown as PubSubEngine;
|
|
113
|
-
const
|
|
114
|
-
const callback =
|
|
115
|
-
pubSub,
|
|
116
|
-
'session-1',
|
|
117
|
-
{ sessionId: 'session-1' } as UserPayload,
|
|
118
|
-
{ current: null }
|
|
119
|
-
);
|
|
109
|
+
const publisher = new AgentRunStatusPublisher(pubSub, { sessionId: 'session-1', userRecord: { ID: 'user-1' } } as UserPayload, 'session-1');
|
|
110
|
+
const callback = publisher.OnStreaming;
|
|
120
111
|
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
121
112
|
try {
|
|
122
113
|
callback({ content: 'early', isComplete: false });
|