@resolveio/server-lib 22.0.4 → 22.0.5
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 +494 -17
- package/methods/ai-terminal.js.map +1 -1
- package/package.json +1 -1
package/methods/ai-terminal.js
CHANGED
|
@@ -159,6 +159,10 @@ var AI_ASSISTANT_COLLECTION_OVERRIDE_MIN_SCORE = 20;
|
|
|
159
159
|
var AI_ASSISTANT_ID_LOOKUP_MAX_RESULTS = 20;
|
|
160
160
|
var AI_ASSISTANT_ID_LOOKUP_CANDIDATE_LIMIT = 4;
|
|
161
161
|
var AI_ASSISTANT_NAME_MATCH_FALLBACK_MAX_FIELDS = 12;
|
|
162
|
+
var AI_ASSISTANT_CONTEXT_MAX_COLLECTIONS = 3;
|
|
163
|
+
var AI_ASSISTANT_CONTEXT_MAX_FIELDS_PER_COLLECTION = 24;
|
|
164
|
+
var AI_ASSISTANT_LOCALE = 'en-US';
|
|
165
|
+
var AI_ASSISTANT_CURRENCY_CODE = 'USD';
|
|
162
166
|
var AI_ASSISTANT_PROGRESS_TICKS = [
|
|
163
167
|
'Grabbing Data',
|
|
164
168
|
'Drafting response'
|
|
@@ -277,6 +281,18 @@ var AI_ASSISTANT_COLLECTION_DOMAIN_TOKENS = new Set([
|
|
|
277
281
|
'chemicals',
|
|
278
282
|
'invoice',
|
|
279
283
|
'invoices',
|
|
284
|
+
'revenue',
|
|
285
|
+
'revenues',
|
|
286
|
+
'sales',
|
|
287
|
+
'sale',
|
|
288
|
+
'billing',
|
|
289
|
+
'billings',
|
|
290
|
+
'payment',
|
|
291
|
+
'payments',
|
|
292
|
+
'paid',
|
|
293
|
+
'income',
|
|
294
|
+
'finance',
|
|
295
|
+
'financial',
|
|
280
296
|
'work',
|
|
281
297
|
'order',
|
|
282
298
|
'orders',
|
|
@@ -317,7 +333,11 @@ var AI_ASSISTANT_FIELD_TOKEN_SYNONYMS = {
|
|
|
317
333
|
batch: ['lot'],
|
|
318
334
|
lot: ['batch'],
|
|
319
335
|
date: ['created', 'createdat', 'created_at', 'date_created', 'updated', 'updatedat', 'updated_at', 'date_updated'],
|
|
320
|
-
total: ['sum', 'amount', 'total_amount', 'total_quantity']
|
|
336
|
+
total: ['sum', 'amount', 'total_amount', 'total_quantity'],
|
|
337
|
+
revenue: ['sales', 'billing', 'paid', 'payment', 'total', 'amount', 'grand', 'subtotal', 'sub_total', 'paid_total', 'grand_total'],
|
|
338
|
+
sales: ['revenue', 'billing', 'paid', 'payment', 'total', 'amount', 'grand', 'subtotal', 'sub_total'],
|
|
339
|
+
billing: ['revenue', 'sales', 'paid', 'payment', 'total', 'amount', 'grand', 'subtotal', 'sub_total'],
|
|
340
|
+
payment: ['paid', 'revenue', 'sales', 'billing', 'total', 'amount']
|
|
321
341
|
};
|
|
322
342
|
var AI_ASSISTANT_ID_LOOKUP_HINTS = {
|
|
323
343
|
customer: ['customers', 'customer-versions'],
|
|
@@ -336,6 +356,11 @@ var AI_ASSISTANT_TERM_SYNONYMS = [
|
|
|
336
356
|
label: 'blend tickets',
|
|
337
357
|
pattern: /\bblend(?:ing)?\s+tickets?\b/i,
|
|
338
358
|
expansions: ['chemical blends', 'chemical-blends', 'report-chemical-blends', 'blend batches']
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
label: 'revenue',
|
|
362
|
+
pattern: /\b(revenue|sales|billing)\b/i,
|
|
363
|
+
expansions: ['invoice', 'invoices', 'paid invoices', 'invoice payments', 'billing', 'sales']
|
|
339
364
|
}
|
|
340
365
|
];
|
|
341
366
|
var AI_ASSISTANT_SYSTEM_PROMPT = [
|
|
@@ -372,6 +397,7 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
|
|
|
372
397
|
'- Output plain Markdown (NO triple backticks).',
|
|
373
398
|
'- When you reference database results, summarize first, then include a Markdown table.',
|
|
374
399
|
'- When presenting record lists or aggregates, produce a Markdown table (pipes).',
|
|
400
|
+
'- Format currency as $1,234.56 (no USD prefix) with two decimals.',
|
|
375
401
|
'- Never show raw JSON dumps.',
|
|
376
402
|
'- Do not invent placeholders like "Not available" or "N/A". If a value is missing in tool results, leave the cell blank or omit the column and note it briefly.',
|
|
377
403
|
'- Do not include `_id` & `__v` & `id_<other collection _id property>` in tables by default.',
|
|
@@ -406,6 +432,8 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
|
|
|
406
432
|
'- If you need grouped/aggregated data (totals by user, rankings, trends), end your response with a single line exactly in this format:',
|
|
407
433
|
'- MONGO_AGG: {"collection":"<name>","pipeline":[...],"options":{"allowDiskUse":true,"limit":20},"permissionView":"</route>"}',
|
|
408
434
|
'- For invoice data, set permissionView to an invoice route (ex: /invoice/list or /report/invoice).',
|
|
435
|
+
'- For revenue/sales/billing questions, use invoices and sum paid_total (fallback to grand_total) with date_paid and Paid/Closed status when available.',
|
|
436
|
+
'- For relative date ranges (last/past/recent), include an upper bound <= $$NOW unless the user specifies a future end date.',
|
|
409
437
|
'- Keep queries minimal, read-only, and avoid user/credential data unless the user is a super admin.',
|
|
410
438
|
'- Assume you are not a super admin unless explicitly told otherwise.',
|
|
411
439
|
'- Only request data when the user has permission for that module; invoice data requires invoice view access.',
|
|
@@ -1168,7 +1196,7 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1168
1196
|
insertResult = _d.sent();
|
|
1169
1197
|
assistantMessageId = (insertResult === null || insertResult === void 0 ? void 0 : insertResult._id) || (insertResult === null || insertResult === void 0 ? void 0 : insertResult.insertedId);
|
|
1170
1198
|
enqueueAssistantCodexRun(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1171
|
-
var runStart, steps, recordStep, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, dataQuestion, lastDirective, toolResponseDebug, toolError, termHints, collectionHints, collectionTokenization, collectionRanking, collectionSelection, collectionOverride, collectionNames, timingBreakdown, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, baseWeights, expandedWeights, dbName, db, _a, assistantContext, prompt_1, workspaceRoot, codexConfig, runOptions, responseText, directiveText, directive, directivePrompt, directiveStart, forcedDirective, _b, initialStart, directivePrompt, forcedStart, forcedDirective, _c, requestedCollection, cleanedResponseText, effectiveDirective, toolRequest, toolStart, toolResponse, _d, toolPayload, followupPrompt, followupStart, followupText, _e, error_2, error_3, finishedAt, finalNow, finishedAt, codexMs, draftingMs, finalMetadata, finalAssistantDoc;
|
|
1199
|
+
var runStart, steps, recordStep, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, dataQuestion, lastDirective, toolResponseDebug, toolError, termHints, collectionHints, fieldHints, collectionTokenization, collectionRanking, collectionSelection, collectionOverride, collectionNames, timingBreakdown, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, baseWeights, expandedWeights, dbName, db, _a, routeHints, rankedCollections, hintCollections, assistantContext, prompt_1, workspaceRoot, codexConfig, runOptions, responseText, directiveText, directive, directivePrompt, directiveStart, forcedDirective, _b, initialStart, directivePrompt, forcedStart, forcedDirective, _c, requestedCollection, cleanedResponseText, effectiveDirective, toolRequest, toolStart, toolResponse, _d, toolPayload, followupPrompt, followupStart, followupText, _e, error_2, error_3, finishedAt, finalNow, finishedAt, codexMs, draftingMs, finalMetadata, finalAssistantDoc;
|
|
1172
1200
|
var _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
1173
1201
|
return __generator(this, function (_u) {
|
|
1174
1202
|
switch (_u.label) {
|
|
@@ -1206,6 +1234,7 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1206
1234
|
toolError = null;
|
|
1207
1235
|
termHints = [];
|
|
1208
1236
|
collectionHints = [];
|
|
1237
|
+
fieldHints = [];
|
|
1209
1238
|
collectionTokenization = null;
|
|
1210
1239
|
collectionRanking = null;
|
|
1211
1240
|
collectionSelection = null;
|
|
@@ -1263,18 +1292,30 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1263
1292
|
: null);
|
|
1264
1293
|
return [3 /*break*/, 5];
|
|
1265
1294
|
case 5:
|
|
1295
|
+
routeHints = resolveCollectionHintsFromRoute(contextRoute, collectionNames);
|
|
1296
|
+
if (routeHints.length) {
|
|
1297
|
+
collectionHints = mergeAssistantHintValues(routeHints, collectionHints);
|
|
1298
|
+
}
|
|
1299
|
+
rankedCollections = Array.isArray(collectionRanking === null || collectionRanking === void 0 ? void 0 : collectionRanking.ranked)
|
|
1300
|
+
? collectionRanking === null || collectionRanking === void 0 ? void 0 : collectionRanking.ranked.map(function (entry) { return entry.name; })
|
|
1301
|
+
: [];
|
|
1302
|
+
hintCollections = mergeAssistantHintValues(collectionHints, rankedCollections)
|
|
1303
|
+
.slice(0, AI_ASSISTANT_CONTEXT_MAX_COLLECTIONS);
|
|
1304
|
+
fieldHints = buildAssistantFieldHints(message, hintCollections);
|
|
1266
1305
|
recordStep('Planning: collection hints', {
|
|
1267
1306
|
contextRoute: contextRoute || undefined,
|
|
1268
1307
|
contextMode: contextMode || undefined,
|
|
1269
1308
|
collectionHints: collectionHints.length ? collectionHints : undefined,
|
|
1270
|
-
termHints: termHints.length ? termHints : undefined
|
|
1309
|
+
termHints: termHints.length ? termHints : undefined,
|
|
1310
|
+
fieldHints: fieldHints.length ? fieldHints : undefined
|
|
1271
1311
|
});
|
|
1272
1312
|
assistantContext = buildAssistantContext(input, {
|
|
1273
1313
|
isSuperAdmin: isSuperAdmin,
|
|
1274
1314
|
hasInvoiceAccess: hasInvoiceAccess,
|
|
1275
1315
|
customerId: customerId,
|
|
1276
1316
|
collectionHints: collectionHints,
|
|
1277
|
-
termHints: termHints
|
|
1317
|
+
termHints: termHints,
|
|
1318
|
+
fieldHints: fieldHints
|
|
1278
1319
|
});
|
|
1279
1320
|
prompt_1 = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
|
|
1280
1321
|
return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
|
|
@@ -1446,6 +1487,7 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1446
1487
|
followupText = _u.sent();
|
|
1447
1488
|
timingBreakdown.followupMs = Date.now() - followupStart;
|
|
1448
1489
|
assistantContent = sanitizeAssistantResponse(followupText);
|
|
1490
|
+
assistantContent = applyAssistantDisplayTableToResponse(assistantContent, toolPayload.result.output.display);
|
|
1449
1491
|
return [3 /*break*/, 25];
|
|
1450
1492
|
case 24:
|
|
1451
1493
|
_e = _u.sent();
|
|
@@ -1513,6 +1555,7 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1513
1555
|
contextRoute: contextRoute || undefined,
|
|
1514
1556
|
termHints: termHints.length ? termHints : undefined,
|
|
1515
1557
|
collectionHints: collectionHints.length ? collectionHints : undefined,
|
|
1558
|
+
fieldHints: fieldHints.length ? fieldHints : undefined,
|
|
1516
1559
|
collectionTokenization: collectionTokenization || undefined,
|
|
1517
1560
|
collectionRanking: collectionRanking || undefined,
|
|
1518
1561
|
collectionSelection: collectionSelection || undefined,
|
|
@@ -4402,6 +4445,136 @@ function trimDisplayTable(display, options) {
|
|
|
4402
4445
|
}) : [];
|
|
4403
4446
|
return __assign(__assign({}, display), { columns: columns, rows: rows, truncated: display.truncated || display.columns.length > maxColumns || rowsSource.length > maxRows });
|
|
4404
4447
|
}
|
|
4448
|
+
var assistantCurrencyFormatter = null;
|
|
4449
|
+
var assistantNumberFormatter = null;
|
|
4450
|
+
var assistantPercentFormatter = null;
|
|
4451
|
+
function getAssistantCurrencyFormatter() {
|
|
4452
|
+
if (!assistantCurrencyFormatter) {
|
|
4453
|
+
assistantCurrencyFormatter = new Intl.NumberFormat(AI_ASSISTANT_LOCALE, {
|
|
4454
|
+
style: 'currency',
|
|
4455
|
+
currency: AI_ASSISTANT_CURRENCY_CODE,
|
|
4456
|
+
minimumFractionDigits: 2,
|
|
4457
|
+
maximumFractionDigits: 2
|
|
4458
|
+
});
|
|
4459
|
+
}
|
|
4460
|
+
return assistantCurrencyFormatter;
|
|
4461
|
+
}
|
|
4462
|
+
function getAssistantNumberFormatter() {
|
|
4463
|
+
if (!assistantNumberFormatter) {
|
|
4464
|
+
assistantNumberFormatter = new Intl.NumberFormat(AI_ASSISTANT_LOCALE, {
|
|
4465
|
+
minimumFractionDigits: 0,
|
|
4466
|
+
maximumFractionDigits: 2
|
|
4467
|
+
});
|
|
4468
|
+
}
|
|
4469
|
+
return assistantNumberFormatter;
|
|
4470
|
+
}
|
|
4471
|
+
function getAssistantPercentFormatter() {
|
|
4472
|
+
if (!assistantPercentFormatter) {
|
|
4473
|
+
assistantPercentFormatter = new Intl.NumberFormat(AI_ASSISTANT_LOCALE, {
|
|
4474
|
+
style: 'percent',
|
|
4475
|
+
minimumFractionDigits: 0,
|
|
4476
|
+
maximumFractionDigits: 2
|
|
4477
|
+
});
|
|
4478
|
+
}
|
|
4479
|
+
return assistantPercentFormatter;
|
|
4480
|
+
}
|
|
4481
|
+
function resolveAssistantNumericValue(value) {
|
|
4482
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
4483
|
+
return value;
|
|
4484
|
+
}
|
|
4485
|
+
if (typeof value === 'string') {
|
|
4486
|
+
var cleaned = value.replace(/[^0-9.+-]/g, '');
|
|
4487
|
+
if (!cleaned) {
|
|
4488
|
+
return null;
|
|
4489
|
+
}
|
|
4490
|
+
var parsed = Number(cleaned);
|
|
4491
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
4492
|
+
}
|
|
4493
|
+
return null;
|
|
4494
|
+
}
|
|
4495
|
+
function isAssistantPercentColumn(column) {
|
|
4496
|
+
return /(percent|pct|percentage|ratio|rate)\b/.test(column);
|
|
4497
|
+
}
|
|
4498
|
+
function isAssistantCurrencyColumn(column) {
|
|
4499
|
+
return /(amount|total|price|cost|balance|fee|revenue|invoice|usd|tax|subtotal|paid|billing|sales)\b/.test(column);
|
|
4500
|
+
}
|
|
4501
|
+
function isAssistantDateColumn(column) {
|
|
4502
|
+
return /(date|time|created|updated|timestamp|at)\b/.test(column);
|
|
4503
|
+
}
|
|
4504
|
+
function isAssistantLikelyDateValue(value) {
|
|
4505
|
+
if (!value) {
|
|
4506
|
+
return false;
|
|
4507
|
+
}
|
|
4508
|
+
if (value instanceof Date) {
|
|
4509
|
+
return true;
|
|
4510
|
+
}
|
|
4511
|
+
if (typeof value === 'string') {
|
|
4512
|
+
if (!/[0-9]/.test(value)) {
|
|
4513
|
+
return false;
|
|
4514
|
+
}
|
|
4515
|
+
var parsed = Date.parse(value);
|
|
4516
|
+
return !Number.isNaN(parsed);
|
|
4517
|
+
}
|
|
4518
|
+
return false;
|
|
4519
|
+
}
|
|
4520
|
+
function formatAssistantDateValue(value) {
|
|
4521
|
+
var dateValue = value instanceof Date ? value : new Date(value);
|
|
4522
|
+
if (Number.isNaN(dateValue.getTime())) {
|
|
4523
|
+
return String(value);
|
|
4524
|
+
}
|
|
4525
|
+
var iso = dateValue.toISOString();
|
|
4526
|
+
var _a = __read(iso.split('T'), 2), datePart = _a[0], timePart = _a[1];
|
|
4527
|
+
if (!timePart) {
|
|
4528
|
+
return datePart || iso;
|
|
4529
|
+
}
|
|
4530
|
+
var trimmed = timePart.replace('Z', '');
|
|
4531
|
+
if (trimmed.startsWith('00:00:00')) {
|
|
4532
|
+
return datePart;
|
|
4533
|
+
}
|
|
4534
|
+
return "".concat(datePart, " ").concat(trimmed.slice(0, 5));
|
|
4535
|
+
}
|
|
4536
|
+
function formatAssistantDisplayCell(value, column) {
|
|
4537
|
+
if (value === null || value === undefined || value === '') {
|
|
4538
|
+
return '';
|
|
4539
|
+
}
|
|
4540
|
+
if (Array.isArray(value)) {
|
|
4541
|
+
return value.map(function (item) { return formatAssistantDisplayCell(item, column); }).filter(Boolean).join(', ');
|
|
4542
|
+
}
|
|
4543
|
+
var columnKey = String(column || '').toLowerCase();
|
|
4544
|
+
if (isAssistantDateColumn(columnKey) && isAssistantLikelyDateValue(value)) {
|
|
4545
|
+
return formatAssistantDateValue(value);
|
|
4546
|
+
}
|
|
4547
|
+
var numericValue = resolveAssistantNumericValue(value);
|
|
4548
|
+
if (numericValue !== null) {
|
|
4549
|
+
if (isAssistantPercentColumn(columnKey)) {
|
|
4550
|
+
var percentValue = numericValue > 1 && numericValue <= 100 ? numericValue / 100 : numericValue;
|
|
4551
|
+
try {
|
|
4552
|
+
return getAssistantPercentFormatter().format(percentValue);
|
|
4553
|
+
}
|
|
4554
|
+
catch (_a) {
|
|
4555
|
+
return "".concat((0, common_1.round)(percentValue * 100), "%");
|
|
4556
|
+
}
|
|
4557
|
+
}
|
|
4558
|
+
if (isAssistantCurrencyColumn(columnKey)) {
|
|
4559
|
+
try {
|
|
4560
|
+
return getAssistantCurrencyFormatter().format(numericValue);
|
|
4561
|
+
}
|
|
4562
|
+
catch (_b) {
|
|
4563
|
+
return "$".concat(numericValue.toFixed(2));
|
|
4564
|
+
}
|
|
4565
|
+
}
|
|
4566
|
+
try {
|
|
4567
|
+
return getAssistantNumberFormatter().format(numericValue);
|
|
4568
|
+
}
|
|
4569
|
+
catch (_c) {
|
|
4570
|
+
return String(numericValue);
|
|
4571
|
+
}
|
|
4572
|
+
}
|
|
4573
|
+
if (isAssistantLikelyDateValue(value) && isAssistantDateColumn(columnKey)) {
|
|
4574
|
+
return formatAssistantDateValue(value);
|
|
4575
|
+
}
|
|
4576
|
+
return String(value);
|
|
4577
|
+
}
|
|
4405
4578
|
function formatDisplayTableMarkdown(display) {
|
|
4406
4579
|
if (!display || !Array.isArray(display.columns) || !display.columns.length) {
|
|
4407
4580
|
return '';
|
|
@@ -4409,11 +4582,38 @@ function formatDisplayTableMarkdown(display) {
|
|
|
4409
4582
|
var header = "| ".concat(display.columns.join(' | '), " |");
|
|
4410
4583
|
var separator = "| ".concat(display.columns.map(function () { return '---'; }).join(' | '), " |");
|
|
4411
4584
|
var rows = (display.rows || []).map(function (row) {
|
|
4412
|
-
var cells = display.columns.map(function (column) {
|
|
4585
|
+
var cells = display.columns.map(function (column) {
|
|
4586
|
+
var rawValue = row === null || row === void 0 ? void 0 : row[column];
|
|
4587
|
+
var formatted = formatAssistantDisplayCell(rawValue, column);
|
|
4588
|
+
return escapeMarkdownCell(formatted);
|
|
4589
|
+
});
|
|
4413
4590
|
return "| ".concat(cells.join(' | '), " |");
|
|
4414
4591
|
});
|
|
4415
4592
|
return __spreadArray([header, separator], __read(rows), false).join('\n').trim();
|
|
4416
4593
|
}
|
|
4594
|
+
function stripAssistantMarkdownTables(value) {
|
|
4595
|
+
var raw = normalizeOptionalString(value);
|
|
4596
|
+
if (!raw) {
|
|
4597
|
+
return '';
|
|
4598
|
+
}
|
|
4599
|
+
var tablePattern = /(^|\n)\|[^\n]*\|\n\|[ \t:-|]+\|\n(?:\|[^\n]*\|\n?)*/g;
|
|
4600
|
+
var cleaned = raw.replace(tablePattern, '\n').trim();
|
|
4601
|
+
return cleaned;
|
|
4602
|
+
}
|
|
4603
|
+
function applyAssistantDisplayTableToResponse(value, display) {
|
|
4604
|
+
if (!display || !Array.isArray(display.rows) || !display.rows.length) {
|
|
4605
|
+
return value;
|
|
4606
|
+
}
|
|
4607
|
+
var table = formatDisplayTableMarkdown(display);
|
|
4608
|
+
if (!table) {
|
|
4609
|
+
return value;
|
|
4610
|
+
}
|
|
4611
|
+
var cleaned = stripAssistantMarkdownTables(value);
|
|
4612
|
+
if (!cleaned) {
|
|
4613
|
+
return table;
|
|
4614
|
+
}
|
|
4615
|
+
return "".concat(cleaned.trim(), "\n\n").concat(table).trim();
|
|
4616
|
+
}
|
|
4417
4617
|
function escapeMarkdownCell(value) {
|
|
4418
4618
|
var raw = value === null || value === undefined ? '' : String(value);
|
|
4419
4619
|
return raw.replace(/\|/g, '\\|').replace(/\r?\n/g, ' ').trim();
|
|
@@ -6559,6 +6759,59 @@ function resolveCollectionHintsFromTokens(tokens, collectionNames, max) {
|
|
|
6559
6759
|
.slice(0, Math.max(max, 0))
|
|
6560
6760
|
.map(function (entry) { return entry.name; });
|
|
6561
6761
|
}
|
|
6762
|
+
function mergeAssistantHintValues() {
|
|
6763
|
+
var groups = [];
|
|
6764
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
6765
|
+
groups[_i] = arguments[_i];
|
|
6766
|
+
}
|
|
6767
|
+
var result = [];
|
|
6768
|
+
var seen = new Set();
|
|
6769
|
+
groups.forEach(function (group) {
|
|
6770
|
+
if (!Array.isArray(group)) {
|
|
6771
|
+
return;
|
|
6772
|
+
}
|
|
6773
|
+
group.forEach(function (value) {
|
|
6774
|
+
var normalized = normalizeOptionalString(value);
|
|
6775
|
+
if (!normalized || seen.has(normalized)) {
|
|
6776
|
+
return;
|
|
6777
|
+
}
|
|
6778
|
+
seen.add(normalized);
|
|
6779
|
+
result.push(normalized);
|
|
6780
|
+
});
|
|
6781
|
+
});
|
|
6782
|
+
return result;
|
|
6783
|
+
}
|
|
6784
|
+
function resolveCollectionHintsFromRoute(route, collectionNames) {
|
|
6785
|
+
var normalizedRoute = normalizeOptionalString(route);
|
|
6786
|
+
if (!normalizedRoute || !collectionNames.length) {
|
|
6787
|
+
return [];
|
|
6788
|
+
}
|
|
6789
|
+
var parts = normalizedRoute.toLowerCase().split(/[/?#]+/g).filter(Boolean);
|
|
6790
|
+
var hints = [];
|
|
6791
|
+
parts.forEach(function (part) {
|
|
6792
|
+
var cleaned = part.replace(/[^a-z0-9_-]/g, '');
|
|
6793
|
+
if (!cleaned) {
|
|
6794
|
+
return;
|
|
6795
|
+
}
|
|
6796
|
+
var base = cleaned.replace(/^-+|-+$/g, '');
|
|
6797
|
+
if (!base) {
|
|
6798
|
+
return;
|
|
6799
|
+
}
|
|
6800
|
+
if (collectionNames.includes(base)) {
|
|
6801
|
+
hints.push(base);
|
|
6802
|
+
}
|
|
6803
|
+
if (!base.endsWith('s') && collectionNames.includes("".concat(base, "s"))) {
|
|
6804
|
+
hints.push("".concat(base, "s"));
|
|
6805
|
+
}
|
|
6806
|
+
if (collectionNames.includes("report-".concat(base))) {
|
|
6807
|
+
hints.push("report-".concat(base));
|
|
6808
|
+
}
|
|
6809
|
+
if (!base.endsWith('s') && collectionNames.includes("report-".concat(base, "s"))) {
|
|
6810
|
+
hints.push("report-".concat(base, "s"));
|
|
6811
|
+
}
|
|
6812
|
+
});
|
|
6813
|
+
return mergeAssistantHintValues(hints);
|
|
6814
|
+
}
|
|
6562
6815
|
function buildCollectionRankingDebugFromTokens(tokens, collectionNames, max) {
|
|
6563
6816
|
if (max === void 0) { max = 8; }
|
|
6564
6817
|
var requestedKey = normalizeCollectionKey(tokens.join('-'));
|
|
@@ -7682,31 +7935,164 @@ function pathExists(target) {
|
|
|
7682
7935
|
});
|
|
7683
7936
|
});
|
|
7684
7937
|
}
|
|
7685
|
-
function
|
|
7938
|
+
function directoryExists(target) {
|
|
7939
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
7940
|
+
var stat, _a;
|
|
7941
|
+
return __generator(this, function (_b) {
|
|
7942
|
+
switch (_b.label) {
|
|
7943
|
+
case 0:
|
|
7944
|
+
_b.trys.push([0, 2, , 3]);
|
|
7945
|
+
return [4 /*yield*/, fs_1.promises.stat(target)];
|
|
7946
|
+
case 1:
|
|
7947
|
+
stat = _b.sent();
|
|
7948
|
+
return [2 /*return*/, stat.isDirectory()];
|
|
7949
|
+
case 2:
|
|
7950
|
+
_a = _b.sent();
|
|
7951
|
+
return [2 /*return*/, false];
|
|
7952
|
+
case 3: return [2 /*return*/];
|
|
7953
|
+
}
|
|
7954
|
+
});
|
|
7955
|
+
});
|
|
7956
|
+
}
|
|
7957
|
+
function isAssistantPathUnderRoot(target, root) {
|
|
7958
|
+
if (!target || !root) {
|
|
7959
|
+
return false;
|
|
7960
|
+
}
|
|
7961
|
+
var relative = path.relative(root, target);
|
|
7962
|
+
if (!relative) {
|
|
7963
|
+
return true;
|
|
7964
|
+
}
|
|
7965
|
+
return !relative.startsWith('..') && !path.isAbsolute(relative);
|
|
7966
|
+
}
|
|
7967
|
+
function isAssistantProjectRoot(candidate) {
|
|
7686
7968
|
return __awaiter(this, void 0, void 0, function () {
|
|
7687
|
-
var
|
|
7969
|
+
var serverPath, angularPath, _a, hasServer, hasPackage;
|
|
7688
7970
|
return __generator(this, function (_b) {
|
|
7689
7971
|
switch (_b.label) {
|
|
7972
|
+
case 0:
|
|
7973
|
+
if (!candidate) {
|
|
7974
|
+
return [2 /*return*/, false];
|
|
7975
|
+
}
|
|
7976
|
+
return [4 /*yield*/, directoryExists(candidate)];
|
|
7977
|
+
case 1:
|
|
7978
|
+
if (!(_b.sent())) {
|
|
7979
|
+
return [2 /*return*/, false];
|
|
7980
|
+
}
|
|
7981
|
+
serverPath = path.join(candidate, 'server');
|
|
7982
|
+
angularPath = path.join(candidate, 'angular');
|
|
7983
|
+
return [4 /*yield*/, directoryExists(serverPath)];
|
|
7984
|
+
case 2:
|
|
7985
|
+
_a = (_b.sent());
|
|
7986
|
+
if (!_a) return [3 /*break*/, 4];
|
|
7987
|
+
return [4 /*yield*/, directoryExists(angularPath)];
|
|
7988
|
+
case 3:
|
|
7989
|
+
_a = (_b.sent());
|
|
7990
|
+
_b.label = 4;
|
|
7991
|
+
case 4:
|
|
7992
|
+
if (_a) {
|
|
7993
|
+
return [2 /*return*/, true];
|
|
7994
|
+
}
|
|
7995
|
+
return [4 /*yield*/, directoryExists(serverPath)];
|
|
7996
|
+
case 5:
|
|
7997
|
+
hasServer = _b.sent();
|
|
7998
|
+
return [4 /*yield*/, pathExists(path.join(candidate, 'package.json'))];
|
|
7999
|
+
case 6:
|
|
8000
|
+
hasPackage = _b.sent();
|
|
8001
|
+
return [2 /*return*/, hasServer && hasPackage];
|
|
8002
|
+
}
|
|
8003
|
+
});
|
|
8004
|
+
});
|
|
8005
|
+
}
|
|
8006
|
+
function resolveAssistantProjectRoot(clientDir) {
|
|
8007
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
8008
|
+
var normalized, resolved, root, parts, i, candidate;
|
|
8009
|
+
return __generator(this, function (_a) {
|
|
8010
|
+
switch (_a.label) {
|
|
8011
|
+
case 0:
|
|
8012
|
+
normalized = normalizeOptionalString(clientDir);
|
|
8013
|
+
if (!normalized) {
|
|
8014
|
+
return [2 /*return*/, ''];
|
|
8015
|
+
}
|
|
8016
|
+
resolved = path.resolve(normalized);
|
|
8017
|
+
root = path.parse(resolved).root || path.sep;
|
|
8018
|
+
parts = resolved.slice(root.length).split(path.sep).filter(Boolean);
|
|
8019
|
+
if (!parts.length) {
|
|
8020
|
+
return [2 /*return*/, ''];
|
|
8021
|
+
}
|
|
8022
|
+
i = parts.length;
|
|
8023
|
+
_a.label = 1;
|
|
8024
|
+
case 1:
|
|
8025
|
+
if (!(i >= 1)) return [3 /*break*/, 4];
|
|
8026
|
+
candidate = path.join.apply(path, __spreadArray([root], __read(parts.slice(0, i)), false));
|
|
8027
|
+
return [4 /*yield*/, isAssistantProjectRoot(candidate)];
|
|
8028
|
+
case 2:
|
|
8029
|
+
if (_a.sent()) {
|
|
8030
|
+
return [2 /*return*/, candidate];
|
|
8031
|
+
}
|
|
8032
|
+
_a.label = 3;
|
|
8033
|
+
case 3:
|
|
8034
|
+
i -= 1;
|
|
8035
|
+
return [3 /*break*/, 1];
|
|
8036
|
+
case 4: return [2 /*return*/, ''];
|
|
8037
|
+
}
|
|
8038
|
+
});
|
|
8039
|
+
});
|
|
8040
|
+
}
|
|
8041
|
+
function resolveAssistantWorkspaceRoot() {
|
|
8042
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
8043
|
+
var config, configured, configuredRoot, clientDir, resolvedClientDir, projectRoot, _a, candidate, stat, _b;
|
|
8044
|
+
return __generator(this, function (_c) {
|
|
8045
|
+
switch (_c.label) {
|
|
7690
8046
|
case 0:
|
|
7691
8047
|
config = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
7692
8048
|
configured = normalizeOptionalString(config['AI_ASSISTANT_WORKSPACE_ROOT']
|
|
7693
8049
|
|| process.env.AI_ASSISTANT_WORKSPACE_ROOT
|
|
7694
8050
|
|| config['CODEX_WORKSPACE_ROOT']
|
|
7695
8051
|
|| process.env.CODEX_WORKSPACE_ROOT);
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
8052
|
+
configuredRoot = configured ? path.resolve(configured) : '';
|
|
8053
|
+
clientDir = normalizeOptionalString(resolveio_server_app_1.ResolveIOServer.getClientDir());
|
|
8054
|
+
resolvedClientDir = clientDir ? path.resolve(clientDir) : '';
|
|
8055
|
+
if (!resolvedClientDir) return [3 /*break*/, 2];
|
|
8056
|
+
return [4 /*yield*/, resolveAssistantProjectRoot(resolvedClientDir)];
|
|
7699
8057
|
case 1:
|
|
7700
|
-
|
|
7701
|
-
return [
|
|
8058
|
+
_a = _c.sent();
|
|
8059
|
+
return [3 /*break*/, 3];
|
|
7702
8060
|
case 2:
|
|
7703
|
-
|
|
7704
|
-
|
|
8061
|
+
_a = '';
|
|
8062
|
+
_c.label = 3;
|
|
7705
8063
|
case 3:
|
|
7706
|
-
|
|
8064
|
+
projectRoot = _a;
|
|
8065
|
+
candidate = configuredRoot || projectRoot || resolvedClientDir || process.cwd();
|
|
8066
|
+
if (configuredRoot) {
|
|
8067
|
+
if (projectRoot && isAssistantPathUnderRoot(projectRoot, configuredRoot)) {
|
|
8068
|
+
candidate = projectRoot;
|
|
8069
|
+
}
|
|
8070
|
+
else if (projectRoot && isAssistantPathUnderRoot(configuredRoot, projectRoot)) {
|
|
8071
|
+
candidate = configuredRoot;
|
|
8072
|
+
}
|
|
8073
|
+
else {
|
|
8074
|
+
candidate = configuredRoot;
|
|
8075
|
+
}
|
|
8076
|
+
}
|
|
8077
|
+
else if (projectRoot) {
|
|
8078
|
+
candidate = projectRoot;
|
|
8079
|
+
}
|
|
8080
|
+
else if (resolvedClientDir) {
|
|
8081
|
+
candidate = resolvedClientDir;
|
|
8082
|
+
}
|
|
7707
8083
|
stat = null;
|
|
7708
|
-
|
|
8084
|
+
_c.label = 4;
|
|
7709
8085
|
case 4:
|
|
8086
|
+
_c.trys.push([4, 6, , 7]);
|
|
8087
|
+
return [4 /*yield*/, fs_1.promises.stat(candidate)];
|
|
8088
|
+
case 5:
|
|
8089
|
+
stat = _c.sent();
|
|
8090
|
+
return [3 /*break*/, 7];
|
|
8091
|
+
case 6:
|
|
8092
|
+
_b = _c.sent();
|
|
8093
|
+
stat = null;
|
|
8094
|
+
return [3 /*break*/, 7];
|
|
8095
|
+
case 7:
|
|
7710
8096
|
if (!stat || !stat.isDirectory()) {
|
|
7711
8097
|
throw new Error('AI assistant workspace root not found.');
|
|
7712
8098
|
}
|
|
@@ -7797,6 +8183,14 @@ function buildAssistantContext(input, userContext) {
|
|
|
7797
8183
|
if (termHints.length) {
|
|
7798
8184
|
lines.push("Term hints: ".concat(termHints.join('; ')));
|
|
7799
8185
|
}
|
|
8186
|
+
var fieldHints = Array.isArray(userContext === null || userContext === void 0 ? void 0 : userContext.fieldHints)
|
|
8187
|
+
? userContext.fieldHints.filter(Boolean)
|
|
8188
|
+
: [];
|
|
8189
|
+
if (fieldHints.length) {
|
|
8190
|
+
fieldHints.forEach(function (hint) {
|
|
8191
|
+
lines.push(hint);
|
|
8192
|
+
});
|
|
8193
|
+
}
|
|
7800
8194
|
var mongoDb = normalizeOptionalString((_c = input === null || input === void 0 ? void 0 : input.mongo) === null || _c === void 0 ? void 0 : _c.database);
|
|
7801
8195
|
var mongoDbs = Array.isArray((_d = input === null || input === void 0 ? void 0 : input.mongo) === null || _d === void 0 ? void 0 : _d.databases)
|
|
7802
8196
|
? input.mongo.databases.map(function (value) { return normalizeOptionalString(value); }).filter(Boolean)
|
|
@@ -7814,6 +8208,85 @@ function buildAssistantContext(input, userContext) {
|
|
|
7814
8208
|
}
|
|
7815
8209
|
return lines.join('\n');
|
|
7816
8210
|
}
|
|
8211
|
+
function buildAssistantFieldHints(message, collectionNames, options) {
|
|
8212
|
+
var normalizedMessage = normalizeOptionalString(message);
|
|
8213
|
+
if (!normalizedMessage || !Array.isArray(collectionNames) || !collectionNames.length) {
|
|
8214
|
+
return [];
|
|
8215
|
+
}
|
|
8216
|
+
var maxCollections = typeof (options === null || options === void 0 ? void 0 : options.maxCollections) === 'number'
|
|
8217
|
+
? Math.max(options.maxCollections, 0)
|
|
8218
|
+
: AI_ASSISTANT_CONTEXT_MAX_COLLECTIONS;
|
|
8219
|
+
var maxFields = typeof (options === null || options === void 0 ? void 0 : options.maxFields) === 'number'
|
|
8220
|
+
? Math.max(options.maxFields, 0)
|
|
8221
|
+
: AI_ASSISTANT_CONTEXT_MAX_FIELDS_PER_COLLECTION;
|
|
8222
|
+
if (!maxCollections || !maxFields) {
|
|
8223
|
+
return [];
|
|
8224
|
+
}
|
|
8225
|
+
var baseTokens = tokenizeFieldKey(normalizedMessage);
|
|
8226
|
+
var expandedTokens = expandFieldTokens(baseTokens);
|
|
8227
|
+
var tokenSet = new Set(expandedTokens);
|
|
8228
|
+
[
|
|
8229
|
+
'date',
|
|
8230
|
+
'status',
|
|
8231
|
+
'total',
|
|
8232
|
+
'amount',
|
|
8233
|
+
'paid',
|
|
8234
|
+
'balance',
|
|
8235
|
+
'grand',
|
|
8236
|
+
'subtotal',
|
|
8237
|
+
'invoice',
|
|
8238
|
+
'revenue',
|
|
8239
|
+
'sales',
|
|
8240
|
+
'billing',
|
|
8241
|
+
'payment'
|
|
8242
|
+
].forEach(function (token) { return tokenSet.add(token); });
|
|
8243
|
+
var hints = [];
|
|
8244
|
+
var candidates = collectionNames.filter(Boolean).slice(0, maxCollections);
|
|
8245
|
+
candidates.forEach(function (collection) {
|
|
8246
|
+
var fields = getCollectionSchemaFieldNames(collection);
|
|
8247
|
+
if (!fields.length) {
|
|
8248
|
+
return;
|
|
8249
|
+
}
|
|
8250
|
+
var scored = fields
|
|
8251
|
+
.filter(function (field) { return field && !shouldRedactField(field); })
|
|
8252
|
+
.map(function (field) {
|
|
8253
|
+
var tokens = tokenizeFieldKey(field);
|
|
8254
|
+
if (!tokens.length) {
|
|
8255
|
+
return null;
|
|
8256
|
+
}
|
|
8257
|
+
var score = tokens.filter(function (token) { return tokenSet.has(token); }).length;
|
|
8258
|
+
var hasDate = tokens.includes('date');
|
|
8259
|
+
var hasStatus = tokens.includes('status');
|
|
8260
|
+
var hasTotal = tokens.includes('total') || tokens.includes('amount') || tokens.includes('paid') || tokens.includes('balance');
|
|
8261
|
+
if (score === 0 && (hasDate || hasStatus || hasTotal)) {
|
|
8262
|
+
score = 1;
|
|
8263
|
+
}
|
|
8264
|
+
if (score <= 0) {
|
|
8265
|
+
return null;
|
|
8266
|
+
}
|
|
8267
|
+
if (isAssistantIdField(field)) {
|
|
8268
|
+
score -= 1;
|
|
8269
|
+
}
|
|
8270
|
+
if (field.includes('.$.') && score < 2) {
|
|
8271
|
+
return null;
|
|
8272
|
+
}
|
|
8273
|
+
return { field: field, score: score };
|
|
8274
|
+
})
|
|
8275
|
+
.filter(function (entry) { return !!entry; })
|
|
8276
|
+
.sort(function (a, b) {
|
|
8277
|
+
if (a.score !== b.score) {
|
|
8278
|
+
return b.score - a.score;
|
|
8279
|
+
}
|
|
8280
|
+
return a.field.localeCompare(b.field);
|
|
8281
|
+
})
|
|
8282
|
+
.slice(0, maxFields)
|
|
8283
|
+
.map(function (entry) { return entry.field; });
|
|
8284
|
+
if (scored.length) {
|
|
8285
|
+
hints.push("Field hints (".concat(collection, "): ").concat(scored.join(', ')));
|
|
8286
|
+
}
|
|
8287
|
+
});
|
|
8288
|
+
return hints;
|
|
8289
|
+
}
|
|
7817
8290
|
var cachedClientRouteIndex = null;
|
|
7818
8291
|
function normalizeRouteKey(value) {
|
|
7819
8292
|
var trimmed = normalizeOptionalString(value);
|
|
@@ -7988,7 +8461,11 @@ function sanitizeAssistantResponse(value) {
|
|
|
7988
8461
|
if (!cleaned) {
|
|
7989
8462
|
return 'I can’t share code, but I can point you to files or explain behavior at a high level.';
|
|
7990
8463
|
}
|
|
7991
|
-
var normalizedCurrency = cleaned
|
|
8464
|
+
var normalizedCurrency = cleaned
|
|
8465
|
+
.replace(/\bUSD(?:\s| | |[\u00A0\u202F\u2007])*\$?\s*([-+]?[0-9][0-9,]*(?:\.[0-9]+)?)/g, function (_match, amount) {
|
|
8466
|
+
return "$".concat(amount);
|
|
8467
|
+
})
|
|
8468
|
+
.replace(/\bUS\$\s*([-+]?[0-9][0-9,]*(?:\.[0-9]+)?)/g, function (_match, amount) {
|
|
7992
8469
|
return "$".concat(amount);
|
|
7993
8470
|
});
|
|
7994
8471
|
return normalizeAssistantRoutes(normalizedCurrency);
|