@app-connect/core 1.7.37 → 1.7.38

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 (286) hide show
  1. package/README.md +17 -16
  2. package/dist/connector/developerPortal.d.ts +6 -0
  3. package/{connector → dist/connector}/developerPortal.js +29 -12
  4. package/dist/connector/mock.d.ts +1 -0
  5. package/{connector → dist/connector}/mock.js +33 -17
  6. package/dist/connector/proxy/engine.d.ts +10 -0
  7. package/dist/connector/proxy/engine.js +222 -0
  8. package/dist/connector/proxy/index.d.ts +5 -0
  9. package/dist/connector/proxy/index.js +511 -0
  10. package/dist/connector/registry.d.ts +1 -0
  11. package/dist/connector/registry.js +243 -0
  12. package/dist/handlers/admin.d.ts +1 -0
  13. package/{handlers → dist/handlers}/admin.js +137 -78
  14. package/dist/handlers/appointment.d.ts +9 -0
  15. package/{handlers → dist/handlers}/appointment.js +58 -29
  16. package/dist/handlers/auth.d.ts +9 -0
  17. package/{handlers → dist/handlers}/auth.js +68 -40
  18. package/dist/handlers/calldown.d.ts +10 -0
  19. package/dist/handlers/calldown.js +134 -0
  20. package/dist/handlers/contact.d.ts +1 -0
  21. package/{handlers → dist/handlers}/contact.js +61 -39
  22. package/dist/handlers/disposition.d.ts +1 -0
  23. package/{handlers → dist/handlers}/disposition.js +20 -10
  24. package/dist/handlers/log.d.ts +1 -0
  25. package/{handlers → dist/handlers}/log.js +91 -124
  26. package/dist/handlers/managedAuth.d.ts +1 -0
  27. package/{handlers → dist/handlers}/managedAuth.js +134 -61
  28. package/dist/handlers/managedOAuth.d.ts +13 -0
  29. package/{handlers → dist/handlers}/managedOAuth.js +102 -30
  30. package/dist/handlers/plugin.d.ts +1 -0
  31. package/{handlers → dist/handlers}/plugin.js +59 -27
  32. package/dist/handlers/user.d.ts +1 -0
  33. package/{handlers → dist/handlers}/user.js +45 -27
  34. package/dist/index.d.ts +1 -0
  35. package/{index.js → dist/index.js} +538 -449
  36. package/dist/jest.config.d.ts +1 -0
  37. package/dist/jest.config.js +65 -0
  38. package/dist/lib/analytics.d.ts +4 -0
  39. package/{lib → dist/lib}/analytics.js +8 -6
  40. package/dist/lib/authSession.d.ts +5 -0
  41. package/{lib → dist/lib}/authSession.js +15 -43
  42. package/dist/lib/cacheCleanup.d.ts +4 -0
  43. package/{lib → dist/lib}/cacheCleanup.js +5 -17
  44. package/dist/lib/callLogComposer.d.ts +109 -0
  45. package/{lib → dist/lib}/callLogComposer.js +157 -197
  46. package/dist/lib/callLogLookup.d.ts +6 -0
  47. package/{lib → dist/lib}/callLogLookup.js +12 -34
  48. package/dist/lib/constants.d.ts +6 -0
  49. package/dist/lib/constants.js +9 -0
  50. package/dist/lib/debugTracer.d.ts +17 -0
  51. package/{lib → dist/lib}/debugTracer.js +7 -83
  52. package/dist/lib/encode.d.ts +3 -0
  53. package/dist/lib/encode.js +50 -0
  54. package/dist/lib/errorHandler.d.ts +7 -0
  55. package/dist/lib/errorHandler.js +161 -0
  56. package/dist/lib/generalErrorMessage.d.ts +7 -0
  57. package/{lib → dist/lib}/generalErrorMessage.js +6 -6
  58. package/dist/lib/jwt.d.ts +4 -0
  59. package/dist/lib/jwt.js +18 -0
  60. package/dist/lib/logger.d.ts +24 -0
  61. package/dist/lib/logger.js +126 -0
  62. package/dist/lib/migrateCallLogsSchema.d.ts +32 -0
  63. package/{lib → dist/lib}/migrateCallLogsSchema.js +75 -160
  64. package/dist/lib/oauth.d.ts +4 -0
  65. package/{lib → dist/lib}/oauth.js +157 -160
  66. package/dist/lib/ringcentral.d.ts +24 -0
  67. package/dist/lib/ringcentral.js +226 -0
  68. package/dist/lib/s3ErrorLogReport.d.ts +4 -0
  69. package/{lib → dist/lib}/s3ErrorLogReport.js +11 -23
  70. package/dist/lib/sharedSMSComposer.d.ts +7 -0
  71. package/{lib → dist/lib}/sharedSMSComposer.js +21 -107
  72. package/dist/lib/util.d.ts +7 -0
  73. package/{lib → dist/lib}/util.js +9 -20
  74. package/dist/mcp/lib/oauthError.d.ts +1 -0
  75. package/dist/mcp/lib/oauthError.js +25 -0
  76. package/dist/mcp/lib/validator.d.ts +1 -0
  77. package/{mcp → dist/mcp}/lib/validator.js +16 -20
  78. package/dist/mcp/lib/widgetSessionToken.d.ts +1 -0
  79. package/dist/mcp/lib/widgetSessionToken.js +46 -0
  80. package/dist/mcp/mcpHandler.d.ts +8 -0
  81. package/{mcp → dist/mcp}/mcpHandler.js +98 -88
  82. package/dist/mcp/tools/cancelAppointment.d.ts +1 -0
  83. package/{mcp → dist/mcp}/tools/cancelAppointment.js +7 -16
  84. package/dist/mcp/tools/checkAuthStatus.d.ts +1 -0
  85. package/{mcp → dist/mcp}/tools/checkAuthStatus.js +21 -14
  86. package/dist/mcp/tools/confirmAppointment.d.ts +1 -0
  87. package/{mcp → dist/mcp}/tools/confirmAppointment.js +7 -16
  88. package/dist/mcp/tools/createAppointment.d.ts +1 -0
  89. package/{mcp → dist/mcp}/tools/createAppointment.js +7 -19
  90. package/dist/mcp/tools/createCallLog.d.ts +1 -0
  91. package/{mcp → dist/mcp}/tools/createCallLog.js +18 -29
  92. package/dist/mcp/tools/createContact.d.ts +1 -0
  93. package/{mcp → dist/mcp}/tools/createContact.js +8 -20
  94. package/dist/mcp/tools/createMessageLog.d.ts +1 -0
  95. package/{mcp → dist/mcp}/tools/createMessageLog.js +14 -26
  96. package/dist/mcp/tools/doAuth.d.ts +1 -0
  97. package/{mcp → dist/mcp}/tools/doAuth.js +17 -13
  98. package/dist/mcp/tools/findContactByName.d.ts +1 -0
  99. package/{mcp → dist/mcp}/tools/findContactByName.js +9 -15
  100. package/dist/mcp/tools/findContactByPhone.d.ts +1 -0
  101. package/{mcp → dist/mcp}/tools/findContactByPhone.js +8 -15
  102. package/dist/mcp/tools/getCallLog.d.ts +1 -0
  103. package/{mcp → dist/mcp}/tools/getCallLog.js +12 -21
  104. package/dist/mcp/tools/getGoogleFilePicker.d.ts +1 -0
  105. package/{mcp → dist/mcp}/tools/getGoogleFilePicker.js +9 -18
  106. package/dist/mcp/tools/getHelp.d.ts +1 -0
  107. package/{mcp → dist/mcp}/tools/getHelp.js +5 -6
  108. package/dist/mcp/tools/getPublicConnectors.d.ts +1 -0
  109. package/{mcp → dist/mcp}/tools/getPublicConnectors.js +19 -18
  110. package/dist/mcp/tools/getSessionInfo.d.ts +1 -0
  111. package/{mcp → dist/mcp}/tools/getSessionInfo.js +10 -16
  112. package/dist/mcp/tools/index.d.ts +8 -0
  113. package/dist/mcp/tools/index.js +50 -0
  114. package/dist/mcp/tools/listAppointments.d.ts +1 -0
  115. package/{mcp → dist/mcp}/tools/listAppointments.js +7 -19
  116. package/dist/mcp/tools/logout.d.ts +1 -0
  117. package/{mcp → dist/mcp}/tools/logout.js +16 -14
  118. package/dist/mcp/tools/rcGetCallLogs.d.ts +1 -0
  119. package/{mcp → dist/mcp}/tools/rcGetCallLogs.js +10 -8
  120. package/dist/mcp/tools/updateAppointment.d.ts +1 -0
  121. package/{mcp → dist/mcp}/tools/updateAppointment.js +17 -22
  122. package/dist/mcp/tools/updateCallLog.d.ts +1 -0
  123. package/{mcp → dist/mcp}/tools/updateCallLog.js +16 -26
  124. package/dist/models/accountDataModel.d.ts +3 -0
  125. package/dist/models/accountDataModel.js +39 -0
  126. package/dist/models/adminConfigModel.d.ts +2 -0
  127. package/dist/models/adminConfigModel.js +39 -0
  128. package/dist/models/cacheModel.d.ts +2 -0
  129. package/{models → dist/models}/cacheModel.js +7 -3
  130. package/dist/models/callDownListModel.d.ts +2 -0
  131. package/{models → dist/models}/callDownListModel.js +8 -4
  132. package/dist/models/callLogModel.d.ts +2 -0
  133. package/dist/models/callLogModel.js +43 -0
  134. package/dist/models/dynamo/connectorSchema.d.ts +2 -0
  135. package/dist/models/dynamo/connectorSchema.js +141 -0
  136. package/dist/models/dynamo/lockSchema.d.ts +2 -0
  137. package/{models → dist/models}/dynamo/lockSchema.js +5 -7
  138. package/dist/models/dynamo/noteCacheSchema.d.ts +2 -0
  139. package/{models → dist/models}/dynamo/noteCacheSchema.js +4 -6
  140. package/dist/models/llmSessionModel.d.ts +2 -0
  141. package/dist/models/llmSessionModel.js +21 -0
  142. package/dist/models/messageLogModel.d.ts +2 -0
  143. package/{models → dist/models}/messageLogModel.js +8 -4
  144. package/dist/models/sequelize.d.ts +2 -0
  145. package/dist/models/sequelize.js +68 -0
  146. package/dist/models/userModel.d.ts +2 -0
  147. package/dist/models/userModel.js +49 -0
  148. package/dist/package.json +100 -0
  149. package/dist/releaseNotes.json +1222 -0
  150. package/dist/tsconfig.json +14 -0
  151. package/dist/types/admin.d.ts +141 -0
  152. package/dist/types/analytics.d.ts +14 -0
  153. package/dist/types/appointment.d.ts +50 -0
  154. package/dist/types/auth.d.ts +137 -0
  155. package/dist/types/authSession.d.ts +35 -0
  156. package/dist/types/cacheCleanup.d.ts +12 -0
  157. package/dist/types/calldown.d.ts +54 -0
  158. package/dist/types/common.d.ts +46 -0
  159. package/dist/types/connector.d.ts +165 -0
  160. package/dist/types/contact.d.ts +125 -0
  161. package/dist/types/errorHandler.d.ts +60 -0
  162. package/dist/types/index.d.ts +76 -0
  163. package/dist/types/json.d.ts +9 -0
  164. package/dist/types/jwt.d.ts +8 -0
  165. package/dist/types/logging.d.ts +224 -0
  166. package/dist/types/managedAuth.d.ts +114 -0
  167. package/dist/types/managedOAuth.d.ts +59 -0
  168. package/dist/types/manifest.d.ts +120 -0
  169. package/dist/types/migration.d.ts +15 -0
  170. package/dist/types/plugin.d.ts +74 -0
  171. package/dist/types/ringcentral.d.ts +61 -0
  172. package/dist/types/s3ErrorLogReport.d.ts +16 -0
  173. package/dist/types/sharedSMSComposer.d.ts +105 -0
  174. package/dist/types/user.d.ts +46 -0
  175. package/dist/types/util.d.ts +7 -0
  176. package/package.json +34 -6
  177. package/releaseNotes.json +8 -0
  178. package/.env.test +0 -5
  179. package/connector/proxy/engine.js +0 -165
  180. package/connector/proxy/index.js +0 -500
  181. package/connector/registry.js +0 -252
  182. package/docs/README.md +0 -50
  183. package/docs/architecture.md +0 -94
  184. package/docs/connectors.md +0 -116
  185. package/docs/handlers.md +0 -128
  186. package/docs/libraries.md +0 -98
  187. package/docs/models.md +0 -146
  188. package/docs/routes.md +0 -119
  189. package/docs/tests.md +0 -73
  190. package/handlers/calldown.js +0 -99
  191. package/jest.config.js +0 -57
  192. package/lib/constants.js +0 -9
  193. package/lib/encode.js +0 -30
  194. package/lib/errorHandler.js +0 -218
  195. package/lib/jwt.js +0 -18
  196. package/lib/logger.js +0 -190
  197. package/lib/ringcentral.js +0 -267
  198. package/mcp/README.md +0 -420
  199. package/mcp/tools/index.js +0 -51
  200. package/mcp/ui/App/App.tsx +0 -358
  201. package/mcp/ui/App/components/AuthInfoForm.tsx +0 -113
  202. package/mcp/ui/App/components/AuthSuccess.tsx +0 -22
  203. package/mcp/ui/App/components/ConnectorList.tsx +0 -82
  204. package/mcp/ui/App/components/DebugPanel.tsx +0 -43
  205. package/mcp/ui/App/components/OAuthConnect.tsx +0 -270
  206. package/mcp/ui/App/lib/callTool.ts +0 -130
  207. package/mcp/ui/App/lib/debugLog.ts +0 -41
  208. package/mcp/ui/App/lib/developerPortal.ts +0 -111
  209. package/mcp/ui/App/main.css +0 -6
  210. package/mcp/ui/App/root.tsx +0 -13
  211. package/mcp/ui/dist/index.html +0 -53
  212. package/mcp/ui/vite.config.ts +0 -16
  213. package/models/accountDataModel.js +0 -34
  214. package/models/adminConfigModel.js +0 -35
  215. package/models/callLogModel.js +0 -39
  216. package/models/dynamo/connectorSchema.js +0 -146
  217. package/models/llmSessionModel.js +0 -17
  218. package/models/sequelize.js +0 -17
  219. package/models/userModel.js +0 -45
  220. package/test/connector/developerPortal.test.js +0 -166
  221. package/test/connector/mock.test.js +0 -131
  222. package/test/connector/proxy/engine.test.js +0 -211
  223. package/test/connector/proxy/index.test.js +0 -525
  224. package/test/connector/proxy/sample.json +0 -162
  225. package/test/connector/registry.test.js +0 -416
  226. package/test/handlers/admin.test.js +0 -960
  227. package/test/handlers/appointment.test.js +0 -260
  228. package/test/handlers/auth.test.js +0 -1096
  229. package/test/handlers/calldown.test.js +0 -310
  230. package/test/handlers/contact.test.js +0 -1014
  231. package/test/handlers/disposition.test.js +0 -396
  232. package/test/handlers/log.test.js +0 -1847
  233. package/test/handlers/managedAuth.test.js +0 -458
  234. package/test/handlers/managedOAuth.test.js +0 -262
  235. package/test/handlers/plugin.test.js +0 -429
  236. package/test/handlers/user.test.js +0 -381
  237. package/test/index.test.js +0 -301
  238. package/test/lib/analytics.test.js +0 -146
  239. package/test/lib/authSession.test.js +0 -173
  240. package/test/lib/cacheCleanup.test.js +0 -127
  241. package/test/lib/callLogComposer.test.js +0 -1231
  242. package/test/lib/debugTracer.test.js +0 -328
  243. package/test/lib/encode.test.js +0 -59
  244. package/test/lib/errorHandler.test.js +0 -246
  245. package/test/lib/generalErrorMessage.test.js +0 -82
  246. package/test/lib/jwt.test.js +0 -176
  247. package/test/lib/logger.test.js +0 -206
  248. package/test/lib/oauth.test.js +0 -359
  249. package/test/lib/ringcentral.test.js +0 -467
  250. package/test/lib/s3ErrorLogReport.test.js +0 -187
  251. package/test/lib/sharedSMSComposer.test.js +0 -1084
  252. package/test/lib/util.test.js +0 -329
  253. package/test/mcp/mcpHandler.test.js +0 -73
  254. package/test/mcp/mcpHandlerMore.test.js +0 -384
  255. package/test/mcp/tools/appointmentTools.test.js +0 -362
  256. package/test/mcp/tools/checkAuthStatus.test.js +0 -83
  257. package/test/mcp/tools/createCallLog.test.js +0 -436
  258. package/test/mcp/tools/createContact.test.js +0 -58
  259. package/test/mcp/tools/createMessageLog.test.js +0 -595
  260. package/test/mcp/tools/doAuth.test.js +0 -113
  261. package/test/mcp/tools/findContactByName.test.js +0 -275
  262. package/test/mcp/tools/findContactByPhone.test.js +0 -296
  263. package/test/mcp/tools/getCallLog.test.js +0 -298
  264. package/test/mcp/tools/getGoogleFilePicker.test.js +0 -281
  265. package/test/mcp/tools/getPublicConnectors.test.js +0 -107
  266. package/test/mcp/tools/getSessionInfo.test.js +0 -127
  267. package/test/mcp/tools/logout.test.js +0 -233
  268. package/test/mcp/tools/rcGetCallLogs.test.js +0 -56
  269. package/test/mcp/tools/updateCallLog.test.js +0 -360
  270. package/test/models/accountDataModel.test.js +0 -98
  271. package/test/models/callDownListModel.test.js +0 -125
  272. package/test/models/dynamo/connectorSchema.test.js +0 -189
  273. package/test/models/dynamo/lockSchema.test.js +0 -37
  274. package/test/models/dynamo/noteCacheSchema.test.js +0 -45
  275. package/test/models/llmSessionModel.test.js +0 -91
  276. package/test/models/models.test.js +0 -660
  277. package/test/routes/calldownRoutes.test.js +0 -224
  278. package/test/routes/coreRouterBroadRoutes.test.js +0 -855
  279. package/test/routes/dispositionRoutes.test.js +0 -192
  280. package/test/routes/managedAuthRoutes.test.js +0 -386
  281. package/test/routes/pluginRoutes.test.js +0 -262
  282. package/test/setup.js +0 -178
  283. /package/{mcp → dist/mcp}/ui/index.html +0 -0
  284. /package/{mcp → dist/mcp}/ui/package-lock.json +0 -0
  285. /package/{mcp → dist/mcp}/ui/package.json +0 -0
  286. /package/{mcp → dist/mcp}/ui/tsconfig.json +0 -0
@@ -0,0 +1,7 @@
1
+ import type { ComposeSharedSMSLogParams, ProcessSharedSMSEntitiesParams, SharedSMSEntity, SharedSMSEntityCounts, SharedSMSLogContent, SharedSMSProcessedEntry } from '../types';
2
+ declare function composeSharedSMSLog({ logFormat, conversation, contactName, timezoneOffset }: ComposeSharedSMSLogParams): SharedSMSLogContent;
3
+ declare function gatherAgents(entities: SharedSMSEntity[]): string[];
4
+ declare function countEntities(entities: SharedSMSEntity[]): SharedSMSEntityCounts;
5
+ declare function processEntities({ entities, timezoneOffset, logFormat, contactName }: ProcessSharedSMSEntitiesParams): SharedSMSProcessedEntry[];
6
+ declare function escapeHtml(text: string | null | undefined): string;
7
+ export { composeSharedSMSLog, gatherAgents as gatherParticipants, countEntities, processEntities, escapeHtml };
@@ -1,6 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.composeSharedSMSLog = composeSharedSMSLog;
4
+ exports.gatherParticipants = gatherAgents;
5
+ exports.countEntities = countEntities;
6
+ exports.processEntities = processEntities;
7
+ exports.escapeHtml = escapeHtml;
1
8
  const moment = require('moment-timezone');
2
9
  const { LOG_DETAILS_FORMAT_TYPE } = require('./constants');
3
-
4
10
  function composeSharedSMSLog({ logFormat = LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT, conversation, contactName, timezoneOffset }) {
5
11
  const conversationCreatedDate = moment(conversation?.creationTime);
6
12
  const conversationUpdatedDate = moment(findLatestModifiedTime(conversation.messages));
@@ -8,24 +14,20 @@ function composeSharedSMSLog({ logFormat = LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT, c
8
14
  conversationCreatedDate.utcOffset(timezoneOffset);
9
15
  conversationUpdatedDate.utcOffset(timezoneOffset);
10
16
  }
11
-
12
17
  const subject = composeSubject({
13
18
  logFormat,
14
19
  contactName
15
20
  });
16
-
17
21
  const body = composeBody({
18
22
  logFormat,
19
23
  conversation,
20
24
  contactName,
21
25
  conversationCreatedDate,
22
26
  conversationUpdatedDate,
23
- timezoneOffset,
27
+ timezoneOffset
24
28
  });
25
-
26
29
  return { subject, body };
27
30
  }
28
-
29
31
  function findLatestModifiedTime(messages) {
30
32
  let result = 0;
31
33
  for (const message of messages) {
@@ -35,10 +37,8 @@ function findLatestModifiedTime(messages) {
35
37
  }
36
38
  return result;
37
39
  }
38
-
39
40
  function composeSubject({ logFormat, contactName }) {
40
41
  const title = `SMS conversation with ${contactName}`;
41
-
42
42
  switch (logFormat) {
43
43
  case LOG_DETAILS_FORMAT_TYPE.HTML:
44
44
  return title;
@@ -49,33 +49,16 @@ function composeSubject({ logFormat, contactName }) {
49
49
  return title;
50
50
  }
51
51
  }
52
-
53
- function composeBody({
54
- logFormat,
55
- conversation,
56
- contactName,
57
- conversationCreatedDate,
58
- conversationUpdatedDate,
59
- timezoneOffset
60
- }) {
61
- // Gather participants from entities
52
+ function composeBody({ logFormat, conversation, contactName, conversationCreatedDate, conversationUpdatedDate, timezoneOffset }) {
62
53
  const agents = gatherAgents(conversation.entities || []);
63
-
64
- // Get owner/call queue info
65
54
  const ownerInfo = getOwnerInfo(conversation);
66
-
67
- // Count messages and notes
68
55
  const { messageCount, noteCount } = countEntities(conversation.entities || []);
69
-
70
- // Process entities into formatted entries
71
56
  const formattedEntries = processEntities({
72
57
  entities: conversation.entities || [],
73
58
  timezoneOffset,
74
59
  logFormat,
75
60
  contactName
76
61
  });
77
-
78
- // Build the body based on format
79
62
  switch (logFormat) {
80
63
  case LOG_DETAILS_FORMAT_TYPE.HTML:
81
64
  return composeHTMLBody({
@@ -113,11 +96,8 @@ function composeBody({
113
96
  });
114
97
  }
115
98
  }
116
-
117
99
  function gatherAgents(entities) {
118
100
  const participantSet = new Set();
119
-
120
- // Add from entities
121
101
  if (entities) {
122
102
  for (const entity of entities) {
123
103
  if (entity.author?.name) {
@@ -136,14 +116,11 @@ function gatherAgents(entities) {
136
116
  }
137
117
  return Array.from(participantSet);
138
118
  }
139
-
140
119
  function getOwnerInfo(conversation) {
141
- if (!conversation.owner) return null;
142
-
120
+ if (!conversation.owner)
121
+ return null;
143
122
  const ownerName = conversation.owner.name || '';
144
123
  const extensionType = conversation.owner.extensionType;
145
-
146
- // Check if it's a call queue (Department type)
147
124
  if (extensionType === 'Department' || ownerName.toLowerCase().includes('queue')) {
148
125
  return {
149
126
  type: 'callQueue',
@@ -151,32 +128,27 @@ function getOwnerInfo(conversation) {
151
128
  extensionId: conversation.owner.extensionId
152
129
  };
153
130
  }
154
-
155
131
  return {
156
132
  type: 'user',
157
133
  name: ownerName,
158
134
  extensionId: conversation.owner.extensionId
159
135
  };
160
136
  }
161
-
162
137
  function countEntities(entities) {
163
138
  let messageCount = 0;
164
139
  let noteCount = 0;
165
-
166
140
  for (const entity of entities) {
167
141
  if (entity.recordType === 'AliveMessage') {
168
142
  messageCount++;
169
- } else if (entity.recordType === 'AliveNote') {
143
+ }
144
+ else if (entity.recordType === 'AliveNote') {
170
145
  noteCount++;
171
146
  }
172
147
  }
173
-
174
148
  return { messageCount, noteCount };
175
149
  }
176
-
177
150
  function processEntities({ entities, timezoneOffset, logFormat, contactName }) {
178
151
  const processedEntries = [];
179
-
180
152
  for (const entity of entities) {
181
153
  const entry = processEntity({
182
154
  entity,
@@ -188,13 +160,9 @@ function processEntities({ entities, timezoneOffset, logFormat, contactName }) {
188
160
  processedEntries.push(entry);
189
161
  }
190
162
  }
191
-
192
- // Sort by creation time (newest first for display)
193
163
  processedEntries.sort((a, b) => b.creationTime - a.creationTime);
194
-
195
164
  return processedEntries;
196
165
  }
197
-
198
166
  function processEntity({ entity, timezoneOffset, logFormat, contactName }) {
199
167
  const creationTime = entity.creationTime;
200
168
  let momentTime = moment(creationTime);
@@ -202,32 +170,24 @@ function processEntity({ entity, timezoneOffset, logFormat, contactName }) {
202
170
  momentTime = momentTime.utcOffset(timezoneOffset);
203
171
  }
204
172
  const formattedTime = momentTime.format('YYYY-MM-DD hh:mm A');
205
-
206
173
  switch (entity.recordType) {
207
174
  case 'AliveMessage':
208
175
  return formatMessage({ entity, contactName, formattedTime, creationTime, logFormat });
209
-
210
176
  case 'ThreadAssignedHint':
211
177
  return formatAssignment({ entity, formattedTime, creationTime, logFormat });
212
-
213
178
  case 'AliveNote':
214
179
  return formatNote({ entity, formattedTime, creationTime, logFormat });
215
-
216
180
  case 'ThreadCreatedHint':
217
- // Skip thread created hints - not typically shown in log body
218
181
  return null;
219
-
220
182
  default:
221
183
  return null;
222
184
  }
223
185
  }
224
-
225
186
  function formatMessage({ entity, contactName, formattedTime, creationTime, logFormat }) {
226
187
  const authorName = entity.author?.name || entity.from?.name;
227
188
  const isInbound = entity.direction === 'Inbound';
228
189
  const senderName = isInbound ? contactName : authorName;
229
190
  const messageText = entity.text || entity.subject || '';
230
-
231
191
  switch (logFormat) {
232
192
  case LOG_DETAILS_FORMAT_TYPE.HTML:
233
193
  return {
@@ -250,10 +210,8 @@ function formatMessage({ entity, contactName, formattedTime, creationTime, logFo
250
210
  };
251
211
  }
252
212
  }
253
-
254
213
  function formatAssignment({ entity, formattedTime, creationTime, logFormat }) {
255
214
  const assigneeName = entity.assignee?.name || 'Unknown';
256
-
257
215
  switch (logFormat) {
258
216
  case LOG_DETAILS_FORMAT_TYPE.HTML:
259
217
  return {
@@ -276,11 +234,9 @@ function formatAssignment({ entity, formattedTime, creationTime, logFormat }) {
276
234
  };
277
235
  }
278
236
  }
279
-
280
237
  function formatNote({ entity, formattedTime, creationTime, logFormat }) {
281
238
  const authorName = entity.author?.name || entity.initiator?.name || 'Unknown';
282
239
  const noteText = entity.text || entity.body || '';
283
-
284
240
  switch (logFormat) {
285
241
  case LOG_DETAILS_FORMAT_TYPE.HTML:
286
242
  return {
@@ -303,34 +259,27 @@ function formatNote({ entity, formattedTime, creationTime, logFormat }) {
303
259
  };
304
260
  }
305
261
  }
306
-
307
262
  function composePlainTextBody({ conversationCreatedDate, conversationUpdatedDate, contactName, agents, ownerInfo, messageCount, noteCount, formattedEntries }) {
308
263
  let body = '';
309
-
310
- // Conversation summary header
311
264
  body += 'Conversation summary\n';
312
265
  body += `Started: ${conversationCreatedDate.format('dddd, MMMM DD, YYYY')} at ${conversationCreatedDate.format('hh:mm A')}\n`;
313
266
  body += `Ended: ${conversationUpdatedDate ? conversationUpdatedDate.format('dddd, MMMM DD, YYYY') : 'On-going'} at ${conversationUpdatedDate ? conversationUpdatedDate.format('hh:mm A') : 'On-going'}\n`;
314
267
  body += `Duration: ${conversationUpdatedDate ? `${conversationUpdatedDate.diff(conversationCreatedDate, 'days')} d ${conversationUpdatedDate.diff(conversationCreatedDate, 'hours')} h` : 'On-going'} \n`;
315
268
  body += '\n';
316
- // Participants
317
269
  body += 'Participants\n';
318
270
  body += `* ${contactName} (customer)\n`;
319
271
  for (const agent of agents) {
320
272
  body += `* ${agent}\n`;
321
273
  }
322
274
  body += '\n';
323
-
324
- // Owner/Call queue info
325
275
  if (ownerInfo) {
326
276
  if (ownerInfo.type === 'callQueue') {
327
277
  body += `Receiving call queue: ${ownerInfo.name}\n\n`;
328
- } else {
278
+ }
279
+ else {
329
280
  body += `Owner: ${ownerInfo.name}\n\n`;
330
281
  }
331
282
  }
332
-
333
- // Conversation count
334
283
  const countParts = [];
335
284
  if (messageCount > 0) {
336
285
  countParts.push(`${messageCount} message${messageCount !== 1 ? 's' : ''}`);
@@ -341,45 +290,34 @@ function composePlainTextBody({ conversationCreatedDate, conversationUpdatedDate
341
290
  body += `Conversation (${countParts.join(', ') || '0 messages'})\n`;
342
291
  body += 'BEGIN\n';
343
292
  body += '------------\n';
344
-
345
- // Formatted entries
346
293
  for (const entry of formattedEntries) {
347
294
  body += entry.content + '\n';
348
295
  }
349
-
350
296
  body += '------------\n';
351
297
  body += 'END';
352
-
353
298
  return body;
354
299
  }
355
-
356
300
  function composeHTMLBody({ conversationCreatedDate, conversationUpdatedDate, contactName, agents, ownerInfo, messageCount, noteCount, formattedEntries }) {
357
301
  let body = '';
358
-
359
- // Conversation summary header
360
302
  body += '<div><b>Conversation summary</b><br>';
361
303
  body += `Started: ${conversationCreatedDate.format('dddd, MMMM DD, YYYY')} at ${conversationCreatedDate.format('hh:mm A')}<br>`;
362
304
  body += `Ended: ${conversationUpdatedDate ? conversationUpdatedDate.format('dddd, MMMM DD, YYYY') : 'On-going'} at ${conversationUpdatedDate ? conversationUpdatedDate.format('hh:mm A') : 'On-going'}<br>`;
363
305
  body += `Duration: ${conversationUpdatedDate ? `${conversationUpdatedDate.diff(conversationCreatedDate, 'days')} d ${conversationUpdatedDate.diff(conversationCreatedDate, 'hours')} h` : 'On-going'}<br>`;
364
306
  body += '</div><br>';
365
- // Participants
366
307
  body += '<div><b>Participants</b><ul>';
367
308
  body += `<li>${escapeHtml(contactName)} (customer)</li>`;
368
309
  for (const agent of agents) {
369
310
  body += `<li>${escapeHtml(agent)}</li>`;
370
311
  }
371
312
  body += '</ul></div>';
372
-
373
- // Owner/Call queue info
374
313
  if (ownerInfo) {
375
314
  if (ownerInfo.type === 'callQueue') {
376
315
  body += `<div>Receiving call queue: <b>${escapeHtml(ownerInfo.name)}</b></div><br>`;
377
- } else {
316
+ }
317
+ else {
378
318
  body += `<div>Owner: <b>${escapeHtml(ownerInfo.name)}</b></div><br>`;
379
319
  }
380
320
  }
381
-
382
- // Conversation count
383
321
  const countParts = [];
384
322
  if (messageCount > 0) {
385
323
  countParts.push(`${messageCount} message${messageCount !== 1 ? 's' : ''}`);
@@ -390,45 +328,34 @@ function composeHTMLBody({ conversationCreatedDate, conversationUpdatedDate, con
390
328
  body += `<div><b>Conversation (${countParts.join(', ') || '0 messages'})</b></div>`;
391
329
  body += '<div>BEGIN</div>';
392
330
  body += '<hr>';
393
-
394
- // Formatted entries
395
331
  for (const entry of formattedEntries) {
396
332
  body += entry.content;
397
333
  }
398
-
399
334
  body += '<hr>';
400
335
  body += '<div>END</div>';
401
-
402
336
  return body;
403
337
  }
404
-
405
338
  function composeMarkdownBody({ conversationCreatedDate, conversationUpdatedDate, contactName, agents, ownerInfo, messageCount, noteCount, formattedEntries }) {
406
339
  let body = '';
407
-
408
- // Conversation summary header
409
340
  body += '## Conversation summary\n';
410
341
  body += `Started: ${conversationCreatedDate.format('dddd, MMMM DD, YYYY')} at ${conversationCreatedDate.format('hh:mm A')}\n`;
411
342
  body += `Ended: ${conversationUpdatedDate ? conversationUpdatedDate.format('dddd, MMMM DD, YYYY') : 'On-going'} at ${conversationUpdatedDate ? conversationUpdatedDate.format('hh:mm A') : 'On-going'}\n`;
412
343
  body += `Duration: ${conversationUpdatedDate ? `${conversationUpdatedDate.diff(conversationCreatedDate, 'days')} d ${conversationUpdatedDate.diff(conversationCreatedDate, 'hours')} h` : 'On-going'} \n`;
413
344
  body += '\n';
414
- // Participants
415
345
  body += '### Participants\n';
416
346
  body += `* ${contactName} (customer)\n`;
417
347
  for (const agent of agents) {
418
348
  body += `* ${agent}\n`;
419
349
  }
420
350
  body += '\n';
421
-
422
- // Owner/Call queue info
423
351
  if (ownerInfo) {
424
352
  if (ownerInfo.type === 'callQueue') {
425
353
  body += `Receiving call queue: **${ownerInfo.name}**\n\n`;
426
- } else {
354
+ }
355
+ else {
427
356
  body += `Owner: **${ownerInfo.name}**\n\n`;
428
357
  }
429
358
  }
430
-
431
- // Conversation count
432
359
  const countParts = [];
433
360
  if (messageCount > 0) {
434
361
  countParts.push(`${messageCount} message${messageCount !== 1 ? 's' : ''}`);
@@ -439,20 +366,16 @@ function composeMarkdownBody({ conversationCreatedDate, conversationUpdatedDate,
439
366
  body += `### Conversation (${countParts.join(', ') || '0 messages'})\n`;
440
367
  body += 'BEGIN\n';
441
368
  body += '---\n';
442
-
443
- // Formatted entries
444
369
  for (const entry of formattedEntries) {
445
370
  body += entry.content + '\n';
446
371
  }
447
-
448
372
  body += '---\n';
449
373
  body += 'END';
450
-
451
374
  return body;
452
375
  }
453
-
454
376
  function escapeHtml(text) {
455
- if (!text) return '';
377
+ if (!text)
378
+ return '';
456
379
  return text
457
380
  .replace(/&/g, '&amp;')
458
381
  .replace(/</g, '&lt;')
@@ -460,12 +383,3 @@ function escapeHtml(text) {
460
383
  .replace(/"/g, '&quot;')
461
384
  .replace(/'/g, '&#039;');
462
385
  }
463
-
464
- module.exports = {
465
- composeSharedSMSLog,
466
- gatherParticipants: gatherAgents,
467
- countEntities,
468
- processEntities,
469
- escapeHtml
470
- };
471
-
@@ -0,0 +1,7 @@
1
+ import type { MediaLinkInput, MostRecentDateParams, SecondsInput } from '../types';
2
+ declare function getTimeZone(countryCode: string, stateCode: string): string | null;
3
+ declare function getHashValue(string: string | number | undefined | null, secretKey: string | undefined | null): string;
4
+ declare function secondsToHoursMinutesSeconds(seconds: SecondsInput): SecondsInput | string;
5
+ declare function getMostRecentDate({ allDateValues }: MostRecentDateParams): number;
6
+ declare function getMediaReaderLinkByPlatformMediaLink(platformMediaLink: MediaLinkInput): string | null;
7
+ export { getTimeZone, getHashValue, secondsToHoursMinutesSeconds, getMostRecentDate, getMediaReaderLinkByPlatformMediaLink };
@@ -1,8 +1,13 @@
1
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTimeZone = getTimeZone;
4
+ exports.getHashValue = getHashValue;
5
+ exports.secondsToHoursMinutesSeconds = secondsToHoursMinutesSeconds;
6
+ exports.getMostRecentDate = getMostRecentDate;
7
+ exports.getMediaReaderLinkByPlatformMediaLink = getMediaReaderLinkByPlatformMediaLink;
2
8
  const tzlookup = require('tz-lookup');
3
9
  const { State } = require('country-state-city');
4
10
  const crypto = require('crypto');
5
-
6
11
  function getTimeZone(countryCode, stateCode) {
7
12
  const state = State.getStateByCodeAndCountry(stateCode, countryCode);
8
13
  if (!state) {
@@ -11,16 +16,10 @@ function getTimeZone(countryCode, stateCode) {
11
16
  const timezone = tzlookup(state.latitude, state.longitude);
12
17
  return timezone;
13
18
  }
14
-
15
-
16
19
  function getHashValue(string, secretKey) {
17
- return crypto.createHash('sha256').update(
18
- `${string}:${secretKey}`
19
- ).digest('hex');
20
+ return crypto.createHash('sha256').update(`${string}:${secretKey}`).digest('hex');
20
21
  }
21
-
22
22
  function secondsToHoursMinutesSeconds(seconds) {
23
- // If not a number, return the input directly
24
23
  if (isNaN(seconds)) {
25
24
  return seconds;
26
25
  }
@@ -36,9 +35,8 @@ function secondsToHoursMinutesSeconds(seconds) {
36
35
  const resultString = [hoursString, minutesString, secondsString].filter(Boolean).join(', ');
37
36
  return resultString;
38
37
  }
39
-
40
38
  function getMostRecentDate({ allDateValues }) {
41
- var result = 0;
39
+ let result = 0;
42
40
  for (const date of allDateValues) {
43
41
  if (!date) {
44
42
  continue;
@@ -49,9 +47,6 @@ function getMostRecentDate({ allDateValues }) {
49
47
  }
50
48
  return result;
51
49
  }
52
-
53
- // media reader link: https://ringcentral.github.io/ringcentral-media-reader/?media=https://media.ringcentral.com/restapi/v1.0/account/{accountId}/extension/{extensionId}/message-store/{messageId}/content/{contentId}
54
- // platform media link: https://media.ringcentral.com/restapi/v1.0/account/{accountId}/extension/{extensionId}/message-store/{messageId}/content/{contentId}
55
50
  function getMediaReaderLinkByPlatformMediaLink(platformMediaLink) {
56
51
  if (!platformMediaLink) {
57
52
  return null;
@@ -59,9 +54,3 @@ function getMediaReaderLinkByPlatformMediaLink(platformMediaLink) {
59
54
  const encodedPlatformMediaLink = encodeURIComponent(platformMediaLink);
60
55
  return `https://ringcentral.github.io/ringcentral-media-reader/?media=${encodedPlatformMediaLink}`;
61
56
  }
62
-
63
- exports.getTimeZone = getTimeZone;
64
- exports.getHashValue = getHashValue;
65
- exports.secondsToHoursMinutesSeconds = secondsToHoursMinutesSeconds;
66
- exports.getMostRecentDate = getMostRecentDate;
67
- exports.getMediaReaderLinkByPlatformMediaLink = getMediaReaderLinkByPlatformMediaLink;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ // @ts-check
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const MCP_OAUTH_REQUIRED_MESSAGE = 'RingCentral authorization is required to use App Connect MCP. If this MCP server was connected before the PKCE update, disconnect and reconnect it so your MCP client gets the new public PKCE client ID.';
5
+ const MCP_OAUTH_STALE_CLIENT_MESSAGE = 'This App Connect MCP authorization was started with an outdated RingCentral OAuth client ID. App Connect MCP now uses PKCE. Disconnect or remove the App Connect MCP server in your MCP client, then add and connect it again.';
6
+ const MCP_OAUTH_INVALID_TOKEN_MESSAGE = 'The RingCentral authorization for App Connect MCP is missing, expired, or could not be refreshed. If this started after the PKCE update, disconnect and reconnect App Connect MCP so your client uses the new public PKCE client ID.';
7
+ function escapeBearerValue(value) {
8
+ return String(value || '').replace(/\\/g, '\\\\').replace(/"/g, '\\"');
9
+ }
10
+ function getMcpOAuthChallengeHeader({ appServer = process.env.APP_SERVER, error = 'invalid_token', errorDescription = MCP_OAUTH_REQUIRED_MESSAGE } = {}) {
11
+ return `Bearer realm="mcp", resource_metadata="${escapeBearerValue(`${appServer}/.well-known/oauth-protected-resource`)}", error="${escapeBearerValue(error)}", error_description="${escapeBearerValue(errorDescription)}"`;
12
+ }
13
+ function buildMcpOAuthError({ error = 'mcp_oauth_reconnect_required', message = MCP_OAUTH_INVALID_TOKEN_MESSAGE, errorDetails = undefined, } = {}) {
14
+ return {
15
+ success: false,
16
+ error,
17
+ message,
18
+ ...(errorDetails ? { errorDetails } : {}),
19
+ };
20
+ }
21
+ exports.MCP_OAUTH_REQUIRED_MESSAGE = MCP_OAUTH_REQUIRED_MESSAGE;
22
+ exports.MCP_OAUTH_STALE_CLIENT_MESSAGE = MCP_OAUTH_STALE_CLIENT_MESSAGE;
23
+ exports.MCP_OAUTH_INVALID_TOKEN_MESSAGE = MCP_OAUTH_INVALID_TOKEN_MESSAGE;
24
+ exports.getMcpOAuthChallengeHeader = getMcpOAuthChallengeHeader;
25
+ exports.buildMcpOAuthError = buildMcpOAuthError;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,42 +1,43 @@
1
+ "use strict";
2
+ // @ts-check
3
+ Object.defineProperty(exports, "__esModule", { value: true });
1
4
  /**
2
5
  * Validates a connector manifest structure
3
- * @param {Object} params - The validation parameters
4
- * @param {Object} params.connectorManifest - The connector manifest object
5
- * @param {string} params.connectorName - The name of the connector (e.g., 'clio')
6
- * @returns {Object} Validation result with isValid boolean and errors array
6
+ * @param {{ connectorManifest?: any, connectorName: string }} params - The validation parameters
7
+ * @returns {{ isValid: boolean, errors: string[] }} Validation result with isValid boolean and errors array
7
8
  */
8
9
  function isManifestValid({ connectorManifest, connectorName }) {
10
+ /** @type {string[]} */
9
11
  const errors = [];
10
-
11
12
  // Check basic manifest structure
12
13
  if (!connectorManifest) {
13
14
  errors.push('connectorManifest is required');
14
15
  return { isValid: false, errors };
15
16
  }
16
-
17
17
  if (!connectorManifest.platforms) {
18
18
  errors.push('connectorManifest.platforms is required');
19
19
  return { isValid: false, errors };
20
20
  }
21
-
22
21
  const platform = connectorManifest.platforms[connectorName];
23
22
  if (!platform) {
24
23
  errors.push(`Platform "${connectorName}" not found in manifest`);
25
24
  return { isValid: false, errors };
26
25
  }
27
-
28
26
  // Validate auth configuration
29
27
  if (!platform.auth) {
30
28
  errors.push('platform.auth is required');
31
- } else {
29
+ }
30
+ else {
32
31
  if (!platform.auth.type) {
33
32
  errors.push('platform.auth.type is required');
34
- } else {
33
+ }
34
+ else {
35
35
  const authType = platform.auth.type.toLowerCase();
36
36
  if (authType === 'oauth') {
37
37
  if (!platform.auth.oauth) {
38
38
  errors.push('platform.auth.oauth configuration is required for oauth type');
39
- } else {
39
+ }
40
+ else {
40
41
  if (!platform.auth.oauth.authUrl) {
41
42
  errors.push('platform.auth.oauth.authUrl is required');
42
43
  }
@@ -44,48 +45,43 @@ function isManifestValid({ connectorManifest, connectorName }) {
44
45
  errors.push('platform.auth.oauth.clientId is required');
45
46
  }
46
47
  }
47
- } else if (authType === 'apikey') {
48
+ }
49
+ else if (authType === 'apikey') {
48
50
  if (!platform.auth.apiKey) {
49
51
  errors.push('platform.auth.apiKey configuration is required for apiKey type');
50
52
  }
51
53
  }
52
54
  }
53
55
  }
54
-
55
56
  // Validate environment configuration (optional but if present, must have type)
56
57
  if (platform.environment) {
57
58
  if (!platform.environment.type) {
58
59
  errors.push('platform.environment.type is required when environment is specified');
59
- } else {
60
+ }
61
+ else {
60
62
  const envType = platform.environment.type.toLowerCase();
61
63
  if (envType === 'selectable' && (!platform.environment.selections || platform.environment.selections.length === 0)) {
62
64
  errors.push('platform.environment.selections is required for selectable environment type');
63
65
  }
64
66
  }
65
67
  }
66
-
67
68
  // Validate required string fields
68
69
  if (!platform.name) {
69
70
  errors.push('platform.name is required');
70
71
  }
71
-
72
72
  // Validate optional but important fields
73
73
  if (platform.settings && !Array.isArray(platform.settings)) {
74
74
  errors.push('platform.settings must be an array if specified');
75
75
  }
76
-
77
76
  if (platform.contactTypes && !Array.isArray(platform.contactTypes)) {
78
77
  errors.push('platform.contactTypes must be an array if specified');
79
78
  }
80
-
81
79
  if (platform.override && !Array.isArray(platform.override)) {
82
80
  errors.push('platform.override must be an array if specified');
83
81
  }
84
-
85
82
  return {
86
83
  isValid: errors.length === 0,
87
84
  errors
88
85
  };
89
86
  }
90
-
91
87
  exports.isManifestValid = isManifestValid;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ // @ts-check
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const { sign, verify } = require('jsonwebtoken');
5
+ const WIDGET_SESSION_TOKEN_TYPE = 'mcp-widget-session';
6
+ const WIDGET_SESSION_TOKEN_TTL = '15m';
7
+ function getSecret() {
8
+ const secret = process.env.APP_SERVER_SECRET_KEY;
9
+ if (!secret) {
10
+ throw new Error('APP_SERVER_SECRET_KEY is not defined');
11
+ }
12
+ return secret;
13
+ }
14
+ function createWidgetSessionToken({ rcExtensionId, openaiSessionId = null, } = {}) {
15
+ if (!rcExtensionId) {
16
+ return null;
17
+ }
18
+ return sign({
19
+ type: WIDGET_SESSION_TOKEN_TYPE,
20
+ rcExtensionId,
21
+ openaiSessionId,
22
+ }, getSecret(), { expiresIn: WIDGET_SESSION_TOKEN_TTL });
23
+ }
24
+ function verifyWidgetSessionToken(token) {
25
+ if (!token || typeof token !== 'string') {
26
+ return null;
27
+ }
28
+ try {
29
+ const payload = verify(token, getSecret());
30
+ if (!payload ||
31
+ payload.type !== WIDGET_SESSION_TOKEN_TYPE ||
32
+ typeof payload.rcExtensionId !== 'string' ||
33
+ !payload.rcExtensionId) {
34
+ return null;
35
+ }
36
+ return {
37
+ rcExtensionId: payload.rcExtensionId,
38
+ openaiSessionId: typeof payload.openaiSessionId === 'string' ? payload.openaiSessionId : null,
39
+ };
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ exports.createWidgetSessionToken = createWidgetSessionToken;
46
+ exports.verifyWidgetSessionToken = verifyWidgetSessionToken;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * MCP Server for RC Unified CRM Extension
3
+ *
4
+ * Stateless hand-rolled JSON-RPC handler — no SDK, no SSE, no sessions Map.
5
+ * Fully compatible with stateless deployments (AWS Lambda, etc.).
6
+ * All auth context is resolved per-request; rcExtensionId is cached in CacheModel.
7
+ */
8
+ export {};