@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ringcentral-runtime.js","sourceRoot":"","sources":["../../src/telephony/ringcentral-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,IAAI,kBAA2D,CAAC;AAEhE,6FAA6F;AAC7F,MAAM,UAAU,8BAA8B,CAAC,OAAoC;IAC/E,kBAAkB,GAAG,OAAO,CAAC;AACjC,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,8BAA8B;IAC1C,OAAO,kBAAkB,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Process-wide holder for the startup-constructed Teams meetings service, so the
|
|
3
|
+
* `StartTeamsMeetingSession` GraphQL resolver reaches the SAME {@link TeamsMeetingsService} (and thus the
|
|
4
|
+
* same {@link TeamsAcsMediaRegistry} the ACS media adapter attaches transports to) that the Graph
|
|
5
|
+
* change-notification webhook router uses. Set once during server boot; read by the resolver + the router.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors `telephony-runtime.ts` (the Twilio equivalent).
|
|
8
|
+
*
|
|
9
|
+
* @module @memberjunction/server/telephony
|
|
10
|
+
*/
|
|
11
|
+
import type { TeamsMeetingsService } from './TeamsMeetingsService.js';
|
|
12
|
+
/** Binds the startup-constructed Teams meetings service (called from server boot). */
|
|
13
|
+
export declare function SetTeamsMeetingsService(service: TeamsMeetingsService): void;
|
|
14
|
+
/** Returns the bound Teams meetings service, or `undefined` when Teams meetings are not configured. */
|
|
15
|
+
export declare function GetTeamsMeetingsService(): TeamsMeetingsService | undefined;
|
|
16
|
+
//# sourceMappingURL=teams-meetings-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teams-meetings-runtime.d.ts","sourceRoot":"","sources":["../../src/telephony/teams-meetings-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAItE,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAE3E;AAED,uGAAuG;AACvG,wBAAgB,uBAAuB,IAAI,oBAAoB,GAAG,SAAS,CAE1E"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Process-wide holder for the startup-constructed Teams meetings service, so the
|
|
3
|
+
* `StartTeamsMeetingSession` GraphQL resolver reaches the SAME {@link TeamsMeetingsService} (and thus the
|
|
4
|
+
* same {@link TeamsAcsMediaRegistry} the ACS media adapter attaches transports to) that the Graph
|
|
5
|
+
* change-notification webhook router uses. Set once during server boot; read by the resolver + the router.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors `telephony-runtime.ts` (the Twilio equivalent).
|
|
8
|
+
*
|
|
9
|
+
* @module @memberjunction/server/telephony
|
|
10
|
+
*/
|
|
11
|
+
let teamsService;
|
|
12
|
+
/** Binds the startup-constructed Teams meetings service (called from server boot). */
|
|
13
|
+
export function SetTeamsMeetingsService(service) {
|
|
14
|
+
teamsService = service;
|
|
15
|
+
}
|
|
16
|
+
/** Returns the bound Teams meetings service, or `undefined` when Teams meetings are not configured. */
|
|
17
|
+
export function GetTeamsMeetingsService() {
|
|
18
|
+
return teamsService;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=teams-meetings-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teams-meetings-runtime.js","sourceRoot":"","sources":["../../src/telephony/teams-meetings-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,IAAI,YAA8C,CAAC;AAEnD,sFAAsF;AACtF,MAAM,UAAU,uBAAuB,CAAC,OAA6B;IACjE,YAAY,GAAG,OAAO,CAAC;AAC3B,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,uBAAuB;IACnC,OAAO,YAAY,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Per-call ACS application-hosted-media pump registry for the Teams meetings ingress.
|
|
3
|
+
*
|
|
4
|
+
* This is the server half of the Teams audio plane — the analogue of {@link TwilioCallMediaRegistry} for
|
|
5
|
+
* telephony. It implements the Teams provider package's `IAcsMediaPump` seam (which `PumpBackedAcsMedia` →
|
|
6
|
+
* `RealTeamsBindings` drive) on top of the live ACS application-hosted-media audio socket(s) the server owns.
|
|
7
|
+
*
|
|
8
|
+
* Like telephony, there is a lifecycle gap: when a meeting bridge session starts, `RealTeamsBindings`
|
|
9
|
+
* registers its inbound-audio handler before the ACS media socket has connected its inbound stream. The
|
|
10
|
+
* registry bridges that gap by buffering handler registrations + outbound PCM per call id and binding them to
|
|
11
|
+
* the media transport once it attaches (the server's native ACS media adapter calls {@link AttachTransport}
|
|
12
|
+
* when the application-hosted-media socket is up for the call).
|
|
13
|
+
*
|
|
14
|
+
* Pure + unit-testable: the media transport is injected as the minimal {@link IAcsMediaTransport} surface, so
|
|
15
|
+
* the registry's buffering / dispatch logic is exercised with a fake transport and no ACS install or network.
|
|
16
|
+
*
|
|
17
|
+
* @module @memberjunction/server/telephony
|
|
18
|
+
*/
|
|
19
|
+
import type { AcsInboundAudioFrame, IAcsMediaPump } from '@memberjunction/ai-bridge-teams';
|
|
20
|
+
/**
|
|
21
|
+
* The minimal ACS media-transport surface the registry drives — a structural subset of the server's native
|
|
22
|
+
* application-hosted-media socket adapter, so the registry never imports the ACS SDK and is testable with a
|
|
23
|
+
* fake. Outbound frames are raw PCM16 `ArrayBuffer`s for the call.
|
|
24
|
+
*/
|
|
25
|
+
export interface IAcsMediaTransport {
|
|
26
|
+
/** Sends one outbound PCM16 frame on the call's application-hosted-media outbound audio socket. */
|
|
27
|
+
sendAudioFrame(pcm: ArrayBuffer): void;
|
|
28
|
+
/** Closes the call's media transport (best-effort; called on call end). */
|
|
29
|
+
close(): void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Coordinates ACS application-hosted-media transports with the bridge bindings, keyed by Graph call id. One
|
|
33
|
+
* instance per server, shared between the meetings service (which binds `PumpBackedAcsMedia` over this as the
|
|
34
|
+
* `IAcsMediaPump`) and the server's native ACS media adapter (which attaches transports + dispatches inbound
|
|
35
|
+
* audio).
|
|
36
|
+
*/
|
|
37
|
+
export declare class TeamsAcsMediaRegistry implements IAcsMediaPump {
|
|
38
|
+
readonly SampleRate: number;
|
|
39
|
+
private readonly channels;
|
|
40
|
+
/**
|
|
41
|
+
* @param SampleRate The ACS audio-socket sample rate in Hz (the application-hosted-media PCM rate the
|
|
42
|
+
* server negotiates). Drives T0 resampling in `RealTeamsBindings`. Defaults to 16000.
|
|
43
|
+
*/
|
|
44
|
+
constructor(SampleRate?: number);
|
|
45
|
+
/** Ensures a channel exists for a call (called when a meeting bridge session for the call starts). */
|
|
46
|
+
RegisterCall(callId: string): void;
|
|
47
|
+
/** @inheritdoc — buffers when the transport has not yet attached; sends immediately once it has. */
|
|
48
|
+
Send(callId: string, pcm: ArrayBuffer): void;
|
|
49
|
+
/** @inheritdoc — stores the handler so frames delivered before AND after transport attach reach it. */
|
|
50
|
+
OnFrame(callId: string, handler: (frame: AcsInboundAudioFrame) => void): void;
|
|
51
|
+
/** @inheritdoc — stores the hand-raise handler (Teams hand-raise is partial; tolerated if it never fires). */
|
|
52
|
+
OnHandRaise(callId: string, handler: (participantId: string, raised: boolean) => void): void;
|
|
53
|
+
/**
|
|
54
|
+
* Binds a connected ACS media transport to a call, flushing any outbound PCM produced while the transport
|
|
55
|
+
* was still connecting. Called by the server's native ACS media adapter once the application-hosted-media
|
|
56
|
+
* socket is up for the call.
|
|
57
|
+
*/
|
|
58
|
+
AttachTransport(callId: string, transport: IAcsMediaTransport): void;
|
|
59
|
+
/** Dispatches one inbound per-participant audio frame to all registered handlers for the call. */
|
|
60
|
+
DispatchInbound(callId: string, frame: AcsInboundAudioFrame): void;
|
|
61
|
+
/** Dispatches one raised-hand signal to all registered hand-raise handlers for the call. */
|
|
62
|
+
DispatchHandRaise(callId: string, participantId: string, raised: boolean): void;
|
|
63
|
+
/** Tears down a call's channel and closes its transport (called on call end / meeting ended). */
|
|
64
|
+
EndCall(callId: string): void;
|
|
65
|
+
/** Whether a channel is currently tracked for the call (test/observability helper). */
|
|
66
|
+
HasCall(callId: string): boolean;
|
|
67
|
+
private ensureChannel;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=teamsAcsMediaRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teamsAcsMediaRegistry.d.ts","sourceRoot":"","sources":["../../src/telephony/teamsAcsMediaRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAE3F;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAC/B,mGAAmG;IACnG,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC;IACvC,2EAA2E;IAC3E,KAAK,IAAI,IAAI,CAAC;CACjB;AAaD;;;;;GAKG;AACH,qBAAa,qBAAsB,YAAW,aAAa;aAO3B,UAAU;IANtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAEhE;;;OAGG;gBACyB,UAAU,SAAQ;IAE9C,sGAAsG;IAC/F,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAMzC,oGAAoG;IAC7F,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI;IASnD,uGAAuG;IAChG,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,IAAI;IAIpF,8GAA8G;IACvG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAMnG;;;;OAIG;IACI,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,kBAAkB,GAAG,IAAI;IAS3E,kGAAkG;IAC3F,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,oBAAoB,GAAG,IAAI;IAUzE,4FAA4F;IACrF,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI;IAUtF,iGAAiG;IAC1F,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAapC,uFAAuF;IAChF,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIvC,OAAO,CAAC,aAAa;CAQxB"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Per-call ACS application-hosted-media pump registry for the Teams meetings ingress.
|
|
3
|
+
*
|
|
4
|
+
* This is the server half of the Teams audio plane — the analogue of {@link TwilioCallMediaRegistry} for
|
|
5
|
+
* telephony. It implements the Teams provider package's `IAcsMediaPump` seam (which `PumpBackedAcsMedia` →
|
|
6
|
+
* `RealTeamsBindings` drive) on top of the live ACS application-hosted-media audio socket(s) the server owns.
|
|
7
|
+
*
|
|
8
|
+
* Like telephony, there is a lifecycle gap: when a meeting bridge session starts, `RealTeamsBindings`
|
|
9
|
+
* registers its inbound-audio handler before the ACS media socket has connected its inbound stream. The
|
|
10
|
+
* registry bridges that gap by buffering handler registrations + outbound PCM per call id and binding them to
|
|
11
|
+
* the media transport once it attaches (the server's native ACS media adapter calls {@link AttachTransport}
|
|
12
|
+
* when the application-hosted-media socket is up for the call).
|
|
13
|
+
*
|
|
14
|
+
* Pure + unit-testable: the media transport is injected as the minimal {@link IAcsMediaTransport} surface, so
|
|
15
|
+
* the registry's buffering / dispatch logic is exercised with a fake transport and no ACS install or network.
|
|
16
|
+
*
|
|
17
|
+
* @module @memberjunction/server/telephony
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Coordinates ACS application-hosted-media transports with the bridge bindings, keyed by Graph call id. One
|
|
21
|
+
* instance per server, shared between the meetings service (which binds `PumpBackedAcsMedia` over this as the
|
|
22
|
+
* `IAcsMediaPump`) and the server's native ACS media adapter (which attaches transports + dispatches inbound
|
|
23
|
+
* audio).
|
|
24
|
+
*/
|
|
25
|
+
export class TeamsAcsMediaRegistry {
|
|
26
|
+
/**
|
|
27
|
+
* @param SampleRate The ACS audio-socket sample rate in Hz (the application-hosted-media PCM rate the
|
|
28
|
+
* server negotiates). Drives T0 resampling in `RealTeamsBindings`. Defaults to 16000.
|
|
29
|
+
*/
|
|
30
|
+
constructor(SampleRate = 16000) {
|
|
31
|
+
this.SampleRate = SampleRate;
|
|
32
|
+
this.channels = new Map();
|
|
33
|
+
}
|
|
34
|
+
/** Ensures a channel exists for a call (called when a meeting bridge session for the call starts). */
|
|
35
|
+
RegisterCall(callId) {
|
|
36
|
+
this.ensureChannel(callId);
|
|
37
|
+
}
|
|
38
|
+
// ── IAcsMediaPump ─────────────────────────────────────────────────────────────
|
|
39
|
+
/** @inheritdoc — buffers when the transport has not yet attached; sends immediately once it has. */
|
|
40
|
+
Send(callId, pcm) {
|
|
41
|
+
const channel = this.ensureChannel(callId);
|
|
42
|
+
if (channel.transport) {
|
|
43
|
+
channel.transport.sendAudioFrame(pcm);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
channel.outboundBuffer.push(pcm);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** @inheritdoc — stores the handler so frames delivered before AND after transport attach reach it. */
|
|
50
|
+
OnFrame(callId, handler) {
|
|
51
|
+
this.ensureChannel(callId).frameHandlers.push(handler);
|
|
52
|
+
}
|
|
53
|
+
/** @inheritdoc — stores the hand-raise handler (Teams hand-raise is partial; tolerated if it never fires). */
|
|
54
|
+
OnHandRaise(callId, handler) {
|
|
55
|
+
this.ensureChannel(callId).handRaiseHandlers.push(handler);
|
|
56
|
+
}
|
|
57
|
+
// ── native-adapter side ─────────────────────────────────────────────────────
|
|
58
|
+
/**
|
|
59
|
+
* Binds a connected ACS media transport to a call, flushing any outbound PCM produced while the transport
|
|
60
|
+
* was still connecting. Called by the server's native ACS media adapter once the application-hosted-media
|
|
61
|
+
* socket is up for the call.
|
|
62
|
+
*/
|
|
63
|
+
AttachTransport(callId, transport) {
|
|
64
|
+
const channel = this.ensureChannel(callId);
|
|
65
|
+
channel.transport = transport;
|
|
66
|
+
const buffered = channel.outboundBuffer.splice(0, channel.outboundBuffer.length);
|
|
67
|
+
for (const pcm of buffered) {
|
|
68
|
+
transport.sendAudioFrame(pcm);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Dispatches one inbound per-participant audio frame to all registered handlers for the call. */
|
|
72
|
+
DispatchInbound(callId, frame) {
|
|
73
|
+
const channel = this.channels.get(callId);
|
|
74
|
+
if (!channel) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
for (const handler of channel.frameHandlers) {
|
|
78
|
+
handler(frame);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Dispatches one raised-hand signal to all registered hand-raise handlers for the call. */
|
|
82
|
+
DispatchHandRaise(callId, participantId, raised) {
|
|
83
|
+
const channel = this.channels.get(callId);
|
|
84
|
+
if (!channel) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
for (const handler of channel.handRaiseHandlers) {
|
|
88
|
+
handler(participantId, raised);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** Tears down a call's channel and closes its transport (called on call end / meeting ended). */
|
|
92
|
+
EndCall(callId) {
|
|
93
|
+
const channel = this.channels.get(callId);
|
|
94
|
+
if (!channel) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
channel.transport?.close();
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
/* best-effort */
|
|
102
|
+
}
|
|
103
|
+
this.channels.delete(callId);
|
|
104
|
+
}
|
|
105
|
+
/** Whether a channel is currently tracked for the call (test/observability helper). */
|
|
106
|
+
HasCall(callId) {
|
|
107
|
+
return this.channels.has(callId);
|
|
108
|
+
}
|
|
109
|
+
ensureChannel(callId) {
|
|
110
|
+
let channel = this.channels.get(callId);
|
|
111
|
+
if (!channel) {
|
|
112
|
+
channel = { frameHandlers: [], handRaiseHandlers: [], outboundBuffer: [] };
|
|
113
|
+
this.channels.set(callId, channel);
|
|
114
|
+
}
|
|
115
|
+
return channel;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=teamsAcsMediaRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teamsAcsMediaRegistry.js","sourceRoot":"","sources":["../../src/telephony/teamsAcsMediaRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Process-wide holder for the startup-constructed telephony service, so the
|
|
3
|
+
* outbound `PlaceTwilioCall` GraphQL resolver reaches the SAME {@link TwilioTelephonyService}
|
|
4
|
+
* (and thus the same {@link TwilioCallMediaRegistry} the Media-Streams WSS attaches sockets to)
|
|
5
|
+
* that the inbound webhook router uses. Set once during server boot; read by the resolver.
|
|
6
|
+
*
|
|
7
|
+
* @module @memberjunction/server/telephony
|
|
8
|
+
*/
|
|
9
|
+
import type { TwilioTelephonyService } from './TwilioTelephonyService.js';
|
|
10
|
+
/** Binds the startup-constructed Twilio telephony service (called from server boot). */
|
|
11
|
+
export declare function SetTwilioTelephonyService(service: TwilioTelephonyService): void;
|
|
12
|
+
/** Returns the bound Twilio telephony service, or `undefined` when telephony is not configured. */
|
|
13
|
+
export declare function GetTwilioTelephonyService(): TwilioTelephonyService | undefined;
|
|
14
|
+
//# sourceMappingURL=telephony-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telephony-runtime.d.ts","sourceRoot":"","sources":["../../src/telephony/telephony-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAI1E,wFAAwF;AACxF,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAE/E;AAED,mGAAmG;AACnG,wBAAgB,yBAAyB,IAAI,sBAAsB,GAAG,SAAS,CAE9E"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Process-wide holder for the startup-constructed telephony service, so the
|
|
3
|
+
* outbound `PlaceTwilioCall` GraphQL resolver reaches the SAME {@link TwilioTelephonyService}
|
|
4
|
+
* (and thus the same {@link TwilioCallMediaRegistry} the Media-Streams WSS attaches sockets to)
|
|
5
|
+
* that the inbound webhook router uses. Set once during server boot; read by the resolver.
|
|
6
|
+
*
|
|
7
|
+
* @module @memberjunction/server/telephony
|
|
8
|
+
*/
|
|
9
|
+
let twilioService;
|
|
10
|
+
/** Binds the startup-constructed Twilio telephony service (called from server boot). */
|
|
11
|
+
export function SetTwilioTelephonyService(service) {
|
|
12
|
+
twilioService = service;
|
|
13
|
+
}
|
|
14
|
+
/** Returns the bound Twilio telephony service, or `undefined` when telephony is not configured. */
|
|
15
|
+
export function GetTwilioTelephonyService() {
|
|
16
|
+
return twilioService;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=telephony-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telephony-runtime.js","sourceRoot":"","sources":["../../src/telephony/telephony-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,IAAI,aAAiD,CAAC;AAEtD,wFAAwF;AACxF,MAAM,UAAU,yBAAyB,CAAC,OAA+B;IACrE,aAAa,GAAG,OAAO,CAAC;AAC5B,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,yBAAyB;IACrC,OAAO,aAAa,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Per-call Media-Streams pump registry for the Twilio telephony ingress.
|
|
3
|
+
*
|
|
4
|
+
* This is the server half of the Twilio media plane: it implements the provider package's
|
|
5
|
+
* `ITwilioMediaPump` seam (which `RealTwilioBindings` drives) on top of the live Media-Streams
|
|
6
|
+
* websockets MJAPI accepts at `WSS /telephony/twilio/media`. It exists because of a lifecycle gap:
|
|
7
|
+
* when an INBOUND call's webhook fires, the bridge session starts and `RealTwilioBindings` registers
|
|
8
|
+
* its inbound-audio handler — but Twilio has not yet opened the media websocket (it does so only AFTER
|
|
9
|
+
* the webhook's `<Connect><Stream>` TwiML response). The registry bridges that gap by buffering
|
|
10
|
+
* handler registrations + outbound frames per Call SID and binding them to the socket once it connects
|
|
11
|
+
* (matched on the `start` frame's Call SID).
|
|
12
|
+
*
|
|
13
|
+
* Pure + unit-testable: the websocket is injected as the minimal {@link ITelephonyMediaSocket} surface,
|
|
14
|
+
* so the registry's buffering / dispatch / stream-SID capture logic is exercised with a fake socket and
|
|
15
|
+
* no `ws` install or network.
|
|
16
|
+
*
|
|
17
|
+
* @module @memberjunction/server/telephony
|
|
18
|
+
*/
|
|
19
|
+
import type { TwilioMediaFrame } from '@memberjunction/ai-bridge-twilio';
|
|
20
|
+
import type { ITwilioMediaPump } from '@memberjunction/ai-bridge-twilio';
|
|
21
|
+
/**
|
|
22
|
+
* The minimal websocket surface the registry drives — a structural subset of a `ws` socket, so the
|
|
23
|
+
* registry never imports `ws` and is testable with a fake. Outbound frames are sent as JSON strings.
|
|
24
|
+
*/
|
|
25
|
+
export interface ITelephonyMediaSocket {
|
|
26
|
+
/** Sends a serialized outbound Media-Streams frame on the call's socket. */
|
|
27
|
+
send(data: string): void;
|
|
28
|
+
/** Closes the socket (best-effort; called on call end). */
|
|
29
|
+
close(): void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Coordinates Media-Streams sockets with the bridge bindings, keyed by Call SID. One instance per
|
|
33
|
+
* server, shared between the inbound-webhook service (which binds `RealTwilioBindings` over this as the
|
|
34
|
+
* `ITwilioMediaPump`) and the WSS server (which attaches sockets + dispatches inbound frames).
|
|
35
|
+
*/
|
|
36
|
+
export declare class TwilioCallMediaRegistry implements ITwilioMediaPump {
|
|
37
|
+
private readonly channels;
|
|
38
|
+
/** Ensures a channel exists for a call (called when a bridge session for the call starts). */
|
|
39
|
+
RegisterCall(callSid: string): void;
|
|
40
|
+
/** @inheritdoc — buffers when the socket has not yet connected; sends immediately once it has. */
|
|
41
|
+
Send(callSid: string, frame: TwilioMediaFrame): void;
|
|
42
|
+
/** @inheritdoc — stores the handler so frames delivered before AND after socket connect reach it. */
|
|
43
|
+
OnFrame(callSid: string, handler: (frame: TwilioMediaFrame) => void): void;
|
|
44
|
+
/** @inheritdoc — the captured stream SID, or `''` until the `start` frame arrives. */
|
|
45
|
+
GetStreamSid(callSid: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Binds a connected Media-Streams socket (and its captured stream SID) to a call, flushing any
|
|
48
|
+
* outbound frames produced while the socket was still connecting. Called by the WSS server on the
|
|
49
|
+
* `start` frame.
|
|
50
|
+
*/
|
|
51
|
+
AttachSocket(callSid: string, socket: ITelephonyMediaSocket, streamSid: string): void;
|
|
52
|
+
/** Dispatches one inbound Media-Streams frame to all registered handlers for the call. */
|
|
53
|
+
DispatchInbound(callSid: string, frame: TwilioMediaFrame): void;
|
|
54
|
+
/** Tears down a call's channel and closes its socket (called on socket close / call end). */
|
|
55
|
+
EndCall(callSid: string): void;
|
|
56
|
+
/** Whether a channel is currently tracked for the call (test/observability helper). */
|
|
57
|
+
HasCall(callSid: string): boolean;
|
|
58
|
+
private ensureChannel;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=twilioMediaRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"twilioMediaRegistry.d.ts","sourceRoot":"","sources":["../../src/telephony/twilioMediaRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzE;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IAClC,4EAA4E;IAC5E,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,2DAA2D;IAC3D,KAAK,IAAI,IAAI,CAAC;CACjB;AAYD;;;;GAIG;AACH,qBAAa,uBAAwB,YAAW,gBAAgB;IAC5D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAEhE,8FAA8F;IACvF,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM1C,kGAAkG;IAC3F,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAS3D,qGAAqG;IAC9F,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAAG,IAAI;IAIjF,sFAAsF;IAC/E,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAM5C;;;;OAIG;IACI,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAU5F,0FAA0F;IACnF,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAatE,6FAA6F;IACtF,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAarC,uFAAuF;IAChF,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIxC,OAAO,CAAC,aAAa;CAQxB"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Per-call Media-Streams pump registry for the Twilio telephony ingress.
|
|
3
|
+
*
|
|
4
|
+
* This is the server half of the Twilio media plane: it implements the provider package's
|
|
5
|
+
* `ITwilioMediaPump` seam (which `RealTwilioBindings` drives) on top of the live Media-Streams
|
|
6
|
+
* websockets MJAPI accepts at `WSS /telephony/twilio/media`. It exists because of a lifecycle gap:
|
|
7
|
+
* when an INBOUND call's webhook fires, the bridge session starts and `RealTwilioBindings` registers
|
|
8
|
+
* its inbound-audio handler — but Twilio has not yet opened the media websocket (it does so only AFTER
|
|
9
|
+
* the webhook's `<Connect><Stream>` TwiML response). The registry bridges that gap by buffering
|
|
10
|
+
* handler registrations + outbound frames per Call SID and binding them to the socket once it connects
|
|
11
|
+
* (matched on the `start` frame's Call SID).
|
|
12
|
+
*
|
|
13
|
+
* Pure + unit-testable: the websocket is injected as the minimal {@link ITelephonyMediaSocket} surface,
|
|
14
|
+
* so the registry's buffering / dispatch / stream-SID capture logic is exercised with a fake socket and
|
|
15
|
+
* no `ws` install or network.
|
|
16
|
+
*
|
|
17
|
+
* @module @memberjunction/server/telephony
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Coordinates Media-Streams sockets with the bridge bindings, keyed by Call SID. One instance per
|
|
21
|
+
* server, shared between the inbound-webhook service (which binds `RealTwilioBindings` over this as the
|
|
22
|
+
* `ITwilioMediaPump`) and the WSS server (which attaches sockets + dispatches inbound frames).
|
|
23
|
+
*/
|
|
24
|
+
export class TwilioCallMediaRegistry {
|
|
25
|
+
constructor() {
|
|
26
|
+
this.channels = new Map();
|
|
27
|
+
}
|
|
28
|
+
/** Ensures a channel exists for a call (called when a bridge session for the call starts). */
|
|
29
|
+
RegisterCall(callSid) {
|
|
30
|
+
this.ensureChannel(callSid);
|
|
31
|
+
}
|
|
32
|
+
// ── ITwilioMediaPump ─────────────────────────────────────────────────────────
|
|
33
|
+
/** @inheritdoc — buffers when the socket has not yet connected; sends immediately once it has. */
|
|
34
|
+
Send(callSid, frame) {
|
|
35
|
+
const channel = this.ensureChannel(callSid);
|
|
36
|
+
if (channel.socket) {
|
|
37
|
+
channel.socket.send(JSON.stringify(frame));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
channel.outboundBuffer.push(frame);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** @inheritdoc — stores the handler so frames delivered before AND after socket connect reach it. */
|
|
44
|
+
OnFrame(callSid, handler) {
|
|
45
|
+
this.ensureChannel(callSid).frameHandlers.push(handler);
|
|
46
|
+
}
|
|
47
|
+
/** @inheritdoc — the captured stream SID, or `''` until the `start` frame arrives. */
|
|
48
|
+
GetStreamSid(callSid) {
|
|
49
|
+
return this.channels.get(callSid)?.streamSid ?? '';
|
|
50
|
+
}
|
|
51
|
+
// ── WSS-server side ─────────────────────────────────────────────────────────
|
|
52
|
+
/**
|
|
53
|
+
* Binds a connected Media-Streams socket (and its captured stream SID) to a call, flushing any
|
|
54
|
+
* outbound frames produced while the socket was still connecting. Called by the WSS server on the
|
|
55
|
+
* `start` frame.
|
|
56
|
+
*/
|
|
57
|
+
AttachSocket(callSid, socket, streamSid) {
|
|
58
|
+
const channel = this.ensureChannel(callSid);
|
|
59
|
+
channel.socket = socket;
|
|
60
|
+
channel.streamSid = streamSid;
|
|
61
|
+
const buffered = channel.outboundBuffer.splice(0, channel.outboundBuffer.length);
|
|
62
|
+
for (const frame of buffered) {
|
|
63
|
+
socket.send(JSON.stringify(frame));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Dispatches one inbound Media-Streams frame to all registered handlers for the call. */
|
|
67
|
+
DispatchInbound(callSid, frame) {
|
|
68
|
+
const channel = this.channels.get(callSid);
|
|
69
|
+
if (!channel) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (frame.event === 'start' && frame.streamSid) {
|
|
73
|
+
channel.streamSid = frame.streamSid;
|
|
74
|
+
}
|
|
75
|
+
for (const handler of channel.frameHandlers) {
|
|
76
|
+
handler(frame);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Tears down a call's channel and closes its socket (called on socket close / call end). */
|
|
80
|
+
EndCall(callSid) {
|
|
81
|
+
const channel = this.channels.get(callSid);
|
|
82
|
+
if (!channel) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
channel.socket?.close();
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
/* best-effort */
|
|
90
|
+
}
|
|
91
|
+
this.channels.delete(callSid);
|
|
92
|
+
}
|
|
93
|
+
/** Whether a channel is currently tracked for the call (test/observability helper). */
|
|
94
|
+
HasCall(callSid) {
|
|
95
|
+
return this.channels.has(callSid);
|
|
96
|
+
}
|
|
97
|
+
ensureChannel(callSid) {
|
|
98
|
+
let channel = this.channels.get(callSid);
|
|
99
|
+
if (!channel) {
|
|
100
|
+
channel = { frameHandlers: [], outboundBuffer: [] };
|
|
101
|
+
this.channels.set(callSid, channel);
|
|
102
|
+
}
|
|
103
|
+
return channel;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=twilioMediaRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"twilioMediaRegistry.js","sourceRoot":"","sources":["../../src/telephony/twilioMediaRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Process-wide holder for the startup-constructed Vonage telephony service, so the
|
|
3
|
+
* outbound `PlaceVonageCall` GraphQL resolver reaches the SAME {@link VonageTelephonyService}
|
|
4
|
+
* (and thus the same {@link VonageCallMediaRegistry} the media WSS attaches sockets to) that the
|
|
5
|
+
* inbound webhook router uses. Set once during server boot; read by the resolver.
|
|
6
|
+
*
|
|
7
|
+
* @module @memberjunction/server/telephony
|
|
8
|
+
*/
|
|
9
|
+
import type { VonageTelephonyService } from './VonageTelephonyService.js';
|
|
10
|
+
/** Binds the startup-constructed Vonage telephony service (called from server boot). */
|
|
11
|
+
export declare function SetVonageTelephonyService(service: VonageTelephonyService): void;
|
|
12
|
+
/** Returns the bound Vonage telephony service, or `undefined` when Vonage telephony is not configured. */
|
|
13
|
+
export declare function GetVonageTelephonyService(): VonageTelephonyService | undefined;
|
|
14
|
+
//# sourceMappingURL=vonage-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vonage-runtime.d.ts","sourceRoot":"","sources":["../../src/telephony/vonage-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAI1E,wFAAwF;AACxF,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAE/E;AAED,0GAA0G;AAC1G,wBAAgB,yBAAyB,IAAI,sBAAsB,GAAG,SAAS,CAE9E"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Process-wide holder for the startup-constructed Vonage telephony service, so the
|
|
3
|
+
* outbound `PlaceVonageCall` GraphQL resolver reaches the SAME {@link VonageTelephonyService}
|
|
4
|
+
* (and thus the same {@link VonageCallMediaRegistry} the media WSS attaches sockets to) that the
|
|
5
|
+
* inbound webhook router uses. Set once during server boot; read by the resolver.
|
|
6
|
+
*
|
|
7
|
+
* @module @memberjunction/server/telephony
|
|
8
|
+
*/
|
|
9
|
+
let vonageService;
|
|
10
|
+
/** Binds the startup-constructed Vonage telephony service (called from server boot). */
|
|
11
|
+
export function SetVonageTelephonyService(service) {
|
|
12
|
+
vonageService = service;
|
|
13
|
+
}
|
|
14
|
+
/** Returns the bound Vonage telephony service, or `undefined` when Vonage telephony is not configured. */
|
|
15
|
+
export function GetVonageTelephonyService() {
|
|
16
|
+
return vonageService;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=vonage-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vonage-runtime.js","sourceRoot":"","sources":["../../src/telephony/vonage-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,IAAI,aAAiD,CAAC;AAEtD,wFAAwF;AACxF,MAAM,UAAU,yBAAyB,CAAC,OAA+B;IACrE,aAAa,GAAG,OAAO,CAAC;AAC5B,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,yBAAyB;IACrC,OAAO,aAAa,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Per-call WebSocket-media pump registry for the Vonage telephony ingress.
|
|
3
|
+
*
|
|
4
|
+
* This is the server half of the Vonage media plane: it implements the provider package's
|
|
5
|
+
* `IVonageMediaPump` seam (which `RealVonageBindings` drives) on top of the live bidirectional media
|
|
6
|
+
* websockets MJAPI accepts at `WSS /telephony/vonage/media`. It exists because of the same lifecycle
|
|
7
|
+
* gap the Twilio ingress has: when an INBOUND call's answer webhook fires, the bridge session starts and
|
|
8
|
+
* `RealVonageBindings` registers its inbound-audio handler — but Vonage has not yet opened the media
|
|
9
|
+
* websocket (it does so only AFTER the answer-webhook's `connect`-websocket NCCO response). The registry
|
|
10
|
+
* bridges that gap by buffering handler registrations + outbound frames per call UUID and binding them to
|
|
11
|
+
* the socket once it connects (matched on the call UUID Vonage forwards on the websocket handshake).
|
|
12
|
+
*
|
|
13
|
+
* Pure + unit-testable: the websocket is injected as the minimal {@link ITelephonyMediaSocket} surface,
|
|
14
|
+
* so the registry's buffering / dispatch logic is exercised with a fake socket and no `ws` install or
|
|
15
|
+
* network.
|
|
16
|
+
*
|
|
17
|
+
* @module @memberjunction/server/telephony
|
|
18
|
+
*/
|
|
19
|
+
import type { VonageControlEvent, IVonageMediaPump } from '@memberjunction/ai-bridge-vonage';
|
|
20
|
+
/**
|
|
21
|
+
* The minimal websocket surface the registry drives — a structural subset of a `ws` socket, so the
|
|
22
|
+
* registry never imports `ws` and is testable with a fake. Vonage audio is sent as BINARY frames (raw
|
|
23
|
+
* L16 PCM); the registry never sends text frames outbound (Vonage's media socket only accepts audio).
|
|
24
|
+
*/
|
|
25
|
+
export interface ITelephonyMediaSocket {
|
|
26
|
+
/** Sends one outbound BINARY audio frame (raw L16 PCM) on the call's socket. */
|
|
27
|
+
sendBinary(data: Uint8Array): void;
|
|
28
|
+
/** Sends one outbound TEXT control frame (JSON command, e.g. `{"action":"clear"}`) on the call's socket. */
|
|
29
|
+
sendText(data: string): void;
|
|
30
|
+
/** Closes the socket (best-effort; called on call end). */
|
|
31
|
+
close(): void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Coordinates Vonage media websockets with the bridge bindings, keyed by call UUID. One instance per
|
|
35
|
+
* server, shared between the inbound-webhook service (which binds `RealVonageBindings` over this as the
|
|
36
|
+
* `IVonageMediaPump`) and the WSS server (which attaches sockets + dispatches inbound audio/events).
|
|
37
|
+
*
|
|
38
|
+
* Models Vonage's wire split: outbound audio → binary frames; inbound binary frames → audio handlers;
|
|
39
|
+
* inbound JSON text frames → parsed {@link VonageControlEvent}s → event handlers. There is no base64
|
|
40
|
+
* envelope or μ-law transcode — that's the Twilio path, not Vonage's.
|
|
41
|
+
*/
|
|
42
|
+
export declare class VonageCallMediaRegistry implements IVonageMediaPump {
|
|
43
|
+
private readonly channels;
|
|
44
|
+
/** Ensures a channel exists for a call (called when a bridge session for the call starts). */
|
|
45
|
+
RegisterCall(callUuid: string): void;
|
|
46
|
+
/**
|
|
47
|
+
* @inheritdoc — re-slices the (already-8 kHz) delta into fixed 320-byte / 20 ms frames before sending,
|
|
48
|
+
* carrying any sub-frame remainder into the next delta so the stream stays continuous (no silence gaps).
|
|
49
|
+
* Each whole frame is sent immediately if the socket is live, else buffered for {@link AttachSocket}.
|
|
50
|
+
*/
|
|
51
|
+
SendAudio(callUuid: string, pcm: ArrayBuffer): void;
|
|
52
|
+
/** @inheritdoc — stores the audio handler so frames delivered before AND after socket connect reach it. */
|
|
53
|
+
OnAudio(callUuid: string, handler: (pcm: ArrayBuffer) => void): void;
|
|
54
|
+
/** @inheritdoc — stores the control-event handler (DTMF / connected / close). */
|
|
55
|
+
OnEvent(callUuid: string, handler: (event: VonageControlEvent) => void): void;
|
|
56
|
+
/**
|
|
57
|
+
* @inheritdoc — barge-in flush: drop any outbound audio buffered locally (socket not yet connected) AND,
|
|
58
|
+
* if the socket is live, send Vonage's `{"action":"clear"}` text command to discard its playback queue.
|
|
59
|
+
* Safe to call for an unknown/uninitialized call (no-op).
|
|
60
|
+
*/
|
|
61
|
+
Clear(callUuid: string): void;
|
|
62
|
+
/**
|
|
63
|
+
* Binds a connected media socket to a call, flushing any outbound audio produced while the socket
|
|
64
|
+
* was still connecting. Called by the WSS server once it resolves the call UUID for the socket (from
|
|
65
|
+
* the `call_uuid` query param the answer NCCO embedded on the media URL).
|
|
66
|
+
*/
|
|
67
|
+
AttachSocket(callUuid: string, socket: ITelephonyMediaSocket): void;
|
|
68
|
+
/** Dispatches one inbound binary audio frame (raw L16 PCM) to all audio handlers for the call. */
|
|
69
|
+
DispatchInboundAudio(callUuid: string, pcm: ArrayBuffer): void;
|
|
70
|
+
/** Dispatches one inbound control event (parsed from a JSON text frame) to all event handlers for the call. */
|
|
71
|
+
DispatchInboundEvent(callUuid: string, event: VonageControlEvent): void;
|
|
72
|
+
/** Tears down a call's channel and closes its socket (called on socket close / call end). */
|
|
73
|
+
EndCall(callUuid: string): void;
|
|
74
|
+
/** Whether a channel is currently tracked for the call (test/observability helper). */
|
|
75
|
+
HasCall(callUuid: string): boolean;
|
|
76
|
+
private ensureChannel;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=vonageMediaRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vonageMediaRegistry.d.ts","sourceRoot":"","sources":["../../src/telephony/vonageMediaRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAE7F;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IAClC,gFAAgF;IAChF,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACnC,4GAA4G;IAC5G,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,2DAA2D;IAC3D,KAAK,IAAI,IAAI,CAAC;CACjB;AAwBD;;;;;;;;GAQG;AACH,qBAAa,uBAAwB,YAAW,gBAAgB;IAC5D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAEhE,8FAA8F;IACvF,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAM3C;;;;OAIG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI;IAoB1D,2GAA2G;IACpG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IAI3E,iFAAiF;IAC1E,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAAG,IAAI;IAIpF;;;;OAIG;IACI,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAYpC;;;;OAIG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,GAAG,IAAI;IAS1E,kGAAkG;IAC3F,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI;IAUrE,+GAA+G;IACxG,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAU9E,6FAA6F;IACtF,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAatC,uFAAuF;IAChF,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIzC,OAAO,CAAC,aAAa;CAQxB"}
|