@resolveio/server-lib 22.1.3 → 22.1.4

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.
@@ -120,11 +120,13 @@ exports.resolveAssistantReadDisplayMaxRows = resolveAssistantReadDisplayMaxRows;
120
120
  exports.normalizeAssistantNowExprPlaceholders = normalizeAssistantNowExprPlaceholders;
121
121
  exports.rewriteMatchExpressionsToExpr = rewriteMatchExpressionsToExpr;
122
122
  exports.normalizeAssistantMonthlyCalendarWindowPipeline = normalizeAssistantMonthlyCalendarWindowPipeline;
123
+ exports.normalizeAssistantAggregatePipeline = normalizeAssistantAggregatePipeline;
123
124
  exports.stripQueryFieldPathsDeep = stripQueryFieldPathsDeep;
124
125
  exports.stripScopedFieldsFromPipeline = stripScopedFieldsFromPipeline;
125
126
  exports.rewriteEmbeddedMatchObjects = rewriteEmbeddedMatchObjects;
126
127
  exports.resolveAssistantCollectionOverride = resolveAssistantCollectionOverride;
127
128
  exports.resolveAssistantCrossCollectionFallbackCandidates = resolveAssistantCrossCollectionFallbackCandidates;
129
+ exports.resolveAssistantAvailableCrossCollectionFallbacksFromNames = resolveAssistantAvailableCrossCollectionFallbacksFromNames;
128
130
  exports.collectUserViewPermissions = collectUserViewPermissions;
129
131
  exports.userHasInvoiceAccess = userHasInvoiceAccess;
130
132
  exports.resolveAssistantUserAccessTier = resolveAssistantUserAccessTier;
@@ -2533,7 +2535,7 @@ function executeAiAssistantReportIssue(payload, context) {
2533
2535
  }
2534
2536
  function executeAiAssistantMongoRead(payload, context) {
2535
2537
  return __awaiter(this, void 0, void 0, function () {
2536
- var input, rawCollection, retryState, triedCollections, crossCollectionRetryEnabled, dbName, db, collectionResolution, collection, bridgeCollection, retryRootCollection, 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, crossCollectionCandidates, crossCollectionCandidates_1, crossCollectionCandidates_1_1, candidateCollection, fallbackPayload, fallbackResult, existingFallbacks, e_1_1, 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;
2538
+ var input, rawCollection, retryState, triedCollections, crossCollectionRetryEnabled, dbName, db, collectionResolution, collection, bridgeCollection, retryRootCollection, schemaFields, effectivePermissionView, _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, crossCollectionCandidates, crossCollectionCandidates_1, crossCollectionCandidates_1_1, candidateCollection, fallbackPayload, fallbackResult, existingFallbacks, e_1_1, 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;
2537
2539
  var e_1, _p;
2538
2540
  var _q, _r;
2539
2541
  return __generator(this, function (_s) {
@@ -2565,7 +2567,10 @@ function executeAiAssistantMongoRead(payload, context) {
2565
2567
  addAssistantCollectionToTriedSet(triedCollections, collection);
2566
2568
  retryRootCollection = normalizeOptionalString(retryState.rootCollection) || collection;
2567
2569
  schemaFields = getCollectionSchemaFieldNames(collection);
2568
- return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
2570
+ effectivePermissionView = bridgeCollection.fallbackFrom
2571
+ ? resolveDefaultAssistantPermissionView(collection)
2572
+ : input.permissionView;
2573
+ return [4 /*yield*/, ensureAssistantReadAccess(context, effectivePermissionView, collection)];
2569
2574
  case 3:
2570
2575
  _a = _s.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
2571
2576
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
@@ -2579,6 +2584,11 @@ function executeAiAssistantMongoRead(payload, context) {
2579
2584
  to: collection,
2580
2585
  used: true
2581
2586
  };
2587
+ fallbackMeta.permissionFallback = {
2588
+ from: normalizeOptionalString(input.permissionView),
2589
+ to: effectivePermissionView,
2590
+ used: true
2591
+ };
2582
2592
  }
2583
2593
  baseQuery = normalizeMongoQuery(input.query);
2584
2594
  if (!isSuperAdmin && customerId) {
@@ -3117,7 +3127,7 @@ function executeAiAssistantMongoRead(payload, context) {
3117
3127
  }
3118
3128
  function executeAiAssistantMongoAggregate(payload, context) {
3119
3129
  return __awaiter(this, void 0, void 0, function () {
3120
- var input, rawCollection, retryState, triedCollections, crossCollectionRetryEnabled, dbName, db, collectionResolution, collection, bridgeCollection, retryRootCollection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, sanitizedPipeline, strippedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, executedPipeline, dateField, aggregateOptions, runAggregateWithRepair, initialAggregate, documents, probeDocs, fallback, fallbackPipeline, fallbackAggregate, fallbackDocs, createdFallback, createdPipeline, createdAggregate, createdDocs, expanded, expandedAggregate, expandedDocs, completionFallback, fallbackPipeline, fallbackAggregate, fallbackDocs, completionExprFallback, fallbackPipeline, fallbackAggregate, fallbackDocs, unwindFallback, shouldUnwind, _c, _d, fallbackPipeline, fallbackAggregate, fallbackDocs, nameFallback, fallbackPipeline, fallbackAggregate, fallbackDocs, _e, _loop_1, i, state_1, matchFields_1, _f, aliases, rewrittenPipeline, fallbackAggregate, fallbackDocs, _loop_2, i, state_2, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, crossCollectionCandidates, crossCollectionCandidates_2, crossCollectionCandidates_2_1, candidateCollection, fallbackPayload, fallbackResult, existingFallbacks, e_2_1, matchStages, diagnostics, combinedMatch, nameFields, dateFields, queryNoName, _g, queryNoDate, _h, _j, _k, _l, allCollections, base, alt, altCount, _m, verification, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
3130
+ var input, rawCollection, retryState, triedCollections, crossCollectionRetryEnabled, dbName, db, collectionResolution, collection, bridgeCollection, retryRootCollection, schemaFields, effectivePermissionView, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, sanitizedPipeline, strippedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, executedPipeline, dateField, aggregateOptions, runAggregateWithRepair, initialAggregate, documents, probeDocs, fallback, fallbackPipeline, fallbackAggregate, fallbackDocs, createdFallback, createdPipeline, createdAggregate, createdDocs, expanded, expandedAggregate, expandedDocs, completionFallback, fallbackPipeline, fallbackAggregate, fallbackDocs, completionExprFallback, fallbackPipeline, fallbackAggregate, fallbackDocs, unwindFallback, shouldUnwind, _c, _d, fallbackPipeline, fallbackAggregate, fallbackDocs, nameFallback, fallbackPipeline, fallbackAggregate, fallbackDocs, _e, _loop_1, i, state_1, matchFields_1, _f, aliases, rewrittenPipeline, fallbackAggregate, fallbackDocs, _loop_2, i, state_2, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, crossCollectionCandidates, crossCollectionCandidates_2, crossCollectionCandidates_2_1, candidateCollection, fallbackPayload, fallbackResult, existingFallbacks, e_2_1, matchStages, diagnostics, combinedMatch, nameFields, dateFields, queryNoName, _g, queryNoDate, _h, _j, _k, _l, allCollections, base, alt, altCount, _m, verification, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
3121
3131
  var e_2, _o;
3122
3132
  var _this = this;
3123
3133
  var _p, _q;
@@ -3150,7 +3160,10 @@ function executeAiAssistantMongoAggregate(payload, context) {
3150
3160
  addAssistantCollectionToTriedSet(triedCollections, collection);
3151
3161
  retryRootCollection = normalizeOptionalString(retryState.rootCollection) || collection;
3152
3162
  schemaFields = getCollectionSchemaFieldNames(collection);
3153
- return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
3163
+ effectivePermissionView = bridgeCollection.fallbackFrom
3164
+ ? resolveDefaultAssistantPermissionView(collection)
3165
+ : input.permissionView;
3166
+ return [4 /*yield*/, ensureAssistantReadAccess(context, effectivePermissionView, collection)];
3154
3167
  case 3:
3155
3168
  _a = _r.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
3156
3169
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
@@ -3164,6 +3177,11 @@ function executeAiAssistantMongoAggregate(payload, context) {
3164
3177
  to: collection,
3165
3178
  used: true
3166
3179
  };
3180
+ fallbackMeta.permissionFallback = {
3181
+ from: normalizeOptionalString(input.permissionView),
3182
+ to: effectivePermissionView,
3183
+ used: true
3184
+ };
3167
3185
  }
3168
3186
  baseQuery = normalizeMongoQuery(input.query);
3169
3187
  if (!isSuperAdmin && customerId) {
@@ -3220,7 +3238,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
3220
3238
  }
3221
3239
  aggregateOptions = __assign(__assign({}, normalizedOptions.aggregateOptions), { readPreference: AI_ASSISTANT_READ_PREFERENCE });
3222
3240
  runAggregateWithRepair = function (pipeline, stage) { return __awaiter(_this, void 0, void 0, function () {
3223
- var docs, error_5, repaired, docs;
3241
+ var docs, error_5, isDateRepair, isRankSortByRepair, repaired, docs;
3224
3242
  return __generator(this, function (_a) {
3225
3243
  switch (_a.label) {
3226
3244
  case 0:
@@ -3233,10 +3251,14 @@ function executeAiAssistantMongoAggregate(payload, context) {
3233
3251
  return [2 /*return*/, { documents: docs, pipeline: pipeline }];
3234
3252
  case 2:
3235
3253
  error_5 = _a.sent();
3236
- if (!isAssistantDateArithmeticArgumentError(error_5)) {
3254
+ isDateRepair = isAssistantDateArithmeticArgumentError(error_5);
3255
+ isRankSortByRepair = isAssistantRankSortByError(error_5);
3256
+ if (!isDateRepair && !isRankSortByRepair) {
3237
3257
  throw error_5;
3238
3258
  }
3239
- repaired = repairAssistantDateArithmeticInPipeline(pipeline);
3259
+ repaired = isDateRepair
3260
+ ? repairAssistantDateArithmeticInPipeline(pipeline)
3261
+ : repairAssistantRankSortByInPipeline(pipeline);
3240
3262
  if (!repaired.changed || containsForbiddenMongoOperators(repaired.pipeline)) {
3241
3263
  throw error_5;
3242
3264
  }
@@ -3245,12 +3267,22 @@ function executeAiAssistantMongoAggregate(payload, context) {
3245
3267
  .toArray()];
3246
3268
  case 3:
3247
3269
  docs = _a.sent();
3248
- fallbackMeta.dateArithmetic = {
3249
- attempted: true,
3250
- used: true,
3251
- stage: stage,
3252
- reason: 'normalized_date_operator_args'
3253
- };
3270
+ if (isDateRepair) {
3271
+ fallbackMeta.dateArithmetic = {
3272
+ attempted: true,
3273
+ used: true,
3274
+ stage: stage,
3275
+ reason: 'normalized_date_operator_args'
3276
+ };
3277
+ }
3278
+ if (isRankSortByRepair) {
3279
+ fallbackMeta.windowRankSortBy = {
3280
+ attempted: true,
3281
+ used: true,
3282
+ stage: stage,
3283
+ reason: 'normalized_rank_sortby_single_key'
3284
+ };
3285
+ }
3254
3286
  return [2 /*return*/, { documents: docs, pipeline: repaired.pipeline }];
3255
3287
  case 4: return [2 /*return*/];
3256
3288
  }
@@ -4782,10 +4814,14 @@ function isAssistantOperationalHeuristicDirective(directive) {
4782
4814
  return rawLine.includes('heuristic_agg(work-order-status)')
4783
4815
  || rawLine.includes('heuristic_agg(work-order-completed-per-day)')
4784
4816
  || rawLine.includes('heuristic_agg(work-order-top-customers)')
4817
+ || rawLine.includes('heuristic_agg(work-order-jobs-top-volume)')
4785
4818
  || rawLine.includes('heuristic_agg(blend-last10-summary)')
4786
4819
  || rawLine.includes('heuristic_agg(blend-throughput-by-day)')
4787
4820
  || rawLine.includes('heuristic_agg(deliveries-per-driver-last-month)')
4788
- || rawLine.includes('heuristic_agg(last-deliveries)');
4821
+ || rawLine.includes('heuristic_agg(deliveries-per-driver-last-30d-top10)')
4822
+ || rawLine.includes('heuristic_agg(last-deliveries)')
4823
+ || rawLine.includes('heuristic_agg(invoice-missing-invoiced-date-created-this-month)')
4824
+ || rawLine.includes('heuristic_agg(support-ticket-billable-hours-user-month-last-6m)');
4789
4825
  }
4790
4826
  function isAssistantDeterministicHeuristicDirective(directive) {
4791
4827
  return isAssistantRevenueByTimeHeuristicDirective(directive)
@@ -5112,6 +5148,76 @@ function buildAssistantHeuristicDirective(message, collectionHints) {
5112
5148
  rawLine: 'HEURISTIC_AGG(deliveries-per-driver-last-month)'
5113
5149
  };
5114
5150
  }
5151
+ if (/\bdeliver(?:y|ies)\b/.test(text)
5152
+ && /\bdrivers?\b/.test(text)
5153
+ && /\b(last|past)\s+30\s+days?\b/.test(text)
5154
+ && /\btop\s+10\b/.test(text)) {
5155
+ return {
5156
+ type: 'aggregate',
5157
+ payload: {
5158
+ collection: 'production-deliveries',
5159
+ permissionView: '/dashboard/driver',
5160
+ pipeline: [
5161
+ {
5162
+ $addFields: {
5163
+ effective_date: { $ifNull: ['$date', { $ifNull: ['$date_created', '$createdAt'] }] },
5164
+ driver_label: buildAssistantTrimmedStringExpr({
5165
+ $ifNull: [
5166
+ '$driver',
5167
+ {
5168
+ $ifNull: [
5169
+ '$driver_name',
5170
+ {
5171
+ $ifNull: [
5172
+ '$driver.fullname',
5173
+ {
5174
+ $ifNull: [
5175
+ '$driver.name',
5176
+ {
5177
+ $ifNull: [
5178
+ { $toString: '$id_driver' },
5179
+ 'Unknown Driver'
5180
+ ]
5181
+ }
5182
+ ]
5183
+ }
5184
+ ]
5185
+ }
5186
+ ]
5187
+ }
5188
+ ]
5189
+ })
5190
+ }
5191
+ },
5192
+ {
5193
+ $match: {
5194
+ effective_date: {
5195
+ $gte: { $dateSubtract: { startDate: '$$NOW', unit: 'day', amount: 30 } },
5196
+ $lt: '$$NOW'
5197
+ }
5198
+ }
5199
+ },
5200
+ {
5201
+ $group: {
5202
+ _id: '$driver_label',
5203
+ delivery_count: { $sum: 1 }
5204
+ }
5205
+ },
5206
+ { $sort: { delivery_count: -1, _id: 1 } },
5207
+ { $limit: 10 },
5208
+ {
5209
+ $project: {
5210
+ _id: 0,
5211
+ driver: '$_id',
5212
+ delivery_count: 1
5213
+ }
5214
+ }
5215
+ ]
5216
+ },
5217
+ cleaned: '',
5218
+ rawLine: 'HEURISTIC_AGG(deliveries-per-driver-last-30d-top10)'
5219
+ };
5220
+ }
5115
5221
  if (/(which\s+blends?|blends?\s+used).*(red\s+ultra\s+lift|chemical\s+red\s+ultra\s+lift)/.test(text)
5116
5222
  && /(last|past)\s+30\s+days/.test(text)) {
5117
5223
  return {
@@ -5258,6 +5364,196 @@ function buildAssistantHeuristicDirective(message, collectionHints) {
5258
5364
  rawLine: 'HEURISTIC_AGG(invoice-top-customers)'
5259
5365
  };
5260
5366
  }
5367
+ if (/\binvoices?\b/.test(text)
5368
+ && /(\bmissing\b|\bwithout\b|\bno\b)/.test(text)
5369
+ && /(\binvoic(?:ed|e)\s+date\b|\bdate[\s_-]*invoic(?:ed|e)\b)/.test(text)
5370
+ && /\bthis\s+month\b/.test(text)) {
5371
+ var thisMonthStart = { $dateTrunc: { date: '$$NOW', unit: 'month' } };
5372
+ return {
5373
+ type: 'aggregate',
5374
+ payload: {
5375
+ collection: 'invoices',
5376
+ permissionView: '/invoice/list',
5377
+ pipeline: [
5378
+ {
5379
+ $addFields: {
5380
+ created_date: { $ifNull: ['$createdAt', { $ifNull: ['$date_created', '$date'] }] },
5381
+ invoiced_date: { $ifNull: ['$date_invoiced', '$date_invoice'] }
5382
+ }
5383
+ },
5384
+ {
5385
+ $match: {
5386
+ created_date: {
5387
+ $gte: thisMonthStart,
5388
+ $lt: '$$NOW'
5389
+ }
5390
+ }
5391
+ },
5392
+ {
5393
+ $match: {
5394
+ $expr: {
5395
+ $or: [
5396
+ { $eq: [{ $type: '$invoiced_date' }, 'missing'] },
5397
+ { $eq: ['$invoiced_date', null] },
5398
+ {
5399
+ $and: [
5400
+ { $eq: [{ $type: '$invoiced_date' }, 'string'] },
5401
+ { $eq: [{ $trim: { input: '$invoiced_date' } }, ''] }
5402
+ ]
5403
+ }
5404
+ ]
5405
+ }
5406
+ }
5407
+ },
5408
+ {
5409
+ $project: {
5410
+ _id: 0,
5411
+ invoice_number: { $ifNull: ['$invoice_number_string', '$invoice_number'] },
5412
+ customer: buildAssistantInvoiceCustomerLabelExpr(),
5413
+ created_date: 1,
5414
+ due_date: '$date_due',
5415
+ sub_total: { $ifNull: ['$sub_total', '$subtotal'] },
5416
+ total: { $ifNull: ['$grand_total', '$paid_total'] }
5417
+ }
5418
+ },
5419
+ { $sort: { created_date: -1, invoice_number: 1 } },
5420
+ { $limit: 200 }
5421
+ ],
5422
+ options: {
5423
+ allowDiskUse: true,
5424
+ export: true,
5425
+ limit: 200
5426
+ }
5427
+ },
5428
+ cleaned: '',
5429
+ rawLine: 'HEURISTIC_AGG(invoice-missing-invoiced-date-created-this-month)'
5430
+ };
5431
+ }
5432
+ if (/\bsupport[\s-]*tickets?\b/.test(text)
5433
+ && /\b(hours?|billable)\b/.test(text)
5434
+ && /\b(last|past)\s+6\s+months?\b/.test(text)
5435
+ && /(\b(per|by|each)\s+user\b|\buser\b)/.test(text)
5436
+ && /(\b(per|by|each)\s+month\b|\bmonth\b)/.test(text)) {
5437
+ return {
5438
+ type: 'aggregate',
5439
+ payload: {
5440
+ collection: 'support-tickets',
5441
+ permissionView: '/support-ticket/list',
5442
+ pipeline: [
5443
+ {
5444
+ $addFields: {
5445
+ effective_date: { $ifNull: ['$date', { $ifNull: ['$date_created', { $ifNull: ['$createdAt', '$updatedAt'] }] }] },
5446
+ billable_hours_value: {
5447
+ $convert: {
5448
+ input: {
5449
+ $ifNull: [
5450
+ '$hours_billed',
5451
+ {
5452
+ $ifNull: [
5453
+ '$billable_hours',
5454
+ {
5455
+ $ifNull: [
5456
+ '$hours',
5457
+ {
5458
+ $ifNull: [
5459
+ '$total_hours',
5460
+ { $ifNull: ['$time.hours', { $ifNull: ['$billing.hours', 0] }] }
5461
+ ]
5462
+ }
5463
+ ]
5464
+ }
5465
+ ]
5466
+ }
5467
+ ]
5468
+ },
5469
+ to: 'double',
5470
+ onError: 0,
5471
+ onNull: 0
5472
+ }
5473
+ },
5474
+ user_label: buildAssistantTrimmedStringExpr({
5475
+ $ifNull: [
5476
+ '$user.fullname',
5477
+ {
5478
+ $ifNull: [
5479
+ '$user.name',
5480
+ {
5481
+ $ifNull: [
5482
+ '$employee.fullname',
5483
+ {
5484
+ $ifNull: [
5485
+ '$employee.name',
5486
+ {
5487
+ $ifNull: [
5488
+ '$created.name',
5489
+ {
5490
+ $ifNull: [
5491
+ { $toString: '$id_user' },
5492
+ 'Unknown User'
5493
+ ]
5494
+ }
5495
+ ]
5496
+ }
5497
+ ]
5498
+ }
5499
+ ]
5500
+ }
5501
+ ]
5502
+ }
5503
+ ]
5504
+ })
5505
+ }
5506
+ },
5507
+ {
5508
+ $match: {
5509
+ effective_date: {
5510
+ $gte: { $dateSubtract: { startDate: '$$NOW', unit: 'month', amount: 6 } },
5511
+ $lt: '$$NOW'
5512
+ }
5513
+ }
5514
+ },
5515
+ {
5516
+ $group: {
5517
+ _id: {
5518
+ user: '$user_label',
5519
+ bucket: {
5520
+ $dateTrunc: {
5521
+ date: '$effective_date',
5522
+ unit: 'month'
5523
+ }
5524
+ }
5525
+ },
5526
+ billable_hours: { $sum: '$billable_hours_value' },
5527
+ ticket_count: { $sum: 1 }
5528
+ }
5529
+ },
5530
+ {
5531
+ $project: {
5532
+ _id: 0,
5533
+ user: '$_id.user',
5534
+ month: {
5535
+ $dateToString: {
5536
+ format: '%Y-%m',
5537
+ date: '$_id.bucket'
5538
+ }
5539
+ },
5540
+ billable_hours: 1,
5541
+ ticket_count: 1
5542
+ }
5543
+ },
5544
+ { $sort: { user: 1, month: 1 } },
5545
+ { $limit: 400 }
5546
+ ],
5547
+ options: {
5548
+ allowDiskUse: true,
5549
+ export: true,
5550
+ limit: 400
5551
+ }
5552
+ },
5553
+ cleaned: '',
5554
+ rawLine: 'HEURISTIC_AGG(support-ticket-billable-hours-user-month-last-6m)'
5555
+ };
5556
+ }
5261
5557
  if (/(last\s+20).*(deliver(?:y|ies)).*(product).*(destination)/.test(text)) {
5262
5558
  return {
5263
5559
  type: 'aggregate',
@@ -5295,6 +5591,108 @@ function buildAssistantHeuristicDirective(message, collectionHints) {
5295
5591
  rawLine: 'HEURISTIC_AGG(last-deliveries)'
5296
5592
  };
5297
5593
  }
5594
+ if (/\bjobs?\b/.test(text)
5595
+ && /(\bhighest\b|\btop\b)/.test(text)
5596
+ && /\btreatment\s+volume\b/.test(text)
5597
+ && /\b(last|past)\s+90\s+days?\b/.test(text)) {
5598
+ return {
5599
+ type: 'aggregate',
5600
+ payload: {
5601
+ collection: 'work-order-dynamics',
5602
+ permissionView: '/work-order-dynamic/list',
5603
+ pipeline: [
5604
+ {
5605
+ $addFields: {
5606
+ effective_date: { $ifNull: ['$date_completed', { $ifNull: ['$date_created', '$createdAt'] }] },
5607
+ treatment_volume_value: {
5608
+ $ifNull: [
5609
+ '$treatment_volume',
5610
+ {
5611
+ $ifNull: [
5612
+ '$total_treatment_volume',
5613
+ {
5614
+ $reduce: {
5615
+ input: { $ifNull: ['$chemicals', []] },
5616
+ initialValue: 0,
5617
+ in: {
5618
+ $add: [
5619
+ '$$value',
5620
+ {
5621
+ $ifNull: [
5622
+ '$$this.quantity',
5623
+ {
5624
+ $ifNull: [
5625
+ '$$this.volume',
5626
+ { $ifNull: ['$$this.delivered.quantity', 0] }
5627
+ ]
5628
+ }
5629
+ ]
5630
+ }
5631
+ ]
5632
+ }
5633
+ }
5634
+ }
5635
+ ]
5636
+ }
5637
+ ]
5638
+ }
5639
+ }
5640
+ },
5641
+ {
5642
+ $match: {
5643
+ effective_date: {
5644
+ $gte: { $dateSubtract: { startDate: '$$NOW', unit: 'day', amount: 90 } },
5645
+ $lt: '$$NOW'
5646
+ }
5647
+ }
5648
+ },
5649
+ {
5650
+ $group: {
5651
+ _id: {
5652
+ $ifNull: [
5653
+ '$job.name',
5654
+ {
5655
+ $ifNull: [
5656
+ '$job_name',
5657
+ { $ifNull: ['$job', { $ifNull: ['$job_number', 'Unknown Job'] }] }
5658
+ ]
5659
+ }
5660
+ ]
5661
+ },
5662
+ total_treatment_volume: {
5663
+ $sum: {
5664
+ $convert: {
5665
+ input: '$treatment_volume_value',
5666
+ to: 'double',
5667
+ onError: 0,
5668
+ onNull: 0
5669
+ }
5670
+ }
5671
+ },
5672
+ work_order_count: { $sum: 1 }
5673
+ }
5674
+ },
5675
+ { $sort: { total_treatment_volume: -1, work_order_count: -1, _id: 1 } },
5676
+ { $limit: 20 },
5677
+ {
5678
+ $project: {
5679
+ _id: 0,
5680
+ job: '$_id',
5681
+ total_treatment_volume: 1,
5682
+ work_order_count: 1
5683
+ }
5684
+ }
5685
+ ],
5686
+ options: {
5687
+ allowDiskUse: true,
5688
+ export: true,
5689
+ limit: 20
5690
+ }
5691
+ },
5692
+ cleaned: '',
5693
+ rawLine: 'HEURISTIC_AGG(work-order-jobs-top-volume)'
5694
+ };
5695
+ }
5298
5696
  var hintCollection = mergeAssistantHintValues(collectionHints, resolveAssistantDefaultCollectionHints(message))[0] || '';
5299
5697
  if (!hintCollection) {
5300
5698
  return null;
@@ -6275,7 +6673,7 @@ function resolveAssistantDatedReportWindow(toolResult) {
6275
6673
  return null;
6276
6674
  }
6277
6675
  function buildAssistantDebugPayload(params) {
6278
- 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, _5, _6;
6676
+ 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, _5, _6, _7;
6279
6677
  var notes = [];
6280
6678
  notes.push("Request classification: ".concat(params.requestType, " (").concat(params.requestTypeSource, ")."));
6281
6679
  if (params.dataQuestion) {
@@ -6356,7 +6754,10 @@ function buildAssistantDebugPayload(params) {
6356
6754
  notes.push("Expanded date fields: ".concat(fields, "."));
6357
6755
  }
6358
6756
  }
6359
- if ((_p = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.queryFieldAliases) === null || _p === void 0 ? void 0 : _p.used) {
6757
+ if ((_p = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.windowRankSortBy) === null || _p === void 0 ? void 0 : _p.used) {
6758
+ notes.push('Retried after normalizing window rank sortBy to a single key.');
6759
+ }
6760
+ if ((_q = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.queryFieldAliases) === null || _q === void 0 ? void 0 : _q.used) {
6360
6761
  var entries = fallbackInfo.queryFieldAliases.aliases
6361
6762
  ? Object.entries(fallbackInfo.queryFieldAliases.aliases)
6362
6763
  .map(function (_a) {
@@ -6369,7 +6770,7 @@ function buildAssistantDebugPayload(params) {
6369
6770
  notes.push("Rewrote query fields: ".concat(entries, "."));
6370
6771
  }
6371
6772
  }
6372
- if ((_q = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.projectionAliases) === null || _q === void 0 ? void 0 : _q.used) {
6773
+ if ((_r = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.projectionAliases) === null || _r === void 0 ? void 0 : _r.used) {
6373
6774
  var entries = fallbackInfo.projectionAliases.aliases
6374
6775
  ? Object.entries(fallbackInfo.projectionAliases.aliases)
6375
6776
  .map(function (_a) {
@@ -6382,45 +6783,45 @@ function buildAssistantDebugPayload(params) {
6382
6783
  notes.push("Expanded projection fields: ".concat(entries, "."));
6383
6784
  }
6384
6785
  }
6385
- if ((_r = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.unwind) === null || _r === void 0 ? void 0 : _r.used) {
6786
+ if ((_s = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.unwind) === null || _s === void 0 ? void 0 : _s.used) {
6386
6787
  notes.push("Applied unwind fallback on ".concat(fallbackInfo.unwind.path, "."));
6387
6788
  }
6388
- if ((_s = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.nameMatch) === null || _s === void 0 ? void 0 : _s.used) {
6789
+ if ((_t = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.nameMatch) === null || _t === void 0 ? void 0 : _t.used) {
6389
6790
  var fields = Array.isArray(fallbackInfo.nameMatch.fields)
6390
6791
  ? fallbackInfo.nameMatch.fields.join(', ')
6391
6792
  : fallbackInfo.nameMatch.field;
6392
6793
  notes.push("Expanded name match fields: ".concat(fields, "."));
6393
6794
  }
6394
- if ((_t = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.chemicalLookup) === null || _t === void 0 ? void 0 : _t.used) {
6795
+ if ((_u = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.chemicalLookup) === null || _u === void 0 ? void 0 : _u.used) {
6395
6796
  var collection = fallbackInfo.chemicalLookup.collection ? " in ".concat(fallbackInfo.chemicalLookup.collection) : '';
6396
6797
  notes.push("Applied chemical lookup".concat(collection, "."));
6397
6798
  }
6398
- if ((_u = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.reportBuilderBridge) === null || _u === void 0 ? void 0 : _u.used) {
6799
+ if ((_v = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.reportBuilderBridge) === null || _v === void 0 ? void 0 : _v.used) {
6399
6800
  var from = fallbackInfo.reportBuilderBridge.from || 'unknown';
6400
6801
  var to = fallbackInfo.reportBuilderBridge.to || 'unknown';
6401
6802
  notes.push("Report builder bridge collection: ".concat(from, " -> ").concat(to, "."));
6402
6803
  }
6403
- if ((_v = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.reportFallback) === null || _v === void 0 ? void 0 : _v.used) {
6804
+ if ((_w = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.reportFallback) === null || _w === void 0 ? void 0 : _w.used) {
6404
6805
  var from = fallbackInfo.reportFallback.from || 'report';
6405
6806
  var to = fallbackInfo.reportFallback.to || 'base';
6406
6807
  notes.push("Report fallback: ".concat(from, " -> ").concat(to, "."));
6407
6808
  }
6408
- if ((_w = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.collectionRetry) === null || _w === void 0 ? void 0 : _w.used) {
6809
+ if ((_x = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.collectionRetry) === null || _x === void 0 ? void 0 : _x.used) {
6409
6810
  var from = fallbackInfo.collectionRetry.from || 'unknown';
6410
6811
  var to = fallbackInfo.collectionRetry.to || 'unknown';
6411
6812
  notes.push("Cross-collection retry: ".concat(from, " -> ").concat(to, "."));
6412
6813
  }
6413
- else if (((_x = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.collectionRetry) === null || _x === void 0 ? void 0 : _x.attempted) && Array.isArray(fallbackInfo.collectionRetry.tried) && fallbackInfo.collectionRetry.tried.length) {
6814
+ else if (((_y = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.collectionRetry) === null || _y === void 0 ? void 0 : _y.attempted) && Array.isArray(fallbackInfo.collectionRetry.tried) && fallbackInfo.collectionRetry.tried.length) {
6414
6815
  notes.push("Cross-collection retry attempted: ".concat(fallbackInfo.collectionRetry.tried.join(', '), "."));
6415
6816
  }
6416
- if ((_y = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idLookup) === null || _y === void 0 ? void 0 : _y.used) {
6817
+ if ((_z = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idLookup) === null || _z === void 0 ? void 0 : _z.used) {
6417
6818
  var field = fallbackInfo.idLookup.field || 'id';
6418
6819
  var strategy = fallbackInfo.idLookup.strategy || 'lookup';
6419
6820
  var collection = fallbackInfo.idLookup.collection ? " in ".concat(fallbackInfo.idLookup.collection) : '';
6420
6821
  var detail = fallbackInfo.idLookup.nameField ? " via ".concat(fallbackInfo.idLookup.nameField) : '';
6421
6822
  notes.push("Resolved ".concat(field, " by ").concat(strategy).concat(collection).concat(detail, "."));
6422
6823
  }
6423
- if ((_z = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idDisplayLookup) === null || _z === void 0 ? void 0 : _z.used) {
6824
+ if ((_0 = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idDisplayLookup) === null || _0 === void 0 ? void 0 : _0.used) {
6424
6825
  var lookups = Array.isArray(fallbackInfo.idDisplayLookup.lookups)
6425
6826
  ? fallbackInfo.idDisplayLookup.lookups
6426
6827
  : [];
@@ -6431,12 +6832,18 @@ function buildAssistantDebugPayload(params) {
6431
6832
  notes.push(summary ? "Resolved id lookups for display: ".concat(summary, ".") : 'Resolved id lookups for display.');
6432
6833
  }
6433
6834
  if (params.toolError) {
6434
- var errorMessage = ((_0 = params.toolError) === null || _0 === void 0 ? void 0 : _0.message) || String(params.toolError || '');
6835
+ var errorMessage = ((_1 = params.toolError) === null || _1 === void 0 ? void 0 : _1.message) || String(params.toolError || '');
6435
6836
  if (errorMessage) {
6436
6837
  notes.push("Tool error: ".concat(errorMessage));
6437
6838
  }
6438
6839
  }
6439
6840
  var payload = {
6841
+ requestClassification: {
6842
+ type: params.requestType,
6843
+ source: params.requestTypeSource,
6844
+ plannerIntentType: params.plannerIntentType || undefined,
6845
+ dataQuestion: params.dataQuestion
6846
+ },
6440
6847
  decision: {
6441
6848
  requestType: params.requestType,
6442
6849
  requestTypeSource: params.requestTypeSource,
@@ -6459,13 +6866,13 @@ function buildAssistantDebugPayload(params) {
6459
6866
  collectionResolved: resolvedCollection || undefined,
6460
6867
  collectionMatched: matchedCollection,
6461
6868
  collectionCandidates: candidateCollections.length ? candidateCollections : undefined,
6462
- collectionScore: typeof ((_1 = params.toolResponseDebug) === null || _1 === void 0 ? void 0 : _1.collectionScore) === 'number'
6869
+ collectionScore: typeof ((_2 = params.toolResponseDebug) === null || _2 === void 0 ? void 0 : _2.collectionScore) === 'number'
6463
6870
  ? params.toolResponseDebug.collectionScore
6464
6871
  : undefined,
6465
- query: ((_2 = params.toolResponseDebug) === null || _2 === void 0 ? void 0 : _2.query) || undefined,
6466
- pipeline: ((_3 = params.toolResponseDebug) === null || _3 === void 0 ? void 0 : _3.executedPipeline) || ((_4 = params.toolResponseDebug) === null || _4 === void 0 ? void 0 : _4.originalPipeline) || undefined,
6467
- options: ((_5 = params.toolResponseDebug) === null || _5 === void 0 ? void 0 : _5.options) || undefined,
6468
- fallbacks: ((_6 = params.toolResponseDebug) === null || _6 === void 0 ? void 0 : _6.fallbacks) || undefined,
6872
+ query: ((_3 = params.toolResponseDebug) === null || _3 === void 0 ? void 0 : _3.query) || undefined,
6873
+ pipeline: ((_4 = params.toolResponseDebug) === null || _4 === void 0 ? void 0 : _4.executedPipeline) || ((_5 = params.toolResponseDebug) === null || _5 === void 0 ? void 0 : _5.originalPipeline) || undefined,
6874
+ options: ((_6 = params.toolResponseDebug) === null || _6 === void 0 ? void 0 : _6.options) || undefined,
6875
+ fallbacks: ((_7 = params.toolResponseDebug) === null || _7 === void 0 ? void 0 : _7.fallbacks) || undefined,
6469
6876
  notes: notes
6470
6877
  };
6471
6878
  if (params.trace && typeof params.trace === 'object') {
@@ -9199,6 +9606,14 @@ function isAssistantDateArithmeticArgumentError(error) {
9199
9606
  || message.includes('undefined variable: now_start_of_next_month')
9200
9607
  || message.includes('undefined variable: now_end_of_month');
9201
9608
  }
9609
+ function isAssistantRankSortByError(error) {
9610
+ var message = normalizeOptionalString(error === null || error === void 0 ? void 0 : error.message).toLowerCase();
9611
+ if (!message) {
9612
+ return false;
9613
+ }
9614
+ return message.includes('$rank must be specified with a top level sortby expression with exactly one element')
9615
+ || message.includes('$denserank must be specified with a top level sortby expression with exactly one element');
9616
+ }
9202
9617
  function didAssistantValueChange(before, after) {
9203
9618
  try {
9204
9619
  return JSON.stringify(before) !== JSON.stringify(after);
@@ -9217,6 +9632,23 @@ function repairAssistantDateArithmeticInPipeline(pipeline) {
9217
9632
  changed: didAssistantValueChange(pipeline, repaired)
9218
9633
  };
9219
9634
  }
9635
+ function repairAssistantRankSortByInPipeline(pipeline) {
9636
+ var repaired = Array.isArray(pipeline)
9637
+ ? pipeline.map(function (stage) {
9638
+ if (!stage || typeof stage !== 'object' || Array.isArray(stage)) {
9639
+ return stage;
9640
+ }
9641
+ if (!stage.$setWindowFields || typeof stage.$setWindowFields !== 'object' || Array.isArray(stage.$setWindowFields)) {
9642
+ return stage;
9643
+ }
9644
+ return __assign(__assign({}, stage), { $setWindowFields: normalizeAssistantSetWindowFieldsRankSortBy(stage.$setWindowFields) });
9645
+ })
9646
+ : pipeline;
9647
+ return {
9648
+ pipeline: repaired,
9649
+ changed: didAssistantValueChange(pipeline, repaired)
9650
+ };
9651
+ }
9220
9652
  function isMatchExpressionOperand(value) {
9221
9653
  if (typeof value === 'string') {
9222
9654
  return value.startsWith('$$');
@@ -9656,6 +10088,39 @@ function normalizeAssistantMonthlyCalendarWindowPipeline(pipeline) {
9656
10088
  return next;
9657
10089
  });
9658
10090
  }
10091
+ function isAssistantRankWindowOutputExpression(value) {
10092
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
10093
+ return false;
10094
+ }
10095
+ return Object.prototype.hasOwnProperty.call(value, '$rank')
10096
+ || Object.prototype.hasOwnProperty.call(value, '$denseRank');
10097
+ }
10098
+ function normalizeAssistantSetWindowFieldsRankSortBy(setWindowFields) {
10099
+ var _a;
10100
+ if (!setWindowFields || typeof setWindowFields !== 'object' || Array.isArray(setWindowFields)) {
10101
+ return setWindowFields;
10102
+ }
10103
+ var output = setWindowFields.output;
10104
+ if (!output || typeof output !== 'object' || Array.isArray(output)) {
10105
+ return setWindowFields;
10106
+ }
10107
+ var usesRankWindowFunction = Object.values(output).some(function (value) { return isAssistantRankWindowOutputExpression(value); });
10108
+ if (!usesRankWindowFunction) {
10109
+ return setWindowFields;
10110
+ }
10111
+ var sortBy = setWindowFields.sortBy;
10112
+ if (!sortBy || typeof sortBy !== 'object' || Array.isArray(sortBy)) {
10113
+ return setWindowFields;
10114
+ }
10115
+ var sortKeys = Object.keys(sortBy).filter(function (key) { return String(key || '').trim(); });
10116
+ if (sortKeys.length <= 1) {
10117
+ return setWindowFields;
10118
+ }
10119
+ var primarySortKey = sortKeys[0];
10120
+ return __assign(__assign({}, setWindowFields), { sortBy: (_a = {},
10121
+ _a[primarySortKey] = sortBy[primarySortKey],
10122
+ _a) });
10123
+ }
9659
10124
  function normalizeAssistantAggregatePipeline(pipeline, collection) {
9660
10125
  if (!Array.isArray(pipeline)) {
9661
10126
  return [];
@@ -9677,6 +10142,9 @@ function normalizeAssistantAggregatePipeline(pipeline, collection) {
9677
10142
  var statusNormalized = isInvoiceCollection ? normalizeInvoiceStatusMatch(exprRewritten) : exprRewritten;
9678
10143
  next.$geoNear = __assign(__assign({}, next.$geoNear), { query: applyAssistantNameRegexToQuery(statusNormalized) });
9679
10144
  }
10145
+ if (next.$setWindowFields && typeof next.$setWindowFields === 'object' && !Array.isArray(next.$setWindowFields)) {
10146
+ next.$setWindowFields = normalizeAssistantSetWindowFieldsRankSortBy(next.$setWindowFields);
10147
+ }
9680
10148
  return normalizeAssistantNowExprPlaceholdersDeep(next);
9681
10149
  });
9682
10150
  return normalizeAssistantMonthlyCalendarWindowPipeline(normalizedPipeline);
@@ -12306,6 +12774,14 @@ var AI_ASSISTANT_BRIDGE_COLLECTION_ALIASES = {
12306
12774
  workorderdynamics: 'work-order-dynamics',
12307
12775
  workordersdynamic: 'work-order-dynamics',
12308
12776
  workordersdynamics: 'work-order-dynamics',
12777
+ trucktreatingdelivery: 'jobs',
12778
+ trucktreatingdeliveries: 'jobs',
12779
+ trucktreatingjob: 'jobs',
12780
+ trucktreatingjobs: 'jobs',
12781
+ trucktreatingroute: 'jobs',
12782
+ trucktreatingroutes: 'jobs',
12783
+ trucktreatingrouteevent: 'jobs',
12784
+ trucktreatingrouteevents: 'jobs',
12309
12785
  delivery: 'work-order-dynamics',
12310
12786
  deliveries: 'work-order-dynamics',
12311
12787
  blendticket: 'chemical-blends',
@@ -12328,6 +12804,10 @@ var AI_ASSISTANT_DIRECT_COLLECTION_FALLBACK_ALLOWLIST = new Set([
12328
12804
  'chemical-blends',
12329
12805
  'report-chemical-blends',
12330
12806
  'jobs',
12807
+ 'production-deliveries',
12808
+ 'truck-treating-deliveries',
12809
+ 'duplicate-deliveries',
12810
+ 'third-party-drivers',
12331
12811
  'customers',
12332
12812
  'support-tickets'
12333
12813
  ]);
@@ -12429,49 +12909,52 @@ function resolveAssistantCrossCollectionFallbackCandidates(collection) {
12429
12909
  });
12430
12910
  return deduped;
12431
12911
  }
12912
+ function resolveAssistantAvailableCrossCollectionFallbacksFromNames(collection, triedCollections, collectionNames) {
12913
+ var candidates = resolveAssistantCrossCollectionFallbackCandidates(collection);
12914
+ if (!candidates.length) {
12915
+ return [];
12916
+ }
12917
+ var namesByFamily = new Map();
12918
+ (collectionNames || []).forEach(function (name) {
12919
+ var family = normalizeAssistantCollectionFamilyName(name);
12920
+ if (!family) {
12921
+ return;
12922
+ }
12923
+ var existing = namesByFamily.get(family) || [];
12924
+ existing.push(name);
12925
+ namesByFamily.set(family, existing);
12926
+ });
12927
+ var currentFamily = normalizeAssistantCollectionFamilyName(collection);
12928
+ var available = [];
12929
+ candidates.forEach(function (candidate) {
12930
+ var family = normalizeAssistantCollectionFamilyName(candidate);
12931
+ if (!family || family === currentFamily || hasAssistantCollectionBeenTried(triedCollections, candidate)) {
12932
+ return;
12933
+ }
12934
+ var familyNames = namesByFamily.get(family) || [];
12935
+ var preferred = familyNames.find(function (name) { return !name.startsWith('report-') && !isVersionCollectionName(name); })
12936
+ || familyNames.find(function (name) { return !name.startsWith('report-'); })
12937
+ || familyNames[0]
12938
+ || '';
12939
+ if (!preferred && isAssistantDirectCollectionFallbackAllowed(candidate)) {
12940
+ preferred = candidate;
12941
+ }
12942
+ if (!preferred || hasAssistantCollectionBeenTried(triedCollections, preferred) || available.includes(preferred)) {
12943
+ return;
12944
+ }
12945
+ available.push(preferred);
12946
+ });
12947
+ return available;
12948
+ }
12432
12949
  function resolveAssistantAvailableCrossCollectionFallbacks(db, dbName, collection, triedCollections) {
12433
12950
  return __awaiter(this, void 0, void 0, function () {
12434
- var candidates, collectionNames, namesByFamily, currentFamily, available;
12951
+ var collectionNames;
12435
12952
  return __generator(this, function (_a) {
12436
12953
  switch (_a.label) {
12437
- case 0:
12438
- candidates = resolveAssistantCrossCollectionFallbackCandidates(collection);
12439
- if (!candidates.length) {
12440
- return [2 /*return*/, []];
12441
- }
12442
- return [4 /*yield*/, listAssistantCollections(db, dbName)];
12954
+ case 0: return [4 /*yield*/, listAssistantCollections(db, dbName)];
12443
12955
  case 1:
12444
12956
  collectionNames = _a.sent();
12445
- namesByFamily = new Map();
12446
- collectionNames.forEach(function (name) {
12447
- var family = normalizeAssistantCollectionFamilyName(name);
12448
- if (!family) {
12449
- return;
12450
- }
12451
- var existing = namesByFamily.get(family) || [];
12452
- existing.push(name);
12453
- namesByFamily.set(family, existing);
12454
- });
12455
- currentFamily = normalizeAssistantCollectionFamilyName(collection);
12456
- available = [];
12457
- candidates.forEach(function (candidate) {
12458
- var family = normalizeAssistantCollectionFamilyName(candidate);
12459
- if (!family || family === currentFamily || hasAssistantCollectionBeenTried(triedCollections, candidate)) {
12460
- return;
12461
- }
12462
- var familyNames = namesByFamily.get(family) || [];
12463
- if (!familyNames.length) {
12464
- return;
12465
- }
12466
- var preferred = familyNames.find(function (name) { return !name.startsWith('report-') && !isVersionCollectionName(name); })
12467
- || familyNames.find(function (name) { return !name.startsWith('report-'); })
12468
- || familyNames[0];
12469
- if (!preferred || hasAssistantCollectionBeenTried(triedCollections, preferred) || available.includes(preferred)) {
12470
- return;
12471
- }
12472
- available.push(preferred);
12473
- });
12474
- return [2 /*return*/, available];
12957
+ return [2 /*return*/, resolveAssistantAvailableCrossCollectionFallbacksFromNames(collection, triedCollections, collectionNames)];
12475
12958
  }
12476
12959
  });
12477
12960
  });
@@ -13897,6 +14380,9 @@ var AI_ASSISTANT_FEATURE_INFO_PATTERNS = [
13897
14380
  /\bwhat\s+changed\b/,
13898
14381
  /\brecent\s+changes?\b/,
13899
14382
  /\blatest\s+changes?\b/,
14383
+ /\bwhat\s+did\s+(?:the\s+)?last\s+(?:system\s+)?update\s+(?:just\s+)?do\b/i,
14384
+ /\blast\s+system\s+update\b/i,
14385
+ /\blast\s+update\b[\s\S]{0,30}\bdo\b/i,
13900
14386
  /\bchangelog\b/,
13901
14387
  /\brelease\s+notes?\b/
13902
14388
  ];
@@ -13921,6 +14407,8 @@ var AI_ASSISTANT_BUG_ISSUE_PATTERNS = [
13921
14407
  /\bwon['’]t\s+let\s+me\b/,
13922
14408
  /\bcan['’]?t\s+close\b/,
13923
14409
  /\bwhy\s+don['’]t\s+i\s+see\b/,
14410
+ /\bmissing\b[\s\S]{0,30}\bdropdown\b/i,
14411
+ /\bdropdown\b[\s\S]{0,30}\bmissing\b/i,
13924
14412
  /\bsubmit\s+button\b[\s\S]{0,60}\b(red|disabled|grey|gray)\b/i
13925
14413
  ];
13926
14414
  function isAssistantDataQuestion(message) {
@@ -14933,6 +15421,12 @@ function shouldUseAssistantNavigationFastPath(message, hasAttachments) {
14933
15421
  if (!text) {
14934
15422
  return false;
14935
15423
  }
15424
+ if (isAssistantChangeHistoryQuestion(text)) {
15425
+ return false;
15426
+ }
15427
+ if (isAssistantBugIssueQuestion(text)) {
15428
+ return false;
15429
+ }
14936
15430
  if (!isAssistantRouteLookupQuestion(text)) {
14937
15431
  return false;
14938
15432
  }
@@ -15020,6 +15514,8 @@ function resolveAssistantNavigationFastPathResponse(params) {
15020
15514
  }
15021
15515
  var AI_ASSISTANT_CHANGE_HISTORY_PATTERNS = [
15022
15516
  /\bwhat\s+changed\b/i,
15517
+ /\bwhat\s+changed\s+on\b/i,
15518
+ /\bwhat\s+changed\s+on\s+(?:this|that|the)\s+page\b/i,
15023
15519
  /\bmost\s+recent\s+change\b/i,
15024
15520
  /\blatest\s+changes?\b/i,
15025
15521
  /\brecent\s+changes?\b/i,
@@ -15029,12 +15525,15 @@ var AI_ASSISTANT_CHANGE_HISTORY_PATTERNS = [
15029
15525
  /\bwhen\s+did\b[\s\S]{0,80}\bget\s+added\b/i,
15030
15526
  /\bwhen\s+was\b[\s\S]{0,80}\badded\b/i,
15031
15527
  /\bwhen\s+does\b[\s\S]{0,80}\bget\s+added\b/i,
15528
+ /\bwhat\s+did\s+(?:the\s+)?last\s+(?:system\s+)?update\s+(?:just\s+)?do\b/i,
15529
+ /\blast\s+system\s+update\b[\s\S]{0,40}\bdo\b/i,
15032
15530
  /\bhow\s+long\b.*\bbeen\s+(this|that)\s+way\b/i,
15033
15531
  /\bsince\s+when\b/i,
15034
15532
  /\bchangelog\b/i,
15035
15533
  /\brelease\s+notes?\b/i,
15036
15534
  /\bgithub\b/i,
15037
- /\bcommits?\b/i
15535
+ /\bcommits?\b/i,
15536
+ /\bupdate\s+history\b/i
15038
15537
  ];
15039
15538
  function isAssistantChangeHistoryQuestion(message) {
15040
15539
  var text = normalizeOptionalString(message).toLowerCase();