@resolveio/server-lib 22.0.8 → 22.0.10
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
CHANGED
|
@@ -166,6 +166,9 @@ var AI_ASSISTANT_PLANNER_MAX_ROUTES = 200;
|
|
|
166
166
|
var AI_ASSISTANT_PLANNER_DEBUG_MAX_CHARS = 2000;
|
|
167
167
|
var AI_ASSISTANT_LOCALE = 'en-US';
|
|
168
168
|
var AI_ASSISTANT_CURRENCY_CODE = 'USD';
|
|
169
|
+
var AI_ASSISTANT_USD_CURRENCY_TEXT_PATTERN = /\b(?:USD|US\$)(?:\s| | |[\u00A0\u202F\u2007])*\$?\s*([-+]?[0-9][0-9,]*(?:\.[0-9]+)?)/gi;
|
|
170
|
+
var AI_ASSISTANT_REVENUE_VERIFY_DIFF_WARN_THRESHOLD = 0.15;
|
|
171
|
+
var AI_ASSISTANT_REVENUE_VERIFY_PAID_GRAND_GAP_WARN_THRESHOLD = 0.10;
|
|
169
172
|
var AI_ASSISTANT_PROGRESS_TICKS = [
|
|
170
173
|
'Grabbing Data',
|
|
171
174
|
'Drafting response'
|
|
@@ -489,6 +492,7 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
|
|
|
489
492
|
'- REPORT_BUILDER_AGG: {"collection":"<name>","pipeline":[...],"options":{"allowDiskUse":true,"limit":20},"permissionView":"</route>"}',
|
|
490
493
|
'- For invoice data, set permissionView to an invoice route (ex: /invoice/list or /report/invoice).',
|
|
491
494
|
'- 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
|
+
'- 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.',
|
|
492
496
|
'- For relative date ranges (last/past/recent), include an upper bound <= $$NOW unless the user specifies a future end date.',
|
|
493
497
|
'- Keep queries minimal, read-only, and avoid user/credential data unless the user is a super admin.',
|
|
494
498
|
'- Assume you are not a super admin unless explicitly told otherwise.',
|
|
@@ -1799,6 +1803,8 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1799
1803
|
if (!assistantContent) {
|
|
1800
1804
|
assistantContent = buildAssistantCodexErrorMessage(null);
|
|
1801
1805
|
}
|
|
1806
|
+
assistantContent = applyAssistantVerificationNotes(assistantContent, toolResult);
|
|
1807
|
+
assistantContent = normalizeAssistantCurrencyText(assistantContent);
|
|
1802
1808
|
if (aiWorkerDebug) {
|
|
1803
1809
|
finishedAt = Date.now();
|
|
1804
1810
|
console.log(new Date(), '[AI Worker Debug] codex run complete', {
|
|
@@ -2398,7 +2404,7 @@ function executeAiAssistantMongoRead(payload, context) {
|
|
|
2398
2404
|
}
|
|
2399
2405
|
function executeAiAssistantMongoAggregate(payload, context) {
|
|
2400
2406
|
return __awaiter(this, void 0, void 0, function () {
|
|
2401
|
-
var input, rawCollection, dbName, db, collectionResolution, collection, bridgeCollection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, sanitizedPipeline, strippedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, dateField, aggregateOptions, documents, executedPipeline, probeDocs, fallback, fallbackPipeline, fallbackDocs, createdFallback, createdPipeline, createdDocs, expanded, expandedDocs, completionFallback, fallbackPipeline, fallbackDocs, completionExprFallback, fallbackPipeline, fallbackDocs, unwindFallback, shouldUnwind, _c, _d, fallbackPipeline, fallbackDocs, nameFallback, fallbackPipeline, fallbackDocs, _e, _loop_1, i, state_1, matchFields_1, _f, aliases, rewrittenPipeline, fallbackDocs, _loop_2, i, state_2, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, matchStages, diagnostics, combinedMatch, nameFields, dateFields, queryNoName, _g, queryNoDate, _h, _j, _k, _l, allCollections, base, alt, altCount, _m, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
|
|
2407
|
+
var input, rawCollection, dbName, db, collectionResolution, collection, bridgeCollection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, sanitizedPipeline, strippedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, dateField, aggregateOptions, documents, executedPipeline, probeDocs, fallback, fallbackPipeline, fallbackDocs, createdFallback, createdPipeline, createdDocs, expanded, expandedDocs, completionFallback, fallbackPipeline, fallbackDocs, completionExprFallback, fallbackPipeline, fallbackDocs, unwindFallback, shouldUnwind, _c, _d, fallbackPipeline, fallbackDocs, nameFallback, fallbackPipeline, fallbackDocs, _e, _loop_1, i, state_1, matchFields_1, _f, aliases, rewrittenPipeline, fallbackDocs, _loop_2, i, state_2, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, matchStages, diagnostics, combinedMatch, nameFields, dateFields, queryNoName, _g, queryNoDate, _h, _j, _k, _l, allCollections, base, alt, altCount, _m, verification, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
|
|
2402
2408
|
var _o, _p;
|
|
2403
2409
|
return __generator(this, function (_q) {
|
|
2404
2410
|
switch (_q.label) {
|
|
@@ -2975,7 +2981,15 @@ function executeAiAssistantMongoAggregate(payload, context) {
|
|
|
2975
2981
|
case 60:
|
|
2976
2982
|
fallbackMeta.zeroDiagnostics = diagnostics;
|
|
2977
2983
|
_q.label = 61;
|
|
2978
|
-
case 61:
|
|
2984
|
+
case 61: return [4 /*yield*/, verifyAssistantAggregateReliability({
|
|
2985
|
+
db: db,
|
|
2986
|
+
collection: collection,
|
|
2987
|
+
pipeline: executedPipeline,
|
|
2988
|
+
documents: documents,
|
|
2989
|
+
aggregateOptions: aggregateOptions
|
|
2990
|
+
})];
|
|
2991
|
+
case 62:
|
|
2992
|
+
verification = _q.sent();
|
|
2979
2993
|
sanitizedDocuments = isSuperAdmin
|
|
2980
2994
|
? documents
|
|
2981
2995
|
: documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
|
|
@@ -2990,7 +3004,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
|
|
|
2990
3004
|
idCustomer: customerId,
|
|
2991
3005
|
isSuperAdmin: isSuperAdmin
|
|
2992
3006
|
})];
|
|
2993
|
-
case
|
|
3007
|
+
case 63:
|
|
2994
3008
|
idLookupDisplay = _q.sent();
|
|
2995
3009
|
if (idLookupDisplay === null || idLookupDisplay === void 0 ? void 0 : idLookupDisplay.docs) {
|
|
2996
3010
|
displayDocs = idLookupDisplay.docs;
|
|
@@ -3004,27 +3018,482 @@ function executeAiAssistantMongoAggregate(payload, context) {
|
|
|
3004
3018
|
maxRows: normalizedOptions.limit || sanitizedDocuments.length,
|
|
3005
3019
|
includeGroupFromId: true
|
|
3006
3020
|
});
|
|
3007
|
-
return [2 /*return*/, __assign({ documents: sanitizedDocuments, display: display }, (isSuperAdmin ? {
|
|
3008
|
-
debug: {
|
|
3009
|
-
collection: collection,
|
|
3010
|
-
collectionRequested: rawCollection,
|
|
3011
|
-
collectionResolved: collection,
|
|
3012
|
-
collectionMatched: collectionResolution.matched,
|
|
3013
|
-
collectionCandidates: collectionResolution.candidates,
|
|
3014
|
-
collectionScore: collectionResolution.score,
|
|
3015
|
-
bridge: 'report-builder',
|
|
3016
|
-
database: dbName,
|
|
3017
|
-
query: scopedQuery,
|
|
3018
|
-
options: normalizedOptions.aggregateOptions,
|
|
3019
|
-
originalPipeline: limitedPipeline,
|
|
3020
|
-
executedPipeline: executedPipeline,
|
|
3021
|
-
fallbacks: fallbackMeta
|
|
3022
|
-
}
|
|
3021
|
+
return [2 /*return*/, __assign(__assign({ documents: sanitizedDocuments, display: display }, (verification ? { verification: verification } : {})), (isSuperAdmin ? {
|
|
3022
|
+
debug: __assign(__assign({ collection: collection, collectionRequested: rawCollection, collectionResolved: collection, collectionMatched: collectionResolution.matched, collectionCandidates: collectionResolution.candidates, collectionScore: collectionResolution.score, bridge: 'report-builder', database: dbName, query: scopedQuery, options: normalizedOptions.aggregateOptions, originalPipeline: limitedPipeline, executedPipeline: executedPipeline }, (verification ? { verification: verification } : {})), { fallbacks: fallbackMeta })
|
|
3023
3023
|
} : {}))];
|
|
3024
3024
|
}
|
|
3025
3025
|
});
|
|
3026
3026
|
});
|
|
3027
3027
|
}
|
|
3028
|
+
function verifyAssistantAggregateReliability(params) {
|
|
3029
|
+
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;
|
|
3031
|
+
var _d, _e;
|
|
3032
|
+
var _f;
|
|
3033
|
+
return __generator(this, function (_g) {
|
|
3034
|
+
switch (_g.label) {
|
|
3035
|
+
case 0:
|
|
3036
|
+
collection = normalizeOptionalString(params.collection).toLowerCase();
|
|
3037
|
+
collectionBase = collection.startsWith('report-') ? collection.slice('report-'.length) : collection;
|
|
3038
|
+
if (collectionBase !== 'invoices') {
|
|
3039
|
+
return [2 /*return*/, null];
|
|
3040
|
+
}
|
|
3041
|
+
monthKey = resolveAssistantMonthlyKey(params.documents);
|
|
3042
|
+
if (!monthKey) {
|
|
3043
|
+
return [2 /*return*/, null];
|
|
3044
|
+
}
|
|
3045
|
+
amountKey = resolveAssistantNumericAmountKey(params.documents, monthKey);
|
|
3046
|
+
if (!amountKey) {
|
|
3047
|
+
return [2 /*return*/, null];
|
|
3048
|
+
}
|
|
3049
|
+
baseMap = mapAssistantRevenueByMonth(params.documents, monthKey, amountKey);
|
|
3050
|
+
if (!baseMap.size) {
|
|
3051
|
+
return [2 /*return*/, null];
|
|
3052
|
+
}
|
|
3053
|
+
groupIndex = findAggregateGroupIndex(params.pipeline || []);
|
|
3054
|
+
if (groupIndex === -1) {
|
|
3055
|
+
return [2 /*return*/, null];
|
|
3056
|
+
}
|
|
3057
|
+
groupPaths = extractGroupFieldPaths(((_f = params.pipeline[groupIndex]) === null || _f === void 0 ? void 0 : _f.$group) || {});
|
|
3058
|
+
dateField = groupPaths.find(function (field) { return /(date|paid|invoice|created|updated|_at)$/i.test(field); })
|
|
3059
|
+
|| groupPaths.find(function (field) { return /(date|paid|invoice|created|updated)/i.test(field); })
|
|
3060
|
+
|| 'date_paid';
|
|
3061
|
+
mergedMatch = mergeAssistantPreGroupMatchStages(params.pipeline || [], groupIndex);
|
|
3062
|
+
dateFieldsInMatch = collectMatchFieldsByCondition(mergedMatch, function (_field, condition) { return isDateCondition(condition); });
|
|
3063
|
+
baseMatchNoDate = dateFieldsInMatch.length ? stripMatchFields(mergedMatch, dateFieldsInMatch) : mergedMatch;
|
|
3064
|
+
primaryDateCondition = findMatchConditionForField(mergedMatch, dateField);
|
|
3065
|
+
verifyPipeline = buildAssistantMonthlyRevenueVerificationPipeline(mergedMatch, dateField);
|
|
3066
|
+
verifyDocs = [];
|
|
3067
|
+
_g.label = 1;
|
|
3068
|
+
case 1:
|
|
3069
|
+
_g.trys.push([1, 3, , 4]);
|
|
3070
|
+
return [4 /*yield*/, params.db.collection(params.collection)
|
|
3071
|
+
.aggregate(verifyPipeline, params.aggregateOptions || {})
|
|
3072
|
+
.toArray()];
|
|
3073
|
+
case 2:
|
|
3074
|
+
verifyDocs = _g.sent();
|
|
3075
|
+
return [3 /*break*/, 4];
|
|
3076
|
+
case 3:
|
|
3077
|
+
_a = _g.sent();
|
|
3078
|
+
return [2 /*return*/, {
|
|
3079
|
+
type: 'invoice_revenue_monthly',
|
|
3080
|
+
checks: [
|
|
3081
|
+
{ name: 'Cross-check query', status: 'warn', details: 'Verification query failed; result not cross-checked.' }
|
|
3082
|
+
],
|
|
3083
|
+
warnings: ['Verification query failed, so this total was not independently cross-checked.'],
|
|
3084
|
+
metrics: {
|
|
3085
|
+
baselineField: amountKey,
|
|
3086
|
+
dateField: dateField
|
|
3087
|
+
}
|
|
3088
|
+
}];
|
|
3089
|
+
case 4:
|
|
3090
|
+
verifyMap = mapAssistantVerificationDocsByMonth(verifyDocs);
|
|
3091
|
+
comparedMonths = 0;
|
|
3092
|
+
paidCloserCount = 0;
|
|
3093
|
+
grandCloserCount = 0;
|
|
3094
|
+
sumPaidDiffPct = 0;
|
|
3095
|
+
sumGrandDiffPct = 0;
|
|
3096
|
+
maxPaidDiffPct = 0;
|
|
3097
|
+
maxGrandDiffPct = 0;
|
|
3098
|
+
sumPaidGrandGapPct = 0;
|
|
3099
|
+
highVarianceMonths = [];
|
|
3100
|
+
baseMap.forEach(function (value, month) {
|
|
3101
|
+
var match = verifyMap.get(month);
|
|
3102
|
+
if (!match) {
|
|
3103
|
+
return;
|
|
3104
|
+
}
|
|
3105
|
+
comparedMonths += 1;
|
|
3106
|
+
var paidDiff = Math.abs(value - match.paid);
|
|
3107
|
+
var grandDiff = Math.abs(value - match.grand);
|
|
3108
|
+
var denom = Math.max(Math.abs(value), 1);
|
|
3109
|
+
var paidPct = paidDiff / denom;
|
|
3110
|
+
var grandPct = grandDiff / denom;
|
|
3111
|
+
sumPaidDiffPct += paidPct;
|
|
3112
|
+
sumGrandDiffPct += grandPct;
|
|
3113
|
+
maxPaidDiffPct = Math.max(maxPaidDiffPct, paidPct);
|
|
3114
|
+
maxGrandDiffPct = Math.max(maxGrandDiffPct, grandPct);
|
|
3115
|
+
if (paidDiff < grandDiff) {
|
|
3116
|
+
paidCloserCount += 1;
|
|
3117
|
+
}
|
|
3118
|
+
else if (grandDiff < paidDiff) {
|
|
3119
|
+
grandCloserCount += 1;
|
|
3120
|
+
}
|
|
3121
|
+
var gapPct = Math.abs(match.paid - match.grand) / Math.max(Math.abs(match.grand), 1);
|
|
3122
|
+
sumPaidGrandGapPct += gapPct;
|
|
3123
|
+
if (Math.min(paidPct, grandPct) >= AI_ASSISTANT_REVENUE_VERIFY_DIFF_WARN_THRESHOLD) {
|
|
3124
|
+
highVarianceMonths.push(month);
|
|
3125
|
+
}
|
|
3126
|
+
});
|
|
3127
|
+
checks = [];
|
|
3128
|
+
warnings = [];
|
|
3129
|
+
avgPaidDiffPct = comparedMonths ? (sumPaidDiffPct / comparedMonths) : 0;
|
|
3130
|
+
avgGrandDiffPct = comparedMonths ? (sumGrandDiffPct / comparedMonths) : 0;
|
|
3131
|
+
avgPaidGrandGapPct = comparedMonths ? (sumPaidGrandGapPct / comparedMonths) : 0;
|
|
3132
|
+
baselineMetric = 'unknown';
|
|
3133
|
+
if (comparedMonths) {
|
|
3134
|
+
if (paidCloserCount > grandCloserCount) {
|
|
3135
|
+
baselineMetric = 'paid_total (date_paid)';
|
|
3136
|
+
}
|
|
3137
|
+
else if (grandCloserCount > paidCloserCount) {
|
|
3138
|
+
baselineMetric = 'grand_total (date_paid)';
|
|
3139
|
+
}
|
|
3140
|
+
else {
|
|
3141
|
+
baselineMetric = 'mixed';
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
if (!comparedMonths) {
|
|
3145
|
+
checks.push({
|
|
3146
|
+
name: 'Cross-check coverage',
|
|
3147
|
+
status: 'warn',
|
|
3148
|
+
details: 'No overlapping month rows were available for verification.'
|
|
3149
|
+
});
|
|
3150
|
+
warnings.push('Could not cross-check this result against alternate invoice total fields for the same months.');
|
|
3151
|
+
}
|
|
3152
|
+
else {
|
|
3153
|
+
checks.push({
|
|
3154
|
+
name: 'Metric alignment',
|
|
3155
|
+
status: baselineMetric === 'mixed' ? 'warn' : 'pass',
|
|
3156
|
+
details: "Result aligns most with ".concat(baselineMetric, ".")
|
|
3157
|
+
});
|
|
3158
|
+
if (baselineMetric === 'mixed') {
|
|
3159
|
+
warnings.push('Revenue appears to mix definitions across months (paid_total vs grand_total).');
|
|
3160
|
+
}
|
|
3161
|
+
checks.push({
|
|
3162
|
+
name: 'Field variance',
|
|
3163
|
+
status: avgPaidGrandGapPct >= AI_ASSISTANT_REVENUE_VERIFY_PAID_GRAND_GAP_WARN_THRESHOLD ? 'warn' : 'pass',
|
|
3164
|
+
details: "Average paid-vs-grand gap: ".concat((0, common_1.round)(avgPaidGrandGapPct * 100, 2), "%.")
|
|
3165
|
+
});
|
|
3166
|
+
if (avgPaidGrandGapPct >= AI_ASSISTANT_REVENUE_VERIFY_PAID_GRAND_GAP_WARN_THRESHOLD) {
|
|
3167
|
+
warnings.push("paid_total and grand_total differ materially for this period (".concat((0, common_1.round)(avgPaidGrandGapPct * 100, 2), "% average gap)."));
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3170
|
+
rollingWindow = detectAssistantRollingMonthWindow(params.pipeline || []);
|
|
3171
|
+
if ((rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.months) && (rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.upperNow)) {
|
|
3172
|
+
checks.push({
|
|
3173
|
+
name: 'Date window shape',
|
|
3174
|
+
status: 'warn',
|
|
3175
|
+
details: "Query uses rolling $$NOW bounds (last ".concat(rollingWindow.months, " months), which can include partial months.")
|
|
3176
|
+
});
|
|
3177
|
+
warnings.push("Date window is rolling (last ".concat(rollingWindow.months, " months to now), so first/current months may be partial."));
|
|
3178
|
+
}
|
|
3179
|
+
else {
|
|
3180
|
+
checks.push({
|
|
3181
|
+
name: 'Date window shape',
|
|
3182
|
+
status: 'pass',
|
|
3183
|
+
details: 'No rolling $$NOW month window pattern detected.'
|
|
3184
|
+
});
|
|
3185
|
+
}
|
|
3186
|
+
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 = resolveAssistantRollingWindowBounds(rollingWindow.months);
|
|
3189
|
+
fullMonthMatch = mergeAssistantMatch(baseMatchNoDate, (_d = {},
|
|
3190
|
+
_d[dateField] = {
|
|
3191
|
+
$gte: bounds.startOfWindow,
|
|
3192
|
+
$lt: bounds.startOfCurrentMonth
|
|
3193
|
+
},
|
|
3194
|
+
_d));
|
|
3195
|
+
_g.label = 5;
|
|
3196
|
+
case 5:
|
|
3197
|
+
_g.trys.push([5, 7, , 8]);
|
|
3198
|
+
return [4 /*yield*/, params.db.collection(params.collection)
|
|
3199
|
+
.aggregate(buildAssistantMonthlyRevenueVerificationPipeline(fullMonthMatch, dateField), params.aggregateOptions || {})
|
|
3200
|
+
.toArray()];
|
|
3201
|
+
case 6:
|
|
3202
|
+
fullMonthDocs = _g.sent();
|
|
3203
|
+
fullMonthMap = mapAssistantMetricByMonth(mapAssistantVerificationDocsByMonth(fullMonthDocs), normalizedMetric);
|
|
3204
|
+
fullMonthDiff = compareAssistantMonthlyValueMaps(baseMap, fullMonthMap);
|
|
3205
|
+
checks.push({
|
|
3206
|
+
name: 'Full-month cross-check',
|
|
3207
|
+
status: fullMonthDiff.comparedMonths && fullMonthDiff.avgDiffPct < AI_ASSISTANT_REVENUE_VERIFY_DIFF_WARN_THRESHOLD ? 'pass' : 'warn',
|
|
3208
|
+
details: fullMonthDiff.comparedMonths
|
|
3209
|
+
? "Compared ".concat(fullMonthDiff.comparedMonths, " month(s); avg diff ").concat((0, common_1.round)(fullMonthDiff.avgDiffPct * 100, 2), "%.")
|
|
3210
|
+
: 'No overlapping months for full-month cross-check.'
|
|
3211
|
+
});
|
|
3212
|
+
if (fullMonthDiff.comparedMonths && fullMonthDiff.avgDiffPct >= AI_ASSISTANT_REVENUE_VERIFY_DIFF_WARN_THRESHOLD) {
|
|
3213
|
+
warnings.push("Rolling-window totals differ from full-month totals by ".concat((0, common_1.round)(fullMonthDiff.avgDiffPct * 100, 2), "% on average."));
|
|
3214
|
+
}
|
|
3215
|
+
if (!fullMonthDiff.comparedMonths) {
|
|
3216
|
+
warnings.push('Could not compare rolling-window results against full-month buckets.');
|
|
3217
|
+
}
|
|
3218
|
+
return [3 /*break*/, 8];
|
|
3219
|
+
case 7:
|
|
3220
|
+
_b = _g.sent();
|
|
3221
|
+
checks.push({
|
|
3222
|
+
name: 'Full-month cross-check',
|
|
3223
|
+
status: 'warn',
|
|
3224
|
+
details: 'Full-month verification query failed.'
|
|
3225
|
+
});
|
|
3226
|
+
warnings.push('Full-month verification query failed.');
|
|
3227
|
+
return [3 /*break*/, 8];
|
|
3228
|
+
case 8:
|
|
3229
|
+
alternateDateField = dateField === 'date_paid'
|
|
3230
|
+
? 'date_invoice'
|
|
3231
|
+
: dateField === 'date_invoice'
|
|
3232
|
+
? 'date_paid'
|
|
3233
|
+
: '';
|
|
3234
|
+
if (!alternateDateField) return [3 /*break*/, 12];
|
|
3235
|
+
alternateDateCondition = null;
|
|
3236
|
+
if ((rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.months) && (rollingWindow === null || rollingWindow === void 0 ? void 0 : rollingWindow.upperNow)) {
|
|
3237
|
+
bounds = resolveAssistantRollingWindowBounds(rollingWindow.months);
|
|
3238
|
+
alternateDateCondition = {
|
|
3239
|
+
$gte: bounds.rollingStart,
|
|
3240
|
+
$lte: bounds.now
|
|
3241
|
+
};
|
|
3242
|
+
}
|
|
3243
|
+
else if (primaryDateCondition && typeof primaryDateCondition === 'object') {
|
|
3244
|
+
alternateDateCondition = primaryDateCondition;
|
|
3245
|
+
}
|
|
3246
|
+
if (!alternateDateCondition) return [3 /*break*/, 12];
|
|
3247
|
+
alternateMatch = mergeAssistantMatch(baseMatchNoDate, (_e = {}, _e[alternateDateField] = alternateDateCondition, _e));
|
|
3248
|
+
_g.label = 9;
|
|
3249
|
+
case 9:
|
|
3250
|
+
_g.trys.push([9, 11, , 12]);
|
|
3251
|
+
return [4 /*yield*/, params.db.collection(params.collection)
|
|
3252
|
+
.aggregate(buildAssistantMonthlyRevenueVerificationPipeline(alternateMatch, alternateDateField), params.aggregateOptions || {})
|
|
3253
|
+
.toArray()];
|
|
3254
|
+
case 10:
|
|
3255
|
+
alternateDocs = _g.sent();
|
|
3256
|
+
alternateMap = mapAssistantMetricByMonth(mapAssistantVerificationDocsByMonth(alternateDocs), normalizedMetric);
|
|
3257
|
+
alternateDiff = compareAssistantMonthlyValueMaps(baseMap, alternateMap);
|
|
3258
|
+
checks.push({
|
|
3259
|
+
name: "Alternate date field (".concat(alternateDateField, ")"),
|
|
3260
|
+
status: alternateDiff.comparedMonths && alternateDiff.avgDiffPct < AI_ASSISTANT_REVENUE_VERIFY_DIFF_WARN_THRESHOLD ? 'pass' : 'warn',
|
|
3261
|
+
details: alternateDiff.comparedMonths
|
|
3262
|
+
? "Compared ".concat(alternateDiff.comparedMonths, " month(s); avg diff ").concat((0, common_1.round)(alternateDiff.avgDiffPct * 100, 2), "%.")
|
|
3263
|
+
: 'No overlapping months for alternate date-field cross-check.'
|
|
3264
|
+
});
|
|
3265
|
+
if (alternateDiff.comparedMonths && alternateDiff.avgDiffPct >= AI_ASSISTANT_REVENUE_VERIFY_DIFF_WARN_THRESHOLD) {
|
|
3266
|
+
warnings.push("Switching from ".concat(dateField, " to ").concat(alternateDateField, " changes monthly totals by ").concat((0, common_1.round)(alternateDiff.avgDiffPct * 100, 2), "% on average."));
|
|
3267
|
+
}
|
|
3268
|
+
return [3 /*break*/, 12];
|
|
3269
|
+
case 11:
|
|
3270
|
+
_c = _g.sent();
|
|
3271
|
+
checks.push({
|
|
3272
|
+
name: "Alternate date field (".concat(alternateDateField, ")"),
|
|
3273
|
+
status: 'warn',
|
|
3274
|
+
details: 'Alternate date-field verification query failed.'
|
|
3275
|
+
});
|
|
3276
|
+
return [3 /*break*/, 12];
|
|
3277
|
+
case 12:
|
|
3278
|
+
if (highVarianceMonths.length) {
|
|
3279
|
+
warnings.push("High variance months vs both paid/grand checks: ".concat(highVarianceMonths.join(', '), "."));
|
|
3280
|
+
}
|
|
3281
|
+
return [2 /*return*/, {
|
|
3282
|
+
type: 'invoice_revenue_monthly',
|
|
3283
|
+
checks: checks,
|
|
3284
|
+
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
|
+
}
|
|
3295
|
+
}];
|
|
3296
|
+
}
|
|
3297
|
+
});
|
|
3298
|
+
});
|
|
3299
|
+
}
|
|
3300
|
+
function resolveAssistantMonthlyKey(documents) {
|
|
3301
|
+
var first = Array.isArray(documents) ? documents.find(function (doc) { return doc && typeof doc === 'object'; }) : null;
|
|
3302
|
+
if (!first) {
|
|
3303
|
+
return '';
|
|
3304
|
+
}
|
|
3305
|
+
return Object.keys(first).find(function (key) {
|
|
3306
|
+
var value = first[key];
|
|
3307
|
+
return typeof value === 'string' && /^\d{4}-\d{2}$/.test(value);
|
|
3308
|
+
}) || '';
|
|
3309
|
+
}
|
|
3310
|
+
function resolveAssistantNumericAmountKey(documents, monthKey) {
|
|
3311
|
+
var first = Array.isArray(documents) ? documents.find(function (doc) { return doc && typeof doc === 'object'; }) : null;
|
|
3312
|
+
if (!first) {
|
|
3313
|
+
return '';
|
|
3314
|
+
}
|
|
3315
|
+
var currencyLike = Object.keys(first).filter(function (key) {
|
|
3316
|
+
if (key === monthKey) {
|
|
3317
|
+
return false;
|
|
3318
|
+
}
|
|
3319
|
+
var value = Number(first[key]);
|
|
3320
|
+
if (!Number.isFinite(value)) {
|
|
3321
|
+
return false;
|
|
3322
|
+
}
|
|
3323
|
+
return /(revenue|amount|total|sales|billing|paid|grand)/i.test(key);
|
|
3324
|
+
});
|
|
3325
|
+
if (currencyLike.length) {
|
|
3326
|
+
return currencyLike[0];
|
|
3327
|
+
}
|
|
3328
|
+
return Object.keys(first).find(function (key) {
|
|
3329
|
+
if (key === monthKey) {
|
|
3330
|
+
return false;
|
|
3331
|
+
}
|
|
3332
|
+
return Number.isFinite(Number(first[key]));
|
|
3333
|
+
}) || '';
|
|
3334
|
+
}
|
|
3335
|
+
function mapAssistantRevenueByMonth(documents, monthKey, valueKey) {
|
|
3336
|
+
var mapped = new Map();
|
|
3337
|
+
(Array.isArray(documents) ? documents : []).forEach(function (doc) {
|
|
3338
|
+
var month = normalizeOptionalString(doc === null || doc === void 0 ? void 0 : doc[monthKey]);
|
|
3339
|
+
if (!month || !/^\d{4}-\d{2}$/.test(month)) {
|
|
3340
|
+
return;
|
|
3341
|
+
}
|
|
3342
|
+
var value = Number(doc === null || doc === void 0 ? void 0 : doc[valueKey]);
|
|
3343
|
+
if (!Number.isFinite(value)) {
|
|
3344
|
+
return;
|
|
3345
|
+
}
|
|
3346
|
+
mapped.set(month, value);
|
|
3347
|
+
});
|
|
3348
|
+
return mapped;
|
|
3349
|
+
}
|
|
3350
|
+
function mergeAssistantPreGroupMatchStages(pipeline, groupIndex) {
|
|
3351
|
+
var matches = [];
|
|
3352
|
+
for (var i = 0; i < groupIndex; i += 1) {
|
|
3353
|
+
var stage = pipeline[i];
|
|
3354
|
+
if (stage && typeof stage === 'object' && stage.$match && typeof stage.$match === 'object') {
|
|
3355
|
+
matches.push(stage.$match);
|
|
3356
|
+
}
|
|
3357
|
+
}
|
|
3358
|
+
if (!matches.length) {
|
|
3359
|
+
return {};
|
|
3360
|
+
}
|
|
3361
|
+
if (matches.length === 1) {
|
|
3362
|
+
return matches[0];
|
|
3363
|
+
}
|
|
3364
|
+
return { $and: matches };
|
|
3365
|
+
}
|
|
3366
|
+
function detectAssistantRollingMonthWindow(pipeline) {
|
|
3367
|
+
var raw = JSON.stringify(Array.isArray(pipeline) ? pipeline : []);
|
|
3368
|
+
if (!raw) {
|
|
3369
|
+
return null;
|
|
3370
|
+
}
|
|
3371
|
+
var amountMatch = raw.match(/"\$dateSubtract":\{"startDate":"\$\$NOW","unit":"month","amount":([0-9]+)\}/);
|
|
3372
|
+
if (!amountMatch) {
|
|
3373
|
+
return null;
|
|
3374
|
+
}
|
|
3375
|
+
var months = Number(amountMatch[1]);
|
|
3376
|
+
if (!Number.isFinite(months) || months < 1) {
|
|
3377
|
+
return null;
|
|
3378
|
+
}
|
|
3379
|
+
var nowCount = (raw.match(/\$\$NOW/g) || []).length;
|
|
3380
|
+
return {
|
|
3381
|
+
months: months,
|
|
3382
|
+
upperNow: nowCount >= 2
|
|
3383
|
+
};
|
|
3384
|
+
}
|
|
3385
|
+
function buildAssistantMonthlyRevenueVerificationPipeline(match, dateField) {
|
|
3386
|
+
var pipeline = [];
|
|
3387
|
+
if (match && typeof match === 'object' && Object.keys(match).length) {
|
|
3388
|
+
pipeline.push({ $match: match });
|
|
3389
|
+
}
|
|
3390
|
+
pipeline.push({
|
|
3391
|
+
$group: {
|
|
3392
|
+
_id: {
|
|
3393
|
+
$dateToString: {
|
|
3394
|
+
format: '%Y-%m',
|
|
3395
|
+
date: "$".concat(dateField)
|
|
3396
|
+
}
|
|
3397
|
+
},
|
|
3398
|
+
paid_total_sum: { $sum: { $ifNull: ['$paid_total', 0] } },
|
|
3399
|
+
grand_total_sum: { $sum: { $ifNull: ['$grand_total', 0] } },
|
|
3400
|
+
invoice_count: { $sum: 1 }
|
|
3401
|
+
}
|
|
3402
|
+
}, {
|
|
3403
|
+
$project: {
|
|
3404
|
+
_id: 0,
|
|
3405
|
+
month: '$_id',
|
|
3406
|
+
paid_total_sum: 1,
|
|
3407
|
+
grand_total_sum: 1,
|
|
3408
|
+
invoice_count: 1
|
|
3409
|
+
}
|
|
3410
|
+
}, { $sort: { month: 1 } }, { $limit: 36 });
|
|
3411
|
+
return pipeline;
|
|
3412
|
+
}
|
|
3413
|
+
function mapAssistantVerificationDocsByMonth(docs) {
|
|
3414
|
+
var mapped = new Map();
|
|
3415
|
+
(Array.isArray(docs) ? docs : []).forEach(function (row) {
|
|
3416
|
+
var month = normalizeOptionalString(row === null || row === void 0 ? void 0 : row.month);
|
|
3417
|
+
if (!month || !/^\d{4}-\d{2}$/.test(month)) {
|
|
3418
|
+
return;
|
|
3419
|
+
}
|
|
3420
|
+
var paid = Number(row === null || row === void 0 ? void 0 : row.paid_total_sum);
|
|
3421
|
+
var grand = Number(row === null || row === void 0 ? void 0 : row.grand_total_sum);
|
|
3422
|
+
var count = Number(row === null || row === void 0 ? void 0 : row.invoice_count);
|
|
3423
|
+
mapped.set(month, {
|
|
3424
|
+
paid: Number.isFinite(paid) ? paid : 0,
|
|
3425
|
+
grand: Number.isFinite(grand) ? grand : 0,
|
|
3426
|
+
count: Number.isFinite(count) ? count : 0
|
|
3427
|
+
});
|
|
3428
|
+
});
|
|
3429
|
+
return mapped;
|
|
3430
|
+
}
|
|
3431
|
+
function normalizeAssistantVerificationMetric(value) {
|
|
3432
|
+
var normalized = normalizeOptionalString(value).toLowerCase();
|
|
3433
|
+
if (normalized.startsWith('paid_total')) {
|
|
3434
|
+
return 'paid';
|
|
3435
|
+
}
|
|
3436
|
+
if (normalized.startsWith('grand_total')) {
|
|
3437
|
+
return 'grand';
|
|
3438
|
+
}
|
|
3439
|
+
return 'mixed';
|
|
3440
|
+
}
|
|
3441
|
+
function mapAssistantMetricByMonth(source, metric) {
|
|
3442
|
+
var mapped = new Map();
|
|
3443
|
+
source.forEach(function (value, month) {
|
|
3444
|
+
var next = metric === 'paid'
|
|
3445
|
+
? value.paid
|
|
3446
|
+
: metric === 'grand'
|
|
3447
|
+
? value.grand
|
|
3448
|
+
: value.paid || value.grand;
|
|
3449
|
+
mapped.set(month, Number.isFinite(next) ? next : 0);
|
|
3450
|
+
});
|
|
3451
|
+
return mapped;
|
|
3452
|
+
}
|
|
3453
|
+
function compareAssistantMonthlyValueMaps(base, compare) {
|
|
3454
|
+
var comparedMonths = 0;
|
|
3455
|
+
var sumDiffPct = 0;
|
|
3456
|
+
var maxDiffPct = 0;
|
|
3457
|
+
base.forEach(function (baseValue, month) {
|
|
3458
|
+
var compareValue = compare.get(month);
|
|
3459
|
+
if (typeof compareValue !== 'number') {
|
|
3460
|
+
return;
|
|
3461
|
+
}
|
|
3462
|
+
var diffPct = Math.abs(baseValue - compareValue) / Math.max(Math.abs(baseValue), 1);
|
|
3463
|
+
comparedMonths += 1;
|
|
3464
|
+
sumDiffPct += diffPct;
|
|
3465
|
+
maxDiffPct = Math.max(maxDiffPct, diffPct);
|
|
3466
|
+
});
|
|
3467
|
+
return {
|
|
3468
|
+
comparedMonths: comparedMonths,
|
|
3469
|
+
avgDiffPct: comparedMonths ? (sumDiffPct / comparedMonths) : 0,
|
|
3470
|
+
maxDiffPct: maxDiffPct
|
|
3471
|
+
};
|
|
3472
|
+
}
|
|
3473
|
+
function mergeAssistantMatch(base, extra) {
|
|
3474
|
+
var baseObj = base && typeof base === 'object' ? base : {};
|
|
3475
|
+
var extraObj = extra && typeof extra === 'object' ? extra : {};
|
|
3476
|
+
if (!Object.keys(baseObj).length) {
|
|
3477
|
+
return extraObj;
|
|
3478
|
+
}
|
|
3479
|
+
if (!Object.keys(extraObj).length) {
|
|
3480
|
+
return baseObj;
|
|
3481
|
+
}
|
|
3482
|
+
return { $and: [baseObj, extraObj] };
|
|
3483
|
+
}
|
|
3484
|
+
function resolveAssistantRollingWindowBounds(months) {
|
|
3485
|
+
var now = new Date();
|
|
3486
|
+
var rollingStart = new Date(now);
|
|
3487
|
+
rollingStart.setUTCMonth(rollingStart.getUTCMonth() - months);
|
|
3488
|
+
var startOfCurrentMonth = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
|
|
3489
|
+
var startOfWindow = new Date(Date.UTC(startOfCurrentMonth.getUTCFullYear(), startOfCurrentMonth.getUTCMonth() - months, 1));
|
|
3490
|
+
return {
|
|
3491
|
+
now: now,
|
|
3492
|
+
rollingStart: rollingStart,
|
|
3493
|
+
startOfCurrentMonth: startOfCurrentMonth,
|
|
3494
|
+
startOfWindow: startOfWindow
|
|
3495
|
+
};
|
|
3496
|
+
}
|
|
3028
3497
|
function extractAssistantMongoDirective(content) {
|
|
3029
3498
|
var lines = String(content || '').split('\n');
|
|
3030
3499
|
var directiveIndex = -1;
|
|
@@ -3121,6 +3590,9 @@ function buildAssistantToolResultPayload(directive, toolResponse) {
|
|
|
3121
3590
|
|| normalizeOptionalString((_c = toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.debug) === null || _c === void 0 ? void 0 : _c.collection)
|
|
3122
3591
|
|| requestedCollection
|
|
3123
3592
|
|| '';
|
|
3593
|
+
var verification = (toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.verification) && typeof toolResponse.verification === 'object'
|
|
3594
|
+
? toolResponse.verification
|
|
3595
|
+
: undefined;
|
|
3124
3596
|
var result = {
|
|
3125
3597
|
type: directive.type === 'aggregate' ? 'mongo_agg' : 'mongo_read',
|
|
3126
3598
|
input: directivePayload,
|
|
@@ -3131,6 +3603,7 @@ function buildAssistantToolResultPayload(directive, toolResponse) {
|
|
|
3131
3603
|
rowCount: rowCount,
|
|
3132
3604
|
columns: trimmedDisplay.columns,
|
|
3133
3605
|
truncated: trimmedDisplay.truncated,
|
|
3606
|
+
verification: verification,
|
|
3134
3607
|
debug: (toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.debug) && typeof toolResponse.debug === 'object' ? toolResponse.debug : undefined
|
|
3135
3608
|
}
|
|
3136
3609
|
};
|
|
@@ -3160,6 +3633,26 @@ function buildAssistantToolResultPrompt(result) {
|
|
|
3160
3633
|
else {
|
|
3161
3634
|
lines.push('Preview: (no rows)');
|
|
3162
3635
|
}
|
|
3636
|
+
var verification = result.output.verification;
|
|
3637
|
+
if (verification && typeof verification === 'object') {
|
|
3638
|
+
var checks = Array.isArray(verification.checks) ? verification.checks : [];
|
|
3639
|
+
var warnings = Array.isArray(verification.warnings) ? verification.warnings : [];
|
|
3640
|
+
if (checks.length || warnings.length) {
|
|
3641
|
+
lines.push('Verification:');
|
|
3642
|
+
}
|
|
3643
|
+
checks.slice(0, 4).forEach(function (entry) {
|
|
3644
|
+
var name = normalizeOptionalString(entry === null || entry === void 0 ? void 0 : entry.name) || 'check';
|
|
3645
|
+
var status = normalizeOptionalString(entry === null || entry === void 0 ? void 0 : entry.status).toLowerCase() === 'warn' ? 'warn' : 'pass';
|
|
3646
|
+
var details = normalizeOptionalString(entry === null || entry === void 0 ? void 0 : entry.details);
|
|
3647
|
+
lines.push("- ".concat(name, ": ").concat(status).concat(details ? " (".concat(details, ")") : ''));
|
|
3648
|
+
});
|
|
3649
|
+
warnings.slice(0, 4).forEach(function (warning) {
|
|
3650
|
+
var text = normalizeOptionalString(warning);
|
|
3651
|
+
if (text) {
|
|
3652
|
+
lines.push("- warning: ".concat(text));
|
|
3653
|
+
}
|
|
3654
|
+
});
|
|
3655
|
+
}
|
|
3163
3656
|
return lines.join('\n');
|
|
3164
3657
|
}
|
|
3165
3658
|
function buildAssistantCodexToolFollowupPrompt(message, attachmentText, historyText, contextText, toolResultText) {
|
|
@@ -3168,7 +3661,7 @@ function buildAssistantCodexToolFollowupPrompt(message, attachmentText, historyT
|
|
|
3168
3661
|
var trimmedHistory = normalizeOptionalString(historyText);
|
|
3169
3662
|
var historyBlock = trimmedHistory ? "\n\nConversation so far:\n".concat(trimmedHistory) : '';
|
|
3170
3663
|
var toolBlock = toolResultText ? "\n\nTool Result:\n".concat(toolResultText) : '';
|
|
3171
|
-
var instruction = '\n\nInstruction:\nNow answer the user. Do NOT output another REPORT_BUILDER_* directive. Output plain Markdown. Summarize first, then include a Markdown table.';
|
|
3664
|
+
var instruction = '\n\nInstruction:\nNow answer the user. Do NOT output another REPORT_BUILDER_* directive. Output plain Markdown. Summarize first, then include a Markdown table. If the Tool Result includes Verification warnings, explicitly include them and call out the metric/date basis used.';
|
|
3172
3665
|
return "System:\n".concat(AI_ASSISTANT_SYSTEM_PROMPT).concat(contextBlock).concat(historyBlock, "\n\nUser:\n").concat(message).concat(attachmentText || '').concat(toolBlock).concat(instruction).trim();
|
|
3173
3666
|
}
|
|
3174
3667
|
function buildAssistantToolFallbackResponse(result) {
|
|
@@ -3187,6 +3680,27 @@ function buildAssistantToolFallbackResponse(result) {
|
|
|
3187
3680
|
}
|
|
3188
3681
|
return lines.join('\n').trim();
|
|
3189
3682
|
}
|
|
3683
|
+
function applyAssistantVerificationNotes(value, toolResult) {
|
|
3684
|
+
var _a, _b, _c, _d;
|
|
3685
|
+
var content = normalizeOptionalString(value);
|
|
3686
|
+
var warnings = Array.isArray((_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.warnings)
|
|
3687
|
+
? (_d = (_c = toolResult === null || toolResult === void 0 ? void 0 : toolResult.output) === null || _c === void 0 ? void 0 : _c.verification) === null || _d === void 0 ? void 0 : _d.warnings.map(function (entry) { return normalizeOptionalString(entry); }).filter(Boolean)
|
|
3688
|
+
: [];
|
|
3689
|
+
if (!warnings.length) {
|
|
3690
|
+
return content || value || '';
|
|
3691
|
+
}
|
|
3692
|
+
var normalizedLower = String(content || '').toLowerCase();
|
|
3693
|
+
var missing = warnings.filter(function (warning) { return !normalizedLower.includes(String(warning).toLowerCase()); });
|
|
3694
|
+
if (!missing.length) {
|
|
3695
|
+
return content || value || '';
|
|
3696
|
+
}
|
|
3697
|
+
var noteLines = ['Verification notes:'];
|
|
3698
|
+
missing.slice(0, 4).forEach(function (warning) { return noteLines.push("- ".concat(warning)); });
|
|
3699
|
+
if (!content) {
|
|
3700
|
+
return noteLines.join('\n');
|
|
3701
|
+
}
|
|
3702
|
+
return "".concat(content, "\n\n").concat(noteLines.join('\n')).trim();
|
|
3703
|
+
}
|
|
3190
3704
|
function buildAssistantDebugPayload(params) {
|
|
3191
3705
|
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;
|
|
3192
3706
|
var notes = [];
|
|
@@ -4876,6 +5390,7 @@ function getAssistantCurrencyFormatter() {
|
|
|
4876
5390
|
assistantCurrencyFormatter = new Intl.NumberFormat(AI_ASSISTANT_LOCALE, {
|
|
4877
5391
|
style: 'currency',
|
|
4878
5392
|
currency: AI_ASSISTANT_CURRENCY_CODE,
|
|
5393
|
+
currencyDisplay: 'narrowSymbol',
|
|
4879
5394
|
minimumFractionDigits: 2,
|
|
4880
5395
|
maximumFractionDigits: 2
|
|
4881
5396
|
});
|
|
@@ -4963,6 +5478,12 @@ function formatAssistantDisplayCell(value, column) {
|
|
|
4963
5478
|
if (Array.isArray(value)) {
|
|
4964
5479
|
return value.map(function (item) { return formatAssistantDisplayCell(item, column); }).filter(Boolean).join(', ');
|
|
4965
5480
|
}
|
|
5481
|
+
if (typeof value === 'string') {
|
|
5482
|
+
var normalizedCurrency = normalizeAssistantCurrencyText(value);
|
|
5483
|
+
if (normalizedCurrency !== value) {
|
|
5484
|
+
return normalizedCurrency;
|
|
5485
|
+
}
|
|
5486
|
+
}
|
|
4966
5487
|
var columnKey = String(column || '').toLowerCase();
|
|
4967
5488
|
if (isAssistantDateColumn(columnKey) && isAssistantLikelyDateValue(value)) {
|
|
4968
5489
|
return formatAssistantDateValue(value);
|
|
@@ -4998,6 +5519,13 @@ function formatAssistantDisplayCell(value, column) {
|
|
|
4998
5519
|
}
|
|
4999
5520
|
return String(value);
|
|
5000
5521
|
}
|
|
5522
|
+
function normalizeAssistantCurrencyText(value) {
|
|
5523
|
+
var raw = String(value || '');
|
|
5524
|
+
if (!raw) {
|
|
5525
|
+
return '';
|
|
5526
|
+
}
|
|
5527
|
+
return raw.replace(AI_ASSISTANT_USD_CURRENCY_TEXT_PATTERN, function (_match, amount) { return "$".concat(amount); });
|
|
5528
|
+
}
|
|
5001
5529
|
function formatDisplayTableMarkdown(display) {
|
|
5002
5530
|
if (!display || !Array.isArray(display.columns) || !display.columns.length) {
|
|
5003
5531
|
return '';
|
|
@@ -5019,7 +5547,7 @@ function stripAssistantMarkdownTables(value) {
|
|
|
5019
5547
|
if (!raw) {
|
|
5020
5548
|
return '';
|
|
5021
5549
|
}
|
|
5022
|
-
var tablePattern = /(^|\n)
|
|
5550
|
+
var tablePattern = /(^|\n)\s*\|[^\n]*\|\s*\n\s*\|[ \t:-|]+\|\s*\n(?:\s*\|[^\n]*\|\s*\n?)*/g;
|
|
5023
5551
|
var cleaned = raw.replace(tablePattern, '\n').trim();
|
|
5024
5552
|
return cleaned;
|
|
5025
5553
|
}
|
|
@@ -9180,13 +9708,7 @@ function sanitizeAssistantResponse(value) {
|
|
|
9180
9708
|
if (!cleaned) {
|
|
9181
9709
|
return 'I can’t share code, but I can point you to files or explain behavior at a high level.';
|
|
9182
9710
|
}
|
|
9183
|
-
var normalizedCurrency = cleaned
|
|
9184
|
-
.replace(/\bUSD(?:\s| | |[\u00A0\u202F\u2007])*\$?\s*([-+]?[0-9][0-9,]*(?:\.[0-9]+)?)/g, function (_match, amount) {
|
|
9185
|
-
return "$".concat(amount);
|
|
9186
|
-
})
|
|
9187
|
-
.replace(/\bUS\$\s*([-+]?[0-9][0-9,]*(?:\.[0-9]+)?)/g, function (_match, amount) {
|
|
9188
|
-
return "$".concat(amount);
|
|
9189
|
-
});
|
|
9711
|
+
var normalizedCurrency = normalizeAssistantCurrencyText(cleaned);
|
|
9190
9712
|
return normalizeAssistantRoutes(normalizedCurrency);
|
|
9191
9713
|
}
|
|
9192
9714
|
function evaluateAssistantGuardrails(message) {
|