@resolveio/server-lib 22.1.0 → 22.1.1

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.
@@ -109,18 +109,21 @@ exports.loadAiTerminalMethods = loadAiTerminalMethods;
109
109
  exports.executeAiAssistantMongoRead = executeAiAssistantMongoRead;
110
110
  exports.executeAiAssistantMongoAggregate = executeAiAssistantMongoAggregate;
111
111
  exports.extractAssistantMongoDirective = extractAssistantMongoDirective;
112
+ exports.buildAssistantInvoiceCustomerLabelExpr = buildAssistantInvoiceCustomerLabelExpr;
112
113
  exports.buildAssistantDatedPivotDisplay = buildAssistantDatedPivotDisplay;
113
114
  exports.normalizeIdsForTargetField = normalizeIdsForTargetField;
114
115
  exports.serializeMongoValue = serializeMongoValue;
115
116
  exports.flattenForTable = flattenForTable;
116
117
  exports.buildDisplayTable = buildDisplayTable;
117
118
  exports.formatDisplayTableMarkdown = formatDisplayTableMarkdown;
119
+ exports.resolveAssistantReadDisplayMaxRows = resolveAssistantReadDisplayMaxRows;
118
120
  exports.normalizeAssistantNowExprPlaceholders = normalizeAssistantNowExprPlaceholders;
119
121
  exports.rewriteMatchExpressionsToExpr = rewriteMatchExpressionsToExpr;
120
122
  exports.normalizeAssistantMonthlyCalendarWindowPipeline = normalizeAssistantMonthlyCalendarWindowPipeline;
121
123
  exports.stripQueryFieldPathsDeep = stripQueryFieldPathsDeep;
122
124
  exports.stripScopedFieldsFromPipeline = stripScopedFieldsFromPipeline;
123
125
  exports.rewriteEmbeddedMatchObjects = rewriteEmbeddedMatchObjects;
126
+ exports.resolveAssistantCollectionOverride = resolveAssistantCollectionOverride;
124
127
  exports.collectUserViewPermissions = collectUserViewPermissions;
125
128
  exports.userHasInvoiceAccess = userHasInvoiceAccess;
126
129
  exports.resolveAssistantUserAccessTier = resolveAssistantUserAccessTier;
@@ -389,6 +392,11 @@ var AI_ASSISTANT_TERM_SYNONYMS = [
389
392
  pattern: /\btruck\s+treating\s+jobs?\b/i,
390
393
  expansions: ['truck treating deliveries', 'truck-treating-deliveries', 'truck treating route events']
391
394
  },
395
+ {
396
+ label: 'active clients',
397
+ pattern: /\b(?:how\s+many\s+)?active\s+(?:clients?|customers?)\b/i,
398
+ expansions: ['customers', 'clients', 'customer status', 'client status']
399
+ },
392
400
  {
393
401
  label: 'blend tickets',
394
402
  pattern: /\bblend(?:ing)?\s+tickets?\b/i,
@@ -2318,10 +2326,10 @@ function executeAiAssistantReportBuilderAggregate(payload, context) {
2318
2326
  }
2319
2327
  function executeAiAssistantMongoRead(payload, context) {
2320
2328
  return __awaiter(this, void 0, void 0, function () {
2321
- var input, rawCollection, dbName, db, collectionResolution, collection, bridgeCollection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, strippedClient, clientScopedQuery, scopedQuery, normalized, findOptions, documents, executedQuery, probeDocs, dateFallback, fallbackQuery, fallbackDocs, expanded, fallbackDocs, nameFallback, fallbackDocs, _c, chemicalLookup, fallbackDocs, queryFields, _d, aliases, rewrittenQuery, fallbackDocs, _e, idLookup, fallbackDocs, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, nameFields, dateFields, diagnostics, queryNoName, _f, queryNoDate, _g, _h, _j, _k, allCollections, base, alt, altCount, _l, total, sanitizedDocuments, requestedFields, missingFields, _m, projectionAliases, expandedProjection, refreshedDocs, includeIds, fieldAliases, displayDocs, idLookupDisplay, priorityFields, display;
2322
- var _o, _p;
2323
- return __generator(this, function (_q) {
2324
- switch (_q.label) {
2329
+ var input, rawCollection, dbName, db, collectionResolution, collection, bridgeCollection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, strippedClient, clientScopedQuery, scopedQuery, normalized, findOptions, documents, executedQuery, probeDocs, dateFallback, fallbackQuery, fallbackDocs, expanded, fallbackDocs, nameFallback, fallbackDocs, _c, chemicalLookup, fallbackDocs, queryFields, _d, aliases, rewrittenQuery, fallbackDocs, _e, activeFallback, fallbackDocs, _f, idLookup, fallbackDocs, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, nameFields, dateFields, diagnostics, queryNoName, _g, queryNoDate, _h, _j, _k, _l, allCollections, base, alt, altCount, _m, total, sanitizedDocuments, requestedFields, missingFields, _o, projectionAliases, expandedProjection, refreshedDocs, includeIds, fieldAliases, displayDocs, idLookupDisplay, priorityFields, displayMaxRows, display;
2330
+ var _p, _q;
2331
+ return __generator(this, function (_r) {
2332
+ switch (_r.label) {
2325
2333
  case 0:
2326
2334
  input = payload || {};
2327
2335
  rawCollection = normalizeOptionalString(input.collection);
@@ -2332,22 +2340,22 @@ function executeAiAssistantMongoRead(payload, context) {
2332
2340
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
2333
2341
  return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
2334
2342
  case 1:
2335
- collectionResolution = _q.sent();
2343
+ collectionResolution = _r.sent();
2336
2344
  collection = collectionResolution.name || rawCollection;
2337
2345
  return [4 /*yield*/, resolveAssistantReportBuilderBridgeCollection(collection, db, dbName)];
2338
2346
  case 2:
2339
- bridgeCollection = _q.sent();
2347
+ bridgeCollection = _r.sent();
2340
2348
  if (bridgeCollection.fallbackFrom) {
2341
2349
  collection = bridgeCollection.collection;
2342
2350
  }
2343
2351
  schemaFields = getCollectionSchemaFieldNames(collection);
2344
2352
  return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
2345
2353
  case 3:
2346
- _a = _q.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
2354
+ _a = _r.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
2347
2355
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
2348
2356
  throw new Error('AI assistant report builder bridge: Access denied.');
2349
2357
  }
2350
- customerId = normalizeOptionalString((_o = user === null || user === void 0 ? void 0 : user.other) === null || _o === void 0 ? void 0 : _o.id_customer);
2358
+ customerId = normalizeOptionalString((_p = user === null || user === void 0 ? void 0 : user.other) === null || _p === void 0 ? void 0 : _p.id_customer);
2351
2359
  fallbackMeta = {};
2352
2360
  if (bridgeCollection.fallbackFrom) {
2353
2361
  fallbackMeta.reportBuilderBridge = {
@@ -2379,11 +2387,11 @@ function executeAiAssistantMongoRead(payload, context) {
2379
2387
  if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 5];
2380
2388
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
2381
2389
  case 4:
2382
- _b = _q.sent();
2390
+ _b = _r.sent();
2383
2391
  return [3 /*break*/, 6];
2384
2392
  case 5:
2385
2393
  _b = false;
2386
- _q.label = 6;
2394
+ _r.label = 6;
2387
2395
  case 6:
2388
2396
  shouldScopeByClient = _b;
2389
2397
  if (!isSuperAdmin && shouldScopeByClient) {
@@ -2403,7 +2411,7 @@ function executeAiAssistantMongoRead(payload, context) {
2403
2411
  findOptions = __assign(__assign({}, normalized.findOptions), { readPreference: AI_ASSISTANT_READ_PREFERENCE });
2404
2412
  return [4 /*yield*/, db.collection(collection).find(scopedQuery, findOptions).toArray()];
2405
2413
  case 7:
2406
- documents = _q.sent();
2414
+ documents = _r.sent();
2407
2415
  executedQuery = scopedQuery;
2408
2416
  probeDocs = null;
2409
2417
  if (!!documents.length) return [3 /*break*/, 9];
@@ -2413,13 +2421,13 @@ function executeAiAssistantMongoRead(payload, context) {
2413
2421
  fallbackMeta.dateField = __assign(__assign({}, dateFallback), { attempted: true, used: false });
2414
2422
  return [4 /*yield*/, db.collection(collection).find(fallbackQuery, findOptions).toArray()];
2415
2423
  case 8:
2416
- fallbackDocs = _q.sent();
2424
+ fallbackDocs = _r.sent();
2417
2425
  if (fallbackDocs.length) {
2418
2426
  documents = fallbackDocs;
2419
2427
  executedQuery = fallbackQuery;
2420
2428
  fallbackMeta.dateField.used = true;
2421
2429
  }
2422
- _q.label = 9;
2430
+ _r.label = 9;
2423
2431
  case 9:
2424
2432
  if (!!documents.length) return [3 /*break*/, 11];
2425
2433
  expanded = expandQueryDateFallbacks(executedQuery, schemaFields);
@@ -2431,13 +2439,13 @@ function executeAiAssistantMongoRead(payload, context) {
2431
2439
  };
2432
2440
  return [4 /*yield*/, db.collection(collection).find(expanded.query, findOptions).toArray()];
2433
2441
  case 10:
2434
- fallbackDocs = _q.sent();
2442
+ fallbackDocs = _r.sent();
2435
2443
  if (fallbackDocs.length) {
2436
2444
  documents = fallbackDocs;
2437
2445
  executedQuery = expanded.query;
2438
2446
  fallbackMeta.dateFieldsExpanded.used = true;
2439
2447
  }
2440
- _q.label = 11;
2448
+ _r.label = 11;
2441
2449
  case 11:
2442
2450
  if (!!documents.length) return [3 /*break*/, 13];
2443
2451
  nameFallback = resolveReadNameMatchFallback(executedQuery);
@@ -2450,13 +2458,13 @@ function executeAiAssistantMongoRead(payload, context) {
2450
2458
  };
2451
2459
  return [4 /*yield*/, db.collection(collection).find(nameFallback.query, findOptions).toArray()];
2452
2460
  case 12:
2453
- fallbackDocs = _q.sent();
2461
+ fallbackDocs = _r.sent();
2454
2462
  if (fallbackDocs.length) {
2455
2463
  documents = fallbackDocs;
2456
2464
  executedQuery = nameFallback.query;
2457
2465
  fallbackMeta.nameMatch.used = true;
2458
2466
  }
2459
- _q.label = 13;
2467
+ _r.label = 13;
2460
2468
  case 13:
2461
2469
  if (!!documents.length) return [3 /*break*/, 18];
2462
2470
  _c = probeDocs;
@@ -2470,8 +2478,8 @@ function executeAiAssistantMongoRead(payload, context) {
2470
2478
  includeClientScope: shouldScopeByClient
2471
2479
  })];
2472
2480
  case 14:
2473
- _c = (_q.sent());
2474
- _q.label = 15;
2481
+ _c = (_r.sent());
2482
+ _r.label = 15;
2475
2483
  case 15:
2476
2484
  probeDocs = _c;
2477
2485
  return [4 /*yield*/, applyChemicalNameLookupFallbackToQuery({
@@ -2484,18 +2492,18 @@ function executeAiAssistantMongoRead(payload, context) {
2484
2492
  probeDocs: probeDocs || undefined
2485
2493
  })];
2486
2494
  case 16:
2487
- chemicalLookup = _q.sent();
2495
+ chemicalLookup = _r.sent();
2488
2496
  if (!chemicalLookup) return [3 /*break*/, 18];
2489
2497
  fallbackMeta.chemicalLookup = __assign(__assign({}, chemicalLookup.meta), { attempted: true, used: false });
2490
2498
  return [4 /*yield*/, db.collection(collection).find(chemicalLookup.query, findOptions).toArray()];
2491
2499
  case 17:
2492
- fallbackDocs = _q.sent();
2500
+ fallbackDocs = _r.sent();
2493
2501
  if (fallbackDocs.length) {
2494
2502
  documents = fallbackDocs;
2495
2503
  executedQuery = chemicalLookup.query;
2496
2504
  fallbackMeta.chemicalLookup.used = true;
2497
2505
  }
2498
- _q.label = 18;
2506
+ _r.label = 18;
2499
2507
  case 18:
2500
2508
  if (!!documents.length) return [3 /*break*/, 22];
2501
2509
  queryFields = extractQueryFieldPaths(executedQuery).filter(function (field) { return !isAssistantIdField(field); });
@@ -2511,8 +2519,8 @@ function executeAiAssistantMongoRead(payload, context) {
2511
2519
  includeClientScope: shouldScopeByClient
2512
2520
  })];
2513
2521
  case 19:
2514
- _d = (_q.sent());
2515
- _q.label = 20;
2522
+ _d = (_r.sent());
2523
+ _r.label = 20;
2516
2524
  case 20:
2517
2525
  probeDocs = _d;
2518
2526
  if (!probeDocs.length) return [3 /*break*/, 22];
@@ -2530,15 +2538,15 @@ function executeAiAssistantMongoRead(payload, context) {
2530
2538
  }, executedQuery);
2531
2539
  return [4 /*yield*/, db.collection(collection).find(rewrittenQuery, findOptions).toArray()];
2532
2540
  case 21:
2533
- fallbackDocs = _q.sent();
2541
+ fallbackDocs = _r.sent();
2534
2542
  if (fallbackDocs.length) {
2535
2543
  documents = fallbackDocs;
2536
2544
  executedQuery = rewrittenQuery;
2537
2545
  fallbackMeta.queryFieldAliases.used = true;
2538
2546
  }
2539
- _q.label = 22;
2547
+ _r.label = 22;
2540
2548
  case 22:
2541
- if (!!documents.length) return [3 /*break*/, 27];
2549
+ if (!!documents.length) return [3 /*break*/, 26];
2542
2550
  _e = probeDocs;
2543
2551
  if (_e) return [3 /*break*/, 24];
2544
2552
  return [4 /*yield*/, fetchAssistantProbeDocs({
@@ -2550,10 +2558,44 @@ function executeAiAssistantMongoRead(payload, context) {
2550
2558
  includeClientScope: shouldScopeByClient
2551
2559
  })];
2552
2560
  case 23:
2553
- _e = (_q.sent());
2554
- _q.label = 24;
2561
+ _e = (_r.sent());
2562
+ _r.label = 24;
2555
2563
  case 24:
2556
2564
  probeDocs = _e;
2565
+ activeFallback = resolveReadActiveStatusFallback(executedQuery, probeDocs || []);
2566
+ if (!activeFallback) return [3 /*break*/, 26];
2567
+ fallbackMeta.activeStatus = {
2568
+ fields: activeFallback.fields,
2569
+ attempted: true,
2570
+ used: false,
2571
+ reason: 'active_fields_missing_in_collection'
2572
+ };
2573
+ return [4 /*yield*/, db.collection(collection).find(activeFallback.query, findOptions).toArray()];
2574
+ case 25:
2575
+ fallbackDocs = _r.sent();
2576
+ if (fallbackDocs.length) {
2577
+ documents = fallbackDocs;
2578
+ executedQuery = activeFallback.query;
2579
+ fallbackMeta.activeStatus.used = true;
2580
+ }
2581
+ _r.label = 26;
2582
+ case 26:
2583
+ if (!!documents.length) return [3 /*break*/, 31];
2584
+ _f = probeDocs;
2585
+ if (_f) return [3 /*break*/, 28];
2586
+ return [4 /*yield*/, fetchAssistantProbeDocs({
2587
+ db: db,
2588
+ collection: collection,
2589
+ idClient: normalizedClient,
2590
+ idCustomer: customerId,
2591
+ isSuperAdmin: isSuperAdmin,
2592
+ includeClientScope: shouldScopeByClient
2593
+ })];
2594
+ case 27:
2595
+ _f = (_r.sent());
2596
+ _r.label = 28;
2597
+ case 28:
2598
+ probeDocs = _f;
2557
2599
  return [4 /*yield*/, applyIdLookupFallbackToQuery({
2558
2600
  query: executedQuery,
2559
2601
  db: db,
@@ -2563,29 +2605,29 @@ function executeAiAssistantMongoRead(payload, context) {
2563
2605
  isSuperAdmin: isSuperAdmin,
2564
2606
  probeDocs: probeDocs || undefined
2565
2607
  })];
2566
- case 25:
2567
- idLookup = _q.sent();
2568
- if (!idLookup) return [3 /*break*/, 27];
2608
+ case 29:
2609
+ idLookup = _r.sent();
2610
+ if (!idLookup) return [3 /*break*/, 31];
2569
2611
  fallbackMeta.idLookup = __assign(__assign({}, idLookup.meta), { attempted: true, used: false });
2570
2612
  return [4 /*yield*/, db.collection(collection).find(idLookup.query, findOptions).toArray()];
2571
- case 26:
2572
- fallbackDocs = _q.sent();
2613
+ case 30:
2614
+ fallbackDocs = _r.sent();
2573
2615
  if (fallbackDocs.length) {
2574
2616
  documents = fallbackDocs;
2575
2617
  executedQuery = idLookup.query;
2576
2618
  fallbackMeta.idLookup.used = true;
2577
2619
  }
2578
- _q.label = 27;
2579
- case 27:
2580
- if (!!documents.length) return [3 /*break*/, 30];
2620
+ _r.label = 31;
2621
+ case 31:
2622
+ if (!!documents.length) return [3 /*break*/, 34];
2581
2623
  return [4 /*yield*/, resolveBaseCollectionFromReport(db, dbName, collection)];
2582
- case 28:
2583
- baseCollection = _q.sent();
2584
- if (!(baseCollection && baseCollection !== collection)) return [3 /*break*/, 30];
2624
+ case 32:
2625
+ baseCollection = _r.sent();
2626
+ if (!(baseCollection && baseCollection !== collection)) return [3 /*break*/, 34];
2585
2627
  fallbackPayload = __assign(__assign({}, input), { collection: baseCollection });
2586
2628
  return [4 /*yield*/, executeAiAssistantMongoRead(fallbackPayload, context)];
2587
- case 29:
2588
- fallbackResult = _q.sent();
2629
+ case 33:
2630
+ fallbackResult = _r.sent();
2589
2631
  if (Array.isArray(fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.documents) && fallbackResult.documents.length) {
2590
2632
  if (isSuperAdmin && (fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.debug) && typeof fallbackResult.debug === 'object') {
2591
2633
  existingFallbacks = fallbackResult.debug.fallbacks && typeof fallbackResult.debug.fallbacks === 'object'
@@ -2602,9 +2644,9 @@ function executeAiAssistantMongoRead(payload, context) {
2602
2644
  if (isSuperAdmin) {
2603
2645
  fallbackMeta.reportFallback = { from: collection, to: baseCollection, attempted: true, used: false };
2604
2646
  }
2605
- _q.label = 30;
2606
- case 30:
2607
- if (!(!documents.length && isSuperAdmin)) return [3 /*break*/, 47];
2647
+ _r.label = 34;
2648
+ case 34:
2649
+ if (!(!documents.length && isSuperAdmin)) return [3 /*break*/, 51];
2608
2650
  nameFields = collectMatchFieldsByCondition(executedQuery, function (field, condition) { return isRegexMatchCondition(condition)
2609
2651
  || (typeof condition === 'string' && shouldApplyAssistantNameRegex(field)); });
2610
2652
  dateFields = collectMatchFieldsByCondition(executedQuery, function (_field, condition) { return isDateCondition(condition); });
@@ -2612,36 +2654,36 @@ function executeAiAssistantMongoRead(payload, context) {
2612
2654
  nameFields: nameFields.length ? nameFields : undefined,
2613
2655
  dateFields: dateFields.length ? dateFields : undefined
2614
2656
  };
2615
- _q.label = 31;
2616
- case 31:
2617
- _q.trys.push([31, 36, , 37]);
2618
- if (!nameFields.length) return [3 /*break*/, 33];
2657
+ _r.label = 35;
2658
+ case 35:
2659
+ _r.trys.push([35, 40, , 41]);
2660
+ if (!nameFields.length) return [3 /*break*/, 37];
2619
2661
  queryNoName = stripMatchFields(executedQuery, nameFields);
2620
- _f = diagnostics;
2662
+ _g = diagnostics;
2621
2663
  return [4 /*yield*/, db.collection(collection).countDocuments(queryNoName, {
2622
2664
  readPreference: AI_ASSISTANT_READ_PREFERENCE
2623
2665
  })];
2624
- case 32:
2625
- _f.recentCount = _q.sent();
2626
- _q.label = 33;
2627
- case 33:
2628
- if (!dateFields.length) return [3 /*break*/, 35];
2666
+ case 36:
2667
+ _g.recentCount = _r.sent();
2668
+ _r.label = 37;
2669
+ case 37:
2670
+ if (!dateFields.length) return [3 /*break*/, 39];
2629
2671
  queryNoDate = stripMatchFields(executedQuery, dateFields);
2630
- _g = diagnostics;
2672
+ _h = diagnostics;
2631
2673
  return [4 /*yield*/, db.collection(collection).countDocuments(queryNoDate, {
2632
2674
  readPreference: AI_ASSISTANT_READ_PREFERENCE
2633
2675
  })];
2634
- case 34:
2635
- _g.nameMatchCount = _q.sent();
2636
- _q.label = 35;
2637
- case 35: return [3 /*break*/, 37];
2638
- case 36:
2639
- _h = _q.sent();
2640
- return [3 /*break*/, 37];
2641
- case 37:
2642
- _q.trys.push([37, 40, , 41]);
2643
- _j = probeDocs;
2644
- if (_j) return [3 /*break*/, 39];
2676
+ case 38:
2677
+ _h.nameMatchCount = _r.sent();
2678
+ _r.label = 39;
2679
+ case 39: return [3 /*break*/, 41];
2680
+ case 40:
2681
+ _j = _r.sent();
2682
+ return [3 /*break*/, 41];
2683
+ case 41:
2684
+ _r.trys.push([41, 44, , 45]);
2685
+ _k = probeDocs;
2686
+ if (_k) return [3 /*break*/, 43];
2645
2687
  return [4 /*yield*/, fetchAssistantProbeDocs({
2646
2688
  db: db,
2647
2689
  collection: collection,
@@ -2650,56 +2692,56 @@ function executeAiAssistantMongoRead(payload, context) {
2650
2692
  isSuperAdmin: isSuperAdmin,
2651
2693
  includeClientScope: shouldScopeByClient
2652
2694
  })];
2653
- case 38:
2654
- _j = (_q.sent());
2655
- _q.label = 39;
2656
- case 39:
2657
- probeDocs = _j;
2695
+ case 42:
2696
+ _k = (_r.sent());
2697
+ _r.label = 43;
2698
+ case 43:
2699
+ probeDocs = _k;
2658
2700
  if (probeDocs.length && nameFields.length) {
2659
2701
  diagnostics.chemicalIdDetected = detectChemicalIdFromProbe(probeDocs, nameFields);
2660
2702
  }
2661
- return [3 /*break*/, 41];
2662
- case 40:
2663
- _k = _q.sent();
2664
- return [3 /*break*/, 41];
2665
- case 41:
2666
- _q.trys.push([41, 45, , 46]);
2703
+ return [3 /*break*/, 45];
2704
+ case 44:
2705
+ _l = _r.sent();
2706
+ return [3 /*break*/, 45];
2707
+ case 45:
2708
+ _r.trys.push([45, 49, , 50]);
2667
2709
  return [4 /*yield*/, listAssistantCollections(db, dbName)];
2668
- case 42:
2669
- allCollections = _q.sent();
2710
+ case 46:
2711
+ allCollections = _r.sent();
2670
2712
  base = stripVersionSuffix(collection.startsWith('report-') ? collection.slice('report-'.length) : collection);
2671
2713
  alt = collection.startsWith('report-') ? base : "report-".concat(base);
2672
- if (!(alt && alt !== collection && allCollections.includes(alt))) return [3 /*break*/, 44];
2714
+ if (!(alt && alt !== collection && allCollections.includes(alt))) return [3 /*break*/, 48];
2673
2715
  return [4 /*yield*/, db.collection(alt).countDocuments({}, { readPreference: AI_ASSISTANT_READ_PREFERENCE })];
2674
- case 43:
2675
- altCount = _q.sent();
2716
+ case 47:
2717
+ altCount = _r.sent();
2676
2718
  diagnostics.alternateCollection = alt;
2677
2719
  diagnostics.alternateCollectionCount = altCount;
2678
- _q.label = 44;
2679
- case 44: return [3 /*break*/, 46];
2680
- case 45:
2681
- _l = _q.sent();
2682
- return [3 /*break*/, 46];
2683
- case 46:
2720
+ _r.label = 48;
2721
+ case 48: return [3 /*break*/, 50];
2722
+ case 49:
2723
+ _m = _r.sent();
2724
+ return [3 /*break*/, 50];
2725
+ case 50:
2684
2726
  fallbackMeta.zeroDiagnostics = diagnostics;
2685
- _q.label = 47;
2686
- case 47:
2727
+ _r.label = 51;
2728
+ case 51:
2687
2729
  total = null;
2688
- if (!normalized.includeTotal) return [3 /*break*/, 49];
2730
+ if (!normalized.includeTotal) return [3 /*break*/, 53];
2689
2731
  return [4 /*yield*/, db.collection(collection).countDocuments(executedQuery, { readPreference: AI_ASSISTANT_READ_PREFERENCE })];
2690
- case 48:
2691
- total = _q.sent();
2692
- _q.label = 49;
2693
- case 49:
2732
+ case 52:
2733
+ total = _r.sent();
2734
+ _r.label = 53;
2735
+ case 53:
2694
2736
  sanitizedDocuments = isSuperAdmin
2695
2737
  ? documents
2696
2738
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
2697
2739
  requestedFields = resolveProjectionRequestedFields(findOptions.projection);
2698
- if (!(sanitizedDocuments.length && requestedFields.length)) return [3 /*break*/, 53];
2740
+ if (!(sanitizedDocuments.length && requestedFields.length)) return [3 /*break*/, 57];
2699
2741
  missingFields = requestedFields.filter(function (field) { return !hasNonEmptyValue(sanitizedDocuments, field, { treatObjectLikeAsEmpty: true }); });
2700
- if (!missingFields.length) return [3 /*break*/, 53];
2701
- _m = probeDocs;
2702
- if (_m) return [3 /*break*/, 51];
2742
+ if (!missingFields.length) return [3 /*break*/, 57];
2743
+ _o = probeDocs;
2744
+ if (_o) return [3 /*break*/, 55];
2703
2745
  return [4 /*yield*/, fetchAssistantProbeDocs({
2704
2746
  db: db,
2705
2747
  collection: collection,
@@ -2708,26 +2750,26 @@ function executeAiAssistantMongoRead(payload, context) {
2708
2750
  isSuperAdmin: isSuperAdmin,
2709
2751
  includeClientScope: shouldScopeByClient
2710
2752
  })];
2711
- case 50:
2712
- _m = (_q.sent());
2713
- _q.label = 51;
2714
- case 51:
2715
- probeDocs = _m;
2716
- if (!probeDocs.length) return [3 /*break*/, 53];
2753
+ case 54:
2754
+ _o = (_r.sent());
2755
+ _r.label = 55;
2756
+ case 55:
2757
+ probeDocs = _o;
2758
+ if (!probeDocs.length) return [3 /*break*/, 57];
2717
2759
  projectionAliases = resolveFieldAliases(probeDocs, missingFields, schemaFields);
2718
- if (!Object.keys(projectionAliases).length) return [3 /*break*/, 53];
2760
+ if (!Object.keys(projectionAliases).length) return [3 /*break*/, 57];
2719
2761
  fallbackMeta.projectionAliases = {
2720
2762
  aliases: projectionAliases,
2721
2763
  attempted: true,
2722
2764
  used: false
2723
2765
  };
2724
2766
  expandedProjection = expandProjectionWithAliases(findOptions.projection, projectionAliases);
2725
- if (!(expandedProjection && expandedProjection !== findOptions.projection)) return [3 /*break*/, 53];
2767
+ if (!(expandedProjection && expandedProjection !== findOptions.projection)) return [3 /*break*/, 57];
2726
2768
  findOptions = __assign(__assign({}, findOptions), { projection: expandedProjection });
2727
2769
  normalized.findOptions.projection = expandedProjection;
2728
2770
  return [4 /*yield*/, db.collection(collection).find(executedQuery, findOptions).toArray()];
2729
- case 52:
2730
- refreshedDocs = _q.sent();
2771
+ case 56:
2772
+ refreshedDocs = _r.sent();
2731
2773
  if (refreshedDocs.length) {
2732
2774
  documents = refreshedDocs;
2733
2775
  sanitizedDocuments = isSuperAdmin
@@ -2735,9 +2777,9 @@ function executeAiAssistantMongoRead(payload, context) {
2735
2777
  : refreshedDocs.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
2736
2778
  fallbackMeta.projectionAliases.used = true;
2737
2779
  }
2738
- _q.label = 53;
2739
- case 53:
2740
- includeIds = ((_p = input.options) === null || _p === void 0 ? void 0 : _p.includeIds) === true;
2780
+ _r.label = 57;
2781
+ case 57:
2782
+ includeIds = ((_q = input.options) === null || _q === void 0 ? void 0 : _q.includeIds) === true;
2741
2783
  fieldAliases = resolveFieldAliases(sanitizedDocuments, requestedFields, schemaFields);
2742
2784
  displayDocs = Object.keys(fieldAliases).length
2743
2785
  ? applyFieldAliasesForDisplay(sanitizedDocuments, fieldAliases)
@@ -2751,8 +2793,8 @@ function executeAiAssistantMongoRead(payload, context) {
2751
2793
  idCustomer: customerId,
2752
2794
  isSuperAdmin: isSuperAdmin
2753
2795
  })];
2754
- case 54:
2755
- idLookupDisplay = _q.sent();
2796
+ case 58:
2797
+ idLookupDisplay = _r.sent();
2756
2798
  if (idLookupDisplay === null || idLookupDisplay === void 0 ? void 0 : idLookupDisplay.docs) {
2757
2799
  displayDocs = idLookupDisplay.docs;
2758
2800
  }
@@ -2761,10 +2803,11 @@ function executeAiAssistantMongoRead(payload, context) {
2761
2803
  }
2762
2804
  priorityFields = requestedFields.length
2763
2805
  ? __spreadArray(__spreadArray([], __read(requestedFields), false), __read(AI_ASSISTANT_DISPLAY_PRIORITY_FIELDS), false) : AI_ASSISTANT_DISPLAY_PRIORITY_FIELDS;
2806
+ displayMaxRows = resolveAssistantReadDisplayMaxRows(normalized.findOptions.limit, sanitizedDocuments.length);
2764
2807
  display = buildDisplayTable(displayDocs, {
2765
2808
  includeIds: includeIds,
2766
2809
  maxColumns: AI_ASSISTANT_DISPLAY_MAX_COLUMNS,
2767
- maxRows: normalized.findOptions.limit,
2810
+ maxRows: displayMaxRows,
2768
2811
  priorityFields: priorityFields,
2769
2812
  includeGroupFromId: false
2770
2813
  });
@@ -4212,30 +4255,81 @@ function resolveAssistantRevenueByTimeRequest(text, scope) {
4212
4255
  amount: Math.min(Math.max((0, common_1.round)(amount), 1), 400)
4213
4256
  };
4214
4257
  }
4258
+ function buildAssistantTrimmedStringExpr(value) {
4259
+ return {
4260
+ $trim: {
4261
+ input: {
4262
+ $convert: {
4263
+ input: value,
4264
+ to: 'string',
4265
+ onError: '',
4266
+ onNull: ''
4267
+ }
4268
+ }
4269
+ }
4270
+ };
4271
+ }
4272
+ function buildAssistantInvoiceCustomerLabelExpr() {
4273
+ return {
4274
+ $let: {
4275
+ vars: {
4276
+ customer_name: buildAssistantTrimmedStringExpr('$customer_name'),
4277
+ customer_fullname: buildAssistantTrimmedStringExpr('$customer.fullname'),
4278
+ customer_nested_name: buildAssistantTrimmedStringExpr('$customer.name'),
4279
+ customer_scalar: buildAssistantTrimmedStringExpr('$customer'),
4280
+ client_name: buildAssistantTrimmedStringExpr('$client_name'),
4281
+ client_fullname: buildAssistantTrimmedStringExpr('$client.fullname'),
4282
+ client_nested_name: buildAssistantTrimmedStringExpr('$client.name'),
4283
+ client_scalar: buildAssistantTrimmedStringExpr('$client'),
4284
+ id_customer: buildAssistantTrimmedStringExpr('$id_customer'),
4285
+ id_client: buildAssistantTrimmedStringExpr('$id_client')
4286
+ },
4287
+ in: {
4288
+ $switch: {
4289
+ branches: [
4290
+ { case: { $gt: [{ $strLenCP: '$$customer_name' }, 0] }, then: '$$customer_name' },
4291
+ { case: { $gt: [{ $strLenCP: '$$customer_fullname' }, 0] }, then: '$$customer_fullname' },
4292
+ { case: { $gt: [{ $strLenCP: '$$customer_nested_name' }, 0] }, then: '$$customer_nested_name' },
4293
+ { case: { $gt: [{ $strLenCP: '$$customer_scalar' }, 0] }, then: '$$customer_scalar' },
4294
+ { case: { $gt: [{ $strLenCP: '$$client_name' }, 0] }, then: '$$client_name' },
4295
+ { case: { $gt: [{ $strLenCP: '$$client_fullname' }, 0] }, then: '$$client_fullname' },
4296
+ { case: { $gt: [{ $strLenCP: '$$client_nested_name' }, 0] }, then: '$$client_nested_name' },
4297
+ { case: { $gt: [{ $strLenCP: '$$client_scalar' }, 0] }, then: '$$client_scalar' },
4298
+ { case: { $gt: [{ $strLenCP: '$$id_customer' }, 0] }, then: '$$id_customer' },
4299
+ { case: { $gt: [{ $strLenCP: '$$id_client' }, 0] }, then: '$$id_client' }
4300
+ ],
4301
+ default: 'Unknown Customer'
4302
+ }
4303
+ }
4304
+ }
4305
+ };
4306
+ }
4307
+ function resolveAssistantRevenueByTimePipelineLimit(request, scope) {
4308
+ var amount = Math.min(Math.max((0, common_1.round)(request.amount), 1), 400);
4309
+ if (scope !== 'by_customer') {
4310
+ return Math.min(Math.max(amount * 2, 20), 200);
4311
+ }
4312
+ // Customer breakdowns need much higher pre-pivot row coverage so each customer appears.
4313
+ var perBucketTargets = {
4314
+ day: 120,
4315
+ week: 220,
4316
+ month: 350,
4317
+ quarter: 450,
4318
+ year: 600
4319
+ };
4320
+ var perBucketTarget = perBucketTargets[request.grain] || 300;
4321
+ return Math.min(Math.max(amount * perBucketTarget, 400), 5000);
4322
+ }
4215
4323
  function buildAssistantInvoiceRevenueByTimePipeline(request, scope) {
4216
4324
  var _a, _b, _c;
4217
4325
  if (scope === void 0) { scope = 'overall'; }
4218
4326
  var grain = request.grain;
4219
4327
  var amount = Math.min(Math.max((0, common_1.round)(request.amount), 1), 400);
4220
4328
  var byCustomer = scope === 'by_customer';
4329
+ var limit = resolveAssistantRevenueByTimePipelineLimit(request, scope);
4221
4330
  var effectiveDateExpr = { $ifNull: ['$date_paid', { $ifNull: ['$date_invoiced', '$createdAt'] }] };
4222
4331
  var effectiveTotalExpr = { $ifNull: ['$paid_total', '$grand_total'] };
4223
- var customerExpr = {
4224
- $ifNull: [
4225
- '$customer_name',
4226
- {
4227
- $ifNull: [
4228
- '$customer.fullname',
4229
- {
4230
- $ifNull: [
4231
- '$customer.name',
4232
- { $ifNull: [{ $toString: '$id_customer' }, 'Unknown Customer'] }
4233
- ]
4234
- }
4235
- ]
4236
- }
4237
- ]
4238
- };
4332
+ var customerExpr = buildAssistantInvoiceCustomerLabelExpr();
4239
4333
  var startDateExpr = grain === 'quarter'
4240
4334
  ? { $dateSubtract: { startDate: '$$NOW', unit: 'month', amount: amount * 3 } }
4241
4335
  : { $dateSubtract: { startDate: '$$NOW', unit: grain, amount: amount } };
@@ -4267,7 +4361,7 @@ function buildAssistantInvoiceRevenueByTimePipeline(request, scope) {
4267
4361
  $project: __assign(__assign({ _id: 0 }, (byCustomer ? { customer: '$_id.customer' } : {})), { quarter: { $concat: [{ $toString: '$_id.year' }, '-Q', { $toString: '$_id.quarter' }] }, total_revenue: 1 })
4268
4362
  },
4269
4363
  { $sort: byCustomer ? { customer: 1, quarter: 1 } : { quarter: 1 } },
4270
- { $limit: Math.min(Math.max(amount * (byCustomer ? 50 : 2), byCustomer ? 120 : 20), byCustomer ? 500 : 200) }
4364
+ { $limit: limit }
4271
4365
  ], false);
4272
4366
  }
4273
4367
  if (grain === 'year') {
@@ -4284,7 +4378,7 @@ function buildAssistantInvoiceRevenueByTimePipeline(request, scope) {
4284
4378
  $project: __assign(__assign({ _id: 0 }, (byCustomer ? { customer: '$_id.customer' } : {})), { year: '$_id.year', total_revenue: 1 })
4285
4379
  },
4286
4380
  { $sort: byCustomer ? { customer: 1, year: 1 } : { year: 1 } },
4287
- { $limit: Math.min(Math.max(amount * (byCustomer ? 50 : 2), byCustomer ? 120 : 20), byCustomer ? 500 : 200) }
4381
+ { $limit: limit }
4288
4382
  ], false);
4289
4383
  }
4290
4384
  var bucketField = grain;
@@ -4314,7 +4408,7 @@ function buildAssistantInvoiceRevenueByTimePipeline(request, scope) {
4314
4408
  }, _a.total_revenue = 1, _a))
4315
4409
  },
4316
4410
  { $sort: byCustomer ? (_b = { customer: 1 }, _b[bucketField] = 1, _b) : (_c = {}, _c[bucketField] = 1, _c) },
4317
- { $limit: Math.min(Math.max(amount * (byCustomer ? 50 : 2), byCustomer ? 120 : 20), byCustomer ? 500 : 200) }
4411
+ { $limit: limit }
4318
4412
  ], false);
4319
4413
  }
4320
4414
  function isAssistantRevenueByTimeHeuristicDirective(directive) {
@@ -4325,8 +4419,18 @@ function isAssistantBlendRedUltraLiftHeuristicDirective(directive) {
4325
4419
  var rawLine = normalizeOptionalString(directive === null || directive === void 0 ? void 0 : directive.rawLine).toLowerCase();
4326
4420
  return rawLine.includes('heuristic_agg(blend-red-ultra-lift)');
4327
4421
  }
4422
+ function isAssistantActiveClientsHeuristicDirective(directive) {
4423
+ var rawLine = normalizeOptionalString(directive === null || directive === void 0 ? void 0 : directive.rawLine).toLowerCase();
4424
+ return rawLine.includes('heuristic_read(active-clients-count)');
4425
+ }
4426
+ function isAssistantInvoiceTopCustomersHeuristicDirective(directive) {
4427
+ var rawLine = normalizeOptionalString(directive === null || directive === void 0 ? void 0 : directive.rawLine).toLowerCase();
4428
+ return rawLine.includes('heuristic_agg(invoice-top-customers)');
4429
+ }
4328
4430
  function isAssistantDeterministicHeuristicDirective(directive) {
4329
4431
  return isAssistantRevenueByTimeHeuristicDirective(directive)
4432
+ || isAssistantActiveClientsHeuristicDirective(directive)
4433
+ || isAssistantInvoiceTopCustomersHeuristicDirective(directive)
4330
4434
  || isAssistantBlendRedUltraLiftHeuristicDirective(directive);
4331
4435
  }
4332
4436
  function buildAssistantHeuristicDirective(message, collectionHints) {
@@ -4334,14 +4438,58 @@ function buildAssistantHeuristicDirective(message, collectionHints) {
4334
4438
  if (!text) {
4335
4439
  return null;
4336
4440
  }
4441
+ if (/\bhow\s+many\b.*\bactive\b.*\b(clients?|customers?)\b/.test(text)
4442
+ || /\bactive\b.*\b(clients?|customers?)\b.*\bhow\s+many\b/.test(text)) {
4443
+ var mergedHints = mergeAssistantHintValues(collectionHints, resolveAssistantDefaultCollectionHints(message));
4444
+ var customerCollection = mergedHints.includes('customers')
4445
+ ? 'customers'
4446
+ : (mergedHints.includes('clients') ? 'clients' : 'customers');
4447
+ return {
4448
+ type: 'read',
4449
+ payload: {
4450
+ collection: customerCollection,
4451
+ permissionView: '/client/list',
4452
+ query: {
4453
+ $or: [
4454
+ { status: { $regex: '^active$', $options: 'i' } },
4455
+ { state: { $regex: '^active$', $options: 'i' } },
4456
+ { active: true },
4457
+ { is_active: true },
4458
+ { enabled: true },
4459
+ { is_enabled: true }
4460
+ ]
4461
+ },
4462
+ options: {
4463
+ projection: {
4464
+ status: 1,
4465
+ state: 1,
4466
+ active: 1,
4467
+ is_active: 1,
4468
+ enabled: 1,
4469
+ is_enabled: 1
4470
+ },
4471
+ limit: 0,
4472
+ includeTotal: true
4473
+ }
4474
+ },
4475
+ cleaned: '',
4476
+ rawLine: 'HEURISTIC_READ(active-clients-count)'
4477
+ };
4478
+ }
4337
4479
  var revenueByCustomerTime = resolveAssistantRevenueByTimeRequest(text, 'by_customer');
4338
4480
  if (revenueByCustomerTime) {
4481
+ var customerLimit = resolveAssistantRevenueByTimePipelineLimit(revenueByCustomerTime, 'by_customer');
4339
4482
  return {
4340
4483
  type: 'aggregate',
4341
4484
  payload: {
4342
4485
  collection: 'invoices',
4343
4486
  permissionView: '/invoice/list',
4344
- pipeline: buildAssistantInvoiceRevenueByTimePipeline(revenueByCustomerTime, 'by_customer')
4487
+ pipeline: buildAssistantInvoiceRevenueByTimePipeline(revenueByCustomerTime, 'by_customer'),
4488
+ options: {
4489
+ allowDiskUse: true,
4490
+ export: true,
4491
+ limit: customerLimit
4492
+ }
4345
4493
  },
4346
4494
  cleaned: '',
4347
4495
  rawLine: "HEURISTIC_AGG(invoice-revenue-time-customer-".concat(revenueByCustomerTime.grain, ")")
@@ -4513,7 +4661,7 @@ function buildAssistantHeuristicDirective(message, collectionHints) {
4513
4661
  pipeline: [
4514
4662
  {
4515
4663
  $addFields: {
4516
- effective_date: { $ifNull: ['$date_paid', '$date_invoiced', '$createdAt'] },
4664
+ effective_date: { $ifNull: ['$date_paid', { $ifNull: ['$date_invoiced', '$createdAt'] }] },
4517
4665
  effective_total: { $ifNull: ['$paid_total', '$grand_total'] }
4518
4666
  }
4519
4667
  },
@@ -4527,7 +4675,7 @@ function buildAssistantHeuristicDirective(message, collectionHints) {
4527
4675
  },
4528
4676
  {
4529
4677
  $group: {
4530
- _id: { $ifNull: ['$customer', { $ifNull: ['$id_customer', 'Unknown'] }] },
4678
+ _id: buildAssistantInvoiceCustomerLabelExpr(),
4531
4679
  invoice_total: { $sum: { $ifNull: ['$effective_total', 0] } },
4532
4680
  invoice_count: { $sum: 1 }
4533
4681
  }
@@ -5284,18 +5432,20 @@ function buildAssistantToolResultPayload(directive, toolResponse, requestMessage
5284
5432
  };
5285
5433
  }
5286
5434
  function resolveAssistantToolResultResponseMaxRows(directive, directivePayload, rowCount) {
5287
- var _a;
5435
+ var _a, _b;
5288
5436
  if (directive.type !== 'aggregate') {
5289
5437
  return AI_ASSISTANT_DISPLAY_PREVIEW_MAX_ROWS;
5290
5438
  }
5291
- var requestedLimit = typeof ((_a = directivePayload === null || directivePayload === void 0 ? void 0 : directivePayload.options) === null || _a === void 0 ? void 0 : _a.limit) === 'number'
5292
- ? Math.min(Math.max((0, common_1.round)(directivePayload.options.limit), 0), AI_ASSISTANT_MONGO_MAX_LIMIT)
5439
+ var exportMode = ((_a = directivePayload === null || directivePayload === void 0 ? void 0 : directivePayload.options) === null || _a === void 0 ? void 0 : _a.export) === true;
5440
+ var maxRows = exportMode ? AI_ASSISTANT_MONGO_EXPORT_MAX_LIMIT : AI_ASSISTANT_MONGO_MAX_LIMIT;
5441
+ var requestedLimit = typeof ((_b = directivePayload === null || directivePayload === void 0 ? void 0 : directivePayload.options) === null || _b === void 0 ? void 0 : _b.limit) === 'number'
5442
+ ? Math.min(Math.max((0, common_1.round)(directivePayload.options.limit), 0), maxRows)
5293
5443
  : 0;
5294
5444
  if (requestedLimit > 0) {
5295
5445
  return requestedLimit;
5296
5446
  }
5297
5447
  if (typeof rowCount === 'number' && rowCount > 0) {
5298
- return Math.min(rowCount, AI_ASSISTANT_MONGO_MAX_LIMIT);
5448
+ return Math.min(rowCount, maxRows);
5299
5449
  }
5300
5450
  return AI_ASSISTANT_DISPLAY_PREVIEW_MAX_ROWS;
5301
5451
  }
@@ -7614,20 +7764,26 @@ function isAssistantMarkdownTableRowLine(line) {
7614
7764
  return /^\|.*\|$/.test(trimmed);
7615
7765
  }
7616
7766
  function ensureAssistantMinimumDisplayColumns(display) {
7767
+ var _a;
7617
7768
  if (!display || !Array.isArray(display.columns) || display.columns.length !== 1) {
7618
7769
  return display;
7619
7770
  }
7620
7771
  var primary = display.columns[0] || 'Result';
7621
- var rows = Array.isArray(display.rows)
7622
- ? display.rows.map(function (row) {
7623
- var next = __assign({}, (row || {}));
7624
- if (!Object.prototype.hasOwnProperty.call(next, 'Details')) {
7625
- next.Details = '';
7626
- }
7627
- return next;
7628
- })
7629
- : [];
7630
- return __assign(__assign({}, display), { columns: [primary, 'Details'], rows: rows });
7772
+ var rows = Array.isArray(display.rows) ? display.rows : [];
7773
+ if (!rows.length) {
7774
+ return display;
7775
+ }
7776
+ var labels = rows
7777
+ .map(function (row) { return normalizeOptionalString((row || {})[primary]) || 'Unknown'; })
7778
+ .filter(Boolean);
7779
+ var uniqueLabels = Array.from(new Set(labels));
7780
+ if (uniqueLabels.length !== 1) {
7781
+ return display;
7782
+ }
7783
+ var totalCount = typeof display.rowCount === 'number' && display.rowCount > 0
7784
+ ? display.rowCount
7785
+ : rows.length;
7786
+ return __assign(__assign({}, display), { columns: [primary, 'Count'], rows: [(_a = {}, _a[primary] = uniqueLabels[0], _a.Count = totalCount, _a)], rowCount: 1, truncated: false });
7631
7787
  }
7632
7788
  function applyAssistantDisplayTableToResponse(value, display) {
7633
7789
  if (!display || !Array.isArray(display.rows)) {
@@ -7636,14 +7792,24 @@ function applyAssistantDisplayTableToResponse(value, display) {
7636
7792
  var normalizedDisplay = ensureAssistantMinimumDisplayColumns(display);
7637
7793
  if (!display.rows.length) {
7638
7794
  var cleaned_1 = stripAssistantMarkdownTables(value);
7639
- var tableDisplay = Array.isArray(normalizedDisplay.columns) && normalizedDisplay.columns.length
7640
- ? __assign(__assign({}, normalizedDisplay), { rows: [] }) : {
7641
- columns: ['Result', 'Details'],
7642
- rows: [{ Result: 'No matching rows', Details: '' }],
7643
- rowCount: normalizedDisplay.rowCount || 0,
7644
- truncated: false,
7645
- includeIds: false
7646
- };
7795
+ var rowCount = typeof normalizedDisplay.rowCount === 'number' && normalizedDisplay.rowCount > 0
7796
+ ? normalizedDisplay.rowCount
7797
+ : 0;
7798
+ var tableDisplay = rowCount > 0
7799
+ ? {
7800
+ columns: ['Metric', 'Value'],
7801
+ rows: [{ Metric: 'Rows matched', Value: rowCount }],
7802
+ rowCount: 1,
7803
+ truncated: false,
7804
+ includeIds: false
7805
+ }
7806
+ : {
7807
+ columns: ['Result', 'Details'],
7808
+ rows: [{ Result: 'No matching rows', Details: '' }],
7809
+ rowCount: 0,
7810
+ truncated: false,
7811
+ includeIds: false
7812
+ };
7647
7813
  var emptyTable = formatDisplayTableMarkdown(tableDisplay);
7648
7814
  if (!emptyTable) {
7649
7815
  return cleaned_1 || value;
@@ -7750,6 +7916,15 @@ function resolveAssistantDatabaseName(database, mongoConfig) {
7750
7916
  }
7751
7917
  return dbName;
7752
7918
  }
7919
+ function resolveAssistantReadDisplayMaxRows(limit, rowCount) {
7920
+ if (typeof limit === 'number' && Number.isFinite(limit) && limit > 0) {
7921
+ return Math.max((0, common_1.round)(limit), 1);
7922
+ }
7923
+ if (typeof rowCount === 'number' && Number.isFinite(rowCount) && rowCount > 0) {
7924
+ return Math.min(Math.max((0, common_1.round)(rowCount), 1), AI_ASSISTANT_DISPLAY_PREVIEW_MAX_ROWS);
7925
+ }
7926
+ return AI_ASSISTANT_DISPLAY_PREVIEW_MAX_ROWS;
7927
+ }
7753
7928
  function normalizeAssistantFindOptions(options) {
7754
7929
  var normalized = options || {};
7755
7930
  var exportMode = normalized.export === true;
@@ -9924,6 +10099,67 @@ function isDateCondition(value) {
9924
10099
  }
9925
10100
  return false;
9926
10101
  }
10102
+ function isAssistantActiveFieldPath(field) {
10103
+ var normalized = normalizeOptionalString(field).toLowerCase();
10104
+ if (!normalized) {
10105
+ return false;
10106
+ }
10107
+ var leaf = normalized.split('.').pop() || normalized;
10108
+ return ['status', 'state', 'active', 'is_active', 'isactive', 'enabled', 'is_enabled', 'isenabled'].includes(leaf);
10109
+ }
10110
+ function isAssistantActiveCondition(value) {
10111
+ if (typeof value === 'boolean') {
10112
+ return value === true;
10113
+ }
10114
+ if (typeof value === 'string') {
10115
+ return /^active$/i.test(value.trim());
10116
+ }
10117
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
10118
+ return false;
10119
+ }
10120
+ var regexValue = value.$regex;
10121
+ if (regexValue instanceof RegExp) {
10122
+ return /active/i.test(regexValue.source);
10123
+ }
10124
+ if (typeof regexValue === 'string' && /active/i.test(regexValue)) {
10125
+ return true;
10126
+ }
10127
+ var eqValue = value.$eq;
10128
+ if (typeof eqValue === 'boolean' && eqValue === true) {
10129
+ return true;
10130
+ }
10131
+ if (typeof eqValue === 'string' && /^active$/i.test(eqValue.trim())) {
10132
+ return true;
10133
+ }
10134
+ var inValues = Array.isArray(value.$in) ? value.$in : [];
10135
+ if (inValues.some(function (entry) { return (typeof entry === 'boolean' && entry === true)
10136
+ || (typeof entry === 'string' && /^active$/i.test(entry.trim())); })) {
10137
+ return true;
10138
+ }
10139
+ return false;
10140
+ }
10141
+ function collectAssistantActiveMatchFields(query) {
10142
+ var fields = collectMatchFieldsByCondition(query, function (field, condition) { return isAssistantActiveFieldPath(field) && isAssistantActiveCondition(condition); });
10143
+ return Array.from(new Set(fields));
10144
+ }
10145
+ function resolveReadActiveStatusFallback(query, probeDocs) {
10146
+ var fields = collectAssistantActiveMatchFields(query);
10147
+ if (!fields.length || !Array.isArray(probeDocs) || !probeDocs.length) {
10148
+ return null;
10149
+ }
10150
+ var hasAnyFieldData = fields.some(function (field) { return hasNonEmptyValue(probeDocs, field, { treatObjectLikeAsEmpty: true }); });
10151
+ if (hasAnyFieldData) {
10152
+ return null;
10153
+ }
10154
+ var stripped = stripQueryFieldPathsDeepWithMeta(query, fields);
10155
+ if (!stripped.changed || !stripped.value || typeof stripped.value !== 'object') {
10156
+ return null;
10157
+ }
10158
+ return {
10159
+ query: stripped.value,
10160
+ fields: fields
10161
+ };
10162
+ }
9927
10163
  function isChemicalFieldPath(field) {
9928
10164
  var normalized = normalizeOptionalString(field).toLowerCase();
9929
10165
  return normalized.includes('chemical');
@@ -11172,6 +11408,10 @@ function resolveAssistantDefaultCollectionHints(message) {
11172
11408
  if (/\bcustomers?\b/.test(text)) {
11173
11409
  push('customers');
11174
11410
  }
11411
+ if (/\bclients?\b/.test(text)) {
11412
+ push('customers');
11413
+ push('clients');
11414
+ }
11175
11415
  return hints;
11176
11416
  }
11177
11417
  function buildCollectionRankingDebugFromTokens(tokens, collectionNames, max) {
@@ -11342,6 +11582,36 @@ function pickPreferredCollectionCandidate(ranked) {
11342
11582
  }
11343
11583
  return top;
11344
11584
  }
11585
+ function normalizeAssistantCollectionOverrideName(value) {
11586
+ var normalized = normalizeOptionalString(value).toLowerCase();
11587
+ if (!normalized) {
11588
+ return '';
11589
+ }
11590
+ var withoutReportPrefix = normalized.startsWith('report-')
11591
+ ? normalized.slice('report-'.length)
11592
+ : normalized;
11593
+ return stripVersionSuffix(withoutReportPrefix);
11594
+ }
11595
+ function isAssistantGenericCollectionName(value) {
11596
+ var normalized = normalizeAssistantCollectionOverrideName(value);
11597
+ if (!normalized) {
11598
+ return false;
11599
+ }
11600
+ return !normalized.includes('-') && !normalized.includes('_');
11601
+ }
11602
+ function isAssistantCollectionRefinementOf(currentCollection, genericCollection) {
11603
+ var current = normalizeAssistantCollectionOverrideName(currentCollection);
11604
+ var generic = normalizeAssistantCollectionOverrideName(genericCollection);
11605
+ if (!current || !generic || current === generic) {
11606
+ return false;
11607
+ }
11608
+ return current.startsWith("".concat(generic, "-"))
11609
+ || current.endsWith("-".concat(generic))
11610
+ || current.includes("-".concat(generic, "-"))
11611
+ || current.startsWith("".concat(generic, "_"))
11612
+ || current.endsWith("_".concat(generic))
11613
+ || current.includes("_".concat(generic, "_"));
11614
+ }
11345
11615
  function resolveAssistantCollectionOverride(collectionRanking, currentCollection) {
11346
11616
  var _a, _b;
11347
11617
  var ranked = Array.isArray(collectionRanking === null || collectionRanking === void 0 ? void 0 : collectionRanking.ranked) ? collectionRanking === null || collectionRanking === void 0 ? void 0 : collectionRanking.ranked : [];
@@ -11366,6 +11636,11 @@ function resolveAssistantCollectionOverride(collectionRanking, currentCollection
11366
11636
  return null;
11367
11637
  }
11368
11638
  var currentScore = (_b = (_a = ranked.find(function (entry) { return entry.name === current; })) === null || _a === void 0 ? void 0 : _a.score) !== null && _b !== void 0 ? _b : 0;
11639
+ if (currentScore >= AI_ASSISTANT_COLLECTION_OVERRIDE_MIN_SCORE
11640
+ && isAssistantGenericCollectionName(top.name)
11641
+ && isAssistantCollectionRefinementOf(current, top.name)) {
11642
+ return null;
11643
+ }
11369
11644
  var scoreGap = top.score - currentScore;
11370
11645
  var currentIsVersion = isVersionCollectionName(current);
11371
11646
  var topIsVersion = isVersionCollectionName(top.name);
@@ -11442,7 +11717,10 @@ var AI_ASSISTANT_BRIDGE_COLLECTION_ALIASES = {
11442
11717
  reportchemicalblends: 'chemical-blends',
11443
11718
  blend: 'chemical-blends',
11444
11719
  blends: 'chemical-blends',
11445
- invoice: 'invoices'
11720
+ invoice: 'invoices',
11721
+ client: 'customers',
11722
+ clients: 'customers',
11723
+ customer: 'customers'
11446
11724
  };
11447
11725
  var AI_ASSISTANT_DIRECT_COLLECTION_FALLBACK_ALLOWLIST = new Set([
11448
11726
  'work-order-dynamics',
@@ -14374,6 +14652,44 @@ function normalizeAssistantRoutes(value) {
14374
14652
  return "".concat(canonical).concat(suffix);
14375
14653
  });
14376
14654
  }
14655
+ function stripAssistantEmptyMarkdownTableRows(value) {
14656
+ var lines = String(value || '').split('\n');
14657
+ var output = [];
14658
+ var index = 0;
14659
+ while (index < lines.length) {
14660
+ var header = String(lines[index] || '').trim();
14661
+ var separator = String(lines[index + 1] || '').trim();
14662
+ var isTableHeader = /^\|.+\|$/.test(header);
14663
+ var isTableSeparator = /^\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(separator);
14664
+ if (!isTableHeader || !isTableSeparator) {
14665
+ output.push(lines[index]);
14666
+ index += 1;
14667
+ continue;
14668
+ }
14669
+ var tableStart = output.length;
14670
+ output.push(lines[index]);
14671
+ output.push(lines[index + 1]);
14672
+ index += 2;
14673
+ var keptRows = 0;
14674
+ while (index < lines.length) {
14675
+ var line = String(lines[index] || '');
14676
+ if (!line.trim() || !line.includes('|')) {
14677
+ break;
14678
+ }
14679
+ var cells = line.split('|').map(function (cell) { return cell.trim(); }).filter(Boolean);
14680
+ var hasContent = cells.some(function (cell) { return cell !== '-' && cell !== '---'; });
14681
+ if (hasContent) {
14682
+ output.push(line);
14683
+ keptRows += 1;
14684
+ }
14685
+ index += 1;
14686
+ }
14687
+ if (keptRows === 0) {
14688
+ output.splice(tableStart, 2);
14689
+ }
14690
+ }
14691
+ return output.join('\n').replace(/\n{3,}/g, '\n\n').trim();
14692
+ }
14377
14693
  function sanitizeAssistantResponse(value) {
14378
14694
  var raw = normalizeOptionalString(value);
14379
14695
  if (!raw) {
@@ -14435,7 +14751,8 @@ function sanitizeAssistantResponse(value) {
14435
14751
  if (!cleaned) {
14436
14752
  return 'I can’t share code, but I can point you to files or explain behavior at a high level.';
14437
14753
  }
14438
- var normalizedCurrency = normalizeAssistantCurrencyText(cleaned);
14754
+ var tableCleaned = stripAssistantEmptyMarkdownTableRows(cleaned);
14755
+ var normalizedCurrency = normalizeAssistantCurrencyText(tableCleaned || cleaned);
14439
14756
  return normalizeAssistantRoutes(normalizedCurrency);
14440
14757
  }
14441
14758
  function evaluateAssistantGuardrails(message) {