@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.
- package/README.md +17 -16
- package/dist/connector/developerPortal.d.ts +6 -0
- package/{connector → dist/connector}/developerPortal.js +29 -12
- package/dist/connector/mock.d.ts +1 -0
- package/{connector → dist/connector}/mock.js +33 -17
- package/dist/connector/proxy/engine.d.ts +10 -0
- package/dist/connector/proxy/engine.js +222 -0
- package/dist/connector/proxy/index.d.ts +5 -0
- package/dist/connector/proxy/index.js +511 -0
- package/dist/connector/registry.d.ts +1 -0
- package/dist/connector/registry.js +243 -0
- package/dist/handlers/admin.d.ts +1 -0
- package/{handlers → dist/handlers}/admin.js +137 -78
- package/dist/handlers/appointment.d.ts +9 -0
- package/{handlers → dist/handlers}/appointment.js +58 -29
- package/dist/handlers/auth.d.ts +9 -0
- package/{handlers → dist/handlers}/auth.js +68 -40
- package/dist/handlers/calldown.d.ts +10 -0
- package/dist/handlers/calldown.js +134 -0
- package/dist/handlers/contact.d.ts +1 -0
- package/{handlers → dist/handlers}/contact.js +61 -39
- package/dist/handlers/disposition.d.ts +1 -0
- package/{handlers → dist/handlers}/disposition.js +20 -10
- package/dist/handlers/log.d.ts +1 -0
- package/{handlers → dist/handlers}/log.js +91 -124
- package/dist/handlers/managedAuth.d.ts +1 -0
- package/{handlers → dist/handlers}/managedAuth.js +134 -61
- package/dist/handlers/managedOAuth.d.ts +13 -0
- package/{handlers → dist/handlers}/managedOAuth.js +102 -30
- package/dist/handlers/plugin.d.ts +1 -0
- package/{handlers → dist/handlers}/plugin.js +59 -27
- package/dist/handlers/user.d.ts +1 -0
- package/{handlers → dist/handlers}/user.js +45 -27
- package/dist/index.d.ts +1 -0
- package/{index.js → dist/index.js} +538 -449
- package/dist/jest.config.d.ts +1 -0
- package/dist/jest.config.js +65 -0
- package/dist/lib/analytics.d.ts +4 -0
- package/{lib → dist/lib}/analytics.js +8 -6
- package/dist/lib/authSession.d.ts +5 -0
- package/{lib → dist/lib}/authSession.js +15 -43
- package/dist/lib/cacheCleanup.d.ts +4 -0
- package/{lib → dist/lib}/cacheCleanup.js +5 -17
- package/dist/lib/callLogComposer.d.ts +109 -0
- package/{lib → dist/lib}/callLogComposer.js +157 -197
- package/dist/lib/callLogLookup.d.ts +6 -0
- package/{lib → dist/lib}/callLogLookup.js +12 -34
- package/dist/lib/constants.d.ts +6 -0
- package/dist/lib/constants.js +9 -0
- package/dist/lib/debugTracer.d.ts +17 -0
- package/{lib → dist/lib}/debugTracer.js +7 -83
- package/dist/lib/encode.d.ts +3 -0
- package/dist/lib/encode.js +50 -0
- package/dist/lib/errorHandler.d.ts +7 -0
- package/dist/lib/errorHandler.js +161 -0
- package/dist/lib/generalErrorMessage.d.ts +7 -0
- package/{lib → dist/lib}/generalErrorMessage.js +6 -6
- package/dist/lib/jwt.d.ts +4 -0
- package/dist/lib/jwt.js +18 -0
- package/dist/lib/logger.d.ts +24 -0
- package/dist/lib/logger.js +126 -0
- package/dist/lib/migrateCallLogsSchema.d.ts +32 -0
- package/{lib → dist/lib}/migrateCallLogsSchema.js +75 -160
- package/dist/lib/oauth.d.ts +4 -0
- package/{lib → dist/lib}/oauth.js +157 -160
- package/dist/lib/ringcentral.d.ts +24 -0
- package/dist/lib/ringcentral.js +226 -0
- package/dist/lib/s3ErrorLogReport.d.ts +4 -0
- package/{lib → dist/lib}/s3ErrorLogReport.js +11 -23
- package/dist/lib/sharedSMSComposer.d.ts +7 -0
- package/{lib → dist/lib}/sharedSMSComposer.js +21 -107
- package/dist/lib/util.d.ts +7 -0
- package/{lib → dist/lib}/util.js +9 -20
- package/dist/mcp/lib/oauthError.d.ts +1 -0
- package/dist/mcp/lib/oauthError.js +25 -0
- package/dist/mcp/lib/validator.d.ts +1 -0
- package/{mcp → dist/mcp}/lib/validator.js +16 -20
- package/dist/mcp/lib/widgetSessionToken.d.ts +1 -0
- package/dist/mcp/lib/widgetSessionToken.js +46 -0
- package/dist/mcp/mcpHandler.d.ts +8 -0
- package/{mcp → dist/mcp}/mcpHandler.js +98 -88
- package/dist/mcp/tools/cancelAppointment.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/cancelAppointment.js +7 -16
- package/dist/mcp/tools/checkAuthStatus.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/checkAuthStatus.js +21 -14
- package/dist/mcp/tools/confirmAppointment.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/confirmAppointment.js +7 -16
- package/dist/mcp/tools/createAppointment.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/createAppointment.js +7 -19
- package/dist/mcp/tools/createCallLog.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/createCallLog.js +18 -29
- package/dist/mcp/tools/createContact.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/createContact.js +8 -20
- package/dist/mcp/tools/createMessageLog.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/createMessageLog.js +14 -26
- package/dist/mcp/tools/doAuth.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/doAuth.js +17 -13
- package/dist/mcp/tools/findContactByName.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/findContactByName.js +9 -15
- package/dist/mcp/tools/findContactByPhone.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/findContactByPhone.js +8 -15
- package/dist/mcp/tools/getCallLog.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/getCallLog.js +12 -21
- package/dist/mcp/tools/getGoogleFilePicker.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/getGoogleFilePicker.js +9 -18
- package/dist/mcp/tools/getHelp.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/getHelp.js +5 -6
- package/dist/mcp/tools/getPublicConnectors.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/getPublicConnectors.js +19 -18
- package/dist/mcp/tools/getSessionInfo.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/getSessionInfo.js +10 -16
- package/dist/mcp/tools/index.d.ts +8 -0
- package/dist/mcp/tools/index.js +50 -0
- package/dist/mcp/tools/listAppointments.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/listAppointments.js +7 -19
- package/dist/mcp/tools/logout.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/logout.js +16 -14
- package/dist/mcp/tools/rcGetCallLogs.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/rcGetCallLogs.js +10 -8
- package/dist/mcp/tools/updateAppointment.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/updateAppointment.js +17 -22
- package/dist/mcp/tools/updateCallLog.d.ts +1 -0
- package/{mcp → dist/mcp}/tools/updateCallLog.js +16 -26
- package/dist/models/accountDataModel.d.ts +3 -0
- package/dist/models/accountDataModel.js +39 -0
- package/dist/models/adminConfigModel.d.ts +2 -0
- package/dist/models/adminConfigModel.js +39 -0
- package/dist/models/cacheModel.d.ts +2 -0
- package/{models → dist/models}/cacheModel.js +7 -3
- package/dist/models/callDownListModel.d.ts +2 -0
- package/{models → dist/models}/callDownListModel.js +8 -4
- package/dist/models/callLogModel.d.ts +2 -0
- package/dist/models/callLogModel.js +43 -0
- package/dist/models/dynamo/connectorSchema.d.ts +2 -0
- package/dist/models/dynamo/connectorSchema.js +141 -0
- package/dist/models/dynamo/lockSchema.d.ts +2 -0
- package/{models → dist/models}/dynamo/lockSchema.js +5 -7
- package/dist/models/dynamo/noteCacheSchema.d.ts +2 -0
- package/{models → dist/models}/dynamo/noteCacheSchema.js +4 -6
- package/dist/models/llmSessionModel.d.ts +2 -0
- package/dist/models/llmSessionModel.js +21 -0
- package/dist/models/messageLogModel.d.ts +2 -0
- package/{models → dist/models}/messageLogModel.js +8 -4
- package/dist/models/sequelize.d.ts +2 -0
- package/dist/models/sequelize.js +68 -0
- package/dist/models/userModel.d.ts +2 -0
- package/dist/models/userModel.js +49 -0
- package/dist/package.json +100 -0
- package/dist/releaseNotes.json +1222 -0
- package/dist/tsconfig.json +14 -0
- package/dist/types/admin.d.ts +141 -0
- package/dist/types/analytics.d.ts +14 -0
- package/dist/types/appointment.d.ts +50 -0
- package/dist/types/auth.d.ts +137 -0
- package/dist/types/authSession.d.ts +35 -0
- package/dist/types/cacheCleanup.d.ts +12 -0
- package/dist/types/calldown.d.ts +54 -0
- package/dist/types/common.d.ts +46 -0
- package/dist/types/connector.d.ts +165 -0
- package/dist/types/contact.d.ts +125 -0
- package/dist/types/errorHandler.d.ts +60 -0
- package/dist/types/index.d.ts +76 -0
- package/dist/types/json.d.ts +9 -0
- package/dist/types/jwt.d.ts +8 -0
- package/dist/types/logging.d.ts +224 -0
- package/dist/types/managedAuth.d.ts +114 -0
- package/dist/types/managedOAuth.d.ts +59 -0
- package/dist/types/manifest.d.ts +120 -0
- package/dist/types/migration.d.ts +15 -0
- package/dist/types/plugin.d.ts +74 -0
- package/dist/types/ringcentral.d.ts +61 -0
- package/dist/types/s3ErrorLogReport.d.ts +16 -0
- package/dist/types/sharedSMSComposer.d.ts +105 -0
- package/dist/types/user.d.ts +46 -0
- package/dist/types/util.d.ts +7 -0
- package/package.json +34 -6
- package/releaseNotes.json +8 -0
- package/.env.test +0 -5
- package/connector/proxy/engine.js +0 -165
- package/connector/proxy/index.js +0 -500
- package/connector/registry.js +0 -252
- package/docs/README.md +0 -50
- package/docs/architecture.md +0 -94
- package/docs/connectors.md +0 -116
- package/docs/handlers.md +0 -128
- package/docs/libraries.md +0 -98
- package/docs/models.md +0 -146
- package/docs/routes.md +0 -119
- package/docs/tests.md +0 -73
- package/handlers/calldown.js +0 -99
- package/jest.config.js +0 -57
- package/lib/constants.js +0 -9
- package/lib/encode.js +0 -30
- package/lib/errorHandler.js +0 -218
- package/lib/jwt.js +0 -18
- package/lib/logger.js +0 -190
- package/lib/ringcentral.js +0 -267
- package/mcp/README.md +0 -420
- package/mcp/tools/index.js +0 -51
- package/mcp/ui/App/App.tsx +0 -358
- package/mcp/ui/App/components/AuthInfoForm.tsx +0 -113
- package/mcp/ui/App/components/AuthSuccess.tsx +0 -22
- package/mcp/ui/App/components/ConnectorList.tsx +0 -82
- package/mcp/ui/App/components/DebugPanel.tsx +0 -43
- package/mcp/ui/App/components/OAuthConnect.tsx +0 -270
- package/mcp/ui/App/lib/callTool.ts +0 -130
- package/mcp/ui/App/lib/debugLog.ts +0 -41
- package/mcp/ui/App/lib/developerPortal.ts +0 -111
- package/mcp/ui/App/main.css +0 -6
- package/mcp/ui/App/root.tsx +0 -13
- package/mcp/ui/dist/index.html +0 -53
- package/mcp/ui/vite.config.ts +0 -16
- package/models/accountDataModel.js +0 -34
- package/models/adminConfigModel.js +0 -35
- package/models/callLogModel.js +0 -39
- package/models/dynamo/connectorSchema.js +0 -146
- package/models/llmSessionModel.js +0 -17
- package/models/sequelize.js +0 -17
- package/models/userModel.js +0 -45
- package/test/connector/developerPortal.test.js +0 -166
- package/test/connector/mock.test.js +0 -131
- package/test/connector/proxy/engine.test.js +0 -211
- package/test/connector/proxy/index.test.js +0 -525
- package/test/connector/proxy/sample.json +0 -162
- package/test/connector/registry.test.js +0 -416
- package/test/handlers/admin.test.js +0 -960
- package/test/handlers/appointment.test.js +0 -260
- package/test/handlers/auth.test.js +0 -1096
- package/test/handlers/calldown.test.js +0 -310
- package/test/handlers/contact.test.js +0 -1014
- package/test/handlers/disposition.test.js +0 -396
- package/test/handlers/log.test.js +0 -1847
- package/test/handlers/managedAuth.test.js +0 -458
- package/test/handlers/managedOAuth.test.js +0 -262
- package/test/handlers/plugin.test.js +0 -429
- package/test/handlers/user.test.js +0 -381
- package/test/index.test.js +0 -301
- package/test/lib/analytics.test.js +0 -146
- package/test/lib/authSession.test.js +0 -173
- package/test/lib/cacheCleanup.test.js +0 -127
- package/test/lib/callLogComposer.test.js +0 -1231
- package/test/lib/debugTracer.test.js +0 -328
- package/test/lib/encode.test.js +0 -59
- package/test/lib/errorHandler.test.js +0 -246
- package/test/lib/generalErrorMessage.test.js +0 -82
- package/test/lib/jwt.test.js +0 -176
- package/test/lib/logger.test.js +0 -206
- package/test/lib/oauth.test.js +0 -359
- package/test/lib/ringcentral.test.js +0 -467
- package/test/lib/s3ErrorLogReport.test.js +0 -187
- package/test/lib/sharedSMSComposer.test.js +0 -1084
- package/test/lib/util.test.js +0 -329
- package/test/mcp/mcpHandler.test.js +0 -73
- package/test/mcp/mcpHandlerMore.test.js +0 -384
- package/test/mcp/tools/appointmentTools.test.js +0 -362
- package/test/mcp/tools/checkAuthStatus.test.js +0 -83
- package/test/mcp/tools/createCallLog.test.js +0 -436
- package/test/mcp/tools/createContact.test.js +0 -58
- package/test/mcp/tools/createMessageLog.test.js +0 -595
- package/test/mcp/tools/doAuth.test.js +0 -113
- package/test/mcp/tools/findContactByName.test.js +0 -275
- package/test/mcp/tools/findContactByPhone.test.js +0 -296
- package/test/mcp/tools/getCallLog.test.js +0 -298
- package/test/mcp/tools/getGoogleFilePicker.test.js +0 -281
- package/test/mcp/tools/getPublicConnectors.test.js +0 -107
- package/test/mcp/tools/getSessionInfo.test.js +0 -127
- package/test/mcp/tools/logout.test.js +0 -233
- package/test/mcp/tools/rcGetCallLogs.test.js +0 -56
- package/test/mcp/tools/updateCallLog.test.js +0 -360
- package/test/models/accountDataModel.test.js +0 -98
- package/test/models/callDownListModel.test.js +0 -125
- package/test/models/dynamo/connectorSchema.test.js +0 -189
- package/test/models/dynamo/lockSchema.test.js +0 -37
- package/test/models/dynamo/noteCacheSchema.test.js +0 -45
- package/test/models/llmSessionModel.test.js +0 -91
- package/test/models/models.test.js +0 -660
- package/test/routes/calldownRoutes.test.js +0 -224
- package/test/routes/coreRouterBroadRoutes.test.js +0 -855
- package/test/routes/dispositionRoutes.test.js +0 -192
- package/test/routes/managedAuthRoutes.test.js +0 -386
- package/test/routes/pluginRoutes.test.js +0 -262
- package/test/setup.js +0 -178
- /package/{mcp → dist/mcp}/ui/index.html +0 -0
- /package/{mcp → dist/mcp}/ui/package-lock.json +0 -0
- /package/{mcp → dist/mcp}/ui/package.json +0 -0
- /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)
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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)
|
|
377
|
+
if (!text)
|
|
378
|
+
return '';
|
|
456
379
|
return text
|
|
457
380
|
.replace(/&/g, '&')
|
|
458
381
|
.replace(/</g, '<')
|
|
@@ -460,12 +383,3 @@ function escapeHtml(text) {
|
|
|
460
383
|
.replace(/"/g, '"')
|
|
461
384
|
.replace(/'/g, ''');
|
|
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 };
|
package/{lib → dist/lib}/util.js
RENAMED
|
@@ -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
|
-
|
|
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 {
|
|
4
|
-
* @
|
|
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
|
-
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
32
31
|
if (!platform.auth.type) {
|
|
33
32
|
errors.push('platform.auth.type is required');
|
|
34
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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 {};
|