@memberjunction/server 5.43.0 → 5.45.0
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/agentSessions/ReturningVisitorRecap.d.ts +39 -0
- package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -0
- package/dist/agentSessions/ReturningVisitorRecap.js +198 -0
- package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -0
- package/dist/agentSessions/SessionJanitor.d.ts +13 -0
- package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
- package/dist/agentSessions/SessionJanitor.js +65 -7
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +40 -0
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/agentSessions/index.d.ts.map +1 -1
- package/dist/agentSessions/index.js +3 -1
- package/dist/agentSessions/index.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.d.ts +10 -0
- package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +16 -0
- package/dist/auth/magicLink/MagicLinkRouter.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/types.d.ts +26 -0
- package/dist/auth/magicLink/types.d.ts.map +1 -1
- package/dist/config.d.ts +1883 -144
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +160 -36
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +45 -2
- package/dist/context.js.map +1 -1
- package/dist/generated/generated.d.ts +1684 -54
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +57105 -48029
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +13 -0
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +22 -0
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +4 -0
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +110 -3
- package/dist/index.js.map +1 -1
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +6 -0
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.d.ts +26 -0
- package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -0
- package/dist/realtimeWidget/WidgetRouter.js +182 -0
- package/dist/realtimeWidget/WidgetRouter.js.map +1 -0
- package/dist/realtimeWidget/WidgetSessionService.d.ts +265 -0
- package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -0
- package/dist/realtimeWidget/WidgetSessionService.js +477 -0
- package/dist/realtimeWidget/WidgetSessionService.js.map +1 -0
- package/dist/realtimeWidget/host-identity.d.ts +40 -0
- package/dist/realtimeWidget/host-identity.d.ts.map +1 -0
- package/dist/realtimeWidget/host-identity.js +58 -0
- package/dist/realtimeWidget/host-identity.js.map +1 -0
- package/dist/realtimeWidget/index.d.ts +10 -0
- package/dist/realtimeWidget/index.d.ts.map +1 -0
- package/dist/realtimeWidget/index.js +9 -0
- package/dist/realtimeWidget/index.js.map +1 -0
- package/dist/realtimeWidget/visitorIdentity.d.ts +76 -0
- package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -0
- package/dist/realtimeWidget/visitorIdentity.js +202 -0
- package/dist/realtimeWidget/visitorIdentity.js.map +1 -0
- package/dist/realtimeWidget/widgetCore.d.ts +106 -0
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -0
- package/dist/realtimeWidget/widgetCore.js +173 -0
- package/dist/realtimeWidget/widgetCore.js.map +1 -0
- package/dist/realtimeWidget/widgetGuestElevation.d.ts +51 -0
- package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -0
- package/dist/realtimeWidget/widgetGuestElevation.js +79 -0
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -0
- package/dist/resolvers/ComponentRegistryResolver.d.ts +7 -0
- package/dist/resolvers/ComponentRegistryResolver.d.ts.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js +31 -8
- package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
- package/dist/resolvers/EntityPermissionResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityPermissionResolver.js +1 -2
- package/dist/resolvers/EntityPermissionResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +74 -0
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +211 -2
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts +6 -4
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +29 -14
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +9 -6
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +15 -13
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.d.ts +8 -1
- package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +28 -4
- package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +91 -2
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +337 -17
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +17 -2
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/RingCentralTelephonyResolver.d.ts +27 -0
- package/dist/resolvers/RingCentralTelephonyResolver.d.ts.map +1 -0
- package/dist/resolvers/RingCentralTelephonyResolver.js +87 -0
- package/dist/resolvers/RingCentralTelephonyResolver.js.map +1 -0
- package/dist/resolvers/RunAIAgentResolver.d.ts +12 -3
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +50 -17
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/SearchKnowledgeResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeResolver.js +2 -0
- package/dist/resolvers/SearchKnowledgeResolver.js.map +1 -1
- package/dist/resolvers/TeamsMeetingsResolver.d.ts +28 -0
- package/dist/resolvers/TeamsMeetingsResolver.d.ts.map +1 -0
- package/dist/resolvers/TeamsMeetingsResolver.js +91 -0
- package/dist/resolvers/TeamsMeetingsResolver.js.map +1 -0
- package/dist/resolvers/TelephonyResolver.d.ts +26 -0
- package/dist/resolvers/TelephonyResolver.d.ts.map +1 -0
- package/dist/resolvers/TelephonyResolver.js +86 -0
- package/dist/resolvers/TelephonyResolver.js.map +1 -0
- package/dist/resolvers/TestQuerySQLResolver.d.ts +1 -1
- package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.js +2 -3
- package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
- package/dist/resolvers/VonageTelephonyResolver.d.ts +26 -0
- package/dist/resolvers/VonageTelephonyResolver.d.ts.map +1 -0
- package/dist/resolvers/VonageTelephonyResolver.js +86 -0
- package/dist/resolvers/VonageTelephonyResolver.js.map +1 -0
- package/dist/resolvers/meetingRecordingRegistration.d.ts +124 -0
- package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -0
- package/dist/resolvers/meetingRecordingRegistration.js +311 -0
- package/dist/resolvers/meetingRecordingRegistration.js.map +1 -0
- package/dist/resolvers/peaksSidecar.d.ts +30 -0
- package/dist/resolvers/peaksSidecar.d.ts.map +1 -0
- package/dist/resolvers/peaksSidecar.js +51 -0
- package/dist/resolvers/peaksSidecar.js.map +1 -0
- package/dist/rest/MediaAccessKeys.d.ts +68 -0
- package/dist/rest/MediaAccessKeys.d.ts.map +1 -0
- package/dist/rest/MediaAccessKeys.js +96 -0
- package/dist/rest/MediaAccessKeys.js.map +1 -0
- package/dist/rest/MediaStreamHandler.d.ts +26 -0
- package/dist/rest/MediaStreamHandler.d.ts.map +1 -0
- package/dist/rest/MediaStreamHandler.js +195 -0
- package/dist/rest/MediaStreamHandler.js.map +1 -0
- package/dist/rest/mediaRange.d.ts +41 -0
- package/dist/rest/mediaRange.d.ts.map +1 -0
- package/dist/rest/mediaRange.js +60 -0
- package/dist/rest/mediaRange.js.map +1 -0
- package/dist/telephony/RingCentralTelephonyService.d.ts +115 -0
- package/dist/telephony/RingCentralTelephonyService.d.ts.map +1 -0
- package/dist/telephony/RingCentralTelephonyService.js +262 -0
- package/dist/telephony/RingCentralTelephonyService.js.map +1 -0
- package/dist/telephony/TeamsMeetingsRouter.d.ts +40 -0
- package/dist/telephony/TeamsMeetingsRouter.d.ts.map +1 -0
- package/dist/telephony/TeamsMeetingsRouter.js +96 -0
- package/dist/telephony/TeamsMeetingsRouter.js.map +1 -0
- package/dist/telephony/TeamsMeetingsService.d.ts +113 -0
- package/dist/telephony/TeamsMeetingsService.d.ts.map +1 -0
- package/dist/telephony/TeamsMeetingsService.js +196 -0
- package/dist/telephony/TeamsMeetingsService.js.map +1 -0
- package/dist/telephony/TwilioTelephonyRouter.d.ts +36 -0
- package/dist/telephony/TwilioTelephonyRouter.d.ts.map +1 -0
- package/dist/telephony/TwilioTelephonyRouter.js +143 -0
- package/dist/telephony/TwilioTelephonyRouter.js.map +1 -0
- package/dist/telephony/TwilioTelephonyService.d.ts +95 -0
- package/dist/telephony/TwilioTelephonyService.d.ts.map +1 -0
- package/dist/telephony/TwilioTelephonyService.js +193 -0
- package/dist/telephony/TwilioTelephonyService.js.map +1 -0
- package/dist/telephony/VonageTelephonyRouter.d.ts +41 -0
- package/dist/telephony/VonageTelephonyRouter.d.ts.map +1 -0
- package/dist/telephony/VonageTelephonyRouter.js +201 -0
- package/dist/telephony/VonageTelephonyRouter.js.map +1 -0
- package/dist/telephony/VonageTelephonyService.d.ts +90 -0
- package/dist/telephony/VonageTelephonyService.d.ts.map +1 -0
- package/dist/telephony/VonageTelephonyService.js +191 -0
- package/dist/telephony/VonageTelephonyService.js.map +1 -0
- package/dist/telephony/calendar-scheduler.d.ts +67 -0
- package/dist/telephony/calendar-scheduler.d.ts.map +1 -0
- package/dist/telephony/calendar-scheduler.js +133 -0
- package/dist/telephony/calendar-scheduler.js.map +1 -0
- package/dist/telephony/index.d.ts +29 -0
- package/dist/telephony/index.d.ts.map +1 -0
- package/dist/telephony/index.js +38 -0
- package/dist/telephony/index.js.map +1 -0
- package/dist/telephony/media-upgrade-router.d.ts +33 -0
- package/dist/telephony/media-upgrade-router.d.ts.map +1 -0
- package/dist/telephony/media-upgrade-router.js +56 -0
- package/dist/telephony/media-upgrade-router.js.map +1 -0
- package/dist/telephony/ringcentral-runtime.d.ts +14 -0
- package/dist/telephony/ringcentral-runtime.d.ts.map +1 -0
- package/dist/telephony/ringcentral-runtime.js +18 -0
- package/dist/telephony/ringcentral-runtime.js.map +1 -0
- package/dist/telephony/teams-meetings-runtime.d.ts +16 -0
- package/dist/telephony/teams-meetings-runtime.d.ts.map +1 -0
- package/dist/telephony/teams-meetings-runtime.js +20 -0
- package/dist/telephony/teams-meetings-runtime.js.map +1 -0
- package/dist/telephony/teamsAcsMediaRegistry.d.ts +69 -0
- package/dist/telephony/teamsAcsMediaRegistry.d.ts.map +1 -0
- package/dist/telephony/teamsAcsMediaRegistry.js +118 -0
- package/dist/telephony/teamsAcsMediaRegistry.js.map +1 -0
- package/dist/telephony/telephony-runtime.d.ts +14 -0
- package/dist/telephony/telephony-runtime.d.ts.map +1 -0
- package/dist/telephony/telephony-runtime.js +18 -0
- package/dist/telephony/telephony-runtime.js.map +1 -0
- package/dist/telephony/twilioMediaRegistry.d.ts +60 -0
- package/dist/telephony/twilioMediaRegistry.d.ts.map +1 -0
- package/dist/telephony/twilioMediaRegistry.js +106 -0
- package/dist/telephony/twilioMediaRegistry.js.map +1 -0
- package/dist/telephony/vonage-runtime.d.ts +14 -0
- package/dist/telephony/vonage-runtime.d.ts.map +1 -0
- package/dist/telephony/vonage-runtime.js +18 -0
- package/dist/telephony/vonage-runtime.js.map +1 -0
- package/dist/telephony/vonageMediaRegistry.d.ts +78 -0
- package/dist/telephony/vonageMediaRegistry.d.ts.map +1 -0
- package/dist/telephony/vonageMediaRegistry.js +158 -0
- package/dist/telephony/vonageMediaRegistry.js.map +1 -0
- package/package.json +88 -82
- package/src/__tests__/FileResolverPeaks.test.ts +64 -0
- package/src/__tests__/MediaAccessKeys.test.ts +68 -0
- package/src/__tests__/MediaStreamHandler.test.ts +91 -0
- package/src/__tests__/RealtimeBridgeResolver.test.ts +10 -1
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +69 -0
- package/src/__tests__/RealtimeCoAgentAppAwareness.integration.test.ts +191 -0
- package/src/__tests__/RemoteBrowserSnapshot.test.ts +123 -0
- package/src/__tests__/SessionManager.test.ts +2 -0
- package/src/__tests__/meetingRecordingRegistration.test.ts +248 -0
- package/src/__tests__/search-knowledge-tags.test.ts +9 -9
- package/src/__tests__/teams-meetings-service.test.ts +65 -0
- package/src/__tests__/teamsAcsMediaRegistry.test.ts +82 -0
- package/src/__tests__/twilio-telephony-service.test.ts +23 -0
- package/src/__tests__/twilioMediaRegistry.test.ts +103 -0
- package/src/__tests__/vonageMediaRegistry.test.ts +180 -0
- package/src/__tests__/widget.test.ts +204 -0
- package/src/__tests__/widgetGuestElevation.test.ts +57 -0
- package/src/__tests__/widgetHostIdentity.test.ts +117 -0
- package/src/agentSessions/ReturningVisitorRecap.ts +242 -0
- package/src/agentSessions/SessionJanitor.ts +66 -6
- package/src/agentSessions/SessionManager.ts +41 -0
- package/src/agentSessions/index.ts +3 -1
- package/src/auth/magicLink/MagicLinkRouter.ts +17 -0
- package/src/auth/magicLink/index.ts +1 -0
- package/src/auth/magicLink/types.ts +26 -0
- package/src/config.ts +172 -38
- package/src/context.ts +50 -3
- package/src/generated/generated.ts +26726 -20464
- package/src/generic/ResolverBase.ts +28 -0
- package/src/generic/RunViewResolver.ts +4 -0
- package/src/index.ts +119 -3
- package/src/integration/CustomColumnPromoter.ts +6 -0
- package/src/realtimeWidget/WidgetRouter.ts +204 -0
- package/src/realtimeWidget/WidgetSessionService.ts +714 -0
- package/src/realtimeWidget/host-identity.ts +84 -0
- package/src/realtimeWidget/index.ts +15 -0
- package/src/realtimeWidget/visitorIdentity.ts +258 -0
- package/src/realtimeWidget/widgetCore.ts +231 -0
- package/src/realtimeWidget/widgetGuestElevation.ts +115 -0
- package/src/resolvers/ComponentRegistryResolver.ts +36 -10
- package/src/resolvers/EntityPermissionResolver.ts +1 -2
- package/src/resolvers/FileResolver.ts +199 -1
- package/src/resolvers/QueryResolver.ts +33 -19
- package/src/resolvers/QuerySystemUserResolver.ts +14 -10
- package/src/resolvers/RealtimeBridgeResolver.ts +36 -4
- package/src/resolvers/RealtimeClientSessionResolver.ts +383 -9
- package/src/resolvers/RemoteBrowserActionResolver.ts +18 -2
- package/src/resolvers/RingCentralTelephonyResolver.ts +64 -0
- package/src/resolvers/RunAIAgentResolver.ts +60 -15
- package/src/resolvers/SearchKnowledgeResolver.ts +2 -0
- package/src/resolvers/TeamsMeetingsResolver.ts +68 -0
- package/src/resolvers/TelephonyResolver.ts +63 -0
- package/src/resolvers/TestQuerySQLResolver.ts +2 -3
- package/src/resolvers/VonageTelephonyResolver.ts +63 -0
- package/src/resolvers/meetingRecordingRegistration.ts +432 -0
- package/src/resolvers/peaksSidecar.ts +52 -0
- package/src/rest/MediaAccessKeys.ts +121 -0
- package/src/rest/MediaStreamHandler.ts +223 -0
- package/src/rest/mediaRange.ts +76 -0
- package/src/telephony/RingCentralTelephonyService.ts +342 -0
- package/src/telephony/TeamsMeetingsRouter.ts +124 -0
- package/src/telephony/TeamsMeetingsService.ts +268 -0
- package/src/telephony/TwilioTelephonyRouter.ts +184 -0
- package/src/telephony/TwilioTelephonyService.ts +261 -0
- package/src/telephony/VonageTelephonyRouter.ts +239 -0
- package/src/telephony/VonageTelephonyService.ts +259 -0
- package/src/telephony/calendar-scheduler.ts +176 -0
- package/src/telephony/index.ts +43 -0
- package/src/telephony/media-upgrade-router.ts +62 -0
- package/src/telephony/ringcentral-runtime.ts +22 -0
- package/src/telephony/teams-meetings-runtime.ts +24 -0
- package/src/telephony/teamsAcsMediaRegistry.ts +152 -0
- package/src/telephony/telephony-runtime.ts +22 -0
- package/src/telephony/twilioMediaRegistry.ts +137 -0
- package/src/telephony/vonage-runtime.ts +22 -0
- package/src/telephony/vonageMediaRegistry.ts +200 -0
- package/dist/agents/skip-agent.d.ts +0 -111
- package/dist/agents/skip-agent.d.ts.map +0 -1
- package/dist/agents/skip-agent.js +0 -1487
- package/dist/agents/skip-agent.js.map +0 -1
- package/dist/agents/skip-sdk.d.ts +0 -261
- package/dist/agents/skip-sdk.d.ts.map +0 -1
- package/dist/agents/skip-sdk.js +0 -909
- package/dist/agents/skip-sdk.js.map +0 -1
- package/src/agents/skip-agent.ts +0 -1594
- package/src/agents/skip-sdk.ts +0 -1210
|
@@ -36,16 +36,17 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
36
36
|
*
|
|
37
37
|
* @module @memberjunction/server
|
|
38
38
|
*/
|
|
39
|
-
import { Resolver, Mutation, Arg, Ctx, Int, ObjectType, Field, PubSub, PubSubEngine } from 'type-graphql';
|
|
39
|
+
import { Resolver, Mutation, Arg, Ctx, Int, Float, ObjectType, Field, PubSub, PubSubEngine } from 'type-graphql';
|
|
40
40
|
import { AuthorizationEvaluator, LogError, LogStatus, RunView } from '@memberjunction/core';
|
|
41
|
-
import { UUIDsEqual } from '@memberjunction/global';
|
|
41
|
+
import { UUIDsEqual, IsValidUUID } from '@memberjunction/global';
|
|
42
42
|
import { AIEngine } from '@memberjunction/aiengine';
|
|
43
43
|
import { AIAgentPermissionHelper, AIEngineBase } from '@memberjunction/ai-engine-base';
|
|
44
|
-
import { RealtimeClientSessionService, RealtimeChannelServerHost, EvaluateRuntimeOverrideAuthorization, ParseRealtimeTypeConfiguration, ResolveEffectiveRealtimeConfig, REALTIME_ADVANCED_SESSION_CONTROLS_AUTHORIZATION, } from '@memberjunction/ai-agents';
|
|
44
|
+
import { RealtimeClientSessionService, RealtimeChannelServerHost, EvaluateRuntimeOverrideAuthorization, ParseRealtimeTypeConfiguration, ResolveEffectiveRealtimeConfig, REALTIME_ADVANCED_SESSION_CONTROLS_AUTHORIZATION, resolveRecordingStorageAccountID, storeRealtimeRecording, writeRealtimeRecordingSegment, deleteRealtimeRecordingSegments, } from '@memberjunction/ai-agents';
|
|
45
45
|
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
46
46
|
import { PUSH_STATUS_UPDATES_TOPIC } from '../generic/PushStatusResolver.js';
|
|
47
47
|
import { GetReadWriteProvider } from '../util.js';
|
|
48
48
|
import { SessionManager } from '../agentSessions/index.js';
|
|
49
|
+
import { resolveWidgetGuestRunContext } from '../realtimeWidget/widgetGuestElevation.js';
|
|
49
50
|
/**
|
|
50
51
|
* Progress steps worth narrating to the realtime model — mirrors the normal agent-run path's filter
|
|
51
52
|
* in {@link import('./RunAIAgentResolver.js').RunAIAgentResolver}. Initialization/validation/finalization
|
|
@@ -222,6 +223,30 @@ CancelRealtimeSessionToolResult = __decorate([
|
|
|
222
223
|
ObjectType()
|
|
223
224
|
], CancelRealtimeSessionToolResult);
|
|
224
225
|
export { CancelRealtimeSessionToolResult };
|
|
226
|
+
/**
|
|
227
|
+
* Result of {@link RealtimeClientSessionResolver.UploadRealtimeRecording} — a structured
|
|
228
|
+
* success/failure envelope. A recording-storage failure must never throw to the browser (the
|
|
229
|
+
* session it belongs to has already ended), so problems come back as `Success: false` with a
|
|
230
|
+
* human-readable reason; only ownership/authn violations (from `loadOwnedSession`) still throw.
|
|
231
|
+
*/
|
|
232
|
+
let UploadRealtimeRecordingResult = class UploadRealtimeRecordingResult {
|
|
233
|
+
};
|
|
234
|
+
__decorate([
|
|
235
|
+
Field(() => Boolean),
|
|
236
|
+
__metadata("design:type", Boolean)
|
|
237
|
+
], UploadRealtimeRecordingResult.prototype, "Success", void 0);
|
|
238
|
+
__decorate([
|
|
239
|
+
Field(() => String, { nullable: true }),
|
|
240
|
+
__metadata("design:type", String)
|
|
241
|
+
], UploadRealtimeRecordingResult.prototype, "ErrorMessage", void 0);
|
|
242
|
+
__decorate([
|
|
243
|
+
Field(() => String, { nullable: true }),
|
|
244
|
+
__metadata("design:type", String)
|
|
245
|
+
], UploadRealtimeRecordingResult.prototype, "FileID", void 0);
|
|
246
|
+
UploadRealtimeRecordingResult = __decorate([
|
|
247
|
+
ObjectType()
|
|
248
|
+
], UploadRealtimeRecordingResult);
|
|
249
|
+
export { UploadRealtimeRecordingResult };
|
|
225
250
|
/**
|
|
226
251
|
* Resolver for the client-direct realtime voice topology. A single {@link SessionManager} and a
|
|
227
252
|
* single {@link RealtimeClientSessionService} are shared across requests — neither holds per-user or
|
|
@@ -272,7 +297,7 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
272
297
|
*
|
|
273
298
|
* @returns The ephemeral config + session linkage the browser needs to open its socket.
|
|
274
299
|
*/
|
|
275
|
-
async StartRealtimeClientSession(targetAgentId, { userPayload, providers }, conversationId, lastSessionId, preferredModelId, clientToolsJson, coAgentId, configOverridesJson) {
|
|
300
|
+
async StartRealtimeClientSession(targetAgentId, { userPayload, providers }, conversationId, lastSessionId, preferredModelId, clientToolsJson, coAgentId, configOverridesJson, recordingStartedAt, recordingConsent, mediaCollectionId, applicationId, appContextJson) {
|
|
276
301
|
const { contextUser, provider } = this.requireUserAndProvider(userPayload, providers);
|
|
277
302
|
const coAgentID = await this.resolveCoAgentID(targetAgentId, coAgentId, contextUser, provider);
|
|
278
303
|
// PAIRING CONSTRAINTS: a co-agent with pairing rows is restricted to that target list
|
|
@@ -284,7 +309,28 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
284
309
|
// the 'Realtime: Advanced Session Controls' authorization (structured rejection, never a
|
|
285
310
|
// silent ignore). Plain starts and within-pairing target selection are never gated here.
|
|
286
311
|
await this.assertRuntimeOverridesAuthorized(coAgentID, configOverridesJson, preferredModelId, contextUser, provider);
|
|
312
|
+
// PUBLIC WEB-WIDGET VOICE CAP (public-web-widget.md W4): when the caller is a widget guest,
|
|
313
|
+
// resolve the deployment's hard duration ceiling and stamp an absolute deadline on the session.
|
|
314
|
+
// The SessionJanitor force-closes (finalizing runs) past the deadline — a server-authoritative
|
|
315
|
+
// bound that does not depend on the client honoring its own abuse guard or the ephemeral token TTL.
|
|
316
|
+
const maxSessionSeconds = await this.resolveWidgetVoiceCapSeconds(userPayload, providers);
|
|
287
317
|
const config = { targetAgentID: effectiveTargetId };
|
|
318
|
+
if (maxSessionSeconds) {
|
|
319
|
+
config.maxSessionDeadlineIso = new Date(Date.now() + maxSessionSeconds * 1000).toISOString();
|
|
320
|
+
}
|
|
321
|
+
// Per-session media-kit override: stored on the session config so the server-side MediaChannelServer
|
|
322
|
+
// resolves it (over the agent default) at start. Validate the id here — a malformed value is
|
|
323
|
+
// dropped (logged), never interpolated; the session still starts and falls back to the agent kit.
|
|
324
|
+
const mediaOverride = mediaCollectionId?.trim();
|
|
325
|
+
if (mediaOverride) {
|
|
326
|
+
if (IsValidUUID(mediaOverride)) {
|
|
327
|
+
config.mediaCollectionID = mediaOverride;
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
LogStatus(`StartRealtimeClientSession: ignoring malformed mediaCollectionId '${mediaCollectionId}' — ` +
|
|
331
|
+
'using the agent default media kit.');
|
|
332
|
+
}
|
|
333
|
+
}
|
|
288
334
|
const session = await this.sessionManager.CreateSession({
|
|
289
335
|
agentID: coAgentID,
|
|
290
336
|
userID: contextUser.ID,
|
|
@@ -292,12 +338,14 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
292
338
|
lastSessionID: lastSessionId,
|
|
293
339
|
config: JSON.stringify(config),
|
|
294
340
|
}, contextUser, provider);
|
|
341
|
+
// Best-effort: stamp recording-start metadata when the browser captured (with consent) at start.
|
|
342
|
+
await this.stampRecordingStart(session, recordingConsent, recordingStartedAt);
|
|
295
343
|
const clientTools = this.parseClientTools(clientToolsJson);
|
|
296
344
|
// Best-effort model-context hydration: the PRIOR session chain's transcript (ownership-
|
|
297
345
|
// checked, capped) is framed into the system prompt so the model REMEMBERS the last leg.
|
|
298
346
|
// Strictly tolerant — any problem yields no hydration, never a failed start.
|
|
299
347
|
const priorTranscript = await this.loadPriorTranscript(lastSessionId, contextUser, provider);
|
|
300
|
-
const result = await this.prepareClientSessionOrClose(session, coAgentID, effectiveTargetId, contextUser, provider, preferredModelId, clientTools, priorTranscript, configOverridesJson);
|
|
348
|
+
const result = await this.prepareClientSessionOrClose(session, coAgentID, effectiveTargetId, contextUser, provider, preferredModelId, clientTools, priorTranscript, configOverridesJson, maxSessionSeconds, applicationId, this.parseAppContext(appContextJson));
|
|
301
349
|
// Best-effort restore of the PRIOR session's persisted channel states (e.g. the whiteboard
|
|
302
350
|
// board). Strictly tolerant — any problem yields a null field, never a failed start.
|
|
303
351
|
result.PriorChannelStatesJson = (await this.loadPriorChannelStatesJson(lastSessionId, contextUser, provider)) ?? undefined;
|
|
@@ -319,6 +367,9 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
319
367
|
const { ResultJson, PausedRunID, Artifacts } = await this.clientSessionService.ExecuteRelayedTool({
|
|
320
368
|
AgentSessionID: agentSessionId,
|
|
321
369
|
TargetAgentID: config.targetAgentID,
|
|
370
|
+
// Multi-target (Move 4): the session's persisted allowed-agent union — a model-named
|
|
371
|
+
// colleague in the call is validated against this; absent ⇒ single-target behavior.
|
|
372
|
+
AllowedAgents: config.allowedAgents,
|
|
322
373
|
// Nest the delegated target-agent run under the co-agent observability run (when present).
|
|
323
374
|
ParentRunID: config.coAgentRunID,
|
|
324
375
|
Call: { CallID: callId, ToolName: toolName, Arguments: argsJson },
|
|
@@ -378,6 +429,10 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
378
429
|
promptRunID: config.promptRunID,
|
|
379
430
|
coAgentRunStepID: config.coAgentRunStepID,
|
|
380
431
|
pendingFeedbackRunID: pausedRunID,
|
|
432
|
+
// Preserve the server-authoritative voice deadline across config rewrites.
|
|
433
|
+
maxSessionDeadlineIso: config.maxSessionDeadlineIso,
|
|
434
|
+
applicationID: config.applicationID,
|
|
435
|
+
allowedAgents: config.allowedAgents,
|
|
381
436
|
};
|
|
382
437
|
session.Config_ = JSON.stringify(next);
|
|
383
438
|
if (!(await session.Save())) {
|
|
@@ -397,12 +452,12 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
397
452
|
*
|
|
398
453
|
* @returns `true` when the transcript turn was persisted.
|
|
399
454
|
*/
|
|
400
|
-
async RelayRealtimeTranscript(agentSessionId, role, text, { userPayload, providers }, replacesPrevious) {
|
|
455
|
+
async RelayRealtimeTranscript(agentSessionId, role, text, { userPayload, providers }, replacesPrevious, utteranceStartMs, utteranceEndMs) {
|
|
401
456
|
const { contextUser, provider } = this.requireUserAndProvider(userPayload, providers);
|
|
402
457
|
const session = await this.loadOwnedActiveSession(agentSessionId, contextUser, provider);
|
|
403
458
|
const saved = replacesPrevious
|
|
404
|
-
? await this.replacePreviousTranscriptTurn(session, role, text, contextUser, provider)
|
|
405
|
-
: await this.persistTranscriptTurn(session, role, text, contextUser, provider);
|
|
459
|
+
? await this.replacePreviousTranscriptTurn(session, role, text, contextUser, provider, utteranceStartMs, utteranceEndMs)
|
|
460
|
+
: await this.persistTranscriptTurn(session, role, text, contextUser, provider, utteranceStartMs, utteranceEndMs);
|
|
406
461
|
if (!saved) {
|
|
407
462
|
return false;
|
|
408
463
|
}
|
|
@@ -423,6 +478,122 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
423
478
|
mapTranscriptRoleToChatRole(role) {
|
|
424
479
|
return role.trim().toLowerCase() === 'user' ? 'user' : 'assistant';
|
|
425
480
|
}
|
|
481
|
+
/**
|
|
482
|
+
* Upload a CLIENT-DIRECT session audio recording, store it in MJStorage, link it to the owning
|
|
483
|
+
* `AIAgentSession`, and stamp the session's recording fields. The browser records locally during
|
|
484
|
+
* the call and uploads the assembled blob (base64) once the session ends.
|
|
485
|
+
*
|
|
486
|
+
* Hard gates (in order):
|
|
487
|
+
* 1. Ownership — `loadOwnedSession` enforces `UserID === contextUser.ID` (throws on violation).
|
|
488
|
+
* 2. Consent — `consent !== true` is a hard refusal: no audio is ever stored without it.
|
|
489
|
+
* 3. Storage configuration — the session's agent must resolve a recording storage account (the
|
|
490
|
+
* agent's `RecordingStorageProviderID`, else `AttachmentStorageProviderID`).
|
|
491
|
+
*
|
|
492
|
+
* Storage failures (and any unexpected throw) come back as `Success: false` with a reason — they
|
|
493
|
+
* NEVER throw to the browser, mirroring the shared {@link storeRealtimeRecording} contract.
|
|
494
|
+
*
|
|
495
|
+
* @param agentSessionId The session the recording belongs to (ownership-gated).
|
|
496
|
+
* @param audioBase64 The base64-encoded recording bytes (client-direct: seekable WAV/PCM).
|
|
497
|
+
* @param mimeType The audio MIME type (`audio/wav` for client-direct; legacy `audio/webm`/`ogg`/`mp4`).
|
|
498
|
+
* @param durationMs Optional client-measured recording duration (ms) — informational.
|
|
499
|
+
* @param consent Whether the user consented to recording. MUST be `true` or the upload is refused.
|
|
500
|
+
* @param peaks Optional capture-time waveform peaks (max-abs per bucket, normalized 0..1). When
|
|
501
|
+
* present, persisted as a `peaks.json` sidecar beside the recording for fast waveform rendering
|
|
502
|
+
* without re-decoding the audio.
|
|
503
|
+
* @returns A structured {@link UploadRealtimeRecordingResult} with the created `MJ: Files` id.
|
|
504
|
+
*/
|
|
505
|
+
async UploadRealtimeRecording(agentSessionId, audioBase64, mimeType, ctx, durationMs, consent, peaks) {
|
|
506
|
+
const { contextUser, provider } = this.requireUserAndProvider(ctx.userPayload, ctx.providers);
|
|
507
|
+
const session = await this.loadOwnedSession(agentSessionId, contextUser, provider);
|
|
508
|
+
// HARD consent gate — no audio is ever stored without an explicit grant.
|
|
509
|
+
if (consent !== true) {
|
|
510
|
+
return { Success: false, ErrorMessage: 'Recording consent was not granted.' };
|
|
511
|
+
}
|
|
512
|
+
try {
|
|
513
|
+
const agent = await provider.GetEntityObject('MJ: AI Agents', contextUser);
|
|
514
|
+
if (!(await agent.Load(session.AgentID))) {
|
|
515
|
+
return { Success: false, ErrorMessage: `Co-agent ${session.AgentID} for the session could not be loaded.` };
|
|
516
|
+
}
|
|
517
|
+
const accountID = await resolveRecordingStorageAccountID(agent, contextUser, provider);
|
|
518
|
+
if (!accountID) {
|
|
519
|
+
return { Success: false, ErrorMessage: 'No recording storage account is configured for this agent.' };
|
|
520
|
+
}
|
|
521
|
+
const buffer = Buffer.from(audioBase64, 'base64');
|
|
522
|
+
if (buffer.length === 0) {
|
|
523
|
+
return { Success: false, ErrorMessage: 'The uploaded recording was empty.' };
|
|
524
|
+
}
|
|
525
|
+
const fileID = await storeRealtimeRecording({
|
|
526
|
+
Audio: buffer,
|
|
527
|
+
MimeType: mimeType,
|
|
528
|
+
Media: 'Audio',
|
|
529
|
+
StartedAt: session.RecordingStartedAt ?? new Date(),
|
|
530
|
+
StorageAccountID: accountID,
|
|
531
|
+
SessionID: agentSessionId,
|
|
532
|
+
ContextUser: contextUser,
|
|
533
|
+
Provider: provider,
|
|
534
|
+
// Sanitized capture-time waveform peaks → persisted as a peaks.json sidecar.
|
|
535
|
+
Peaks: this.sanitizePeaks(peaks),
|
|
536
|
+
});
|
|
537
|
+
// Canonical consolidated file written — drop the crash-recovery shards (best-effort).
|
|
538
|
+
if (fileID) {
|
|
539
|
+
await deleteRealtimeRecordingSegments(agentSessionId, accountID, contextUser);
|
|
540
|
+
}
|
|
541
|
+
return {
|
|
542
|
+
Success: !!fileID,
|
|
543
|
+
FileID: fileID ?? undefined,
|
|
544
|
+
ErrorMessage: fileID ? undefined : 'Storage upload failed.',
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
catch (error) {
|
|
548
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
549
|
+
LogError(`RealtimeClientSessionResolver.UploadRealtimeRecording failed for session ${agentSessionId}: ${message}`);
|
|
550
|
+
return { Success: false, ErrorMessage: message };
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Uploads ONE crash-recovery audio shard (~15s) for an IN-PROGRESS recording into the session's
|
|
555
|
+
* folder (`realtime-recordings/<sessionId>/seg-NNNN.<ext>`) as a raw storage object. Durability
|
|
556
|
+
* insurance during a live call so a browser/tab death loses at most the last window; the shards are
|
|
557
|
+
* deleted once the canonical consolidated file lands via {@link UploadRealtimeRecording}. Ownership-
|
|
558
|
+
* gated; consent was already established at session start. Best-effort — returns `false` (never
|
|
559
|
+
* throws) on any problem so a failed shard never disrupts the live call.
|
|
560
|
+
*
|
|
561
|
+
* @param agentSessionId The in-progress session (ownership-gated).
|
|
562
|
+
* @param segmentIndex 0-based shard index within the session.
|
|
563
|
+
* @param audioBase64 The base64-encoded shard bytes.
|
|
564
|
+
* @param mimeType The audio MIME type.
|
|
565
|
+
* @returns `true` when the shard was stored.
|
|
566
|
+
*/
|
|
567
|
+
async UploadRealtimeRecordingSegment(agentSessionId, segmentIndex, audioBase64, mimeType, ctx) {
|
|
568
|
+
try {
|
|
569
|
+
const { contextUser, provider } = this.requireUserAndProvider(ctx.userPayload, ctx.providers);
|
|
570
|
+
const session = await this.loadOwnedSession(agentSessionId, contextUser, provider);
|
|
571
|
+
const agent = await provider.GetEntityObject('MJ: AI Agents', contextUser);
|
|
572
|
+
if (!(await agent.Load(session.AgentID))) {
|
|
573
|
+
return false;
|
|
574
|
+
}
|
|
575
|
+
const accountID = await resolveRecordingStorageAccountID(agent, contextUser, provider);
|
|
576
|
+
if (!accountID) {
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
const buffer = Buffer.from(audioBase64, 'base64');
|
|
580
|
+
if (buffer.length === 0) {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
return await writeRealtimeRecordingSegment({
|
|
584
|
+
SessionID: agentSessionId,
|
|
585
|
+
SegmentIndex: segmentIndex,
|
|
586
|
+
Audio: buffer,
|
|
587
|
+
MimeType: mimeType,
|
|
588
|
+
StorageAccountID: accountID,
|
|
589
|
+
ContextUser: contextUser,
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
catch (error) {
|
|
593
|
+
LogError(`RealtimeClientSessionResolver.UploadRealtimeRecordingSegment failed for session ${agentSessionId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
594
|
+
return false;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
426
597
|
/**
|
|
427
598
|
* Relays a co-agent CHANNEL tool-call (browser_ / Whiteboard_ etc.) onto the session's co-agent
|
|
428
599
|
* AIPromptRun.Messages — run-only observability so the run captures what the co-agent DID, not just
|
|
@@ -525,6 +696,22 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
525
696
|
clampTokenDelta(value) {
|
|
526
697
|
return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
527
698
|
}
|
|
699
|
+
/**
|
|
700
|
+
* Sanitizes client-supplied waveform peaks before they're persisted: drops anything that isn't a
|
|
701
|
+
* finite number, clamps each to `[0, 1]`, and caps the array length so a hostile client can't bloat
|
|
702
|
+
* the sidecar. Returns `undefined` for a missing/empty array (no sidecar written).
|
|
703
|
+
*/
|
|
704
|
+
sanitizePeaks(peaks) {
|
|
705
|
+
if (!Array.isArray(peaks) || peaks.length === 0) {
|
|
706
|
+
return undefined;
|
|
707
|
+
}
|
|
708
|
+
const MAX_PEAKS = 4096; // generous ceiling above the client's ~600-bucket target
|
|
709
|
+
const cleaned = peaks
|
|
710
|
+
.slice(0, MAX_PEAKS)
|
|
711
|
+
.filter((v) => Number.isFinite(v))
|
|
712
|
+
.map((v) => (v < 0 ? 0 : v > 1 ? 1 : v));
|
|
713
|
+
return cleaned.length > 0 ? cleaned : undefined;
|
|
714
|
+
}
|
|
528
715
|
/**
|
|
529
716
|
* Reads the co-agent `AIPromptRun` id from the session config WITHOUT the relay path's
|
|
530
717
|
* throw-on-missing-target semantics — usage relay is best-effort, so a missing/malformed
|
|
@@ -1014,12 +1201,15 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
1014
1201
|
* (from {@link loadPriorTranscript}) — the service frames it into the system prompt so a
|
|
1015
1202
|
* resumed session remembers the previous leg(s).
|
|
1016
1203
|
*/
|
|
1017
|
-
async prepareClientSessionOrClose(session, coAgentID, targetAgentId, contextUser, provider, preferredModelId, clientTools, priorTranscript, configOverridesJson) {
|
|
1204
|
+
async prepareClientSessionOrClose(session, coAgentID, targetAgentId, contextUser, provider, preferredModelId, clientTools, priorTranscript, configOverridesJson, maxSessionSeconds, applicationId, appContext) {
|
|
1018
1205
|
const prep = await this.clientSessionService.PrepareClientSession({
|
|
1019
1206
|
CoAgentID: coAgentID,
|
|
1020
1207
|
TargetAgentID: targetAgentId,
|
|
1021
1208
|
AgentSessionID: session.ID,
|
|
1022
1209
|
ConversationID: session.ConversationID ?? undefined,
|
|
1210
|
+
// Server-authoritative voice duration cap (widget guests) — bounds the driver session
|
|
1211
|
+
// where supported; the janitor enforces the session deadline regardless.
|
|
1212
|
+
MaxSessionSeconds: maxSessionSeconds,
|
|
1023
1213
|
// MVP: conversation history is not yet hydrated into ChatMessage[]; the co-agent
|
|
1024
1214
|
// companion prompt runs without prior turns. A later phase loads the session's
|
|
1025
1215
|
// Conversation into ChatMessage[] for richer context.
|
|
@@ -1033,13 +1223,17 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
1033
1223
|
PriorTranscript: priorTranscript,
|
|
1034
1224
|
// Pre-authorized runtime override layer (assertRuntimeOverridesAuthorized gated it).
|
|
1035
1225
|
ConfigOverridesJson: configOverridesJson,
|
|
1226
|
+
// App awareness (Move 1/3/4): the app sources the app cascade layer + RelevantAgents
|
|
1227
|
+
// (allowed-agent union); the snapshot is injected into the system prompt at mint.
|
|
1228
|
+
ApplicationID: applicationId,
|
|
1229
|
+
AppContext: appContext,
|
|
1036
1230
|
}, contextUser, provider);
|
|
1037
1231
|
if (!prep.Success || !prep.ClientConfig) {
|
|
1038
1232
|
// Prep failure is an ERROR close, not an explicit user hang-up — stamp it as such.
|
|
1039
1233
|
await this.sessionManager.CloseSession(session.ID, contextUser, provider, 'Error');
|
|
1040
1234
|
throw new Error(prep.ErrorMessage ?? 'Failed to prepare the client realtime session.');
|
|
1041
1235
|
}
|
|
1042
|
-
await this.persistObservabilityRunIDs(session, targetAgentId, prep.CoAgentRunID, prep.PromptRunID, prep.CoAgentRunStepID);
|
|
1236
|
+
await this.persistObservabilityRunIDs(session, targetAgentId, prep.CoAgentRunID, prep.PromptRunID, prep.CoAgentRunStepID, applicationId, prep.EffectiveConfig?.realtime?.allowedAgents);
|
|
1043
1237
|
const cfg = prep.ClientConfig;
|
|
1044
1238
|
return {
|
|
1045
1239
|
AgentSessionId: session.ID,
|
|
@@ -1061,8 +1255,19 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
1061
1255
|
* finalize the runs (and on relay to nest delegated runs). Best-effort: a save failure is logged,
|
|
1062
1256
|
* not thrown — the voice session still proceeds, it just won't carry the run ids.
|
|
1063
1257
|
*/
|
|
1064
|
-
async persistObservabilityRunIDs(session, targetAgentID, coAgentRunID, promptRunID, coAgentRunStepID) {
|
|
1065
|
-
|
|
1258
|
+
async persistObservabilityRunIDs(session, targetAgentID, coAgentRunID, promptRunID, coAgentRunStepID, applicationID, allowedAgents) {
|
|
1259
|
+
// Preserve any server-authoritative voice deadline stamped at session start (this rebuilds the
|
|
1260
|
+
// full config, so read the existing value forward rather than dropping it).
|
|
1261
|
+
const existing = this.tryReadSessionConfig(session);
|
|
1262
|
+
const config = {
|
|
1263
|
+
targetAgentID,
|
|
1264
|
+
coAgentRunID,
|
|
1265
|
+
promptRunID,
|
|
1266
|
+
coAgentRunStepID,
|
|
1267
|
+
maxSessionDeadlineIso: existing?.maxSessionDeadlineIso,
|
|
1268
|
+
applicationID,
|
|
1269
|
+
allowedAgents: allowedAgents && allowedAgents.length > 0 ? allowedAgents : undefined,
|
|
1270
|
+
};
|
|
1066
1271
|
session.Config_ = JSON.stringify(config);
|
|
1067
1272
|
const saved = await session.Save();
|
|
1068
1273
|
if (!saved) {
|
|
@@ -1545,6 +1750,28 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
1545
1750
|
LogError(`SaveSessionChannelArtifact: LastActiveAt stamp failed: ${error.message}`);
|
|
1546
1751
|
}
|
|
1547
1752
|
}
|
|
1753
|
+
/**
|
|
1754
|
+
* Tolerantly parses the `appContextJson` mutation arg into an {@link AppContextSnapshot}. Returns
|
|
1755
|
+
* `undefined` for absent/blank/malformed/non-object payloads — app context is best-effort enrichment
|
|
1756
|
+
* and must never fail a session start.
|
|
1757
|
+
*
|
|
1758
|
+
* @param appContextJson The raw JSON string the browser sent, or undefined.
|
|
1759
|
+
* @returns The parsed snapshot, or `undefined`.
|
|
1760
|
+
*/
|
|
1761
|
+
parseAppContext(appContextJson) {
|
|
1762
|
+
if (!appContextJson || !appContextJson.trim()) {
|
|
1763
|
+
return undefined;
|
|
1764
|
+
}
|
|
1765
|
+
try {
|
|
1766
|
+
const parsed = JSON.parse(appContextJson);
|
|
1767
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
|
|
1768
|
+
? parsed
|
|
1769
|
+
: undefined;
|
|
1770
|
+
}
|
|
1771
|
+
catch {
|
|
1772
|
+
return undefined;
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1548
1775
|
/**
|
|
1549
1776
|
* Tolerantly parses + validates client-declared UI tool definitions (see the SECURITY NOTE on
|
|
1550
1777
|
* {@link StartRealtimeClientSession}). Never throws — any rejection logs and returns
|
|
@@ -1613,6 +1840,9 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
1613
1840
|
promptRunID: typeof parsed.promptRunID === 'string' ? parsed.promptRunID : undefined,
|
|
1614
1841
|
coAgentRunStepID: typeof parsed.coAgentRunStepID === 'string' ? parsed.coAgentRunStepID : undefined,
|
|
1615
1842
|
pendingFeedbackRunID: typeof parsed.pendingFeedbackRunID === 'string' ? parsed.pendingFeedbackRunID : undefined,
|
|
1843
|
+
maxSessionDeadlineIso: typeof parsed.maxSessionDeadlineIso === 'string' ? parsed.maxSessionDeadlineIso : undefined,
|
|
1844
|
+
applicationID: typeof parsed.applicationID === 'string' ? parsed.applicationID : undefined,
|
|
1845
|
+
allowedAgents: Array.isArray(parsed.allowedAgents) ? parsed.allowedAgents : undefined,
|
|
1616
1846
|
};
|
|
1617
1847
|
}
|
|
1618
1848
|
}
|
|
@@ -1622,13 +1852,58 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
1622
1852
|
}
|
|
1623
1853
|
throw new Error(`Realtime session ${session.ID} has no target agent configured`);
|
|
1624
1854
|
}
|
|
1855
|
+
/** Like {@link readSessionConfig} but returns `undefined` instead of throwing (for best-effort reads). */
|
|
1856
|
+
tryReadSessionConfig(session) {
|
|
1857
|
+
try {
|
|
1858
|
+
return this.readSessionConfig(session);
|
|
1859
|
+
}
|
|
1860
|
+
catch {
|
|
1861
|
+
return undefined;
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
/**
|
|
1865
|
+
* Resolves the server-authoritative voice duration cap (seconds) for a session start, or `undefined`
|
|
1866
|
+
* when no cap applies (the common, uncapped case). A cap applies only when the caller is a public
|
|
1867
|
+
* web-widget guest with a configured `VoiceMaxSessionMinutes` on its widget instance (the same value
|
|
1868
|
+
* surfaced to the client guard at mint). Never throws — a resolution failure yields no cap rather
|
|
1869
|
+
* than blocking the start.
|
|
1870
|
+
*/
|
|
1871
|
+
async resolveWidgetVoiceCapSeconds(userPayload, providers) {
|
|
1872
|
+
const elevation = await resolveWidgetGuestRunContext(userPayload, GetReadWriteProvider(providers));
|
|
1873
|
+
const minutes = elevation?.widget.VoiceMaxSessionMinutes;
|
|
1874
|
+
return minutes && minutes > 0 ? minutes * 60 : undefined;
|
|
1875
|
+
}
|
|
1625
1876
|
/**
|
|
1626
1877
|
* Persists a single transcript turn as a `Conversation Detail` stamped with the session's
|
|
1627
1878
|
* conversation, the mapped role, the turn text, the session id, and the owning user.
|
|
1628
1879
|
*
|
|
1629
1880
|
* @returns The boolean save result (logs `CompleteMessage` on failure).
|
|
1630
1881
|
*/
|
|
1631
|
-
|
|
1882
|
+
/**
|
|
1883
|
+
* Stamps `RecordingStartedAt` (the recording `t0` alignment origin) + `RecordingMedia` on a
|
|
1884
|
+
* just-started session when the browser captured WITH consent. Best-effort: a parse/save failure
|
|
1885
|
+
* is logged and swallowed — a recording-metadata problem must never fail the session start.
|
|
1886
|
+
*
|
|
1887
|
+
* @param session The freshly created/loaded session.
|
|
1888
|
+
* @param recordingConsent Whether the user consented to recording — only `true` stamps anything.
|
|
1889
|
+
* @param recordingStartedAt ISO-8601 recording start timestamp from the browser.
|
|
1890
|
+
*/
|
|
1891
|
+
async stampRecordingStart(session, recordingConsent, recordingStartedAt) {
|
|
1892
|
+
if (recordingConsent !== true || !recordingStartedAt) {
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
const startedAt = new Date(recordingStartedAt);
|
|
1896
|
+
if (Number.isNaN(startedAt.getTime())) {
|
|
1897
|
+
LogError(`RealtimeClientSessionResolver.stampRecordingStart: invalid recordingStartedAt '${recordingStartedAt}' for session ${session.ID}`);
|
|
1898
|
+
return;
|
|
1899
|
+
}
|
|
1900
|
+
session.RecordingStartedAt = startedAt;
|
|
1901
|
+
session.RecordingMedia = 'Audio';
|
|
1902
|
+
if (!(await session.Save())) {
|
|
1903
|
+
LogError(`RealtimeClientSessionResolver.stampRecordingStart save failed: ${session.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
async persistTranscriptTurn(session, role, text, contextUser, provider, utteranceStartMs, utteranceEndMs) {
|
|
1632
1907
|
const detail = await provider.GetEntityObject(CONVERSATION_DETAIL_ENTITY, contextUser);
|
|
1633
1908
|
detail.NewRecord();
|
|
1634
1909
|
detail.ConversationID = session.ConversationID;
|
|
@@ -1636,6 +1911,12 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
1636
1911
|
detail.Message = text;
|
|
1637
1912
|
detail.AgentSessionID = session.ID;
|
|
1638
1913
|
detail.UserID = contextUser.ID;
|
|
1914
|
+
if (typeof utteranceStartMs === 'number' && utteranceStartMs >= 0) {
|
|
1915
|
+
detail.UtteranceStartMs = utteranceStartMs;
|
|
1916
|
+
}
|
|
1917
|
+
if (typeof utteranceEndMs === 'number' && utteranceEndMs >= 0) {
|
|
1918
|
+
detail.UtteranceEndMs = utteranceEndMs;
|
|
1919
|
+
}
|
|
1639
1920
|
const saved = await detail.Save();
|
|
1640
1921
|
if (!saved) {
|
|
1641
1922
|
LogError(`RealtimeClientSessionResolver.persistTranscriptTurn save failed: ${detail.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
@@ -1649,7 +1930,7 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
1649
1930
|
* appending a near-duplicate. Falls back to a plain insert when no prior turn exists
|
|
1650
1931
|
* (the superseded turn may have failed to persist) — a correction is never dropped.
|
|
1651
1932
|
*/
|
|
1652
|
-
async replacePreviousTranscriptTurn(session, role, text, contextUser, provider) {
|
|
1933
|
+
async replacePreviousTranscriptTurn(session, role, text, contextUser, provider, utteranceStartMs, utteranceEndMs) {
|
|
1653
1934
|
const mappedRole = this.mapTranscriptRole(role);
|
|
1654
1935
|
const rv = RunView.FromMetadataProvider(provider);
|
|
1655
1936
|
const result = await rv.RunView({
|
|
@@ -1661,9 +1942,17 @@ let RealtimeClientSessionResolver = class RealtimeClientSessionResolver extends
|
|
|
1661
1942
|
}, contextUser);
|
|
1662
1943
|
const previous = result.Success ? (result.Results?.[0] ?? null) : null;
|
|
1663
1944
|
if (!previous) {
|
|
1664
|
-
return this.persistTranscriptTurn(session, role, text, contextUser, provider);
|
|
1945
|
+
return this.persistTranscriptTurn(session, role, text, contextUser, provider, utteranceStartMs, utteranceEndMs);
|
|
1665
1946
|
}
|
|
1666
1947
|
previous.Message = text;
|
|
1948
|
+
// The correction extends the existing turn: always refresh the end boundary when provided,
|
|
1949
|
+
// but only set the start when it wasn't already captured on the superseded turn.
|
|
1950
|
+
if (typeof utteranceEndMs === 'number' && utteranceEndMs >= 0) {
|
|
1951
|
+
previous.UtteranceEndMs = utteranceEndMs;
|
|
1952
|
+
}
|
|
1953
|
+
if (typeof utteranceStartMs === 'number' && utteranceStartMs >= 0 && previous.UtteranceStartMs == null) {
|
|
1954
|
+
previous.UtteranceStartMs = utteranceStartMs;
|
|
1955
|
+
}
|
|
1667
1956
|
const saved = await previous.Save();
|
|
1668
1957
|
if (!saved) {
|
|
1669
1958
|
LogError(`RealtimeClientSessionResolver.replacePreviousTranscriptTurn save failed: ${previous.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
@@ -1689,8 +1978,13 @@ __decorate([
|
|
|
1689
1978
|
__param(5, Arg('clientToolsJson', () => String, { nullable: true })),
|
|
1690
1979
|
__param(6, Arg('coAgentId', () => String, { nullable: true })),
|
|
1691
1980
|
__param(7, Arg('configOverridesJson', () => String, { nullable: true })),
|
|
1981
|
+
__param(8, Arg('recordingStartedAt', () => String, { nullable: true })),
|
|
1982
|
+
__param(9, Arg('recordingConsent', () => Boolean, { nullable: true })),
|
|
1983
|
+
__param(10, Arg('mediaCollectionId', () => String, { nullable: true })),
|
|
1984
|
+
__param(11, Arg('applicationId', () => String, { nullable: true })),
|
|
1985
|
+
__param(12, Arg('appContextJson', () => String, { nullable: true })),
|
|
1692
1986
|
__metadata("design:type", Function),
|
|
1693
|
-
__metadata("design:paramtypes", [String, Object, String, String, String, String, String, String]),
|
|
1987
|
+
__metadata("design:paramtypes", [String, Object, String, String, String, String, String, String, String, Boolean, String, String, String]),
|
|
1694
1988
|
__metadata("design:returntype", Promise)
|
|
1695
1989
|
], RealtimeClientSessionResolver.prototype, "StartRealtimeClientSession", null);
|
|
1696
1990
|
__decorate([
|
|
@@ -1712,10 +2006,36 @@ __decorate([
|
|
|
1712
2006
|
__param(2, Arg('text', () => String)),
|
|
1713
2007
|
__param(3, Ctx()),
|
|
1714
2008
|
__param(4, Arg('replacesPrevious', () => Boolean, { nullable: true })),
|
|
2009
|
+
__param(5, Arg('utteranceStartMs', () => Int, { nullable: true })),
|
|
2010
|
+
__param(6, Arg('utteranceEndMs', () => Int, { nullable: true })),
|
|
1715
2011
|
__metadata("design:type", Function),
|
|
1716
|
-
__metadata("design:paramtypes", [String, String, String, Object, Boolean]),
|
|
2012
|
+
__metadata("design:paramtypes", [String, String, String, Object, Boolean, Number, Number]),
|
|
1717
2013
|
__metadata("design:returntype", Promise)
|
|
1718
2014
|
], RealtimeClientSessionResolver.prototype, "RelayRealtimeTranscript", null);
|
|
2015
|
+
__decorate([
|
|
2016
|
+
Mutation(() => UploadRealtimeRecordingResult),
|
|
2017
|
+
__param(0, Arg('agentSessionId', () => String)),
|
|
2018
|
+
__param(1, Arg('audioBase64', () => String)),
|
|
2019
|
+
__param(2, Arg('mimeType', () => String)),
|
|
2020
|
+
__param(3, Ctx()),
|
|
2021
|
+
__param(4, Arg('durationMs', () => Int, { nullable: true })),
|
|
2022
|
+
__param(5, Arg('consent', () => Boolean, { nullable: true })),
|
|
2023
|
+
__param(6, Arg('peaks', () => [Float], { nullable: true })),
|
|
2024
|
+
__metadata("design:type", Function),
|
|
2025
|
+
__metadata("design:paramtypes", [String, String, String, Object, Number, Boolean, Array]),
|
|
2026
|
+
__metadata("design:returntype", Promise)
|
|
2027
|
+
], RealtimeClientSessionResolver.prototype, "UploadRealtimeRecording", null);
|
|
2028
|
+
__decorate([
|
|
2029
|
+
Mutation(() => Boolean),
|
|
2030
|
+
__param(0, Arg('agentSessionId', () => String)),
|
|
2031
|
+
__param(1, Arg('segmentIndex', () => Int)),
|
|
2032
|
+
__param(2, Arg('audioBase64', () => String)),
|
|
2033
|
+
__param(3, Arg('mimeType', () => String)),
|
|
2034
|
+
__param(4, Ctx()),
|
|
2035
|
+
__metadata("design:type", Function),
|
|
2036
|
+
__metadata("design:paramtypes", [String, Number, String, String, Object]),
|
|
2037
|
+
__metadata("design:returntype", Promise)
|
|
2038
|
+
], RealtimeClientSessionResolver.prototype, "UploadRealtimeRecordingSegment", null);
|
|
1719
2039
|
__decorate([
|
|
1720
2040
|
Mutation(() => Boolean),
|
|
1721
2041
|
__param(0, Arg('agentSessionId', () => String)),
|