@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,262 @@
1
+ /**
2
+ * @fileoverview Orchestrates RingCentral telephony bridge sessions (inbound + outbound) for MJAPI over the
3
+ * **SIP softphone** transport.
4
+ *
5
+ * RingCentral's only product that carries bidirectional call audio is a registered SIP softphone (the
6
+ * `ringcentral-softphone` SDK over SIP/TLS + RTP/SRTP) — its WebSocket "Call Streaming" product is
7
+ * receive-only and cannot inject the agent's voice. So unlike the Twilio/Vonage ingresses (public webhook
8
+ * + media WSS), this service owns a **long-lived SIP registration**: one
9
+ * {@link RingCentralSoftphoneHandle} created + registered at boot, shared across all calls. Inbound calls
10
+ * arrive as SIP INVITEs on that registration (no HTTP webhook); outbound calls place SIP calls through it.
11
+ *
12
+ * It does NOT re-implement bridge logic: it resolves the RingCentral provider + the agent identity, opens a
13
+ * server-side realtime session via the agent layer's `CreateBridgeRealtimeSession` factory, binds a
14
+ * {@link RingCentralSoftphoneCallSdk} (drawing its session from the shared handle) onto the driver, and
15
+ * hands everything to `AIBridgeEngine.StartBridgeSession` — the same seam the Twilio/Vonage services use.
16
+ *
17
+ * @module @memberjunction/server/telephony
18
+ */
19
+ import { RunView, Metadata, LogError, LogStatus } from '@memberjunction/core';
20
+ import { UserCache } from '@memberjunction/sqlserver-dataprovider';
21
+ import { AIBridgeEngine } from '@memberjunction/ai-bridge-server';
22
+ import { CreateBridgeRealtimeSession } from '@memberjunction/ai-agents';
23
+ import { CARRIER_SAMPLE_RATE_CONFIG_KEY, DIRECTION_CONFIG_KEY, FROM_NUMBER_CONFIG_KEY, INBOUND_CALL_ID_CONFIG_KEY, } from '@memberjunction/ai-bridge-base';
24
+ import { createRingCentralSoftphone, RingCentralSoftphoneCallSdk, } from '@memberjunction/ai-bridge-ringcentral';
25
+ import { SessionManager } from '../agentSessions/SessionManager.js';
26
+ const RINGCENTRAL_PROVIDER_DRIVER = 'RingCentralBridge';
27
+ const AGENT_IDENTITY_ENTITY = 'MJ: AI Bridge Agent Identities';
28
+ const PHONE_IDENTITY_TYPE = 'PhoneNumber';
29
+ /** PCM16 carrier rate (Hz) per softphone codec — the rate the bridge resamples to/from the model rate. */
30
+ const CODEC_CARRIER_RATE = {
31
+ 'OPUS/16000': 16000,
32
+ 'OPUS/48000/2': 48000,
33
+ 'PCMU/8000': 8000,
34
+ };
35
+ /**
36
+ * Starts RingCentral bridge sessions over a shared SIP-softphone registration. One instance per server,
37
+ * constructed at boot and held by the runtime holder so the outbound `PlaceRingCentralCall` resolver and the
38
+ * inbound INVITE coordinator share the same registration.
39
+ */
40
+ export class RingCentralTelephonyService {
41
+ constructor(config, deps = {}) {
42
+ this.config = config;
43
+ /** The shared SIP registration — created + registered by {@link start}; null until then. */
44
+ this.handle = null;
45
+ /** The carrier PCM16 rate for the negotiated codec (set in {@link start}). */
46
+ this.carrierSampleRate = CODEC_CARRIER_RATE['OPUS/16000'];
47
+ this.engine = deps.engine ?? AIBridgeEngine.Instance;
48
+ this.sessionFactory = deps.sessionFactory ?? CreateBridgeRealtimeSession;
49
+ this.sessionManager = deps.sessionManager ?? new SessionManager();
50
+ this.createHandle = deps.createHandle ?? createRingCentralSoftphone;
51
+ }
52
+ /**
53
+ * Creates + registers the shared SIP softphone and wires inbound INVITE handling. Called once at boot
54
+ * (fire-and-forget so SIP registration never blocks server startup); logs success/failure. Inbound calls
55
+ * only flow once this resolves.
56
+ */
57
+ async start() {
58
+ try {
59
+ this.carrierSampleRate = CODEC_CARRIER_RATE[this.config.codec ?? 'OPUS/16000'];
60
+ this.handle = await this.createHandle(this.toSoftphoneConfig());
61
+ this.handle.onInvite((info) => void this.onInboundInvite(info));
62
+ await this.handle.register();
63
+ LogStatus('[Telephony][RingCentral] softphone telephony started (inbound + outbound ready).');
64
+ }
65
+ catch (e) {
66
+ this.handle = null;
67
+ LogError(`[Telephony][RingCentral] softphone start failed: ${e instanceof Error ? e.message : String(e)}`);
68
+ }
69
+ }
70
+ /** Best-effort teardown of the SIP registration (server shutdown). */
71
+ dispose() {
72
+ this.handle?.dispose();
73
+ this.handle = null;
74
+ }
75
+ /**
76
+ * Resolves the dialed DID to a pinned agent and starts an INBOUND bridge session. The bound
77
+ * {@link RingCentralSoftphoneCallSdk} answers the parked INVITE for `sessionId`. Returns
78
+ * `{ accepted:false }` (never throws) when no agent identity matches the DID, so the coordinator can
79
+ * decline the INVITE cleanly.
80
+ */
81
+ async HandleInboundCall(input, contextUser, provider) {
82
+ try {
83
+ const identity = await this.resolveAgentIdentityByPhone(input.to, contextUser);
84
+ if (!identity) {
85
+ return { accepted: false, reason: `No active agent identity for dialed number '${input.to}'.` };
86
+ }
87
+ await this.startBridge({
88
+ agentID: identity.AgentID,
89
+ direction: 'Inbound',
90
+ address: input.from,
91
+ inboundCallId: input.sessionId,
92
+ contextUser,
93
+ provider,
94
+ });
95
+ return { accepted: true };
96
+ }
97
+ catch (e) {
98
+ LogError(`[Telephony][RingCentral] inbound call ${input.sessionId} failed: ${e instanceof Error ? e.message : String(e)}`);
99
+ return { accepted: false, reason: 'Internal error starting the agent.' };
100
+ }
101
+ }
102
+ /**
103
+ * Places an OUTBOUND call from a given agent identity to a destination number. The bound
104
+ * {@link RingCentralSoftphoneCallSdk} places the SIP call through the shared registration; the returned
105
+ * SIP `Call-ID` is the bridge's external connection id.
106
+ *
107
+ * @returns The placed call's SIP `Call-ID`.
108
+ */
109
+ async PlaceOutboundCall(agentIdentityId, toNumber, contextUser, provider) {
110
+ const identity = await this.loadAgentIdentity(agentIdentityId, contextUser, provider);
111
+ if (!identity) {
112
+ throw new Error(`Agent identity '${agentIdentityId}' not found or inactive.`);
113
+ }
114
+ const session = await this.startBridge({
115
+ agentID: identity.AgentID,
116
+ direction: 'Outbound',
117
+ address: toNumber,
118
+ fromNumber: identity.IdentityValue,
119
+ contextUser,
120
+ provider,
121
+ });
122
+ return session.RoomKey ?? '';
123
+ }
124
+ // ── internals ────────────────────────────────────────────────────────────────
125
+ /** Inbound INVITE coordinator: resolve the server principal, start a bridge, decline if no agent matched. */
126
+ async onInboundInvite(info) {
127
+ const context = this.resolveServerContext();
128
+ if (!context) {
129
+ LogError('[Telephony][RingCentral] no server context user available; declining inbound call.');
130
+ await this.handle?.declineCall(info.callId);
131
+ return;
132
+ }
133
+ const result = await this.HandleInboundCall({ sessionId: info.callId, from: info.from, to: info.to }, context.user, context.provider);
134
+ if (!result.accepted) {
135
+ LogStatus(`[Telephony][RingCentral] inbound ${info.callId} not accepted: ${result.reason ?? 'unknown'}; declining.`);
136
+ await this.handle?.declineCall(info.callId);
137
+ }
138
+ }
139
+ /** Shared inbound/outbound bridge-start: resolve provider, open the realtime session, bind the SDK, start. */
140
+ async startBridge(args) {
141
+ await this.engine.Config(false, args.contextUser, args.provider);
142
+ const ringCentralProvider = this.resolveProvider();
143
+ const agentSession = await this.sessionManager.CreateSession({ agentID: args.agentID, userID: args.contextUser.ID }, args.contextUser, args.provider);
144
+ const realtimeSession = await this.sessionFactory({
145
+ AgentID: args.agentID,
146
+ TargetAgentID: args.agentID,
147
+ ContextUser: args.contextUser,
148
+ MetadataProvider: args.provider,
149
+ AgentSessionID: agentSession.ID,
150
+ RoomName: args.address,
151
+ });
152
+ const active = await this.engine.StartBridgeSession({
153
+ AgentSessionID: agentSession.ID,
154
+ AgentID: args.agentID,
155
+ TargetAgentID: args.agentID,
156
+ Provider: ringCentralProvider,
157
+ RealtimeSession: realtimeSession,
158
+ Address: args.address,
159
+ Direction: args.direction,
160
+ Configuration: this.buildSessionConfiguration(args.direction, args.fromNumber, args.inboundCallId),
161
+ BindSdk: this.buildBindSdk(),
162
+ ContextUser: args.contextUser,
163
+ MetadataProvider: args.provider,
164
+ });
165
+ return { RoomKey: active.RoomKey };
166
+ }
167
+ /** Resolves the seeded RingCentral provider row (by driver class, falling back to display name). */
168
+ resolveProvider() {
169
+ const provider = this.engine.ProviderByDriverClass(RINGCENTRAL_PROVIDER_DRIVER) ?? this.engine.ProviderByName('RingCentral');
170
+ if (!provider) {
171
+ throw new Error(`No active 'MJ: AI Bridge Providers' row for the RingCentral bridge (DriverClass '${RINGCENTRAL_PROVIDER_DRIVER}').`);
172
+ }
173
+ return provider;
174
+ }
175
+ /**
176
+ * Builds the per-session SDK binding that wires a {@link RingCentralSoftphoneCallSdk} (drawing its
177
+ * session from the shared SIP registration handle) onto the telephony driver — overriding the package's
178
+ * default unbound SDK. Reads the handle lazily at call time so a call placed during the brief boot window
179
+ * before registration fails loudly rather than binding a null handle.
180
+ */
181
+ buildBindSdk() {
182
+ return (driver) => {
183
+ const telephony = driver;
184
+ telephony.SetSdkFactory(() => new RingCentralSoftphoneCallSdk(this.requireHandle()));
185
+ };
186
+ }
187
+ /** Returns the live registration handle, or throws if the softphone hasn't registered yet. */
188
+ requireHandle() {
189
+ if (!this.handle) {
190
+ throw new Error('[Telephony][RingCentral] softphone not registered yet (start() pending or failed).');
191
+ }
192
+ return this.handle;
193
+ }
194
+ /** Assembles the per-session bridge configuration (direction / from-number / inbound-call-id / carrier rate). */
195
+ buildSessionConfiguration(direction, fromNumber, inboundCallId) {
196
+ // The engine does NOT forward the top-level Direction into the driver's Configuration; set it here so
197
+ // an inbound call answers instead of wrongly taking the outbound-dial path. The carrier rate tells the
198
+ // base bridge the SIP leg is wideband (16 kHz for OPUS/16000), not the 8 kHz G.711 default.
199
+ const config = {
200
+ [DIRECTION_CONFIG_KEY]: direction,
201
+ [CARRIER_SAMPLE_RATE_CONFIG_KEY]: this.carrierSampleRate,
202
+ };
203
+ if (fromNumber) {
204
+ config[FROM_NUMBER_CONFIG_KEY] = fromNumber;
205
+ }
206
+ if (inboundCallId) {
207
+ config[INBOUND_CALL_ID_CONFIG_KEY] = inboundCallId;
208
+ }
209
+ return config;
210
+ }
211
+ /** Maps the server config block to the softphone SDK's SIP-device config (credentials resolved upstream). */
212
+ toSoftphoneConfig() {
213
+ return {
214
+ domain: this.config.sipDomain,
215
+ outboundProxy: this.config.sipOutboundProxy,
216
+ username: this.config.sipUsername,
217
+ password: this.config.sipPassword,
218
+ authorizationId: this.config.sipAuthorizationId,
219
+ codec: this.config.codec,
220
+ ignoreTlsCertErrors: this.config.ignoreTlsCertErrors,
221
+ };
222
+ }
223
+ /** Resolves the server-side principal + provider for an inbound call (no MJ JWT on a SIP INVITE). */
224
+ resolveServerContext() {
225
+ const user = UserCache.Instance.GetSystemUser() ?? UserCache.Users.find((u) => u.IsActive && u.Type?.trim().toLowerCase() === 'owner') ?? null;
226
+ const provider = Metadata.Provider; // global-provider-ok: inbound SIP INVITE has no MJ JWT / per-request provider; the server's single default provider is correct
227
+ if (!user || !provider) {
228
+ return null;
229
+ }
230
+ return { user, provider };
231
+ }
232
+ /** Finds the active agent identity whose phone number matches the dialed DID. */
233
+ async resolveAgentIdentityByPhone(dialedNumber, contextUser) {
234
+ const normalized = (dialedNumber ?? '').trim();
235
+ if (!normalized) {
236
+ return null;
237
+ }
238
+ const rv = new RunView();
239
+ const result = await rv.RunView({
240
+ EntityName: AGENT_IDENTITY_ENTITY,
241
+ ExtraFilter: `IdentityType='${PHONE_IDENTITY_TYPE}' AND IdentityValue='${normalized.replace(/'/g, "''")}' AND IsActive=1`,
242
+ MaxRows: 1,
243
+ ResultType: 'entity_object',
244
+ }, contextUser);
245
+ if (!result.Success) {
246
+ LogError(`[Telephony][RingCentral] agent-identity lookup failed: ${result.ErrorMessage}`);
247
+ return null;
248
+ }
249
+ return result.Results?.[0] ?? null;
250
+ }
251
+ /** Loads a specific agent identity by id (used by outbound PlaceCall), requiring it be active. */
252
+ async loadAgentIdentity(agentIdentityId, contextUser, provider) {
253
+ // Use the request-scoped provider (multi-provider safe), not the global Metadata.
254
+ const entity = await provider.GetEntityObject(AGENT_IDENTITY_ENTITY, contextUser);
255
+ const loaded = await entity.Load(agentIdentityId);
256
+ if (!loaded || !entity.IsActive) {
257
+ return null;
258
+ }
259
+ return entity;
260
+ }
261
+ }
262
+ //# sourceMappingURL=RingCentralTelephonyService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RingCentralTelephonyService.js","sourceRoot":"","sources":["../../src/telephony/RingCentralTelephonyService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @fileoverview Express wiring for the Teams meetings ingress — the Microsoft Graph change-notification webhook.
3
+ *
4
+ * One public surface (Graph cannot present an MJ JWT — the subscription validation-token handshake + the
5
+ * per-notification `clientState` shared secret are the gate):
6
+ * - `POST /meetings/teams/notifications` — the Graph change-notification endpoint. Handles BOTH:
7
+ * 1. The **subscription-validation handshake**: when Graph creates/renews a subscription it calls this
8
+ * URL with `?validationToken=…` and expects the exact token echoed back as `text/plain` 200.
9
+ * 2. **Real call/participant notifications**: each carries a `clientState` verified (constant-time)
10
+ * against the secret set on subscription creation, then mapped to the meetings service's roster /
11
+ * call-ended drive helpers.
12
+ *
13
+ * Mirrors the Twilio telephony public-router pattern: mount the router BEFORE the unified auth middleware. The
14
+ * validation + notification parsing use the offline-complete, unit-tested helpers from the Teams provider
15
+ * package (`validateGraphNotification` / `parseCallNotification`); this module is thin HTTP plumbing over them
16
+ * and the {@link TeamsMeetingsService}.
17
+ *
18
+ * The ACS application-hosted-media socket(s) (the audio plane) are owned by the server's native ACS media
19
+ * adapter, which attaches transports to the shared {@link TeamsAcsMediaRegistry} — there is no media WSS here
20
+ * (unlike Twilio Media Streams), because ACS app-hosted media is negotiated out-of-band by that adapter.
21
+ *
22
+ * @module @memberjunction/server/telephony
23
+ */
24
+ import { Router } from 'express';
25
+ import type { TeamsMeetingsConfig } from '../config.js';
26
+ import { TeamsAcsMediaRegistry } from './teamsAcsMediaRegistry.js';
27
+ import { TeamsMeetingsService } from './TeamsMeetingsService.js';
28
+ /** The mount path for the Teams meetings public router. */
29
+ export declare const TEAMS_MEETINGS_MOUNT_PATH = "/meetings/teams";
30
+ /**
31
+ * Builds the Teams meetings handler: the public Graph change-notification router + the shared ACS media
32
+ * registry + the meetings service (returned for observability/tests + so server boot can bind the service to
33
+ * the runtime holder and hand the registry to the native ACS media adapter).
34
+ */
35
+ export declare function createTeamsMeetingsHandler(config: TeamsMeetingsConfig): {
36
+ publicRouter: Router;
37
+ registry: TeamsAcsMediaRegistry;
38
+ service: TeamsMeetingsService;
39
+ };
40
+ //# sourceMappingURL=TeamsMeetingsRouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TeamsMeetingsRouter.d.ts","sourceRoot":"","sources":["../../src/telephony/TeamsMeetingsRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,MAAM,EAAqC,MAAM,SAAS,CAAC;AAOpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,2DAA2D;AAC3D,eAAO,MAAM,yBAAyB,oBAAoB,CAAC;AAO3D;;;;GAIG;AACH,wBAAgB,0BAA0B,CACtC,MAAM,EAAE,mBAAmB,GAC5B;IACC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,qBAAqB,CAAC;IAChC,OAAO,EAAE,oBAAoB,CAAC;CACjC,CAYA"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @fileoverview Express wiring for the Teams meetings ingress — the Microsoft Graph change-notification webhook.
3
+ *
4
+ * One public surface (Graph cannot present an MJ JWT — the subscription validation-token handshake + the
5
+ * per-notification `clientState` shared secret are the gate):
6
+ * - `POST /meetings/teams/notifications` — the Graph change-notification endpoint. Handles BOTH:
7
+ * 1. The **subscription-validation handshake**: when Graph creates/renews a subscription it calls this
8
+ * URL with `?validationToken=…` and expects the exact token echoed back as `text/plain` 200.
9
+ * 2. **Real call/participant notifications**: each carries a `clientState` verified (constant-time)
10
+ * against the secret set on subscription creation, then mapped to the meetings service's roster /
11
+ * call-ended drive helpers.
12
+ *
13
+ * Mirrors the Twilio telephony public-router pattern: mount the router BEFORE the unified auth middleware. The
14
+ * validation + notification parsing use the offline-complete, unit-tested helpers from the Teams provider
15
+ * package (`validateGraphNotification` / `parseCallNotification`); this module is thin HTTP plumbing over them
16
+ * and the {@link TeamsMeetingsService}.
17
+ *
18
+ * The ACS application-hosted-media socket(s) (the audio plane) are owned by the server's native ACS media
19
+ * adapter, which attaches transports to the shared {@link TeamsAcsMediaRegistry} — there is no media WSS here
20
+ * (unlike Twilio Media Streams), because ACS app-hosted media is negotiated out-of-band by that adapter.
21
+ *
22
+ * @module @memberjunction/server/telephony
23
+ */
24
+ import { Router, json } from 'express';
25
+ import { LogError, LogStatus } from '@memberjunction/core';
26
+ import { validateGraphNotification, parseCallNotification, } from '@memberjunction/ai-bridge-teams';
27
+ import { TeamsAcsMediaRegistry } from './teamsAcsMediaRegistry.js';
28
+ import { TeamsMeetingsService } from './TeamsMeetingsService.js';
29
+ /** The mount path for the Teams meetings public router. */
30
+ export const TEAMS_MEETINGS_MOUNT_PATH = '/meetings/teams';
31
+ /**
32
+ * Builds the Teams meetings handler: the public Graph change-notification router + the shared ACS media
33
+ * registry + the meetings service (returned for observability/tests + so server boot can bind the service to
34
+ * the runtime holder and hand the registry to the native ACS media adapter).
35
+ */
36
+ export function createTeamsMeetingsHandler(config) {
37
+ const registry = new TeamsAcsMediaRegistry(config.acsSampleRate);
38
+ const service = new TeamsMeetingsService(config, registry);
39
+ const publicRouter = Router();
40
+ // Graph posts JSON; it also issues the validation handshake as a query-param GET-like POST. Parse JSON but
41
+ // tolerate an empty body on the handshake.
42
+ publicRouter.post('/notifications', json({ type: () => true }), (req, res) => {
43
+ handleGraphNotification(service, config, req, res);
44
+ });
45
+ return { publicRouter, registry, service };
46
+ }
47
+ /** Handles the Graph webhook: echo the validation token, else verify clientState + drive the service. */
48
+ function handleGraphNotification(service, config, req, res) {
49
+ const validationToken = readValidationToken(req);
50
+ const batch = (req.body ?? {});
51
+ const notifications = Array.isArray(batch.value) ? batch.value : [];
52
+ const clientStates = notifications.map((n) => n.clientState);
53
+ const verdict = validateGraphNotification(validationToken, config.notificationClientState ?? '', clientStates);
54
+ if (verdict.Kind === 'validation') {
55
+ // The subscription-validation handshake: echo the token verbatim as text/plain 200.
56
+ res.status(200).type('text/plain').send(verdict.ValidationToken);
57
+ return;
58
+ }
59
+ if (verdict.Kind === 'reject') {
60
+ LogStatus(`[Meetings][Teams] notification rejected: ${verdict.Reason}`);
61
+ res.status(verdict.Reason === 'empty-validation-token' ? 400 : 403).type('text/plain').send('Rejected.');
62
+ return;
63
+ }
64
+ dispatchNotifications(service, notifications);
65
+ // Graph requires a fast 202 to acknowledge receipt; processing is fire-and-forget.
66
+ res.status(202).end();
67
+ }
68
+ /** Maps each Graph call/participant notification to the meetings service's roster / call-ended drive helpers. */
69
+ function dispatchNotifications(service, notifications) {
70
+ for (const notification of notifications) {
71
+ try {
72
+ const normalized = parseCallNotification(notification);
73
+ if (normalized.state === 'terminated') {
74
+ service.DriveCallEnded(normalized.callId);
75
+ }
76
+ else if (normalized.participants.length > 0) {
77
+ service.DriveParticipantsUpdated(normalized.callId, normalized.participants);
78
+ }
79
+ }
80
+ catch (e) {
81
+ LogError(`[Meetings][Teams] failed to process notification: ${e instanceof Error ? e.message : String(e)}`);
82
+ }
83
+ }
84
+ }
85
+ /** Reads the `?validationToken=…` query param (Graph URL-encodes it), when present. */
86
+ function readValidationToken(req) {
87
+ const raw = req.query?.validationToken;
88
+ if (typeof raw === 'string') {
89
+ return raw;
90
+ }
91
+ if (Array.isArray(raw) && typeof raw[0] === 'string') {
92
+ return raw[0];
93
+ }
94
+ return undefined;
95
+ }
96
+ //# sourceMappingURL=TeamsMeetingsRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TeamsMeetingsRouter.js","sourceRoot":"","sources":["../../src/telephony/TeamsMeetingsRouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * @fileoverview Orchestrates Teams meeting bridge sessions (join-by-URL) for MJAPI.
3
+ *
4
+ * This is the composition layer between the Teams meetings ingress (the public Graph change-notification
5
+ * webhook + the server-owned ACS media plane) and the ONE unified realtime-agent pathway. It does NOT
6
+ * re-implement any bridge logic: it resolves the Teams provider + the agent identity, opens a server-side
7
+ * realtime session via the agent layer's `CreateBridgeRealtimeSession` factory, binds the REAL Teams binding
8
+ * (`RealTeamsBindings` over the Graph control plane + the per-call ACS media registry) onto the driver, and
9
+ * hands everything to `AIBridgeEngine.StartBridgeSession` — exactly the seam the Twilio telephony service +
10
+ * the LiveKit room coordinator use.
11
+ *
12
+ * Collaborators are injected (engine, session factory, session manager) so the resolution/branching logic is
13
+ * unit-testable with fakes; the actual Graph call placement + ACS media flow are live-only (real Teams/Azure
14
+ * credentials + a publicly reachable Graph webhook URL — see meeting-vendor-bindings-teams-slack.md M1).
15
+ *
16
+ * @module @memberjunction/server/telephony
17
+ */
18
+ import { UserInfo, IMetadataProvider } from '@memberjunction/core';
19
+ import { AIBridgeEngine, type StartBridgeSessionParams } from '@memberjunction/ai-bridge-server';
20
+ import { CreateBridgeRealtimeSession } from '@memberjunction/ai-agents';
21
+ import { type BridgeNativeSdkBinding } from '@memberjunction/ai-bridge-base';
22
+ import { RealGraphCallsClient } from '@memberjunction/ai-bridge-teams';
23
+ import type { TeamsMeetingsConfig } from '../config.js';
24
+ import { SessionManager } from '../agentSessions/SessionManager.js';
25
+ import { TeamsAcsMediaRegistry } from './teamsAcsMediaRegistry.js';
26
+ /** Result of starting a Teams meeting bridge session. */
27
+ export interface JoinMeetingResult {
28
+ /** Whether a bridge session was started for the meeting. */
29
+ accepted: boolean;
30
+ /** The Graph call id the bot joined (the bridge's external connection id), when accepted. */
31
+ callId?: string;
32
+ /** Why it was rejected (no agent identity, provider missing, unparseable join URL, etc.). */
33
+ reason?: string;
34
+ }
35
+ /** Injectable collaborators (production defaults wired in the constructor; fakes in tests). */
36
+ export interface TeamsMeetingsServiceDeps {
37
+ engine?: Pick<AIBridgeEngine, 'ProviderByName' | 'ProviderByDriverClass' | 'StartBridgeSession' | 'Config'>;
38
+ sessionFactory?: typeof CreateBridgeRealtimeSession;
39
+ sessionManager?: Pick<SessionManager, 'CreateSession'>;
40
+ /** Constructs the Graph control-plane client for a session (default: the real lazy-SDK client). */
41
+ graphClientFactory?: (accessToken: string, tenantId?: string) => RealGraphCallsClient;
42
+ }
43
+ /**
44
+ * Starts Teams meeting bridge sessions. One instance per server, constructed alongside the meetings router and
45
+ * sharing the {@link TeamsAcsMediaRegistry} with the server's ACS media adapter.
46
+ */
47
+ export declare class TeamsMeetingsService {
48
+ private readonly config;
49
+ private readonly registry;
50
+ private readonly engine;
51
+ private readonly sessionFactory;
52
+ private readonly sessionManager;
53
+ private readonly graphClientFactory;
54
+ /** Live Graph clients keyed by call id, so the webhook ingress can drive their roster/ended handlers. */
55
+ private readonly graphClientsByCall;
56
+ constructor(config: TeamsMeetingsConfig, registry: TeamsAcsMediaRegistry, deps?: TeamsMeetingsServiceDeps);
57
+ /**
58
+ * Joins a Teams meeting by URL for a given agent identity and starts the bridge session. The bound
59
+ * `RealTeamsBindings` issues the Graph `POST /communications/calls` and accepts the ACS media transport
60
+ * (attached by the server's media adapter) for the joined call. Returns `{ accepted:false }` (never
61
+ * throws) when the agent identity is missing/inactive, so the caller can answer cleanly.
62
+ *
63
+ * @param agentIdentityId The agent identity to join as (its Teams account/email is the bot's identity).
64
+ * @param joinUrl The Teams meeting join URL.
65
+ * @param contextUser The request-scoped principal.
66
+ * @param provider The request-scoped metadata provider (multi-provider safe — never the global Metadata).
67
+ */
68
+ JoinMeetingByUrl(agentIdentityId: string, joinUrl: string, contextUser: UserInfo, provider: IMetadataProvider): Promise<JoinMeetingResult>;
69
+ /**
70
+ * Drives the retained Graph roster handler for a call from a Graph change notification (called by the
71
+ * webhook ingress — Graph delivers roster changes over the webhook, not a client subscription).
72
+ */
73
+ DriveParticipantsUpdated(callId: string, participants: {
74
+ id: string;
75
+ displayName?: string;
76
+ role?: string;
77
+ }[]): void;
78
+ /** Drives the call-ended handler for a call from a Graph change notification, then tears the call down. */
79
+ DriveCallEnded(callId: string): void;
80
+ /**
81
+ * Builds the {@link StartBridgeSessionParams} for a SCHEDULED Teams join — a bridge the
82
+ * {@link ScheduledBridgeRunner} owns (it created the `MJ: AI Agent Sessions` row and owns the
83
+ * `StartBridgeSession` call). Reuses the same provider resolution, realtime-session factory, Graph
84
+ * client, and bind-sdk as an on-demand join, so a scheduled Teams join is identical to a live one
85
+ * for audio (the ACS media registry is wired via {@link buildBindSdk}).
86
+ *
87
+ * NOTE: an on-demand join also registers the live Graph client by call id for webhook-driven
88
+ * roster/ended routing; the runner abstracts the post-start call id away, so for a SCHEDULED join
89
+ * that notification routing is a documented follow-on. Audio is fully wired here.
90
+ */
91
+ BuildScheduledStartParams(args: {
92
+ agentID: string;
93
+ joinUrl: string;
94
+ agentSessionID: string;
95
+ contextUser: UserInfo;
96
+ provider: IMetadataProvider;
97
+ }): Promise<StartBridgeSessionParams>;
98
+ /** Resolves provider, opens the realtime session, binds the real Teams SDK, and starts the bridge. */
99
+ private startBridge;
100
+ /** Resolves the seeded Teams provider row (by driver class, falling back to display name). */
101
+ private resolveProvider;
102
+ /**
103
+ * Builds the per-session SDK binding that wires the REAL Teams binding (`RealTeamsBindings` over the Graph
104
+ * control plane + the per-call ACS media registry) onto the Teams driver — overriding the package's default
105
+ * native loader. This is where the offline-complete seams meet the live Graph + ACS plumbing.
106
+ */
107
+ buildBindSdk(graphClient: RealGraphCallsClient): BridgeNativeSdkBinding;
108
+ /** Assembles the per-session bridge configuration (carries the resolved tenant for diagnostics). */
109
+ private buildSessionConfiguration;
110
+ /** Loads a specific agent identity by id (used by join-by-URL), requiring it be active. */
111
+ private loadAgentIdentity;
112
+ }
113
+ //# sourceMappingURL=TeamsMeetingsService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TeamsMeetingsService.d.ts","sourceRoot":"","sources":["../../src/telephony/TeamsMeetingsService.ts"],"names":[],"mappings":"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"}