@resolveio/server-lib 20.14.44 → 20.14.46

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.
@@ -89,6 +89,7 @@ var Excel = require("exceljs");
89
89
  var moment = require("moment-timezone");
90
90
  var simpl_schema_1 = require("simpl-schema");
91
91
  var cron_job_collection_1 = require("../collections/cron-job.collection");
92
+ var communication_metric_collection_1 = require("../collections/communication-metric.collection");
92
93
  var file_collection_1 = require("../collections/file.collection");
93
94
  var openai_usage_ledger_collection_1 = require("../collections/openai-usage-ledger.collection");
94
95
  var report_builder_report_collection_1 = require("../collections/report-builder-report.collection");
@@ -796,6 +797,10 @@ var OPENAI_USAGE_BILLING_ENDPOINT = 'https://backend.resolveio.com/api/openai-us
796
797
  var OPENAI_USAGE_DEFAULT_LOOKBACK_DAYS = 30;
797
798
  var OPENAI_USAGE_DEFAULT_BATCH_SIZE = 500;
798
799
  var OPENAI_USAGE_DEFAULT_OVERLAP_MINUTES = 10;
800
+ var COMMUNICATION_METRICS_ENDPOINT = 'https://backend.resolveio.com/api/communication-metrics/report';
801
+ var COMMUNICATION_METRICS_DEFAULT_LOOKBACK_DAYS = 30;
802
+ var COMMUNICATION_METRICS_DEFAULT_BATCH_SIZE = 1000;
803
+ var COMMUNICATION_METRICS_DEFAULT_OVERLAP_MINUTES = 10;
799
804
  var toNumberSetting = function (value, fallback, allowZero) {
800
805
  if (allowZero === void 0) { allowZero = false; }
801
806
  var parsed = Number(value);
@@ -889,6 +894,68 @@ var normalizeUsagePayloadEntry = function (entry) {
889
894
  id_conversation: normalizeIdentifier(entry.id_conversation)
890
895
  };
891
896
  };
897
+ var resolveCommunicationMetricsSyncConfig = function () {
898
+ var _a, _b;
899
+ var config = ((_a = resolveio_server_app_1.ResolveIOServer.getServerConfig) === null || _a === void 0 ? void 0 : _a.call(resolveio_server_app_1.ResolveIOServer)) || {};
900
+ var endpoint = normalizeString(config['COMMUNICATION_METRICS_REPORT_URL']
901
+ || config['COMMUNICATION_METRICS_BILLING_URL']
902
+ || process.env.COMMUNICATION_METRICS_REPORT_URL
903
+ || process.env.COMMUNICATION_METRICS_BILLING_URL) || COMMUNICATION_METRICS_ENDPOINT;
904
+ var apiKey = normalizeString(config['COMMUNICATION_METRICS_INGEST_KEY']
905
+ || config['COMMUNICATION_METRICS_API_KEY']
906
+ || process.env.COMMUNICATION_METRICS_INGEST_KEY
907
+ || process.env.COMMUNICATION_METRICS_API_KEY
908
+ || config['OPENAI_USAGE_INGEST_KEY']
909
+ || config['OPENAI_USAGE_API_KEY']
910
+ || process.env.OPENAI_USAGE_INGEST_KEY
911
+ || process.env.OPENAI_USAGE_API_KEY
912
+ || process.env.OPENAI_USAGE_REPORT_KEY);
913
+ var batchSize = toNumberSetting(config['COMMUNICATION_METRICS_SYNC_BATCH_SIZE'] || process.env.COMMUNICATION_METRICS_SYNC_BATCH_SIZE, COMMUNICATION_METRICS_DEFAULT_BATCH_SIZE);
914
+ var lookbackDays = toNumberSetting(config['COMMUNICATION_METRICS_SYNC_LOOKBACK_DAYS'] || process.env.COMMUNICATION_METRICS_SYNC_LOOKBACK_DAYS, COMMUNICATION_METRICS_DEFAULT_LOOKBACK_DAYS);
915
+ var overlapMinutes = toNumberSetting(config['COMMUNICATION_METRICS_SYNC_OVERLAP_MINUTES'] || process.env.COMMUNICATION_METRICS_SYNC_OVERLAP_MINUTES, COMMUNICATION_METRICS_DEFAULT_OVERLAP_MINUTES, true);
916
+ var enabledRaw = (_b = config['COMMUNICATION_METRICS_SYNC_ENABLED']) !== null && _b !== void 0 ? _b : process.env.COMMUNICATION_METRICS_SYNC_ENABLED;
917
+ var enabled = typeof enabledRaw === 'string'
918
+ ? enabledRaw.trim().toLowerCase() !== 'false' && enabledRaw.trim() !== '0'
919
+ : enabledRaw !== false;
920
+ return { config: config, endpoint: endpoint, apiKey: apiKey, batchSize: batchSize, lookbackDays: lookbackDays, overlapMinutes: overlapMinutes, enabled: enabled };
921
+ };
922
+ var buildCommunicationMetricsQuery = function (cursorAt, cursorId) {
923
+ if (!cursorId) {
924
+ return { date: { $gte: cursorAt } };
925
+ }
926
+ return {
927
+ $or: [
928
+ { date: { $gt: cursorAt } },
929
+ { date: cursorAt, _id: { $gt: cursorId } }
930
+ ]
931
+ };
932
+ };
933
+ var normalizeCommunicationMetricEntry = function (entry) {
934
+ var _a, _b;
935
+ if (!entry) {
936
+ return null;
937
+ }
938
+ var date = normalizeDate(entry.date || entry.timestamp);
939
+ var type = normalizeString(entry.type);
940
+ if (!date || !type) {
941
+ return null;
942
+ }
943
+ var value = Number((_b = (_a = entry.value) !== null && _a !== void 0 ? _a : entry.count) !== null && _b !== void 0 ? _b : 0);
944
+ if (!Number.isFinite(value) || !value) {
945
+ return null;
946
+ }
947
+ var id = normalizeIdentifier(entry._id) || normalizeIdentifier(entry.id) || '';
948
+ var unit = normalizeString(entry.unit);
949
+ var metadata = entry.metadata && typeof entry.metadata === 'object' ? entry.metadata : undefined;
950
+ return {
951
+ _id: id || undefined,
952
+ date: date,
953
+ type: type,
954
+ value: value,
955
+ unit: unit || undefined,
956
+ metadata: metadata
957
+ };
958
+ };
892
959
  function loadCronJobMethods(methodManager) {
893
960
  methodManager.methods({
894
961
  cronEmailMergedDocsCleanUp: {
@@ -1047,6 +1114,118 @@ function loadCronJobMethods(methodManager) {
1047
1114
  });
1048
1115
  }
1049
1116
  },
1117
+ cronCommunicationMetricsSync: {
1118
+ check: new simpl_schema_1.default({
1119
+ data: {
1120
+ type: Object,
1121
+ blackbox: true
1122
+ }
1123
+ }),
1124
+ function: function () {
1125
+ return __awaiter(this, void 0, void 0, function () {
1126
+ var _a, config, endpoint, apiKey, batchSize, lookbackDays, overlapMinutes, enabled, rootUrl, jobDoc, runData, lastSyncedAt, lastSyncedId, lookbackMs, cursorAt, cursorId, totalSent, cursorMoved, source, i, query, entries, payloadEntries, lastEntry;
1127
+ var _b;
1128
+ return __generator(this, function (_c) {
1129
+ switch (_c.label) {
1130
+ case 0:
1131
+ _a = resolveCommunicationMetricsSyncConfig(), config = _a.config, endpoint = _a.endpoint, apiKey = _a.apiKey, batchSize = _a.batchSize, lookbackDays = _a.lookbackDays, overlapMinutes = _a.overlapMinutes, enabled = _a.enabled;
1132
+ if (!enabled) {
1133
+ return [2 /*return*/, true];
1134
+ }
1135
+ rootUrl = normalizeString(config['ROOT_URL']);
1136
+ if (rootUrl === 'https://resolveio.com' || rootUrl === 'http://localhost:4200') {
1137
+ return [2 /*return*/, true];
1138
+ }
1139
+ if (!endpoint || !apiKey) {
1140
+ console.warn('[Communication Metrics Sync] Missing endpoint or API key.');
1141
+ return [2 /*return*/, false];
1142
+ }
1143
+ return [4 /*yield*/, cron_job_collection_1.CronJobs.findOne({ name: 'Communication Metrics Sync' })];
1144
+ case 1:
1145
+ jobDoc = _c.sent();
1146
+ runData = jobDoc === null || jobDoc === void 0 ? void 0 : jobDoc.method_run_data;
1147
+ lastSyncedAt = normalizeDate(runData === null || runData === void 0 ? void 0 : runData.last_synced_at);
1148
+ lastSyncedId = normalizeString(runData === null || runData === void 0 ? void 0 : runData.last_synced_id);
1149
+ lookbackMs = lookbackDays * 24 * 60 * 60 * 1000;
1150
+ cursorAt = lastSyncedAt || new Date(Date.now() - lookbackMs);
1151
+ if (lastSyncedAt && overlapMinutes > 0) {
1152
+ cursorAt = new Date(cursorAt.getTime() - overlapMinutes * 60 * 1000);
1153
+ }
1154
+ cursorId = lastSyncedId;
1155
+ totalSent = 0;
1156
+ cursorMoved = false;
1157
+ source = {
1158
+ clientSlug: (_b = resolveio_server_app_1.ResolveIOServer.getClientName) === null || _b === void 0 ? void 0 : _b.call(resolveio_server_app_1.ResolveIOServer),
1159
+ clientName: normalizeString(config['CLIENT_NAME']),
1160
+ rootUrl: rootUrl,
1161
+ reportedAt: new Date(),
1162
+ appVersion: process.env.APP_VERSION
1163
+ };
1164
+ i = 0;
1165
+ _c.label = 2;
1166
+ case 2:
1167
+ if (!(i < 1000)) return [3 /*break*/, 7];
1168
+ query = buildCommunicationMetricsQuery(cursorAt, cursorId);
1169
+ return [4 /*yield*/, communication_metric_collection_1.CommunicationMetrics.find(query, {
1170
+ sort: { date: 1, _id: 1 },
1171
+ limit: batchSize
1172
+ })];
1173
+ case 3:
1174
+ entries = _c.sent();
1175
+ if (!entries.length) {
1176
+ return [3 /*break*/, 7];
1177
+ }
1178
+ payloadEntries = entries
1179
+ .map(function (entry) { return normalizeCommunicationMetricEntry(entry); })
1180
+ .filter(Boolean);
1181
+ if (!payloadEntries.length) return [3 /*break*/, 5];
1182
+ return [4 /*yield*/, axios_1.default.post(endpoint, { entries: payloadEntries, source: source }, {
1183
+ headers: {
1184
+ 'Content-Type': 'application/json',
1185
+ 'X-ResolveIO-Communication-Metrics-Key': apiKey,
1186
+ 'X-ResolveIO-OpenAI-Usage-Key': apiKey,
1187
+ 'X-OpenAI-Usage-Key': apiKey,
1188
+ 'X-API-Key': apiKey
1189
+ },
1190
+ timeout: 20000
1191
+ })];
1192
+ case 4:
1193
+ _c.sent();
1194
+ totalSent += payloadEntries.length;
1195
+ _c.label = 5;
1196
+ case 5:
1197
+ lastEntry = entries[entries.length - 1];
1198
+ if (lastEntry) {
1199
+ cursorAt = normalizeDate(lastEntry.date) || cursorAt;
1200
+ cursorId = normalizeString(lastEntry._id) || cursorId;
1201
+ cursorMoved = true;
1202
+ }
1203
+ if (entries.length < batchSize) {
1204
+ return [3 /*break*/, 7];
1205
+ }
1206
+ _c.label = 6;
1207
+ case 6:
1208
+ i++;
1209
+ return [3 /*break*/, 2];
1210
+ case 7:
1211
+ if (!cursorMoved) return [3 /*break*/, 9];
1212
+ return [4 /*yield*/, cron_job_collection_1.CronJobs.updateOne({ name: 'Communication Metrics Sync' }, {
1213
+ $set: {
1214
+ 'method_run_data.last_synced_at': cursorAt,
1215
+ 'method_run_data.last_synced_id': cursorId,
1216
+ 'method_run_data.last_sent_at': new Date(),
1217
+ 'method_run_data.last_sent_count': totalSent
1218
+ }
1219
+ })];
1220
+ case 8:
1221
+ _c.sent();
1222
+ _c.label = 9;
1223
+ case 9: return [2 /*return*/, true];
1224
+ }
1225
+ });
1226
+ });
1227
+ }
1228
+ },
1050
1229
  reportbuilderCronJob: {
1051
1230
  check: new simpl_schema_1.default({
1052
1231
  data: {