@resolveio/server-lib 22.0.10 → 22.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/methods/ai-terminal.js +398 -86
- package/methods/ai-terminal.js.map +1 -1
- package/methods/report-builder.js +34 -8
- package/methods/report-builder.js.map +1 -1
- package/package.json +1 -1
- package/services/codex-client.d.ts +24 -0
- package/services/codex-client.js +345 -23
- package/services/codex-client.js.map +1 -1
package/methods/ai-terminal.js
CHANGED
|
@@ -139,7 +139,8 @@ var DEFAULT_MAX_FILE_MB = 50;
|
|
|
139
139
|
var DEFAULT_MAX_TOTAL_MB = 100;
|
|
140
140
|
var DEFAULT_MAX_ATTACHMENT_CHARS = 12000;
|
|
141
141
|
var DEFAULT_MAX_TOTAL_ATTACHMENT_CHARS = 40000;
|
|
142
|
-
var DEFAULT_CODEX_MODEL = 'gpt-5.
|
|
142
|
+
var DEFAULT_CODEX_MODEL = 'gpt-5.3-codex';
|
|
143
|
+
var DEFAULT_CODEX_FALLBACK_MODEL = 'gpt-5.2-codex';
|
|
143
144
|
var DEFAULT_CODEX_TIMEOUT_MS = 180000;
|
|
144
145
|
var AI_ASSISTANT_MONGO_DEFAULT_LIMIT = 20;
|
|
145
146
|
var AI_ASSISTANT_MONGO_MAX_LIMIT = 200;
|
|
@@ -381,12 +382,13 @@ var AI_ASSISTANT_REPORT_BUILDER_EXPERT_PLAYBOOK = [
|
|
|
381
382
|
'',
|
|
382
383
|
'2) Resolve the target dataset safely.',
|
|
383
384
|
'- Map user wording to internal collection names using routes, collection hints, field hints, and synonym expansion.',
|
|
384
|
-
'- Prefer report-* collections when permissionView is under /report.',
|
|
385
|
+
'- Prefer report-* collections when permissionView is under /report-builder.',
|
|
385
386
|
'- Never use *.versions unless user explicitly requests bug-history/version investigation.',
|
|
386
387
|
'- Never invent collection names or fields.',
|
|
387
388
|
'',
|
|
388
389
|
'3) Enforce permissions and scope in the directive.',
|
|
389
390
|
'- Always include permissionView.',
|
|
391
|
+
'- Use /report-builder as the default permissionView for data directives; avoid /report/* routes.',
|
|
390
392
|
'- Assume non-super-admin unless explicitly told otherwise.',
|
|
391
393
|
'- Invoice-like collections require invoice view access.',
|
|
392
394
|
'- Customer portal users must stay in their own customer scope.',
|
|
@@ -435,7 +437,7 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
|
|
|
435
437
|
'- Step 1 (always): determine the target collections/models/modules/workflows using context, routes, and collection hints. Assume the user is non-technical and will not provide internal names.',
|
|
436
438
|
'- Never use *.versions collections for normal requests. Only use a .versions collection when explicitly investigating a bug by checking the last ~5 updates.',
|
|
437
439
|
'- Planning stage: regex/keyword scan the codebase for collectionName/model definitions, methods, publications, and Angular routes/modules to map user wording to internal names.',
|
|
438
|
-
'- If permissionView starts with /report
|
|
440
|
+
'- If permissionView starts with /report-builder, prefer the report-* collection when both report and base collections exist.',
|
|
439
441
|
'- Map user wording to internal collections/fields yourself. Do not ask for property names unless required to run a query.',
|
|
440
442
|
'- Use term hints from context (synonym expansions) when mapping user language to collections.',
|
|
441
443
|
'- Do not guess or invent collections/fields. If unsure, verify in the codebase or run a small REPORT_BUILDER_READ probe (limit 1-5) to learn the shape.',
|
|
@@ -490,7 +492,8 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
|
|
|
490
492
|
'- REPORT_BUILDER_READ: {"collection":"<name>","query":{...},"options":{"projection":{...},"sort":{...},"limit":20},"permissionView":"</route>"}',
|
|
491
493
|
'- If you need grouped/aggregated data (totals by user, rankings, trends), end your response with a single line exactly in this format:',
|
|
492
494
|
'- REPORT_BUILDER_AGG: {"collection":"<name>","pipeline":[...],"options":{"allowDiskUse":true,"limit":20},"permissionView":"</route>"}',
|
|
493
|
-
'- For invoice data, set permissionView to an invoice route (ex: /invoice/list or /report/
|
|
495
|
+
'- For invoice data, set permissionView to an invoice-capable route (ex: /invoice/list or /report-builder/list).',
|
|
496
|
+
'- Do not use /report/* routes as permissionView for data directives; use /report-builder or a module route.',
|
|
494
497
|
'- For revenue/sales/billing questions, use invoices and sum paid_total (fallback to grand_total) with date_paid and Paid/Closed status when available.',
|
|
495
498
|
'- For revenue answers, always state the metric/date basis used (paid_total/date_paid vs grand_total/date_invoice). If tool verification warns about ambiguity or partial months, call that out before totals.',
|
|
496
499
|
'- For relative date ranges (last/past/recent), include an upper bound <= $$NOW unless the user specifies a future end date.',
|
|
@@ -532,7 +535,7 @@ var AI_ASSISTANT_PLANNER_SYSTEM_PROMPT = [
|
|
|
532
535
|
' - Never propose querying blocked/sensitive collections if the user lacks permission.',
|
|
533
536
|
'',
|
|
534
537
|
'4) PERMISSION MATCHING:',
|
|
535
|
-
' - Do NOT hardcode invoice access to "/report
|
|
538
|
+
' - Do NOT hardcode invoice access to "/report-builder/*".',
|
|
536
539
|
' - For invoice-related data or navigation, permission is satisfied if ANY user view contains "invoice" case-insensitive.',
|
|
537
540
|
' (General rule: for an entity token X, permission is satisfied if any view contains X case-insensitive.)',
|
|
538
541
|
' - If permission checks are ambiguous, choose the safest restriction and explain.',
|
|
@@ -667,7 +670,7 @@ var AI_FORM_PATCH_SYSTEM_PROMPT = [
|
|
|
667
670
|
'- Use ISO 8601 for dates and true/false for booleans.',
|
|
668
671
|
'- Use medium reasoning effort.'
|
|
669
672
|
].join('\n');
|
|
670
|
-
var
|
|
673
|
+
var assistantCodexClientByConfig = new Map();
|
|
671
674
|
var assistantCodexRunQueue = [];
|
|
672
675
|
var assistantCodexRunDraining = false;
|
|
673
676
|
/* eslint-enable no-unused-vars */
|
|
@@ -1320,7 +1323,7 @@ function executeAiFormPatch(payload, context) {
|
|
|
1320
1323
|
}
|
|
1321
1324
|
function executeAiAssistantCodexRun(payload, context) {
|
|
1322
1325
|
return __awaiter(this, void 0, void 0, function () {
|
|
1323
|
-
var input, message, aiWorkerDebug, requestId, guardrail, conversation_2, now_2, userMsg, assistantMsg, user, isSuperAdmin, hasInvoiceAccess, customerId, conversation, now, attachments, attachmentData, historyLimit, history, _a, historyLines, userDoc, initialProgress, assistantDoc, insertResult, assistantMessageId;
|
|
1326
|
+
var input, message, aiWorkerDebug, requestId, codexModel, codexFallbackModels, guardrail, conversation_2, now_2, userMsg, assistantMsg, user, isSuperAdmin, hasInvoiceAccess, customerId, conversation, now, attachments, attachmentData, historyLimit, history, _a, historyLines, recentToolError, userDoc, initialProgress, assistantDoc, insertResult, assistantMessageId;
|
|
1324
1327
|
var _this = this;
|
|
1325
1328
|
var _b, _c;
|
|
1326
1329
|
return __generator(this, function (_d) {
|
|
@@ -1336,6 +1339,8 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1336
1339
|
}
|
|
1337
1340
|
aiWorkerDebug = isAiWorkerDebugEnabled();
|
|
1338
1341
|
requestId = normalizeOptionalString(input.request_id);
|
|
1342
|
+
codexModel = resolveCodexModel(input.config);
|
|
1343
|
+
codexFallbackModels = resolveCodexFallbackModels(input.config, codexModel);
|
|
1339
1344
|
guardrail = evaluateAssistantGuardrails(message);
|
|
1340
1345
|
if (!(guardrail === null || guardrail === void 0 ? void 0 : guardrail.blocked)) return [3 /*break*/, 5];
|
|
1341
1346
|
return [4 /*yield*/, ensureConversation(input, 'codex')];
|
|
@@ -1415,6 +1420,9 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1415
1420
|
historyLines.push("".concat(role, ": ").concat(content));
|
|
1416
1421
|
}
|
|
1417
1422
|
});
|
|
1423
|
+
recentToolError = isAssistantWhyFollowupMessage(message)
|
|
1424
|
+
? resolveRecentAssistantToolError(history)
|
|
1425
|
+
: '';
|
|
1418
1426
|
userDoc = {
|
|
1419
1427
|
id_conversation: conversation._id,
|
|
1420
1428
|
role: 'user',
|
|
@@ -1429,7 +1437,7 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1429
1437
|
id_conversation: conversation._id,
|
|
1430
1438
|
role: 'assistant',
|
|
1431
1439
|
content: AI_ASSISTANT_PROGRESS_PLACEHOLDER,
|
|
1432
|
-
metadata: __assign(__assign({ model:
|
|
1440
|
+
metadata: __assign(__assign(__assign({ model: codexModel }, (codexFallbackModels.length ? { model_fallbacks: codexFallbackModels } : {})), (requestId ? { request_id: requestId } : {})), { pending: true, progress: initialProgress }),
|
|
1433
1441
|
createdAt: now,
|
|
1434
1442
|
updatedAt: now
|
|
1435
1443
|
};
|
|
@@ -1564,16 +1572,22 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1564
1572
|
customerId: customerId,
|
|
1565
1573
|
collectionHints: collectionHints,
|
|
1566
1574
|
termHints: termHints,
|
|
1567
|
-
fieldHints: fieldHints
|
|
1575
|
+
fieldHints: fieldHints,
|
|
1576
|
+
recentToolError: recentToolError
|
|
1568
1577
|
});
|
|
1569
1578
|
prompt_1 = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
|
|
1570
1579
|
return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
|
|
1571
1580
|
case 6:
|
|
1572
1581
|
workspaceRoot = _x.sent();
|
|
1573
|
-
codexConfig = resolveCodexSettings(
|
|
1582
|
+
codexConfig = resolveCodexSettings({
|
|
1583
|
+
model: codexModel,
|
|
1584
|
+
fallbackModels: codexFallbackModels
|
|
1585
|
+
});
|
|
1574
1586
|
runOptions = {
|
|
1575
1587
|
timeoutMs: resolveCodexTimeoutMs(),
|
|
1588
|
+
fallbackModels: codexFallbackModels,
|
|
1576
1589
|
threadOptions: {
|
|
1590
|
+
model: codexModel,
|
|
1577
1591
|
workingDirectory: workspaceRoot,
|
|
1578
1592
|
sandboxMode: 'read-only',
|
|
1579
1593
|
skipGitRepoCheck: true,
|
|
@@ -1804,6 +1818,7 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1804
1818
|
assistantContent = buildAssistantCodexErrorMessage(null);
|
|
1805
1819
|
}
|
|
1806
1820
|
assistantContent = applyAssistantVerificationNotes(assistantContent, toolResult);
|
|
1821
|
+
assistantContent = applyAssistantDatedReportWindow(assistantContent, toolResult);
|
|
1807
1822
|
assistantContent = normalizeAssistantCurrencyText(assistantContent);
|
|
1808
1823
|
if (aiWorkerDebug) {
|
|
1809
1824
|
finishedAt = Date.now();
|
|
@@ -1874,7 +1889,7 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1874
1889
|
}
|
|
1875
1890
|
});
|
|
1876
1891
|
}
|
|
1877
|
-
finalMetadata = __assign(__assign(__assign({ model:
|
|
1892
|
+
finalMetadata = __assign(__assign(__assign(__assign({ model: codexModel }, (codexFallbackModels.length ? { model_fallbacks: codexFallbackModels } : {})), (requestId ? { request_id: requestId } : {})), (toolResult ? { tool_result: toolResult } : {})), (assistantDebug ? { debug: assistantDebug } : {}));
|
|
1878
1893
|
finalAssistantDoc = __assign(__assign({}, assistantDoc), { _id: assistantMessageId, content: assistantContent, metadata: finalMetadata, updatedAt: finalNow });
|
|
1879
1894
|
if (!assistantMessageId) return [3 /*break*/, 39];
|
|
1880
1895
|
return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.updateOne({ _id: assistantMessageId }, {
|
|
@@ -3027,7 +3042,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
|
|
|
3027
3042
|
}
|
|
3028
3043
|
function verifyAssistantAggregateReliability(params) {
|
|
3029
3044
|
return __awaiter(this, void 0, void 0, function () {
|
|
3030
|
-
var collection, collectionBase, monthKey, amountKey, baseMap, groupIndex, groupPaths, dateField, mergedMatch, dateFieldsInMatch, baseMatchNoDate, primaryDateCondition, verifyPipeline, verifyDocs, _a, verifyMap, comparedMonths, paidCloserCount, grandCloserCount, sumPaidDiffPct, sumGrandDiffPct, maxPaidDiffPct, maxGrandDiffPct, sumPaidGrandGapPct, highVarianceMonths, checks, warnings, avgPaidDiffPct, avgGrandDiffPct, avgPaidGrandGapPct, baselineMetric, rollingWindow, normalizedMetric, bounds, fullMonthMatch, fullMonthDocs, fullMonthMap, fullMonthDiff, _b, alternateDateField, alternateDateCondition, bounds, alternateMatch, alternateDocs, alternateMap, alternateDiff, _c;
|
|
3045
|
+
var collection, collectionBase, monthKey, amountKey, baseMap, groupIndex, groupPaths, dateField, mergedMatch, dateFieldsInMatch, baseMatchNoDate, primaryDateCondition, verifyPipeline, verifyDocs, _a, verifyMap, comparedMonths, paidCloserCount, grandCloserCount, sumPaidDiffPct, sumGrandDiffPct, maxPaidDiffPct, maxGrandDiffPct, sumPaidGrandGapPct, highVarianceMonths, checks, warnings, avgPaidDiffPct, avgGrandDiffPct, avgPaidGrandGapPct, baselineMetric, rollingWindow, rollingWindowBounds, verificationWindow, rollingStart, rollingEnd, fullMonthStart, fullMonthEndExclusive, normalizedMetric, bounds, fullMonthMatch, fullMonthDocs, fullMonthMap, fullMonthDiff, _b, alternateDateField, alternateDateCondition, bounds, alternateMatch, alternateDocs, alternateMap, alternateDiff, _c;
|
|
3031
3046
|
var _d, _e;
|
|
3032
3047
|
var _f;
|
|
3033
3048
|
return __generator(this, function (_g) {
|
|
@@ -3168,13 +3183,29 @@ function verifyAssistantAggregateReliability(params) {
|
|
|
3168
3183
|
}
|
|
3169
3184
|
}
|
|
3170
3185
|
rollingWindow = detectAssistantRollingMonthWindow(params.pipeline || []);
|
|
3186
|
+
rollingWindowBounds = null;
|
|
3187
|
+
verificationWindow = null;
|
|
3171
3188
|
if ((rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.months) && (rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.upperNow)) {
|
|
3189
|
+
rollingWindowBounds = resolveAssistantRollingWindowBounds(rollingWindow.months);
|
|
3190
|
+
rollingStart = formatAssistantIsoDateOnly(rollingWindowBounds.rollingStart);
|
|
3191
|
+
rollingEnd = formatAssistantIsoDateOnly(rollingWindowBounds.now);
|
|
3192
|
+
fullMonthStart = formatAssistantIsoDateOnly(rollingWindowBounds.startOfWindow);
|
|
3193
|
+
fullMonthEndExclusive = formatAssistantIsoDateOnly(rollingWindowBounds.startOfCurrentMonth);
|
|
3194
|
+
verificationWindow = {
|
|
3195
|
+
type: 'rolling_last_n_months',
|
|
3196
|
+
months: rollingWindow.months,
|
|
3197
|
+
startDate: rollingStart,
|
|
3198
|
+
endDate: rollingEnd,
|
|
3199
|
+
timezone: 'UTC',
|
|
3200
|
+
fullMonthStartDate: fullMonthStart,
|
|
3201
|
+
fullMonthEndDateExclusive: fullMonthEndExclusive
|
|
3202
|
+
};
|
|
3172
3203
|
checks.push({
|
|
3173
3204
|
name: 'Date window shape',
|
|
3174
3205
|
status: 'warn',
|
|
3175
|
-
details: "Query uses rolling $$NOW bounds (last ".concat(rollingWindow.months, " months), which can include partial months.")
|
|
3206
|
+
details: "Query uses rolling $$NOW bounds (".concat(rollingStart, " to ").concat(rollingEnd, " UTC; last ").concat(rollingWindow.months, " months), which can include partial months.")
|
|
3176
3207
|
});
|
|
3177
|
-
warnings.push("Date window is rolling (last ".concat(rollingWindow.months, " months
|
|
3208
|
+
warnings.push("Date window is rolling (".concat(rollingStart, " to ").concat(rollingEnd, " UTC; last ").concat(rollingWindow.months, " months), so first/current months may be partial."));
|
|
3178
3209
|
}
|
|
3179
3210
|
else {
|
|
3180
3211
|
checks.push({
|
|
@@ -3184,8 +3215,8 @@ function verifyAssistantAggregateReliability(params) {
|
|
|
3184
3215
|
});
|
|
3185
3216
|
}
|
|
3186
3217
|
normalizedMetric = normalizeAssistantVerificationMetric(baselineMetric);
|
|
3187
|
-
if (!((rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.months) && (rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.upperNow))) return [3 /*break*/, 8];
|
|
3188
|
-
bounds =
|
|
3218
|
+
if (!((rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.months) && (rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.upperNow) && rollingWindowBounds)) return [3 /*break*/, 8];
|
|
3219
|
+
bounds = rollingWindowBounds;
|
|
3189
3220
|
fullMonthMatch = mergeAssistantMatch(baseMatchNoDate, (_d = {},
|
|
3190
3221
|
_d[dateField] = {
|
|
3191
3222
|
$gte: bounds.startOfWindow,
|
|
@@ -3233,8 +3264,8 @@ function verifyAssistantAggregateReliability(params) {
|
|
|
3233
3264
|
: '';
|
|
3234
3265
|
if (!alternateDateField) return [3 /*break*/, 12];
|
|
3235
3266
|
alternateDateCondition = null;
|
|
3236
|
-
if ((rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.months) && (rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.upperNow)) {
|
|
3237
|
-
bounds =
|
|
3267
|
+
if ((rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.months) && (rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.upperNow) && rollingWindowBounds) {
|
|
3268
|
+
bounds = rollingWindowBounds;
|
|
3238
3269
|
alternateDateCondition = {
|
|
3239
3270
|
$gte: bounds.rollingStart,
|
|
3240
3271
|
$lte: bounds.now
|
|
@@ -3282,16 +3313,7 @@ function verifyAssistantAggregateReliability(params) {
|
|
|
3282
3313
|
type: 'invoice_revenue_monthly',
|
|
3283
3314
|
checks: checks,
|
|
3284
3315
|
warnings: warnings,
|
|
3285
|
-
metrics: {
|
|
3286
|
-
baselineField: amountKey,
|
|
3287
|
-
dateField: dateField,
|
|
3288
|
-
comparedMonths: comparedMonths,
|
|
3289
|
-
avgDiffToPaidPct: (0, common_1.round)(avgPaidDiffPct * 100, 2),
|
|
3290
|
-
avgDiffToGrandPct: (0, common_1.round)(avgGrandDiffPct * 100, 2),
|
|
3291
|
-
maxDiffToPaidPct: (0, common_1.round)(maxPaidDiffPct * 100, 2),
|
|
3292
|
-
maxDiffToGrandPct: (0, common_1.round)(maxGrandDiffPct * 100, 2),
|
|
3293
|
-
avgPaidGrandGapPct: (0, common_1.round)(avgPaidGrandGapPct * 100, 2)
|
|
3294
|
-
}
|
|
3316
|
+
metrics: __assign({ baselineField: amountKey, dateField: dateField, comparedMonths: comparedMonths, avgDiffToPaidPct: (0, common_1.round)(avgPaidDiffPct * 100, 2), avgDiffToGrandPct: (0, common_1.round)(avgGrandDiffPct * 100, 2), maxDiffToPaidPct: (0, common_1.round)(maxPaidDiffPct * 100, 2), maxDiffToGrandPct: (0, common_1.round)(maxGrandDiffPct * 100, 2), avgPaidGrandGapPct: (0, common_1.round)(avgPaidGrandGapPct * 100, 2) }, (verificationWindow ? { window: verificationWindow } : {}))
|
|
3295
3317
|
}];
|
|
3296
3318
|
}
|
|
3297
3319
|
});
|
|
@@ -3494,6 +3516,12 @@ function resolveAssistantRollingWindowBounds(months) {
|
|
|
3494
3516
|
startOfWindow: startOfWindow
|
|
3495
3517
|
};
|
|
3496
3518
|
}
|
|
3519
|
+
function formatAssistantIsoDateOnly(value) {
|
|
3520
|
+
if (!(value instanceof Date) || Number.isNaN(value.getTime())) {
|
|
3521
|
+
return '';
|
|
3522
|
+
}
|
|
3523
|
+
return value.toISOString().slice(0, 10);
|
|
3524
|
+
}
|
|
3497
3525
|
function extractAssistantMongoDirective(content) {
|
|
3498
3526
|
var lines = String(content || '').split('\n');
|
|
3499
3527
|
var directiveIndex = -1;
|
|
@@ -3548,13 +3576,12 @@ function extractAssistantMongoDirective(content) {
|
|
|
3548
3576
|
};
|
|
3549
3577
|
}
|
|
3550
3578
|
function buildAssistantToolRequest(directive, payload) {
|
|
3551
|
-
var _a;
|
|
3552
3579
|
var base = directive.payload && typeof directive.payload === 'object' ? directive.payload : {};
|
|
3553
3580
|
var request = __assign({}, base);
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
request.permissionView = route;
|
|
3581
|
+
if (!request.permissionView) {
|
|
3582
|
+
request.permissionView = '/report-builder';
|
|
3557
3583
|
}
|
|
3584
|
+
request.permissionView = normalizeAssistantPermissionView(request.permissionView, request.collection);
|
|
3558
3585
|
if (!request.id_client) {
|
|
3559
3586
|
var idClient = normalizeOptionalString(payload === null || payload === void 0 ? void 0 : payload.id_client);
|
|
3560
3587
|
if (idClient) {
|
|
@@ -3566,6 +3593,24 @@ function buildAssistantToolRequest(directive, payload) {
|
|
|
3566
3593
|
}
|
|
3567
3594
|
return request;
|
|
3568
3595
|
}
|
|
3596
|
+
function normalizeAssistantPermissionView(permissionView, collection) {
|
|
3597
|
+
var normalizedPermission = normalizeOptionalString(permissionView);
|
|
3598
|
+
var normalizedCollection = normalizeOptionalString(collection);
|
|
3599
|
+
var loweredPermission = normalizedPermission.toLowerCase();
|
|
3600
|
+
if (!normalizedPermission) {
|
|
3601
|
+
return '/report-builder';
|
|
3602
|
+
}
|
|
3603
|
+
if (loweredPermission === '/report-builder' || loweredPermission.startsWith('/report-builder/')) {
|
|
3604
|
+
return '/report-builder';
|
|
3605
|
+
}
|
|
3606
|
+
if (loweredPermission === '/report' || loweredPermission.startsWith('/report/')) {
|
|
3607
|
+
if (requiresInvoicePermission(normalizedCollection)) {
|
|
3608
|
+
return '/invoice/list';
|
|
3609
|
+
}
|
|
3610
|
+
return '/report-builder';
|
|
3611
|
+
}
|
|
3612
|
+
return normalizedPermission;
|
|
3613
|
+
}
|
|
3569
3614
|
function buildAssistantToolResultPayload(directive, toolResponse) {
|
|
3570
3615
|
var _a, _b, _c;
|
|
3571
3616
|
var directivePayload = directive.payload || {};
|
|
@@ -3701,6 +3746,30 @@ function applyAssistantVerificationNotes(value, toolResult) {
|
|
|
3701
3746
|
}
|
|
3702
3747
|
return "".concat(content, "\n\n").concat(noteLines.join('\n')).trim();
|
|
3703
3748
|
}
|
|
3749
|
+
function applyAssistantDatedReportWindow(value, toolResult) {
|
|
3750
|
+
var _a, _b, _c;
|
|
3751
|
+
var content = normalizeOptionalString(value);
|
|
3752
|
+
var window = (_c = (_b = (_a = toolResult === null || toolResult === void 0 ? void 0 : toolResult.output) === null || _a === void 0 ? void 0 : _a.verification) === null || _b === void 0 ? void 0 : _b.metrics) === null || _c === void 0 ? void 0 : _c.window;
|
|
3753
|
+
if (!window || typeof window !== 'object') {
|
|
3754
|
+
return content || value || '';
|
|
3755
|
+
}
|
|
3756
|
+
var startDate = normalizeOptionalString(window.startDate);
|
|
3757
|
+
var endDate = normalizeOptionalString(window.endDate);
|
|
3758
|
+
if (!startDate || !endDate) {
|
|
3759
|
+
return content || value || '';
|
|
3760
|
+
}
|
|
3761
|
+
var months = normalizeOptionalNumber(window.months);
|
|
3762
|
+
var monthsText = months && months > 0 ? "; rolling last ".concat((0, common_1.round)(months), " month").concat((0, common_1.round)(months) === 1 ? '' : 's') : '';
|
|
3763
|
+
var line = "Report date range (UTC): ".concat(startDate, " to ").concat(endDate).concat(monthsText, ".");
|
|
3764
|
+
var normalizedLower = String(content || '').toLowerCase();
|
|
3765
|
+
if (normalizedLower.includes(startDate.toLowerCase()) && normalizedLower.includes(endDate.toLowerCase())) {
|
|
3766
|
+
return content || value || '';
|
|
3767
|
+
}
|
|
3768
|
+
if (!content) {
|
|
3769
|
+
return line;
|
|
3770
|
+
}
|
|
3771
|
+
return "".concat(line, "\n\n").concat(content).trim();
|
|
3772
|
+
}
|
|
3704
3773
|
function buildAssistantDebugPayload(params) {
|
|
3705
3774
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4;
|
|
3706
3775
|
var notes = [];
|
|
@@ -3877,7 +3946,7 @@ function buildAssistantToolErrorMessage(error, directive, request) {
|
|
|
3877
3946
|
? "Open ".concat(routeHint, " in the app to view this data or request access.")
|
|
3878
3947
|
: 'Open the related screen in the app to view this data or request access.';
|
|
3879
3948
|
if (!routeHint && collection && requiresInvoicePermission(collection)) {
|
|
3880
|
-
routeLine = 'Open /invoice/list or /report/
|
|
3949
|
+
routeLine = 'Open /invoice/list or /report-builder/list to view this data or request access.';
|
|
3881
3950
|
}
|
|
3882
3951
|
if (normalized.includes('permission scope required')) {
|
|
3883
3952
|
return "I need a permission scope to access that data. ".concat(routeLine);
|
|
@@ -3891,6 +3960,9 @@ function buildAssistantToolErrorMessage(error, directive, request) {
|
|
|
3891
3960
|
if (normalized.includes('database access denied')) {
|
|
3892
3961
|
return "Database access is restricted for that request. ".concat(routeLine);
|
|
3893
3962
|
}
|
|
3963
|
+
if (normalized.includes('undefined variable') && normalized.includes('now_minus')) {
|
|
3964
|
+
return "The query used an unsupported relative date token. Please retry; the assistant now normalizes relative dates automatically. ".concat(routeLine);
|
|
3965
|
+
}
|
|
3894
3966
|
if (normalized.includes('report builder bridge') && normalized.includes('not configured')) {
|
|
3895
3967
|
return "That dataset is not configured for report builder access yet. ".concat(routeLine);
|
|
3896
3968
|
}
|
|
@@ -5547,9 +5619,49 @@ function stripAssistantMarkdownTables(value) {
|
|
|
5547
5619
|
if (!raw) {
|
|
5548
5620
|
return '';
|
|
5549
5621
|
}
|
|
5550
|
-
var
|
|
5551
|
-
var
|
|
5552
|
-
|
|
5622
|
+
var lines = raw.split('\n');
|
|
5623
|
+
var kept = [];
|
|
5624
|
+
for (var index = 0; index < lines.length; index += 1) {
|
|
5625
|
+
var line = lines[index];
|
|
5626
|
+
var nextLine = lines[index + 1];
|
|
5627
|
+
if (isAssistantMarkdownTableHeaderLine(line) && isAssistantMarkdownTableSeparatorLine(nextLine || '')) {
|
|
5628
|
+
index += 2;
|
|
5629
|
+
while (index < lines.length && isAssistantMarkdownTableRowLine(lines[index])) {
|
|
5630
|
+
index += 1;
|
|
5631
|
+
}
|
|
5632
|
+
while (index < lines.length && !normalizeOptionalString(lines[index])) {
|
|
5633
|
+
index += 1;
|
|
5634
|
+
}
|
|
5635
|
+
index -= 1;
|
|
5636
|
+
if (kept.length && normalizeOptionalString(kept[kept.length - 1])) {
|
|
5637
|
+
kept.push('');
|
|
5638
|
+
}
|
|
5639
|
+
continue;
|
|
5640
|
+
}
|
|
5641
|
+
kept.push(line);
|
|
5642
|
+
}
|
|
5643
|
+
return kept.join('\n').replace(/\n{3,}/g, '\n\n').trim();
|
|
5644
|
+
}
|
|
5645
|
+
function isAssistantMarkdownTableHeaderLine(line) {
|
|
5646
|
+
var trimmed = normalizeOptionalString(line);
|
|
5647
|
+
if (!trimmed || !trimmed.includes('|')) {
|
|
5648
|
+
return false;
|
|
5649
|
+
}
|
|
5650
|
+
return /^\|.+\|$/.test(trimmed);
|
|
5651
|
+
}
|
|
5652
|
+
function isAssistantMarkdownTableSeparatorLine(line) {
|
|
5653
|
+
var trimmed = normalizeOptionalString(line);
|
|
5654
|
+
if (!trimmed || !trimmed.includes('|')) {
|
|
5655
|
+
return false;
|
|
5656
|
+
}
|
|
5657
|
+
return /^\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(trimmed);
|
|
5658
|
+
}
|
|
5659
|
+
function isAssistantMarkdownTableRowLine(line) {
|
|
5660
|
+
var trimmed = normalizeOptionalString(line);
|
|
5661
|
+
if (!trimmed || !trimmed.includes('|')) {
|
|
5662
|
+
return false;
|
|
5663
|
+
}
|
|
5664
|
+
return /^\|.*\|$/.test(trimmed);
|
|
5553
5665
|
}
|
|
5554
5666
|
function applyAssistantDisplayTableToResponse(value, display) {
|
|
5555
5667
|
if (!display || !Array.isArray(display.rows) || !display.rows.length) {
|
|
@@ -5595,7 +5707,7 @@ function isDisplayObjectLike(value) {
|
|
|
5595
5707
|
}
|
|
5596
5708
|
function ensureAssistantReadAccess(context, permissionView, collection) {
|
|
5597
5709
|
return __awaiter(this, void 0, void 0, function () {
|
|
5598
|
-
var idUser, user, isSuperAdmin, normalizedPermission,
|
|
5710
|
+
var idUser, user, isSuperAdmin, normalizedCollection, normalizedPermission, requiresInvoiceAccess, hasInvoiceAccess, hasViewAccess;
|
|
5599
5711
|
var _a;
|
|
5600
5712
|
return __generator(this, function (_b) {
|
|
5601
5713
|
switch (_b.label) {
|
|
@@ -5611,20 +5723,21 @@ function ensureAssistantReadAccess(context, permissionView, collection) {
|
|
|
5611
5723
|
throw new Error('AI assistant report builder bridge: Unauthorized.');
|
|
5612
5724
|
}
|
|
5613
5725
|
isSuperAdmin = !!((_a = user === null || user === void 0 ? void 0 : user.roles) === null || _a === void 0 ? void 0 : _a.super_admin);
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
if (!normalizedPermission) {
|
|
5617
|
-
throw new Error('AI assistant report builder bridge: Permission scope required.');
|
|
5618
|
-
}
|
|
5619
|
-
if (!userHasViewPermission(user, normalizedPermission)) {
|
|
5620
|
-
throw new Error('AI assistant report builder bridge: Access denied.');
|
|
5621
|
-
}
|
|
5622
|
-
normalizedCollection = normalizeOptionalString(collection);
|
|
5623
|
-
if (normalizedCollection && requiresInvoicePermission(normalizedCollection) && !userHasInvoiceAccess(user)) {
|
|
5624
|
-
throw new Error('AI assistant report builder bridge: Access denied.');
|
|
5625
|
-
}
|
|
5726
|
+
if (isSuperAdmin) {
|
|
5727
|
+
return [2 /*return*/, { user: user, isSuperAdmin: isSuperAdmin }];
|
|
5626
5728
|
}
|
|
5627
|
-
|
|
5729
|
+
normalizedCollection = normalizeOptionalString(collection);
|
|
5730
|
+
normalizedPermission = normalizeAssistantPermissionView(permissionView, normalizedCollection);
|
|
5731
|
+
if (!normalizedPermission) {
|
|
5732
|
+
throw new Error('AI assistant report builder bridge: Permission scope required.');
|
|
5733
|
+
}
|
|
5734
|
+
requiresInvoiceAccess = normalizedCollection ? requiresInvoicePermission(normalizedCollection) : false;
|
|
5735
|
+
hasInvoiceAccess = requiresInvoiceAccess && userHasInvoiceAccess(user);
|
|
5736
|
+
hasViewAccess = userHasViewPermission(user, normalizedPermission);
|
|
5737
|
+
if (!hasViewAccess && !hasInvoiceAccess) {
|
|
5738
|
+
throw new Error('AI assistant report builder bridge: Access denied.');
|
|
5739
|
+
}
|
|
5740
|
+
if (requiresInvoiceAccess && !hasInvoiceAccess) {
|
|
5628
5741
|
throw new Error('AI assistant report builder bridge: Access denied.');
|
|
5629
5742
|
}
|
|
5630
5743
|
return [2 /*return*/, { user: user, isSuperAdmin: isSuperAdmin }];
|
|
@@ -5700,6 +5813,90 @@ function sanitizeAssistantProjection(projection) {
|
|
|
5700
5813
|
return projection;
|
|
5701
5814
|
}
|
|
5702
5815
|
var AGG_MATCH_EXPR_OPERATORS = new Set(['$eq', '$ne', '$gt', '$gte', '$lt', '$lte']);
|
|
5816
|
+
var ASSISTANT_NOW_RELATIVE_PATTERN = /^\$\$NOW_(MINUS|PLUS)_([0-9]+)_(MINUTES?|HOURS?|DAYS?|WEEKS?|MONTHS?|YEARS?)$/i;
|
|
5817
|
+
function normalizeAssistantTimeUnit(raw) {
|
|
5818
|
+
var normalized = String(raw || '').toLowerCase();
|
|
5819
|
+
if (normalized.startsWith('minute')) {
|
|
5820
|
+
return 'minute';
|
|
5821
|
+
}
|
|
5822
|
+
if (normalized.startsWith('hour')) {
|
|
5823
|
+
return 'hour';
|
|
5824
|
+
}
|
|
5825
|
+
if (normalized.startsWith('day')) {
|
|
5826
|
+
return 'day';
|
|
5827
|
+
}
|
|
5828
|
+
if (normalized.startsWith('week')) {
|
|
5829
|
+
return 'week';
|
|
5830
|
+
}
|
|
5831
|
+
if (normalized.startsWith('month')) {
|
|
5832
|
+
return 'month';
|
|
5833
|
+
}
|
|
5834
|
+
return 'year';
|
|
5835
|
+
}
|
|
5836
|
+
function parseAssistantNowRelativeToken(value) {
|
|
5837
|
+
var trimmed = normalizeOptionalString(value);
|
|
5838
|
+
if (!trimmed) {
|
|
5839
|
+
return null;
|
|
5840
|
+
}
|
|
5841
|
+
var match = trimmed.match(ASSISTANT_NOW_RELATIVE_PATTERN);
|
|
5842
|
+
if (!match) {
|
|
5843
|
+
return null;
|
|
5844
|
+
}
|
|
5845
|
+
var direction = String(match[1] || '').toUpperCase() === 'PLUS' ? 'PLUS' : 'MINUS';
|
|
5846
|
+
var amount = Number(match[2]);
|
|
5847
|
+
if (!Number.isFinite(amount) || amount < 0) {
|
|
5848
|
+
return null;
|
|
5849
|
+
}
|
|
5850
|
+
var unit = normalizeAssistantTimeUnit(match[3] || '');
|
|
5851
|
+
return {
|
|
5852
|
+
operator: direction === 'PLUS' ? '$dateAdd' : '$dateSubtract',
|
|
5853
|
+
amount: amount,
|
|
5854
|
+
unit: unit
|
|
5855
|
+
};
|
|
5856
|
+
}
|
|
5857
|
+
function normalizeAssistantNowExprOperand(value) {
|
|
5858
|
+
var _a;
|
|
5859
|
+
if (typeof value !== 'string') {
|
|
5860
|
+
return value;
|
|
5861
|
+
}
|
|
5862
|
+
var trimmed = normalizeOptionalString(value);
|
|
5863
|
+
if (!trimmed) {
|
|
5864
|
+
return value;
|
|
5865
|
+
}
|
|
5866
|
+
if (trimmed === '$$NOW') {
|
|
5867
|
+
return '$$NOW';
|
|
5868
|
+
}
|
|
5869
|
+
var parsed = parseAssistantNowRelativeToken(trimmed);
|
|
5870
|
+
if (!parsed) {
|
|
5871
|
+
return value;
|
|
5872
|
+
}
|
|
5873
|
+
return _a = {},
|
|
5874
|
+
_a[parsed.operator] = {
|
|
5875
|
+
startDate: '$$NOW',
|
|
5876
|
+
unit: parsed.unit,
|
|
5877
|
+
amount: parsed.amount
|
|
5878
|
+
},
|
|
5879
|
+
_a;
|
|
5880
|
+
}
|
|
5881
|
+
function normalizeAssistantNowExprPlaceholdersDeep(value) {
|
|
5882
|
+
if (Array.isArray(value)) {
|
|
5883
|
+
return value.map(function (entry) { return normalizeAssistantNowExprPlaceholdersDeep(entry); });
|
|
5884
|
+
}
|
|
5885
|
+
if (value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
|
|
5886
|
+
return value;
|
|
5887
|
+
}
|
|
5888
|
+
if (typeof value === 'string') {
|
|
5889
|
+
return normalizeAssistantNowExprOperand(value);
|
|
5890
|
+
}
|
|
5891
|
+
if (!value || typeof value !== 'object') {
|
|
5892
|
+
return value;
|
|
5893
|
+
}
|
|
5894
|
+
var result = {};
|
|
5895
|
+
Object.keys(value).forEach(function (key) {
|
|
5896
|
+
result[key] = normalizeAssistantNowExprPlaceholdersDeep(value[key]);
|
|
5897
|
+
});
|
|
5898
|
+
return result;
|
|
5899
|
+
}
|
|
5703
5900
|
function isMatchExpressionOperand(value) {
|
|
5704
5901
|
if (typeof value === 'string') {
|
|
5705
5902
|
return value.startsWith('$$');
|
|
@@ -5757,7 +5954,7 @@ function rewriteMatchExpressionsToExpr(match) {
|
|
|
5757
5954
|
}
|
|
5758
5955
|
var operand = nextEntry_1[op];
|
|
5759
5956
|
if (isMatchExpressionOperand(operand)) {
|
|
5760
|
-
exprClauses.push((_a = {}, _a[op] = ["$".concat(key), operand], _a));
|
|
5957
|
+
exprClauses.push((_a = {}, _a[op] = ["$".concat(key), normalizeAssistantNowExprOperand(operand)], _a));
|
|
5761
5958
|
delete nextEntry_1[op];
|
|
5762
5959
|
moved_1 = true;
|
|
5763
5960
|
}
|
|
@@ -5771,7 +5968,7 @@ function rewriteMatchExpressionsToExpr(match) {
|
|
|
5771
5968
|
return;
|
|
5772
5969
|
}
|
|
5773
5970
|
if (typeof entry === 'string' && entry.startsWith('$$')) {
|
|
5774
|
-
exprClauses.push({ $eq: ["$".concat(key), entry] });
|
|
5971
|
+
exprClauses.push({ $eq: ["$".concat(key), normalizeAssistantNowExprOperand(entry)] });
|
|
5775
5972
|
return;
|
|
5776
5973
|
}
|
|
5777
5974
|
result[key] = entry;
|
|
@@ -5848,7 +6045,7 @@ function normalizeAssistantAggregatePipeline(pipeline, collection) {
|
|
|
5848
6045
|
var statusNormalized = isInvoiceCollection ? normalizeInvoiceStatusMatch(exprRewritten) : exprRewritten;
|
|
5849
6046
|
next.$geoNear = __assign(__assign({}, next.$geoNear), { query: applyAssistantNameRegexToQuery(statusNormalized) });
|
|
5850
6047
|
}
|
|
5851
|
-
return next;
|
|
6048
|
+
return normalizeAssistantNowExprPlaceholdersDeep(next);
|
|
5852
6049
|
});
|
|
5853
6050
|
}
|
|
5854
6051
|
function buildAssistantAggregatePipeline(query, pipeline) {
|
|
@@ -7495,7 +7692,9 @@ function normalizeMongoQuery(query) {
|
|
|
7495
7692
|
throw new Error('AI assistant report builder bridge: Query contains restricted operators.');
|
|
7496
7693
|
}
|
|
7497
7694
|
var rewritten = rewriteEmbeddedMatchObjects(normalized);
|
|
7498
|
-
|
|
7695
|
+
var exprRewritten = rewriteMatchExpressionsToExpr(rewritten);
|
|
7696
|
+
var nowNormalized = normalizeAssistantNowExprPlaceholdersDeep(exprRewritten);
|
|
7697
|
+
return applyAssistantNameRegexToQuery(nowNormalized);
|
|
7499
7698
|
}
|
|
7500
7699
|
function shouldApplyAssistantNameRegex(field) {
|
|
7501
7700
|
var normalized = String(field || '').toLowerCase().trim();
|
|
@@ -8019,7 +8218,7 @@ function shouldAllowVersionCollections(message) {
|
|
|
8019
8218
|
}
|
|
8020
8219
|
function resolveReportCollectionName(permissionView, collectionNames, currentCollection) {
|
|
8021
8220
|
var normalizedView = normalizeOptionalString(permissionView).toLowerCase();
|
|
8022
|
-
if (!normalizedView.startsWith('/report
|
|
8221
|
+
if (!normalizedView.startsWith('/report-builder')) {
|
|
8023
8222
|
return null;
|
|
8024
8223
|
}
|
|
8025
8224
|
var current = stripVersionSuffix(normalizeOptionalString(currentCollection));
|
|
@@ -8027,11 +8226,6 @@ function resolveReportCollectionName(permissionView, collectionNames, currentCol
|
|
|
8027
8226
|
if (collectionNames.includes(reportCollection)) {
|
|
8028
8227
|
return reportCollection;
|
|
8029
8228
|
}
|
|
8030
|
-
var routeTail = normalizedView.replace('/report/', '').replace(/\//g, '-');
|
|
8031
|
-
var routeCandidate = routeTail ? "report-".concat(routeTail) : '';
|
|
8032
|
-
if (routeCandidate && collectionNames.includes(routeCandidate)) {
|
|
8033
|
-
return routeCandidate;
|
|
8034
|
-
}
|
|
8035
8229
|
return null;
|
|
8036
8230
|
}
|
|
8037
8231
|
function resolveBaseCollectionFromReport(db, dbName, collection) {
|
|
@@ -8069,7 +8263,7 @@ function resolveCollectionOverrideWithContext(params) {
|
|
|
8069
8263
|
to: reportPreferred,
|
|
8070
8264
|
fromScore: 0,
|
|
8071
8265
|
toScore: 0,
|
|
8072
|
-
reason: 'report route preference'
|
|
8266
|
+
reason: 'report builder route preference'
|
|
8073
8267
|
};
|
|
8074
8268
|
}
|
|
8075
8269
|
}
|
|
@@ -8677,14 +8871,43 @@ function userHasViewPermission(user, view) {
|
|
|
8677
8871
|
}
|
|
8678
8872
|
return false;
|
|
8679
8873
|
}
|
|
8680
|
-
function
|
|
8681
|
-
|
|
8874
|
+
function collectUserViewPermissions(user) {
|
|
8875
|
+
var _a, _b;
|
|
8876
|
+
if (!user) {
|
|
8877
|
+
return [];
|
|
8878
|
+
}
|
|
8879
|
+
var groups = Array.isArray((_a = user.roles) === null || _a === void 0 ? void 0 : _a.groups) ? user.roles.groups : [];
|
|
8880
|
+
var miscs = Array.isArray((_b = user.roles) === null || _b === void 0 ? void 0 : _b.miscs) ? user.roles.miscs : [];
|
|
8881
|
+
var collected = [];
|
|
8882
|
+
var seen = new Set();
|
|
8883
|
+
var push = function (value) {
|
|
8884
|
+
var normalized = normalizeOptionalString(value);
|
|
8885
|
+
if (!normalized || seen.has(normalized)) {
|
|
8886
|
+
return;
|
|
8887
|
+
}
|
|
8888
|
+
seen.add(normalized);
|
|
8889
|
+
collected.push(normalized);
|
|
8890
|
+
};
|
|
8891
|
+
groups.forEach(function (group) {
|
|
8892
|
+
var views = Array.isArray(group === null || group === void 0 ? void 0 : group.views) ? group.views : [];
|
|
8893
|
+
views.forEach(push);
|
|
8894
|
+
});
|
|
8895
|
+
miscs.forEach(push);
|
|
8896
|
+
return collected;
|
|
8897
|
+
}
|
|
8898
|
+
function userHasViewTokenPermission(user, tokenRegex) {
|
|
8899
|
+
var _a;
|
|
8900
|
+
if (!user || !tokenRegex) {
|
|
8682
8901
|
return false;
|
|
8683
8902
|
}
|
|
8684
|
-
|
|
8903
|
+
if ((_a = user.roles) === null || _a === void 0 ? void 0 : _a.super_admin) {
|
|
8904
|
+
return true;
|
|
8905
|
+
}
|
|
8906
|
+
var permissions = collectUserViewPermissions(user);
|
|
8907
|
+
return permissions.some(function (view) { return tokenRegex.test(view); });
|
|
8685
8908
|
}
|
|
8686
8909
|
function userHasInvoiceAccess(user) {
|
|
8687
|
-
return
|
|
8910
|
+
return userHasViewTokenPermission(user, /invoice/i);
|
|
8688
8911
|
}
|
|
8689
8912
|
function requiresInvoicePermission(collection) {
|
|
8690
8913
|
var normalized = normalizeOptionalString(collection).toLowerCase();
|
|
@@ -8736,16 +8959,59 @@ function resolveCodexWorkerThreadEnabled() {
|
|
|
8736
8959
|
}
|
|
8737
8960
|
return process.env.IS_WORKER_INSTANCE !== 'true';
|
|
8738
8961
|
}
|
|
8739
|
-
function
|
|
8740
|
-
|
|
8741
|
-
|
|
8962
|
+
function normalizeCodexModelList(value) {
|
|
8963
|
+
if (Array.isArray(value)) {
|
|
8964
|
+
return value
|
|
8965
|
+
.map(function (entry) { return normalizeOptionalString(entry); })
|
|
8966
|
+
.filter(Boolean);
|
|
8967
|
+
}
|
|
8968
|
+
var raw = normalizeOptionalString(value);
|
|
8969
|
+
if (!raw) {
|
|
8970
|
+
return [];
|
|
8971
|
+
}
|
|
8972
|
+
return raw
|
|
8973
|
+
.split(',')
|
|
8974
|
+
.map(function (entry) { return normalizeOptionalString(entry); })
|
|
8975
|
+
.filter(Boolean);
|
|
8976
|
+
}
|
|
8977
|
+
function resolveCodexModel(config) {
|
|
8978
|
+
var serverConfig = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
8979
|
+
var raw = normalizeOptionalString((config === null || config === void 0 ? void 0 : config.model)
|
|
8980
|
+
|| (config === null || config === void 0 ? void 0 : config.codex_model)
|
|
8981
|
+
|| serverConfig['AI_ASSISTANT_CODEX_MODEL']
|
|
8742
8982
|
|| process.env.AI_ASSISTANT_CODEX_MODEL
|
|
8743
|
-
||
|
|
8983
|
+
|| serverConfig['AI_TERMINAL_CODEX_MODEL']
|
|
8744
8984
|
|| process.env.AI_TERMINAL_CODEX_MODEL
|
|
8745
|
-
||
|
|
8985
|
+
|| serverConfig['AI_DASHBOARD_CODEX_MODEL']
|
|
8746
8986
|
|| process.env.AI_DASHBOARD_CODEX_MODEL);
|
|
8747
8987
|
return raw || DEFAULT_CODEX_MODEL;
|
|
8748
8988
|
}
|
|
8989
|
+
function resolveCodexFallbackModels(config, primaryModel) {
|
|
8990
|
+
var serverConfig = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
8991
|
+
var primary = normalizeOptionalString(primaryModel || resolveCodexModel(config));
|
|
8992
|
+
var models = [];
|
|
8993
|
+
var push = function (value) {
|
|
8994
|
+
var normalized = normalizeOptionalString(value);
|
|
8995
|
+
if (!normalized || normalized === primary || models.includes(normalized)) {
|
|
8996
|
+
return;
|
|
8997
|
+
}
|
|
8998
|
+
models.push(normalized);
|
|
8999
|
+
};
|
|
9000
|
+
normalizeCodexModelList(config === null || config === void 0 ? void 0 : config.fallback_models).forEach(push);
|
|
9001
|
+
normalizeCodexModelList(config === null || config === void 0 ? void 0 : config.fallbackModels).forEach(push);
|
|
9002
|
+
push(config === null || config === void 0 ? void 0 : config.fallback_model);
|
|
9003
|
+
push(config === null || config === void 0 ? void 0 : config.fallbackModel);
|
|
9004
|
+
normalizeCodexModelList(serverConfig['AI_ASSISTANT_CODEX_FALLBACK_MODELS'] || process.env.AI_ASSISTANT_CODEX_FALLBACK_MODELS).forEach(push);
|
|
9005
|
+
push(serverConfig['AI_ASSISTANT_CODEX_FALLBACK_MODEL'] || process.env.AI_ASSISTANT_CODEX_FALLBACK_MODEL);
|
|
9006
|
+
normalizeCodexModelList(serverConfig['AI_TERMINAL_CODEX_FALLBACK_MODELS'] || process.env.AI_TERMINAL_CODEX_FALLBACK_MODELS).forEach(push);
|
|
9007
|
+
push(serverConfig['AI_TERMINAL_CODEX_FALLBACK_MODEL'] || process.env.AI_TERMINAL_CODEX_FALLBACK_MODEL);
|
|
9008
|
+
normalizeCodexModelList(serverConfig['AI_DASHBOARD_CODEX_FALLBACK_MODELS'] || process.env.AI_DASHBOARD_CODEX_FALLBACK_MODELS).forEach(push);
|
|
9009
|
+
push(serverConfig['AI_DASHBOARD_CODEX_FALLBACK_MODEL'] || process.env.AI_DASHBOARD_CODEX_FALLBACK_MODEL);
|
|
9010
|
+
if (!models.length) {
|
|
9011
|
+
push(DEFAULT_CODEX_FALLBACK_MODEL);
|
|
9012
|
+
}
|
|
9013
|
+
return models;
|
|
9014
|
+
}
|
|
8749
9015
|
function resolveCodexThoughtLevel() {
|
|
8750
9016
|
var config = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
8751
9017
|
var raw = normalizeOptionalString(config['AI_ASSISTANT_CODEX_THOUGHT_LEVEL']
|
|
@@ -8760,25 +9026,38 @@ function resolveCodexThoughtLevel() {
|
|
|
8760
9026
|
}
|
|
8761
9027
|
return 'low';
|
|
8762
9028
|
}
|
|
8763
|
-
function resolveCodexSettings() {
|
|
9029
|
+
function resolveCodexSettings(options) {
|
|
8764
9030
|
var serverConfig = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
8765
9031
|
var apiKey = (serverConfig['OPENAI_API_KEY'] || process.env.OPENAI_API_KEY || '').trim();
|
|
8766
9032
|
if (!apiKey) {
|
|
8767
9033
|
throw new Error('OpenAI API key missing. Add OPENAI_API_KEY to server config.');
|
|
8768
9034
|
}
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
model: resolveCodexModel(),
|
|
8773
|
-
maxRetries: normalizeOptionalNumber(serverConfig['OPENAI_MAX_RETRIES'] || process.env.OPENAI_MAX_RETRIES),
|
|
8774
|
-
retryDelayMs: normalizeOptionalNumber(serverConfig['OPENAI_RETRY_DELAY_MS'] || process.env.OPENAI_RETRY_DELAY_MS)
|
|
8775
|
-
};
|
|
9035
|
+
var model = normalizeOptionalString(options === null || options === void 0 ? void 0 : options.model) || resolveCodexModel();
|
|
9036
|
+
var fallbackModels = resolveCodexFallbackModels({ fallbackModels: options === null || options === void 0 ? void 0 : options.fallbackModels }, model);
|
|
9037
|
+
return __assign(__assign({ apiKey: apiKey, baseUrl: (serverConfig['OPENAI_BASE_URL'] || process.env.OPENAI_BASE_URL || '').trim() || undefined, model: model }, (fallbackModels.length ? { fallbackModel: fallbackModels[0], fallbackModels: fallbackModels } : {})), { maxRetries: normalizeOptionalNumber(serverConfig['OPENAI_MAX_RETRIES'] || process.env.OPENAI_MAX_RETRIES), retryDelayMs: normalizeOptionalNumber(serverConfig['OPENAI_RETRY_DELAY_MS'] || process.env.OPENAI_RETRY_DELAY_MS) });
|
|
8776
9038
|
}
|
|
8777
|
-
function
|
|
8778
|
-
|
|
8779
|
-
|
|
9039
|
+
function buildAssistantCodexClientCacheKey(config) {
|
|
9040
|
+
var _a, _b;
|
|
9041
|
+
return JSON.stringify({
|
|
9042
|
+
apiKey: normalizeOptionalString(config === null || config === void 0 ? void 0 : config.apiKey),
|
|
9043
|
+
baseUrl: normalizeOptionalString(config === null || config === void 0 ? void 0 : config.baseUrl),
|
|
9044
|
+
model: normalizeOptionalString(config === null || config === void 0 ? void 0 : config.model),
|
|
9045
|
+
fallbackModel: normalizeOptionalString(config === null || config === void 0 ? void 0 : config.fallbackModel),
|
|
9046
|
+
fallbackModels: normalizeCodexModelList(config === null || config === void 0 ? void 0 : config.fallbackModels),
|
|
9047
|
+
maxRetries: (_a = config === null || config === void 0 ? void 0 : config.maxRetries) !== null && _a !== void 0 ? _a : null,
|
|
9048
|
+
retryDelayMs: (_b = config === null || config === void 0 ? void 0 : config.retryDelayMs) !== null && _b !== void 0 ? _b : null
|
|
9049
|
+
});
|
|
9050
|
+
}
|
|
9051
|
+
function getAssistantCodexClient(config) {
|
|
9052
|
+
var resolved = config || resolveCodexSettings();
|
|
9053
|
+
var key = buildAssistantCodexClientCacheKey(resolved);
|
|
9054
|
+
var existing = assistantCodexClientByConfig.get(key);
|
|
9055
|
+
if (existing) {
|
|
9056
|
+
return existing;
|
|
8780
9057
|
}
|
|
8781
|
-
|
|
9058
|
+
var client = new codex_client_1.CodexClient(resolved);
|
|
9059
|
+
assistantCodexClientByConfig.set(key, client);
|
|
9060
|
+
return client;
|
|
8782
9061
|
}
|
|
8783
9062
|
var CodexWorkerBootstrapError = /** @class */ (function (_super) {
|
|
8784
9063
|
__extends(CodexWorkerBootstrapError, _super);
|
|
@@ -8873,14 +9152,14 @@ function runCodexInWorkerThread(prompt, runOptions, config, streamStatusHandler)
|
|
|
8873
9152
|
case 0:
|
|
8874
9153
|
streamedOptions = applyCodexStreamStatusHandler(runOptions, streamStatusHandler);
|
|
8875
9154
|
if (!!resolveCodexWorkerThreadEnabled()) return [3 /*break*/, 2];
|
|
8876
|
-
codexClient = getAssistantCodexClient();
|
|
9155
|
+
codexClient = getAssistantCodexClient(config);
|
|
8877
9156
|
return [4 /*yield*/, codexClient.run(prompt, streamedOptions)];
|
|
8878
9157
|
case 1: return [2 /*return*/, _a.sent()];
|
|
8879
9158
|
case 2: return [4 /*yield*/, resolveCodexWorkerPath()];
|
|
8880
9159
|
case 3:
|
|
8881
9160
|
workerPath = _a.sent();
|
|
8882
9161
|
if (!!workerPath) return [3 /*break*/, 5];
|
|
8883
|
-
codexClient = getAssistantCodexClient();
|
|
9162
|
+
codexClient = getAssistantCodexClient(config);
|
|
8884
9163
|
return [4 /*yield*/, codexClient.run(prompt, streamedOptions)];
|
|
8885
9164
|
case 4: return [2 /*return*/, _a.sent()];
|
|
8886
9165
|
case 5:
|
|
@@ -8893,7 +9172,7 @@ function runCodexInWorkerThread(prompt, runOptions, config, streamStatusHandler)
|
|
|
8893
9172
|
throw error_4;
|
|
8894
9173
|
}
|
|
8895
9174
|
console.error('Codex worker bootstrap failed, falling back to in-process run.', error_4);
|
|
8896
|
-
codexClient = getAssistantCodexClient();
|
|
9175
|
+
codexClient = getAssistantCodexClient(config);
|
|
8897
9176
|
return [4 /*yield*/, codexClient.run(prompt, streamedOptions)];
|
|
8898
9177
|
case 8: return [2 /*return*/, _a.sent()];
|
|
8899
9178
|
case 9: return [2 /*return*/];
|
|
@@ -9055,7 +9334,8 @@ function sanitizeCodexRunOptions(options) {
|
|
|
9055
9334
|
timeoutMs: options.timeoutMs,
|
|
9056
9335
|
threadOptions: options.threadOptions,
|
|
9057
9336
|
threadKey: options.threadKey,
|
|
9058
|
-
reuseThread: options.reuseThread
|
|
9337
|
+
reuseThread: options.reuseThread,
|
|
9338
|
+
fallbackModels: options.fallbackModels
|
|
9059
9339
|
};
|
|
9060
9340
|
}
|
|
9061
9341
|
function resolveCodexWorkerPath() {
|
|
@@ -9438,6 +9718,10 @@ function buildAssistantContext(input, userContext) {
|
|
|
9438
9718
|
lines.push(hint);
|
|
9439
9719
|
});
|
|
9440
9720
|
}
|
|
9721
|
+
var recentToolError = normalizeOptionalString(userContext === null || userContext === void 0 ? void 0 : userContext.recentToolError);
|
|
9722
|
+
if (recentToolError) {
|
|
9723
|
+
lines.push("Most recent data-query error: ".concat(recentToolError));
|
|
9724
|
+
}
|
|
9441
9725
|
var mongoDb = normalizeOptionalString((_c = input === null || input === void 0 ? void 0 : input.mongo) === null || _c === void 0 ? void 0 : _c.database);
|
|
9442
9726
|
var mongoDbs = Array.isArray((_d = input === null || input === void 0 ? void 0 : input.mongo) === null || _d === void 0 ? void 0 : _d.databases)
|
|
9443
9727
|
? input.mongo.databases.map(function (value) { return normalizeOptionalString(value); }).filter(Boolean)
|
|
@@ -9534,6 +9818,34 @@ function buildAssistantFieldHints(message, collectionNames, options) {
|
|
|
9534
9818
|
});
|
|
9535
9819
|
return hints;
|
|
9536
9820
|
}
|
|
9821
|
+
function isAssistantWhyFollowupMessage(message) {
|
|
9822
|
+
var normalized = normalizeOptionalString(message).toLowerCase();
|
|
9823
|
+
if (!normalized) {
|
|
9824
|
+
return false;
|
|
9825
|
+
}
|
|
9826
|
+
return /^(so\s+)?why(?:\s+not)?[.!?]*$/.test(normalized)
|
|
9827
|
+
|| /^(so\s+)?why\b/.test(normalized);
|
|
9828
|
+
}
|
|
9829
|
+
function resolveRecentAssistantToolError(history) {
|
|
9830
|
+
var _a, _b;
|
|
9831
|
+
var entries = Array.isArray(history) ? history : [];
|
|
9832
|
+
for (var i = entries.length - 1; i >= 0; i -= 1) {
|
|
9833
|
+
var entry = entries[i];
|
|
9834
|
+
if ((entry === null || entry === void 0 ? void 0 : entry.role) !== 'assistant') {
|
|
9835
|
+
continue;
|
|
9836
|
+
}
|
|
9837
|
+
var notes = Array.isArray((_b = (_a = entry === null || entry === void 0 ? void 0 : entry.metadata) === null || _a === void 0 ? void 0 : _a.debug) === null || _b === void 0 ? void 0 : _b.notes)
|
|
9838
|
+
? entry.metadata.debug.notes
|
|
9839
|
+
: [];
|
|
9840
|
+
var matched = notes
|
|
9841
|
+
.map(function (note) { return normalizeOptionalString(note); })
|
|
9842
|
+
.find(function (note) { return note.toLowerCase().startsWith('tool error:'); });
|
|
9843
|
+
if (matched) {
|
|
9844
|
+
return matched.replace(/^tool error:\s*/i, '').trim();
|
|
9845
|
+
}
|
|
9846
|
+
}
|
|
9847
|
+
return '';
|
|
9848
|
+
}
|
|
9537
9849
|
var cachedClientRouteIndex = null;
|
|
9538
9850
|
function normalizeRouteKey(value) {
|
|
9539
9851
|
var trimmed = normalizeOptionalString(value);
|