@resolveio/server-lib 22.2.5 → 22.2.7

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.
@@ -0,0 +1,2934 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
24
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ var __read = (this && this.__read) || function (o, n) {
50
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
51
+ if (!m) return o;
52
+ var i = m.call(o), r, ar = [], e;
53
+ try {
54
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
55
+ }
56
+ catch (error) { e = { error: error }; }
57
+ finally {
58
+ try {
59
+ if (r && !r.done && (m = i["return"])) m.call(i);
60
+ }
61
+ finally { if (e) throw e.error; }
62
+ }
63
+ return ar;
64
+ };
65
+ var __values = (this && this.__values) || function(o) {
66
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
67
+ if (m) return m.call(o);
68
+ if (o && typeof o.length === "number") return {
69
+ next: function () {
70
+ if (o && i >= o.length) o = void 0;
71
+ return { value: o && o[i++], done: !o };
72
+ }
73
+ };
74
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
75
+ };
76
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
77
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
78
+ if (ar || !(i in from)) {
79
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
80
+ ar[i] = from[i];
81
+ }
82
+ }
83
+ return to.concat(ar || Array.prototype.slice.call(from));
84
+ };
85
+ Object.defineProperty(exports, "__esModule", { value: true });
86
+ exports.ErrorAutoFixManager = void 0;
87
+ exports.registerErrorAutoFixManagerDependencies = registerErrorAutoFixManagerDependencies;
88
+ exports.ensureErrorAutoFixManager = ensureErrorAutoFixManager;
89
+ exports.reportDevError = reportDevError;
90
+ var resolveio_server_app_1 = require("../resolveio-server-app");
91
+ var common_1 = require("../util/common");
92
+ var axios_1 = require("axios");
93
+ var crypto_1 = require("crypto");
94
+ var url_1 = require("url");
95
+ var user_collection_1 = require("../collections/user.collection");
96
+ var customer_notification_content_manager_1 = require("./customer-notification-content.manager");
97
+ var OPTIONAL_COLLECTION = {
98
+ findOne: function () { return Promise.resolve(null); },
99
+ findById: function () { return Promise.resolve(null); },
100
+ find: function () { return Promise.resolve([]); }
101
+ };
102
+ var AICoderApps = OPTIONAL_COLLECTION;
103
+ var AIDashboardJobs = OPTIONAL_COLLECTION;
104
+ var Clients = OPTIONAL_COLLECTION;
105
+ var ErrorAutoFixLogs = null;
106
+ var configuredErrorAutoFixDependencies = null;
107
+ function resolveErrorAutoFixManagerDependencies(overrides) {
108
+ var resolved = __assign(__assign({}, (configuredErrorAutoFixDependencies || {})), (overrides || {}));
109
+ if (!resolved.ErrorAutoFixLogs) {
110
+ throw new Error('ErrorAutoFixManager dependencies are not configured.');
111
+ }
112
+ return resolved;
113
+ }
114
+ function applyErrorAutoFixDependencies(dependencies) {
115
+ configuredErrorAutoFixDependencies = dependencies;
116
+ Clients = dependencies.Clients || OPTIONAL_COLLECTION;
117
+ ErrorAutoFixLogs = dependencies.ErrorAutoFixLogs;
118
+ AICoderApps = dependencies.AICoderApps || OPTIONAL_COLLECTION;
119
+ AIDashboardJobs = dependencies.AIDashboardJobs || OPTIONAL_COLLECTION;
120
+ }
121
+ function registerErrorAutoFixManagerDependencies(dependencies) {
122
+ applyErrorAutoFixDependencies(dependencies);
123
+ ensureErrorAutoFixManager();
124
+ }
125
+ var INFRA_SUBJECT_KEYWORDS = [
126
+ 'failed snapshot',
127
+ 'replica set',
128
+ 'data size used',
129
+ 'oplog',
130
+ 'lock during backup',
131
+ 'backup',
132
+ 'no primary',
133
+ 'no secondary',
134
+ 'preferred primary',
135
+ 'exceeding memory',
136
+ 'exceeding storage',
137
+ 'unhealthy status',
138
+ 'disconnected status',
139
+ 'replication lag',
140
+ 'database storage size',
141
+ 'compacting collections',
142
+ 'failed connection',
143
+ 'heartbeat',
144
+ 'high cpu usage',
145
+ 'high ram usage'
146
+ ];
147
+ var DEFAULT_ERROR_ALERT_EMAIL = 'dev@resolveio.com';
148
+ var MAX_LOCAL_NOTIFICATION_USERS = 5000;
149
+ var LIBRARY_MARKER_PATTERNS = [
150
+ { label: 'node_modules stack', pattern: /(?:^|[\/\\])node_modules(?:[\/\\]|$)/i },
151
+ { label: '@resolveio/client-lib', pattern: /@resolveio\/client-lib(?:-[a-z0-9-]+)?/i },
152
+ { label: '@resolveio/server-lib', pattern: /@resolveio\/server-lib/i },
153
+ { label: 'resolveio-client-lib path', pattern: /(?:^|[\/\\])resolveio-client-lib(?:[\/\\]|$)/i },
154
+ { label: 'resolveio-server-lib path', pattern: /(?:^|[\/\\])resolveio-server-lib(?:[\/\\]|$)/i },
155
+ { label: 'base template path', pattern: /(?:^|[\/\\])aicoder[\/\\]templates[\/\\]base_(?:small|medium|large|tool)(?:[\/\\]|$)/i }
156
+ ];
157
+ var APP_OWNED_PATH_PATTERN = /(?:^|[\/\\])(angular[\/\\]app|server[\/\\]src)(?:[\/\\]|$)/i;
158
+ var FILE_PATH_PATTERN = /(?:webpack:\/\/\/?|\/|\.\/|[A-Za-z]:\\)[^\s'"`]+?\.(?:ts|tsx|js|jsx|mjs|cjs|html|scss|css)/g;
159
+ var ErrorAutoFixManager = /** @class */ (function () {
160
+ function ErrorAutoFixManager(serverConfig, dependencies) {
161
+ this._serverConfig = null;
162
+ this.githubApiBase = 'https://api.github.com';
163
+ this.dashboardMonitors = new Map();
164
+ this.ready = false;
165
+ var resolvedDependencies = resolveErrorAutoFixManagerDependencies(dependencies);
166
+ applyErrorAutoFixDependencies(resolvedDependencies);
167
+ this._serverConfig = serverConfig || {};
168
+ this.config = this.resolveConfig();
169
+ if (!resolvedDependencies.AICoderApps || !resolvedDependencies.AIDashboardJobs) {
170
+ this.config.dashboardWorkflowEnabled = false;
171
+ }
172
+ if (!this.config.enabled) {
173
+ return;
174
+ }
175
+ if (!this.config.dashboardWorkflowEnabled && (!this.config.repoRoot || !this.config.githubOwner || !this.config.githubRepo)) {
176
+ console.warn('ErrorAutoFixManager disabled - missing critical configuration.');
177
+ return;
178
+ }
179
+ this.ready = true;
180
+ // console.log('ErrorAutoFixManager initialized (HTTP intake mode).');
181
+ // console.log('ErrorAutoFixManager config source:', this.config.configSource);
182
+ // if (this.config.debugLogging) {
183
+ // console.log('ErrorAutoFixManager debug logging enabled.');
184
+ // }
185
+ // if (!this.config.autoRunEnabled) {
186
+ // console.log('ErrorAutoFixManager auto-run disabled. Manual OpenAI runs required.');
187
+ // }
188
+ }
189
+ ErrorAutoFixManager.prototype.isReady = function () {
190
+ var _a;
191
+ return !!(this.ready && ((_a = this.config) === null || _a === void 0 ? void 0 : _a.enabled));
192
+ };
193
+ ErrorAutoFixManager.prototype.validateIngestKey = function (candidate) {
194
+ var _a;
195
+ var keys = Array.isArray((_a = this.config) === null || _a === void 0 ? void 0 : _a.ingestKeys) ? this.config.ingestKeys.filter(Boolean) : [];
196
+ if (!keys.length) {
197
+ return true;
198
+ }
199
+ if (!candidate) {
200
+ return false;
201
+ }
202
+ return keys.includes(candidate.trim());
203
+ };
204
+ ErrorAutoFixManager.prototype.debugLog = function (message, details) {
205
+ var _a;
206
+ if (!((_a = this.config) === null || _a === void 0 ? void 0 : _a.debugLogging)) {
207
+ return;
208
+ }
209
+ return;
210
+ if (typeof details === 'undefined') {
211
+ console.log("[ErrorAutoFixManager][debug] ".concat(message));
212
+ }
213
+ else {
214
+ console.log("[ErrorAutoFixManager][debug] ".concat(message), details);
215
+ }
216
+ };
217
+ ErrorAutoFixManager.prototype.resolveConfig = function () {
218
+ var scAutofix = (this._serverConfig && (this._serverConfig.autofix || this._serverConfig.AUTOFIX)) || {};
219
+ var notifyEmails = [];
220
+ var escalationEmails = [];
221
+ if (process.env.AUTOFIX_NOTIFY_EMAILS) {
222
+ notifyEmails = process.env.AUTOFIX_NOTIFY_EMAILS.split(',').map(function (a) { return a.trim(); }).filter(Boolean);
223
+ }
224
+ else if (Array.isArray(scAutofix.notifyEmails)) {
225
+ notifyEmails = scAutofix.notifyEmails.map(function (a) { return (a || '').trim(); }).filter(Boolean);
226
+ }
227
+ else if (typeof scAutofix.notifyEmails === 'string') {
228
+ notifyEmails = scAutofix.notifyEmails.split(',').map(function (a) { return a.trim(); }).filter(Boolean);
229
+ }
230
+ if (process.env.AUTOFIX_ESCALATION_EMAILS) {
231
+ escalationEmails = process.env.AUTOFIX_ESCALATION_EMAILS.split(',').map(function (a) { return a.trim(); }).filter(Boolean);
232
+ }
233
+ else if (Array.isArray(scAutofix.escalationEmails)) {
234
+ escalationEmails = scAutofix.escalationEmails.map(function (a) { return (a || '').trim(); }).filter(Boolean);
235
+ }
236
+ else if (typeof scAutofix.escalationEmails === 'string') {
237
+ escalationEmails = scAutofix.escalationEmails.split(',').map(function (a) { return a.trim(); }).filter(Boolean);
238
+ }
239
+ var getString = function (envKey, scKey, fallback) {
240
+ if (fallback === void 0) { fallback = ''; }
241
+ return process.env[envKey] || scAutofix[scKey] || fallback;
242
+ };
243
+ var getNumber = function (envKey, scKey, fallback) {
244
+ var envVal = Number(process.env[envKey]);
245
+ if (!Number.isNaN(envVal) && process.env[envKey] !== undefined) {
246
+ return envVal;
247
+ }
248
+ var scVal = Number(scAutofix[scKey]);
249
+ if (!Number.isNaN(scVal) && scAutofix[scKey] !== undefined) {
250
+ return scVal;
251
+ }
252
+ return fallback;
253
+ };
254
+ var getBoolean = function (envKey, scKey, fallback) {
255
+ if (fallback === void 0) { fallback = false; }
256
+ if (typeof process.env[envKey] !== 'undefined') {
257
+ return process.env[envKey] === 'true';
258
+ }
259
+ if (typeof scAutofix[scKey] !== 'undefined') {
260
+ return !!scAutofix[scKey];
261
+ }
262
+ return fallback;
263
+ };
264
+ var parseKeyList = function (value) {
265
+ if (Array.isArray(value)) {
266
+ return value.map(function (val) { return "".concat(val || '').trim(); }).filter(Boolean);
267
+ }
268
+ if (typeof value === 'string') {
269
+ return value.split(',').map(function (val) { return val.trim(); }).filter(Boolean);
270
+ }
271
+ return [];
272
+ };
273
+ var normalizePositiveInt = function (value, fallback) {
274
+ if (!Number.isFinite(value) || value <= 0) {
275
+ return fallback;
276
+ }
277
+ return Math.floor(value);
278
+ };
279
+ var openaiProjectId = getString('OPENAI_PROJECT_ID', 'openaiProjectId');
280
+ var openaiEnvironment = getString('OPENAI_ENVIRONMENT', 'openaiEnvironment', openaiProjectId);
281
+ var ingestSource = typeof process.env.AUTOFIX_INGEST_KEYS !== 'undefined'
282
+ ? process.env.AUTOFIX_INGEST_KEYS
283
+ : scAutofix.ingestKeys;
284
+ return {
285
+ enabled: getBoolean('AUTOFIX_ENABLED', 'enabled', false),
286
+ repoRoot: getString('AUTOFIX_REPO_ROOT', 'repoRoot', ''),
287
+ baseBranch: getString('AUTOFIX_BASE_BRANCH', 'baseBranch', 'main'),
288
+ branchPrefix: getString('AUTOFIX_BRANCH_PREFIX', 'branchPrefix', 'openai/auto'),
289
+ githubToken: getString('GITHUB_TOKEN', 'githubToken', getString('AUTOFIX_GITHUB_TOKEN', 'githubToken')),
290
+ githubOwner: getString('AUTOFIX_GITHUB_OWNER', 'githubOwner', 'resolveio'),
291
+ githubRepo: getString('AUTOFIX_GITHUB_REPO', 'githubRepo', 'resolveio-all'),
292
+ commandTimeoutMs: getNumber('AUTOFIX_COMMAND_TIMEOUT_MS', 'commandTimeoutMs', 600000),
293
+ notifyEmails: notifyEmails,
294
+ debugLogging: getBoolean('AUTOFIX_DEBUG_LOGS', 'debugLogging', false),
295
+ configSource: process.env.AUTOFIX_ENABLED ? 'environment' : (Object.keys(scAutofix).length ? 'serverConfig' : 'defaults'),
296
+ openaiEnvironment: openaiEnvironment,
297
+ openaiProjectId: openaiProjectId,
298
+ autoRunEnabled: getBoolean('AUTOFIX_AUTORUN_ENABLED', 'autoRunEnabled', false),
299
+ ingestKeys: parseKeyList(ingestSource),
300
+ dashboardWorkflowEnabled: getBoolean('AUTOFIX_DASHBOARD_WORKFLOW_ENABLED', 'dashboardWorkflowEnabled', true),
301
+ dashboardFallbackToGithub: getBoolean('AUTOFIX_DASHBOARD_FALLBACK_TO_GITHUB', 'dashboardFallbackToGithub', true),
302
+ dashboardWaitTimeoutMs: getNumber('AUTOFIX_DASHBOARD_WAIT_TIMEOUT_MS', 'dashboardWaitTimeoutMs', 45 * 60 * 1000),
303
+ dashboardPublishRequired: getBoolean('AUTOFIX_DASHBOARD_PUBLISH_REQUIRED', 'dashboardPublishRequired', true),
304
+ maxAutoRunAttemptsPerIssue: normalizePositiveInt(getNumber('AUTOFIX_MAX_AUTORUN_ATTEMPTS_PER_ISSUE', 'maxAutoRunAttemptsPerIssue', 3), 3),
305
+ escalationEmails: escalationEmails
306
+ };
307
+ };
308
+ ErrorAutoFixManager.prototype.extractEmailAddress = function (value) {
309
+ if (!value) {
310
+ return '';
311
+ }
312
+ var email = value;
313
+ var angleMatch = value.match(/<([^>]+)>/);
314
+ if (angleMatch && angleMatch[1]) {
315
+ email = angleMatch[1];
316
+ }
317
+ email = email.split(';')[0].split(',')[0];
318
+ return email.trim().toLowerCase();
319
+ };
320
+ ErrorAutoFixManager.prototype.escapeRegex = function (value) {
321
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
322
+ };
323
+ ErrorAutoFixManager.prototype.resolveClientForEnvironment = function (environment) {
324
+ return __awaiter(this, void 0, void 0, function () {
325
+ var host, escaped, query, err_1;
326
+ return __generator(this, function (_a) {
327
+ switch (_a.label) {
328
+ case 0:
329
+ host = this.extractHostFromUrl(environment);
330
+ if (!host) {
331
+ return [2 /*return*/, null];
332
+ }
333
+ _a.label = 1;
334
+ case 1:
335
+ _a.trys.push([1, 3, , 4]);
336
+ escaped = this.escapeRegex(host);
337
+ query = {
338
+ website: {
339
+ $regex: escaped,
340
+ $options: 'i'
341
+ }
342
+ };
343
+ return [4 /*yield*/, Clients.findOne(query)];
344
+ case 2: return [2 /*return*/, _a.sent()];
345
+ case 3:
346
+ err_1 = _a.sent();
347
+ console.error('ErrorAutoFixManager resolveClientForEnvironment error:', err_1);
348
+ return [2 /*return*/, null];
349
+ case 4: return [2 /*return*/];
350
+ }
351
+ });
352
+ });
353
+ };
354
+ ErrorAutoFixManager.prototype.extractHostFromUrl = function (value) {
355
+ if (!value) {
356
+ return null;
357
+ }
358
+ var trimmed = value.trim();
359
+ if (!trimmed) {
360
+ return null;
361
+ }
362
+ try {
363
+ var parsed = new url_1.URL(trimmed);
364
+ return parsed.hostname.toLowerCase();
365
+ }
366
+ catch (_a) {
367
+ return trimmed.toLowerCase();
368
+ }
369
+ };
370
+ ErrorAutoFixManager.prototype.resolveClientForReport = function (report) {
371
+ return __awaiter(this, void 0, void 0, function () {
372
+ var byId, tryField, _a, _b, _c, err_2;
373
+ var _this = this;
374
+ return __generator(this, function (_d) {
375
+ switch (_d.label) {
376
+ case 0:
377
+ if (!report) {
378
+ return [2 /*return*/, null];
379
+ }
380
+ _d.label = 1;
381
+ case 1:
382
+ _d.trys.push([1, 11, , 12]);
383
+ if (!report.clientId) return [3 /*break*/, 3];
384
+ return [4 /*yield*/, Clients.findById(report.clientId)];
385
+ case 2:
386
+ byId = _d.sent();
387
+ if (byId) {
388
+ return [2 /*return*/, byId];
389
+ }
390
+ _d.label = 3;
391
+ case 3:
392
+ tryField = function (field, value) { return __awaiter(_this, void 0, void 0, function () {
393
+ var escaped, query;
394
+ return __generator(this, function (_a) {
395
+ switch (_a.label) {
396
+ case 0:
397
+ if (!value) {
398
+ return [2 /*return*/, null];
399
+ }
400
+ escaped = this.escapeRegex(value);
401
+ query = {};
402
+ query[field] = { $regex: "^".concat(escaped, "$"), $options: 'i' };
403
+ return [4 /*yield*/, Clients.findOne(query)];
404
+ case 1: return [2 /*return*/, _a.sent()];
405
+ }
406
+ });
407
+ }); };
408
+ return [4 /*yield*/, tryField('name', report.clientName)];
409
+ case 4:
410
+ _c = (_d.sent());
411
+ if (_c) return [3 /*break*/, 6];
412
+ return [4 /*yield*/, tryField('demo_name', report.clientSlug)];
413
+ case 5:
414
+ _c = (_d.sent());
415
+ _d.label = 6;
416
+ case 6:
417
+ _b = _c;
418
+ if (_b) return [3 /*break*/, 8];
419
+ return [4 /*yield*/, tryField('repo', report.clientRepo)];
420
+ case 7:
421
+ _b = (_d.sent());
422
+ _d.label = 8;
423
+ case 8:
424
+ _a = _b;
425
+ if (_a) return [3 /*break*/, 10];
426
+ return [4 /*yield*/, this.resolveClientForEnvironment(report.environment)];
427
+ case 9:
428
+ _a = (_d.sent());
429
+ _d.label = 10;
430
+ case 10: return [2 /*return*/, (_a)];
431
+ case 11:
432
+ err_2 = _d.sent();
433
+ console.error('ErrorAutoFixManager resolveClientForReport error:', err_2);
434
+ return [2 /*return*/, null];
435
+ case 12: return [2 /*return*/];
436
+ }
437
+ });
438
+ });
439
+ };
440
+ ErrorAutoFixManager.prototype.determineOpenAIEnvironment = function (client) {
441
+ var repoCandidate = ((client === null || client === void 0 ? void 0 : client.repo) || '').trim();
442
+ if (repoCandidate) {
443
+ return repoCandidate;
444
+ }
445
+ var configEnv = (this.config.openaiEnvironment || '').trim();
446
+ if (configEnv) {
447
+ return configEnv;
448
+ }
449
+ if ((this.config.githubOwner || '').trim() && (this.config.githubRepo || '').trim()) {
450
+ return "".concat(this.config.githubOwner, "/").concat(this.config.githubRepo).trim();
451
+ }
452
+ return '';
453
+ };
454
+ ErrorAutoFixManager.prototype.resolveEnvironmentForTask = function (email, log) {
455
+ if (email && email.openai_environment && email.openai_environment.trim()) {
456
+ return email.openai_environment.trim();
457
+ }
458
+ if (log && log.openai_environment && log.openai_environment.trim()) {
459
+ return log.openai_environment.trim();
460
+ }
461
+ return this.determineOpenAIEnvironment();
462
+ };
463
+ ErrorAutoFixManager.prototype.buildEmailFromReport = function (report) {
464
+ var timestamp = report.reportedAt instanceof Date && !Number.isNaN(report.reportedAt.getTime())
465
+ ? report.reportedAt
466
+ : new Date();
467
+ var safeMessage = (report.message || '').toString().trim() || 'Unknown error';
468
+ var subjectBase = "[AppError] ".concat(report.sourceApp || 'application').concat(report.environment ? " (".concat(report.environment, ")") : '');
469
+ var subject = "".concat(subjectBase, " - ").concat(safeMessage.slice(0, 120));
470
+ var lines = [
471
+ "Source App:\t".concat(report.sourceApp),
472
+ "Environment:\t".concat(report.environment || 'n/a'),
473
+ "Severity:\t".concat(report.severity || 'error'),
474
+ "Client Hint:\t".concat(report.clientName || report.clientSlug || report.clientRepo || report.clientId || 'n/a'),
475
+ "Reported By:\t".concat(report.reportedBy || report.clientEmail || 'n/a'),
476
+ "Reported At:\t".concat(timestamp.toISOString()),
477
+ "Message:\t".concat(safeMessage)
478
+ ];
479
+ if (report.stack) {
480
+ lines.push('', 'Stack Trace:', report.stack);
481
+ }
482
+ if (report.context && typeof report.context === 'object' && Object.keys(report.context).length) {
483
+ lines.push('', 'Context JSON:', JSON.stringify(report.context, null, 2));
484
+ }
485
+ if (report.metadata && typeof report.metadata === 'object' && Object.keys(report.metadata).length) {
486
+ lines.push('', 'Metadata JSON:', JSON.stringify(report.metadata, null, 2));
487
+ }
488
+ if (Array.isArray(report.attachments) && report.attachments.length) {
489
+ lines.push('', 'Attachments:');
490
+ report.attachments.forEach(function (att) {
491
+ var desc = [];
492
+ if (att.name) {
493
+ desc.push(att.name);
494
+ }
495
+ if (att.contentType) {
496
+ desc.push(att.contentType);
497
+ }
498
+ if (typeof att.size === 'number') {
499
+ desc.push("".concat(att.size, "b"));
500
+ }
501
+ var summary = desc.length ? desc.join(' | ') : 'attachment';
502
+ lines.push("- ".concat(summary).concat(att.url ? " -> ".concat(att.url) : ''));
503
+ });
504
+ }
505
+ if (report.fingerprint) {
506
+ lines.push('', "Fingerprint:\t".concat(report.fingerprint));
507
+ }
508
+ if (report.idempotencyKey) {
509
+ lines.push("Idempotency Key:\t".concat(report.idempotencyKey));
510
+ }
511
+ var body = lines.join('\n');
512
+ return {
513
+ key: "report:".concat(timestamp.getTime().toString(36), ":").concat(Math.random().toString(36).slice(2, 10)),
514
+ subject: subject,
515
+ body: body,
516
+ raw: body,
517
+ from: report.reportedBy || report.clientEmail || 'errors@resolveio.com',
518
+ sourceApp: report.sourceApp,
519
+ sourceEnvironment: report.environment,
520
+ severity: report.severity,
521
+ reportedBy: report.reportedBy,
522
+ reportMetadata: report.metadata,
523
+ reportContext: report.context,
524
+ attachments: Array.isArray(report.attachments) ? report.attachments : [],
525
+ openai_environment: report.clientRepo,
526
+ reportedAt: timestamp
527
+ };
528
+ };
529
+ ErrorAutoFixManager.prototype.classifyEmail = function (email) {
530
+ var subject = (email.subject || '').toLowerCase();
531
+ var body = email.body || '';
532
+ var normalizedBody = body.toLowerCase();
533
+ if (subject.includes('autofix') &&
534
+ (normalizedBody.includes('auto-fix workflow') || normalizedBody.includes('autofix workflow'))) {
535
+ return { source: 'noise', skip: true, reason: 'AutoFix status notification' };
536
+ }
537
+ if (subject.includes('[database]') || subject.includes('[server]')) {
538
+ return { source: 'infrastructure', skip: true, reason: 'Infrastructure alert (subject tag)' };
539
+ }
540
+ var infraKeyword = INFRA_SUBJECT_KEYWORDS.find(function (keyword) { return subject.includes(keyword); });
541
+ if (infraKeyword) {
542
+ return { source: 'infrastructure', skip: true, reason: "Infrastructure alert (".concat(infraKeyword, ")") };
543
+ }
544
+ if (!body.trim()) {
545
+ return { source: 'noise', skip: true, reason: 'Empty error payload' };
546
+ }
547
+ var emptyErrorsRegex = /errors\s*[\r\n]+(\{\s*\}|\[\s*\])/i;
548
+ if (emptyErrorsRegex.test(body)) {
549
+ return { source: 'noise', skip: true, reason: 'Empty error details' };
550
+ }
551
+ if (subject.includes('database is down') || normalizedBody.includes('database is down')) {
552
+ return { source: 'infrastructure', skip: true, reason: 'Database outage alert' };
553
+ }
554
+ return { source: 'app', skip: false };
555
+ };
556
+ ErrorAutoFixManager.prototype.generateRawEmailHash = function (email) {
557
+ return (0, crypto_1.createHash)('sha256').update("".concat(email.subject || '', "\n").concat(email.body || ''), 'utf8').digest('hex');
558
+ };
559
+ ErrorAutoFixManager.prototype.generateIssueHash = function (email) {
560
+ var subject = this.normalizeTextForHash(email.subject || '');
561
+ var body = this.normalizeBodyForHash(email.body || '');
562
+ return (0, crypto_1.createHash)('sha256').update("".concat(subject, "\n").concat(body), 'utf8').digest('hex');
563
+ };
564
+ ErrorAutoFixManager.prototype.normalizeTextForHash = function (value) {
565
+ if (!value) {
566
+ return '';
567
+ }
568
+ var normalized = value
569
+ .replace(/\r/g, '\n')
570
+ .toLowerCase()
571
+ .replace(/0x[0-9a-f]+/gi, '0x#')
572
+ .replace(/\b[0-9a-f]{7,64}\b/gi, '#')
573
+ .replace(/\b[0-9]{4}[-/][0-9]{2}[-/][0-9]{2}(?:[ t][0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]{1,6})?)?\b/g, '#datetime#')
574
+ .replace(/\b[0-9]{2}:[0-9]{2}:[0-9]{2}\b/g, '#time#')
575
+ .replace(/[0-9]+/g, '#')
576
+ .replace(/[^\S\n]+/g, ' ')
577
+ .split('\n')
578
+ .map(function (line) { return line.trim(); })
579
+ .filter(Boolean)
580
+ .slice(0, 60)
581
+ .join('\n');
582
+ return normalized.length > 4000 ? normalized.slice(0, 4000) : normalized;
583
+ };
584
+ ErrorAutoFixManager.prototype.normalizeBodyForHash = function (body) {
585
+ if (!body) {
586
+ return '';
587
+ }
588
+ var withoutStackNoise = body
589
+ .replace(/=+\s*stack trace\s*=+/gi, 'stack trace')
590
+ .replace(/-{3,}/g, '-')
591
+ .replace(/\[[^\]]*request id[^\]]*\]/gi, '[request id]')
592
+ .replace(/guid:[^\s]+/gi, 'guid:#')
593
+ .replace(/request id:[^\s]+/gi, 'request id:#')
594
+ .replace(/correlation id:[^\s]+/gi, 'correlation id:#');
595
+ return this.normalizeTextForHash(withoutStackNoise);
596
+ };
597
+ ErrorAutoFixManager.prototype.parseRepoTarget = function (env) {
598
+ var trimmed = (env || '').trim();
599
+ if (!trimmed) {
600
+ return null;
601
+ }
602
+ var _a = __read(trimmed.split('/', 2), 2), owner = _a[0], repo = _a[1];
603
+ if (!owner || !repo) {
604
+ return null;
605
+ }
606
+ return {
607
+ owner: owner.trim(),
608
+ repo: repo.trim()
609
+ };
610
+ };
611
+ ErrorAutoFixManager.prototype.buildWorkBranch = function (hash) {
612
+ var shortHash = (hash || '').toLowerCase().replace(/[^a-z0-9]/g, '').slice(0, 12) || 'autofix';
613
+ var prefix = (this.config.branchPrefix || 'openai/auto').trim();
614
+ if (!prefix) {
615
+ return shortHash;
616
+ }
617
+ var segments = prefix.split('/').map(function (segment) { return segment.trim(); }).filter(Boolean);
618
+ var sanitized = segments.map(function (segment) { return segment.replace(/[^a-zA-Z0-9._-]/g, '-'); });
619
+ return "".concat(sanitized.join('/'), "/").concat(shortHash);
620
+ };
621
+ ErrorAutoFixManager.prototype.normalizeEmailText = function (value, limit) {
622
+ if (limit === void 0) { limit = 20000; }
623
+ if (!value) {
624
+ return '';
625
+ }
626
+ var cleaned = value.replace(/\r/g, '');
627
+ if (cleaned.length <= limit) {
628
+ return cleaned;
629
+ }
630
+ return "".concat(cleaned.slice(0, limit), "\n... (truncated)");
631
+ };
632
+ ErrorAutoFixManager.prototype.buildContextMarkdown = function (email, identifier, normalizedBody) {
633
+ var lines = [
634
+ "# OpenAI Error Context: ".concat(identifier),
635
+ '',
636
+ "**Subject**: ".concat(email.subject || '(no subject)'),
637
+ email.fromAddress ? "**From**: ".concat(email.fromAddress) : undefined,
638
+ email.client_name ? "**Client**: ".concat(email.client_name) : undefined,
639
+ email.source_type ? "**Classification**: ".concat(email.source_type).concat(email.classification_reason ? " (".concat(email.classification_reason, ")") : '') : undefined,
640
+ email.id_client ? "**Client Id**: ".concat(email.id_client) : undefined,
641
+ '',
642
+ '## Body',
643
+ '```',
644
+ normalizedBody || '(empty body)',
645
+ '```',
646
+ '',
647
+ '_Generated by ErrorAutoFixManager_'
648
+ ];
649
+ return lines.filter(function (line) { return typeof line !== 'undefined'; }).join('\n');
650
+ };
651
+ ErrorAutoFixManager.prototype.buildOpenAIComment = function (email, contextPath, normalizedBody) {
652
+ var lines = [
653
+ '@openai review',
654
+ '',
655
+ "**Email Subject**: ".concat(email.subject || '(no subject)'),
656
+ email.fromAddress ? "**From**: ".concat(email.fromAddress) : undefined,
657
+ email.client_name ? "**Client**: ".concat(email.client_name) : undefined,
658
+ contextPath ? "Context file: `".concat(contextPath, "`") : undefined,
659
+ '',
660
+ '```',
661
+ normalizedBody || '(empty body)',
662
+ '```',
663
+ '',
664
+ 'Please investigate this error and propose a minimal, safe fix.'
665
+ ];
666
+ return lines.filter(function (line) { return typeof line !== 'undefined'; }).join('\n');
667
+ };
668
+ ErrorAutoFixManager.prototype.formatGithubError = function (error) {
669
+ var _a, _b, _c;
670
+ if (!error) {
671
+ return 'GitHub request failed.';
672
+ }
673
+ var status = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status;
674
+ var message = ((_c = (_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.message) || (error === null || error === void 0 ? void 0 : error.message) || 'GitHub request failed.';
675
+ if (status) {
676
+ return "GitHub API error (".concat(status, "): ").concat(message);
677
+ }
678
+ return "GitHub API error: ".concat(message);
679
+ };
680
+ ErrorAutoFixManager.prototype.buildGithubAuthHeader = function (token) {
681
+ var trimmed = (token || '').trim();
682
+ if (!trimmed) {
683
+ return '';
684
+ }
685
+ if (/^(token|Bearer)\s+/i.test(trimmed)) {
686
+ return trimmed;
687
+ }
688
+ if (trimmed.includes('.') && !trimmed.startsWith('gh')) {
689
+ return "Bearer ".concat(trimmed);
690
+ }
691
+ return "token ".concat(trimmed);
692
+ };
693
+ ErrorAutoFixManager.prototype.githubRequest = function (config_1) {
694
+ return __awaiter(this, arguments, void 0, function (config, allow404) {
695
+ var authHeader, headers, finalConfig, response, err_3, status_1;
696
+ var _a;
697
+ if (allow404 === void 0) { allow404 = false; }
698
+ return __generator(this, function (_b) {
699
+ switch (_b.label) {
700
+ case 0:
701
+ authHeader = this.buildGithubAuthHeader(this.config.githubToken);
702
+ headers = __assign(__assign({}, (authHeader ? { Authorization: authHeader } : {})), { Accept: 'application/vnd.github+json', 'User-Agent': 'ResolveIO-AutoFix', 'X-GitHub-Api-Version': '2022-11-28' });
703
+ finalConfig = __assign(__assign({}, config), { baseURL: this.githubApiBase, headers: __assign(__assign({}, headers), (config.headers || {})), timeout: Math.min(Math.max(this.config.commandTimeoutMs || 600000, 1000), 120000) });
704
+ _b.label = 1;
705
+ case 1:
706
+ _b.trys.push([1, 3, , 4]);
707
+ return [4 /*yield*/, axios_1.default.request(finalConfig)];
708
+ case 2:
709
+ response = _b.sent();
710
+ return [2 /*return*/, response.data];
711
+ case 3:
712
+ err_3 = _b.sent();
713
+ status_1 = (_a = err_3 === null || err_3 === void 0 ? void 0 : err_3.response) === null || _a === void 0 ? void 0 : _a.status;
714
+ if (allow404 && status_1 === 404) {
715
+ return [2 /*return*/, null];
716
+ }
717
+ throw new Error(this.formatGithubError(err_3));
718
+ case 4: return [2 /*return*/];
719
+ }
720
+ });
721
+ });
722
+ };
723
+ ErrorAutoFixManager.prototype.resolveBaseBranch = function (target) {
724
+ return __awaiter(this, void 0, void 0, function () {
725
+ var fallback, repo, defaultBranch, err_4;
726
+ return __generator(this, function (_a) {
727
+ switch (_a.label) {
728
+ case 0:
729
+ fallback = (this.config.baseBranch || 'main').trim();
730
+ _a.label = 1;
731
+ case 1:
732
+ _a.trys.push([1, 3, , 4]);
733
+ return [4 /*yield*/, this.githubRequest({ method: 'GET', url: "/repos/".concat(target.owner, "/").concat(target.repo) })];
734
+ case 2:
735
+ repo = _a.sent();
736
+ defaultBranch = ((repo === null || repo === void 0 ? void 0 : repo.default_branch) || '').trim();
737
+ return [2 /*return*/, defaultBranch || fallback];
738
+ case 3:
739
+ err_4 = _a.sent();
740
+ this.debugLog('Failed to fetch default branch. Falling back to configured branch.', {
741
+ target: target,
742
+ error: err_4 === null || err_4 === void 0 ? void 0 : err_4.message
743
+ });
744
+ return [2 /*return*/, fallback];
745
+ case 4: return [2 /*return*/];
746
+ }
747
+ });
748
+ });
749
+ };
750
+ ErrorAutoFixManager.prototype.getBranchSha = function (target, branch) {
751
+ return __awaiter(this, void 0, void 0, function () {
752
+ var ref, sha;
753
+ var _a;
754
+ return __generator(this, function (_b) {
755
+ switch (_b.label) {
756
+ case 0: return [4 /*yield*/, this.githubRequest({ method: 'GET', url: "/repos/".concat(target.owner, "/").concat(target.repo, "/git/ref/heads/").concat(branch) })];
757
+ case 1:
758
+ ref = _b.sent();
759
+ sha = (_a = ref === null || ref === void 0 ? void 0 : ref.object) === null || _a === void 0 ? void 0 : _a.sha;
760
+ if (!sha) {
761
+ throw new Error("Base branch ".concat(branch, " not found."));
762
+ }
763
+ return [2 /*return*/, sha];
764
+ }
765
+ });
766
+ });
767
+ };
768
+ ErrorAutoFixManager.prototype.ensureBranch = function (target, newBranch, baseBranch, baseSha) {
769
+ return __awaiter(this, void 0, void 0, function () {
770
+ var existing;
771
+ return __generator(this, function (_a) {
772
+ switch (_a.label) {
773
+ case 0: return [4 /*yield*/, this.githubRequest({ method: 'GET', url: "/repos/".concat(target.owner, "/").concat(target.repo, "/git/ref/heads/").concat(newBranch) }, true)];
774
+ case 1:
775
+ existing = _a.sent();
776
+ if (existing) {
777
+ return [2 /*return*/];
778
+ }
779
+ return [4 /*yield*/, this.githubRequest({
780
+ method: 'POST',
781
+ url: "/repos/".concat(target.owner, "/").concat(target.repo, "/git/refs"),
782
+ data: {
783
+ ref: "refs/heads/".concat(newBranch),
784
+ sha: baseSha
785
+ }
786
+ })];
787
+ case 2:
788
+ _a.sent();
789
+ return [2 /*return*/];
790
+ }
791
+ });
792
+ });
793
+ };
794
+ ErrorAutoFixManager.prototype.upsertContextFile = function (target, branch, contextPath, content) {
795
+ return __awaiter(this, void 0, void 0, function () {
796
+ var encodedPath, existing, sha, commitMessage;
797
+ return __generator(this, function (_a) {
798
+ switch (_a.label) {
799
+ case 0:
800
+ encodedPath = encodeURIComponent(contextPath).replace(/%2F/g, '/');
801
+ return [4 /*yield*/, this.githubRequest({
802
+ method: 'GET',
803
+ url: "/repos/".concat(target.owner, "/").concat(target.repo, "/contents/").concat(encodedPath),
804
+ params: { ref: branch }
805
+ }, true)];
806
+ case 1:
807
+ existing = _a.sent();
808
+ sha = existing && existing.sha ? existing.sha : undefined;
809
+ commitMessage = "chore(openai): update error context ".concat(contextPath);
810
+ return [4 /*yield*/, this.githubRequest({
811
+ method: 'PUT',
812
+ url: "/repos/".concat(target.owner, "/").concat(target.repo, "/contents/").concat(encodedPath),
813
+ data: {
814
+ message: commitMessage.slice(0, 200),
815
+ content: Buffer.from(content, 'utf8').toString('base64'),
816
+ branch: branch,
817
+ sha: sha
818
+ }
819
+ })];
820
+ case 2:
821
+ _a.sent();
822
+ return [2 /*return*/];
823
+ }
824
+ });
825
+ });
826
+ };
827
+ ErrorAutoFixManager.prototype.findOpenPullRequest = function (target, branch, base) {
828
+ return __awaiter(this, void 0, void 0, function () {
829
+ var prs;
830
+ return __generator(this, function (_a) {
831
+ switch (_a.label) {
832
+ case 0: return [4 /*yield*/, this.githubRequest({
833
+ method: 'GET',
834
+ url: "/repos/".concat(target.owner, "/").concat(target.repo, "/pulls"),
835
+ params: {
836
+ state: 'open',
837
+ head: "".concat(target.owner, ":").concat(branch),
838
+ base: base,
839
+ per_page: 1
840
+ }
841
+ })];
842
+ case 1:
843
+ prs = _a.sent();
844
+ if (prs && prs.length) {
845
+ return [2 /*return*/, prs[0]];
846
+ }
847
+ return [2 /*return*/, null];
848
+ }
849
+ });
850
+ });
851
+ };
852
+ ErrorAutoFixManager.prototype.createPullRequest = function (target, branch, base, title, body) {
853
+ return __awaiter(this, void 0, void 0, function () {
854
+ var pr;
855
+ return __generator(this, function (_a) {
856
+ switch (_a.label) {
857
+ case 0: return [4 /*yield*/, this.githubRequest({
858
+ method: 'POST',
859
+ url: "/repos/".concat(target.owner, "/").concat(target.repo, "/pulls"),
860
+ data: {
861
+ title: title,
862
+ head: branch,
863
+ base: base,
864
+ body: body
865
+ }
866
+ })];
867
+ case 1:
868
+ pr = _a.sent();
869
+ return [2 /*return*/, pr];
870
+ }
871
+ });
872
+ });
873
+ };
874
+ ErrorAutoFixManager.prototype.commentOnPullRequest = function (target, prNumber, body) {
875
+ return __awaiter(this, void 0, void 0, function () {
876
+ return __generator(this, function (_a) {
877
+ switch (_a.label) {
878
+ case 0: return [4 /*yield*/, this.githubRequest({
879
+ method: 'POST',
880
+ url: "/repos/".concat(target.owner, "/").concat(target.repo, "/issues/").concat(prNumber, "/comments"),
881
+ data: {
882
+ body: body
883
+ }
884
+ })];
885
+ case 1:
886
+ _a.sent();
887
+ return [2 /*return*/];
888
+ }
889
+ });
890
+ });
891
+ };
892
+ ErrorAutoFixManager.prototype.reserveLog = function (email, client) {
893
+ return __awaiter(this, void 0, void 0, function () {
894
+ var hash, rawHash, now, existing, updatedExisting, metaUpdate, reactivated, attemptsUsed, maxAttempts, reason, exhausted, resumed, counterValue, counterString, doc;
895
+ return __generator(this, function (_a) {
896
+ switch (_a.label) {
897
+ case 0:
898
+ hash = email.hash;
899
+ rawHash = email.rawHash || hash;
900
+ now = email.reportedAt || new Date();
901
+ existing = null;
902
+ if (!hash) return [3 /*break*/, 2];
903
+ return [4 /*yield*/, ErrorAutoFixLogs.findOne({ issue_hash: hash })];
904
+ case 1:
905
+ existing = _a.sent();
906
+ _a.label = 2;
907
+ case 2:
908
+ if (!(!existing && rawHash)) return [3 /*break*/, 4];
909
+ return [4 /*yield*/, ErrorAutoFixLogs.findOne({ email_hash: rawHash })];
910
+ case 3:
911
+ existing = _a.sent();
912
+ _a.label = 4;
913
+ case 4:
914
+ if (!(!existing && hash && hash !== rawHash)) return [3 /*break*/, 6];
915
+ return [4 /*yield*/, ErrorAutoFixLogs.findOne({ email_hash: hash })];
916
+ case 5:
917
+ existing = _a.sent();
918
+ _a.label = 6;
919
+ case 6:
920
+ if (!existing) return [3 /*break*/, 18];
921
+ return [4 /*yield*/, this.markDuplicate(existing._id, now)];
922
+ case 7:
923
+ _a.sent();
924
+ return [4 /*yield*/, ErrorAutoFixLogs.findOne({ _id: existing._id })];
925
+ case 8:
926
+ updatedExisting = (_a.sent()) || existing;
927
+ metaUpdate = {};
928
+ if (hash && (!updatedExisting.issue_hash || updatedExisting.issue_hash !== hash)) {
929
+ metaUpdate.issue_hash = hash;
930
+ }
931
+ if (rawHash && (!updatedExisting.email_hash || updatedExisting.email_hash !== rawHash)) {
932
+ metaUpdate.email_hash = rawHash;
933
+ }
934
+ if (email.fromAddress && email.fromAddress !== updatedExisting.from_email) {
935
+ metaUpdate.from_email = email.fromAddress;
936
+ }
937
+ if (client) {
938
+ if (!updatedExisting.id_client || updatedExisting.id_client !== client._id) {
939
+ metaUpdate.id_client = client._id;
940
+ }
941
+ if (!updatedExisting.client_name || updatedExisting.client_name !== client.name) {
942
+ metaUpdate.client_name = client.name;
943
+ }
944
+ }
945
+ if (email.openai_environment && email.openai_environment !== updatedExisting.openai_environment) {
946
+ metaUpdate.openai_environment = email.openai_environment;
947
+ }
948
+ if (email.sourceApp && email.sourceApp !== updatedExisting.source_app) {
949
+ metaUpdate.source_app = email.sourceApp;
950
+ }
951
+ if (email.sourceEnvironment && email.sourceEnvironment !== updatedExisting.source_environment) {
952
+ metaUpdate.source_environment = email.sourceEnvironment;
953
+ }
954
+ if (email.severity && email.severity !== updatedExisting.severity) {
955
+ metaUpdate.severity = email.severity;
956
+ }
957
+ if (email.reportedBy && email.reportedBy !== updatedExisting.reported_by) {
958
+ metaUpdate.reported_by = email.reportedBy;
959
+ }
960
+ if (typeof email.reportMetadata !== 'undefined') {
961
+ metaUpdate.report_metadata = email.reportMetadata;
962
+ }
963
+ if (typeof email.reportContext !== 'undefined') {
964
+ metaUpdate.report_context = email.reportContext;
965
+ }
966
+ if (typeof email.attachments !== 'undefined') {
967
+ metaUpdate.attachments = email.attachments;
968
+ }
969
+ metaUpdate.last_reported_at = now;
970
+ if (!Object.keys(metaUpdate).length) return [3 /*break*/, 10];
971
+ return [4 /*yield*/, this.updateLog(updatedExisting._id, metaUpdate)];
972
+ case 9:
973
+ _a.sent();
974
+ _a.label = 10;
975
+ case 10:
976
+ if (!(updatedExisting.status === 'completed')) return [3 /*break*/, 12];
977
+ return [4 /*yield*/, ErrorAutoFixLogs.findOneAndUpdate({ _id: updatedExisting._id }, {
978
+ $set: {
979
+ status: 'pending',
980
+ ignored: false,
981
+ last_error: '',
982
+ openai_task_id: '',
983
+ branch_name: '',
984
+ pr_url: ''
985
+ }
986
+ }, {
987
+ returnDocument: 'after'
988
+ })];
989
+ case 11:
990
+ reactivated = (_a.sent()) || updatedExisting;
991
+ return [2 /*return*/, {
992
+ proceed: true,
993
+ log: reactivated
994
+ }];
995
+ case 12:
996
+ if (updatedExisting.ignored) {
997
+ return [2 /*return*/, {
998
+ proceed: false,
999
+ log: updatedExisting,
1000
+ reason: 'ignored'
1001
+ }];
1002
+ }
1003
+ if (!(this.config.autoRunEnabled && (updatedExisting.status === 'failed' || updatedExisting.status === 'skipped') && !updatedExisting.ignored)) return [3 /*break*/, 17];
1004
+ attemptsUsed = Number.isFinite(Number(updatedExisting.attempt_count))
1005
+ ? Number(updatedExisting.attempt_count)
1006
+ : 0;
1007
+ maxAttempts = Number.isFinite(Number(this.config.maxAutoRunAttemptsPerIssue))
1008
+ ? Number(this.config.maxAutoRunAttemptsPerIssue)
1009
+ : 0;
1010
+ if (!(maxAttempts > 0 && attemptsUsed >= maxAttempts)) return [3 /*break*/, 15];
1011
+ reason = "Auto-fix attempt budget reached (".concat(attemptsUsed, "/").concat(maxAttempts, ").");
1012
+ return [4 /*yield*/, ErrorAutoFixLogs.findOneAndUpdate({ _id: updatedExisting._id }, {
1013
+ $set: {
1014
+ status: 'skipped',
1015
+ ignored: true,
1016
+ last_error: "".concat(reason, " Marked ignored pending manual intervention."),
1017
+ last_result_at: now,
1018
+ updatedAt: now
1019
+ }
1020
+ }, {
1021
+ returnDocument: 'after'
1022
+ })];
1023
+ case 13:
1024
+ exhausted = (_a.sent()) || updatedExisting;
1025
+ return [4 /*yield*/, this.sendEscalationNotice(exhausted, reason)];
1026
+ case 14:
1027
+ _a.sent();
1028
+ return [2 /*return*/, {
1029
+ proceed: false,
1030
+ log: exhausted,
1031
+ reason: 'budget_exhausted'
1032
+ }];
1033
+ case 15: return [4 /*yield*/, ErrorAutoFixLogs.findOneAndUpdate({ _id: updatedExisting._id }, {
1034
+ $inc: {
1035
+ attempt_count: 1
1036
+ },
1037
+ $set: {
1038
+ status: 'in_progress',
1039
+ last_attempt_at: now,
1040
+ openai_task_id: '',
1041
+ branch_name: '',
1042
+ pr_url: '',
1043
+ last_error: ''
1044
+ }
1045
+ }, {
1046
+ returnDocument: 'after'
1047
+ })];
1048
+ case 16:
1049
+ resumed = _a.sent();
1050
+ return [2 /*return*/, {
1051
+ proceed: true,
1052
+ log: resumed || updatedExisting
1053
+ }];
1054
+ case 17:
1055
+ if (updatedExisting.status === 'in_progress') {
1056
+ return [2 /*return*/, {
1057
+ proceed: false,
1058
+ log: updatedExisting,
1059
+ reason: 'in_progress'
1060
+ }];
1061
+ }
1062
+ if (updatedExisting.status === 'success') {
1063
+ return [2 /*return*/, {
1064
+ proceed: false,
1065
+ log: updatedExisting,
1066
+ reason: 'success'
1067
+ }];
1068
+ }
1069
+ return [2 /*return*/, {
1070
+ proceed: false,
1071
+ log: updatedExisting,
1072
+ reason: 'duplicate'
1073
+ }];
1074
+ case 18: return [4 /*yield*/, resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().callMethod('incCounter', 'autofix_error')];
1075
+ case 19:
1076
+ counterValue = _a.sent();
1077
+ counterString = (0, common_1.pad)(counterValue, 6);
1078
+ doc = {
1079
+ _id: (0, common_1.objectIdHexString)(),
1080
+ email_hash: rawHash,
1081
+ issue_hash: hash,
1082
+ subject: email.subject,
1083
+ message_id: email.messageId,
1084
+ body: email.body,
1085
+ status: this.config.autoRunEnabled ? 'in_progress' : 'pending',
1086
+ ignored: false,
1087
+ attempt_count: this.config.autoRunEnabled ? 1 : 0,
1088
+ duplicate_count: 0,
1089
+ autofix_error_count: counterValue,
1090
+ autofix_error_count_string: counterString,
1091
+ first_seen_at: now,
1092
+ last_attempt_at: this.config.autoRunEnabled ? now : undefined,
1093
+ from_email: email.fromAddress || '',
1094
+ id_client: client === null || client === void 0 ? void 0 : client._id,
1095
+ client_name: client === null || client === void 0 ? void 0 : client.name,
1096
+ openai_environment: email.openai_environment || this.determineOpenAIEnvironment(client),
1097
+ source_app: email.sourceApp,
1098
+ source_environment: email.sourceEnvironment,
1099
+ severity: email.severity,
1100
+ reported_by: email.reportedBy || email.fromAddress || '',
1101
+ last_reported_at: now,
1102
+ report_metadata: email.reportMetadata,
1103
+ report_context: email.reportContext,
1104
+ attachments: email.attachments
1105
+ };
1106
+ return [4 /*yield*/, ErrorAutoFixLogs.insertOne(doc)];
1107
+ case 20:
1108
+ _a.sent();
1109
+ return [2 /*return*/, {
1110
+ proceed: true,
1111
+ log: doc
1112
+ }];
1113
+ }
1114
+ });
1115
+ });
1116
+ };
1117
+ ErrorAutoFixManager.prototype.markDuplicate = function (logId, timestamp) {
1118
+ return __awaiter(this, void 0, void 0, function () {
1119
+ return __generator(this, function (_a) {
1120
+ switch (_a.label) {
1121
+ case 0: return [4 /*yield*/, ErrorAutoFixLogs.updateOne({ _id: logId }, {
1122
+ $inc: {
1123
+ duplicate_count: 1
1124
+ },
1125
+ $set: {
1126
+ last_duplicate_at: timestamp,
1127
+ last_reported_at: timestamp,
1128
+ updatedAt: timestamp
1129
+ }
1130
+ })];
1131
+ case 1:
1132
+ _a.sent();
1133
+ return [2 /*return*/];
1134
+ }
1135
+ });
1136
+ });
1137
+ };
1138
+ ErrorAutoFixManager.prototype.updateLog = function (logId, set, inc) {
1139
+ return __awaiter(this, void 0, void 0, function () {
1140
+ var cleanedSet, rawSet, update, result;
1141
+ return __generator(this, function (_a) {
1142
+ switch (_a.label) {
1143
+ case 0:
1144
+ cleanedSet = {};
1145
+ rawSet = set ? __assign({}, set) : {};
1146
+ Object.keys(rawSet).forEach(function (key) {
1147
+ if (typeof rawSet[key] !== 'undefined') {
1148
+ cleanedSet[key] = rawSet[key];
1149
+ }
1150
+ });
1151
+ cleanedSet.updatedAt = new Date();
1152
+ update = {
1153
+ $set: cleanedSet
1154
+ };
1155
+ if (inc) {
1156
+ update.$inc = inc;
1157
+ }
1158
+ return [4 /*yield*/, ErrorAutoFixLogs.findOneAndUpdate({ _id: logId }, update, {
1159
+ returnDocument: 'after'
1160
+ })];
1161
+ case 1:
1162
+ result = _a.sent();
1163
+ return [2 /*return*/, result];
1164
+ }
1165
+ });
1166
+ });
1167
+ };
1168
+ ErrorAutoFixManager.prototype.getEscalationRecipients = function () {
1169
+ var unique = new Set();
1170
+ var add = function (value) {
1171
+ var normalized = String(value || '').trim().toLowerCase();
1172
+ if (!normalized) {
1173
+ return;
1174
+ }
1175
+ unique.add(normalized);
1176
+ };
1177
+ (this.config.escalationEmails || []).forEach(add);
1178
+ (this.config.notifyEmails || []).forEach(add);
1179
+ if (!unique.size) {
1180
+ add(DEFAULT_ERROR_ALERT_EMAIL);
1181
+ }
1182
+ return Array.from(unique);
1183
+ };
1184
+ ErrorAutoFixManager.prototype.sendEscalationNotice = function (log, reason) {
1185
+ return __awaiter(this, void 0, void 0, function () {
1186
+ var recipients, identifier, subject, body, methodManager, recipients_1, recipients_1_1, recipient, error_1, e_1_1;
1187
+ var e_1, _a;
1188
+ return __generator(this, function (_b) {
1189
+ switch (_b.label) {
1190
+ case 0:
1191
+ recipients = this.getEscalationRecipients();
1192
+ if (!recipients.length || !(log === null || log === void 0 ? void 0 : log._id)) {
1193
+ return [2 /*return*/];
1194
+ }
1195
+ identifier = log.autofix_error_count_string || log._id;
1196
+ subject = "ResolveIO AutoFix Escalation: ".concat(identifier);
1197
+ body = [
1198
+ 'Auto-fix retry budget was exhausted for this recurring issue and further autonomous attempts were stopped.',
1199
+ '',
1200
+ "Reason: ".concat(reason),
1201
+ "Issue Log ID: ".concat(log._id),
1202
+ "Issue Counter: ".concat(log.autofix_error_count_string || 'n/a'),
1203
+ "Client: ".concat(log.client_name || log.id_client || 'unknown'),
1204
+ "Source App: ".concat(log.source_app || 'unknown'),
1205
+ "Environment: ".concat(log.source_environment || log.openai_environment || 'unknown'),
1206
+ "Attempts: ".concat(log.attempt_count || 0, "/").concat(this.config.maxAutoRunAttemptsPerIssue),
1207
+ "Issue Hash: ".concat(log.issue_hash || log.email_hash || 'n/a'),
1208
+ '',
1209
+ 'The issue is now marked ignored for auto-fix to protect customer token usage. Manual intervention is required.'
1210
+ ].join('\n');
1211
+ methodManager = resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager();
1212
+ _b.label = 1;
1213
+ case 1:
1214
+ _b.trys.push([1, 8, 9, 10]);
1215
+ recipients_1 = __values(recipients), recipients_1_1 = recipients_1.next();
1216
+ _b.label = 2;
1217
+ case 2:
1218
+ if (!!recipients_1_1.done) return [3 /*break*/, 7];
1219
+ recipient = recipients_1_1.value;
1220
+ _b.label = 3;
1221
+ case 3:
1222
+ _b.trys.push([3, 5, , 6]);
1223
+ return [4 /*yield*/, methodManager.sendEmail(recipient, subject, body)];
1224
+ case 4:
1225
+ _b.sent();
1226
+ return [3 /*break*/, 6];
1227
+ case 5:
1228
+ error_1 = _b.sent();
1229
+ console.error('Failed sending auto-fix escalation email', { recipient: recipient, logId: log._id, error: error_1 });
1230
+ return [3 /*break*/, 6];
1231
+ case 6:
1232
+ recipients_1_1 = recipients_1.next();
1233
+ return [3 /*break*/, 2];
1234
+ case 7: return [3 /*break*/, 10];
1235
+ case 8:
1236
+ e_1_1 = _b.sent();
1237
+ e_1 = { error: e_1_1 };
1238
+ return [3 /*break*/, 10];
1239
+ case 9:
1240
+ try {
1241
+ if (recipients_1_1 && !recipients_1_1.done && (_a = recipients_1.return)) _a.call(recipients_1);
1242
+ }
1243
+ finally { if (e_1) throw e_1.error; }
1244
+ return [7 /*endfinally*/];
1245
+ case 10: return [2 /*return*/];
1246
+ }
1247
+ });
1248
+ });
1249
+ };
1250
+ ErrorAutoFixManager.prototype.collectLibraryIssueSignalText = function (email, log) {
1251
+ var attachments = Array.isArray(log === null || log === void 0 ? void 0 : log.attachments) ? log.attachments : [];
1252
+ var attachmentSignals = attachments.map(function (attachment) {
1253
+ return [
1254
+ (attachment === null || attachment === void 0 ? void 0 : attachment.name) || '',
1255
+ (attachment === null || attachment === void 0 ? void 0 : attachment.url) || '',
1256
+ (attachment === null || attachment === void 0 ? void 0 : attachment.contentType) || ''
1257
+ ].filter(Boolean).join(' ');
1258
+ });
1259
+ var metadata = (log === null || log === void 0 ? void 0 : log.report_metadata) && Object.keys(log.report_metadata).length
1260
+ ? JSON.stringify(log.report_metadata)
1261
+ : '';
1262
+ var context = (log === null || log === void 0 ? void 0 : log.report_context) && Object.keys(log.report_context).length
1263
+ ? JSON.stringify(log.report_context)
1264
+ : '';
1265
+ return [
1266
+ (email === null || email === void 0 ? void 0 : email.subject) || '',
1267
+ (email === null || email === void 0 ? void 0 : email.body) || '',
1268
+ (log === null || log === void 0 ? void 0 : log.body) || '',
1269
+ metadata,
1270
+ context,
1271
+ attachmentSignals.join('\n')
1272
+ ].filter(Boolean).join('\n');
1273
+ };
1274
+ ErrorAutoFixManager.prototype.evaluateLibraryIssueGate = function (email, log) {
1275
+ var e_2, _a;
1276
+ var signalText = this.collectLibraryIssueSignalText(email, log);
1277
+ if (!signalText) {
1278
+ return { blocked: false, evidence: [] };
1279
+ }
1280
+ var evidence = [];
1281
+ var markerHits = 0;
1282
+ try {
1283
+ for (var LIBRARY_MARKER_PATTERNS_1 = __values(LIBRARY_MARKER_PATTERNS), LIBRARY_MARKER_PATTERNS_1_1 = LIBRARY_MARKER_PATTERNS_1.next(); !LIBRARY_MARKER_PATTERNS_1_1.done; LIBRARY_MARKER_PATTERNS_1_1 = LIBRARY_MARKER_PATTERNS_1.next()) {
1284
+ var marker = LIBRARY_MARKER_PATTERNS_1_1.value;
1285
+ if (!marker.pattern.test(signalText)) {
1286
+ continue;
1287
+ }
1288
+ markerHits += 1;
1289
+ evidence.push(marker.label);
1290
+ }
1291
+ }
1292
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
1293
+ finally {
1294
+ try {
1295
+ if (LIBRARY_MARKER_PATTERNS_1_1 && !LIBRARY_MARKER_PATTERNS_1_1.done && (_a = LIBRARY_MARKER_PATTERNS_1.return)) _a.call(LIBRARY_MARKER_PATTERNS_1);
1296
+ }
1297
+ finally { if (e_2) throw e_2.error; }
1298
+ }
1299
+ var rawPaths = signalText.match(FILE_PATH_PATTERN) || [];
1300
+ var normalizedPaths = rawPaths
1301
+ .map(function (value) { return String(value || '').trim(); })
1302
+ .filter(Boolean)
1303
+ .map(function (value) { return value.replace(/\\/g, '/').toLowerCase(); });
1304
+ var appOwnedPathCount = normalizedPaths.filter(function (value) { return APP_OWNED_PATH_PATTERN.test(value); }).length;
1305
+ var libraryPathCount = normalizedPaths.filter(function (value) {
1306
+ return value.includes('/node_modules/')
1307
+ || value.includes('@resolveio/client-lib')
1308
+ || value.includes('@resolveio/server-lib')
1309
+ || value.includes('/resolveio-client-lib/')
1310
+ || value.includes('/resolveio-server-lib/')
1311
+ || value.includes('/aicoder/templates/base_');
1312
+ }).length;
1313
+ var shouldBlock = (libraryPathCount > 0 && appOwnedPathCount === 0)
1314
+ || (markerHits >= 2 && appOwnedPathCount === 0)
1315
+ || (markerHits >= 1 && libraryPathCount >= 2);
1316
+ if (!shouldBlock) {
1317
+ return { blocked: false, evidence: evidence };
1318
+ }
1319
+ var compactEvidence = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray([], __read(evidence), false), __read((libraryPathCount ? ["library_paths=".concat(libraryPathCount)] : [])), false), __read((appOwnedPathCount ? ["app_paths=".concat(appOwnedPathCount)] : [])), false))).slice(0, 8);
1320
+ return {
1321
+ blocked: true,
1322
+ reason: 'Root cause appears to be in shared ResolveIO libraries/templates; app-level auto-fix was blocked.',
1323
+ evidence: compactEvidence
1324
+ };
1325
+ };
1326
+ ErrorAutoFixManager.prototype.sendLibraryIssueNotice = function (log, reason, evidence) {
1327
+ return __awaiter(this, void 0, void 0, function () {
1328
+ var recipients, identifier, subject, body, methodManager, recipients_2, recipients_2_1, recipient, error_2, e_3_1;
1329
+ var e_3, _a;
1330
+ return __generator(this, function (_b) {
1331
+ switch (_b.label) {
1332
+ case 0:
1333
+ recipients = this.getEscalationRecipients();
1334
+ if (!recipients.length || !(log === null || log === void 0 ? void 0 : log._id)) {
1335
+ return [2 /*return*/];
1336
+ }
1337
+ identifier = log.autofix_error_count_string || log._id;
1338
+ subject = "ResolveIO AutoFix Blocked (Library): ".concat(identifier);
1339
+ body = [
1340
+ 'Auto-fix was blocked because the issue appears library-owned, so no autonomous patch was attempted.',
1341
+ '',
1342
+ "Reason: ".concat(reason),
1343
+ evidence.length ? "Evidence: ".concat(evidence.join(', ')) : '',
1344
+ "Issue Log ID: ".concat(log._id),
1345
+ "Issue Counter: ".concat(log.autofix_error_count_string || 'n/a'),
1346
+ "Client: ".concat(log.client_name || log.id_client || 'unknown'),
1347
+ "Source App: ".concat(log.source_app || 'unknown'),
1348
+ "Environment: ".concat(log.source_environment || log.openai_environment || 'unknown'),
1349
+ "Issue Hash: ".concat(log.issue_hash || log.email_hash || 'n/a'),
1350
+ '',
1351
+ 'Manual library release/fix is required. App-level auto-fix remains blocked for this issue to protect credits.'
1352
+ ].filter(Boolean).join('\n');
1353
+ methodManager = resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager();
1354
+ _b.label = 1;
1355
+ case 1:
1356
+ _b.trys.push([1, 8, 9, 10]);
1357
+ recipients_2 = __values(recipients), recipients_2_1 = recipients_2.next();
1358
+ _b.label = 2;
1359
+ case 2:
1360
+ if (!!recipients_2_1.done) return [3 /*break*/, 7];
1361
+ recipient = recipients_2_1.value;
1362
+ _b.label = 3;
1363
+ case 3:
1364
+ _b.trys.push([3, 5, , 6]);
1365
+ return [4 /*yield*/, methodManager.sendEmail(recipient, subject, body)];
1366
+ case 4:
1367
+ _b.sent();
1368
+ return [3 /*break*/, 6];
1369
+ case 5:
1370
+ error_2 = _b.sent();
1371
+ console.error('Failed sending library-issue auto-fix email', { recipient: recipient, logId: log._id, error: error_2 });
1372
+ return [3 /*break*/, 6];
1373
+ case 6:
1374
+ recipients_2_1 = recipients_2.next();
1375
+ return [3 /*break*/, 2];
1376
+ case 7: return [3 /*break*/, 10];
1377
+ case 8:
1378
+ e_3_1 = _b.sent();
1379
+ e_3 = { error: e_3_1 };
1380
+ return [3 /*break*/, 10];
1381
+ case 9:
1382
+ try {
1383
+ if (recipients_2_1 && !recipients_2_1.done && (_a = recipients_2.return)) _a.call(recipients_2);
1384
+ }
1385
+ finally { if (e_3) throw e_3.error; }
1386
+ return [7 /*endfinally*/];
1387
+ case 10: return [2 /*return*/];
1388
+ }
1389
+ });
1390
+ });
1391
+ };
1392
+ ErrorAutoFixManager.prototype.blockLibraryOwnedIssue = function (email, log, gate) {
1393
+ return __awaiter(this, void 0, void 0, function () {
1394
+ var reason, details, message, updated;
1395
+ return __generator(this, function (_a) {
1396
+ switch (_a.label) {
1397
+ case 0:
1398
+ reason = gate.reason || 'Library-owned issue detected.';
1399
+ details = gate.evidence.length ? "Signals: ".concat(gate.evidence.join(', ')) : '';
1400
+ message = [reason, details].filter(Boolean).join(' ');
1401
+ return [4 /*yield*/, this.updateLog(log._id, {
1402
+ status: 'skipped',
1403
+ ignored: true,
1404
+ last_error: message,
1405
+ last_result_at: new Date()
1406
+ })];
1407
+ case 1:
1408
+ updated = (_a.sent()) || log;
1409
+ return [4 /*yield*/, this.notifyCustomerWorkflowStatus('blocked_library_issue', email, updated, {
1410
+ error: reason,
1411
+ notes: details
1412
+ })];
1413
+ case 2:
1414
+ _a.sent();
1415
+ return [4 /*yield*/, this.sendLibraryIssueNotice(updated, reason, gate.evidence)];
1416
+ case 3:
1417
+ _a.sent();
1418
+ return [2 /*return*/, {
1419
+ status: 'skipped',
1420
+ email: email,
1421
+ error: message,
1422
+ log: updated,
1423
+ reason: 'library_issue_blocked',
1424
+ summary: updated.plan_summary || email.subject,
1425
+ notes: details
1426
+ }];
1427
+ }
1428
+ });
1429
+ });
1430
+ };
1431
+ ErrorAutoFixManager.prototype.shouldNotifySkip = function (reason) {
1432
+ return ['in_progress', 'success', 'ignored', 'duplicate', 'pending'].indexOf(reason) === -1;
1433
+ };
1434
+ ErrorAutoFixManager.prototype.isGeneratedAICoderClient = function (idClient) {
1435
+ return __awaiter(this, void 0, void 0, function () {
1436
+ var normalizedClientId, match;
1437
+ return __generator(this, function (_a) {
1438
+ switch (_a.label) {
1439
+ case 0:
1440
+ normalizedClientId = String(idClient || '').trim();
1441
+ if (!normalizedClientId) {
1442
+ return [2 /*return*/, false];
1443
+ }
1444
+ return [4 /*yield*/, AICoderApps.findOne({
1445
+ client_id: normalizedClientId
1446
+ }, {
1447
+ projection: {
1448
+ _id: 1
1449
+ }
1450
+ })];
1451
+ case 1:
1452
+ match = _a.sent();
1453
+ return [2 /*return*/, !!(match === null || match === void 0 ? void 0 : match._id)];
1454
+ }
1455
+ });
1456
+ });
1457
+ };
1458
+ ErrorAutoFixManager.prototype.buildAICoderWorkflowSummary = function (stage, email, log, extra) {
1459
+ return (0, customer_notification_content_manager_1.buildGeneratedAppAutoFixSummary)(stage, {
1460
+ source_app: String((log === null || log === void 0 ? void 0 : log.source_app) || (email === null || email === void 0 ? void 0 : email.sourceApp) || '').trim(),
1461
+ environment: String((log === null || log === void 0 ? void 0 : log.source_environment) || (email === null || email === void 0 ? void 0 : email.sourceEnvironment) || '').trim(),
1462
+ severity: String((log === null || log === void 0 ? void 0 : log.severity) || (email === null || email === void 0 ? void 0 : email.severity) || '').trim(),
1463
+ error: extra === null || extra === void 0 ? void 0 : extra.error
1464
+ }, extra);
1465
+ };
1466
+ ErrorAutoFixManager.prototype.buildResolveIOProjectWorkflowDetails = function (email, log, extra) {
1467
+ return (0, customer_notification_content_manager_1.buildResolveIOProjectAutoFixDetails)({
1468
+ client_name: (log === null || log === void 0 ? void 0 : log.client_name) || (email === null || email === void 0 ? void 0 : email.client_name) || '',
1469
+ issue_counter: (log === null || log === void 0 ? void 0 : log.autofix_error_count_string) || '',
1470
+ source_app: (log === null || log === void 0 ? void 0 : log.source_app) || (email === null || email === void 0 ? void 0 : email.sourceApp) || '',
1471
+ environment: (log === null || log === void 0 ? void 0 : log.source_environment) || (email === null || email === void 0 ? void 0 : email.sourceEnvironment) || (log === null || log === void 0 ? void 0 : log.openai_environment) || '',
1472
+ severity: (log === null || log === void 0 ? void 0 : log.severity) || (email === null || email === void 0 ? void 0 : email.severity) || '',
1473
+ issue_hash: (log === null || log === void 0 ? void 0 : log.issue_hash) || (email === null || email === void 0 ? void 0 : email.issueHash) || (log === null || log === void 0 ? void 0 : log.email_hash) || '',
1474
+ log_id: (log === null || log === void 0 ? void 0 : log._id) || '',
1475
+ notes: extra === null || extra === void 0 ? void 0 : extra.notes,
1476
+ error: extra === null || extra === void 0 ? void 0 : extra.error
1477
+ });
1478
+ };
1479
+ ErrorAutoFixManager.prototype.buildLocalInternalUserCriteria = function () {
1480
+ return {
1481
+ $and: [
1482
+ {
1483
+ is_customer: {
1484
+ $ne: true
1485
+ }
1486
+ },
1487
+ {
1488
+ $nor: [
1489
+ {
1490
+ 'other.id_customer': {
1491
+ $exists: true,
1492
+ $nin: ['', null]
1493
+ }
1494
+ },
1495
+ {
1496
+ id_customer: {
1497
+ $exists: true,
1498
+ $nin: ['', null]
1499
+ }
1500
+ }
1501
+ ]
1502
+ }
1503
+ ]
1504
+ };
1505
+ };
1506
+ ErrorAutoFixManager.prototype.buildLocalAdminUserCriteria = function () {
1507
+ return {
1508
+ $or: [
1509
+ {
1510
+ 'roles.super_admin': true
1511
+ },
1512
+ {
1513
+ 'roles.groups.name': {
1514
+ $regex: 'admin',
1515
+ $options: 'i'
1516
+ }
1517
+ },
1518
+ {
1519
+ 'roles.groups.views': {
1520
+ $regex: '^/manage'
1521
+ }
1522
+ },
1523
+ {
1524
+ 'roles.groups.views': '/manage'
1525
+ }
1526
+ ]
1527
+ };
1528
+ };
1529
+ ErrorAutoFixManager.prototype.resolveLocalNotificationUserIds = function (isGeneratedApp) {
1530
+ return __awaiter(this, void 0, void 0, function () {
1531
+ var andClauses, users, unique, users_1, users_1_1, user, idUser;
1532
+ var e_4, _a;
1533
+ return __generator(this, function (_b) {
1534
+ switch (_b.label) {
1535
+ case 0:
1536
+ andClauses = [
1537
+ {
1538
+ active: true
1539
+ },
1540
+ {
1541
+ username: {
1542
+ $exists: true
1543
+ }
1544
+ }
1545
+ ];
1546
+ if (isGeneratedApp) {
1547
+ andClauses.push(this.buildLocalInternalUserCriteria());
1548
+ }
1549
+ else {
1550
+ andClauses.push(this.buildLocalAdminUserCriteria());
1551
+ }
1552
+ return [4 /*yield*/, user_collection_1.Users.find({
1553
+ $and: andClauses
1554
+ }, {
1555
+ projection: {
1556
+ _id: 1
1557
+ },
1558
+ limit: MAX_LOCAL_NOTIFICATION_USERS
1559
+ })];
1560
+ case 1:
1561
+ users = _b.sent();
1562
+ if (!Array.isArray(users) || !users.length) {
1563
+ return [2 /*return*/, []];
1564
+ }
1565
+ unique = new Set();
1566
+ try {
1567
+ for (users_1 = __values(users), users_1_1 = users_1.next(); !users_1_1.done; users_1_1 = users_1.next()) {
1568
+ user = users_1_1.value;
1569
+ idUser = String((user === null || user === void 0 ? void 0 : user._id) || '').trim();
1570
+ if (idUser) {
1571
+ unique.add(idUser);
1572
+ }
1573
+ if (unique.size >= MAX_LOCAL_NOTIFICATION_USERS) {
1574
+ break;
1575
+ }
1576
+ }
1577
+ }
1578
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
1579
+ finally {
1580
+ try {
1581
+ if (users_1_1 && !users_1_1.done && (_a = users_1.return)) _a.call(users_1);
1582
+ }
1583
+ finally { if (e_4) throw e_4.error; }
1584
+ }
1585
+ return [2 /*return*/, Array.from(unique)];
1586
+ }
1587
+ });
1588
+ });
1589
+ };
1590
+ ErrorAutoFixManager.prototype.notifyCustomerWorkflowStatus = function (stage, email, log, extra) {
1591
+ return __awaiter(this, void 0, void 0, function () {
1592
+ var idClient, isGeneratedApp, resolvedEnvironment, app, issueKey, clientName, targetPayload, idUsers, basePayload, payload, error_3;
1593
+ return __generator(this, function (_a) {
1594
+ switch (_a.label) {
1595
+ case 0:
1596
+ idClient = String((log === null || log === void 0 ? void 0 : log.id_client) || (email === null || email === void 0 ? void 0 : email.id_client) || '').trim();
1597
+ isGeneratedApp = false;
1598
+ if (!idClient) return [3 /*break*/, 2];
1599
+ return [4 /*yield*/, this.isGeneratedAICoderClient(idClient)];
1600
+ case 1:
1601
+ isGeneratedApp = _a.sent();
1602
+ return [3 /*break*/, 4];
1603
+ case 2:
1604
+ resolvedEnvironment = this.resolveEnvironmentForTask(email, log);
1605
+ return [4 /*yield*/, this.resolveAutoFixApp(email, log, resolvedEnvironment)];
1606
+ case 3:
1607
+ app = _a.sent();
1608
+ isGeneratedApp = !!app;
1609
+ _a.label = 4;
1610
+ case 4:
1611
+ if (!isGeneratedApp && stage !== 'completed_success') {
1612
+ return [2 /*return*/];
1613
+ }
1614
+ issueKey = String((log === null || log === void 0 ? void 0 : log.issue_hash) || (log === null || log === void 0 ? void 0 : log.email_hash) || (email === null || email === void 0 ? void 0 : email.issueHash) || (email === null || email === void 0 ? void 0 : email.hash) || (log === null || log === void 0 ? void 0 : log._id) || '').trim();
1615
+ clientName = String((log === null || log === void 0 ? void 0 : log.client_name) || (email === null || email === void 0 ? void 0 : email.client_name) || '').trim();
1616
+ targetPayload = {};
1617
+ if (!idClient) return [3 /*break*/, 5];
1618
+ targetPayload.target_type = isGeneratedApp ? 'client_internal' : 'client_admins';
1619
+ targetPayload.id_client = idClient;
1620
+ targetPayload.client_name = clientName || undefined;
1621
+ return [3 /*break*/, 7];
1622
+ case 5: return [4 /*yield*/, this.resolveLocalNotificationUserIds(isGeneratedApp)];
1623
+ case 6:
1624
+ idUsers = _a.sent();
1625
+ if (!idUsers.length) {
1626
+ return [2 /*return*/];
1627
+ }
1628
+ targetPayload.target_type = 'users';
1629
+ targetPayload.id_users = idUsers;
1630
+ targetPayload.client_name = clientName || undefined;
1631
+ _a.label = 7;
1632
+ case 7:
1633
+ basePayload = __assign(__assign({}, targetPayload), { category: 'autofix', source: 'error-auto-fix', source_id: String((log === null || log === void 0 ? void 0 : log._id) || '').trim() || undefined, dedupe_key: issueKey ? "autofix:".concat(issueKey, ":").concat(stage) : "autofix:".concat(String((log === null || log === void 0 ? void 0 : log._id) || '').trim(), ":").concat(stage), metadata: {
1634
+ issue_hash: (log === null || log === void 0 ? void 0 : log.issue_hash) || (email === null || email === void 0 ? void 0 : email.issueHash) || '',
1635
+ log_id: (log === null || log === void 0 ? void 0 : log._id) || '',
1636
+ severity: (log === null || log === void 0 ? void 0 : log.severity) || (email === null || email === void 0 ? void 0 : email.severity) || '',
1637
+ source_app: (log === null || log === void 0 ? void 0 : log.source_app) || (email === null || email === void 0 ? void 0 : email.sourceApp) || '',
1638
+ source_environment: (log === null || log === void 0 ? void 0 : log.source_environment) || (email === null || email === void 0 ? void 0 : email.sourceEnvironment) || '',
1639
+ error: (extra === null || extra === void 0 ? void 0 : extra.error) || '',
1640
+ notes: (extra === null || extra === void 0 ? void 0 : extra.notes) || ''
1641
+ } });
1642
+ payload = {};
1643
+ if (isGeneratedApp) {
1644
+ if (stage === 'detected_autofix_enabled') {
1645
+ payload = {
1646
+ title: 'Issue detected. Auto-fix is in progress.',
1647
+ message: 'We detected an issue in your app and started an automatic fix workflow. We will notify you when it is complete.',
1648
+ severity: 'info',
1649
+ details: this.buildAICoderWorkflowSummary(stage, email, log, extra)
1650
+ };
1651
+ }
1652
+ else if (stage === 'detected_autofix_disabled') {
1653
+ payload = {
1654
+ title: 'Issue detected. Auto-fix is disabled.',
1655
+ message: 'We detected an issue, but automatic fixing is not enabled. Please ask the AI assistant to investigate this issue.',
1656
+ severity: 'warning',
1657
+ details: this.buildAICoderWorkflowSummary(stage, email, log, extra)
1658
+ };
1659
+ }
1660
+ else if (stage === 'completed_success') {
1661
+ payload = {
1662
+ title: 'Auto-fix completed successfully.',
1663
+ message: 'Your issue was fixed automatically and the update was published.',
1664
+ severity: 'success',
1665
+ details: this.buildAICoderWorkflowSummary(stage, email, log, extra)
1666
+ };
1667
+ }
1668
+ else if (stage === 'blocked_library_issue') {
1669
+ payload = {
1670
+ title: 'Issue requires a platform library update.',
1671
+ message: 'We detected this issue in shared platform libraries, so app auto-fix was stopped. Our engineering team has been notified to ship a library-level fix.',
1672
+ severity: 'warning',
1673
+ details: this.buildAICoderWorkflowSummary(stage, email, log, extra)
1674
+ };
1675
+ }
1676
+ else {
1677
+ payload = {
1678
+ title: 'Auto-fix needs manual review.',
1679
+ message: 'We could not complete an automatic fix for this issue. Manual follow-up is required.',
1680
+ severity: 'warning',
1681
+ details: this.buildAICoderWorkflowSummary(stage, email, log, extra)
1682
+ };
1683
+ }
1684
+ }
1685
+ else {
1686
+ payload = {
1687
+ title: 'ResolveIO project auto-fix completed',
1688
+ message: "A fix for ".concat(String((log === null || log === void 0 ? void 0 : log.source_app) || (email === null || email === void 0 ? void 0 : email.sourceApp) || 'the project').trim(), " completed successfully."),
1689
+ severity: 'success',
1690
+ details: this.buildResolveIOProjectWorkflowDetails(email, log, extra)
1691
+ };
1692
+ }
1693
+ _a.label = 8;
1694
+ case 8:
1695
+ _a.trys.push([8, 10, , 11]);
1696
+ return [4 /*yield*/, resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().callMethod('createCustomerNotification', __assign(__assign({}, basePayload), payload))];
1697
+ case 9:
1698
+ _a.sent();
1699
+ return [3 /*break*/, 11];
1700
+ case 10:
1701
+ error_3 = _a.sent();
1702
+ this.debugLog('Failed to create customer auto-fix notification', {
1703
+ logId: log === null || log === void 0 ? void 0 : log._id,
1704
+ stage: stage,
1705
+ error: (error_3 === null || error_3 === void 0 ? void 0 : error_3.message) || error_3
1706
+ });
1707
+ return [3 /*break*/, 11];
1708
+ case 11: return [2 /*return*/];
1709
+ }
1710
+ });
1711
+ });
1712
+ };
1713
+ ErrorAutoFixManager.prototype.delay = function (ms) {
1714
+ return __awaiter(this, void 0, void 0, function () {
1715
+ return __generator(this, function (_a) {
1716
+ switch (_a.label) {
1717
+ case 0:
1718
+ // eslint-disable-next-line no-restricted-syntax
1719
+ return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, ms); })];
1720
+ case 1:
1721
+ // eslint-disable-next-line no-restricted-syntax
1722
+ _a.sent();
1723
+ return [2 /*return*/];
1724
+ }
1725
+ });
1726
+ });
1727
+ };
1728
+ ErrorAutoFixManager.prototype.reportDevError = function (options) {
1729
+ return __awaiter(this, void 0, void 0, function () {
1730
+ var subject, body, sourceApp, environment, severity, fingerprint, metadata, err_5;
1731
+ return __generator(this, function (_a) {
1732
+ switch (_a.label) {
1733
+ case 0:
1734
+ subject = ((options === null || options === void 0 ? void 0 : options.subject) || '').trim() || 'ResolveIO alert';
1735
+ body = (options === null || options === void 0 ? void 0 : options.body) || '';
1736
+ sourceApp = (options === null || options === void 0 ? void 0 : options.sourceApp) || resolveio_server_app_1.ResolveIOServer.getClientName() || 'resolveio-server';
1737
+ environment = (options === null || options === void 0 ? void 0 : options.environment) || process.env.NODE_ENV || '';
1738
+ severity = (options === null || options === void 0 ? void 0 : options.severity) || 'infrastructure';
1739
+ fingerprint = ((options === null || options === void 0 ? void 0 : options.fingerprint) || (0, crypto_1.createHash)('sha256').update("".concat(sourceApp, ":").concat(environment || 'env', ":").concat(subject)).digest('hex')).trim();
1740
+ metadata = (options === null || options === void 0 ? void 0 : options.metadata) && Object.keys(options.metadata).length ? options.metadata : undefined;
1741
+ if (!this.isReady()) {
1742
+ console.warn('AutoFix manager not ready for dev alert', { subject: subject, environment: environment });
1743
+ return [2 /*return*/];
1744
+ }
1745
+ _a.label = 1;
1746
+ case 1:
1747
+ _a.trys.push([1, 3, , 4]);
1748
+ return [4 /*yield*/, this.ingestErrorReport({
1749
+ sourceApp: sourceApp,
1750
+ environment: environment,
1751
+ message: subject,
1752
+ stack: body,
1753
+ severity: severity,
1754
+ metadata: metadata,
1755
+ fingerprint: fingerprint,
1756
+ idempotencyKey: options === null || options === void 0 ? void 0 : options.idempotencyKey,
1757
+ clientId: options === null || options === void 0 ? void 0 : options.clientId,
1758
+ clientName: options === null || options === void 0 ? void 0 : options.clientName,
1759
+ clientSlug: options === null || options === void 0 ? void 0 : options.clientSlug,
1760
+ reportedBy: 'resolveio-server'
1761
+ })];
1762
+ case 2:
1763
+ _a.sent();
1764
+ return [3 /*break*/, 4];
1765
+ case 3:
1766
+ err_5 = _a.sent();
1767
+ console.error('Failed to log developer alert', subject, err_5);
1768
+ return [3 /*break*/, 4];
1769
+ case 4: return [2 /*return*/];
1770
+ }
1771
+ });
1772
+ });
1773
+ };
1774
+ ErrorAutoFixManager.prototype.ingestErrorReport = function (report) {
1775
+ return __awaiter(this, void 0, void 0, function () {
1776
+ var normalizedReport, email, rawHash, fingerprint, client, reservation, classification, updated, queued, result, finalLog, _a;
1777
+ return __generator(this, function (_b) {
1778
+ switch (_b.label) {
1779
+ case 0:
1780
+ if (!this.isReady()) {
1781
+ throw new Error('ErrorAutoFixManager is not enabled.');
1782
+ }
1783
+ if (!report || !report.sourceApp || !report.message) {
1784
+ throw new Error('Invalid error report payload.');
1785
+ }
1786
+ normalizedReport = __assign(__assign({}, report), { message: (report.message || '').toString(), stack: report.stack ? report.stack.toString() : undefined, metadata: report.metadata || undefined, context: report.context || undefined, attachments: Array.isArray(report.attachments) ? report.attachments : undefined, reportedAt: report.reportedAt instanceof Date && !Number.isNaN(report.reportedAt.getTime()) ? report.reportedAt : new Date() });
1787
+ email = this.buildEmailFromReport(normalizedReport);
1788
+ email.reportedAt = normalizedReport.reportedAt;
1789
+ email.openai_environment = normalizedReport.clientRepo || email.openai_environment;
1790
+ email.fromAddress = this.extractEmailAddress(normalizedReport.clientEmail || normalizedReport.reportedBy || email.from || '');
1791
+ if (!email.fromAddress && normalizedReport.clientSlug) {
1792
+ email.fromAddress = "".concat(normalizedReport.clientSlug, "@errors.resolveio.com");
1793
+ }
1794
+ rawHash = normalizedReport.idempotencyKey ? normalizedReport.idempotencyKey.trim() : '';
1795
+ email.rawHash = rawHash || this.generateRawEmailHash(email);
1796
+ fingerprint = normalizedReport.fingerprint ? normalizedReport.fingerprint.trim() : '';
1797
+ if (fingerprint) {
1798
+ email.issueHash = fingerprint;
1799
+ email.hash = fingerprint;
1800
+ }
1801
+ else {
1802
+ email.issueHash = this.generateIssueHash(email);
1803
+ email.hash = email.issueHash || email.rawHash;
1804
+ }
1805
+ return [4 /*yield*/, this.resolveClientForReport(normalizedReport)];
1806
+ case 1:
1807
+ client = _b.sent();
1808
+ return [4 /*yield*/, this.reserveLog(email, client)];
1809
+ case 2:
1810
+ reservation = _b.sent();
1811
+ if (!!reservation.proceed) return [3 /*break*/, 5];
1812
+ if (!(reservation.reason && this.shouldNotifySkip(reservation.reason))) return [3 /*break*/, 4];
1813
+ return [4 /*yield*/, this.notify({
1814
+ status: 'skipped',
1815
+ email: email,
1816
+ reason: reservation.reason,
1817
+ error: "Skipped auto-fix (".concat(reservation.reason, ")."),
1818
+ log: reservation.log
1819
+ })];
1820
+ case 3:
1821
+ _b.sent();
1822
+ _b.label = 4;
1823
+ case 4: return [2 /*return*/, {
1824
+ status: reservation.reason === 'duplicate' ? 'duplicate' : reservation.reason || 'skipped',
1825
+ reason: reservation.reason,
1826
+ log: reservation.log
1827
+ }];
1828
+ case 5:
1829
+ email.logId = reservation.log._id;
1830
+ classification = this.classifyEmail(email);
1831
+ return [4 /*yield*/, this.updateLog(email.logId, {
1832
+ id_client: client === null || client === void 0 ? void 0 : client._id,
1833
+ client_name: client === null || client === void 0 ? void 0 : client.name,
1834
+ from_email: email.fromAddress,
1835
+ source_type: classification.source,
1836
+ classification_reason: classification.reason || '',
1837
+ openai_environment: email.openai_environment || reservation.log.openai_environment || this.determineOpenAIEnvironment(client),
1838
+ source_app: email.sourceApp,
1839
+ source_environment: email.sourceEnvironment,
1840
+ severity: email.severity,
1841
+ reported_by: email.reportedBy || email.fromAddress,
1842
+ report_metadata: email.reportMetadata,
1843
+ report_context: email.reportContext,
1844
+ attachments: email.attachments,
1845
+ last_reported_at: email.reportedAt || new Date()
1846
+ })];
1847
+ case 6:
1848
+ _b.sent();
1849
+ if (!classification.skip) return [3 /*break*/, 10];
1850
+ return [4 /*yield*/, this.updateLog(email.logId, {
1851
+ status: 'skipped',
1852
+ last_error: classification.reason || 'Ignored non-app alert',
1853
+ last_result_at: new Date()
1854
+ })];
1855
+ case 7:
1856
+ updated = _b.sent();
1857
+ if (!classification.notify) return [3 /*break*/, 9];
1858
+ return [4 /*yield*/, this.notify({
1859
+ status: 'skipped',
1860
+ email: email,
1861
+ error: classification.reason,
1862
+ log: updated,
1863
+ reason: 'classified'
1864
+ })];
1865
+ case 8:
1866
+ _b.sent();
1867
+ _b.label = 9;
1868
+ case 9: return [2 /*return*/, {
1869
+ status: 'skipped',
1870
+ reason: classification.reason,
1871
+ log: updated
1872
+ }];
1873
+ case 10:
1874
+ if (!!this.config.autoRunEnabled) return [3 /*break*/, 13];
1875
+ return [4 /*yield*/, this.updateLog(email.logId, {
1876
+ status: 'pending'
1877
+ })];
1878
+ case 11:
1879
+ queued = _b.sent();
1880
+ return [4 /*yield*/, this.notifyCustomerWorkflowStatus('detected_autofix_disabled', email, queued || reservation.log)];
1881
+ case 12:
1882
+ _b.sent();
1883
+ return [2 /*return*/, {
1884
+ status: 'queued',
1885
+ log: queued
1886
+ }];
1887
+ case 13: return [4 /*yield*/, this.notifyCustomerWorkflowStatus('detected_autofix_enabled', email, reservation.log)];
1888
+ case 14:
1889
+ _b.sent();
1890
+ return [4 /*yield*/, this.processEmail(email, reservation.log)];
1891
+ case 15:
1892
+ result = _b.sent();
1893
+ return [4 /*yield*/, this.notify(result)];
1894
+ case 16:
1895
+ _b.sent();
1896
+ _a = result.log;
1897
+ if (_a) return [3 /*break*/, 18];
1898
+ return [4 /*yield*/, ErrorAutoFixLogs.findOne({ _id: email.logId })];
1899
+ case 17:
1900
+ _a = (_b.sent());
1901
+ _b.label = 18;
1902
+ case 18:
1903
+ finalLog = _a;
1904
+ return [2 /*return*/, {
1905
+ status: result.status,
1906
+ reason: result.reason,
1907
+ log: finalLog || result.log
1908
+ }];
1909
+ }
1910
+ });
1911
+ });
1912
+ };
1913
+ ErrorAutoFixManager.prototype.runLog = function (logId) {
1914
+ return __awaiter(this, void 0, void 0, function () {
1915
+ var log, now, email, inProgressLog, result;
1916
+ return __generator(this, function (_a) {
1917
+ switch (_a.label) {
1918
+ case 0:
1919
+ if (!this.config.enabled) {
1920
+ throw new Error('Auto-fix manager disabled.');
1921
+ }
1922
+ return [4 /*yield*/, ErrorAutoFixLogs.findOne({ _id: logId })];
1923
+ case 1:
1924
+ log = _a.sent();
1925
+ if (!log) {
1926
+ throw new Error('Auto-fix log not found.');
1927
+ }
1928
+ if (log.ignored) {
1929
+ throw new Error('Auto-fix log is ignored.');
1930
+ }
1931
+ if (log.status === 'in_progress') {
1932
+ throw new Error('Auto-fix workflow already running.');
1933
+ }
1934
+ if (!log.body) {
1935
+ throw new Error('Auto-fix log is missing email body.');
1936
+ }
1937
+ now = new Date();
1938
+ email = this.buildEmailFromLog(log);
1939
+ return [4 /*yield*/, ErrorAutoFixLogs.findOneAndUpdate({ _id: logId }, {
1940
+ $inc: {
1941
+ attempt_count: 1
1942
+ },
1943
+ $set: {
1944
+ status: 'in_progress',
1945
+ last_attempt_at: now,
1946
+ last_error: '',
1947
+ ignored: false
1948
+ }
1949
+ }, {
1950
+ returnDocument: 'after'
1951
+ })];
1952
+ case 2:
1953
+ inProgressLog = (_a.sent()) || log;
1954
+ return [4 /*yield*/, this.processEmail(email, inProgressLog)];
1955
+ case 3:
1956
+ result = _a.sent();
1957
+ return [4 /*yield*/, this.notify(result)];
1958
+ case 4:
1959
+ _a.sent();
1960
+ return [2 /*return*/, result];
1961
+ }
1962
+ });
1963
+ });
1964
+ };
1965
+ ErrorAutoFixManager.prototype.buildEmailFromLog = function (log) {
1966
+ return {
1967
+ key: log.message_id || log._id,
1968
+ subject: log.subject,
1969
+ body: log.body || '',
1970
+ messageId: log.message_id,
1971
+ hash: log.issue_hash || log.email_hash,
1972
+ rawHash: log.email_hash,
1973
+ issueHash: log.issue_hash,
1974
+ raw: log.body || '',
1975
+ id_client: log.id_client,
1976
+ client_name: log.client_name,
1977
+ fromAddress: log.from_email,
1978
+ source_type: log.source_type || 'app',
1979
+ classification_reason: log.classification_reason,
1980
+ openai_environment: log.openai_environment,
1981
+ sourceApp: log.source_app,
1982
+ sourceEnvironment: log.source_environment,
1983
+ severity: log.severity,
1984
+ reportedBy: log.reported_by,
1985
+ reportMetadata: log.report_metadata,
1986
+ reportContext: log.report_context,
1987
+ attachments: log.attachments,
1988
+ reportedAt: log.last_reported_at
1989
+ };
1990
+ };
1991
+ ErrorAutoFixManager.prototype.processEmail = function (email, log) {
1992
+ return __awaiter(this, void 0, void 0, function () {
1993
+ var libraryIssueGate, dashboardResult;
1994
+ return __generator(this, function (_a) {
1995
+ switch (_a.label) {
1996
+ case 0:
1997
+ libraryIssueGate = this.evaluateLibraryIssueGate(email, log);
1998
+ if (!libraryIssueGate.blocked) return [3 /*break*/, 2];
1999
+ return [4 /*yield*/, this.blockLibraryOwnedIssue(email, log, libraryIssueGate)];
2000
+ case 1: return [2 /*return*/, _a.sent()];
2001
+ case 2:
2002
+ if (!this.config.dashboardWorkflowEnabled) return [3 /*break*/, 4];
2003
+ return [4 /*yield*/, this.dispatchDashboardWorkflow(email, log)];
2004
+ case 3:
2005
+ dashboardResult = _a.sent();
2006
+ if (dashboardResult.status === 'in_progress' || dashboardResult.status === 'success') {
2007
+ return [2 /*return*/, dashboardResult];
2008
+ }
2009
+ if (!this.config.dashboardFallbackToGithub) {
2010
+ return [2 /*return*/, dashboardResult];
2011
+ }
2012
+ this.debugLog('Dashboard workflow unavailable; falling back to GitHub workflow.', {
2013
+ logId: log === null || log === void 0 ? void 0 : log._id,
2014
+ reason: dashboardResult.reason,
2015
+ error: dashboardResult.error
2016
+ });
2017
+ _a.label = 4;
2018
+ case 4: return [4 /*yield*/, this.dispatchGithubWorkflow(email, log)];
2019
+ case 5: return [2 /*return*/, _a.sent()];
2020
+ }
2021
+ });
2022
+ });
2023
+ };
2024
+ ErrorAutoFixManager.prototype.shouldFallbackDashboardMethod = function (error) {
2025
+ var message = "".concat((error === null || error === void 0 ? void 0 : error.message) || '').toLowerCase();
2026
+ return message.includes('not found')
2027
+ || message.includes('worker dispatch unavailable')
2028
+ || message.includes('no worker')
2029
+ || message.includes('unavailable for aidashboard');
2030
+ };
2031
+ ErrorAutoFixManager.prototype.createDashboardJob = function (payload) {
2032
+ return __awaiter(this, void 0, void 0, function () {
2033
+ var methodManager, error_4, manager;
2034
+ return __generator(this, function (_a) {
2035
+ switch (_a.label) {
2036
+ case 0:
2037
+ methodManager = resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager();
2038
+ _a.label = 1;
2039
+ case 1:
2040
+ _a.trys.push([1, 3, , 4]);
2041
+ return [4 /*yield*/, methodManager.callMethod('aiDashboardCreateJob', payload)];
2042
+ case 2: return [2 /*return*/, _a.sent()];
2043
+ case 3:
2044
+ error_4 = _a.sent();
2045
+ if (!this.shouldFallbackDashboardMethod(error_4)) {
2046
+ throw error_4;
2047
+ }
2048
+ return [3 /*break*/, 4];
2049
+ case 4:
2050
+ manager = resolveio_server_app_1.ResolveIOServer['AIDashboardManager'];
2051
+ if (!(manager && manager.isEnabled && manager.isEnabled())) return [3 /*break*/, 6];
2052
+ return [4 /*yield*/, manager.createJob(payload)];
2053
+ case 5: return [2 /*return*/, _a.sent()];
2054
+ case 6: throw new Error('AI Dashboard manager is not available.');
2055
+ }
2056
+ });
2057
+ });
2058
+ };
2059
+ ErrorAutoFixManager.prototype.waitForDashboardJobStop = function (jobId, timeoutMs) {
2060
+ return __awaiter(this, void 0, void 0, function () {
2061
+ var methodManager, error_5, manager;
2062
+ return __generator(this, function (_a) {
2063
+ switch (_a.label) {
2064
+ case 0:
2065
+ methodManager = resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager();
2066
+ _a.label = 1;
2067
+ case 1:
2068
+ _a.trys.push([1, 3, , 4]);
2069
+ return [4 /*yield*/, methodManager.callMethod('aiDashboardWaitForJobStop', jobId, timeoutMs)];
2070
+ case 2:
2071
+ _a.sent();
2072
+ return [2 /*return*/];
2073
+ case 3:
2074
+ error_5 = _a.sent();
2075
+ if (!this.shouldFallbackDashboardMethod(error_5)) {
2076
+ throw error_5;
2077
+ }
2078
+ return [3 /*break*/, 4];
2079
+ case 4:
2080
+ manager = resolveio_server_app_1.ResolveIOServer['AIDashboardManager'];
2081
+ if (!(manager && manager.isEnabled && manager.isEnabled())) return [3 /*break*/, 6];
2082
+ return [4 /*yield*/, manager.waitForJobStop(jobId, timeoutMs)];
2083
+ case 5:
2084
+ _a.sent();
2085
+ return [2 /*return*/];
2086
+ case 6: throw new Error('AI Dashboard manager is not available.');
2087
+ }
2088
+ });
2089
+ });
2090
+ };
2091
+ ErrorAutoFixManager.prototype.isDashboardJobRunning = function (jobId) {
2092
+ return __awaiter(this, void 0, void 0, function () {
2093
+ var methodManager, running, error_6, manager;
2094
+ return __generator(this, function (_a) {
2095
+ switch (_a.label) {
2096
+ case 0:
2097
+ methodManager = resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager();
2098
+ _a.label = 1;
2099
+ case 1:
2100
+ _a.trys.push([1, 3, , 4]);
2101
+ return [4 /*yield*/, methodManager.callMethod('aiDashboardIsJobRunning', jobId)];
2102
+ case 2:
2103
+ running = _a.sent();
2104
+ return [2 /*return*/, !!running];
2105
+ case 3:
2106
+ error_6 = _a.sent();
2107
+ if (!this.shouldFallbackDashboardMethod(error_6)) {
2108
+ throw error_6;
2109
+ }
2110
+ return [3 /*break*/, 4];
2111
+ case 4:
2112
+ manager = resolveio_server_app_1.ResolveIOServer['AIDashboardManager'];
2113
+ if (manager && manager.isEnabled && manager.isEnabled()) {
2114
+ return [2 /*return*/, !!manager.isJobRunning(jobId)];
2115
+ }
2116
+ throw new Error('AI Dashboard manager is not available.');
2117
+ }
2118
+ });
2119
+ });
2120
+ };
2121
+ ErrorAutoFixManager.prototype.resolveAutoFixApp = function (email, log, resolvedEnvironment) {
2122
+ return __awaiter(this, void 0, void 0, function () {
2123
+ var clientId, byClientId, lookupClientCandidates, lookupClientCandidates_1, lookupClientCandidates_1_1, candidate, escaped, clientDoc, byClient, e_5_1, environmentRepo, escapedRepo, byRepo, appNameCandidates, appNameCandidates_1, appNameCandidates_1_1, candidate, escaped, bySlugOrName, e_6_1;
2124
+ var e_5, _a, e_6, _b;
2125
+ return __generator(this, function (_c) {
2126
+ switch (_c.label) {
2127
+ case 0:
2128
+ clientId = (email.id_client || log.id_client || '').trim();
2129
+ if (!clientId) return [3 /*break*/, 2];
2130
+ return [4 /*yield*/, AICoderApps.findOne({ client_id: clientId }, {
2131
+ sort: {
2132
+ updatedAt: -1,
2133
+ createdAt: -1
2134
+ }
2135
+ })];
2136
+ case 1:
2137
+ byClientId = _c.sent();
2138
+ if (byClientId) {
2139
+ return [2 /*return*/, byClientId];
2140
+ }
2141
+ _c.label = 2;
2142
+ case 2:
2143
+ lookupClientCandidates = [
2144
+ (email.client_name || '').trim(),
2145
+ (log.client_name || '').trim()
2146
+ ].filter(Boolean);
2147
+ _c.label = 3;
2148
+ case 3:
2149
+ _c.trys.push([3, 9, 10, 11]);
2150
+ lookupClientCandidates_1 = __values(lookupClientCandidates), lookupClientCandidates_1_1 = lookupClientCandidates_1.next();
2151
+ _c.label = 4;
2152
+ case 4:
2153
+ if (!!lookupClientCandidates_1_1.done) return [3 /*break*/, 8];
2154
+ candidate = lookupClientCandidates_1_1.value;
2155
+ escaped = this.escapeRegex(candidate);
2156
+ return [4 /*yield*/, Clients.findOne({
2157
+ $or: [
2158
+ { name: { $regex: "^".concat(escaped, "$"), $options: 'i' } },
2159
+ { demo_name: { $regex: "^".concat(escaped, "$"), $options: 'i' } },
2160
+ { repo: { $regex: "^".concat(escaped, "$"), $options: 'i' } }
2161
+ ]
2162
+ })];
2163
+ case 5:
2164
+ clientDoc = _c.sent();
2165
+ if (!(clientDoc === null || clientDoc === void 0 ? void 0 : clientDoc._id)) {
2166
+ return [3 /*break*/, 7];
2167
+ }
2168
+ return [4 /*yield*/, AICoderApps.findOne({ client_id: clientDoc._id }, {
2169
+ sort: {
2170
+ updatedAt: -1,
2171
+ createdAt: -1
2172
+ }
2173
+ })];
2174
+ case 6:
2175
+ byClient = _c.sent();
2176
+ if (byClient) {
2177
+ return [2 /*return*/, byClient];
2178
+ }
2179
+ _c.label = 7;
2180
+ case 7:
2181
+ lookupClientCandidates_1_1 = lookupClientCandidates_1.next();
2182
+ return [3 /*break*/, 4];
2183
+ case 8: return [3 /*break*/, 11];
2184
+ case 9:
2185
+ e_5_1 = _c.sent();
2186
+ e_5 = { error: e_5_1 };
2187
+ return [3 /*break*/, 11];
2188
+ case 10:
2189
+ try {
2190
+ if (lookupClientCandidates_1_1 && !lookupClientCandidates_1_1.done && (_a = lookupClientCandidates_1.return)) _a.call(lookupClientCandidates_1);
2191
+ }
2192
+ finally { if (e_5) throw e_5.error; }
2193
+ return [7 /*endfinally*/];
2194
+ case 11:
2195
+ environmentRepo = (resolvedEnvironment || '').trim();
2196
+ if (!environmentRepo) return [3 /*break*/, 13];
2197
+ escapedRepo = this.escapeRegex(environmentRepo);
2198
+ return [4 /*yield*/, AICoderApps.findOne({
2199
+ repo: {
2200
+ $regex: "^".concat(escapedRepo, "$"),
2201
+ $options: 'i'
2202
+ }
2203
+ }, {
2204
+ sort: {
2205
+ updatedAt: -1,
2206
+ createdAt: -1
2207
+ }
2208
+ })];
2209
+ case 12:
2210
+ byRepo = _c.sent();
2211
+ if (byRepo) {
2212
+ return [2 /*return*/, byRepo];
2213
+ }
2214
+ _c.label = 13;
2215
+ case 13:
2216
+ appNameCandidates = [
2217
+ (email.sourceApp || '').trim(),
2218
+ (log.source_app || '').trim()
2219
+ ].filter(Boolean);
2220
+ _c.label = 14;
2221
+ case 14:
2222
+ _c.trys.push([14, 19, 20, 21]);
2223
+ appNameCandidates_1 = __values(appNameCandidates), appNameCandidates_1_1 = appNameCandidates_1.next();
2224
+ _c.label = 15;
2225
+ case 15:
2226
+ if (!!appNameCandidates_1_1.done) return [3 /*break*/, 18];
2227
+ candidate = appNameCandidates_1_1.value;
2228
+ escaped = this.escapeRegex(candidate);
2229
+ return [4 /*yield*/, AICoderApps.findOne({
2230
+ $or: [
2231
+ { slug: { $regex: "^".concat(escaped, "$"), $options: 'i' } },
2232
+ { name: { $regex: "^".concat(escaped, "$"), $options: 'i' } }
2233
+ ]
2234
+ }, {
2235
+ sort: {
2236
+ updatedAt: -1,
2237
+ createdAt: -1
2238
+ }
2239
+ })];
2240
+ case 16:
2241
+ bySlugOrName = _c.sent();
2242
+ if (bySlugOrName) {
2243
+ return [2 /*return*/, bySlugOrName];
2244
+ }
2245
+ _c.label = 17;
2246
+ case 17:
2247
+ appNameCandidates_1_1 = appNameCandidates_1.next();
2248
+ return [3 /*break*/, 15];
2249
+ case 18: return [3 /*break*/, 21];
2250
+ case 19:
2251
+ e_6_1 = _c.sent();
2252
+ e_6 = { error: e_6_1 };
2253
+ return [3 /*break*/, 21];
2254
+ case 20:
2255
+ try {
2256
+ if (appNameCandidates_1_1 && !appNameCandidates_1_1.done && (_b = appNameCandidates_1.return)) _b.call(appNameCandidates_1);
2257
+ }
2258
+ finally { if (e_6) throw e_6.error; }
2259
+ return [7 /*endfinally*/];
2260
+ case 21: return [2 /*return*/, null];
2261
+ }
2262
+ });
2263
+ });
2264
+ };
2265
+ ErrorAutoFixManager.prototype.buildDashboardAutoFixTitle = function (email, log, app) {
2266
+ var identifier = log.autofix_error_count_string || (log._id || '').slice(-6) || 'error';
2267
+ var source = (email.sourceApp || log.source_app || (app === null || app === void 0 ? void 0 : app.name) || 'application').trim();
2268
+ return "Auto-fix ".concat(identifier, ": ").concat(source);
2269
+ };
2270
+ ErrorAutoFixManager.prototype.buildDashboardAutoFixDescription = function (email, log, app) {
2271
+ var normalizedBody = this.normalizeEmailText(email.body || log.body || '', 15000);
2272
+ var metadata = log.report_metadata && Object.keys(log.report_metadata).length
2273
+ ? JSON.stringify(log.report_metadata, null, 2)
2274
+ : '';
2275
+ var context = log.report_context && Object.keys(log.report_context).length
2276
+ ? JSON.stringify(log.report_context, null, 2)
2277
+ : '';
2278
+ var attachments = Array.isArray(log.attachments) ? log.attachments : [];
2279
+ var attachmentLines = attachments.length
2280
+ ? attachments.map(function (att) { return "- ".concat(((att === null || att === void 0 ? void 0 : att.name) || 'attachment').trim(), " ").concat((att === null || att === void 0 ? void 0 : att.url) ? "(".concat(att.url, ")") : '').trim(); }).join('\n')
2281
+ : '(none)';
2282
+ var lines = [
2283
+ 'Autonomous production error remediation request.',
2284
+ '',
2285
+ 'Hard requirements:',
2286
+ '1. Before changing code, query the project MongoDB diagnostics logs for the latest context.',
2287
+ '2. Query `error-autofix-logs` using `_id`, `issue_hash`, and `email_hash` from this task, then use the newest matching records.',
2288
+ '3. If a previous dashboard job id is provided, query `ai-development-jobs` by that `_id` and review recent failure logs before retrying.',
2289
+ '4. Treat `.dashboard-output/build-*.log` as primary build evidence, and `.build-output/build-*.log` as retained history when diagnosing failures.',
2290
+ '5. Reproduce and fix the reported issue with the smallest safe code change.',
2291
+ '6. Keep query/result behavior backward compatible unless explicitly required by the bug fix.',
2292
+ '7. Run project build checks and continue iterating until the build is green.',
2293
+ '8. Ensure there are no new lint/type/runtime regressions introduced by the fix.',
2294
+ '9. Finish by publishing the passing fix to the default branch and deploying artifacts.',
2295
+ '',
2296
+ "App: ".concat((app === null || app === void 0 ? void 0 : app.name) || (app === null || app === void 0 ? void 0 : app._id) || 'unknown'),
2297
+ "Repo: ".concat((app === null || app === void 0 ? void 0 : app.repo) || 'unknown'),
2298
+ "Environment: ".concat(email.sourceEnvironment || log.source_environment || 'unknown'),
2299
+ "Severity: ".concat(email.severity || log.severity || 'error'),
2300
+ "Fingerprint: ".concat(email.issueHash || log.issue_hash || log.email_hash || 'n/a'),
2301
+ "Error Log Id: ".concat(String((log === null || log === void 0 ? void 0 : log._id) || '').trim() || 'n/a'),
2302
+ "Previous Dashboard Job Id: ".concat(String((log === null || log === void 0 ? void 0 : log.openai_task_id) || '').trim() || 'n/a'),
2303
+ '',
2304
+ 'Reported error payload:',
2305
+ '```',
2306
+ normalizedBody || '(empty error body)',
2307
+ '```',
2308
+ '',
2309
+ 'Attachments:',
2310
+ attachmentLines
2311
+ ];
2312
+ if (metadata) {
2313
+ lines.push('', 'Metadata JSON:', '```json', metadata, '```');
2314
+ }
2315
+ if (context) {
2316
+ lines.push('', 'Context JSON:', '```json', context, '```');
2317
+ }
2318
+ return lines.join('\n');
2319
+ };
2320
+ ErrorAutoFixManager.prototype.evaluateDashboardPublishOutcome = function (job) {
2321
+ var logEntries = Array.isArray(job === null || job === void 0 ? void 0 : job.log) ? job.log : [];
2322
+ var lastMatch = function (predicate) {
2323
+ for (var i = logEntries.length - 1; i >= 0; i -= 1) {
2324
+ if (predicate(logEntries[i] || '')) {
2325
+ return logEntries[i];
2326
+ }
2327
+ }
2328
+ return '';
2329
+ };
2330
+ var failureEntry = lastMatch(function (entry) { return /publish failed|artifact publish failed|deploy failed/i.test(entry || ''); });
2331
+ if (failureEntry) {
2332
+ return {
2333
+ success: false,
2334
+ message: failureEntry
2335
+ };
2336
+ }
2337
+ var publishEntry = lastMatch(function (entry) { return /Published build to /i.test(entry || ''); });
2338
+ if (publishEntry) {
2339
+ var branchMatch = publishEntry.match(/\(([^()]+)\)\.?$/);
2340
+ return {
2341
+ success: true,
2342
+ branchName: (branchMatch && branchMatch[1]) ? branchMatch[1].trim() : undefined,
2343
+ message: publishEntry
2344
+ };
2345
+ }
2346
+ var skippedEntry = lastMatch(function (entry) { return /Publish skipped/i.test(entry || ''); });
2347
+ if (skippedEntry) {
2348
+ return {
2349
+ success: !this.config.dashboardPublishRequired,
2350
+ message: skippedEntry
2351
+ };
2352
+ }
2353
+ return {
2354
+ success: !this.config.dashboardPublishRequired,
2355
+ message: 'Dashboard job completed without a publish confirmation log entry.'
2356
+ };
2357
+ };
2358
+ ErrorAutoFixManager.prototype.queueDashboardMonitor = function (log, email, jobId, effectiveEnvironment) {
2359
+ var _this = this;
2360
+ var logId = ((log === null || log === void 0 ? void 0 : log._id) || '').trim();
2361
+ var normalizedJobId = (jobId || '').trim();
2362
+ if (!logId || !normalizedJobId) {
2363
+ return;
2364
+ }
2365
+ if (this.dashboardMonitors.has(logId)) {
2366
+ return;
2367
+ }
2368
+ var monitor = (function () { return __awaiter(_this, void 0, void 0, function () {
2369
+ var error_7;
2370
+ return __generator(this, function (_a) {
2371
+ switch (_a.label) {
2372
+ case 0:
2373
+ _a.trys.push([0, 2, 3, 4]);
2374
+ return [4 /*yield*/, this.monitorDashboardAutoFixJob(log, email, normalizedJobId, effectiveEnvironment)];
2375
+ case 1:
2376
+ _a.sent();
2377
+ return [3 /*break*/, 4];
2378
+ case 2:
2379
+ error_7 = _a.sent();
2380
+ console.error('Auto-fix dashboard monitor failed', { logId: logId, jobId: normalizedJobId, error: error_7 });
2381
+ return [3 /*break*/, 4];
2382
+ case 3:
2383
+ this.dashboardMonitors.delete(logId);
2384
+ return [7 /*endfinally*/];
2385
+ case 4: return [2 /*return*/];
2386
+ }
2387
+ });
2388
+ }); })();
2389
+ this.dashboardMonitors.set(logId, monitor);
2390
+ };
2391
+ ErrorAutoFixManager.prototype.monitorDashboardAutoFixJob = function (log, email, jobId, effectiveEnvironment) {
2392
+ return __awaiter(this, void 0, void 0, function () {
2393
+ var logId, fail, error_8, message, isRunning, error_9, message, job, publishOutcome, fallbackBranch, branchName, successLog;
2394
+ var _this = this;
2395
+ var _a;
2396
+ return __generator(this, function (_b) {
2397
+ switch (_b.label) {
2398
+ case 0:
2399
+ logId = ((log === null || log === void 0 ? void 0 : log._id) || '').trim();
2400
+ if (!logId) {
2401
+ return [2 /*return*/];
2402
+ }
2403
+ fail = function (message) { return __awaiter(_this, void 0, void 0, function () {
2404
+ var failedLog;
2405
+ return __generator(this, function (_a) {
2406
+ switch (_a.label) {
2407
+ case 0: return [4 /*yield*/, this.updateLog(logId, {
2408
+ status: 'failed',
2409
+ last_error: message,
2410
+ last_result_at: new Date(),
2411
+ openai_task_id: jobId,
2412
+ openai_environment: effectiveEnvironment
2413
+ })];
2414
+ case 1:
2415
+ failedLog = (_a.sent()) || log;
2416
+ return [4 /*yield*/, this.notifyCustomerWorkflowStatus('completed_failed', email, failedLog, { error: message })];
2417
+ case 2:
2418
+ _a.sent();
2419
+ return [4 /*yield*/, this.notify({
2420
+ status: 'failed',
2421
+ email: email,
2422
+ error: message,
2423
+ log: failedLog,
2424
+ summary: failedLog.plan_summary || email.subject
2425
+ })];
2426
+ case 3:
2427
+ _a.sent();
2428
+ return [2 /*return*/];
2429
+ }
2430
+ });
2431
+ }); };
2432
+ _b.label = 1;
2433
+ case 1:
2434
+ _b.trys.push([1, 3, , 5]);
2435
+ return [4 /*yield*/, this.waitForDashboardJobStop(jobId, this.config.dashboardWaitTimeoutMs)];
2436
+ case 2:
2437
+ _b.sent();
2438
+ return [3 /*break*/, 5];
2439
+ case 3:
2440
+ error_8 = _b.sent();
2441
+ message = (error_8 === null || error_8 === void 0 ? void 0 : error_8.message) || 'Failed while waiting for dashboard job completion.';
2442
+ return [4 /*yield*/, fail(message)];
2443
+ case 4:
2444
+ _b.sent();
2445
+ return [2 /*return*/];
2446
+ case 5:
2447
+ isRunning = false;
2448
+ _b.label = 6;
2449
+ case 6:
2450
+ _b.trys.push([6, 8, , 10]);
2451
+ return [4 /*yield*/, this.isDashboardJobRunning(jobId)];
2452
+ case 7:
2453
+ isRunning = _b.sent();
2454
+ return [3 /*break*/, 10];
2455
+ case 8:
2456
+ error_9 = _b.sent();
2457
+ message = (error_9 === null || error_9 === void 0 ? void 0 : error_9.message) || 'Unable to confirm dashboard job completion state.';
2458
+ return [4 /*yield*/, fail(message)];
2459
+ case 9:
2460
+ _b.sent();
2461
+ return [2 /*return*/];
2462
+ case 10:
2463
+ if (!isRunning) return [3 /*break*/, 12];
2464
+ return [4 /*yield*/, fail("Dashboard job ".concat(jobId, " timed out before completion."))];
2465
+ case 11:
2466
+ _b.sent();
2467
+ return [2 /*return*/];
2468
+ case 12: return [4 /*yield*/, AIDashboardJobs.findOne({ _id: jobId })];
2469
+ case 13:
2470
+ job = _b.sent();
2471
+ if (!!job) return [3 /*break*/, 15];
2472
+ return [4 /*yield*/, fail("Dashboard job ".concat(jobId, " not found."))];
2473
+ case 14:
2474
+ _b.sent();
2475
+ return [2 /*return*/];
2476
+ case 15:
2477
+ if (!(job.phase !== 'COMPLETE' || job.paused)) return [3 /*break*/, 17];
2478
+ return [4 /*yield*/, fail("Dashboard job ".concat(jobId, " ended in phase ").concat(job.phase || 'unknown').concat(job.paused ? ' (paused)' : '', "."))];
2479
+ case 16:
2480
+ _b.sent();
2481
+ return [2 /*return*/];
2482
+ case 17:
2483
+ publishOutcome = this.evaluateDashboardPublishOutcome(job);
2484
+ if (!!publishOutcome.success) return [3 /*break*/, 19];
2485
+ return [4 /*yield*/, fail(publishOutcome.message)];
2486
+ case 18:
2487
+ _b.sent();
2488
+ return [2 /*return*/];
2489
+ case 19:
2490
+ fallbackBranch = (String(((_a = this._serverConfig) === null || _a === void 0 ? void 0 : _a['GITHUB_DEFAULT_BRANCH']) || process.env.GITHUB_DEFAULT_BRANCH || 'main').trim() || 'main');
2491
+ branchName = publishOutcome.branchName || fallbackBranch;
2492
+ return [4 /*yield*/, this.updateLog(logId, {
2493
+ status: 'success',
2494
+ branch_name: branchName,
2495
+ pr_url: '',
2496
+ last_error: '',
2497
+ last_result_at: new Date(),
2498
+ openai_task_id: jobId,
2499
+ openai_environment: effectiveEnvironment
2500
+ })];
2501
+ case 20:
2502
+ successLog = (_b.sent()) || log;
2503
+ return [4 /*yield*/, this.notifyCustomerWorkflowStatus('completed_success', email, successLog, { notes: publishOutcome.message })];
2504
+ case 21:
2505
+ _b.sent();
2506
+ return [4 /*yield*/, this.notify({
2507
+ status: 'success',
2508
+ email: email,
2509
+ branchName: branchName,
2510
+ log: successLog,
2511
+ summary: successLog.plan_summary || email.subject,
2512
+ notes: publishOutcome.message
2513
+ })];
2514
+ case 22:
2515
+ _b.sent();
2516
+ return [2 /*return*/];
2517
+ }
2518
+ });
2519
+ });
2520
+ };
2521
+ ErrorAutoFixManager.prototype.dispatchDashboardWorkflow = function (email, log) {
2522
+ return __awaiter(this, void 0, void 0, function () {
2523
+ var fail, openaiEnvironment, app, repo, effectiveEnvironment, emailHash, rawHash, title, description, job, error_10, message, jobId, queuedLog;
2524
+ var _this = this;
2525
+ return __generator(this, function (_a) {
2526
+ switch (_a.label) {
2527
+ case 0:
2528
+ fail = function (status, reason, message) { return __awaiter(_this, void 0, void 0, function () {
2529
+ var updated;
2530
+ return __generator(this, function (_a) {
2531
+ switch (_a.label) {
2532
+ case 0: return [4 /*yield*/, this.updateLog(log._id, {
2533
+ status: status,
2534
+ last_error: message,
2535
+ last_result_at: new Date()
2536
+ })];
2537
+ case 1:
2538
+ updated = (_a.sent()) || log;
2539
+ return [2 /*return*/, {
2540
+ status: status,
2541
+ email: email,
2542
+ error: message,
2543
+ log: updated,
2544
+ reason: reason
2545
+ }];
2546
+ }
2547
+ });
2548
+ }); };
2549
+ openaiEnvironment = this.resolveEnvironmentForTask(email, log);
2550
+ return [4 /*yield*/, this.resolveAutoFixApp(email, log, openaiEnvironment)];
2551
+ case 1:
2552
+ app = _a.sent();
2553
+ if (!!(app === null || app === void 0 ? void 0 : app._id)) return [3 /*break*/, 3];
2554
+ return [4 /*yield*/, fail('skipped', 'dashboard_app_not_found', 'No AI Coder app found for this error log.')];
2555
+ case 2: return [2 /*return*/, _a.sent()];
2556
+ case 3:
2557
+ repo = (app.repo || '').trim();
2558
+ if (!!repo) return [3 /*break*/, 5];
2559
+ return [4 /*yield*/, fail('skipped', 'dashboard_repo_missing', 'Resolved AI Coder app is missing repo configuration.')];
2560
+ case 4: return [2 /*return*/, _a.sent()];
2561
+ case 5:
2562
+ effectiveEnvironment = repo;
2563
+ emailHash = email.issueHash || email.hash || this.generateIssueHash(email);
2564
+ rawHash = email.rawHash || this.generateRawEmailHash(email);
2565
+ title = this.buildDashboardAutoFixTitle(email, log, app);
2566
+ description = this.buildDashboardAutoFixDescription(email, log, app);
2567
+ _a.label = 6;
2568
+ case 6:
2569
+ _a.trys.push([6, 8, , 10]);
2570
+ return [4 /*yield*/, this.createDashboardJob({
2571
+ project: app._id,
2572
+ title: title,
2573
+ description: description,
2574
+ repo: repo,
2575
+ path: app.git_local_path || undefined,
2576
+ projectRoot: app.project_root || undefined
2577
+ })];
2578
+ case 7:
2579
+ job = _a.sent();
2580
+ return [3 /*break*/, 10];
2581
+ case 8:
2582
+ error_10 = _a.sent();
2583
+ message = (error_10 === null || error_10 === void 0 ? void 0 : error_10.message) || 'Unable to enqueue dashboard auto-fix job.';
2584
+ return [4 /*yield*/, fail('failed', 'dashboard_job_create_failed', message)];
2585
+ case 9: return [2 /*return*/, _a.sent()];
2586
+ case 10:
2587
+ jobId = ((job === null || job === void 0 ? void 0 : job._id) || '').trim();
2588
+ if (!!jobId) return [3 /*break*/, 12];
2589
+ return [4 /*yield*/, fail('failed', 'dashboard_job_missing_id', 'Dashboard job created without an id.')];
2590
+ case 11: return [2 /*return*/, _a.sent()];
2591
+ case 12: return [4 /*yield*/, this.updateLog(log._id, {
2592
+ status: 'in_progress',
2593
+ last_attempt_at: new Date(),
2594
+ branch_name: '',
2595
+ pr_url: '',
2596
+ last_error: '',
2597
+ openai_environment: effectiveEnvironment,
2598
+ issue_hash: emailHash,
2599
+ email_hash: rawHash,
2600
+ openai_task_id: jobId,
2601
+ plan_summary: title,
2602
+ plan_body: description
2603
+ })];
2604
+ case 13:
2605
+ queuedLog = (_a.sent()) || log;
2606
+ this.queueDashboardMonitor(queuedLog, email, jobId, effectiveEnvironment);
2607
+ return [2 /*return*/, {
2608
+ status: 'in_progress',
2609
+ email: email,
2610
+ log: queuedLog,
2611
+ reason: 'dashboard_job_queued',
2612
+ summary: title,
2613
+ notes: "Dashboard job ".concat(jobId, " queued for autonomous build/fix/publish/deploy.")
2614
+ }];
2615
+ }
2616
+ });
2617
+ });
2618
+ };
2619
+ ErrorAutoFixManager.prototype.dispatchGithubWorkflow = function (email, log) {
2620
+ return __awaiter(this, void 0, void 0, function () {
2621
+ var openaiEnvironment, fallbackEnv, resolvedEnvironment, repoTarget, updated, updated, effectiveEnv, emailHash, rawHash, workBranch, contextIdentifier, contextPath, normalizedBody, contextContent, commentBody, baseBranch, baseSha, pr, title, bodyLines, updated, err_6, message, updated;
2622
+ return __generator(this, function (_a) {
2623
+ switch (_a.label) {
2624
+ case 0:
2625
+ openaiEnvironment = this.resolveEnvironmentForTask(email, log);
2626
+ fallbackEnv = this.config.githubOwner && this.config.githubRepo ? "".concat(this.config.githubOwner, "/").concat(this.config.githubRepo) : '';
2627
+ resolvedEnvironment = (openaiEnvironment || fallbackEnv || '').trim();
2628
+ repoTarget = this.parseRepoTarget(resolvedEnvironment) || this.parseRepoTarget(fallbackEnv);
2629
+ this.debugLog('Starting GitHub PR workflow.', {
2630
+ emailKey: email.key,
2631
+ logId: log._id,
2632
+ openaiEnvironment: resolvedEnvironment,
2633
+ repoTarget: repoTarget
2634
+ });
2635
+ if (!!this.config.githubToken) return [3 /*break*/, 2];
2636
+ return [4 /*yield*/, this.updateLog(log._id, {
2637
+ status: 'skipped',
2638
+ last_error: 'GitHub token not configured',
2639
+ last_result_at: new Date(),
2640
+ id_client: email.id_client,
2641
+ client_name: email.client_name,
2642
+ from_email: email.fromAddress,
2643
+ source_type: email.source_type,
2644
+ classification_reason: email.classification_reason || '',
2645
+ openai_environment: resolvedEnvironment
2646
+ })];
2647
+ case 1:
2648
+ updated = (_a.sent()) || log;
2649
+ return [2 /*return*/, {
2650
+ status: 'skipped',
2651
+ email: email,
2652
+ error: 'GitHub token not configured',
2653
+ log: updated,
2654
+ reason: 'missing_github_token'
2655
+ }];
2656
+ case 2:
2657
+ if (!!repoTarget) return [3 /*break*/, 4];
2658
+ return [4 /*yield*/, this.updateLog(log._id, {
2659
+ status: 'skipped',
2660
+ last_error: 'GitHub repository not configured',
2661
+ last_result_at: new Date(),
2662
+ id_client: email.id_client,
2663
+ client_name: email.client_name,
2664
+ from_email: email.fromAddress,
2665
+ source_type: email.source_type,
2666
+ classification_reason: email.classification_reason || '',
2667
+ openai_environment: resolvedEnvironment
2668
+ })];
2669
+ case 3:
2670
+ updated = (_a.sent()) || log;
2671
+ return [2 /*return*/, {
2672
+ status: 'skipped',
2673
+ email: email,
2674
+ error: 'GitHub repository not configured',
2675
+ log: updated,
2676
+ reason: 'missing_github_repo'
2677
+ }];
2678
+ case 4:
2679
+ effectiveEnv = "".concat(repoTarget.owner, "/").concat(repoTarget.repo);
2680
+ emailHash = email.issueHash || email.hash || this.generateIssueHash(email);
2681
+ rawHash = email.rawHash || this.generateRawEmailHash(email);
2682
+ workBranch = this.buildWorkBranch(emailHash);
2683
+ contextIdentifier = (emailHash || '').slice(0, 12) || 'autofix';
2684
+ contextPath = ".openai/error-context/".concat(contextIdentifier, ".md");
2685
+ normalizedBody = this.normalizeEmailText(email.body || '');
2686
+ contextContent = this.buildContextMarkdown(email, contextIdentifier, normalizedBody);
2687
+ commentBody = this.buildOpenAIComment(email, contextPath, normalizedBody);
2688
+ return [4 /*yield*/, this.updateLog(log._id, {
2689
+ status: 'in_progress',
2690
+ last_attempt_at: new Date(),
2691
+ branch_name: workBranch,
2692
+ pr_url: '',
2693
+ last_error: '',
2694
+ openai_environment: effectiveEnv,
2695
+ issue_hash: emailHash,
2696
+ email_hash: rawHash
2697
+ })];
2698
+ case 5:
2699
+ _a.sent();
2700
+ _a.label = 6;
2701
+ case 6:
2702
+ _a.trys.push([6, 16, , 18]);
2703
+ return [4 /*yield*/, this.resolveBaseBranch(repoTarget)];
2704
+ case 7:
2705
+ baseBranch = _a.sent();
2706
+ return [4 /*yield*/, this.getBranchSha(repoTarget, baseBranch)];
2707
+ case 8:
2708
+ baseSha = _a.sent();
2709
+ return [4 /*yield*/, this.ensureBranch(repoTarget, workBranch, baseBranch, baseSha)];
2710
+ case 9:
2711
+ _a.sent();
2712
+ return [4 /*yield*/, this.upsertContextFile(repoTarget, workBranch, contextPath, contextContent)];
2713
+ case 10:
2714
+ _a.sent();
2715
+ return [4 /*yield*/, this.findOpenPullRequest(repoTarget, workBranch, baseBranch)];
2716
+ case 11:
2717
+ pr = _a.sent();
2718
+ if (!!pr) return [3 /*break*/, 13];
2719
+ title = "AI Autofix: ".concat((email.subject || 'ResolveIO Error').slice(0, 180));
2720
+ bodyLines = [
2721
+ 'This PR was opened automatically to let AI investigate the reported failure.',
2722
+ '',
2723
+ "Context file: `".concat(contextPath, "`")
2724
+ ];
2725
+ return [4 /*yield*/, this.createPullRequest(repoTarget, workBranch, baseBranch, title, bodyLines.join('\n'))];
2726
+ case 12:
2727
+ pr = _a.sent();
2728
+ _a.label = 13;
2729
+ case 13: return [4 /*yield*/, this.commentOnPullRequest(repoTarget, pr.number, commentBody)];
2730
+ case 14:
2731
+ _a.sent();
2732
+ return [4 /*yield*/, this.updateLog(log._id, {
2733
+ status: 'success',
2734
+ branch_name: workBranch,
2735
+ pr_url: pr.html_url,
2736
+ plan_summary: email.subject,
2737
+ plan_body: commentBody,
2738
+ last_result_at: new Date(),
2739
+ id_client: email.id_client,
2740
+ client_name: email.client_name,
2741
+ from_email: email.fromAddress,
2742
+ source_type: email.source_type,
2743
+ classification_reason: email.classification_reason || '',
2744
+ openai_environment: effectiveEnv,
2745
+ issue_hash: emailHash,
2746
+ email_hash: rawHash
2747
+ })];
2748
+ case 15:
2749
+ updated = (_a.sent()) || log;
2750
+ return [2 /*return*/, {
2751
+ status: 'success',
2752
+ email: email,
2753
+ branchName: workBranch,
2754
+ prUrl: pr.html_url,
2755
+ log: updated,
2756
+ summary: email.subject,
2757
+ notes: "Context file: ".concat(contextPath)
2758
+ }];
2759
+ case 16:
2760
+ err_6 = _a.sent();
2761
+ message = (err_6 === null || err_6 === void 0 ? void 0 : err_6.message) || 'GitHub workflow failed.';
2762
+ return [4 /*yield*/, this.updateLog(log._id, {
2763
+ status: 'failed',
2764
+ last_error: message,
2765
+ last_result_at: new Date(),
2766
+ id_client: email.id_client,
2767
+ client_name: email.client_name,
2768
+ from_email: email.fromAddress,
2769
+ source_type: email.source_type,
2770
+ classification_reason: email.classification_reason || '',
2771
+ openai_environment: effectiveEnv,
2772
+ issue_hash: emailHash,
2773
+ email_hash: rawHash
2774
+ })];
2775
+ case 17:
2776
+ updated = (_a.sent()) || log;
2777
+ return [2 /*return*/, {
2778
+ status: 'failed',
2779
+ email: email,
2780
+ error: message,
2781
+ log: updated
2782
+ }];
2783
+ case 18: return [2 /*return*/];
2784
+ }
2785
+ });
2786
+ });
2787
+ };
2788
+ ErrorAutoFixManager.prototype.notify = function (result) {
2789
+ return __awaiter(this, void 0, void 0, function () {
2790
+ var recipients, subject, bodyLines, logId, summary, reason, textBody, recipients_3, recipients_3_1, email, e_7_1;
2791
+ var e_7, _a;
2792
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k;
2793
+ return __generator(this, function (_l) {
2794
+ switch (_l.label) {
2795
+ case 0:
2796
+ if (result.status === 'in_progress') {
2797
+ return [2 /*return*/];
2798
+ }
2799
+ if (result.status === 'skipped' && result.reason && !this.shouldNotifySkip(result.reason)) {
2800
+ return [2 /*return*/];
2801
+ }
2802
+ recipients = this.config.notifyEmails.length
2803
+ ? this.config.notifyEmails
2804
+ : (result.status === 'failed' ? [DEFAULT_ERROR_ALERT_EMAIL] : []);
2805
+ if (!recipients.length) {
2806
+ return [2 /*return*/];
2807
+ }
2808
+ subject = '';
2809
+ bodyLines = [];
2810
+ logId = ((_b = result.log) === null || _b === void 0 ? void 0 : _b._id) || '';
2811
+ summary = result.summary || ((_c = result.log) === null || _c === void 0 ? void 0 : _c.plan_summary) || result.email.subject;
2812
+ if (result.status === 'success') {
2813
+ subject = "ResolveIO AutoFix \u2714 ".concat(summary);
2814
+ bodyLines = [
2815
+ 'Auto-fix workflow completed successfully.',
2816
+ "Client: ".concat(((_d = result.log) === null || _d === void 0 ? void 0 : _d.client_name) || result.email.client_name || 'Unknown'),
2817
+ "Source: ".concat(((_e = result.log) === null || _e === void 0 ? void 0 : _e.source_type) || result.email.source_type || 'app'),
2818
+ '',
2819
+ "Branch: ".concat(result.branchName || 'unknown'),
2820
+ "PR: ".concat(result.prUrl || 'pending'),
2821
+ '',
2822
+ 'Summary:',
2823
+ summary || '(none)',
2824
+ ''
2825
+ ];
2826
+ if (result.notes) {
2827
+ bodyLines.push("Notes: ".concat(result.notes), '');
2828
+ }
2829
+ if (logId) {
2830
+ bodyLines.push("Log ID: ".concat(logId));
2831
+ }
2832
+ }
2833
+ else if (result.status === 'failed') {
2834
+ subject = "ResolveIO AutoFix \u2716 ".concat(summary);
2835
+ bodyLines = [
2836
+ 'Auto-fix workflow failed.',
2837
+ "Reason: ".concat(result.error || ((_f = result.log) === null || _f === void 0 ? void 0 : _f.last_error) || 'Unknown error'),
2838
+ "Client: ".concat(((_g = result.log) === null || _g === void 0 ? void 0 : _g.client_name) || result.email.client_name || 'Unknown'),
2839
+ "Source: ".concat(((_h = result.log) === null || _h === void 0 ? void 0 : _h.source_type) || result.email.source_type || 'app'),
2840
+ '',
2841
+ 'Email Subject:',
2842
+ result.email.subject
2843
+ ];
2844
+ if (logId) {
2845
+ bodyLines.push('', "Log ID: ".concat(logId));
2846
+ }
2847
+ }
2848
+ else {
2849
+ subject = "ResolveIO AutoFix \u26A0 ".concat(result.email.subject);
2850
+ reason = result.reason || 'skipped';
2851
+ bodyLines = [
2852
+ "Auto-fix skipped. Reason: ".concat(reason, "."),
2853
+ result.error && result.error !== reason ? "Details: ".concat(result.error) : '',
2854
+ "Client: ".concat(((_j = result.log) === null || _j === void 0 ? void 0 : _j.client_name) || result.email.client_name || 'Unknown'),
2855
+ "Source: ".concat(((_k = result.log) === null || _k === void 0 ? void 0 : _k.source_type) || result.email.source_type || 'app'),
2856
+ ''
2857
+ ];
2858
+ if (logId) {
2859
+ bodyLines.push("Log ID: ".concat(logId));
2860
+ }
2861
+ bodyLines.push('Update or remove the log entry to retry processing.');
2862
+ }
2863
+ textBody = bodyLines.filter(function (line) { return line !== undefined && line !== null && line !== ''; }).join('\n');
2864
+ _l.label = 1;
2865
+ case 1:
2866
+ _l.trys.push([1, 6, 7, 8]);
2867
+ recipients_3 = __values(recipients), recipients_3_1 = recipients_3.next();
2868
+ _l.label = 2;
2869
+ case 2:
2870
+ if (!!recipients_3_1.done) return [3 /*break*/, 5];
2871
+ email = recipients_3_1.value;
2872
+ return [4 /*yield*/, resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().sendEmail(email, subject, textBody)];
2873
+ case 3:
2874
+ _l.sent();
2875
+ _l.label = 4;
2876
+ case 4:
2877
+ recipients_3_1 = recipients_3.next();
2878
+ return [3 /*break*/, 2];
2879
+ case 5: return [3 /*break*/, 8];
2880
+ case 6:
2881
+ e_7_1 = _l.sent();
2882
+ e_7 = { error: e_7_1 };
2883
+ return [3 /*break*/, 8];
2884
+ case 7:
2885
+ try {
2886
+ if (recipients_3_1 && !recipients_3_1.done && (_a = recipients_3.return)) _a.call(recipients_3);
2887
+ }
2888
+ finally { if (e_7) throw e_7.error; }
2889
+ return [7 /*endfinally*/];
2890
+ case 8: return [2 /*return*/];
2891
+ }
2892
+ });
2893
+ });
2894
+ };
2895
+ return ErrorAutoFixManager;
2896
+ }());
2897
+ exports.ErrorAutoFixManager = ErrorAutoFixManager;
2898
+ function ensureErrorAutoFixManager(serverConfig) {
2899
+ var existing = resolveio_server_app_1.ResolveIOServer['AutoFixManager'];
2900
+ if (existing) {
2901
+ return existing;
2902
+ }
2903
+ if (!configuredErrorAutoFixDependencies) {
2904
+ return null;
2905
+ }
2906
+ var resolvedServerConfig = serverConfig || resolveio_server_app_1.ResolveIOServer.getServerConfig();
2907
+ if (!resolvedServerConfig) {
2908
+ return null;
2909
+ }
2910
+ var manager = new ErrorAutoFixManager(resolvedServerConfig);
2911
+ resolveio_server_app_1.ResolveIOServer['AutoFixManager'] = manager;
2912
+ return manager;
2913
+ }
2914
+ function reportDevError(options) {
2915
+ return __awaiter(this, void 0, void 0, function () {
2916
+ var manager;
2917
+ return __generator(this, function (_a) {
2918
+ switch (_a.label) {
2919
+ case 0:
2920
+ manager = ensureErrorAutoFixManager();
2921
+ if (!manager) {
2922
+ console.warn('AutoFix manager not initialized for dev alert', options === null || options === void 0 ? void 0 : options.subject);
2923
+ return [2 /*return*/];
2924
+ }
2925
+ return [4 /*yield*/, manager.reportDevError(options)];
2926
+ case 1:
2927
+ _a.sent();
2928
+ return [2 /*return*/];
2929
+ }
2930
+ });
2931
+ });
2932
+ }
2933
+
2934
+ //# sourceMappingURL=error-auto-fix.manager.js.map