@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.
Files changed (309) hide show
  1. package/dist/agentSessions/ReturningVisitorRecap.d.ts +39 -0
  2. package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -0
  3. package/dist/agentSessions/ReturningVisitorRecap.js +198 -0
  4. package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -0
  5. package/dist/agentSessions/SessionJanitor.d.ts +13 -0
  6. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  7. package/dist/agentSessions/SessionJanitor.js +65 -7
  8. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  9. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  10. package/dist/agentSessions/SessionManager.js +40 -0
  11. package/dist/agentSessions/SessionManager.js.map +1 -1
  12. package/dist/agentSessions/index.d.ts.map +1 -1
  13. package/dist/agentSessions/index.js +3 -1
  14. package/dist/agentSessions/index.js.map +1 -1
  15. package/dist/auth/magicLink/MagicLinkRouter.d.ts +10 -0
  16. package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
  17. package/dist/auth/magicLink/MagicLinkRouter.js +16 -0
  18. package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
  19. package/dist/auth/magicLink/index.d.ts +1 -1
  20. package/dist/auth/magicLink/index.d.ts.map +1 -1
  21. package/dist/auth/magicLink/index.js +1 -1
  22. package/dist/auth/magicLink/index.js.map +1 -1
  23. package/dist/auth/magicLink/types.d.ts +26 -0
  24. package/dist/auth/magicLink/types.d.ts.map +1 -1
  25. package/dist/config.d.ts +1883 -144
  26. package/dist/config.d.ts.map +1 -1
  27. package/dist/config.js +160 -36
  28. package/dist/config.js.map +1 -1
  29. package/dist/context.d.ts.map +1 -1
  30. package/dist/context.js +45 -2
  31. package/dist/context.js.map +1 -1
  32. package/dist/generated/generated.d.ts +1684 -54
  33. package/dist/generated/generated.d.ts.map +1 -1
  34. package/dist/generated/generated.js +57105 -48029
  35. package/dist/generated/generated.js.map +1 -1
  36. package/dist/generic/ResolverBase.d.ts +13 -0
  37. package/dist/generic/ResolverBase.d.ts.map +1 -1
  38. package/dist/generic/ResolverBase.js +22 -0
  39. package/dist/generic/ResolverBase.js.map +1 -1
  40. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  41. package/dist/generic/RunViewResolver.js +4 -0
  42. package/dist/generic/RunViewResolver.js.map +1 -1
  43. package/dist/index.d.ts +2 -2
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +110 -3
  46. package/dist/index.js.map +1 -1
  47. package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
  48. package/dist/integration/CustomColumnPromoter.js +6 -0
  49. package/dist/integration/CustomColumnPromoter.js.map +1 -1
  50. package/dist/realtimeWidget/WidgetRouter.d.ts +26 -0
  51. package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -0
  52. package/dist/realtimeWidget/WidgetRouter.js +182 -0
  53. package/dist/realtimeWidget/WidgetRouter.js.map +1 -0
  54. package/dist/realtimeWidget/WidgetSessionService.d.ts +265 -0
  55. package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -0
  56. package/dist/realtimeWidget/WidgetSessionService.js +477 -0
  57. package/dist/realtimeWidget/WidgetSessionService.js.map +1 -0
  58. package/dist/realtimeWidget/host-identity.d.ts +40 -0
  59. package/dist/realtimeWidget/host-identity.d.ts.map +1 -0
  60. package/dist/realtimeWidget/host-identity.js +58 -0
  61. package/dist/realtimeWidget/host-identity.js.map +1 -0
  62. package/dist/realtimeWidget/index.d.ts +10 -0
  63. package/dist/realtimeWidget/index.d.ts.map +1 -0
  64. package/dist/realtimeWidget/index.js +9 -0
  65. package/dist/realtimeWidget/index.js.map +1 -0
  66. package/dist/realtimeWidget/visitorIdentity.d.ts +76 -0
  67. package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -0
  68. package/dist/realtimeWidget/visitorIdentity.js +202 -0
  69. package/dist/realtimeWidget/visitorIdentity.js.map +1 -0
  70. package/dist/realtimeWidget/widgetCore.d.ts +106 -0
  71. package/dist/realtimeWidget/widgetCore.d.ts.map +1 -0
  72. package/dist/realtimeWidget/widgetCore.js +173 -0
  73. package/dist/realtimeWidget/widgetCore.js.map +1 -0
  74. package/dist/realtimeWidget/widgetGuestElevation.d.ts +51 -0
  75. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -0
  76. package/dist/realtimeWidget/widgetGuestElevation.js +79 -0
  77. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -0
  78. package/dist/resolvers/ComponentRegistryResolver.d.ts +7 -0
  79. package/dist/resolvers/ComponentRegistryResolver.d.ts.map +1 -1
  80. package/dist/resolvers/ComponentRegistryResolver.js +31 -8
  81. package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
  82. package/dist/resolvers/EntityPermissionResolver.d.ts.map +1 -1
  83. package/dist/resolvers/EntityPermissionResolver.js +1 -2
  84. package/dist/resolvers/EntityPermissionResolver.js.map +1 -1
  85. package/dist/resolvers/FileResolver.d.ts +74 -0
  86. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  87. package/dist/resolvers/FileResolver.js +211 -2
  88. package/dist/resolvers/FileResolver.js.map +1 -1
  89. package/dist/resolvers/QueryResolver.d.ts +6 -4
  90. package/dist/resolvers/QueryResolver.d.ts.map +1 -1
  91. package/dist/resolvers/QueryResolver.js +29 -14
  92. package/dist/resolvers/QueryResolver.js.map +1 -1
  93. package/dist/resolvers/QuerySystemUserResolver.d.ts +9 -6
  94. package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
  95. package/dist/resolvers/QuerySystemUserResolver.js +15 -13
  96. package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
  97. package/dist/resolvers/RealtimeBridgeResolver.d.ts +8 -1
  98. package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
  99. package/dist/resolvers/RealtimeBridgeResolver.js +28 -4
  100. package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
  101. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +91 -2
  102. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  103. package/dist/resolvers/RealtimeClientSessionResolver.js +337 -17
  104. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  105. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  106. package/dist/resolvers/RemoteBrowserActionResolver.js +17 -2
  107. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  108. package/dist/resolvers/RingCentralTelephonyResolver.d.ts +27 -0
  109. package/dist/resolvers/RingCentralTelephonyResolver.d.ts.map +1 -0
  110. package/dist/resolvers/RingCentralTelephonyResolver.js +87 -0
  111. package/dist/resolvers/RingCentralTelephonyResolver.js.map +1 -0
  112. package/dist/resolvers/RunAIAgentResolver.d.ts +12 -3
  113. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  114. package/dist/resolvers/RunAIAgentResolver.js +50 -17
  115. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  116. package/dist/resolvers/SearchKnowledgeResolver.d.ts.map +1 -1
  117. package/dist/resolvers/SearchKnowledgeResolver.js +2 -0
  118. package/dist/resolvers/SearchKnowledgeResolver.js.map +1 -1
  119. package/dist/resolvers/TeamsMeetingsResolver.d.ts +28 -0
  120. package/dist/resolvers/TeamsMeetingsResolver.d.ts.map +1 -0
  121. package/dist/resolvers/TeamsMeetingsResolver.js +91 -0
  122. package/dist/resolvers/TeamsMeetingsResolver.js.map +1 -0
  123. package/dist/resolvers/TelephonyResolver.d.ts +26 -0
  124. package/dist/resolvers/TelephonyResolver.d.ts.map +1 -0
  125. package/dist/resolvers/TelephonyResolver.js +86 -0
  126. package/dist/resolvers/TelephonyResolver.js.map +1 -0
  127. package/dist/resolvers/TestQuerySQLResolver.d.ts +1 -1
  128. package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
  129. package/dist/resolvers/TestQuerySQLResolver.js +2 -3
  130. package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
  131. package/dist/resolvers/VonageTelephonyResolver.d.ts +26 -0
  132. package/dist/resolvers/VonageTelephonyResolver.d.ts.map +1 -0
  133. package/dist/resolvers/VonageTelephonyResolver.js +86 -0
  134. package/dist/resolvers/VonageTelephonyResolver.js.map +1 -0
  135. package/dist/resolvers/meetingRecordingRegistration.d.ts +124 -0
  136. package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -0
  137. package/dist/resolvers/meetingRecordingRegistration.js +311 -0
  138. package/dist/resolvers/meetingRecordingRegistration.js.map +1 -0
  139. package/dist/resolvers/peaksSidecar.d.ts +30 -0
  140. package/dist/resolvers/peaksSidecar.d.ts.map +1 -0
  141. package/dist/resolvers/peaksSidecar.js +51 -0
  142. package/dist/resolvers/peaksSidecar.js.map +1 -0
  143. package/dist/rest/MediaAccessKeys.d.ts +68 -0
  144. package/dist/rest/MediaAccessKeys.d.ts.map +1 -0
  145. package/dist/rest/MediaAccessKeys.js +96 -0
  146. package/dist/rest/MediaAccessKeys.js.map +1 -0
  147. package/dist/rest/MediaStreamHandler.d.ts +26 -0
  148. package/dist/rest/MediaStreamHandler.d.ts.map +1 -0
  149. package/dist/rest/MediaStreamHandler.js +195 -0
  150. package/dist/rest/MediaStreamHandler.js.map +1 -0
  151. package/dist/rest/mediaRange.d.ts +41 -0
  152. package/dist/rest/mediaRange.d.ts.map +1 -0
  153. package/dist/rest/mediaRange.js +60 -0
  154. package/dist/rest/mediaRange.js.map +1 -0
  155. package/dist/telephony/RingCentralTelephonyService.d.ts +115 -0
  156. package/dist/telephony/RingCentralTelephonyService.d.ts.map +1 -0
  157. package/dist/telephony/RingCentralTelephonyService.js +262 -0
  158. package/dist/telephony/RingCentralTelephonyService.js.map +1 -0
  159. package/dist/telephony/TeamsMeetingsRouter.d.ts +40 -0
  160. package/dist/telephony/TeamsMeetingsRouter.d.ts.map +1 -0
  161. package/dist/telephony/TeamsMeetingsRouter.js +96 -0
  162. package/dist/telephony/TeamsMeetingsRouter.js.map +1 -0
  163. package/dist/telephony/TeamsMeetingsService.d.ts +113 -0
  164. package/dist/telephony/TeamsMeetingsService.d.ts.map +1 -0
  165. package/dist/telephony/TeamsMeetingsService.js +196 -0
  166. package/dist/telephony/TeamsMeetingsService.js.map +1 -0
  167. package/dist/telephony/TwilioTelephonyRouter.d.ts +36 -0
  168. package/dist/telephony/TwilioTelephonyRouter.d.ts.map +1 -0
  169. package/dist/telephony/TwilioTelephonyRouter.js +143 -0
  170. package/dist/telephony/TwilioTelephonyRouter.js.map +1 -0
  171. package/dist/telephony/TwilioTelephonyService.d.ts +95 -0
  172. package/dist/telephony/TwilioTelephonyService.d.ts.map +1 -0
  173. package/dist/telephony/TwilioTelephonyService.js +193 -0
  174. package/dist/telephony/TwilioTelephonyService.js.map +1 -0
  175. package/dist/telephony/VonageTelephonyRouter.d.ts +41 -0
  176. package/dist/telephony/VonageTelephonyRouter.d.ts.map +1 -0
  177. package/dist/telephony/VonageTelephonyRouter.js +201 -0
  178. package/dist/telephony/VonageTelephonyRouter.js.map +1 -0
  179. package/dist/telephony/VonageTelephonyService.d.ts +90 -0
  180. package/dist/telephony/VonageTelephonyService.d.ts.map +1 -0
  181. package/dist/telephony/VonageTelephonyService.js +191 -0
  182. package/dist/telephony/VonageTelephonyService.js.map +1 -0
  183. package/dist/telephony/calendar-scheduler.d.ts +67 -0
  184. package/dist/telephony/calendar-scheduler.d.ts.map +1 -0
  185. package/dist/telephony/calendar-scheduler.js +133 -0
  186. package/dist/telephony/calendar-scheduler.js.map +1 -0
  187. package/dist/telephony/index.d.ts +29 -0
  188. package/dist/telephony/index.d.ts.map +1 -0
  189. package/dist/telephony/index.js +38 -0
  190. package/dist/telephony/index.js.map +1 -0
  191. package/dist/telephony/media-upgrade-router.d.ts +33 -0
  192. package/dist/telephony/media-upgrade-router.d.ts.map +1 -0
  193. package/dist/telephony/media-upgrade-router.js +56 -0
  194. package/dist/telephony/media-upgrade-router.js.map +1 -0
  195. package/dist/telephony/ringcentral-runtime.d.ts +14 -0
  196. package/dist/telephony/ringcentral-runtime.d.ts.map +1 -0
  197. package/dist/telephony/ringcentral-runtime.js +18 -0
  198. package/dist/telephony/ringcentral-runtime.js.map +1 -0
  199. package/dist/telephony/teams-meetings-runtime.d.ts +16 -0
  200. package/dist/telephony/teams-meetings-runtime.d.ts.map +1 -0
  201. package/dist/telephony/teams-meetings-runtime.js +20 -0
  202. package/dist/telephony/teams-meetings-runtime.js.map +1 -0
  203. package/dist/telephony/teamsAcsMediaRegistry.d.ts +69 -0
  204. package/dist/telephony/teamsAcsMediaRegistry.d.ts.map +1 -0
  205. package/dist/telephony/teamsAcsMediaRegistry.js +118 -0
  206. package/dist/telephony/teamsAcsMediaRegistry.js.map +1 -0
  207. package/dist/telephony/telephony-runtime.d.ts +14 -0
  208. package/dist/telephony/telephony-runtime.d.ts.map +1 -0
  209. package/dist/telephony/telephony-runtime.js +18 -0
  210. package/dist/telephony/telephony-runtime.js.map +1 -0
  211. package/dist/telephony/twilioMediaRegistry.d.ts +60 -0
  212. package/dist/telephony/twilioMediaRegistry.d.ts.map +1 -0
  213. package/dist/telephony/twilioMediaRegistry.js +106 -0
  214. package/dist/telephony/twilioMediaRegistry.js.map +1 -0
  215. package/dist/telephony/vonage-runtime.d.ts +14 -0
  216. package/dist/telephony/vonage-runtime.d.ts.map +1 -0
  217. package/dist/telephony/vonage-runtime.js +18 -0
  218. package/dist/telephony/vonage-runtime.js.map +1 -0
  219. package/dist/telephony/vonageMediaRegistry.d.ts +78 -0
  220. package/dist/telephony/vonageMediaRegistry.d.ts.map +1 -0
  221. package/dist/telephony/vonageMediaRegistry.js +158 -0
  222. package/dist/telephony/vonageMediaRegistry.js.map +1 -0
  223. package/package.json +88 -82
  224. package/src/__tests__/FileResolverPeaks.test.ts +64 -0
  225. package/src/__tests__/MediaAccessKeys.test.ts +68 -0
  226. package/src/__tests__/MediaStreamHandler.test.ts +91 -0
  227. package/src/__tests__/RealtimeBridgeResolver.test.ts +10 -1
  228. package/src/__tests__/RealtimeClientSessionResolver.test.ts +69 -0
  229. package/src/__tests__/RealtimeCoAgentAppAwareness.integration.test.ts +191 -0
  230. package/src/__tests__/RemoteBrowserSnapshot.test.ts +123 -0
  231. package/src/__tests__/SessionManager.test.ts +2 -0
  232. package/src/__tests__/meetingRecordingRegistration.test.ts +248 -0
  233. package/src/__tests__/search-knowledge-tags.test.ts +9 -9
  234. package/src/__tests__/teams-meetings-service.test.ts +65 -0
  235. package/src/__tests__/teamsAcsMediaRegistry.test.ts +82 -0
  236. package/src/__tests__/twilio-telephony-service.test.ts +23 -0
  237. package/src/__tests__/twilioMediaRegistry.test.ts +103 -0
  238. package/src/__tests__/vonageMediaRegistry.test.ts +180 -0
  239. package/src/__tests__/widget.test.ts +204 -0
  240. package/src/__tests__/widgetGuestElevation.test.ts +57 -0
  241. package/src/__tests__/widgetHostIdentity.test.ts +117 -0
  242. package/src/agentSessions/ReturningVisitorRecap.ts +242 -0
  243. package/src/agentSessions/SessionJanitor.ts +66 -6
  244. package/src/agentSessions/SessionManager.ts +41 -0
  245. package/src/agentSessions/index.ts +3 -1
  246. package/src/auth/magicLink/MagicLinkRouter.ts +17 -0
  247. package/src/auth/magicLink/index.ts +1 -0
  248. package/src/auth/magicLink/types.ts +26 -0
  249. package/src/config.ts +172 -38
  250. package/src/context.ts +50 -3
  251. package/src/generated/generated.ts +26726 -20464
  252. package/src/generic/ResolverBase.ts +28 -0
  253. package/src/generic/RunViewResolver.ts +4 -0
  254. package/src/index.ts +119 -3
  255. package/src/integration/CustomColumnPromoter.ts +6 -0
  256. package/src/realtimeWidget/WidgetRouter.ts +204 -0
  257. package/src/realtimeWidget/WidgetSessionService.ts +714 -0
  258. package/src/realtimeWidget/host-identity.ts +84 -0
  259. package/src/realtimeWidget/index.ts +15 -0
  260. package/src/realtimeWidget/visitorIdentity.ts +258 -0
  261. package/src/realtimeWidget/widgetCore.ts +231 -0
  262. package/src/realtimeWidget/widgetGuestElevation.ts +115 -0
  263. package/src/resolvers/ComponentRegistryResolver.ts +36 -10
  264. package/src/resolvers/EntityPermissionResolver.ts +1 -2
  265. package/src/resolvers/FileResolver.ts +199 -1
  266. package/src/resolvers/QueryResolver.ts +33 -19
  267. package/src/resolvers/QuerySystemUserResolver.ts +14 -10
  268. package/src/resolvers/RealtimeBridgeResolver.ts +36 -4
  269. package/src/resolvers/RealtimeClientSessionResolver.ts +383 -9
  270. package/src/resolvers/RemoteBrowserActionResolver.ts +18 -2
  271. package/src/resolvers/RingCentralTelephonyResolver.ts +64 -0
  272. package/src/resolvers/RunAIAgentResolver.ts +60 -15
  273. package/src/resolvers/SearchKnowledgeResolver.ts +2 -0
  274. package/src/resolvers/TeamsMeetingsResolver.ts +68 -0
  275. package/src/resolvers/TelephonyResolver.ts +63 -0
  276. package/src/resolvers/TestQuerySQLResolver.ts +2 -3
  277. package/src/resolvers/VonageTelephonyResolver.ts +63 -0
  278. package/src/resolvers/meetingRecordingRegistration.ts +432 -0
  279. package/src/resolvers/peaksSidecar.ts +52 -0
  280. package/src/rest/MediaAccessKeys.ts +121 -0
  281. package/src/rest/MediaStreamHandler.ts +223 -0
  282. package/src/rest/mediaRange.ts +76 -0
  283. package/src/telephony/RingCentralTelephonyService.ts +342 -0
  284. package/src/telephony/TeamsMeetingsRouter.ts +124 -0
  285. package/src/telephony/TeamsMeetingsService.ts +268 -0
  286. package/src/telephony/TwilioTelephonyRouter.ts +184 -0
  287. package/src/telephony/TwilioTelephonyService.ts +261 -0
  288. package/src/telephony/VonageTelephonyRouter.ts +239 -0
  289. package/src/telephony/VonageTelephonyService.ts +259 -0
  290. package/src/telephony/calendar-scheduler.ts +176 -0
  291. package/src/telephony/index.ts +43 -0
  292. package/src/telephony/media-upgrade-router.ts +62 -0
  293. package/src/telephony/ringcentral-runtime.ts +22 -0
  294. package/src/telephony/teams-meetings-runtime.ts +24 -0
  295. package/src/telephony/teamsAcsMediaRegistry.ts +152 -0
  296. package/src/telephony/telephony-runtime.ts +22 -0
  297. package/src/telephony/twilioMediaRegistry.ts +137 -0
  298. package/src/telephony/vonage-runtime.ts +22 -0
  299. package/src/telephony/vonageMediaRegistry.ts +200 -0
  300. package/dist/agents/skip-agent.d.ts +0 -111
  301. package/dist/agents/skip-agent.d.ts.map +0 -1
  302. package/dist/agents/skip-agent.js +0 -1487
  303. package/dist/agents/skip-agent.js.map +0 -1
  304. package/dist/agents/skip-sdk.d.ts +0 -261
  305. package/dist/agents/skip-sdk.d.ts.map +0 -1
  306. package/dist/agents/skip-sdk.js +0 -909
  307. package/dist/agents/skip-sdk.js.map +0 -1
  308. package/src/agents/skip-agent.ts +0 -1594
  309. package/src/agents/skip-sdk.ts +0 -1210
@@ -0,0 +1,191 @@
1
+ /**
2
+ * @fileoverview Orchestrates Vonage telephony bridge sessions (inbound + outbound) for MJAPI.
3
+ *
4
+ * This is the composition layer between the carrier ingress (the public answer/event webhooks + the
5
+ * bidirectional media WSS) and the ONE unified realtime-agent pathway. It does NOT re-implement any
6
+ * bridge logic: it resolves the Vonage provider + the agent identity, opens a server-side realtime
7
+ * session via the agent layer's `CreateBridgeRealtimeSession` factory, binds `RealVonageBindings` (real
8
+ * REST Voice client + the per-call media registry) onto the driver, and hands everything to
9
+ * `AIBridgeEngine.StartBridgeSession` — exactly the seam the Twilio service + LiveKit room coordinator use.
10
+ *
11
+ * Collaborators are injected (engine, session factory, session manager) so the resolution/branching
12
+ * logic is unit-testable with fakes; the actual call placement + media flow are live-only (real Vonage
13
+ * credentials + a publicly reachable media URL — see telephony-vendor-bindings.md §T2).
14
+ *
15
+ * @module @memberjunction/server/telephony
16
+ */
17
+ import { RunView, LogError } from '@memberjunction/core';
18
+ import { AIBridgeEngine } from '@memberjunction/ai-bridge-server';
19
+ import { CreateBridgeRealtimeSession } from '@memberjunction/ai-agents';
20
+ import { DIRECTION_CONFIG_KEY, FROM_NUMBER_CONFIG_KEY, INBOUND_CALL_ID_CONFIG_KEY, } from '@memberjunction/ai-bridge-base';
21
+ import { VonageCallSdk, RealVonageBindings, RealVonageVoiceClient } from '@memberjunction/ai-bridge-vonage';
22
+ import { SessionManager } from '../agentSessions/SessionManager.js';
23
+ const VONAGE_PROVIDER_DRIVER = 'VonageBridge';
24
+ const AGENT_IDENTITY_ENTITY = 'MJ: AI Bridge Agent Identities';
25
+ const PHONE_IDENTITY_TYPE = 'PhoneNumber';
26
+ /**
27
+ * Starts Vonage bridge sessions. One instance per server, constructed alongside the telephony router and
28
+ * sharing the {@link VonageCallMediaRegistry} with the media WSS server.
29
+ */
30
+ export class VonageTelephonyService {
31
+ constructor(config, registry, deps = {}) {
32
+ this.config = config;
33
+ this.registry = registry;
34
+ this.voice = new RealVonageVoiceClient({
35
+ ApplicationId: config.applicationId,
36
+ PrivateKey: config.privateKey,
37
+ ApiKey: config.apiKey,
38
+ ApiSecret: config.apiSecret,
39
+ });
40
+ this.engine = deps.engine ?? AIBridgeEngine.Instance;
41
+ this.sessionFactory = deps.sessionFactory ?? CreateBridgeRealtimeSession;
42
+ this.sessionManager = deps.sessionManager ?? new SessionManager();
43
+ }
44
+ /**
45
+ * Resolves the dialed DID to a pinned agent and starts an INBOUND bridge session. The bound
46
+ * `RealVonageBindings` will accept the media socket (opened by the answer webhook's `connect` NCCO)
47
+ * for the call UUID. Returns `{ accepted:false }` (never throws) when no agent identity matches the
48
+ * DID, so the webhook can answer with a polite "no agent" NCCO instead of a 500.
49
+ */
50
+ async HandleInboundCall(input, contextUser, provider) {
51
+ try {
52
+ const identity = await this.resolveAgentIdentityByPhone(input.to, contextUser);
53
+ if (!identity) {
54
+ return { accepted: false, reason: `No active agent identity for dialed number '${input.to}'.` };
55
+ }
56
+ this.registry.RegisterCall(input.callId);
57
+ await this.startBridge({
58
+ agentID: identity.AgentID,
59
+ direction: 'Inbound',
60
+ address: input.from,
61
+ inboundCallId: input.callId,
62
+ contextUser,
63
+ provider,
64
+ });
65
+ return { accepted: true };
66
+ }
67
+ catch (e) {
68
+ LogError(`[Telephony][Vonage] inbound call ${input.callId} failed: ${e instanceof Error ? e.message : String(e)}`);
69
+ return { accepted: false, reason: 'Internal error starting the agent.' };
70
+ }
71
+ }
72
+ /**
73
+ * Places an OUTBOUND call from a given agent identity to a destination number. The bound
74
+ * `RealVonageBindings.createCall` issues the Voice REST `POST /v1/calls` with the `connect`-websocket
75
+ * NCCO; the returned call UUID is the bridge's external connection id.
76
+ *
77
+ * @returns The placed call UUID.
78
+ */
79
+ async PlaceOutboundCall(agentIdentityId, toNumber, contextUser, provider) {
80
+ const identity = await this.loadAgentIdentity(agentIdentityId, contextUser, provider);
81
+ if (!identity) {
82
+ throw new Error(`Agent identity '${agentIdentityId}' not found or inactive.`);
83
+ }
84
+ const session = await this.startBridge({
85
+ agentID: identity.AgentID,
86
+ direction: 'Outbound',
87
+ address: toNumber,
88
+ fromNumber: identity.IdentityValue,
89
+ contextUser,
90
+ provider,
91
+ });
92
+ return session.RoomKey ?? '';
93
+ }
94
+ // ── internals ────────────────────────────────────────────────────────────────
95
+ /** Shared inbound/outbound bridge-start: resolve provider, open the realtime session, bind the SDK, start. */
96
+ async startBridge(args) {
97
+ await this.engine.Config(false, args.contextUser, args.provider);
98
+ const vonageProvider = this.resolveProvider();
99
+ const agentSession = await this.sessionManager.CreateSession({ agentID: args.agentID, userID: args.contextUser.ID }, args.contextUser, args.provider);
100
+ const realtimeSession = await this.sessionFactory({
101
+ AgentID: args.agentID,
102
+ TargetAgentID: args.agentID,
103
+ ContextUser: args.contextUser,
104
+ MetadataProvider: args.provider,
105
+ AgentSessionID: agentSession.ID,
106
+ RoomName: args.address,
107
+ });
108
+ const active = await this.engine.StartBridgeSession({
109
+ AgentSessionID: agentSession.ID,
110
+ AgentID: args.agentID,
111
+ TargetAgentID: args.agentID,
112
+ Provider: vonageProvider,
113
+ RealtimeSession: realtimeSession,
114
+ Address: args.address,
115
+ Direction: args.direction,
116
+ Configuration: this.buildSessionConfiguration(args.direction, args.fromNumber, args.inboundCallId),
117
+ BindSdk: this.buildBindSdk(),
118
+ ContextUser: args.contextUser,
119
+ MetadataProvider: args.provider,
120
+ });
121
+ return { RoomKey: active.RoomKey };
122
+ }
123
+ /** Resolves the seeded Vonage provider row (by driver class, falling back to display name). */
124
+ resolveProvider() {
125
+ const provider = this.engine.ProviderByDriverClass(VONAGE_PROVIDER_DRIVER) ?? this.engine.ProviderByName('Vonage');
126
+ if (!provider) {
127
+ throw new Error(`No active 'MJ: AI Bridge Providers' row for the Vonage bridge (DriverClass '${VONAGE_PROVIDER_DRIVER}').`);
128
+ }
129
+ return provider;
130
+ }
131
+ /**
132
+ * Builds the per-session SDK binding that wires the REAL Vonage bindings (REST Voice client + the
133
+ * per-call media registry) onto the telephony driver — overriding the package's default unbound SDK.
134
+ * This is where the offline-complete seams meet the live REST + websocket plumbing.
135
+ */
136
+ buildBindSdk() {
137
+ return (driver) => {
138
+ const telephony = driver;
139
+ telephony.SetSdkFactory(() => new VonageCallSdk(new RealVonageBindings({
140
+ Voice: this.voice,
141
+ MediaPump: this.registry,
142
+ MediaWssUrl: this.config.mediaPublicUrl,
143
+ EventUrl: this.config.eventUrl,
144
+ })));
145
+ };
146
+ }
147
+ /** Assembles the per-session bridge configuration (direction/from-number/inbound-call-id config keys). */
148
+ buildSessionConfiguration(direction, fromNumber, inboundCallId) {
149
+ // The engine does NOT forward the top-level Direction into the driver's Configuration; the bridge
150
+ // defaults to 'Outbound' when the key is absent. Set it here so an inbound call answers instead of
151
+ // wrongly taking the outbound-dial path ("No 'From' number is specified").
152
+ const config = { [DIRECTION_CONFIG_KEY]: direction };
153
+ if (fromNumber) {
154
+ config[FROM_NUMBER_CONFIG_KEY] = fromNumber;
155
+ }
156
+ if (inboundCallId) {
157
+ config[INBOUND_CALL_ID_CONFIG_KEY] = inboundCallId;
158
+ }
159
+ return config;
160
+ }
161
+ /** Finds the active agent identity whose phone number matches the dialed DID. */
162
+ async resolveAgentIdentityByPhone(dialedNumber, contextUser) {
163
+ const normalized = (dialedNumber ?? '').trim();
164
+ if (!normalized) {
165
+ return null;
166
+ }
167
+ const rv = new RunView();
168
+ const result = await rv.RunView({
169
+ EntityName: AGENT_IDENTITY_ENTITY,
170
+ ExtraFilter: `IdentityType='${PHONE_IDENTITY_TYPE}' AND IdentityValue='${normalized.replace(/'/g, "''")}' AND IsActive=1`,
171
+ MaxRows: 1,
172
+ ResultType: 'entity_object',
173
+ }, contextUser);
174
+ if (!result.Success) {
175
+ LogError(`[Telephony][Vonage] agent-identity lookup failed: ${result.ErrorMessage}`);
176
+ return null;
177
+ }
178
+ return result.Results?.[0] ?? null;
179
+ }
180
+ /** Loads a specific agent identity by id (used by outbound PlaceCall), requiring it be active. */
181
+ async loadAgentIdentity(agentIdentityId, contextUser, provider) {
182
+ // Use the request-scoped provider (multi-provider safe), not the global Metadata.
183
+ const entity = await provider.GetEntityObject(AGENT_IDENTITY_ENTITY, contextUser);
184
+ const loaded = await entity.Load(agentIdentityId);
185
+ if (!loaded || !entity.IsActive) {
186
+ return null;
187
+ }
188
+ return entity;
189
+ }
190
+ }
191
+ //# sourceMappingURL=VonageTelephonyService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VonageTelephonyService.js","sourceRoot":"","sources":["../../src/telephony/VonageTelephonyService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @fileoverview Host wiring for the scheduled/invite-driven meeting join loop (program M2).
3
+ *
4
+ * Composes the offline-complete seams from `@memberjunction/ai-bridge-server` into a running
5
+ * background loop, mirroring the {@link SessionJanitor} startup pattern (run once at boot, then on an
6
+ * interval):
7
+ *
8
+ * 1. {@link CalendarWatcher} polls each agent identity's calendar (via the injected
9
+ * {@link CalendarSourceResolver}, bound here to the real {@link GraphCalendarClient} /
10
+ * {@link GoogleCalendarClient}) and creates a `Scheduled` `AIAgentSessionBridge` for every invite
11
+ * addressed to the agent.
12
+ * 2. {@link ScheduledBridgeRunner} starts each bridge whose `ScheduledStartTime` is due, building the
13
+ * realtime session + the provider bind-sdk via the per-provider meeting service (Teams today).
14
+ *
15
+ * Calendar credentials are PRE-RESOLVED upstream (the bot's Graph access token comes from the Teams
16
+ * meetings config — `botAccessToken`, resolved via MJ config, never inline). Google calendar polling
17
+ * binds only when a Google auth client is supplied; otherwise those identities are skipped (the watcher
18
+ * tolerates a `null` source per identity). Live verification requires a real tenant + the Azure app /
19
+ * Google service account — the same access the meeting bridges need.
20
+ *
21
+ * @module @memberjunction/server/telephony
22
+ */
23
+ import { UserInfo, IMetadataProvider } from '@memberjunction/core';
24
+ import { type CalendarSourceResolver, type ScheduledBridgeSessionFactory } from '@memberjunction/ai-bridge-server';
25
+ import type { TeamsMeetingsConfig } from '../config.js';
26
+ import { TeamsMeetingsService } from './TeamsMeetingsService.js';
27
+ /** Options for {@link StartCalendarScheduler}. */
28
+ export interface CalendarSchedulerOptions {
29
+ /** The server metadata provider all reads/writes run under. */
30
+ Provider: IMetadataProvider;
31
+ /** The system user the watcher + runner (and every created/started bridge) run as. */
32
+ ContextUser: UserInfo;
33
+ /** The Teams meetings service (shared with the ingress) — supplies the scheduled-join bind-sdk. */
34
+ TeamsService: TeamsMeetingsService;
35
+ /** The Teams meetings config — supplies the bot Graph access token for calendar polling. */
36
+ TeamsConfig: TeamsMeetingsConfig;
37
+ /** Poll cadence (ms). Defaults to {@link DEFAULT_POLL_INTERVAL_MS}. */
38
+ PollIntervalMs?: number;
39
+ }
40
+ /** A running scheduler handle — call {@link CalendarSchedulerHandle.Stop} to clear the interval. */
41
+ export interface CalendarSchedulerHandle {
42
+ /** Stops the periodic sweep/run loop (clears the timer). Safe to call more than once. */
43
+ Stop(): void;
44
+ }
45
+ /**
46
+ * Builds the {@link CalendarSourceResolver} that binds the real calendar clients per identity. Graph
47
+ * (Teams/Microsoft) identities bind a {@link GraphCalendarClient} authenticated with the bot's
48
+ * pre-resolved Graph token; any identity without configured credentials resolves to `null` and is
49
+ * skipped this sweep (the watcher tolerates that). Google binding activates when a Google auth client
50
+ * is wired into the deployment (none configured today → Google-backed identities are skipped).
51
+ */
52
+ export declare function buildCalendarSourceResolver(teamsConfig: TeamsMeetingsConfig): CalendarSourceResolver;
53
+ /**
54
+ * Builds the {@link ScheduledBridgeSessionFactory} that turns a due bridge into start params. Resolves
55
+ * the bridge's agent (via its `AIAgentSession`) and, for a Teams bridge, delegates to the shared
56
+ * {@link TeamsMeetingsService} so the scheduled join reuses the exact provider/session/bind-sdk path as
57
+ * an on-demand join. Returns `null` (skip) for a provider with no scheduled-join wiring yet, or when the
58
+ * bridge has no join address.
59
+ */
60
+ export declare function buildScheduledSessionFactory(teamsService: TeamsMeetingsService): ScheduledBridgeSessionFactory;
61
+ /**
62
+ * Starts the calendar/scheduled-bridge loop: sweeps calendars and runs due bridges once immediately,
63
+ * then on a fixed interval. Mirrors {@link SessionJanitor.Start}. A sweep/run failure is logged and the
64
+ * loop continues — a transient calendar/transport error never kills the scheduler.
65
+ */
66
+ export declare function StartCalendarScheduler(options: CalendarSchedulerOptions): CalendarSchedulerHandle;
67
+ //# sourceMappingURL=calendar-scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-scheduler.d.ts","sourceRoot":"","sources":["../../src/telephony/calendar-scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAuB,MAAM,sBAAsB,CAAC;AAExF,OAAO,EAKH,KAAK,sBAAsB,EAC3B,KAAK,6BAA6B,EAErC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAQjE,kDAAkD;AAClD,MAAM,WAAW,wBAAwB;IACrC,+DAA+D;IAC/D,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,sFAAsF;IACtF,WAAW,EAAE,QAAQ,CAAC;IACtB,mGAAmG;IACnG,YAAY,EAAE,oBAAoB,CAAC;IACnC,4FAA4F;IAC5F,WAAW,EAAE,mBAAmB,CAAC;IACjC,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,oGAAoG;AACpG,MAAM,WAAW,uBAAuB;IACpC,yFAAyF;IACzF,IAAI,IAAI,IAAI,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,mBAAmB,GAAG,sBAAsB,CAgBpG;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,YAAY,EAAE,oBAAoB,GAAG,6BAA6B,CAyB9G;AAeD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,wBAAwB,GAAG,uBAAuB,CAmCjG"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * @fileoverview Host wiring for the scheduled/invite-driven meeting join loop (program M2).
3
+ *
4
+ * Composes the offline-complete seams from `@memberjunction/ai-bridge-server` into a running
5
+ * background loop, mirroring the {@link SessionJanitor} startup pattern (run once at boot, then on an
6
+ * interval):
7
+ *
8
+ * 1. {@link CalendarWatcher} polls each agent identity's calendar (via the injected
9
+ * {@link CalendarSourceResolver}, bound here to the real {@link GraphCalendarClient} /
10
+ * {@link GoogleCalendarClient}) and creates a `Scheduled` `AIAgentSessionBridge` for every invite
11
+ * addressed to the agent.
12
+ * 2. {@link ScheduledBridgeRunner} starts each bridge whose `ScheduledStartTime` is due, building the
13
+ * realtime session + the provider bind-sdk via the per-provider meeting service (Teams today).
14
+ *
15
+ * Calendar credentials are PRE-RESOLVED upstream (the bot's Graph access token comes from the Teams
16
+ * meetings config — `botAccessToken`, resolved via MJ config, never inline). Google calendar polling
17
+ * binds only when a Google auth client is supplied; otherwise those identities are skipped (the watcher
18
+ * tolerates a `null` source per identity). Live verification requires a real tenant + the Azure app /
19
+ * Google service account — the same access the meeting bridges need.
20
+ *
21
+ * @module @memberjunction/server/telephony
22
+ */
23
+ import { LogStatus, LogError } from '@memberjunction/core';
24
+ import { CalendarWatcher, ScheduledBridgeRunner, GraphCalendarSource, GraphCalendarClient, } from '@memberjunction/ai-bridge-server';
25
+ /** The Teams bridge driver class — identities/bridges on this provider poll Graph + join via the Teams service. */
26
+ const TEAMS_PROVIDER_DRIVER = 'TeamsBridge';
27
+ /** Default cadence (ms) for the calendar sweep + due-bridge run. 60s balances freshness vs. API quota. */
28
+ const DEFAULT_POLL_INTERVAL_MS = 60_000;
29
+ /**
30
+ * Builds the {@link CalendarSourceResolver} that binds the real calendar clients per identity. Graph
31
+ * (Teams/Microsoft) identities bind a {@link GraphCalendarClient} authenticated with the bot's
32
+ * pre-resolved Graph token; any identity without configured credentials resolves to `null` and is
33
+ * skipped this sweep (the watcher tolerates that). Google binding activates when a Google auth client
34
+ * is wired into the deployment (none configured today → Google-backed identities are skipped).
35
+ */
36
+ export function buildCalendarSourceResolver(teamsConfig) {
37
+ return (_identity, provider) => {
38
+ const driver = provider?.DriverClass?.trim();
39
+ if (driver === TEAMS_PROVIDER_DRIVER && teamsConfig.botAccessToken) {
40
+ return new GraphCalendarSource(new GraphCalendarClient({ Credentials: { AccessToken: teamsConfig.botAccessToken } }));
41
+ }
42
+ // Google Calendar is a deliberate, CLOSED seam — intentionally not bound here. The
43
+ // GoogleCalendarClient is built + unit-tested, but binding it would be dead code today:
44
+ // 1. there is no Google Meet *join* path for a detected invite to trigger (the scheduled-join
45
+ // factory is Teams-only), and
46
+ // 2. Google's Meet Media API is Developer-Preview + allowlist-gated regardless (every meeting
47
+ // participant must be enrolled), so it isn't a shippable target.
48
+ // To activate: define a Google auth client from config AND wire a Google Meet join. Until then
49
+ // Google identities are skipped rather than erroring the sweep.
50
+ return null;
51
+ };
52
+ }
53
+ /**
54
+ * Builds the {@link ScheduledBridgeSessionFactory} that turns a due bridge into start params. Resolves
55
+ * the bridge's agent (via its `AIAgentSession`) and, for a Teams bridge, delegates to the shared
56
+ * {@link TeamsMeetingsService} so the scheduled join reuses the exact provider/session/bind-sdk path as
57
+ * an on-demand join. Returns `null` (skip) for a provider with no scheduled-join wiring yet, or when the
58
+ * bridge has no join address.
59
+ */
60
+ export function buildScheduledSessionFactory(teamsService) {
61
+ return async (ctx) => {
62
+ const joinUrl = ctx.BridgeRow.Address?.trim();
63
+ if (!joinUrl) {
64
+ LogStatus(`[CalendarScheduler] bridge ${ctx.BridgeRow.ID} has no join address; skipping.`);
65
+ return null;
66
+ }
67
+ if (ctx.Provider.DriverClass?.trim() !== TEAMS_PROVIDER_DRIVER) {
68
+ LogStatus(`[CalendarScheduler] no scheduled-join wiring for provider '${ctx.Provider.Name}'; skipping bridge ${ctx.BridgeRow.ID}.`);
69
+ return null;
70
+ }
71
+ const agentID = await resolveAgentID(ctx.BridgeRow.AgentSessionID, ctx.ContextUser, ctx.MetadataProvider);
72
+ if (!agentID) {
73
+ LogStatus(`[CalendarScheduler] could not resolve agent for session ${ctx.BridgeRow.AgentSessionID}; skipping.`);
74
+ return null;
75
+ }
76
+ const params = await teamsService.BuildScheduledStartParams({
77
+ agentID,
78
+ joinUrl,
79
+ agentSessionID: ctx.BridgeRow.AgentSessionID,
80
+ contextUser: ctx.ContextUser,
81
+ provider: ctx.MetadataProvider,
82
+ });
83
+ return params;
84
+ };
85
+ }
86
+ /** Loads the `AIAgentSession` to resolve the agent the scheduled bridge belongs to. */
87
+ async function resolveAgentID(agentSessionID, contextUser, provider) {
88
+ const session = await provider.GetEntityObject('MJ: AI Agent Sessions', contextUser);
89
+ if (!(await session.Load(agentSessionID))) {
90
+ return null;
91
+ }
92
+ return session.AgentID;
93
+ }
94
+ /**
95
+ * Starts the calendar/scheduled-bridge loop: sweeps calendars and runs due bridges once immediately,
96
+ * then on a fixed interval. Mirrors {@link SessionJanitor.Start}. A sweep/run failure is logged and the
97
+ * loop continues — a transient calendar/transport error never kills the scheduler.
98
+ */
99
+ export function StartCalendarScheduler(options) {
100
+ const watcher = new CalendarWatcher({
101
+ SourceResolver: buildCalendarSourceResolver(options.TeamsConfig),
102
+ ContextUser: options.ContextUser,
103
+ MetadataProvider: options.Provider,
104
+ });
105
+ const runner = new ScheduledBridgeRunner({
106
+ SessionFactory: buildScheduledSessionFactory(options.TeamsService),
107
+ ContextUser: options.ContextUser,
108
+ MetadataProvider: options.Provider,
109
+ });
110
+ const tick = async () => {
111
+ try {
112
+ const swept = await watcher.Sweep();
113
+ const ran = await runner.RunDueBridges();
114
+ if (swept.BridgesCreated > 0 || ran.Started > 0) {
115
+ LogStatus(`[CalendarScheduler] swept ${swept.BridgesCreated} new bridge(s); started ${ran.Started} due bridge(s).`);
116
+ }
117
+ }
118
+ catch (err) {
119
+ LogError(`[CalendarScheduler] sweep/run pass failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
120
+ }
121
+ };
122
+ void tick(); // run-once at boot
123
+ const timer = setInterval(() => void tick(), options.PollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
124
+ // Don't let the poll timer keep the process alive at shutdown (the loop is best-effort background work).
125
+ timer.unref?.();
126
+ LogStatus(`[CalendarScheduler] started (every ${(options.PollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS) / 1000}s).`);
127
+ return {
128
+ Stop() {
129
+ clearInterval(timer);
130
+ },
131
+ };
132
+ }
133
+ //# sourceMappingURL=calendar-scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-scheduler.js","sourceRoot":"","sources":["../../src/telephony/calendar-scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @fileoverview Public exports for the MJAPI telephony + meetings ingress.
3
+ *
4
+ * Each vendor ingress is a quartet: a per-call media registry, a bridge-orchestration service, an
5
+ * Express/WSS router (the `create*Handler` factory + mount-path consts), and a process-wide runtime
6
+ * holder (`Set*`/`Get*`). The routers + runtimes are star-exported; the service + registry modules are
7
+ * re-exported by name to avoid star-export ambiguity on their internal, per-vendor-identical helper
8
+ * types (`InboundCallInput`, `InboundCallResult`, `ITelephonyMediaSocket`). Those internal types are
9
+ * not part of the package's public surface — code that needs them imports from the source module.
10
+ *
11
+ * @module @memberjunction/server/telephony
12
+ */
13
+ export * from './media-upgrade-router.js';
14
+ export { TwilioCallMediaRegistry } from './twilioMediaRegistry.js';
15
+ export { TwilioTelephonyService, type TwilioTelephonyServiceDeps } from './TwilioTelephonyService.js';
16
+ export * from './TwilioTelephonyRouter.js';
17
+ export * from './telephony-runtime.js';
18
+ export { VonageCallMediaRegistry } from './vonageMediaRegistry.js';
19
+ export { VonageTelephonyService, type VonageTelephonyServiceDeps } from './VonageTelephonyService.js';
20
+ export * from './VonageTelephonyRouter.js';
21
+ export * from './vonage-runtime.js';
22
+ export { RingCentralTelephonyService, type RingCentralTelephonyServiceDeps } from './RingCentralTelephonyService.js';
23
+ export * from './ringcentral-runtime.js';
24
+ export * from './teamsAcsMediaRegistry.js';
25
+ export * from './TeamsMeetingsService.js';
26
+ export * from './TeamsMeetingsRouter.js';
27
+ export * from './teams-meetings-runtime.js';
28
+ export * from './calendar-scheduler.js';
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/telephony/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,cAAc,2BAA2B,CAAC;AAG1C,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,KAAK,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACtG,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AAGvC,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,KAAK,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACtG,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AAMpC,OAAO,EAAE,2BAA2B,EAAE,KAAK,+BAA+B,EAAE,MAAM,kCAAkC,CAAC;AACrH,cAAc,0BAA0B,CAAC;AAGzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAG5C,cAAc,yBAAyB,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @fileoverview Public exports for the MJAPI telephony + meetings ingress.
3
+ *
4
+ * Each vendor ingress is a quartet: a per-call media registry, a bridge-orchestration service, an
5
+ * Express/WSS router (the `create*Handler` factory + mount-path consts), and a process-wide runtime
6
+ * holder (`Set*`/`Get*`). The routers + runtimes are star-exported; the service + registry modules are
7
+ * re-exported by name to avoid star-export ambiguity on their internal, per-vendor-identical helper
8
+ * types (`InboundCallInput`, `InboundCallResult`, `ITelephonyMediaSocket`). Those internal types are
9
+ * not part of the package's public surface — code that needs them imports from the source module.
10
+ *
11
+ * @module @memberjunction/server/telephony
12
+ */
13
+ // ── Shared WebSocket-upgrade dispatcher (routes GraphQL + all media sockets by path) ──────
14
+ export * from './media-upgrade-router.js';
15
+ // ── Twilio Programmable Voice + Media Streams ──────────────────────────────────────────
16
+ export { TwilioCallMediaRegistry } from './twilioMediaRegistry.js';
17
+ export { TwilioTelephonyService } from './TwilioTelephonyService.js';
18
+ export * from './TwilioTelephonyRouter.js';
19
+ export * from './telephony-runtime.js';
20
+ // ── Vonage Voice + WebSocket-media ─────────────────────────────────────────────────────
21
+ export { VonageCallMediaRegistry } from './vonageMediaRegistry.js';
22
+ export { VonageTelephonyService } from './VonageTelephonyService.js';
23
+ export * from './VonageTelephonyRouter.js';
24
+ export * from './vonage-runtime.js';
25
+ // ── RingCentral SIP softphone (the only RingCentral transport with bidirectional call audio) ──
26
+ // No media registry / webhook router: the softphone is an outbound SIP registration that receives inbound
27
+ // INVITEs directly. The service owns the registration; the runtime holder shares it with the outbound
28
+ // PlaceRingCentralCall resolver.
29
+ export { RingCentralTelephonyService } from './RingCentralTelephonyService.js';
30
+ export * from './ringcentral-runtime.js';
31
+ // ── Teams meetings (Microsoft Graph cloud-communications + ACS application-hosted media) ──
32
+ export * from './teamsAcsMediaRegistry.js';
33
+ export * from './TeamsMeetingsService.js';
34
+ export * from './TeamsMeetingsRouter.js';
35
+ export * from './teams-meetings-runtime.js';
36
+ // ── Scheduled / invite-driven meeting join loop (M2: calendar watcher + due-bridge runner) ──
37
+ export * from './calendar-scheduler.js';
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/telephony/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,6FAA6F;AAC7F,cAAc,2BAA2B,CAAC;AAE1C,0FAA0F;AAC1F,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAmC,MAAM,6BAA6B,CAAC;AACtG,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AAEvC,0FAA0F;AAC1F,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAmC,MAAM,6BAA6B,CAAC;AACtG,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AAEpC,iGAAiG;AACjG,0GAA0G;AAC1G,sGAAsG;AACtG,iCAAiC;AACjC,OAAO,EAAE,2BAA2B,EAAwC,MAAM,kCAAkC,CAAC;AACrH,cAAc,0BAA0B,CAAC;AAEzC,6FAA6F;AAC7F,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAE5C,+FAA+F;AAC/F,cAAc,yBAAyB,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @fileoverview Single WebSocket-upgrade dispatcher for the shared HTTP server.
3
+ *
4
+ * Why this exists: in `ws` 8.x, every `new WebSocketServer({ server })` attaches its OWN `upgrade`
5
+ * listener that calls `handleUpgrade` UNCONDITIONALLY, and `handleUpgrade` does `abortHandshake(400)` for
6
+ * any request whose path it doesn't own. So two `{server}`-bound servers on one HTTP server (e.g. the
7
+ * GraphQL subscriptions socket on `/` AND a telephony Media-Streams socket on `/telephony/.../media`)
8
+ * fight on every upgrade — the non-owning server 400s the request. That's exactly what made Twilio's
9
+ * `<Connect><Stream>` fail with error 31920 ("Stream WebSocket failed to connect").
10
+ *
11
+ * The fix: telephony/meetings media servers are created with `{ noServer: true }` (no auto-listener) and
12
+ * register their path here; at boot we strip the auto-listeners and install ONE `upgrade` listener that
13
+ * routes by path — GraphQL on its root path, each media socket on its own. When no media routes are
14
+ * registered (telephony disabled), we leave the GraphQL server's own listener untouched (zero change).
15
+ *
16
+ * @module @memberjunction/server/telephony
17
+ */
18
+ import type { Server as HttpServer } from 'node:http';
19
+ import type { WebSocketServer } from 'ws';
20
+ /** Registers a media WebSocket route. Called by each vendor router's attach step. */
21
+ export declare function RegisterMediaUpgradeRoute(path: string, wss: WebSocketServer): void;
22
+ /**
23
+ * Installs the single path-routing `upgrade` dispatcher. No-op when no media routes are registered, so
24
+ * the GraphQL server keeps its own listener untouched. Otherwise it removes the auto-attached listeners
25
+ * (GraphQL's included) and dispatches every upgrade by pathname — GraphQL on `graphqlPath`, each media
26
+ * socket on its registered path; unknown paths are destroyed.
27
+ *
28
+ * @param httpServer the shared HTTP server.
29
+ * @param graphqlWss the GraphQL subscriptions WebSocketServer (kept, re-dispatched on its path).
30
+ * @param graphqlPath the GraphQL root path (the path GraphQL's socket listens on).
31
+ */
32
+ export declare function InstallMediaUpgradeDispatcher(httpServer: HttpServer, graphqlWss: WebSocketServer, graphqlPath: string): void;
33
+ //# sourceMappingURL=media-upgrade-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-upgrade-router.d.ts","sourceRoot":"","sources":["../../src/telephony/media-upgrade-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAmB,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAK1C,qFAAqF;AACrF,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,IAAI,CAElF;AAED;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAqB5H"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @fileoverview Single WebSocket-upgrade dispatcher for the shared HTTP server.
3
+ *
4
+ * Why this exists: in `ws` 8.x, every `new WebSocketServer({ server })` attaches its OWN `upgrade`
5
+ * listener that calls `handleUpgrade` UNCONDITIONALLY, and `handleUpgrade` does `abortHandshake(400)` for
6
+ * any request whose path it doesn't own. So two `{server}`-bound servers on one HTTP server (e.g. the
7
+ * GraphQL subscriptions socket on `/` AND a telephony Media-Streams socket on `/telephony/.../media`)
8
+ * fight on every upgrade — the non-owning server 400s the request. That's exactly what made Twilio's
9
+ * `<Connect><Stream>` fail with error 31920 ("Stream WebSocket failed to connect").
10
+ *
11
+ * The fix: telephony/meetings media servers are created with `{ noServer: true }` (no auto-listener) and
12
+ * register their path here; at boot we strip the auto-listeners and install ONE `upgrade` listener that
13
+ * routes by path — GraphQL on its root path, each media socket on its own. When no media routes are
14
+ * registered (telephony disabled), we leave the GraphQL server's own listener untouched (zero change).
15
+ *
16
+ * @module @memberjunction/server/telephony
17
+ */
18
+ /** path → the `{ noServer:true }` WebSocketServer that owns it. */
19
+ const mediaRoutes = new Map();
20
+ /** Registers a media WebSocket route. Called by each vendor router's attach step. */
21
+ export function RegisterMediaUpgradeRoute(path, wss) {
22
+ mediaRoutes.set(path, wss);
23
+ }
24
+ /**
25
+ * Installs the single path-routing `upgrade` dispatcher. No-op when no media routes are registered, so
26
+ * the GraphQL server keeps its own listener untouched. Otherwise it removes the auto-attached listeners
27
+ * (GraphQL's included) and dispatches every upgrade by pathname — GraphQL on `graphqlPath`, each media
28
+ * socket on its registered path; unknown paths are destroyed.
29
+ *
30
+ * @param httpServer the shared HTTP server.
31
+ * @param graphqlWss the GraphQL subscriptions WebSocketServer (kept, re-dispatched on its path).
32
+ * @param graphqlPath the GraphQL root path (the path GraphQL's socket listens on).
33
+ */
34
+ export function InstallMediaUpgradeDispatcher(httpServer, graphqlWss, graphqlPath) {
35
+ if (mediaRoutes.size === 0) {
36
+ return;
37
+ }
38
+ httpServer.removeAllListeners('upgrade');
39
+ const dispatch = (wss, req, socket, head) => {
40
+ wss.handleUpgrade(req, socket, head, (ws) => wss.emit('connection', ws, req));
41
+ };
42
+ httpServer.on('upgrade', (req, socket, head) => {
43
+ const pathname = (req.url ?? '').split('?')[0];
44
+ if (pathname === graphqlPath) {
45
+ dispatch(graphqlWss, req, socket, head);
46
+ return;
47
+ }
48
+ const wss = mediaRoutes.get(pathname);
49
+ if (wss) {
50
+ dispatch(wss, req, socket, head);
51
+ return;
52
+ }
53
+ socket.destroy();
54
+ });
55
+ }
56
+ //# sourceMappingURL=media-upgrade-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-upgrade-router.js","sourceRoot":"","sources":["../../src/telephony/media-upgrade-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,mEAAmE;AACnE,MAAM,WAAW,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEvD,qFAAqF;AACrF,MAAM,UAAU,yBAAyB,CAAC,IAAY,EAAE,GAAoB;IACxE,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,6BAA6B,CAAC,UAAsB,EAAE,UAA2B,EAAE,WAAmB;IAClH,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;IACX,CAAC;IACD,UAAU,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,CAAC,GAAoB,EAAE,GAAoB,EAAE,MAAc,EAAE,IAAY,EAAQ,EAAE;QAChG,GAAG,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;IAClF,CAAC,CAAC;IACF,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAoB,EAAE,MAAc,EAAE,IAAY,EAAE,EAAE;QAC5E,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;YAC3B,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YACxC,OAAO;QACX,CAAC;QACD,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,GAAG,EAAE,CAAC;YACN,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YACjC,OAAO;QACX,CAAC;QACD,MAAM,CAAC,OAAO,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @fileoverview Process-wide holder for the startup-constructed RingCentral telephony service, so the
3
+ * outbound `PlaceRingCentralCall` GraphQL resolver reaches the SAME {@link RingCentralTelephonyService}
4
+ * (and thus the same long-lived SIP-softphone registration) that the inbound INVITE coordinator uses. Set
5
+ * once during server boot; read by the resolver.
6
+ *
7
+ * @module @memberjunction/server/telephony
8
+ */
9
+ import type { RingCentralTelephonyService } from './RingCentralTelephonyService.js';
10
+ /** Binds the startup-constructed RingCentral telephony service (called from server boot). */
11
+ export declare function SetRingCentralTelephonyService(service: RingCentralTelephonyService): void;
12
+ /** Returns the bound RingCentral telephony service, or `undefined` when telephony is not configured. */
13
+ export declare function GetRingCentralTelephonyService(): RingCentralTelephonyService | undefined;
14
+ //# sourceMappingURL=ringcentral-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ringcentral-runtime.d.ts","sourceRoot":"","sources":["../../src/telephony/ringcentral-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAIpF,6FAA6F;AAC7F,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,2BAA2B,GAAG,IAAI,CAEzF;AAED,wGAAwG;AACxG,wBAAgB,8BAA8B,IAAI,2BAA2B,GAAG,SAAS,CAExF"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @fileoverview Process-wide holder for the startup-constructed RingCentral telephony service, so the
3
+ * outbound `PlaceRingCentralCall` GraphQL resolver reaches the SAME {@link RingCentralTelephonyService}
4
+ * (and thus the same long-lived SIP-softphone registration) that the inbound INVITE coordinator uses. Set
5
+ * once during server boot; read by the resolver.
6
+ *
7
+ * @module @memberjunction/server/telephony
8
+ */
9
+ let ringCentralService;
10
+ /** Binds the startup-constructed RingCentral telephony service (called from server boot). */
11
+ export function SetRingCentralTelephonyService(service) {
12
+ ringCentralService = service;
13
+ }
14
+ /** Returns the bound RingCentral telephony service, or `undefined` when telephony is not configured. */
15
+ export function GetRingCentralTelephonyService() {
16
+ return ringCentralService;
17
+ }
18
+ //# sourceMappingURL=ringcentral-runtime.js.map