@resolveio/server-lib 22.1.0 → 22.1.2

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.
@@ -84,15 +84,6 @@ var __read = (this && this.__read) || function (o, n) {
84
84
  }
85
85
  return ar;
86
86
  };
87
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
88
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
89
- if (ar || !(i in from)) {
90
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
91
- ar[i] = from[i];
92
- }
93
- }
94
- return to.concat(ar || Array.prototype.slice.call(from));
95
- };
96
87
  var __values = (this && this.__values) || function(o) {
97
88
  var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
98
89
  if (m) return m.call(o);
@@ -104,23 +95,36 @@ var __values = (this && this.__values) || function(o) {
104
95
  };
105
96
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
106
97
  };
98
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
99
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
100
+ if (ar || !(i in from)) {
101
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
102
+ ar[i] = from[i];
103
+ }
104
+ }
105
+ return to.concat(ar || Array.prototype.slice.call(from));
106
+ };
107
107
  Object.defineProperty(exports, "__esModule", { value: true });
108
108
  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;
127
+ exports.resolveAssistantCrossCollectionFallbackCandidates = resolveAssistantCrossCollectionFallbackCandidates;
124
128
  exports.collectUserViewPermissions = collectUserViewPermissions;
125
129
  exports.userHasInvoiceAccess = userHasInvoiceAccess;
126
130
  exports.resolveAssistantUserAccessTier = resolveAssistantUserAccessTier;
@@ -145,6 +149,7 @@ var resolveio_server_app_1 = require("../resolveio-server-app");
145
149
  var user_collection_1 = require("../collections/user.collection");
146
150
  var ai_terminal_conversation_collection_1 = require("../collections/ai-terminal-conversation.collection");
147
151
  var ai_terminal_message_collection_1 = require("../collections/ai-terminal-message.collection");
152
+ var ai_terminal_issue_report_collection_1 = require("../collections/ai-terminal-issue-report.collection");
148
153
  var common_1 = require("../util/common");
149
154
  var tokenizer_1 = require("../util/tokenizer");
150
155
  var openai_client_1 = require("../services/openai-client");
@@ -244,6 +249,7 @@ var AI_ASSISTANT_BLOCKED_COLLECTIONS = new Set([
244
249
  'logged-in-users',
245
250
  'ai-terminal-messages',
246
251
  'ai-terminal-conversations',
252
+ 'ai-terminal-issue-reports',
247
253
  'openai-usage-ledger',
248
254
  'logs',
249
255
  'notifications',
@@ -344,7 +350,8 @@ var AI_ASSISTANT_COLLECTION_DOMAIN_TOKENS = new Set([
344
350
  'sample',
345
351
  'samples',
346
352
  'customer',
347
- 'customers'
353
+ 'customers',
354
+ 'support'
348
355
  ]);
349
356
  var AI_ASSISTANT_COLLECTION_GENERIC_TOKENS = new Set([
350
357
  'ticket',
@@ -389,6 +396,11 @@ var AI_ASSISTANT_TERM_SYNONYMS = [
389
396
  pattern: /\btruck\s+treating\s+jobs?\b/i,
390
397
  expansions: ['truck treating deliveries', 'truck-treating-deliveries', 'truck treating route events']
391
398
  },
399
+ {
400
+ label: 'active clients',
401
+ pattern: /\b(?:how\s+many\s+)?active\s+(?:clients?|customers?)\b/i,
402
+ expansions: ['customers', 'clients', 'customer status', 'client status']
403
+ },
392
404
  {
393
405
  label: 'blend tickets',
394
406
  pattern: /\bblend(?:ing)?\s+tickets?\b/i,
@@ -398,6 +410,11 @@ var AI_ASSISTANT_TERM_SYNONYMS = [
398
410
  label: 'revenue',
399
411
  pattern: /\b(revenue|sales|billing)\b/i,
400
412
  expansions: ['invoice', 'invoices', 'paid invoices', 'invoice payments', 'billing', 'sales']
413
+ },
414
+ {
415
+ label: 'support tickets',
416
+ pattern: /\bsupport[\s-]*tickets?\b/i,
417
+ expansions: ['support-tickets', 'support ticket', 'ticket hours', 'billable hours']
401
418
  }
402
419
  ];
403
420
  var AI_ASSISTANT_REPORT_BUILDER_EXPERT_PLAYBOOK = [
@@ -1052,6 +1069,24 @@ function loadAiTerminalMethods(methodManager) {
1052
1069
  });
1053
1070
  });
1054
1071
  } }),
1072
+ aiCoderTerminalReportIssue: {
1073
+ check: new simpl_schema_1.default({
1074
+ payload: {
1075
+ type: Object,
1076
+ blackbox: true
1077
+ }
1078
+ }),
1079
+ function: function (payload) {
1080
+ return __awaiter(this, void 0, void 0, function () {
1081
+ return __generator(this, function (_a) {
1082
+ switch (_a.label) {
1083
+ case 0: return [4 /*yield*/, executeAiAssistantReportIssue(payload, this)];
1084
+ case 1: return [2 /*return*/, _a.sent()];
1085
+ }
1086
+ });
1087
+ });
1088
+ }
1089
+ },
1055
1090
  aiAssistantMongoRead: {
1056
1091
  check: new simpl_schema_1.default({
1057
1092
  payload: {
@@ -1579,10 +1614,10 @@ function executeAiAssistantCodexRun(payload, context) {
1579
1614
  insertResult = _e.sent();
1580
1615
  assistantMessageId = (insertResult === null || insertResult === void 0 ? void 0 : insertResult._id) || (insertResult === null || insertResult === void 0 ? void 0 : insertResult.insertedId);
1581
1616
  enqueueAssistantCodexRun(function () { return __awaiter(_this, void 0, void 0, function () {
1582
- var runStart, steps, recordStep, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, requestClassification, dataQuestion, lastDirective, heuristicDirectivePrecomputed, usedDeterministicHeuristicFastPath, requestedTimeGrain, enforceDatedDirective, datedDirectiveRetryUsed, datedDirectiveResolved, toolResponseDebug, toolError, termHints, collectionHints, fieldHints, collectionTokenization, collectionRanking, collectionSelection, collectionOverride, collectionNames, plannerEnabled, plannerUsed, plannerOutput, plannerRaw, timingBreakdown, codexUsage, accumulateCodexUsage, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, baseWeights, expandedWeights, dbName, db, _a, routeHints, rankedCollections, hintCollections, assistantContext, hasDeterministicHeuristicFastPath, prompt_1, workspaceRoot, codexConfig, runOptions, shouldRunPlanner, plannerPrompt, plannerStart, _b, preferListDirective, directiveStyleHint, directivePromptMode, responseText, directiveText, directive, heuristicDirectiveFastPath, directivePrompt, directiveStart, forcedDirective, _c, initialStart, extractedDirective, directivePrompt, forcedStart, forcedDirective, _d, strictDirectivePrompt, strictStart, strictDirectiveText, strictDirective, strictDirectiveIsDated, shouldUseStrictDirective, _e, guardDirectivePrompt, guardStart, guardDirectiveText, guardDirective, _f, heuristicDirective, requestedCollection, cleanedResponseText, effectiveDirective, toolRequest, toolStart, toolResponse, _g, toolPayload, skipFollowupCodex, followupPrompt, followupStart, followupText, _h, error_2, error_3, finishedAt, finalNow, finishedAt, codexMs, draftingMs, finalMetadata, finalUsage, usageClientId, usageError_1, finalAssistantDoc, setPayload;
1583
- var _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8;
1584
- return __generator(this, function (_9) {
1585
- switch (_9.label) {
1617
+ var runStart, steps, recordStep, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, requestClassification, dataQuestion, lastDirective, heuristicDirectivePrecomputed, usedDeterministicHeuristicFastPath, requestedTimeGrain, requestedBreakdownDimensions, enforceDatedDirective, enforceGroupedDirective, datedDirectiveRetryUsed, datedDirectiveResolved, toolResponseDebug, toolError, termHints, collectionHints, fieldHints, collectionTokenization, collectionRanking, collectionSelection, collectionOverride, collectionNames, plannerEnabled, plannerUsed, plannerOutput, plannerRaw, timingBreakdown, codexUsage, accumulateCodexUsage, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, baseWeights, expandedWeights, dbName, db, _a, routeHints, rankedCollections, hintCollections, assistantContext, hasDeterministicHeuristicFastPath, prompt_1, workspaceRoot, codexConfig, runOptions, shouldRunPlanner, plannerPrompt, plannerStart, _b, preferListDirective, directiveStyleHint, directivePromptMode, responseText, directiveText, directive, heuristicDirectiveFastPath, directivePrompt, directiveStart, forcedDirective, _c, initialStart, extractedDirective, error_2, directivePrompt, forcedStart, forcedDirective, _d, strictDirectivePrompt, strictStart, strictDirectiveText, strictDirective, strictDirectiveIsDated, shouldUseStrictDirective, _e, guardDirectivePrompt, guardStart, guardDirectiveText, guardDirective, _f, groupedDirectivePrompt, groupedStart, groupedDirectiveText, groupedDirective, _g, heuristicDirective, requestedCollection, cleanedResponseText, effectiveDirective, toolRequest, toolStart, toolResponse, _h, toolPayload, skipFollowupCodex, followupPrompt, followupStart, followupText, _j, error_3, error_4, finishedAt, finalNow, finishedAt, codexMs, draftingMs, finalMetadata, finalUsage, usageClientId, usageError_1, finalAssistantDoc, setPayload;
1618
+ var _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12;
1619
+ return __generator(this, function (_13) {
1620
+ switch (_13.label) {
1586
1621
  case 0:
1587
1622
  runStart = Date.now();
1588
1623
  if (aiWorkerDebug) {
@@ -1617,7 +1652,9 @@ function executeAiAssistantCodexRun(payload, context) {
1617
1652
  heuristicDirectivePrecomputed = null;
1618
1653
  usedDeterministicHeuristicFastPath = false;
1619
1654
  requestedTimeGrain = null;
1655
+ requestedBreakdownDimensions = [];
1620
1656
  enforceDatedDirective = false;
1657
+ enforceGroupedDirective = false;
1621
1658
  datedDirectiveRetryUsed = false;
1622
1659
  datedDirectiveResolved = false;
1623
1660
  toolResponseDebug = null;
@@ -1657,17 +1694,17 @@ function executeAiAssistantCodexRun(payload, context) {
1657
1694
  codexUsage.output_tokens += outputTokens;
1658
1695
  codexUsage.total_tokens += inputTokens + outputTokens;
1659
1696
  };
1660
- contextRoute = normalizeOptionalString((_j = input === null || input === void 0 ? void 0 : input.context) === null || _j === void 0 ? void 0 : _j.route);
1661
- contextMode = normalizeOptionalString((_k = input === null || input === void 0 ? void 0 : input.context) === null || _k === void 0 ? void 0 : _k.mode);
1697
+ contextRoute = normalizeOptionalString((_k = input === null || input === void 0 ? void 0 : input.context) === null || _k === void 0 ? void 0 : _k.route);
1698
+ contextMode = normalizeOptionalString((_l = input === null || input === void 0 ? void 0 : input.context) === null || _l === void 0 ? void 0 : _l.mode);
1662
1699
  recordStep('Queued', { requestId: requestId || undefined });
1663
1700
  recordStep('Planning: request classification', {
1664
1701
  type: requestClassification.type,
1665
1702
  source: requestClassification.source,
1666
1703
  dataQuestion: dataQuestion
1667
1704
  });
1668
- _9.label = 1;
1705
+ _13.label = 1;
1669
1706
  case 1:
1670
- _9.trys.push([1, 43, 44, 45]);
1707
+ _13.trys.push([1, 49, 50, 51]);
1671
1708
  hintSeed = [message, contextRoute].filter(Boolean).join(' ');
1672
1709
  termExpansion = expandAssistantTermSynonyms(hintSeed);
1673
1710
  hintText = termExpansion.expanded || hintSeed;
@@ -1688,19 +1725,19 @@ function executeAiAssistantCodexRun(payload, context) {
1688
1725
  recordStep('Planning: term expansion', {
1689
1726
  termMatches: termExpansion.matches.length ? termExpansion.matches : undefined
1690
1727
  });
1691
- _9.label = 2;
1728
+ _13.label = 2;
1692
1729
  case 2:
1693
- _9.trys.push([2, 4, , 5]);
1730
+ _13.trys.push([2, 4, , 5]);
1694
1731
  dbName = resolveAssistantDatabaseName(undefined, input.mongo);
1695
1732
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1696
1733
  return [4 /*yield*/, listAssistantCollections(db, dbName)];
1697
1734
  case 3:
1698
- collectionNames = _9.sent();
1735
+ collectionNames = _13.sent();
1699
1736
  collectionHints = resolveCollectionHintsFromTokens(expandedTokens, collectionNames, 5);
1700
1737
  collectionRanking = buildCollectionRankingDebugFromTokens(expandedTokens, collectionNames, 8);
1701
1738
  return [3 /*break*/, 5];
1702
1739
  case 4:
1703
- _a = _9.sent();
1740
+ _a = _13.sent();
1704
1741
  collectionHints = [];
1705
1742
  collectionRanking = collectionRanking || ((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens)
1706
1743
  ? buildCollectionRankingDebugFromTokens(collectionTokenization.expandedTokens || [], [], 0)
@@ -1743,14 +1780,14 @@ function executeAiAssistantCodexRun(payload, context) {
1743
1780
  if (hasDeterministicHeuristicFastPath) {
1744
1781
  recordStep('Planning: heuristic directive fast path', {
1745
1782
  type: heuristicDirectivePrecomputed === null || heuristicDirectivePrecomputed === void 0 ? void 0 : heuristicDirectivePrecomputed.type,
1746
- collection: normalizeOptionalString((_l = heuristicDirectivePrecomputed === null || heuristicDirectivePrecomputed === void 0 ? void 0 : heuristicDirectivePrecomputed.payload) === null || _l === void 0 ? void 0 : _l.collection) || undefined,
1783
+ collection: normalizeOptionalString((_m = heuristicDirectivePrecomputed === null || heuristicDirectivePrecomputed === void 0 ? void 0 : heuristicDirectivePrecomputed.payload) === null || _m === void 0 ? void 0 : _m.collection) || undefined,
1747
1784
  heuristic: normalizeOptionalString(heuristicDirectivePrecomputed === null || heuristicDirectivePrecomputed === void 0 ? void 0 : heuristicDirectivePrecomputed.rawLine) || undefined
1748
1785
  });
1749
1786
  }
1750
1787
  prompt_1 = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1751
1788
  return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
1752
1789
  case 6:
1753
- workspaceRoot = _9.sent();
1790
+ workspaceRoot = _13.sent();
1754
1791
  codexConfig = resolveCodexSettings({
1755
1792
  model: codexModel,
1756
1793
  fallbackModels: codexFallbackModels
@@ -1789,41 +1826,48 @@ function executeAiAssistantCodexRun(payload, context) {
1789
1826
  fieldHints: fieldHints,
1790
1827
  inputClientId: input.id_client
1791
1828
  });
1792
- _9.label = 7;
1829
+ _13.label = 7;
1793
1830
  case 7:
1794
- _9.trys.push([7, 9, , 10]);
1831
+ _13.trys.push([7, 9, , 10]);
1795
1832
  plannerStart = Date.now();
1796
1833
  return [4 /*yield*/, runCodexInWorkerThread(plannerPrompt, runOptions, codexConfig, streamProgress)];
1797
1834
  case 8:
1798
- plannerRaw = _9.sent();
1835
+ plannerRaw = _13.sent();
1799
1836
  accumulateCodexUsage(plannerPrompt, plannerRaw);
1800
1837
  timingBreakdown.plannerMs = Date.now() - plannerStart;
1801
1838
  plannerOutput = parseJsonObject(plannerRaw);
1802
1839
  recordStep('Planning: planner result', { parsed: !!plannerOutput });
1803
1840
  return [3 /*break*/, 10];
1804
1841
  case 9:
1805
- _b = _9.sent();
1842
+ _b = _13.sent();
1806
1843
  recordStep('Planning: planner result', { parsed: false });
1807
1844
  return [3 /*break*/, 10];
1808
1845
  case 10:
1809
1846
  requestClassification = classifyAssistantRequestType(message, plannerOutput || undefined);
1810
1847
  dataQuestion = requestClassification.dataQuestion;
1811
1848
  requestedTimeGrain = resolveAssistantRequestedTimeGrain(message, plannerOutput || undefined);
1849
+ requestedBreakdownDimensions = extractAssistantRequestedBreakdownDimensions(message);
1812
1850
  preferListDirective = shouldPreferAssistantListDirective(message, plannerOutput || undefined, requestClassification);
1813
1851
  enforceDatedDirective = shouldEnforceAssistantDatedDirective(message, plannerOutput || undefined, requestClassification);
1852
+ enforceGroupedDirective = shouldEnforceAssistantGroupedDirective(message, plannerOutput || undefined, requestClassification);
1814
1853
  directiveStyleHint = buildAssistantDirectiveStyleHint({
1815
1854
  enforceDated: enforceDatedDirective,
1855
+ enforceGrouped: enforceGroupedDirective,
1816
1856
  requestedTimeGrain: requestedTimeGrain,
1857
+ requestedBreakdowns: requestedBreakdownDimensions,
1817
1858
  preferList: preferListDirective
1818
1859
  });
1819
- directivePromptMode = enforceDatedDirective ? 'aggregate_only' : 'any';
1860
+ directivePromptMode = (enforceDatedDirective || enforceGroupedDirective) ? 'aggregate_only' : 'any';
1820
1861
  datedDirectiveRetryUsed = false;
1821
1862
  recordStep('Planning: request classification', {
1822
1863
  type: requestClassification.type,
1823
1864
  source: requestClassification.source,
1824
1865
  plannerIntentType: requestClassification.plannerIntentType || undefined,
1825
1866
  dataQuestion: dataQuestion,
1826
- reportStyle: enforceDatedDirective ? 'dated' : undefined,
1867
+ reportStyle: enforceDatedDirective
1868
+ ? 'dated'
1869
+ : (enforceGroupedDirective ? 'grouped' : undefined),
1870
+ breakdownDimensions: requestedBreakdownDimensions.length ? requestedBreakdownDimensions : undefined,
1827
1871
  timeGrain: requestedTimeGrain || undefined
1828
1872
  });
1829
1873
  responseText = '';
@@ -1839,12 +1883,12 @@ function executeAiAssistantCodexRun(payload, context) {
1839
1883
  directiveSource = 'forced';
1840
1884
  lastDirective = heuristicDirectiveFastPath;
1841
1885
  usedDeterministicHeuristicFastPath = true;
1842
- collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_m = directive.payload) === null || _m === void 0 ? void 0 : _m.collection) || '');
1886
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_o = directive.payload) === null || _o === void 0 ? void 0 : _o.collection) || '');
1843
1887
  recordStep('Directive resolved', {
1844
1888
  source: directiveSource,
1845
1889
  type: directive.type,
1846
- collection: normalizeOptionalString((_o = directive.payload) === null || _o === void 0 ? void 0 : _o.collection) || undefined,
1847
- permissionView: normalizeOptionalString((_p = directive.payload) === null || _p === void 0 ? void 0 : _p.permissionView) || undefined,
1890
+ collection: normalizeOptionalString((_p = directive.payload) === null || _p === void 0 ? void 0 : _p.collection) || undefined,
1891
+ permissionView: normalizeOptionalString((_q = directive.payload) === null || _q === void 0 ? void 0 : _q.permissionView) || undefined,
1848
1892
  reportStyle: 'heuristic_fast_path',
1849
1893
  timeGrain: requestedTimeGrain || undefined
1850
1894
  });
@@ -1852,13 +1896,13 @@ function executeAiAssistantCodexRun(payload, context) {
1852
1896
  if (!(dataQuestion && !directive)) return [3 /*break*/, 14];
1853
1897
  recordStep('Directive: determine tool', { type: 'data-question' });
1854
1898
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, directiveStyleHint, directivePromptMode);
1855
- _9.label = 11;
1899
+ _13.label = 11;
1856
1900
  case 11:
1857
- _9.trys.push([11, 13, , 14]);
1901
+ _13.trys.push([11, 13, , 14]);
1858
1902
  directiveStart = Date.now();
1859
1903
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1860
1904
  case 12:
1861
- directiveText = _9.sent();
1905
+ directiveText = _13.sent();
1862
1906
  accumulateCodexUsage(directivePrompt, directiveText);
1863
1907
  timingBreakdown.directiveMs = Date.now() - directiveStart;
1864
1908
  forcedDirective = extractAssistantMongoDirective(directiveText);
@@ -1866,25 +1910,28 @@ function executeAiAssistantCodexRun(payload, context) {
1866
1910
  directive = forcedDirective;
1867
1911
  directiveSource = 'model';
1868
1912
  lastDirective = forcedDirective;
1869
- collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_q = directive.payload) === null || _q === void 0 ? void 0 : _q.collection) || '');
1913
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_r = directive.payload) === null || _r === void 0 ? void 0 : _r.collection) || '');
1870
1914
  recordStep('Directive resolved', {
1871
1915
  source: directiveSource,
1872
1916
  type: directive.type,
1873
- collection: normalizeOptionalString((_r = directive.payload) === null || _r === void 0 ? void 0 : _r.collection) || undefined,
1874
- permissionView: normalizeOptionalString((_s = directive.payload) === null || _s === void 0 ? void 0 : _s.permissionView) || undefined
1917
+ collection: normalizeOptionalString((_s = directive.payload) === null || _s === void 0 ? void 0 : _s.collection) || undefined,
1918
+ permissionView: normalizeOptionalString((_t = directive.payload) === null || _t === void 0 ? void 0 : _t.permissionView) || undefined
1875
1919
  });
1876
1920
  }
1877
1921
  return [3 /*break*/, 14];
1878
1922
  case 13:
1879
- _c = _9.sent();
1923
+ _c = _13.sent();
1880
1924
  return [3 /*break*/, 14];
1881
1925
  case 14:
1882
- if (!!directive) return [3 /*break*/, 16];
1926
+ if (!(!directive && !dataQuestion)) return [3 /*break*/, 18];
1883
1927
  recordStep('Response: draft initial answer', { mode: 'full' });
1928
+ _13.label = 15;
1929
+ case 15:
1930
+ _13.trys.push([15, 17, , 18]);
1884
1931
  initialStart = Date.now();
1885
1932
  return [4 /*yield*/, runCodexInWorkerThread(prompt_1, runOptions, codexConfig, streamProgress)];
1886
- case 15:
1887
- responseText = _9.sent();
1933
+ case 16:
1934
+ responseText = _13.sent();
1888
1935
  accumulateCodexUsage(prompt_1, responseText);
1889
1936
  timingBreakdown.initialResponseMs = Date.now() - initialStart;
1890
1937
  extractedDirective = extractAssistantMongoDirective(responseText);
@@ -1892,26 +1939,32 @@ function executeAiAssistantCodexRun(payload, context) {
1892
1939
  if (directive) {
1893
1940
  directiveSource = 'model';
1894
1941
  lastDirective = directive;
1895
- collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_t = directive.payload) === null || _t === void 0 ? void 0 : _t.collection) || '');
1942
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_u = directive.payload) === null || _u === void 0 ? void 0 : _u.collection) || '');
1896
1943
  recordStep('Directive resolved', {
1897
1944
  source: directiveSource,
1898
1945
  type: directive.type,
1899
- collection: normalizeOptionalString((_u = directive.payload) === null || _u === void 0 ? void 0 : _u.collection) || undefined,
1900
- permissionView: normalizeOptionalString((_v = directive.payload) === null || _v === void 0 ? void 0 : _v.permissionView) || undefined
1946
+ collection: normalizeOptionalString((_v = directive.payload) === null || _v === void 0 ? void 0 : _v.collection) || undefined,
1947
+ permissionView: normalizeOptionalString((_w = directive.payload) === null || _w === void 0 ? void 0 : _w.permissionView) || undefined
1901
1948
  });
1902
1949
  }
1903
- _9.label = 16;
1904
- case 16:
1905
- if (!(!directive && dataQuestion)) return [3 /*break*/, 20];
1950
+ return [3 /*break*/, 18];
1951
+ case 17:
1952
+ error_2 = _13.sent();
1953
+ recordStep('Response: initial draft failed', {
1954
+ message: normalizeOptionalString(error_2 === null || error_2 === void 0 ? void 0 : error_2.message) || 'Unknown error'
1955
+ });
1956
+ return [3 /*break*/, 18];
1957
+ case 18:
1958
+ if (!(!directive && dataQuestion)) return [3 /*break*/, 22];
1906
1959
  recordStep('Directive: forced retry', { mode: 'directive-only' });
1907
1960
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, directiveStyleHint, directivePromptMode);
1908
- _9.label = 17;
1909
- case 17:
1910
- _9.trys.push([17, 19, , 20]);
1961
+ _13.label = 19;
1962
+ case 19:
1963
+ _13.trys.push([19, 21, , 22]);
1911
1964
  forcedStart = Date.now();
1912
1965
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1913
- case 18:
1914
- directiveText = _9.sent();
1966
+ case 20:
1967
+ directiveText = _13.sent();
1915
1968
  accumulateCodexUsage(directivePrompt, directiveText);
1916
1969
  timingBreakdown.forcedDirectiveMs = Date.now() - forcedStart;
1917
1970
  forcedDirective = extractAssistantMongoDirective(directiveText);
@@ -1919,39 +1972,41 @@ function executeAiAssistantCodexRun(payload, context) {
1919
1972
  directive = forcedDirective;
1920
1973
  directiveSource = 'forced';
1921
1974
  lastDirective = forcedDirective;
1922
- collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_w = directive.payload) === null || _w === void 0 ? void 0 : _w.collection) || '');
1975
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_x = directive.payload) === null || _x === void 0 ? void 0 : _x.collection) || '');
1923
1976
  recordStep('Directive resolved', {
1924
1977
  source: directiveSource,
1925
1978
  type: directive.type,
1926
- collection: normalizeOptionalString((_x = directive.payload) === null || _x === void 0 ? void 0 : _x.collection) || undefined,
1927
- permissionView: normalizeOptionalString((_y = directive.payload) === null || _y === void 0 ? void 0 : _y.permissionView) || undefined
1979
+ collection: normalizeOptionalString((_y = directive.payload) === null || _y === void 0 ? void 0 : _y.collection) || undefined,
1980
+ permissionView: normalizeOptionalString((_z = directive.payload) === null || _z === void 0 ? void 0 : _z.permissionView) || undefined
1928
1981
  });
1929
1982
  }
1930
- return [3 /*break*/, 20];
1931
- case 19:
1932
- _d = _9.sent();
1933
- return [3 /*break*/, 20];
1934
- case 20:
1983
+ return [3 /*break*/, 22];
1984
+ case 21:
1985
+ _d = _13.sent();
1986
+ return [3 /*break*/, 22];
1987
+ case 22:
1935
1988
  if (!(directive
1936
1989
  && enforceDatedDirective
1937
1990
  && !isAssistantDeterministicHeuristicDirective(directive)
1938
- && !isAssistantDirectiveDated(directive))) return [3 /*break*/, 24];
1991
+ && !isAssistantDirectiveDated(directive))) return [3 /*break*/, 26];
1939
1992
  recordStep('Directive: dated retry', {
1940
1993
  currentType: directive.type,
1941
1994
  timeGrain: requestedTimeGrain || undefined
1942
1995
  });
1943
1996
  strictDirectivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, buildAssistantDirectiveStyleHint({
1944
1997
  enforceDated: true,
1998
+ enforceGrouped: enforceGroupedDirective,
1945
1999
  requestedTimeGrain: requestedTimeGrain,
2000
+ requestedBreakdowns: requestedBreakdownDimensions,
1946
2001
  strict: true
1947
2002
  }), 'aggregate_only');
1948
- _9.label = 21;
1949
- case 21:
1950
- _9.trys.push([21, 23, , 24]);
2003
+ _13.label = 23;
2004
+ case 23:
2005
+ _13.trys.push([23, 25, , 26]);
1951
2006
  strictStart = Date.now();
1952
2007
  return [4 /*yield*/, runCodexInWorkerThread(strictDirectivePrompt, runOptions, codexConfig, streamProgress)];
1953
- case 22:
1954
- strictDirectiveText = _9.sent();
2008
+ case 24:
2009
+ strictDirectiveText = _13.sent();
1955
2010
  accumulateCodexUsage(strictDirectivePrompt, strictDirectiveText);
1956
2011
  timingBreakdown.forcedDirectiveMs += Date.now() - strictStart;
1957
2012
  strictDirective = extractAssistantMongoDirective(strictDirectiveText);
@@ -1962,41 +2017,43 @@ function executeAiAssistantCodexRun(payload, context) {
1962
2017
  directiveSource = 'forced';
1963
2018
  lastDirective = strictDirective;
1964
2019
  datedDirectiveRetryUsed = true;
1965
- collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_z = directive.payload) === null || _z === void 0 ? void 0 : _z.collection) || '');
2020
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_0 = directive.payload) === null || _0 === void 0 ? void 0 : _0.collection) || '');
1966
2021
  recordStep('Directive resolved', {
1967
2022
  source: directiveSource,
1968
2023
  type: directive.type,
1969
- collection: normalizeOptionalString((_0 = directive.payload) === null || _0 === void 0 ? void 0 : _0.collection) || undefined,
1970
- permissionView: normalizeOptionalString((_1 = directive.payload) === null || _1 === void 0 ? void 0 : _1.permissionView) || undefined,
2024
+ collection: normalizeOptionalString((_1 = directive.payload) === null || _1 === void 0 ? void 0 : _1.collection) || undefined,
2025
+ permissionView: normalizeOptionalString((_2 = directive.payload) === null || _2 === void 0 ? void 0 : _2.permissionView) || undefined,
1971
2026
  reportStyle: strictDirectiveIsDated ? 'dated' : 'aggregate_fallback',
1972
2027
  timeGrain: requestedTimeGrain || undefined
1973
2028
  });
1974
2029
  }
1975
- return [3 /*break*/, 24];
1976
- case 23:
1977
- _e = _9.sent();
1978
- return [3 /*break*/, 24];
1979
- case 24:
2030
+ return [3 /*break*/, 26];
2031
+ case 25:
2032
+ _e = _13.sent();
2033
+ return [3 /*break*/, 26];
2034
+ case 26:
1980
2035
  if (!(directive
1981
2036
  && enforceDatedDirective
1982
2037
  && !isAssistantDeterministicHeuristicDirective(directive)
1983
- && directive.type === 'read')) return [3 /*break*/, 28];
2038
+ && directive.type === 'read')) return [3 /*break*/, 30];
1984
2039
  recordStep('Directive: dated guard retry', {
1985
2040
  currentType: directive.type,
1986
2041
  timeGrain: requestedTimeGrain || undefined
1987
2042
  });
1988
2043
  guardDirectivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, buildAssistantDirectiveStyleHint({
1989
2044
  enforceDated: true,
2045
+ enforceGrouped: enforceGroupedDirective,
1990
2046
  requestedTimeGrain: requestedTimeGrain,
2047
+ requestedBreakdowns: requestedBreakdownDimensions,
1991
2048
  strict: true
1992
2049
  }), 'aggregate_only');
1993
- _9.label = 25;
1994
- case 25:
1995
- _9.trys.push([25, 27, , 28]);
2050
+ _13.label = 27;
2051
+ case 27:
2052
+ _13.trys.push([27, 29, , 30]);
1996
2053
  guardStart = Date.now();
1997
2054
  return [4 /*yield*/, runCodexInWorkerThread(guardDirectivePrompt, runOptions, codexConfig, streamProgress)];
1998
- case 26:
1999
- guardDirectiveText = _9.sent();
2055
+ case 28:
2056
+ guardDirectiveText = _13.sent();
2000
2057
  accumulateCodexUsage(guardDirectivePrompt, guardDirectiveText);
2001
2058
  timingBreakdown.forcedDirectiveMs += Date.now() - guardStart;
2002
2059
  guardDirective = extractAssistantMongoDirective(guardDirectiveText);
@@ -2005,21 +2062,69 @@ function executeAiAssistantCodexRun(payload, context) {
2005
2062
  directiveSource = 'forced';
2006
2063
  lastDirective = guardDirective;
2007
2064
  datedDirectiveRetryUsed = true;
2008
- collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_2 = directive.payload) === null || _2 === void 0 ? void 0 : _2.collection) || '');
2065
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_3 = directive.payload) === null || _3 === void 0 ? void 0 : _3.collection) || '');
2009
2066
  recordStep('Directive resolved', {
2010
2067
  source: directiveSource,
2011
2068
  type: directive.type,
2012
- collection: normalizeOptionalString((_3 = directive.payload) === null || _3 === void 0 ? void 0 : _3.collection) || undefined,
2013
- permissionView: normalizeOptionalString((_4 = directive.payload) === null || _4 === void 0 ? void 0 : _4.permissionView) || undefined,
2069
+ collection: normalizeOptionalString((_4 = directive.payload) === null || _4 === void 0 ? void 0 : _4.collection) || undefined,
2070
+ permissionView: normalizeOptionalString((_5 = directive.payload) === null || _5 === void 0 ? void 0 : _5.permissionView) || undefined,
2014
2071
  reportStyle: isAssistantDirectiveDated(guardDirective) ? 'dated' : 'aggregate_fallback',
2015
2072
  timeGrain: requestedTimeGrain || undefined
2016
2073
  });
2017
2074
  }
2018
- return [3 /*break*/, 28];
2019
- case 27:
2020
- _f = _9.sent();
2021
- return [3 /*break*/, 28];
2022
- case 28:
2075
+ return [3 /*break*/, 30];
2076
+ case 29:
2077
+ _f = _13.sent();
2078
+ return [3 /*break*/, 30];
2079
+ case 30:
2080
+ if (!(directive
2081
+ && enforceGroupedDirective
2082
+ && !isAssistantDeterministicHeuristicDirective(directive)
2083
+ && !isAssistantDirectiveGrouped(directive))) return [3 /*break*/, 34];
2084
+ recordStep('Directive: grouped guard retry', {
2085
+ currentType: directive.type,
2086
+ breakdownDimensions: requestedBreakdownDimensions.length ? requestedBreakdownDimensions : undefined
2087
+ });
2088
+ groupedDirectivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, buildAssistantDirectiveStyleHint({
2089
+ enforceDated: enforceDatedDirective,
2090
+ enforceGrouped: true,
2091
+ requestedTimeGrain: requestedTimeGrain,
2092
+ requestedBreakdowns: requestedBreakdownDimensions,
2093
+ strict: true
2094
+ }), 'aggregate_only');
2095
+ _13.label = 31;
2096
+ case 31:
2097
+ _13.trys.push([31, 33, , 34]);
2098
+ groupedStart = Date.now();
2099
+ return [4 /*yield*/, runCodexInWorkerThread(groupedDirectivePrompt, runOptions, codexConfig, streamProgress)];
2100
+ case 32:
2101
+ groupedDirectiveText = _13.sent();
2102
+ accumulateCodexUsage(groupedDirectivePrompt, groupedDirectiveText);
2103
+ timingBreakdown.forcedDirectiveMs += Date.now() - groupedStart;
2104
+ groupedDirective = extractAssistantMongoDirective(groupedDirectiveText);
2105
+ if (isAssistantExecutableDirective(groupedDirective) && isAssistantDirectiveGrouped(groupedDirective)) {
2106
+ directive = groupedDirective;
2107
+ directiveSource = 'forced';
2108
+ lastDirective = groupedDirective;
2109
+ datedDirectiveRetryUsed = true;
2110
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_6 = directive.payload) === null || _6 === void 0 ? void 0 : _6.collection) || '');
2111
+ recordStep('Directive resolved', {
2112
+ source: directiveSource,
2113
+ type: directive.type,
2114
+ collection: normalizeOptionalString((_7 = directive.payload) === null || _7 === void 0 ? void 0 : _7.collection) || undefined,
2115
+ permissionView: normalizeOptionalString((_8 = directive.payload) === null || _8 === void 0 ? void 0 : _8.permissionView) || undefined,
2116
+ reportStyle: isAssistantDirectiveDated(groupedDirective)
2117
+ ? 'dated'
2118
+ : 'grouped',
2119
+ breakdownDimensions: requestedBreakdownDimensions.length ? requestedBreakdownDimensions : undefined,
2120
+ timeGrain: requestedTimeGrain || undefined
2121
+ });
2122
+ }
2123
+ return [3 /*break*/, 34];
2124
+ case 33:
2125
+ _g = _13.sent();
2126
+ return [3 /*break*/, 34];
2127
+ case 34:
2023
2128
  if (!directive && dataQuestion) {
2024
2129
  heuristicDirective = buildAssistantHeuristicDirective(message, collectionHints);
2025
2130
  if (isAssistantExecutableDirective(heuristicDirective)) {
@@ -2029,19 +2134,19 @@ function executeAiAssistantCodexRun(payload, context) {
2029
2134
  recordStep('Directive resolved', {
2030
2135
  source: directiveSource,
2031
2136
  type: directive.type,
2032
- collection: normalizeOptionalString((_5 = directive.payload) === null || _5 === void 0 ? void 0 : _5.collection) || undefined,
2033
- permissionView: normalizeOptionalString((_6 = directive.payload) === null || _6 === void 0 ? void 0 : _6.permissionView) || undefined,
2137
+ collection: normalizeOptionalString((_9 = directive.payload) === null || _9 === void 0 ? void 0 : _9.collection) || undefined,
2138
+ permissionView: normalizeOptionalString((_10 = directive.payload) === null || _10 === void 0 ? void 0 : _10.permissionView) || undefined,
2034
2139
  reportStyle: 'heuristic_fallback'
2035
2140
  });
2036
2141
  }
2037
2142
  }
2038
2143
  if (directive) {
2039
- requestedCollection = normalizeOptionalString((_7 = directive.payload) === null || _7 === void 0 ? void 0 : _7.collection);
2144
+ requestedCollection = normalizeOptionalString((_11 = directive.payload) === null || _11 === void 0 ? void 0 : _11.collection);
2040
2145
  collectionOverride = resolveCollectionOverrideWithContext({
2041
2146
  message: message,
2042
2147
  collectionRanking: collectionRanking,
2043
2148
  requestedCollection: requestedCollection,
2044
- permissionView: normalizeOptionalString((_8 = directive.payload) === null || _8 === void 0 ? void 0 : _8.permissionView) || contextRoute,
2149
+ permissionView: normalizeOptionalString((_12 = directive.payload) === null || _12 === void 0 ? void 0 : _12.permissionView) || contextRoute,
2045
2150
  collectionNames: collectionNames
2046
2151
  });
2047
2152
  if (collectionOverride) {
@@ -2058,7 +2163,7 @@ function executeAiAssistantCodexRun(payload, context) {
2058
2163
  if (cleanedResponseText) {
2059
2164
  assistantContent = sanitizeAssistantResponse(cleanedResponseText);
2060
2165
  }
2061
- if (!((directive === null || directive === void 0 ? void 0 : directive.payload) && AI_ASSISTANT_TOOL_MAX_STEPS > 0)) return [3 /*break*/, 41];
2166
+ if (!((directive === null || directive === void 0 ? void 0 : directive.payload) && AI_ASSISTANT_TOOL_MAX_STEPS > 0)) return [3 /*break*/, 47];
2062
2167
  effectiveDirective = collectionOverride
2063
2168
  ? __assign(__assign({}, directive), { payload: __assign(__assign({}, (directive.payload || {})), { collection: collectionOverride.to }) }) : directive;
2064
2169
  toolRequest = buildAssistantToolRequest(effectiveDirective, input);
@@ -2068,21 +2173,21 @@ function executeAiAssistantCodexRun(payload, context) {
2068
2173
  collection: normalizeOptionalString(toolRequest === null || toolRequest === void 0 ? void 0 : toolRequest.collection) || undefined,
2069
2174
  permissionView: normalizeOptionalString(toolRequest === null || toolRequest === void 0 ? void 0 : toolRequest.permissionView) || undefined
2070
2175
  });
2071
- _9.label = 29;
2072
- case 29:
2073
- _9.trys.push([29, 39, , 40]);
2176
+ _13.label = 35;
2177
+ case 35:
2178
+ _13.trys.push([35, 45, , 46]);
2074
2179
  toolStart = Date.now();
2075
- if (!(effectiveDirective.type === 'aggregate')) return [3 /*break*/, 31];
2180
+ if (!(effectiveDirective.type === 'aggregate')) return [3 /*break*/, 37];
2076
2181
  return [4 /*yield*/, executeAiAssistantReportBuilderAggregate(toolRequest, context)];
2077
- case 30:
2078
- _g = _9.sent();
2079
- return [3 /*break*/, 33];
2080
- case 31: return [4 /*yield*/, executeAiAssistantReportBuilderRead(toolRequest, context)];
2081
- case 32:
2082
- _g = _9.sent();
2083
- _9.label = 33;
2084
- case 33:
2085
- toolResponse = _g;
2182
+ case 36:
2183
+ _h = _13.sent();
2184
+ return [3 /*break*/, 39];
2185
+ case 37: return [4 /*yield*/, executeAiAssistantReportBuilderRead(toolRequest, context)];
2186
+ case 38:
2187
+ _h = _13.sent();
2188
+ _13.label = 39;
2189
+ case 39:
2190
+ toolResponse = _h;
2086
2191
  timingBreakdown.toolMs = Date.now() - toolStart;
2087
2192
  toolResponseDebug = (toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.debug) && typeof toolResponse.debug === 'object'
2088
2193
  ? toolResponse.debug
@@ -2097,53 +2202,53 @@ function executeAiAssistantCodexRun(payload, context) {
2097
2202
  progressTracker.push('Drafting response');
2098
2203
  skipFollowupCodex = usedDeterministicHeuristicFastPath
2099
2204
  || isAssistantDeterministicHeuristicDirective(effectiveDirective);
2100
- if (!skipFollowupCodex) return [3 /*break*/, 34];
2205
+ if (!skipFollowupCodex) return [3 /*break*/, 40];
2101
2206
  recordStep('Drafting response: deterministic summary', {
2102
2207
  reason: normalizeOptionalString(effectiveDirective.rawLine) || 'deterministic_heuristic'
2103
2208
  });
2104
2209
  assistantContent = buildAssistantToolFallbackResponse(toolPayload.result);
2105
2210
  assistantContent = applyAssistantDisplayTableToResponse(assistantContent, toolPayload.result.output.display);
2106
- return [3 /*break*/, 38];
2107
- case 34:
2211
+ return [3 /*break*/, 44];
2212
+ case 40:
2108
2213
  recordStep('Drafting response');
2109
2214
  followupPrompt = buildAssistantCodexToolFollowupPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, toolPayload.prompt);
2110
- _9.label = 35;
2111
- case 35:
2112
- _9.trys.push([35, 37, , 38]);
2215
+ _13.label = 41;
2216
+ case 41:
2217
+ _13.trys.push([41, 43, , 44]);
2113
2218
  followupStart = Date.now();
2114
2219
  return [4 /*yield*/, runCodexInWorkerThread(followupPrompt, runOptions, codexConfig, streamProgress)];
2115
- case 36:
2116
- followupText = _9.sent();
2220
+ case 42:
2221
+ followupText = _13.sent();
2117
2222
  accumulateCodexUsage(followupPrompt, followupText);
2118
2223
  timingBreakdown.followupMs = Date.now() - followupStart;
2119
2224
  assistantContent = sanitizeAssistantResponse(followupText);
2120
2225
  assistantContent = applyAssistantDisplayTableToResponse(assistantContent, toolPayload.result.output.display);
2121
- return [3 /*break*/, 38];
2122
- case 37:
2123
- _h = _9.sent();
2226
+ return [3 /*break*/, 44];
2227
+ case 43:
2228
+ _j = _13.sent();
2124
2229
  assistantContent = buildAssistantToolFallbackResponse(toolPayload.result);
2125
- return [3 /*break*/, 38];
2126
- case 38: return [3 /*break*/, 40];
2127
- case 39:
2128
- error_2 = _9.sent();
2129
- assistantContent = buildAssistantToolErrorMessage(error_2);
2130
- toolError = error_2;
2131
- return [3 /*break*/, 40];
2132
- case 40: return [3 /*break*/, 42];
2133
- case 41:
2230
+ return [3 /*break*/, 44];
2231
+ case 44: return [3 /*break*/, 46];
2232
+ case 45:
2233
+ error_3 = _13.sent();
2234
+ assistantContent = buildAssistantToolErrorMessage(error_3);
2235
+ toolError = error_3;
2236
+ return [3 /*break*/, 46];
2237
+ case 46: return [3 /*break*/, 48];
2238
+ case 47:
2134
2239
  progressTracker.push('Drafting response');
2135
2240
  recordStep('Drafting response');
2136
- _9.label = 42;
2137
- case 42: return [3 /*break*/, 45];
2138
- case 43:
2139
- error_3 = _9.sent();
2140
- assistantContent = buildAssistantCodexErrorMessage(error_3);
2141
- recordStep('Error', { message: normalizeOptionalString(error_3 === null || error_3 === void 0 ? void 0 : error_3.message) || 'Unknown error' });
2142
- return [3 /*break*/, 45];
2143
- case 44:
2241
+ _13.label = 48;
2242
+ case 48: return [3 /*break*/, 51];
2243
+ case 49:
2244
+ error_4 = _13.sent();
2245
+ assistantContent = buildAssistantCodexErrorMessage(error_4);
2246
+ recordStep('Error', { message: normalizeOptionalString(error_4 === null || error_4 === void 0 ? void 0 : error_4.message) || 'Unknown error' });
2247
+ return [3 /*break*/, 51];
2248
+ case 50:
2144
2249
  progressTracker.stop();
2145
2250
  return [7 /*endfinally*/];
2146
- case 45:
2251
+ case 51:
2147
2252
  if (!assistantContent) {
2148
2253
  assistantContent = buildAssistantCodexErrorMessage(null);
2149
2254
  }
@@ -2180,7 +2285,9 @@ function executeAiAssistantCodexRun(payload, context) {
2180
2285
  requestTypeSource: requestClassification.source,
2181
2286
  plannerIntentType: requestClassification.plannerIntentType,
2182
2287
  dataQuestion: dataQuestion,
2183
- reportStyleIntent: enforceDatedDirective ? 'dated' : null,
2288
+ reportStyleIntent: enforceDatedDirective
2289
+ ? 'dated'
2290
+ : (enforceGroupedDirective ? 'grouped' : null),
2184
2291
  requestedTimeGrain: requestedTimeGrain,
2185
2292
  datedDirectiveRetryUsed: datedDirectiveRetryUsed,
2186
2293
  datedDirectiveResolved: datedDirectiveResolved,
@@ -2237,14 +2344,14 @@ function executeAiAssistantCodexRun(payload, context) {
2237
2344
  output_tokens: codexUsage.output_tokens,
2238
2345
  total_tokens: codexUsage.total_tokens
2239
2346
  } : null;
2240
- if (!finalUsage) return [3 /*break*/, 50];
2347
+ if (!finalUsage) return [3 /*break*/, 56];
2241
2348
  return [4 /*yield*/, resolveClientId(conversation, input.id_client, context === null || context === void 0 ? void 0 : context.id_user)];
2242
- case 46:
2243
- usageClientId = _9.sent();
2244
- if (!usageClientId) return [3 /*break*/, 50];
2245
- _9.label = 47;
2246
- case 47:
2247
- _9.trys.push([47, 49, , 50]);
2349
+ case 52:
2350
+ usageClientId = _13.sent();
2351
+ if (!usageClientId) return [3 /*break*/, 56];
2352
+ _13.label = 53;
2353
+ case 53:
2354
+ _13.trys.push([53, 55, , 56]);
2248
2355
  return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)({
2249
2356
  id_client: usageClientId,
2250
2357
  model: finalUsage.model,
@@ -2255,16 +2362,16 @@ function executeAiAssistantCodexRun(payload, context) {
2255
2362
  id_request: requestId || undefined,
2256
2363
  id_conversation: conversation._id
2257
2364
  })];
2258
- case 48:
2259
- _9.sent();
2260
- return [3 /*break*/, 50];
2261
- case 49:
2262
- usageError_1 = _9.sent();
2365
+ case 54:
2366
+ _13.sent();
2367
+ return [3 /*break*/, 56];
2368
+ case 55:
2369
+ usageError_1 = _13.sent();
2263
2370
  console.error(new Date(), 'Failed to record codex usage', usageError_1);
2264
- return [3 /*break*/, 50];
2265
- case 50:
2371
+ return [3 /*break*/, 56];
2372
+ case 56:
2266
2373
  finalAssistantDoc = __assign(__assign(__assign(__assign({}, assistantDoc), { _id: assistantMessageId, content: assistantContent, metadata: finalMetadata }), (finalUsage ? { usage: finalUsage } : {})), { updatedAt: finalNow });
2267
- if (!assistantMessageId) return [3 /*break*/, 52];
2374
+ if (!assistantMessageId) return [3 /*break*/, 58];
2268
2375
  setPayload = {
2269
2376
  content: assistantContent,
2270
2377
  metadata: finalMetadata,
@@ -2274,18 +2381,18 @@ function executeAiAssistantCodexRun(payload, context) {
2274
2381
  setPayload.usage = finalUsage;
2275
2382
  }
2276
2383
  return [4 /*yield*/, updateAssistantMessageWithFallback(assistantMessageId, setPayload)];
2277
- case 51:
2278
- _9.sent();
2279
- _9.label = 52;
2280
- case 52: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
2281
- case 53:
2282
- _9.sent();
2283
- if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 55];
2384
+ case 57:
2385
+ _13.sent();
2386
+ _13.label = 58;
2387
+ case 58: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
2388
+ case 59:
2389
+ _13.sent();
2390
+ if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 61];
2284
2391
  return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
2285
- case 54:
2286
- _9.sent();
2287
- _9.label = 55;
2288
- case 55: return [2 /*return*/, finalAssistantDoc];
2392
+ case 60:
2393
+ _13.sent();
2394
+ _13.label = 61;
2395
+ case 61: return [2 /*return*/, finalAssistantDoc];
2289
2396
  }
2290
2397
  });
2291
2398
  }); });
@@ -2316,38 +2423,155 @@ function executeAiAssistantReportBuilderAggregate(payload, context) {
2316
2423
  });
2317
2424
  });
2318
2425
  }
2426
+ function executeAiAssistantReportIssue(payload, context) {
2427
+ return __awaiter(this, void 0, void 0, function () {
2428
+ var input, reason, expected, requestedConversationId, requestedMessageId, conversationId, assistantMessage, messageConversationId, conversation, userPrompt, createdAt, userQuery, userMessage, assistantContent, toolResult, reportMetadata, category, severity, requestId, idClient, _a, idApp, now, doc, insertResult;
2429
+ var _b, _c, _d, _e, _f, _g;
2430
+ return __generator(this, function (_h) {
2431
+ switch (_h.label) {
2432
+ case 0:
2433
+ input = payload || {};
2434
+ reason = normalizeOptionalString(input.reason);
2435
+ expected = normalizeOptionalString(input.expected);
2436
+ if (reason.length < 3) {
2437
+ throw new Error('Issue reason is required.');
2438
+ }
2439
+ requestedConversationId = normalizeOptionalString(input.id_conversation);
2440
+ requestedMessageId = normalizeOptionalString(input.id_message);
2441
+ conversationId = requestedConversationId;
2442
+ assistantMessage = null;
2443
+ if (!requestedMessageId) return [3 /*break*/, 2];
2444
+ return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.findOne({ _id: requestedMessageId })];
2445
+ case 1:
2446
+ assistantMessage = (_h.sent());
2447
+ if (!assistantMessage) {
2448
+ throw new Error('Assistant message not found.');
2449
+ }
2450
+ messageConversationId = normalizeOptionalString(assistantMessage.id_conversation);
2451
+ if (!conversationId) {
2452
+ conversationId = messageConversationId;
2453
+ }
2454
+ else if (messageConversationId && messageConversationId !== conversationId) {
2455
+ throw new Error('Message does not belong to the selected conversation.');
2456
+ }
2457
+ _h.label = 2;
2458
+ case 2:
2459
+ if (!conversationId) {
2460
+ throw new Error('Conversation id is required.');
2461
+ }
2462
+ return [4 /*yield*/, ai_terminal_conversation_collection_1.AiTerminalConversations.findOne({ _id: conversationId })];
2463
+ case 3:
2464
+ conversation = _h.sent();
2465
+ if (!conversation) {
2466
+ throw new Error('Conversation not found.');
2467
+ }
2468
+ if (!!assistantMessage) return [3 /*break*/, 5];
2469
+ return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.findOne({ id_conversation: conversationId, role: 'assistant' }, { sort: { createdAt: -1 } })];
2470
+ case 4:
2471
+ assistantMessage = (_h.sent());
2472
+ _h.label = 5;
2473
+ case 5:
2474
+ userPrompt = '';
2475
+ if (!assistantMessage) return [3 /*break*/, 7];
2476
+ createdAt = (assistantMessage === null || assistantMessage === void 0 ? void 0 : assistantMessage.createdAt) ? new Date(assistantMessage.createdAt) : null;
2477
+ userQuery = {
2478
+ id_conversation: conversationId,
2479
+ role: 'user'
2480
+ };
2481
+ if (createdAt && Number.isFinite(createdAt.getTime())) {
2482
+ userQuery.createdAt = { $lte: createdAt };
2483
+ }
2484
+ return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.findOne(userQuery, { sort: { createdAt: -1 } })];
2485
+ case 6:
2486
+ userMessage = _h.sent();
2487
+ if (userMessage === null || userMessage === void 0 ? void 0 : userMessage.content) {
2488
+ userPrompt = normalizeOptionalString(userMessage.content);
2489
+ }
2490
+ _h.label = 7;
2491
+ case 7:
2492
+ assistantContent = normalizeOptionalString(assistantMessage === null || assistantMessage === void 0 ? void 0 : assistantMessage.content);
2493
+ toolResult = (_b = assistantMessage === null || assistantMessage === void 0 ? void 0 : assistantMessage.metadata) === null || _b === void 0 ? void 0 : _b.tool_result;
2494
+ reportMetadata = (input === null || input === void 0 ? void 0 : input.metadata) && typeof input.metadata === 'object' && !Array.isArray(input.metadata)
2495
+ ? __assign({}, input.metadata) : {};
2496
+ category = normalizeOptionalString(input.category);
2497
+ severity = normalizeOptionalString(input.severity);
2498
+ if (category) {
2499
+ reportMetadata.category = category;
2500
+ }
2501
+ if (severity) {
2502
+ reportMetadata.severity = severity;
2503
+ }
2504
+ requestId = normalizeOptionalString(input.request_id)
2505
+ || normalizeOptionalString((_c = assistantMessage === null || assistantMessage === void 0 ? void 0 : assistantMessage.metadata) === null || _c === void 0 ? void 0 : _c.request_id);
2506
+ _a = normalizeOptionalString(input.id_client)
2507
+ || normalizeOptionalString(conversation === null || conversation === void 0 ? void 0 : conversation.id_client);
2508
+ if (_a) return [3 /*break*/, 9];
2509
+ return [4 /*yield*/, resolveClientIdFromConfig(undefined, context === null || context === void 0 ? void 0 : context.id_user)];
2510
+ case 8:
2511
+ _a = (_h.sent());
2512
+ _h.label = 9;
2513
+ case 9:
2514
+ idClient = _a;
2515
+ idApp = normalizeOptionalString(input.id_app)
2516
+ || normalizeOptionalString(conversation === null || conversation === void 0 ? void 0 : conversation.id_app);
2517
+ now = new Date();
2518
+ doc = __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({ id_conversation: conversationId, status: 'open', source: 'user_report', reason: reason }, (expected ? { expected_outcome: expected } : {})), (userPrompt ? { user_prompt: userPrompt } : {})), (assistantContent ? { assistant_content: assistantContent } : {})), (requestId ? { request_id: requestId } : {})), ((toolResult === null || toolResult === void 0 ? void 0 : toolResult.type) ? { tool_type: normalizeOptionalString(toolResult.type) } : {})), (((_d = toolResult === null || toolResult === void 0 ? void 0 : toolResult.output) === null || _d === void 0 ? void 0 : _d.collection) || ((_e = toolResult === null || toolResult === void 0 ? void 0 : toolResult.input) === null || _e === void 0 ? void 0 : _e.collection)
2519
+ ? { tool_collection: normalizeOptionalString(((_f = toolResult === null || toolResult === void 0 ? void 0 : toolResult.output) === null || _f === void 0 ? void 0 : _f.collection) || ((_g = toolResult === null || toolResult === void 0 ? void 0 : toolResult.input) === null || _g === void 0 ? void 0 : _g.collection)) }
2520
+ : {})), (requestedMessageId || (assistantMessage === null || assistantMessage === void 0 ? void 0 : assistantMessage._id) ? { id_message: normalizeOptionalString(requestedMessageId || (assistantMessage === null || assistantMessage === void 0 ? void 0 : assistantMessage._id)) } : {})), (idClient ? { id_client: idClient } : {})), (idApp ? { id_app: idApp } : {})), (normalizeOptionalString(context === null || context === void 0 ? void 0 : context.id_user) ? { id_user: normalizeOptionalString(context.id_user) } : {})), (Object.keys(reportMetadata).length ? { metadata: reportMetadata } : {})), { createdAt: now, updatedAt: now });
2521
+ return [4 /*yield*/, ai_terminal_issue_report_collection_1.AiTerminalIssueReports.insertOne(doc)];
2522
+ case 10:
2523
+ insertResult = _h.sent();
2524
+ return [2 /*return*/, {
2525
+ id_issue_report: insertResult._id,
2526
+ id_conversation: conversationId,
2527
+ id_message: normalizeOptionalString(doc.id_message),
2528
+ status: 'open'
2529
+ }];
2530
+ }
2531
+ });
2532
+ });
2533
+ }
2319
2534
  function executeAiAssistantMongoRead(payload, context) {
2320
2535
  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) {
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;
2537
+ var e_1, _p;
2538
+ var _q, _r;
2539
+ return __generator(this, function (_s) {
2540
+ switch (_s.label) {
2325
2541
  case 0:
2326
2542
  input = payload || {};
2327
2543
  rawCollection = normalizeOptionalString(input.collection);
2328
2544
  if (!rawCollection) {
2329
2545
  throw new Error('AI assistant report builder bridge: Collection is required.');
2330
2546
  }
2547
+ retryState = input.__assistantRetryState && typeof input.__assistantRetryState === 'object'
2548
+ ? input.__assistantRetryState
2549
+ : {};
2550
+ triedCollections = buildAssistantTriedCollectionSet(retryState.triedCollections);
2551
+ addAssistantCollectionToTriedSet(triedCollections, rawCollection);
2552
+ crossCollectionRetryEnabled = retryState.disableCrossCollectionRetry !== true;
2331
2553
  dbName = resolveAssistantDatabaseName(input.database, input.mongo);
2332
2554
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
2333
2555
  return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
2334
2556
  case 1:
2335
- collectionResolution = _q.sent();
2557
+ collectionResolution = _s.sent();
2336
2558
  collection = collectionResolution.name || rawCollection;
2337
2559
  return [4 /*yield*/, resolveAssistantReportBuilderBridgeCollection(collection, db, dbName)];
2338
2560
  case 2:
2339
- bridgeCollection = _q.sent();
2561
+ bridgeCollection = _s.sent();
2340
2562
  if (bridgeCollection.fallbackFrom) {
2341
2563
  collection = bridgeCollection.collection;
2342
2564
  }
2565
+ addAssistantCollectionToTriedSet(triedCollections, collection);
2566
+ retryRootCollection = normalizeOptionalString(retryState.rootCollection) || collection;
2343
2567
  schemaFields = getCollectionSchemaFieldNames(collection);
2344
2568
  return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
2345
2569
  case 3:
2346
- _a = _q.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
2570
+ _a = _s.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
2347
2571
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
2348
2572
  throw new Error('AI assistant report builder bridge: Access denied.');
2349
2573
  }
2350
- customerId = normalizeOptionalString((_o = user === null || user === void 0 ? void 0 : user.other) === null || _o === void 0 ? void 0 : _o.id_customer);
2574
+ customerId = normalizeOptionalString((_q = user === null || user === void 0 ? void 0 : user.other) === null || _q === void 0 ? void 0 : _q.id_customer);
2351
2575
  fallbackMeta = {};
2352
2576
  if (bridgeCollection.fallbackFrom) {
2353
2577
  fallbackMeta.reportBuilderBridge = {
@@ -2379,11 +2603,11 @@ function executeAiAssistantMongoRead(payload, context) {
2379
2603
  if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 5];
2380
2604
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
2381
2605
  case 4:
2382
- _b = _q.sent();
2606
+ _b = _s.sent();
2383
2607
  return [3 /*break*/, 6];
2384
2608
  case 5:
2385
2609
  _b = false;
2386
- _q.label = 6;
2610
+ _s.label = 6;
2387
2611
  case 6:
2388
2612
  shouldScopeByClient = _b;
2389
2613
  if (!isSuperAdmin && shouldScopeByClient) {
@@ -2403,7 +2627,7 @@ function executeAiAssistantMongoRead(payload, context) {
2403
2627
  findOptions = __assign(__assign({}, normalized.findOptions), { readPreference: AI_ASSISTANT_READ_PREFERENCE });
2404
2628
  return [4 /*yield*/, db.collection(collection).find(scopedQuery, findOptions).toArray()];
2405
2629
  case 7:
2406
- documents = _q.sent();
2630
+ documents = _s.sent();
2407
2631
  executedQuery = scopedQuery;
2408
2632
  probeDocs = null;
2409
2633
  if (!!documents.length) return [3 /*break*/, 9];
@@ -2413,13 +2637,13 @@ function executeAiAssistantMongoRead(payload, context) {
2413
2637
  fallbackMeta.dateField = __assign(__assign({}, dateFallback), { attempted: true, used: false });
2414
2638
  return [4 /*yield*/, db.collection(collection).find(fallbackQuery, findOptions).toArray()];
2415
2639
  case 8:
2416
- fallbackDocs = _q.sent();
2640
+ fallbackDocs = _s.sent();
2417
2641
  if (fallbackDocs.length) {
2418
2642
  documents = fallbackDocs;
2419
2643
  executedQuery = fallbackQuery;
2420
2644
  fallbackMeta.dateField.used = true;
2421
2645
  }
2422
- _q.label = 9;
2646
+ _s.label = 9;
2423
2647
  case 9:
2424
2648
  if (!!documents.length) return [3 /*break*/, 11];
2425
2649
  expanded = expandQueryDateFallbacks(executedQuery, schemaFields);
@@ -2431,13 +2655,13 @@ function executeAiAssistantMongoRead(payload, context) {
2431
2655
  };
2432
2656
  return [4 /*yield*/, db.collection(collection).find(expanded.query, findOptions).toArray()];
2433
2657
  case 10:
2434
- fallbackDocs = _q.sent();
2658
+ fallbackDocs = _s.sent();
2435
2659
  if (fallbackDocs.length) {
2436
2660
  documents = fallbackDocs;
2437
2661
  executedQuery = expanded.query;
2438
2662
  fallbackMeta.dateFieldsExpanded.used = true;
2439
2663
  }
2440
- _q.label = 11;
2664
+ _s.label = 11;
2441
2665
  case 11:
2442
2666
  if (!!documents.length) return [3 /*break*/, 13];
2443
2667
  nameFallback = resolveReadNameMatchFallback(executedQuery);
@@ -2450,13 +2674,13 @@ function executeAiAssistantMongoRead(payload, context) {
2450
2674
  };
2451
2675
  return [4 /*yield*/, db.collection(collection).find(nameFallback.query, findOptions).toArray()];
2452
2676
  case 12:
2453
- fallbackDocs = _q.sent();
2677
+ fallbackDocs = _s.sent();
2454
2678
  if (fallbackDocs.length) {
2455
2679
  documents = fallbackDocs;
2456
2680
  executedQuery = nameFallback.query;
2457
2681
  fallbackMeta.nameMatch.used = true;
2458
2682
  }
2459
- _q.label = 13;
2683
+ _s.label = 13;
2460
2684
  case 13:
2461
2685
  if (!!documents.length) return [3 /*break*/, 18];
2462
2686
  _c = probeDocs;
@@ -2470,8 +2694,8 @@ function executeAiAssistantMongoRead(payload, context) {
2470
2694
  includeClientScope: shouldScopeByClient
2471
2695
  })];
2472
2696
  case 14:
2473
- _c = (_q.sent());
2474
- _q.label = 15;
2697
+ _c = (_s.sent());
2698
+ _s.label = 15;
2475
2699
  case 15:
2476
2700
  probeDocs = _c;
2477
2701
  return [4 /*yield*/, applyChemicalNameLookupFallbackToQuery({
@@ -2484,18 +2708,18 @@ function executeAiAssistantMongoRead(payload, context) {
2484
2708
  probeDocs: probeDocs || undefined
2485
2709
  })];
2486
2710
  case 16:
2487
- chemicalLookup = _q.sent();
2711
+ chemicalLookup = _s.sent();
2488
2712
  if (!chemicalLookup) return [3 /*break*/, 18];
2489
2713
  fallbackMeta.chemicalLookup = __assign(__assign({}, chemicalLookup.meta), { attempted: true, used: false });
2490
2714
  return [4 /*yield*/, db.collection(collection).find(chemicalLookup.query, findOptions).toArray()];
2491
2715
  case 17:
2492
- fallbackDocs = _q.sent();
2716
+ fallbackDocs = _s.sent();
2493
2717
  if (fallbackDocs.length) {
2494
2718
  documents = fallbackDocs;
2495
2719
  executedQuery = chemicalLookup.query;
2496
2720
  fallbackMeta.chemicalLookup.used = true;
2497
2721
  }
2498
- _q.label = 18;
2722
+ _s.label = 18;
2499
2723
  case 18:
2500
2724
  if (!!documents.length) return [3 /*break*/, 22];
2501
2725
  queryFields = extractQueryFieldPaths(executedQuery).filter(function (field) { return !isAssistantIdField(field); });
@@ -2511,8 +2735,8 @@ function executeAiAssistantMongoRead(payload, context) {
2511
2735
  includeClientScope: shouldScopeByClient
2512
2736
  })];
2513
2737
  case 19:
2514
- _d = (_q.sent());
2515
- _q.label = 20;
2738
+ _d = (_s.sent());
2739
+ _s.label = 20;
2516
2740
  case 20:
2517
2741
  probeDocs = _d;
2518
2742
  if (!probeDocs.length) return [3 /*break*/, 22];
@@ -2530,15 +2754,15 @@ function executeAiAssistantMongoRead(payload, context) {
2530
2754
  }, executedQuery);
2531
2755
  return [4 /*yield*/, db.collection(collection).find(rewrittenQuery, findOptions).toArray()];
2532
2756
  case 21:
2533
- fallbackDocs = _q.sent();
2757
+ fallbackDocs = _s.sent();
2534
2758
  if (fallbackDocs.length) {
2535
2759
  documents = fallbackDocs;
2536
2760
  executedQuery = rewrittenQuery;
2537
2761
  fallbackMeta.queryFieldAliases.used = true;
2538
2762
  }
2539
- _q.label = 22;
2763
+ _s.label = 22;
2540
2764
  case 22:
2541
- if (!!documents.length) return [3 /*break*/, 27];
2765
+ if (!!documents.length) return [3 /*break*/, 26];
2542
2766
  _e = probeDocs;
2543
2767
  if (_e) return [3 /*break*/, 24];
2544
2768
  return [4 /*yield*/, fetchAssistantProbeDocs({
@@ -2550,10 +2774,44 @@ function executeAiAssistantMongoRead(payload, context) {
2550
2774
  includeClientScope: shouldScopeByClient
2551
2775
  })];
2552
2776
  case 23:
2553
- _e = (_q.sent());
2554
- _q.label = 24;
2777
+ _e = (_s.sent());
2778
+ _s.label = 24;
2555
2779
  case 24:
2556
2780
  probeDocs = _e;
2781
+ activeFallback = resolveReadActiveStatusFallback(executedQuery, probeDocs || []);
2782
+ if (!activeFallback) return [3 /*break*/, 26];
2783
+ fallbackMeta.activeStatus = {
2784
+ fields: activeFallback.fields,
2785
+ attempted: true,
2786
+ used: false,
2787
+ reason: 'active_fields_missing_in_collection'
2788
+ };
2789
+ return [4 /*yield*/, db.collection(collection).find(activeFallback.query, findOptions).toArray()];
2790
+ case 25:
2791
+ fallbackDocs = _s.sent();
2792
+ if (fallbackDocs.length) {
2793
+ documents = fallbackDocs;
2794
+ executedQuery = activeFallback.query;
2795
+ fallbackMeta.activeStatus.used = true;
2796
+ }
2797
+ _s.label = 26;
2798
+ case 26:
2799
+ if (!!documents.length) return [3 /*break*/, 31];
2800
+ _f = probeDocs;
2801
+ if (_f) return [3 /*break*/, 28];
2802
+ return [4 /*yield*/, fetchAssistantProbeDocs({
2803
+ db: db,
2804
+ collection: collection,
2805
+ idClient: normalizedClient,
2806
+ idCustomer: customerId,
2807
+ isSuperAdmin: isSuperAdmin,
2808
+ includeClientScope: shouldScopeByClient
2809
+ })];
2810
+ case 27:
2811
+ _f = (_s.sent());
2812
+ _s.label = 28;
2813
+ case 28:
2814
+ probeDocs = _f;
2557
2815
  return [4 /*yield*/, applyIdLookupFallbackToQuery({
2558
2816
  query: executedQuery,
2559
2817
  db: db,
@@ -2563,29 +2821,32 @@ function executeAiAssistantMongoRead(payload, context) {
2563
2821
  isSuperAdmin: isSuperAdmin,
2564
2822
  probeDocs: probeDocs || undefined
2565
2823
  })];
2566
- case 25:
2567
- idLookup = _q.sent();
2568
- if (!idLookup) return [3 /*break*/, 27];
2824
+ case 29:
2825
+ idLookup = _s.sent();
2826
+ if (!idLookup) return [3 /*break*/, 31];
2569
2827
  fallbackMeta.idLookup = __assign(__assign({}, idLookup.meta), { attempted: true, used: false });
2570
2828
  return [4 /*yield*/, db.collection(collection).find(idLookup.query, findOptions).toArray()];
2571
- case 26:
2572
- fallbackDocs = _q.sent();
2829
+ case 30:
2830
+ fallbackDocs = _s.sent();
2573
2831
  if (fallbackDocs.length) {
2574
2832
  documents = fallbackDocs;
2575
2833
  executedQuery = idLookup.query;
2576
2834
  fallbackMeta.idLookup.used = true;
2577
2835
  }
2578
- _q.label = 27;
2579
- case 27:
2580
- if (!!documents.length) return [3 /*break*/, 30];
2836
+ _s.label = 31;
2837
+ case 31:
2838
+ if (!!documents.length) return [3 /*break*/, 34];
2581
2839
  return [4 /*yield*/, resolveBaseCollectionFromReport(db, dbName, collection)];
2582
- case 28:
2583
- baseCollection = _q.sent();
2584
- if (!(baseCollection && baseCollection !== collection)) return [3 /*break*/, 30];
2585
- fallbackPayload = __assign(__assign({}, input), { collection: baseCollection });
2840
+ case 32:
2841
+ baseCollection = _s.sent();
2842
+ if (!(baseCollection && baseCollection !== collection)) return [3 /*break*/, 34];
2843
+ addAssistantCollectionToTriedSet(triedCollections, baseCollection);
2844
+ fallbackPayload = __assign(__assign({}, input), { collection: baseCollection, __assistantRetryState: buildAssistantRetryState(retryState, triedCollections, {
2845
+ rootCollection: retryRootCollection
2846
+ }) });
2586
2847
  return [4 /*yield*/, executeAiAssistantMongoRead(fallbackPayload, context)];
2587
- case 29:
2588
- fallbackResult = _q.sent();
2848
+ case 33:
2849
+ fallbackResult = _s.sent();
2589
2850
  if (Array.isArray(fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.documents) && fallbackResult.documents.length) {
2590
2851
  if (isSuperAdmin && (fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.debug) && typeof fallbackResult.debug === 'object') {
2591
2852
  existingFallbacks = fallbackResult.debug.fallbacks && typeof fallbackResult.debug.fallbacks === 'object'
@@ -2602,9 +2863,68 @@ function executeAiAssistantMongoRead(payload, context) {
2602
2863
  if (isSuperAdmin) {
2603
2864
  fallbackMeta.reportFallback = { from: collection, to: baseCollection, attempted: true, used: false };
2604
2865
  }
2605
- _q.label = 30;
2606
- case 30:
2607
- if (!(!documents.length && isSuperAdmin)) return [3 /*break*/, 47];
2866
+ _s.label = 34;
2867
+ case 34:
2868
+ if (!(!documents.length && crossCollectionRetryEnabled)) return [3 /*break*/, 43];
2869
+ return [4 /*yield*/, resolveAssistantAvailableCrossCollectionFallbacks(db, dbName, collection, triedCollections)];
2870
+ case 35:
2871
+ crossCollectionCandidates = _s.sent();
2872
+ if (!crossCollectionCandidates.length) return [3 /*break*/, 43];
2873
+ fallbackMeta.collectionRetry = {
2874
+ from: collection,
2875
+ root: retryRootCollection,
2876
+ tried: crossCollectionCandidates,
2877
+ attempted: true,
2878
+ used: false
2879
+ };
2880
+ _s.label = 36;
2881
+ case 36:
2882
+ _s.trys.push([36, 41, 42, 43]);
2883
+ crossCollectionCandidates_1 = __values(crossCollectionCandidates), crossCollectionCandidates_1_1 = crossCollectionCandidates_1.next();
2884
+ _s.label = 37;
2885
+ case 37:
2886
+ if (!!crossCollectionCandidates_1_1.done) return [3 /*break*/, 40];
2887
+ candidateCollection = crossCollectionCandidates_1_1.value;
2888
+ addAssistantCollectionToTriedSet(triedCollections, candidateCollection);
2889
+ fallbackPayload = __assign(__assign({}, input), { collection: candidateCollection, __assistantRetryState: buildAssistantRetryState(retryState, triedCollections, {
2890
+ rootCollection: retryRootCollection,
2891
+ disableCrossCollectionRetry: true
2892
+ }) });
2893
+ return [4 /*yield*/, executeAiAssistantMongoRead(fallbackPayload, context)];
2894
+ case 38:
2895
+ fallbackResult = _s.sent();
2896
+ if (Array.isArray(fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.documents) && fallbackResult.documents.length) {
2897
+ if (isSuperAdmin && (fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.debug) && typeof fallbackResult.debug === 'object') {
2898
+ existingFallbacks = fallbackResult.debug.fallbacks && typeof fallbackResult.debug.fallbacks === 'object'
2899
+ ? fallbackResult.debug.fallbacks
2900
+ : {};
2901
+ fallbackResult.debug.fallbacks = __assign(__assign({}, existingFallbacks), { collectionRetry: {
2902
+ from: collection,
2903
+ to: candidateCollection,
2904
+ root: retryRootCollection,
2905
+ tried: crossCollectionCandidates,
2906
+ used: true
2907
+ } });
2908
+ }
2909
+ return [2 /*return*/, fallbackResult];
2910
+ }
2911
+ _s.label = 39;
2912
+ case 39:
2913
+ crossCollectionCandidates_1_1 = crossCollectionCandidates_1.next();
2914
+ return [3 /*break*/, 37];
2915
+ case 40: return [3 /*break*/, 43];
2916
+ case 41:
2917
+ e_1_1 = _s.sent();
2918
+ e_1 = { error: e_1_1 };
2919
+ return [3 /*break*/, 43];
2920
+ case 42:
2921
+ try {
2922
+ if (crossCollectionCandidates_1_1 && !crossCollectionCandidates_1_1.done && (_p = crossCollectionCandidates_1.return)) _p.call(crossCollectionCandidates_1);
2923
+ }
2924
+ finally { if (e_1) throw e_1.error; }
2925
+ return [7 /*endfinally*/];
2926
+ case 43:
2927
+ if (!(!documents.length && isSuperAdmin)) return [3 /*break*/, 60];
2608
2928
  nameFields = collectMatchFieldsByCondition(executedQuery, function (field, condition) { return isRegexMatchCondition(condition)
2609
2929
  || (typeof condition === 'string' && shouldApplyAssistantNameRegex(field)); });
2610
2930
  dateFields = collectMatchFieldsByCondition(executedQuery, function (_field, condition) { return isDateCondition(condition); });
@@ -2612,36 +2932,36 @@ function executeAiAssistantMongoRead(payload, context) {
2612
2932
  nameFields: nameFields.length ? nameFields : undefined,
2613
2933
  dateFields: dateFields.length ? dateFields : undefined
2614
2934
  };
2615
- _q.label = 31;
2616
- case 31:
2617
- _q.trys.push([31, 36, , 37]);
2618
- if (!nameFields.length) return [3 /*break*/, 33];
2935
+ _s.label = 44;
2936
+ case 44:
2937
+ _s.trys.push([44, 49, , 50]);
2938
+ if (!nameFields.length) return [3 /*break*/, 46];
2619
2939
  queryNoName = stripMatchFields(executedQuery, nameFields);
2620
- _f = diagnostics;
2940
+ _g = diagnostics;
2621
2941
  return [4 /*yield*/, db.collection(collection).countDocuments(queryNoName, {
2622
2942
  readPreference: AI_ASSISTANT_READ_PREFERENCE
2623
2943
  })];
2624
- case 32:
2625
- _f.recentCount = _q.sent();
2626
- _q.label = 33;
2627
- case 33:
2628
- if (!dateFields.length) return [3 /*break*/, 35];
2944
+ case 45:
2945
+ _g.recentCount = _s.sent();
2946
+ _s.label = 46;
2947
+ case 46:
2948
+ if (!dateFields.length) return [3 /*break*/, 48];
2629
2949
  queryNoDate = stripMatchFields(executedQuery, dateFields);
2630
- _g = diagnostics;
2950
+ _h = diagnostics;
2631
2951
  return [4 /*yield*/, db.collection(collection).countDocuments(queryNoDate, {
2632
2952
  readPreference: AI_ASSISTANT_READ_PREFERENCE
2633
2953
  })];
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];
2954
+ case 47:
2955
+ _h.nameMatchCount = _s.sent();
2956
+ _s.label = 48;
2957
+ case 48: return [3 /*break*/, 50];
2958
+ case 49:
2959
+ _j = _s.sent();
2960
+ return [3 /*break*/, 50];
2961
+ case 50:
2962
+ _s.trys.push([50, 53, , 54]);
2963
+ _k = probeDocs;
2964
+ if (_k) return [3 /*break*/, 52];
2645
2965
  return [4 /*yield*/, fetchAssistantProbeDocs({
2646
2966
  db: db,
2647
2967
  collection: collection,
@@ -2650,56 +2970,56 @@ function executeAiAssistantMongoRead(payload, context) {
2650
2970
  isSuperAdmin: isSuperAdmin,
2651
2971
  includeClientScope: shouldScopeByClient
2652
2972
  })];
2653
- case 38:
2654
- _j = (_q.sent());
2655
- _q.label = 39;
2656
- case 39:
2657
- probeDocs = _j;
2973
+ case 51:
2974
+ _k = (_s.sent());
2975
+ _s.label = 52;
2976
+ case 52:
2977
+ probeDocs = _k;
2658
2978
  if (probeDocs.length && nameFields.length) {
2659
2979
  diagnostics.chemicalIdDetected = detectChemicalIdFromProbe(probeDocs, nameFields);
2660
2980
  }
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]);
2981
+ return [3 /*break*/, 54];
2982
+ case 53:
2983
+ _l = _s.sent();
2984
+ return [3 /*break*/, 54];
2985
+ case 54:
2986
+ _s.trys.push([54, 58, , 59]);
2667
2987
  return [4 /*yield*/, listAssistantCollections(db, dbName)];
2668
- case 42:
2669
- allCollections = _q.sent();
2988
+ case 55:
2989
+ allCollections = _s.sent();
2670
2990
  base = stripVersionSuffix(collection.startsWith('report-') ? collection.slice('report-'.length) : collection);
2671
2991
  alt = collection.startsWith('report-') ? base : "report-".concat(base);
2672
- if (!(alt && alt !== collection && allCollections.includes(alt))) return [3 /*break*/, 44];
2992
+ if (!(alt && alt !== collection && allCollections.includes(alt))) return [3 /*break*/, 57];
2673
2993
  return [4 /*yield*/, db.collection(alt).countDocuments({}, { readPreference: AI_ASSISTANT_READ_PREFERENCE })];
2674
- case 43:
2675
- altCount = _q.sent();
2994
+ case 56:
2995
+ altCount = _s.sent();
2676
2996
  diagnostics.alternateCollection = alt;
2677
2997
  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:
2998
+ _s.label = 57;
2999
+ case 57: return [3 /*break*/, 59];
3000
+ case 58:
3001
+ _m = _s.sent();
3002
+ return [3 /*break*/, 59];
3003
+ case 59:
2684
3004
  fallbackMeta.zeroDiagnostics = diagnostics;
2685
- _q.label = 47;
2686
- case 47:
3005
+ _s.label = 60;
3006
+ case 60:
2687
3007
  total = null;
2688
- if (!normalized.includeTotal) return [3 /*break*/, 49];
3008
+ if (!normalized.includeTotal) return [3 /*break*/, 62];
2689
3009
  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:
3010
+ case 61:
3011
+ total = _s.sent();
3012
+ _s.label = 62;
3013
+ case 62:
2694
3014
  sanitizedDocuments = isSuperAdmin
2695
3015
  ? documents
2696
3016
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
2697
3017
  requestedFields = resolveProjectionRequestedFields(findOptions.projection);
2698
- if (!(sanitizedDocuments.length && requestedFields.length)) return [3 /*break*/, 53];
3018
+ if (!(sanitizedDocuments.length && requestedFields.length)) return [3 /*break*/, 66];
2699
3019
  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];
3020
+ if (!missingFields.length) return [3 /*break*/, 66];
3021
+ _o = probeDocs;
3022
+ if (_o) return [3 /*break*/, 64];
2703
3023
  return [4 /*yield*/, fetchAssistantProbeDocs({
2704
3024
  db: db,
2705
3025
  collection: collection,
@@ -2708,26 +3028,26 @@ function executeAiAssistantMongoRead(payload, context) {
2708
3028
  isSuperAdmin: isSuperAdmin,
2709
3029
  includeClientScope: shouldScopeByClient
2710
3030
  })];
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];
3031
+ case 63:
3032
+ _o = (_s.sent());
3033
+ _s.label = 64;
3034
+ case 64:
3035
+ probeDocs = _o;
3036
+ if (!probeDocs.length) return [3 /*break*/, 66];
2717
3037
  projectionAliases = resolveFieldAliases(probeDocs, missingFields, schemaFields);
2718
- if (!Object.keys(projectionAliases).length) return [3 /*break*/, 53];
3038
+ if (!Object.keys(projectionAliases).length) return [3 /*break*/, 66];
2719
3039
  fallbackMeta.projectionAliases = {
2720
3040
  aliases: projectionAliases,
2721
3041
  attempted: true,
2722
3042
  used: false
2723
3043
  };
2724
3044
  expandedProjection = expandProjectionWithAliases(findOptions.projection, projectionAliases);
2725
- if (!(expandedProjection && expandedProjection !== findOptions.projection)) return [3 /*break*/, 53];
3045
+ if (!(expandedProjection && expandedProjection !== findOptions.projection)) return [3 /*break*/, 66];
2726
3046
  findOptions = __assign(__assign({}, findOptions), { projection: expandedProjection });
2727
3047
  normalized.findOptions.projection = expandedProjection;
2728
3048
  return [4 /*yield*/, db.collection(collection).find(executedQuery, findOptions).toArray()];
2729
- case 52:
2730
- refreshedDocs = _q.sent();
3049
+ case 65:
3050
+ refreshedDocs = _s.sent();
2731
3051
  if (refreshedDocs.length) {
2732
3052
  documents = refreshedDocs;
2733
3053
  sanitizedDocuments = isSuperAdmin
@@ -2735,9 +3055,9 @@ function executeAiAssistantMongoRead(payload, context) {
2735
3055
  : refreshedDocs.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
2736
3056
  fallbackMeta.projectionAliases.used = true;
2737
3057
  }
2738
- _q.label = 53;
2739
- case 53:
2740
- includeIds = ((_p = input.options) === null || _p === void 0 ? void 0 : _p.includeIds) === true;
3058
+ _s.label = 66;
3059
+ case 66:
3060
+ includeIds = ((_r = input.options) === null || _r === void 0 ? void 0 : _r.includeIds) === true;
2741
3061
  fieldAliases = resolveFieldAliases(sanitizedDocuments, requestedFields, schemaFields);
2742
3062
  displayDocs = Object.keys(fieldAliases).length
2743
3063
  ? applyFieldAliasesForDisplay(sanitizedDocuments, fieldAliases)
@@ -2751,8 +3071,8 @@ function executeAiAssistantMongoRead(payload, context) {
2751
3071
  idCustomer: customerId,
2752
3072
  isSuperAdmin: isSuperAdmin
2753
3073
  })];
2754
- case 54:
2755
- idLookupDisplay = _q.sent();
3074
+ case 67:
3075
+ idLookupDisplay = _s.sent();
2756
3076
  if (idLookupDisplay === null || idLookupDisplay === void 0 ? void 0 : idLookupDisplay.docs) {
2757
3077
  displayDocs = idLookupDisplay.docs;
2758
3078
  }
@@ -2761,10 +3081,11 @@ function executeAiAssistantMongoRead(payload, context) {
2761
3081
  }
2762
3082
  priorityFields = requestedFields.length
2763
3083
  ? __spreadArray(__spreadArray([], __read(requestedFields), false), __read(AI_ASSISTANT_DISPLAY_PRIORITY_FIELDS), false) : AI_ASSISTANT_DISPLAY_PRIORITY_FIELDS;
3084
+ displayMaxRows = resolveAssistantReadDisplayMaxRows(normalized.findOptions.limit, sanitizedDocuments.length);
2764
3085
  display = buildDisplayTable(displayDocs, {
2765
3086
  includeIds: includeIds,
2766
3087
  maxColumns: AI_ASSISTANT_DISPLAY_MAX_COLUMNS,
2767
- maxRows: normalized.findOptions.limit,
3088
+ maxRows: displayMaxRows,
2768
3089
  priorityFields: priorityFields,
2769
3090
  includeGroupFromId: false
2770
3091
  });
@@ -2796,37 +3117,46 @@ function executeAiAssistantMongoRead(payload, context) {
2796
3117
  }
2797
3118
  function executeAiAssistantMongoAggregate(payload, context) {
2798
3119
  return __awaiter(this, void 0, void 0, function () {
2799
- var input, rawCollection, dbName, db, collectionResolution, collection, bridgeCollection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, sanitizedPipeline, strippedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, 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, matchStages, diagnostics, combinedMatch, nameFields, dateFields, queryNoName, _g, queryNoDate, _h, _j, _k, _l, allCollections, base, alt, altCount, _m, verification, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
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;
3121
+ var e_2, _o;
2800
3122
  var _this = this;
2801
- var _o, _p;
2802
- return __generator(this, function (_q) {
2803
- switch (_q.label) {
3123
+ var _p, _q;
3124
+ return __generator(this, function (_r) {
3125
+ switch (_r.label) {
2804
3126
  case 0:
2805
3127
  input = payload || {};
2806
3128
  rawCollection = normalizeOptionalString(input.collection);
2807
3129
  if (!rawCollection) {
2808
3130
  throw new Error('AI assistant report builder bridge: Collection is required.');
2809
3131
  }
3132
+ retryState = input.__assistantRetryState && typeof input.__assistantRetryState === 'object'
3133
+ ? input.__assistantRetryState
3134
+ : {};
3135
+ triedCollections = buildAssistantTriedCollectionSet(retryState.triedCollections);
3136
+ addAssistantCollectionToTriedSet(triedCollections, rawCollection);
3137
+ crossCollectionRetryEnabled = retryState.disableCrossCollectionRetry !== true;
2810
3138
  dbName = resolveAssistantDatabaseName(input.database, input.mongo);
2811
3139
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
2812
3140
  return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
2813
3141
  case 1:
2814
- collectionResolution = _q.sent();
3142
+ collectionResolution = _r.sent();
2815
3143
  collection = collectionResolution.name || rawCollection;
2816
3144
  return [4 /*yield*/, resolveAssistantReportBuilderBridgeCollection(collection, db, dbName)];
2817
3145
  case 2:
2818
- bridgeCollection = _q.sent();
3146
+ bridgeCollection = _r.sent();
2819
3147
  if (bridgeCollection.fallbackFrom) {
2820
3148
  collection = bridgeCollection.collection;
2821
3149
  }
3150
+ addAssistantCollectionToTriedSet(triedCollections, collection);
3151
+ retryRootCollection = normalizeOptionalString(retryState.rootCollection) || collection;
2822
3152
  schemaFields = getCollectionSchemaFieldNames(collection);
2823
3153
  return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
2824
3154
  case 3:
2825
- _a = _q.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
3155
+ _a = _r.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
2826
3156
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
2827
3157
  throw new Error('AI assistant report builder bridge: Access denied.');
2828
3158
  }
2829
- customerId = normalizeOptionalString((_o = user === null || user === void 0 ? void 0 : user.other) === null || _o === void 0 ? void 0 : _o.id_customer);
3159
+ customerId = normalizeOptionalString((_p = user === null || user === void 0 ? void 0 : user.other) === null || _p === void 0 ? void 0 : _p.id_customer);
2830
3160
  fallbackMeta = {};
2831
3161
  if (bridgeCollection.fallbackFrom) {
2832
3162
  fallbackMeta.reportBuilderBridge = {
@@ -2858,11 +3188,11 @@ function executeAiAssistantMongoAggregate(payload, context) {
2858
3188
  if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 5];
2859
3189
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
2860
3190
  case 4:
2861
- _b = _q.sent();
3191
+ _b = _r.sent();
2862
3192
  return [3 /*break*/, 6];
2863
3193
  case 5:
2864
3194
  _b = false;
2865
- _q.label = 6;
3195
+ _r.label = 6;
2866
3196
  case 6:
2867
3197
  shouldScopeByClient = _b;
2868
3198
  clientScopedQuery = shouldScopeByClient
@@ -2890,7 +3220,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
2890
3220
  }
2891
3221
  aggregateOptions = __assign(__assign({}, normalizedOptions.aggregateOptions), { readPreference: AI_ASSISTANT_READ_PREFERENCE });
2892
3222
  runAggregateWithRepair = function (pipeline, stage) { return __awaiter(_this, void 0, void 0, function () {
2893
- var docs, error_4, repaired, docs;
3223
+ var docs, error_5, repaired, docs;
2894
3224
  return __generator(this, function (_a) {
2895
3225
  switch (_a.label) {
2896
3226
  case 0:
@@ -2902,13 +3232,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2902
3232
  docs = _a.sent();
2903
3233
  return [2 /*return*/, { documents: docs, pipeline: pipeline }];
2904
3234
  case 2:
2905
- error_4 = _a.sent();
2906
- if (!isAssistantDateArithmeticArgumentError(error_4)) {
2907
- throw error_4;
3235
+ error_5 = _a.sent();
3236
+ if (!isAssistantDateArithmeticArgumentError(error_5)) {
3237
+ throw error_5;
2908
3238
  }
2909
3239
  repaired = repairAssistantDateArithmeticInPipeline(pipeline);
2910
3240
  if (!repaired.changed || containsForbiddenMongoOperators(repaired.pipeline)) {
2911
- throw error_4;
3241
+ throw error_5;
2912
3242
  }
2913
3243
  return [4 /*yield*/, db.collection(collection)
2914
3244
  .aggregate(repaired.pipeline, aggregateOptions)
@@ -2928,7 +3258,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
2928
3258
  }); };
2929
3259
  return [4 /*yield*/, runAggregateWithRepair(executedPipeline, 'initial')];
2930
3260
  case 7:
2931
- initialAggregate = _q.sent();
3261
+ initialAggregate = _r.sent();
2932
3262
  documents = initialAggregate.documents;
2933
3263
  executedPipeline = initialAggregate.pipeline;
2934
3264
  dateField = findAggregateDateField(executedPipeline);
@@ -2941,14 +3271,14 @@ function executeAiAssistantMongoAggregate(payload, context) {
2941
3271
  if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 9];
2942
3272
  return [4 /*yield*/, runAggregateWithRepair(fallbackPipeline, 'date_field_fallback')];
2943
3273
  case 8:
2944
- fallbackAggregate = _q.sent();
3274
+ fallbackAggregate = _r.sent();
2945
3275
  fallbackDocs = fallbackAggregate.documents;
2946
3276
  if (fallbackDocs.length) {
2947
3277
  documents = fallbackDocs;
2948
3278
  executedPipeline = fallbackAggregate.pipeline;
2949
3279
  fallbackMeta.dateField.used = true;
2950
3280
  }
2951
- _q.label = 9;
3281
+ _r.label = 9;
2952
3282
  case 9:
2953
3283
  if (!(!documents.length && dateField !== 'createdAt')) return [3 /*break*/, 11];
2954
3284
  createdFallback = { from: dateField, to: 'createdAt', attempted: true, used: false };
@@ -2957,14 +3287,14 @@ function executeAiAssistantMongoAggregate(payload, context) {
2957
3287
  if (!!containsForbiddenMongoOperators(createdPipeline)) return [3 /*break*/, 11];
2958
3288
  return [4 /*yield*/, runAggregateWithRepair(createdPipeline, 'date_field_created_at')];
2959
3289
  case 10:
2960
- createdAggregate = _q.sent();
3290
+ createdAggregate = _r.sent();
2961
3291
  createdDocs = createdAggregate.documents;
2962
3292
  if (createdDocs.length) {
2963
3293
  documents = createdDocs;
2964
3294
  executedPipeline = createdAggregate.pipeline;
2965
3295
  fallbackMeta.dateFieldCreatedAt.used = true;
2966
3296
  }
2967
- _q.label = 11;
3297
+ _r.label = 11;
2968
3298
  case 11:
2969
3299
  if (!!documents.length) return [3 /*break*/, 13];
2970
3300
  expanded = expandAggregateDateMatchFallback(executedPipeline, schemaFields);
@@ -2977,14 +3307,14 @@ function executeAiAssistantMongoAggregate(payload, context) {
2977
3307
  if (!!containsForbiddenMongoOperators(expanded.pipeline)) return [3 /*break*/, 13];
2978
3308
  return [4 /*yield*/, runAggregateWithRepair(expanded.pipeline, 'date_fields_expanded')];
2979
3309
  case 12:
2980
- expandedAggregate = _q.sent();
3310
+ expandedAggregate = _r.sent();
2981
3311
  expandedDocs = expandedAggregate.documents;
2982
3312
  if (expandedDocs.length) {
2983
3313
  documents = expandedDocs;
2984
3314
  executedPipeline = expandedAggregate.pipeline;
2985
3315
  fallbackMeta.dateFieldsExpanded.used = true;
2986
3316
  }
2987
- _q.label = 13;
3317
+ _r.label = 13;
2988
3318
  case 13:
2989
3319
  if (!!documents.length) return [3 /*break*/, 17];
2990
3320
  completionFallback = resolveAggregateCompletionFallback(executedPipeline);
@@ -3001,14 +3331,14 @@ function executeAiAssistantMongoAggregate(payload, context) {
3001
3331
  if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 15];
3002
3332
  return [4 /*yield*/, runAggregateWithRepair(fallbackPipeline, 'completion_add_fields')];
3003
3333
  case 14:
3004
- fallbackAggregate = _q.sent();
3334
+ fallbackAggregate = _r.sent();
3005
3335
  fallbackDocs = fallbackAggregate.documents;
3006
3336
  if (fallbackDocs.length) {
3007
3337
  documents = fallbackDocs;
3008
3338
  executedPipeline = fallbackAggregate.pipeline;
3009
3339
  fallbackMeta.completion.used = true;
3010
3340
  }
3011
- _q.label = 15;
3341
+ _r.label = 15;
3012
3342
  case 15:
3013
3343
  if (!!documents.length) return [3 /*break*/, 17];
3014
3344
  completionExprFallback = resolveAggregateCompletionExprFallback(executedPipeline);
@@ -3025,23 +3355,23 @@ function executeAiAssistantMongoAggregate(payload, context) {
3025
3355
  if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 17];
3026
3356
  return [4 /*yield*/, runAggregateWithRepair(fallbackPipeline, 'completion_expr')];
3027
3357
  case 16:
3028
- fallbackAggregate = _q.sent();
3358
+ fallbackAggregate = _r.sent();
3029
3359
  fallbackDocs = fallbackAggregate.documents;
3030
3360
  if (fallbackDocs.length) {
3031
3361
  documents = fallbackDocs;
3032
3362
  executedPipeline = fallbackAggregate.pipeline;
3033
3363
  fallbackMeta.completion.used = true;
3034
3364
  }
3035
- _q.label = 17;
3365
+ _r.label = 17;
3036
3366
  case 17:
3037
3367
  if (!(documents.length <= 1)) return [3 /*break*/, 26];
3038
3368
  unwindFallback = resolveAggregateUnwindFallback(executedPipeline);
3039
3369
  if (!unwindFallback) return [3 /*break*/, 26];
3040
3370
  fallbackMeta.unwind = { path: unwindFallback.path, attempted: true, used: false };
3041
3371
  shouldUnwind = false;
3042
- _q.label = 18;
3372
+ _r.label = 18;
3043
3373
  case 18:
3044
- _q.trys.push([18, 21, , 22]);
3374
+ _r.trys.push([18, 21, , 22]);
3045
3375
  _c = probeDocs;
3046
3376
  if (_c) return [3 /*break*/, 20];
3047
3377
  return [4 /*yield*/, fetchAssistantProbeDocs({
@@ -3053,14 +3383,14 @@ function executeAiAssistantMongoAggregate(payload, context) {
3053
3383
  includeClientScope: shouldScopeByClient
3054
3384
  })];
3055
3385
  case 19:
3056
- _c = (_q.sent());
3057
- _q.label = 20;
3386
+ _c = (_r.sent());
3387
+ _r.label = 20;
3058
3388
  case 20:
3059
3389
  probeDocs = _c;
3060
3390
  shouldUnwind = probeDocs.length ? hasArrayValueAtPath(probeDocs, unwindFallback.path) : false;
3061
3391
  return [3 /*break*/, 22];
3062
3392
  case 21:
3063
- _d = _q.sent();
3393
+ _d = _r.sent();
3064
3394
  shouldUnwind = false;
3065
3395
  return [3 /*break*/, 22];
3066
3396
  case 22:
@@ -3069,18 +3399,18 @@ function executeAiAssistantMongoAggregate(payload, context) {
3069
3399
  if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 24];
3070
3400
  return [4 /*yield*/, runAggregateWithRepair(fallbackPipeline, 'unwind')];
3071
3401
  case 23:
3072
- fallbackAggregate = _q.sent();
3402
+ fallbackAggregate = _r.sent();
3073
3403
  fallbackDocs = fallbackAggregate.documents;
3074
3404
  if (fallbackDocs.length > documents.length) {
3075
3405
  documents = fallbackDocs;
3076
3406
  executedPipeline = fallbackAggregate.pipeline;
3077
3407
  fallbackMeta.unwind.used = true;
3078
3408
  }
3079
- _q.label = 24;
3409
+ _r.label = 24;
3080
3410
  case 24: return [3 /*break*/, 26];
3081
3411
  case 25:
3082
3412
  fallbackMeta.unwind.skipped = 'not_array';
3083
- _q.label = 26;
3413
+ _r.label = 26;
3084
3414
  case 26:
3085
3415
  if (!!documents.length) return [3 /*break*/, 28];
3086
3416
  nameFallback = resolveAggregateNameMatchFallback(executedPipeline);
@@ -3095,14 +3425,14 @@ function executeAiAssistantMongoAggregate(payload, context) {
3095
3425
  if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 28];
3096
3426
  return [4 /*yield*/, runAggregateWithRepair(fallbackPipeline, 'name_match')];
3097
3427
  case 27:
3098
- fallbackAggregate = _q.sent();
3428
+ fallbackAggregate = _r.sent();
3099
3429
  fallbackDocs = fallbackAggregate.documents;
3100
3430
  if (fallbackDocs.length) {
3101
3431
  documents = fallbackDocs;
3102
3432
  executedPipeline = fallbackAggregate.pipeline;
3103
3433
  fallbackMeta.nameMatch.used = true;
3104
3434
  }
3105
- _q.label = 28;
3435
+ _r.label = 28;
3106
3436
  case 28:
3107
3437
  if (!!documents.length) return [3 /*break*/, 34];
3108
3438
  _e = probeDocs;
@@ -3116,14 +3446,14 @@ function executeAiAssistantMongoAggregate(payload, context) {
3116
3446
  includeClientScope: shouldScopeByClient
3117
3447
  })];
3118
3448
  case 29:
3119
- _e = (_q.sent());
3120
- _q.label = 30;
3449
+ _e = (_r.sent());
3450
+ _r.label = 30;
3121
3451
  case 30:
3122
3452
  probeDocs = _e;
3123
3453
  _loop_1 = function (i) {
3124
3454
  var stage, chemicalLookup, rewrittenPipeline, fallbackAggregate, fallbackDocs;
3125
- return __generator(this, function (_r) {
3126
- switch (_r.label) {
3455
+ return __generator(this, function (_s) {
3456
+ switch (_s.label) {
3127
3457
  case 0:
3128
3458
  stage = executedPipeline[i];
3129
3459
  if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
@@ -3139,7 +3469,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
3139
3469
  probeDocs: probeDocs || undefined
3140
3470
  })];
3141
3471
  case 1:
3142
- chemicalLookup = _r.sent();
3472
+ chemicalLookup = _s.sent();
3143
3473
  if (!chemicalLookup) {
3144
3474
  return [2 /*return*/, "continue"];
3145
3475
  }
@@ -3148,7 +3478,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
3148
3478
  if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 3];
3149
3479
  return [4 /*yield*/, runAggregateWithRepair(rewrittenPipeline, 'chemical_lookup')];
3150
3480
  case 2:
3151
- fallbackAggregate = _r.sent();
3481
+ fallbackAggregate = _s.sent();
3152
3482
  fallbackDocs = fallbackAggregate.documents;
3153
3483
  if (fallbackDocs.length) {
3154
3484
  documents = fallbackDocs;
@@ -3156,21 +3486,21 @@ function executeAiAssistantMongoAggregate(payload, context) {
3156
3486
  fallbackMeta.chemicalLookup.used = true;
3157
3487
  return [2 /*return*/, "break"];
3158
3488
  }
3159
- _r.label = 3;
3489
+ _s.label = 3;
3160
3490
  case 3: return [2 /*return*/];
3161
3491
  }
3162
3492
  });
3163
3493
  };
3164
3494
  i = 0;
3165
- _q.label = 31;
3495
+ _r.label = 31;
3166
3496
  case 31:
3167
3497
  if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 34];
3168
3498
  return [5 /*yield**/, _loop_1(i)];
3169
3499
  case 32:
3170
- state_1 = _q.sent();
3500
+ state_1 = _r.sent();
3171
3501
  if (state_1 === "break")
3172
3502
  return [3 /*break*/, 34];
3173
- _q.label = 33;
3503
+ _r.label = 33;
3174
3504
  case 33:
3175
3505
  i += 1;
3176
3506
  return [3 /*break*/, 31];
@@ -3196,8 +3526,8 @@ function executeAiAssistantMongoAggregate(payload, context) {
3196
3526
  includeClientScope: shouldScopeByClient
3197
3527
  })];
3198
3528
  case 35:
3199
- _f = (_q.sent());
3200
- _q.label = 36;
3529
+ _f = (_r.sent());
3530
+ _r.label = 36;
3201
3531
  case 36:
3202
3532
  probeDocs = _f;
3203
3533
  if (!probeDocs.length) return [3 /*break*/, 38];
@@ -3216,27 +3546,27 @@ function executeAiAssistantMongoAggregate(payload, context) {
3216
3546
  if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 38];
3217
3547
  return [4 /*yield*/, runAggregateWithRepair(rewrittenPipeline, 'query_field_aliases')];
3218
3548
  case 37:
3219
- fallbackAggregate = _q.sent();
3549
+ fallbackAggregate = _r.sent();
3220
3550
  fallbackDocs = fallbackAggregate.documents;
3221
3551
  if (fallbackDocs.length) {
3222
3552
  documents = fallbackDocs;
3223
3553
  executedPipeline = fallbackAggregate.pipeline;
3224
3554
  fallbackMeta.queryFieldAliases.used = true;
3225
3555
  }
3226
- _q.label = 38;
3556
+ _r.label = 38;
3227
3557
  case 38:
3228
3558
  if (!!documents.length) return [3 /*break*/, 42];
3229
3559
  _loop_2 = function (i) {
3230
- var stage, _s, idLookup, rewrittenPipeline, fallbackAggregate, fallbackDocs;
3231
- return __generator(this, function (_t) {
3232
- switch (_t.label) {
3560
+ var stage, _t, idLookup, rewrittenPipeline, fallbackAggregate, fallbackDocs;
3561
+ return __generator(this, function (_u) {
3562
+ switch (_u.label) {
3233
3563
  case 0:
3234
3564
  stage = executedPipeline[i];
3235
3565
  if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
3236
3566
  return [2 /*return*/, "continue"];
3237
3567
  }
3238
- _s = probeDocs;
3239
- if (_s) return [3 /*break*/, 2];
3568
+ _t = probeDocs;
3569
+ if (_t) return [3 /*break*/, 2];
3240
3570
  return [4 /*yield*/, fetchAssistantProbeDocs({
3241
3571
  db: db,
3242
3572
  collection: collection,
@@ -3246,10 +3576,10 @@ function executeAiAssistantMongoAggregate(payload, context) {
3246
3576
  includeClientScope: shouldScopeByClient
3247
3577
  })];
3248
3578
  case 1:
3249
- _s = (_t.sent());
3250
- _t.label = 2;
3579
+ _t = (_u.sent());
3580
+ _u.label = 2;
3251
3581
  case 2:
3252
- probeDocs = _s;
3582
+ probeDocs = _t;
3253
3583
  return [4 /*yield*/, applyIdLookupFallbackToQuery({
3254
3584
  query: stage.$match,
3255
3585
  db: db,
@@ -3260,7 +3590,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
3260
3590
  probeDocs: probeDocs || undefined
3261
3591
  })];
3262
3592
  case 3:
3263
- idLookup = _t.sent();
3593
+ idLookup = _u.sent();
3264
3594
  if (!idLookup) {
3265
3595
  return [2 /*return*/, "continue"];
3266
3596
  }
@@ -3269,7 +3599,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
3269
3599
  if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 5];
3270
3600
  return [4 /*yield*/, runAggregateWithRepair(rewrittenPipeline, 'id_lookup')];
3271
3601
  case 4:
3272
- fallbackAggregate = _t.sent();
3602
+ fallbackAggregate = _u.sent();
3273
3603
  fallbackDocs = fallbackAggregate.documents;
3274
3604
  if (fallbackDocs.length) {
3275
3605
  documents = fallbackDocs;
@@ -3277,21 +3607,21 @@ function executeAiAssistantMongoAggregate(payload, context) {
3277
3607
  fallbackMeta.idLookup.used = true;
3278
3608
  return [2 /*return*/, "break"];
3279
3609
  }
3280
- _t.label = 5;
3610
+ _u.label = 5;
3281
3611
  case 5: return [2 /*return*/];
3282
3612
  }
3283
3613
  });
3284
3614
  };
3285
3615
  i = 0;
3286
- _q.label = 39;
3616
+ _r.label = 39;
3287
3617
  case 39:
3288
3618
  if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 42];
3289
3619
  return [5 /*yield**/, _loop_2(i)];
3290
3620
  case 40:
3291
- state_2 = _q.sent();
3621
+ state_2 = _r.sent();
3292
3622
  if (state_2 === "break")
3293
3623
  return [3 /*break*/, 42];
3294
- _q.label = 41;
3624
+ _r.label = 41;
3295
3625
  case 41:
3296
3626
  i += 1;
3297
3627
  return [3 /*break*/, 39];
@@ -3299,12 +3629,15 @@ function executeAiAssistantMongoAggregate(payload, context) {
3299
3629
  if (!!documents.length) return [3 /*break*/, 45];
3300
3630
  return [4 /*yield*/, resolveBaseCollectionFromReport(db, dbName, collection)];
3301
3631
  case 43:
3302
- baseCollection = _q.sent();
3632
+ baseCollection = _r.sent();
3303
3633
  if (!(baseCollection && baseCollection !== collection)) return [3 /*break*/, 45];
3304
- fallbackPayload = __assign(__assign({}, input), { collection: baseCollection });
3634
+ addAssistantCollectionToTriedSet(triedCollections, baseCollection);
3635
+ fallbackPayload = __assign(__assign({}, input), { collection: baseCollection, __assistantRetryState: buildAssistantRetryState(retryState, triedCollections, {
3636
+ rootCollection: retryRootCollection
3637
+ }) });
3305
3638
  return [4 /*yield*/, executeAiAssistantMongoAggregate(fallbackPayload, context)];
3306
3639
  case 44:
3307
- fallbackResult = _q.sent();
3640
+ fallbackResult = _r.sent();
3308
3641
  if (Array.isArray(fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.documents) && fallbackResult.documents.length) {
3309
3642
  if (isSuperAdmin && (fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.debug) && typeof fallbackResult.debug === 'object') {
3310
3643
  existingFallbacks = fallbackResult.debug.fallbacks && typeof fallbackResult.debug.fallbacks === 'object'
@@ -3321,48 +3654,107 @@ function executeAiAssistantMongoAggregate(payload, context) {
3321
3654
  if (isSuperAdmin) {
3322
3655
  fallbackMeta.reportFallback = { from: collection, to: baseCollection, attempted: true, used: false };
3323
3656
  }
3324
- _q.label = 45;
3657
+ _r.label = 45;
3325
3658
  case 45:
3326
- if (!(!documents.length && isSuperAdmin)) return [3 /*break*/, 62];
3659
+ if (!(!documents.length && crossCollectionRetryEnabled)) return [3 /*break*/, 54];
3660
+ return [4 /*yield*/, resolveAssistantAvailableCrossCollectionFallbacks(db, dbName, collection, triedCollections)];
3661
+ case 46:
3662
+ crossCollectionCandidates = _r.sent();
3663
+ if (!crossCollectionCandidates.length) return [3 /*break*/, 54];
3664
+ fallbackMeta.collectionRetry = {
3665
+ from: collection,
3666
+ root: retryRootCollection,
3667
+ tried: crossCollectionCandidates,
3668
+ attempted: true,
3669
+ used: false
3670
+ };
3671
+ _r.label = 47;
3672
+ case 47:
3673
+ _r.trys.push([47, 52, 53, 54]);
3674
+ crossCollectionCandidates_2 = __values(crossCollectionCandidates), crossCollectionCandidates_2_1 = crossCollectionCandidates_2.next();
3675
+ _r.label = 48;
3676
+ case 48:
3677
+ if (!!crossCollectionCandidates_2_1.done) return [3 /*break*/, 51];
3678
+ candidateCollection = crossCollectionCandidates_2_1.value;
3679
+ addAssistantCollectionToTriedSet(triedCollections, candidateCollection);
3680
+ fallbackPayload = __assign(__assign({}, input), { collection: candidateCollection, __assistantRetryState: buildAssistantRetryState(retryState, triedCollections, {
3681
+ rootCollection: retryRootCollection,
3682
+ disableCrossCollectionRetry: true
3683
+ }) });
3684
+ return [4 /*yield*/, executeAiAssistantMongoAggregate(fallbackPayload, context)];
3685
+ case 49:
3686
+ fallbackResult = _r.sent();
3687
+ if (Array.isArray(fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.documents) && fallbackResult.documents.length) {
3688
+ if (isSuperAdmin && (fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.debug) && typeof fallbackResult.debug === 'object') {
3689
+ existingFallbacks = fallbackResult.debug.fallbacks && typeof fallbackResult.debug.fallbacks === 'object'
3690
+ ? fallbackResult.debug.fallbacks
3691
+ : {};
3692
+ fallbackResult.debug.fallbacks = __assign(__assign({}, existingFallbacks), { collectionRetry: {
3693
+ from: collection,
3694
+ to: candidateCollection,
3695
+ root: retryRootCollection,
3696
+ tried: crossCollectionCandidates,
3697
+ used: true
3698
+ } });
3699
+ }
3700
+ return [2 /*return*/, fallbackResult];
3701
+ }
3702
+ _r.label = 50;
3703
+ case 50:
3704
+ crossCollectionCandidates_2_1 = crossCollectionCandidates_2.next();
3705
+ return [3 /*break*/, 48];
3706
+ case 51: return [3 /*break*/, 54];
3707
+ case 52:
3708
+ e_2_1 = _r.sent();
3709
+ e_2 = { error: e_2_1 };
3710
+ return [3 /*break*/, 54];
3711
+ case 53:
3712
+ try {
3713
+ if (crossCollectionCandidates_2_1 && !crossCollectionCandidates_2_1.done && (_o = crossCollectionCandidates_2.return)) _o.call(crossCollectionCandidates_2);
3714
+ }
3715
+ finally { if (e_2) throw e_2.error; }
3716
+ return [7 /*endfinally*/];
3717
+ case 54:
3718
+ if (!(!documents.length && isSuperAdmin)) return [3 /*break*/, 71];
3327
3719
  matchStages = (executedPipeline || []).filter(function (stage) { return stage && typeof stage === 'object' && stage.$match && typeof stage.$match === 'object'; });
3328
3720
  diagnostics = {};
3329
- if (!matchStages.length) return [3 /*break*/, 62];
3721
+ if (!matchStages.length) return [3 /*break*/, 71];
3330
3722
  combinedMatch = matchStages.reduce(function (acc, stage) { return ({ $and: __spreadArray(__spreadArray([], __read((acc.$and || [])), false), [stage.$match], false) }); }, { $and: [] });
3331
3723
  nameFields = collectMatchFieldsByCondition(combinedMatch, function (field, condition) { return isRegexMatchCondition(condition)
3332
3724
  || (typeof condition === 'string' && shouldApplyAssistantNameRegex(field)); });
3333
3725
  dateFields = collectMatchFieldsByCondition(combinedMatch, function (_field, condition) { return isDateCondition(condition); });
3334
3726
  diagnostics.nameFields = nameFields.length ? nameFields : undefined;
3335
3727
  diagnostics.dateFields = dateFields.length ? dateFields : undefined;
3336
- _q.label = 46;
3337
- case 46:
3338
- _q.trys.push([46, 51, , 52]);
3339
- if (!nameFields.length) return [3 /*break*/, 48];
3728
+ _r.label = 55;
3729
+ case 55:
3730
+ _r.trys.push([55, 60, , 61]);
3731
+ if (!nameFields.length) return [3 /*break*/, 57];
3340
3732
  queryNoName = stripMatchFields(combinedMatch, nameFields);
3341
3733
  _g = diagnostics;
3342
3734
  return [4 /*yield*/, db.collection(collection).countDocuments(queryNoName, {
3343
3735
  readPreference: AI_ASSISTANT_READ_PREFERENCE
3344
3736
  })];
3345
- case 47:
3346
- _g.recentCount = _q.sent();
3347
- _q.label = 48;
3348
- case 48:
3349
- if (!dateFields.length) return [3 /*break*/, 50];
3737
+ case 56:
3738
+ _g.recentCount = _r.sent();
3739
+ _r.label = 57;
3740
+ case 57:
3741
+ if (!dateFields.length) return [3 /*break*/, 59];
3350
3742
  queryNoDate = stripMatchFields(combinedMatch, dateFields);
3351
3743
  _h = diagnostics;
3352
3744
  return [4 /*yield*/, db.collection(collection).countDocuments(queryNoDate, {
3353
3745
  readPreference: AI_ASSISTANT_READ_PREFERENCE
3354
3746
  })];
3355
- case 49:
3356
- _h.nameMatchCount = _q.sent();
3357
- _q.label = 50;
3358
- case 50: return [3 /*break*/, 52];
3359
- case 51:
3360
- _j = _q.sent();
3361
- return [3 /*break*/, 52];
3362
- case 52:
3363
- _q.trys.push([52, 55, , 56]);
3747
+ case 58:
3748
+ _h.nameMatchCount = _r.sent();
3749
+ _r.label = 59;
3750
+ case 59: return [3 /*break*/, 61];
3751
+ case 60:
3752
+ _j = _r.sent();
3753
+ return [3 /*break*/, 61];
3754
+ case 61:
3755
+ _r.trys.push([61, 64, , 65]);
3364
3756
  _k = probeDocs;
3365
- if (_k) return [3 /*break*/, 54];
3757
+ if (_k) return [3 /*break*/, 63];
3366
3758
  return [4 /*yield*/, fetchAssistantProbeDocs({
3367
3759
  db: db,
3368
3760
  collection: collection,
@@ -3371,52 +3763,52 @@ function executeAiAssistantMongoAggregate(payload, context) {
3371
3763
  isSuperAdmin: isSuperAdmin,
3372
3764
  includeClientScope: shouldScopeByClient
3373
3765
  })];
3374
- case 53:
3375
- _k = (_q.sent());
3376
- _q.label = 54;
3377
- case 54:
3766
+ case 62:
3767
+ _k = (_r.sent());
3768
+ _r.label = 63;
3769
+ case 63:
3378
3770
  probeDocs = _k;
3379
3771
  if (probeDocs.length && nameFields.length) {
3380
3772
  diagnostics.chemicalIdDetected = detectChemicalIdFromProbe(probeDocs, nameFields);
3381
3773
  }
3382
- return [3 /*break*/, 56];
3383
- case 55:
3384
- _l = _q.sent();
3385
- return [3 /*break*/, 56];
3386
- case 56:
3387
- _q.trys.push([56, 60, , 61]);
3774
+ return [3 /*break*/, 65];
3775
+ case 64:
3776
+ _l = _r.sent();
3777
+ return [3 /*break*/, 65];
3778
+ case 65:
3779
+ _r.trys.push([65, 69, , 70]);
3388
3780
  return [4 /*yield*/, listAssistantCollections(db, dbName)];
3389
- case 57:
3390
- allCollections = _q.sent();
3781
+ case 66:
3782
+ allCollections = _r.sent();
3391
3783
  base = stripVersionSuffix(collection.startsWith('report-') ? collection.slice('report-'.length) : collection);
3392
3784
  alt = collection.startsWith('report-') ? base : "report-".concat(base);
3393
- if (!(alt && alt !== collection && allCollections.includes(alt))) return [3 /*break*/, 59];
3785
+ if (!(alt && alt !== collection && allCollections.includes(alt))) return [3 /*break*/, 68];
3394
3786
  return [4 /*yield*/, db.collection(alt).countDocuments({}, { readPreference: AI_ASSISTANT_READ_PREFERENCE })];
3395
- case 58:
3396
- altCount = _q.sent();
3787
+ case 67:
3788
+ altCount = _r.sent();
3397
3789
  diagnostics.alternateCollection = alt;
3398
3790
  diagnostics.alternateCollectionCount = altCount;
3399
- _q.label = 59;
3400
- case 59: return [3 /*break*/, 61];
3401
- case 60:
3402
- _m = _q.sent();
3403
- return [3 /*break*/, 61];
3404
- case 61:
3791
+ _r.label = 68;
3792
+ case 68: return [3 /*break*/, 70];
3793
+ case 69:
3794
+ _m = _r.sent();
3795
+ return [3 /*break*/, 70];
3796
+ case 70:
3405
3797
  fallbackMeta.zeroDiagnostics = diagnostics;
3406
- _q.label = 62;
3407
- case 62: return [4 /*yield*/, verifyAssistantAggregateReliability({
3798
+ _r.label = 71;
3799
+ case 71: return [4 /*yield*/, verifyAssistantAggregateReliability({
3408
3800
  db: db,
3409
3801
  collection: collection,
3410
3802
  pipeline: executedPipeline,
3411
3803
  documents: documents,
3412
3804
  aggregateOptions: aggregateOptions
3413
3805
  })];
3414
- case 63:
3415
- verification = _q.sent();
3806
+ case 72:
3807
+ verification = _r.sent();
3416
3808
  sanitizedDocuments = isSuperAdmin
3417
3809
  ? documents
3418
3810
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
3419
- includeIds = ((_p = input.options) === null || _p === void 0 ? void 0 : _p.includeIds) === true;
3811
+ includeIds = ((_q = input.options) === null || _q === void 0 ? void 0 : _q.includeIds) === true;
3420
3812
  displayDocs = sanitizedDocuments.map(function (doc) { return flattenForTable(doc, {
3421
3813
  includeGroupFromId: true,
3422
3814
  includeIds: true
@@ -3430,8 +3822,8 @@ function executeAiAssistantMongoAggregate(payload, context) {
3430
3822
  idCustomer: customerId,
3431
3823
  isSuperAdmin: isSuperAdmin
3432
3824
  })];
3433
- case 64:
3434
- idLookupDisplay = _q.sent();
3825
+ case 73:
3826
+ idLookupDisplay = _r.sent();
3435
3827
  if (idLookupDisplay === null || idLookupDisplay === void 0 ? void 0 : idLookupDisplay.docs) {
3436
3828
  displayDocs = idLookupDisplay.docs;
3437
3829
  }
@@ -4165,7 +4557,8 @@ function resolveAssistantRevenueByTimeRequest(text, scope) {
4165
4557
  if (!/\b(revenue|invoice)\b/.test(normalized)) {
4166
4558
  return null;
4167
4559
  }
4168
- var byCustomer = /\bby\s+each\s+customer\b/.test(normalized) || /\bby\s+customer\b/.test(normalized);
4560
+ var byCustomer = /\b(?:by|per)\s+(?:each\s+)?(?:customer|client|account)s?\b/.test(normalized)
4561
+ || /\bfor\s+each\s+(?:customer|client|account)\b/.test(normalized);
4169
4562
  if (scope === 'overall' && byCustomer) {
4170
4563
  return null;
4171
4564
  }
@@ -4173,19 +4566,19 @@ function resolveAssistantRevenueByTimeRequest(text, scope) {
4173
4566
  return null;
4174
4567
  }
4175
4568
  var grain = null;
4176
- if (/\bby\s+day\b|\bdaily\b/.test(normalized)) {
4569
+ if (/\b(?:by|per)\s+day\b|\bdaily\b/.test(normalized)) {
4177
4570
  grain = 'day';
4178
4571
  }
4179
- else if (/\bby\s+week\b|\bweekly\b/.test(normalized)) {
4572
+ else if (/\b(?:by|per)\s+week\b|\bweekly\b/.test(normalized)) {
4180
4573
  grain = 'week';
4181
4574
  }
4182
- else if (/\bby\s+month\b|\bmonthly\b/.test(normalized)) {
4575
+ else if (/\b(?:by|per)\s+month\b|\bmonthly\b/.test(normalized)) {
4183
4576
  grain = 'month';
4184
4577
  }
4185
- else if (/\bby\s+quarter\b|\bquarterly\b/.test(normalized)) {
4578
+ else if (/\b(?:by|per)\s+quarter\b|\bquarterly\b/.test(normalized)) {
4186
4579
  grain = 'quarter';
4187
4580
  }
4188
- else if (/\bby\s+year\b|\byearly\b|\bannually\b/.test(normalized)) {
4581
+ else if (/\b(?:by|per)\s+year\b|\byearly\b|\bannually\b/.test(normalized)) {
4189
4582
  grain = 'year';
4190
4583
  }
4191
4584
  if (!grain) {
@@ -4212,30 +4605,81 @@ function resolveAssistantRevenueByTimeRequest(text, scope) {
4212
4605
  amount: Math.min(Math.max((0, common_1.round)(amount), 1), 400)
4213
4606
  };
4214
4607
  }
4608
+ function buildAssistantTrimmedStringExpr(value) {
4609
+ return {
4610
+ $trim: {
4611
+ input: {
4612
+ $convert: {
4613
+ input: value,
4614
+ to: 'string',
4615
+ onError: '',
4616
+ onNull: ''
4617
+ }
4618
+ }
4619
+ }
4620
+ };
4621
+ }
4622
+ function buildAssistantInvoiceCustomerLabelExpr() {
4623
+ return {
4624
+ $let: {
4625
+ vars: {
4626
+ customer_name: buildAssistantTrimmedStringExpr('$customer_name'),
4627
+ customer_fullname: buildAssistantTrimmedStringExpr('$customer.fullname'),
4628
+ customer_nested_name: buildAssistantTrimmedStringExpr('$customer.name'),
4629
+ customer_scalar: buildAssistantTrimmedStringExpr('$customer'),
4630
+ client_name: buildAssistantTrimmedStringExpr('$client_name'),
4631
+ client_fullname: buildAssistantTrimmedStringExpr('$client.fullname'),
4632
+ client_nested_name: buildAssistantTrimmedStringExpr('$client.name'),
4633
+ client_scalar: buildAssistantTrimmedStringExpr('$client'),
4634
+ id_customer: buildAssistantTrimmedStringExpr('$id_customer'),
4635
+ id_client: buildAssistantTrimmedStringExpr('$id_client')
4636
+ },
4637
+ in: {
4638
+ $switch: {
4639
+ branches: [
4640
+ { case: { $gt: [{ $strLenCP: '$$customer_name' }, 0] }, then: '$$customer_name' },
4641
+ { case: { $gt: [{ $strLenCP: '$$customer_fullname' }, 0] }, then: '$$customer_fullname' },
4642
+ { case: { $gt: [{ $strLenCP: '$$customer_nested_name' }, 0] }, then: '$$customer_nested_name' },
4643
+ { case: { $gt: [{ $strLenCP: '$$customer_scalar' }, 0] }, then: '$$customer_scalar' },
4644
+ { case: { $gt: [{ $strLenCP: '$$client_name' }, 0] }, then: '$$client_name' },
4645
+ { case: { $gt: [{ $strLenCP: '$$client_fullname' }, 0] }, then: '$$client_fullname' },
4646
+ { case: { $gt: [{ $strLenCP: '$$client_nested_name' }, 0] }, then: '$$client_nested_name' },
4647
+ { case: { $gt: [{ $strLenCP: '$$client_scalar' }, 0] }, then: '$$client_scalar' },
4648
+ { case: { $gt: [{ $strLenCP: '$$id_customer' }, 0] }, then: '$$id_customer' },
4649
+ { case: { $gt: [{ $strLenCP: '$$id_client' }, 0] }, then: '$$id_client' }
4650
+ ],
4651
+ default: 'Unknown Customer'
4652
+ }
4653
+ }
4654
+ }
4655
+ };
4656
+ }
4657
+ function resolveAssistantRevenueByTimePipelineLimit(request, scope) {
4658
+ var amount = Math.min(Math.max((0, common_1.round)(request.amount), 1), 400);
4659
+ if (scope !== 'by_customer') {
4660
+ return Math.min(Math.max(amount * 2, 20), 200);
4661
+ }
4662
+ // Customer breakdowns need much higher pre-pivot row coverage so each customer appears.
4663
+ var perBucketTargets = {
4664
+ day: 120,
4665
+ week: 220,
4666
+ month: 350,
4667
+ quarter: 450,
4668
+ year: 600
4669
+ };
4670
+ var perBucketTarget = perBucketTargets[request.grain] || 300;
4671
+ return Math.min(Math.max(amount * perBucketTarget, 400), 5000);
4672
+ }
4215
4673
  function buildAssistantInvoiceRevenueByTimePipeline(request, scope) {
4216
4674
  var _a, _b, _c;
4217
4675
  if (scope === void 0) { scope = 'overall'; }
4218
4676
  var grain = request.grain;
4219
4677
  var amount = Math.min(Math.max((0, common_1.round)(request.amount), 1), 400);
4220
4678
  var byCustomer = scope === 'by_customer';
4679
+ var limit = resolveAssistantRevenueByTimePipelineLimit(request, scope);
4221
4680
  var effectiveDateExpr = { $ifNull: ['$date_paid', { $ifNull: ['$date_invoiced', '$createdAt'] }] };
4222
4681
  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
- };
4682
+ var customerExpr = buildAssistantInvoiceCustomerLabelExpr();
4239
4683
  var startDateExpr = grain === 'quarter'
4240
4684
  ? { $dateSubtract: { startDate: '$$NOW', unit: 'month', amount: amount * 3 } }
4241
4685
  : { $dateSubtract: { startDate: '$$NOW', unit: grain, amount: amount } };
@@ -4267,7 +4711,7 @@ function buildAssistantInvoiceRevenueByTimePipeline(request, scope) {
4267
4711
  $project: __assign(__assign({ _id: 0 }, (byCustomer ? { customer: '$_id.customer' } : {})), { quarter: { $concat: [{ $toString: '$_id.year' }, '-Q', { $toString: '$_id.quarter' }] }, total_revenue: 1 })
4268
4712
  },
4269
4713
  { $sort: byCustomer ? { customer: 1, quarter: 1 } : { quarter: 1 } },
4270
- { $limit: Math.min(Math.max(amount * (byCustomer ? 50 : 2), byCustomer ? 120 : 20), byCustomer ? 500 : 200) }
4714
+ { $limit: limit }
4271
4715
  ], false);
4272
4716
  }
4273
4717
  if (grain === 'year') {
@@ -4284,7 +4728,7 @@ function buildAssistantInvoiceRevenueByTimePipeline(request, scope) {
4284
4728
  $project: __assign(__assign({ _id: 0 }, (byCustomer ? { customer: '$_id.customer' } : {})), { year: '$_id.year', total_revenue: 1 })
4285
4729
  },
4286
4730
  { $sort: byCustomer ? { customer: 1, year: 1 } : { year: 1 } },
4287
- { $limit: Math.min(Math.max(amount * (byCustomer ? 50 : 2), byCustomer ? 120 : 20), byCustomer ? 500 : 200) }
4731
+ { $limit: limit }
4288
4732
  ], false);
4289
4733
  }
4290
4734
  var bucketField = grain;
@@ -4314,7 +4758,7 @@ function buildAssistantInvoiceRevenueByTimePipeline(request, scope) {
4314
4758
  }, _a.total_revenue = 1, _a))
4315
4759
  },
4316
4760
  { $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) }
4761
+ { $limit: limit }
4318
4762
  ], false);
4319
4763
  }
4320
4764
  function isAssistantRevenueByTimeHeuristicDirective(directive) {
@@ -4325,8 +4769,29 @@ function isAssistantBlendRedUltraLiftHeuristicDirective(directive) {
4325
4769
  var rawLine = normalizeOptionalString(directive === null || directive === void 0 ? void 0 : directive.rawLine).toLowerCase();
4326
4770
  return rawLine.includes('heuristic_agg(blend-red-ultra-lift)');
4327
4771
  }
4772
+ function isAssistantActiveClientsHeuristicDirective(directive) {
4773
+ var rawLine = normalizeOptionalString(directive === null || directive === void 0 ? void 0 : directive.rawLine).toLowerCase();
4774
+ return rawLine.includes('heuristic_read(active-clients-count)');
4775
+ }
4776
+ function isAssistantInvoiceTopCustomersHeuristicDirective(directive) {
4777
+ var rawLine = normalizeOptionalString(directive === null || directive === void 0 ? void 0 : directive.rawLine).toLowerCase();
4778
+ return rawLine.includes('heuristic_agg(invoice-top-customers)');
4779
+ }
4780
+ function isAssistantOperationalHeuristicDirective(directive) {
4781
+ var rawLine = normalizeOptionalString(directive === null || directive === void 0 ? void 0 : directive.rawLine).toLowerCase();
4782
+ return rawLine.includes('heuristic_agg(work-order-status)')
4783
+ || rawLine.includes('heuristic_agg(work-order-completed-per-day)')
4784
+ || rawLine.includes('heuristic_agg(work-order-top-customers)')
4785
+ || rawLine.includes('heuristic_agg(blend-last10-summary)')
4786
+ || rawLine.includes('heuristic_agg(blend-throughput-by-day)')
4787
+ || rawLine.includes('heuristic_agg(deliveries-per-driver-last-month)')
4788
+ || rawLine.includes('heuristic_agg(last-deliveries)');
4789
+ }
4328
4790
  function isAssistantDeterministicHeuristicDirective(directive) {
4329
4791
  return isAssistantRevenueByTimeHeuristicDirective(directive)
4792
+ || isAssistantActiveClientsHeuristicDirective(directive)
4793
+ || isAssistantInvoiceTopCustomersHeuristicDirective(directive)
4794
+ || isAssistantOperationalHeuristicDirective(directive)
4330
4795
  || isAssistantBlendRedUltraLiftHeuristicDirective(directive);
4331
4796
  }
4332
4797
  function buildAssistantHeuristicDirective(message, collectionHints) {
@@ -4334,14 +4799,58 @@ function buildAssistantHeuristicDirective(message, collectionHints) {
4334
4799
  if (!text) {
4335
4800
  return null;
4336
4801
  }
4802
+ if (/\bhow\s+many\b.*\bactive\b.*\b(clients?|customers?)\b/.test(text)
4803
+ || /\bactive\b.*\b(clients?|customers?)\b.*\bhow\s+many\b/.test(text)) {
4804
+ var mergedHints = mergeAssistantHintValues(collectionHints, resolveAssistantDefaultCollectionHints(message));
4805
+ var customerCollection = mergedHints.includes('customers')
4806
+ ? 'customers'
4807
+ : (mergedHints.includes('clients') ? 'clients' : 'customers');
4808
+ return {
4809
+ type: 'read',
4810
+ payload: {
4811
+ collection: customerCollection,
4812
+ permissionView: '/client/list',
4813
+ query: {
4814
+ $or: [
4815
+ { status: { $regex: '^active$', $options: 'i' } },
4816
+ { state: { $regex: '^active$', $options: 'i' } },
4817
+ { active: true },
4818
+ { is_active: true },
4819
+ { enabled: true },
4820
+ { is_enabled: true }
4821
+ ]
4822
+ },
4823
+ options: {
4824
+ projection: {
4825
+ status: 1,
4826
+ state: 1,
4827
+ active: 1,
4828
+ is_active: 1,
4829
+ enabled: 1,
4830
+ is_enabled: 1
4831
+ },
4832
+ limit: 0,
4833
+ includeTotal: true
4834
+ }
4835
+ },
4836
+ cleaned: '',
4837
+ rawLine: 'HEURISTIC_READ(active-clients-count)'
4838
+ };
4839
+ }
4337
4840
  var revenueByCustomerTime = resolveAssistantRevenueByTimeRequest(text, 'by_customer');
4338
4841
  if (revenueByCustomerTime) {
4842
+ var customerLimit = resolveAssistantRevenueByTimePipelineLimit(revenueByCustomerTime, 'by_customer');
4339
4843
  return {
4340
4844
  type: 'aggregate',
4341
4845
  payload: {
4342
4846
  collection: 'invoices',
4343
4847
  permissionView: '/invoice/list',
4344
- pipeline: buildAssistantInvoiceRevenueByTimePipeline(revenueByCustomerTime, 'by_customer')
4848
+ pipeline: buildAssistantInvoiceRevenueByTimePipeline(revenueByCustomerTime, 'by_customer'),
4849
+ options: {
4850
+ allowDiskUse: true,
4851
+ export: true,
4852
+ limit: customerLimit
4853
+ }
4345
4854
  },
4346
4855
  cleaned: '',
4347
4856
  rawLine: "HEURISTIC_AGG(invoice-revenue-time-customer-".concat(revenueByCustomerTime.grain, ")")
@@ -4360,12 +4869,14 @@ function buildAssistantHeuristicDirective(message, collectionHints) {
4360
4869
  rawLine: "HEURISTIC_AGG(invoice-revenue-time-".concat(revenueByTime.grain, ")")
4361
4870
  };
4362
4871
  }
4363
- if (/(last\s+20).*(work[\s-]*orders?).*(group(ed)?\s+by\s+status)/.test(text)) {
4872
+ if (/\b(last|latest|recent)\s+20\b/.test(text)
4873
+ && /\bwork[\s-]*orders?\b/.test(text)
4874
+ && /\b(group(ed)?\s+by|by|per)\s+status\b/.test(text)) {
4364
4875
  return {
4365
4876
  type: 'aggregate',
4366
4877
  payload: {
4367
4878
  collection: 'work-order-dynamics',
4368
- permissionView: '/work-order/list',
4879
+ permissionView: '/work-order-dynamic/list',
4369
4880
  pipeline: [
4370
4881
  {
4371
4882
  $addFields: {
@@ -4402,6 +4913,205 @@ function buildAssistantHeuristicDirective(message, collectionHints) {
4402
4913
  rawLine: 'HEURISTIC_AGG(work-order-status)'
4403
4914
  };
4404
4915
  }
4916
+ if (/\bwork[\s-]*orders?\b/.test(text)
4917
+ && /\b(completed|complete)\b/.test(text)
4918
+ && /\b(per|by)\s+day\b/.test(text)
4919
+ && /\b(last|past)\s+30\s+days?\b/.test(text)) {
4920
+ return {
4921
+ type: 'aggregate',
4922
+ payload: {
4923
+ collection: 'work-order-dynamics',
4924
+ permissionView: '/work-order-dynamic/list',
4925
+ pipeline: [
4926
+ {
4927
+ $match: {
4928
+ date_completed: {
4929
+ $gte: { $dateSubtract: { startDate: '$$NOW', unit: 'day', amount: 30 } },
4930
+ $lt: '$$NOW'
4931
+ }
4932
+ }
4933
+ },
4934
+ {
4935
+ $group: {
4936
+ _id: {
4937
+ $dateToString: {
4938
+ format: '%Y-%m-%d',
4939
+ date: '$date_completed',
4940
+ timezone: 'UTC'
4941
+ }
4942
+ },
4943
+ completed_work_orders: { $sum: 1 }
4944
+ }
4945
+ },
4946
+ { $sort: { _id: 1 } },
4947
+ {
4948
+ $project: {
4949
+ _id: 0,
4950
+ day_utc: '$_id',
4951
+ completed_work_orders: 1
4952
+ }
4953
+ }
4954
+ ]
4955
+ },
4956
+ cleaned: '',
4957
+ rawLine: 'HEURISTIC_AGG(work-order-completed-per-day)'
4958
+ };
4959
+ }
4960
+ if (/\btop\s+10\b/.test(text)
4961
+ && /\bcustomers?\b/.test(text)
4962
+ && /\bwork[\s-]*orders?\b/.test(text)
4963
+ && /\b(last|past)\s+6\s+months?\b/.test(text)) {
4964
+ return {
4965
+ type: 'aggregate',
4966
+ payload: {
4967
+ collection: 'work-order-dynamics',
4968
+ permissionView: '/work-order-dynamic/list',
4969
+ pipeline: [
4970
+ {
4971
+ $match: {
4972
+ date_created: {
4973
+ $gte: { $dateSubtract: { startDate: '$$NOW', unit: 'month', amount: 6 } },
4974
+ $lt: '$$NOW'
4975
+ }
4976
+ }
4977
+ },
4978
+ {
4979
+ $group: {
4980
+ _id: { $ifNull: ['$customer', 'Unknown'] },
4981
+ work_order_count: { $sum: 1 }
4982
+ }
4983
+ },
4984
+ { $sort: { work_order_count: -1, _id: 1 } },
4985
+ { $limit: 10 },
4986
+ {
4987
+ $project: {
4988
+ _id: 0,
4989
+ customer: '$_id',
4990
+ work_order_count: 1
4991
+ }
4992
+ }
4993
+ ]
4994
+ },
4995
+ cleaned: '',
4996
+ rawLine: 'HEURISTIC_AGG(work-order-top-customers)'
4997
+ };
4998
+ }
4999
+ if (/\bblend(?:ing)?\b/.test(text)
5000
+ && /\b(last\s+10)\b/.test(text)
5001
+ && /\b(summarize|summary)\b/.test(text)
5002
+ && /\btickets?\b/.test(text)) {
5003
+ return {
5004
+ type: 'aggregate',
5005
+ payload: {
5006
+ collection: 'chemical-blends',
5007
+ permissionView: '/report-builder/list',
5008
+ pipeline: [
5009
+ { $sort: { date: -1, createdAt: -1, _id: -1 } },
5010
+ { $limit: 10 },
5011
+ {
5012
+ $project: {
5013
+ _id: 0,
5014
+ product: buildAssistantTrimmedStringExpr({ $ifNull: ['$blend_name', '$chemical'] }),
5015
+ total_volume: { $ifNull: ['$chemical_recipe_quantity', 0] },
5016
+ volume_unit: buildAssistantTrimmedStringExpr({
5017
+ $cond: [{ $eq: ['$blend_in_pounds', true] }, 'lb', 'gal']
5018
+ }),
5019
+ created_date: { $ifNull: ['$date', '$createdAt'] },
5020
+ batch_number: buildAssistantTrimmedStringExpr('$batch_number')
5021
+ }
5022
+ }
5023
+ ]
5024
+ },
5025
+ cleaned: '',
5026
+ rawLine: 'HEURISTIC_AGG(blend-last10-summary)'
5027
+ };
5028
+ }
5029
+ if (/\bblend(?:ing)?\b/.test(text)
5030
+ && /\bthroughput\b/.test(text)
5031
+ && /\b(per|by)\s+day\b/.test(text)
5032
+ && /\b(last|past)\s+2\s+weeks?\b/.test(text)) {
5033
+ return {
5034
+ type: 'aggregate',
5035
+ payload: {
5036
+ collection: 'chemical-blends',
5037
+ permissionView: '/report-builder/list',
5038
+ pipeline: [
5039
+ {
5040
+ $match: {
5041
+ date: {
5042
+ $gte: { $dateSubtract: { startDate: '$$NOW', unit: 'day', amount: 14 } },
5043
+ $lt: '$$NOW'
5044
+ }
5045
+ }
5046
+ },
5047
+ {
5048
+ $group: {
5049
+ _id: {
5050
+ $dateToString: {
5051
+ format: '%Y-%m-%d',
5052
+ date: '$date',
5053
+ timezone: 'UTC'
5054
+ }
5055
+ },
5056
+ blend_count: { $sum: 1 },
5057
+ total_volume: { $sum: { $ifNull: ['$chemical_recipe_quantity', 0] } }
5058
+ }
5059
+ },
5060
+ { $sort: { _id: 1 } },
5061
+ {
5062
+ $project: {
5063
+ _id: 0,
5064
+ day_utc: '$_id',
5065
+ blend_count: 1,
5066
+ total_volume: 1
5067
+ }
5068
+ }
5069
+ ]
5070
+ },
5071
+ cleaned: '',
5072
+ rawLine: 'HEURISTIC_AGG(blend-throughput-by-day)'
5073
+ };
5074
+ }
5075
+ if (/\bdeliver(?:y|ies)\b/.test(text)
5076
+ && /\bdrivers?\b/.test(text)
5077
+ && /\blast\s+month\b/.test(text)) {
5078
+ var thisMonthStart = { $dateTrunc: { date: '$$NOW', unit: 'month' } };
5079
+ return {
5080
+ type: 'aggregate',
5081
+ payload: {
5082
+ collection: 'work-order-dynamics',
5083
+ permissionView: '/work-order-dynamic/list',
5084
+ pipeline: [
5085
+ {
5086
+ $match: {
5087
+ date_completed: {
5088
+ $gte: { $dateSubtract: { startDate: thisMonthStart, unit: 'month', amount: 1 } },
5089
+ $lt: thisMonthStart
5090
+ },
5091
+ status: { $in: ['Completed', 'Closed'] }
5092
+ }
5093
+ },
5094
+ { $unwind: { path: '$drivers', preserveNullAndEmptyArrays: true } },
5095
+ {
5096
+ $group: {
5097
+ _id: { $ifNull: ['$drivers.user', 'Unassigned'] },
5098
+ delivery_count: { $sum: 1 }
5099
+ }
5100
+ },
5101
+ { $sort: { delivery_count: -1, _id: 1 } },
5102
+ {
5103
+ $project: {
5104
+ _id: 0,
5105
+ driver: '$_id',
5106
+ delivery_count: 1
5107
+ }
5108
+ }
5109
+ ]
5110
+ },
5111
+ cleaned: '',
5112
+ rawLine: 'HEURISTIC_AGG(deliveries-per-driver-last-month)'
5113
+ };
5114
+ }
4405
5115
  if (/(which\s+blends?|blends?\s+used).*(red\s+ultra\s+lift|chemical\s+red\s+ultra\s+lift)/.test(text)
4406
5116
  && /(last|past)\s+30\s+days/.test(text)) {
4407
5117
  return {
@@ -4513,7 +5223,7 @@ function buildAssistantHeuristicDirective(message, collectionHints) {
4513
5223
  pipeline: [
4514
5224
  {
4515
5225
  $addFields: {
4516
- effective_date: { $ifNull: ['$date_paid', '$date_invoiced', '$createdAt'] },
5226
+ effective_date: { $ifNull: ['$date_paid', { $ifNull: ['$date_invoiced', '$createdAt'] }] },
4517
5227
  effective_total: { $ifNull: ['$paid_total', '$grand_total'] }
4518
5228
  }
4519
5229
  },
@@ -4527,7 +5237,7 @@ function buildAssistantHeuristicDirective(message, collectionHints) {
4527
5237
  },
4528
5238
  {
4529
5239
  $group: {
4530
- _id: { $ifNull: ['$customer', { $ifNull: ['$id_customer', 'Unknown'] }] },
5240
+ _id: buildAssistantInvoiceCustomerLabelExpr(),
4531
5241
  invoice_total: { $sum: { $ifNull: ['$effective_total', 0] } },
4532
5242
  invoice_count: { $sum: 1 }
4533
5243
  }
@@ -4553,7 +5263,7 @@ function buildAssistantHeuristicDirective(message, collectionHints) {
4553
5263
  type: 'aggregate',
4554
5264
  payload: {
4555
5265
  collection: 'work-order-dynamics',
4556
- permissionView: '/work-order/list',
5266
+ permissionView: '/work-order-dynamic/list',
4557
5267
  pipeline: [
4558
5268
  {
4559
5269
  $match: {
@@ -4636,6 +5346,9 @@ function resolveDefaultAssistantPermissionView(collection) {
4636
5346
  if (base.startsWith('employee')) {
4637
5347
  return '/employee/list';
4638
5348
  }
5349
+ if (base.startsWith('support-ticket') || base.startsWith('supportticket')) {
5350
+ return '/support-ticket/list';
5351
+ }
4639
5352
  return '/report-builder';
4640
5353
  }
4641
5354
  function normalizeAssistantPermissionView(permissionView, collection) {
@@ -4716,7 +5429,7 @@ function ensureAssistantDisplayColumns(display, requestedColumns) {
4716
5429
  return __assign(__assign({}, display), { columns: columns, rows: rows });
4717
5430
  }
4718
5431
  function resolveAssistantPipelineTimeGrain(pipeline) {
4719
- var e_1, _a;
5432
+ var e_3, _a;
4720
5433
  if (!Array.isArray(pipeline) || !pipeline.length) {
4721
5434
  return null;
4722
5435
  }
@@ -4778,12 +5491,12 @@ function resolveAssistantPipelineTimeGrain(pipeline) {
4778
5491
  }
4779
5492
  }
4780
5493
  }
4781
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
5494
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
4782
5495
  finally {
4783
5496
  try {
4784
5497
  if (priority_1_1 && !priority_1_1.done && (_a = priority_1.return)) _a.call(priority_1);
4785
5498
  }
4786
- finally { if (e_1) throw e_1.error; }
5499
+ finally { if (e_3) throw e_3.error; }
4787
5500
  }
4788
5501
  return null;
4789
5502
  }
@@ -5284,18 +5997,20 @@ function buildAssistantToolResultPayload(directive, toolResponse, requestMessage
5284
5997
  };
5285
5998
  }
5286
5999
  function resolveAssistantToolResultResponseMaxRows(directive, directivePayload, rowCount) {
5287
- var _a;
6000
+ var _a, _b;
5288
6001
  if (directive.type !== 'aggregate') {
5289
6002
  return AI_ASSISTANT_DISPLAY_PREVIEW_MAX_ROWS;
5290
6003
  }
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)
6004
+ var exportMode = ((_a = directivePayload === null || directivePayload === void 0 ? void 0 : directivePayload.options) === null || _a === void 0 ? void 0 : _a.export) === true;
6005
+ var maxRows = exportMode ? AI_ASSISTANT_MONGO_EXPORT_MAX_LIMIT : AI_ASSISTANT_MONGO_MAX_LIMIT;
6006
+ var requestedLimit = typeof ((_b = directivePayload === null || directivePayload === void 0 ? void 0 : directivePayload.options) === null || _b === void 0 ? void 0 : _b.limit) === 'number'
6007
+ ? Math.min(Math.max((0, common_1.round)(directivePayload.options.limit), 0), maxRows)
5293
6008
  : 0;
5294
6009
  if (requestedLimit > 0) {
5295
6010
  return requestedLimit;
5296
6011
  }
5297
6012
  if (typeof rowCount === 'number' && rowCount > 0) {
5298
- return Math.min(rowCount, AI_ASSISTANT_MONGO_MAX_LIMIT);
6013
+ return Math.min(rowCount, maxRows);
5299
6014
  }
5300
6015
  return AI_ASSISTANT_DISPLAY_PREVIEW_MAX_ROWS;
5301
6016
  }
@@ -5484,7 +6199,7 @@ function applyAssistantDatedReportWindow(value, toolResult) {
5484
6199
  return "".concat(line, "\n\n").concat(content).trim();
5485
6200
  }
5486
6201
  function resolveAssistantDatedReportWindow(toolResult) {
5487
- var e_2, _a;
6202
+ var e_4, _a;
5488
6203
  var _b, _c, _d, _e, _f, _g, _h, _j;
5489
6204
  var verificationWindow = (_d = (_c = (_b = toolResult === null || toolResult === void 0 ? void 0 : toolResult.output) === null || _b === void 0 ? void 0 : _b.verification) === null || _c === void 0 ? void 0 : _c.metrics) === null || _d === void 0 ? void 0 : _d.window;
5490
6205
  var verificationStart = normalizeOptionalString(verificationWindow === null || verificationWindow === void 0 ? void 0 : verificationWindow.startDate);
@@ -5550,17 +6265,17 @@ function resolveAssistantDatedReportWindow(toolResult) {
5550
6265
  };
5551
6266
  }
5552
6267
  }
5553
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
6268
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
5554
6269
  finally {
5555
6270
  try {
5556
6271
  if (pipelineCandidates_1_1 && !pipelineCandidates_1_1.done && (_a = pipelineCandidates_1.return)) _a.call(pipelineCandidates_1);
5557
6272
  }
5558
- finally { if (e_2) throw e_2.error; }
6273
+ finally { if (e_4) throw e_4.error; }
5559
6274
  }
5560
6275
  return null;
5561
6276
  }
5562
6277
  function buildAssistantDebugPayload(params) {
5563
- 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;
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;
5564
6279
  var notes = [];
5565
6280
  notes.push("Request classification: ".concat(params.requestType, " (").concat(params.requestTypeSource, ")."));
5566
6281
  if (params.dataQuestion) {
@@ -5578,6 +6293,12 @@ function buildAssistantDebugPayload(params) {
5578
6293
  notes.push('Directive did not include explicit time-based grouping.');
5579
6294
  }
5580
6295
  }
6296
+ if (params.reportStyleIntent === 'grouped') {
6297
+ notes.push('Report style intent: grouped.');
6298
+ if (params.datedDirectiveRetryUsed) {
6299
+ notes.push('Retried directive generation to enforce grouped aggregation.');
6300
+ }
6301
+ }
5581
6302
  if (params.directiveSource === 'forced') {
5582
6303
  notes.push('Assistant response omitted a REPORT_BUILDER_* directive; ran a directive-only pass.');
5583
6304
  }
@@ -5684,14 +6405,22 @@ function buildAssistantDebugPayload(params) {
5684
6405
  var to = fallbackInfo.reportFallback.to || 'base';
5685
6406
  notes.push("Report fallback: ".concat(from, " -> ").concat(to, "."));
5686
6407
  }
5687
- if ((_w = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idLookup) === null || _w === void 0 ? void 0 : _w.used) {
6408
+ if ((_w = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.collectionRetry) === null || _w === void 0 ? void 0 : _w.used) {
6409
+ var from = fallbackInfo.collectionRetry.from || 'unknown';
6410
+ var to = fallbackInfo.collectionRetry.to || 'unknown';
6411
+ notes.push("Cross-collection retry: ".concat(from, " -> ").concat(to, "."));
6412
+ }
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) {
6414
+ notes.push("Cross-collection retry attempted: ".concat(fallbackInfo.collectionRetry.tried.join(', '), "."));
6415
+ }
6416
+ if ((_y = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idLookup) === null || _y === void 0 ? void 0 : _y.used) {
5688
6417
  var field = fallbackInfo.idLookup.field || 'id';
5689
6418
  var strategy = fallbackInfo.idLookup.strategy || 'lookup';
5690
6419
  var collection = fallbackInfo.idLookup.collection ? " in ".concat(fallbackInfo.idLookup.collection) : '';
5691
6420
  var detail = fallbackInfo.idLookup.nameField ? " via ".concat(fallbackInfo.idLookup.nameField) : '';
5692
6421
  notes.push("Resolved ".concat(field, " by ").concat(strategy).concat(collection).concat(detail, "."));
5693
6422
  }
5694
- if ((_x = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idDisplayLookup) === null || _x === void 0 ? void 0 : _x.used) {
6423
+ if ((_z = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idDisplayLookup) === null || _z === void 0 ? void 0 : _z.used) {
5695
6424
  var lookups = Array.isArray(fallbackInfo.idDisplayLookup.lookups)
5696
6425
  ? fallbackInfo.idDisplayLookup.lookups
5697
6426
  : [];
@@ -5702,7 +6431,7 @@ function buildAssistantDebugPayload(params) {
5702
6431
  notes.push(summary ? "Resolved id lookups for display: ".concat(summary, ".") : 'Resolved id lookups for display.');
5703
6432
  }
5704
6433
  if (params.toolError) {
5705
- var errorMessage = ((_y = params.toolError) === null || _y === void 0 ? void 0 : _y.message) || String(params.toolError || '');
6434
+ var errorMessage = ((_0 = params.toolError) === null || _0 === void 0 ? void 0 : _0.message) || String(params.toolError || '');
5706
6435
  if (errorMessage) {
5707
6436
  notes.push("Tool error: ".concat(errorMessage));
5708
6437
  }
@@ -5730,13 +6459,13 @@ function buildAssistantDebugPayload(params) {
5730
6459
  collectionResolved: resolvedCollection || undefined,
5731
6460
  collectionMatched: matchedCollection,
5732
6461
  collectionCandidates: candidateCollections.length ? candidateCollections : undefined,
5733
- collectionScore: typeof ((_z = params.toolResponseDebug) === null || _z === void 0 ? void 0 : _z.collectionScore) === 'number'
6462
+ collectionScore: typeof ((_1 = params.toolResponseDebug) === null || _1 === void 0 ? void 0 : _1.collectionScore) === 'number'
5734
6463
  ? params.toolResponseDebug.collectionScore
5735
6464
  : undefined,
5736
- query: ((_0 = params.toolResponseDebug) === null || _0 === void 0 ? void 0 : _0.query) || undefined,
5737
- pipeline: ((_1 = params.toolResponseDebug) === null || _1 === void 0 ? void 0 : _1.executedPipeline) || ((_2 = params.toolResponseDebug) === null || _2 === void 0 ? void 0 : _2.originalPipeline) || undefined,
5738
- options: ((_3 = params.toolResponseDebug) === null || _3 === void 0 ? void 0 : _3.options) || undefined,
5739
- fallbacks: ((_4 = params.toolResponseDebug) === null || _4 === void 0 ? void 0 : _4.fallbacks) || 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,
5740
6469
  notes: notes
5741
6470
  };
5742
6471
  if (params.trace && typeof params.trace === 'object') {
@@ -6117,7 +6846,7 @@ function getValueAtPath(obj, path) {
6117
6846
  return walk(obj, 0);
6118
6847
  }
6119
6848
  function hasArrayValueAtPath(docs, path) {
6120
- var e_3, _a;
6849
+ var e_5, _a;
6121
6850
  if (!Array.isArray(docs) || !docs.length || !path) {
6122
6851
  return false;
6123
6852
  }
@@ -6130,17 +6859,17 @@ function hasArrayValueAtPath(docs, path) {
6130
6859
  }
6131
6860
  }
6132
6861
  }
6133
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
6862
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
6134
6863
  finally {
6135
6864
  try {
6136
6865
  if (docs_1_1 && !docs_1_1.done && (_a = docs_1.return)) _a.call(docs_1);
6137
6866
  }
6138
- finally { if (e_3) throw e_3.error; }
6867
+ finally { if (e_5) throw e_5.error; }
6139
6868
  }
6140
6869
  return false;
6141
6870
  }
6142
6871
  function inferIdFieldStorageTypeFromDocs(docs, fieldPath) {
6143
- var e_4, _a, e_5, _b;
6872
+ var e_6, _a, e_7, _b;
6144
6873
  if (!Array.isArray(docs) || !fieldPath) {
6145
6874
  return 'unknown';
6146
6875
  }
@@ -6153,7 +6882,7 @@ function inferIdFieldStorageTypeFromDocs(docs, fieldPath) {
6153
6882
  : doc === null || doc === void 0 ? void 0 : doc[fieldPath];
6154
6883
  var queue = Array.isArray(value) ? value : [value];
6155
6884
  try {
6156
- for (var queue_1 = (e_5 = void 0, __values(queue)), queue_1_1 = queue_1.next(); !queue_1_1.done; queue_1_1 = queue_1.next()) {
6885
+ for (var queue_1 = (e_7 = void 0, __values(queue)), queue_1_1 = queue_1.next(); !queue_1_1.done; queue_1_1 = queue_1.next()) {
6157
6886
  var entry = queue_1_1.value;
6158
6887
  if (entry === null || entry === undefined) {
6159
6888
  continue;
@@ -6166,21 +6895,21 @@ function inferIdFieldStorageTypeFromDocs(docs, fieldPath) {
6166
6895
  }
6167
6896
  }
6168
6897
  }
6169
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
6898
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
6170
6899
  finally {
6171
6900
  try {
6172
6901
  if (queue_1_1 && !queue_1_1.done && (_b = queue_1.return)) _b.call(queue_1);
6173
6902
  }
6174
- finally { if (e_5) throw e_5.error; }
6903
+ finally { if (e_7) throw e_7.error; }
6175
6904
  }
6176
6905
  }
6177
6906
  }
6178
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
6907
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
6179
6908
  finally {
6180
6909
  try {
6181
6910
  if (docs_2_1 && !docs_2_1.done && (_a = docs_2.return)) _a.call(docs_2);
6182
6911
  }
6183
- finally { if (e_4) throw e_4.error; }
6912
+ finally { if (e_6) throw e_6.error; }
6184
6913
  }
6185
6914
  return sawString ? 'string' : 'unknown';
6186
6915
  }
@@ -6275,7 +7004,7 @@ function normalizeLookupKeyValue(value) {
6275
7004
  return '';
6276
7005
  }
6277
7006
  function collectTopLevelIdFieldValues(docs, options) {
6278
- var e_6, _a, e_7, _b;
7007
+ var e_8, _a, e_9, _b;
6279
7008
  if (!Array.isArray(docs) || !docs.length) {
6280
7009
  return [];
6281
7010
  }
@@ -6323,26 +7052,26 @@ function collectTopLevelIdFieldValues(docs, options) {
6323
7052
  });
6324
7053
  };
6325
7054
  try {
6326
- for (var keys_1 = (e_7 = void 0, __values(keys)), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
7055
+ for (var keys_1 = (e_9 = void 0, __values(keys)), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
6327
7056
  var key = keys_1_1.value;
6328
7057
  _loop_3(key);
6329
7058
  }
6330
7059
  }
6331
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
7060
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
6332
7061
  finally {
6333
7062
  try {
6334
7063
  if (keys_1_1 && !keys_1_1.done && (_b = keys_1.return)) _b.call(keys_1);
6335
7064
  }
6336
- finally { if (e_7) throw e_7.error; }
7065
+ finally { if (e_9) throw e_9.error; }
6337
7066
  }
6338
7067
  }
6339
7068
  }
6340
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
7069
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
6341
7070
  finally {
6342
7071
  try {
6343
7072
  if (docs_3_1 && !docs_3_1.done && (_a = docs_3.return)) _a.call(docs_3);
6344
7073
  }
6345
- finally { if (e_6) throw e_6.error; }
7074
+ finally { if (e_8) throw e_8.error; }
6346
7075
  }
6347
7076
  return Array.from(fieldMap.entries()).map(function (_a) {
6348
7077
  var _b = __read(_a, 2), field = _b[0], values = _b[1];
@@ -6353,7 +7082,7 @@ function collectTopLevelIdFieldValues(docs, options) {
6353
7082
  });
6354
7083
  }
6355
7084
  function resolveLookupDisplayField(baseToken, probeDocs, schemaFields) {
6356
- var e_8, _a, e_9, _b;
7085
+ var e_10, _a, e_11, _b;
6357
7086
  var normalizedBase = normalizeOptionalString(baseToken);
6358
7087
  if (!normalizedBase) {
6359
7088
  return null;
@@ -6371,12 +7100,12 @@ function resolveLookupDisplayField(baseToken, probeDocs, schemaFields) {
6371
7100
  }
6372
7101
  }
6373
7102
  }
6374
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
7103
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
6375
7104
  finally {
6376
7105
  try {
6377
7106
  if (schemaCandidates_1_1 && !schemaCandidates_1_1.done && (_a = schemaCandidates_1.return)) _a.call(schemaCandidates_1);
6378
7107
  }
6379
- finally { if (e_8) throw e_8.error; }
7108
+ finally { if (e_10) throw e_10.error; }
6380
7109
  }
6381
7110
  return schemaCandidates[0];
6382
7111
  }
@@ -6389,12 +7118,12 @@ function resolveLookupDisplayField(baseToken, probeDocs, schemaFields) {
6389
7118
  }
6390
7119
  }
6391
7120
  }
6392
- catch (e_9_1) { e_9 = { error: e_9_1 }; }
7121
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
6393
7122
  finally {
6394
7123
  try {
6395
7124
  if (candidates_1_1 && !candidates_1_1.done && (_b = candidates_1.return)) _b.call(candidates_1);
6396
7125
  }
6397
- finally { if (e_9) throw e_9.error; }
7126
+ finally { if (e_11) throw e_11.error; }
6398
7127
  }
6399
7128
  return candidates.length ? candidates[0] : null;
6400
7129
  }
@@ -6407,8 +7136,8 @@ function resolveLookupMappingsForField(field, mappings) {
6407
7136
  }
6408
7137
  function applyIdLookupDisplayEnrichment(params) {
6409
7138
  return __awaiter(this, void 0, void 0, function () {
6410
- var docs, collection, db, dbName, idClient, idCustomer, isSuperAdmin, idFields, lookupMappings, allCollections, collectionProbeCache, collectionSchemaCache, lookupMeta, enrichedDocs, _loop_4, idFields_1, idFields_1_1, fieldEntry, e_10_1;
6411
- var e_10, _a;
7139
+ var docs, collection, db, dbName, idClient, idCustomer, isSuperAdmin, idFields, lookupMappings, allCollections, collectionProbeCache, collectionSchemaCache, lookupMeta, enrichedDocs, _loop_4, idFields_1, idFields_1_1, fieldEntry, e_12_1;
7140
+ var e_12, _a;
6412
7141
  return __generator(this, function (_b) {
6413
7142
  switch (_b.label) {
6414
7143
  case 0:
@@ -6432,8 +7161,8 @@ function applyIdLookupDisplayEnrichment(params) {
6432
7161
  lookupMeta = [];
6433
7162
  enrichedDocs = docs.map(function (doc) { return (__assign({}, doc)); });
6434
7163
  _loop_4 = function (fieldEntry) {
6435
- var values, baseToken, mappingMatches, candidateCollections, filteredCandidates, _loop_5, filteredCandidates_1, filteredCandidates_1_1, candidate, state_3, e_11_1;
6436
- var e_11, _c;
7164
+ var values, baseToken, mappingMatches, candidateCollections, filteredCandidates, _loop_5, filteredCandidates_1, filteredCandidates_1_1, candidate, state_3, e_13_1;
7165
+ var e_13, _c;
6437
7166
  return __generator(this, function (_d) {
6438
7167
  switch (_d.label) {
6439
7168
  case 0:
@@ -6582,7 +7311,7 @@ function applyIdLookupDisplayEnrichment(params) {
6582
7311
  _d.label = 1;
6583
7312
  case 1:
6584
7313
  _d.trys.push([1, 6, 7, 8]);
6585
- filteredCandidates_1 = (e_11 = void 0, __values(filteredCandidates)), filteredCandidates_1_1 = filteredCandidates_1.next();
7314
+ filteredCandidates_1 = (e_13 = void 0, __values(filteredCandidates)), filteredCandidates_1_1 = filteredCandidates_1.next();
6586
7315
  _d.label = 2;
6587
7316
  case 2:
6588
7317
  if (!!filteredCandidates_1_1.done) return [3 /*break*/, 5];
@@ -6598,14 +7327,14 @@ function applyIdLookupDisplayEnrichment(params) {
6598
7327
  return [3 /*break*/, 2];
6599
7328
  case 5: return [3 /*break*/, 8];
6600
7329
  case 6:
6601
- e_11_1 = _d.sent();
6602
- e_11 = { error: e_11_1 };
7330
+ e_13_1 = _d.sent();
7331
+ e_13 = { error: e_13_1 };
6603
7332
  return [3 /*break*/, 8];
6604
7333
  case 7:
6605
7334
  try {
6606
7335
  if (filteredCandidates_1_1 && !filteredCandidates_1_1.done && (_c = filteredCandidates_1.return)) _c.call(filteredCandidates_1);
6607
7336
  }
6608
- finally { if (e_11) throw e_11.error; }
7337
+ finally { if (e_13) throw e_13.error; }
6609
7338
  return [7 /*endfinally*/];
6610
7339
  case 8: return [2 /*return*/];
6611
7340
  }
@@ -6628,14 +7357,14 @@ function applyIdLookupDisplayEnrichment(params) {
6628
7357
  return [3 /*break*/, 3];
6629
7358
  case 6: return [3 /*break*/, 9];
6630
7359
  case 7:
6631
- e_10_1 = _b.sent();
6632
- e_10 = { error: e_10_1 };
7360
+ e_12_1 = _b.sent();
7361
+ e_12 = { error: e_12_1 };
6633
7362
  return [3 /*break*/, 9];
6634
7363
  case 8:
6635
7364
  try {
6636
7365
  if (idFields_1_1 && !idFields_1_1.done && (_a = idFields_1.return)) _a.call(idFields_1);
6637
7366
  }
6638
- finally { if (e_10) throw e_10.error; }
7367
+ finally { if (e_12) throw e_12.error; }
6639
7368
  return [7 /*endfinally*/];
6640
7369
  case 9:
6641
7370
  if (!lookupMeta.length) {
@@ -6654,7 +7383,7 @@ function applyIdLookupDisplayEnrichment(params) {
6654
7383
  });
6655
7384
  }
6656
7385
  function hasNonEmptyValue(docs, fieldPath, options) {
6657
- var e_12, _a;
7386
+ var e_14, _a;
6658
7387
  if (!Array.isArray(docs) || !fieldPath) {
6659
7388
  return false;
6660
7389
  }
@@ -6671,12 +7400,12 @@ function hasNonEmptyValue(docs, fieldPath, options) {
6671
7400
  }
6672
7401
  }
6673
7402
  }
6674
- catch (e_12_1) { e_12 = { error: e_12_1 }; }
7403
+ catch (e_14_1) { e_14 = { error: e_14_1 }; }
6675
7404
  finally {
6676
7405
  try {
6677
7406
  if (docs_4_1 && !docs_4_1.done && (_a = docs_4.return)) _a.call(docs_4);
6678
7407
  }
6679
- finally { if (e_12) throw e_12.error; }
7408
+ finally { if (e_14) throw e_14.error; }
6680
7409
  }
6681
7410
  return false;
6682
7411
  }
@@ -7614,20 +8343,26 @@ function isAssistantMarkdownTableRowLine(line) {
7614
8343
  return /^\|.*\|$/.test(trimmed);
7615
8344
  }
7616
8345
  function ensureAssistantMinimumDisplayColumns(display) {
8346
+ var _a;
7617
8347
  if (!display || !Array.isArray(display.columns) || display.columns.length !== 1) {
7618
8348
  return display;
7619
8349
  }
7620
8350
  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 });
8351
+ var rows = Array.isArray(display.rows) ? display.rows : [];
8352
+ if (!rows.length) {
8353
+ return display;
8354
+ }
8355
+ var labels = rows
8356
+ .map(function (row) { return normalizeOptionalString((row || {})[primary]) || 'Unknown'; })
8357
+ .filter(Boolean);
8358
+ var uniqueLabels = Array.from(new Set(labels));
8359
+ if (uniqueLabels.length !== 1) {
8360
+ return display;
8361
+ }
8362
+ var totalCount = typeof display.rowCount === 'number' && display.rowCount > 0
8363
+ ? display.rowCount
8364
+ : rows.length;
8365
+ return __assign(__assign({}, display), { columns: [primary, 'Count'], rows: [(_a = {}, _a[primary] = uniqueLabels[0], _a.Count = totalCount, _a)], rowCount: 1, truncated: false });
7631
8366
  }
7632
8367
  function applyAssistantDisplayTableToResponse(value, display) {
7633
8368
  if (!display || !Array.isArray(display.rows)) {
@@ -7636,14 +8371,24 @@ function applyAssistantDisplayTableToResponse(value, display) {
7636
8371
  var normalizedDisplay = ensureAssistantMinimumDisplayColumns(display);
7637
8372
  if (!display.rows.length) {
7638
8373
  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
- };
8374
+ var rowCount = typeof normalizedDisplay.rowCount === 'number' && normalizedDisplay.rowCount > 0
8375
+ ? normalizedDisplay.rowCount
8376
+ : 0;
8377
+ var tableDisplay = rowCount > 0
8378
+ ? {
8379
+ columns: ['Metric', 'Value'],
8380
+ rows: [{ Metric: 'Rows matched', Value: rowCount }],
8381
+ rowCount: 1,
8382
+ truncated: false,
8383
+ includeIds: false
8384
+ }
8385
+ : {
8386
+ columns: ['Result', 'Details'],
8387
+ rows: [{ Result: 'No matching rows', Details: '' }],
8388
+ rowCount: 0,
8389
+ truncated: false,
8390
+ includeIds: false
8391
+ };
7647
8392
  var emptyTable = formatDisplayTableMarkdown(tableDisplay);
7648
8393
  if (!emptyTable) {
7649
8394
  return cleaned_1 || value;
@@ -7750,6 +8495,15 @@ function resolveAssistantDatabaseName(database, mongoConfig) {
7750
8495
  }
7751
8496
  return dbName;
7752
8497
  }
8498
+ function resolveAssistantReadDisplayMaxRows(limit, rowCount) {
8499
+ if (typeof limit === 'number' && Number.isFinite(limit) && limit > 0) {
8500
+ return Math.max((0, common_1.round)(limit), 1);
8501
+ }
8502
+ if (typeof rowCount === 'number' && Number.isFinite(rowCount) && rowCount > 0) {
8503
+ return Math.min(Math.max((0, common_1.round)(rowCount), 1), AI_ASSISTANT_DISPLAY_PREVIEW_MAX_ROWS);
8504
+ }
8505
+ return AI_ASSISTANT_DISPLAY_PREVIEW_MAX_ROWS;
8506
+ }
7753
8507
  function normalizeAssistantFindOptions(options) {
7754
8508
  var normalized = options || {};
7755
8509
  var exportMode = normalized.export === true;
@@ -8676,7 +9430,7 @@ function flattenAssistantExprClauses(expr) {
8676
9430
  return [expr];
8677
9431
  }
8678
9432
  function detectAssistantMonthWindowInExpr(expr, allowedDateFields) {
8679
- var e_13, _a;
9433
+ var e_15, _a;
8680
9434
  var clauses = flattenAssistantExprClauses(expr);
8681
9435
  if (!clauses.length) {
8682
9436
  return null;
@@ -8750,12 +9504,12 @@ function detectAssistantMonthWindowInExpr(expr, allowedDateFields) {
8750
9504
  return state_4.value;
8751
9505
  }
8752
9506
  }
8753
- catch (e_13_1) { e_13 = { error: e_13_1 }; }
9507
+ catch (e_15_1) { e_15 = { error: e_15_1 }; }
8754
9508
  finally {
8755
9509
  try {
8756
9510
  if (lowerClauses_1_1 && !lowerClauses_1_1.done && (_a = lowerClauses_1.return)) _a.call(lowerClauses_1);
8757
9511
  }
8758
- finally { if (e_13) throw e_13.error; }
9512
+ finally { if (e_15) throw e_15.error; }
8759
9513
  }
8760
9514
  return null;
8761
9515
  }
@@ -8818,7 +9572,7 @@ function resolveAssistantMonthlyGroupDateFields(pipeline) {
8818
9572
  return fields;
8819
9573
  }
8820
9574
  function detectAssistantMonthWindowFromPipeline(pipeline) {
8821
- var e_14, _a;
9575
+ var e_16, _a;
8822
9576
  var _b;
8823
9577
  var monthlyFields = resolveAssistantMonthlyGroupDateFields(pipeline);
8824
9578
  var scanMatch = function (match) {
@@ -8846,12 +9600,12 @@ function detectAssistantMonthWindowFromPipeline(pipeline) {
8846
9600
  }
8847
9601
  }
8848
9602
  }
8849
- catch (e_14_1) { e_14 = { error: e_14_1 }; }
9603
+ catch (e_16_1) { e_16 = { error: e_16_1 }; }
8850
9604
  finally {
8851
9605
  try {
8852
9606
  if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
8853
9607
  }
8854
- finally { if (e_14) throw e_14.error; }
9608
+ finally { if (e_16) throw e_16.error; }
8855
9609
  }
8856
9610
  return null;
8857
9611
  }
@@ -9054,7 +9808,7 @@ function matchContainsField(value, field) {
9054
9808
  });
9055
9809
  }
9056
9810
  function resolveAggregateCompletionFallback(pipeline) {
9057
- var e_15, _a;
9811
+ var e_17, _a;
9058
9812
  if (!Array.isArray(pipeline)) {
9059
9813
  return null;
9060
9814
  }
@@ -9067,7 +9821,7 @@ function resolveAggregateCompletionFallback(pipeline) {
9067
9821
  }
9068
9822
  var addFields = stage.$addFields;
9069
9823
  try {
9070
- for (var _b = (e_15 = void 0, __values(Object.keys(addFields))), _c = _b.next(); !_c.done; _c = _b.next()) {
9824
+ for (var _b = (e_17 = void 0, __values(Object.keys(addFields))), _c = _b.next(); !_c.done; _c = _b.next()) {
9071
9825
  var key = _c.value;
9072
9826
  if (!isCompletionFieldName(key)) {
9073
9827
  continue;
@@ -9081,12 +9835,12 @@ function resolveAggregateCompletionFallback(pipeline) {
9081
9835
  }
9082
9836
  }
9083
9837
  }
9084
- catch (e_15_1) { e_15 = { error: e_15_1 }; }
9838
+ catch (e_17_1) { e_17 = { error: e_17_1 }; }
9085
9839
  finally {
9086
9840
  try {
9087
9841
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
9088
9842
  }
9089
- finally { if (e_15) throw e_15.error; }
9843
+ finally { if (e_17) throw e_17.error; }
9090
9844
  }
9091
9845
  if (candidateField) {
9092
9846
  break;
@@ -9242,7 +9996,7 @@ function buildCompletionFallbackSources(field) {
9242
9996
  ]);
9243
9997
  }
9244
9998
  function resolveAggregateCompletionExprFallback(pipeline) {
9245
- var e_16, _a;
9999
+ var e_18, _a;
9246
10000
  if (!Array.isArray(pipeline)) {
9247
10001
  return null;
9248
10002
  }
@@ -9262,7 +10016,7 @@ function resolveAggregateCompletionExprFallback(pipeline) {
9262
10016
  }
9263
10017
  if (!candidateField) {
9264
10018
  try {
9265
- for (var _b = (e_16 = void 0, __values(Object.keys(matchStage))), _c = _b.next(); !_c.done; _c = _b.next()) {
10019
+ for (var _b = (e_18 = void 0, __values(Object.keys(matchStage))), _c = _b.next(); !_c.done; _c = _b.next()) {
9266
10020
  var key = _c.value;
9267
10021
  if (key.startsWith('$')) {
9268
10022
  continue;
@@ -9277,12 +10031,12 @@ function resolveAggregateCompletionExprFallback(pipeline) {
9277
10031
  }
9278
10032
  }
9279
10033
  }
9280
- catch (e_16_1) { e_16 = { error: e_16_1 }; }
10034
+ catch (e_18_1) { e_18 = { error: e_18_1 }; }
9281
10035
  finally {
9282
10036
  try {
9283
10037
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
9284
10038
  }
9285
- finally { if (e_16) throw e_16.error; }
10039
+ finally { if (e_18) throw e_18.error; }
9286
10040
  }
9287
10041
  }
9288
10042
  if (!candidateField) {
@@ -9422,7 +10176,7 @@ function hasAssistantDateGroupingOperator(value) {
9422
10176
  return Object.keys(value).some(function (key) { return hasAssistantDateGroupingOperator(value[key]); });
9423
10177
  }
9424
10178
  function isGroupFieldDerivedFromDateExpression(pipeline, groupIndex, groupPaths) {
9425
- var e_17, _a, e_18, _b;
10179
+ var e_19, _a, e_20, _b;
9426
10180
  if (!Array.isArray(pipeline) || groupIndex <= 0 || !groupPaths.length) {
9427
10181
  return false;
9428
10182
  }
@@ -9448,14 +10202,14 @@ function isGroupFieldDerivedFromDateExpression(pipeline, groupIndex, groupPaths)
9448
10202
  continue;
9449
10203
  }
9450
10204
  try {
9451
- for (var stageKeys_1 = (e_17 = void 0, __values(stageKeys)), stageKeys_1_1 = stageKeys_1.next(); !stageKeys_1_1.done; stageKeys_1_1 = stageKeys_1.next()) {
10205
+ for (var stageKeys_1 = (e_19 = void 0, __values(stageKeys)), stageKeys_1_1 = stageKeys_1.next(); !stageKeys_1_1.done; stageKeys_1_1 = stageKeys_1.next()) {
9452
10206
  var stageKey = stageKeys_1_1.value;
9453
10207
  var payload = stage[stageKey];
9454
10208
  if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
9455
10209
  continue;
9456
10210
  }
9457
10211
  try {
9458
- for (var groupFields_1 = (e_18 = void 0, __values(groupFields)), groupFields_1_1 = groupFields_1.next(); !groupFields_1_1.done; groupFields_1_1 = groupFields_1.next()) {
10212
+ for (var groupFields_1 = (e_20 = void 0, __values(groupFields)), groupFields_1_1 = groupFields_1.next(); !groupFields_1_1.done; groupFields_1_1 = groupFields_1.next()) {
9459
10213
  var groupField = groupFields_1_1.value;
9460
10214
  if (!Object.prototype.hasOwnProperty.call(payload, groupField)) {
9461
10215
  continue;
@@ -9465,21 +10219,21 @@ function isGroupFieldDerivedFromDateExpression(pipeline, groupIndex, groupPaths)
9465
10219
  }
9466
10220
  }
9467
10221
  }
9468
- catch (e_18_1) { e_18 = { error: e_18_1 }; }
10222
+ catch (e_20_1) { e_20 = { error: e_20_1 }; }
9469
10223
  finally {
9470
10224
  try {
9471
10225
  if (groupFields_1_1 && !groupFields_1_1.done && (_b = groupFields_1.return)) _b.call(groupFields_1);
9472
10226
  }
9473
- finally { if (e_18) throw e_18.error; }
10227
+ finally { if (e_20) throw e_20.error; }
9474
10228
  }
9475
10229
  }
9476
10230
  }
9477
- catch (e_17_1) { e_17 = { error: e_17_1 }; }
10231
+ catch (e_19_1) { e_19 = { error: e_19_1 }; }
9478
10232
  finally {
9479
10233
  try {
9480
10234
  if (stageKeys_1_1 && !stageKeys_1_1.done && (_a = stageKeys_1.return)) _a.call(stageKeys_1);
9481
10235
  }
9482
- finally { if (e_17) throw e_17.error; }
10236
+ finally { if (e_19) throw e_19.error; }
9483
10237
  }
9484
10238
  }
9485
10239
  return false;
@@ -9506,6 +10260,12 @@ function isAssistantTimeGroupedAggregatePipeline(pipeline) {
9506
10260
  }
9507
10261
  return isGroupFieldDerivedFromDateExpression(pipeline, groupIndex, groupPaths);
9508
10262
  }
10263
+ function isAssistantGroupedAggregatePipeline(pipeline) {
10264
+ if (!Array.isArray(pipeline) || !pipeline.length) {
10265
+ return false;
10266
+ }
10267
+ return findAggregateGroupIndex(pipeline) !== -1;
10268
+ }
9509
10269
  function isAssistantDirectiveDated(directive) {
9510
10270
  var _a;
9511
10271
  if (!directive || directive.type !== 'aggregate') {
@@ -9514,6 +10274,14 @@ function isAssistantDirectiveDated(directive) {
9514
10274
  var pipeline = Array.isArray((_a = directive.payload) === null || _a === void 0 ? void 0 : _a.pipeline) ? directive.payload.pipeline : [];
9515
10275
  return isAssistantTimeGroupedAggregatePipeline(pipeline);
9516
10276
  }
10277
+ function isAssistantDirectiveGrouped(directive) {
10278
+ var _a;
10279
+ if (!directive || directive.type !== 'aggregate') {
10280
+ return false;
10281
+ }
10282
+ var pipeline = Array.isArray((_a = directive.payload) === null || _a === void 0 ? void 0 : _a.pipeline) ? directive.payload.pipeline : [];
10283
+ return isAssistantGroupedAggregatePipeline(pipeline);
10284
+ }
9517
10285
  function findCommonPathPrefix(paths) {
9518
10286
  var _a;
9519
10287
  if (!paths.length) {
@@ -9572,7 +10340,7 @@ function isRegexMatchCondition(value) {
9572
10340
  return false;
9573
10341
  }
9574
10342
  function findRegexMatchInMatchObject(match, prefix) {
9575
- var e_19, _a, e_20, _b;
10343
+ var e_21, _a, e_22, _b;
9576
10344
  if (prefix === void 0) { prefix = ''; }
9577
10345
  if (Array.isArray(match)) {
9578
10346
  try {
@@ -9584,12 +10352,12 @@ function findRegexMatchInMatchObject(match, prefix) {
9584
10352
  }
9585
10353
  }
9586
10354
  }
9587
- catch (e_19_1) { e_19 = { error: e_19_1 }; }
10355
+ catch (e_21_1) { e_21 = { error: e_21_1 }; }
9588
10356
  finally {
9589
10357
  try {
9590
10358
  if (match_1_1 && !match_1_1.done && (_a = match_1.return)) _a.call(match_1);
9591
10359
  }
9592
- finally { if (e_19) throw e_19.error; }
10360
+ finally { if (e_21) throw e_21.error; }
9593
10361
  }
9594
10362
  return null;
9595
10363
  }
@@ -9620,12 +10388,12 @@ function findRegexMatchInMatchObject(match, prefix) {
9620
10388
  }
9621
10389
  }
9622
10390
  }
9623
- catch (e_20_1) { e_20 = { error: e_20_1 }; }
10391
+ catch (e_22_1) { e_22 = { error: e_22_1 }; }
9624
10392
  finally {
9625
10393
  try {
9626
10394
  if (keys_2_1 && !keys_2_1.done && (_b = keys_2.return)) _b.call(keys_2);
9627
10395
  }
9628
- finally { if (e_20) throw e_20.error; }
10396
+ finally { if (e_22) throw e_22.error; }
9629
10397
  }
9630
10398
  return null;
9631
10399
  }
@@ -9849,7 +10617,7 @@ function collectMatchFieldsByCondition(match, predicate, prefix) {
9849
10617
  return results;
9850
10618
  }
9851
10619
  function findMatchConditionForField(match, targetField, prefix) {
9852
- var e_21, _a, e_22, _b;
10620
+ var e_23, _a, e_24, _b;
9853
10621
  if (prefix === void 0) { prefix = ''; }
9854
10622
  if (!match || typeof match !== 'object') {
9855
10623
  return undefined;
@@ -9864,12 +10632,12 @@ function findMatchConditionForField(match, targetField, prefix) {
9864
10632
  }
9865
10633
  }
9866
10634
  }
9867
- catch (e_21_1) { e_21 = { error: e_21_1 }; }
10635
+ catch (e_23_1) { e_23 = { error: e_23_1 }; }
9868
10636
  finally {
9869
10637
  try {
9870
10638
  if (match_2_1 && !match_2_1.done && (_a = match_2.return)) _a.call(match_2);
9871
10639
  }
9872
- finally { if (e_21) throw e_21.error; }
10640
+ finally { if (e_23) throw e_23.error; }
9873
10641
  }
9874
10642
  return undefined;
9875
10643
  }
@@ -9896,12 +10664,12 @@ function findMatchConditionForField(match, targetField, prefix) {
9896
10664
  }
9897
10665
  }
9898
10666
  }
9899
- catch (e_22_1) { e_22 = { error: e_22_1 }; }
10667
+ catch (e_24_1) { e_24 = { error: e_24_1 }; }
9900
10668
  finally {
9901
10669
  try {
9902
10670
  if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
9903
10671
  }
9904
- finally { if (e_22) throw e_22.error; }
10672
+ finally { if (e_24) throw e_24.error; }
9905
10673
  }
9906
10674
  return undefined;
9907
10675
  }
@@ -9924,6 +10692,67 @@ function isDateCondition(value) {
9924
10692
  }
9925
10693
  return false;
9926
10694
  }
10695
+ function isAssistantActiveFieldPath(field) {
10696
+ var normalized = normalizeOptionalString(field).toLowerCase();
10697
+ if (!normalized) {
10698
+ return false;
10699
+ }
10700
+ var leaf = normalized.split('.').pop() || normalized;
10701
+ return ['status', 'state', 'active', 'is_active', 'isactive', 'enabled', 'is_enabled', 'isenabled'].includes(leaf);
10702
+ }
10703
+ function isAssistantActiveCondition(value) {
10704
+ if (typeof value === 'boolean') {
10705
+ return value === true;
10706
+ }
10707
+ if (typeof value === 'string') {
10708
+ return /^active$/i.test(value.trim());
10709
+ }
10710
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
10711
+ return false;
10712
+ }
10713
+ var regexValue = value.$regex;
10714
+ if (regexValue instanceof RegExp) {
10715
+ return /active/i.test(regexValue.source);
10716
+ }
10717
+ if (typeof regexValue === 'string' && /active/i.test(regexValue)) {
10718
+ return true;
10719
+ }
10720
+ var eqValue = value.$eq;
10721
+ if (typeof eqValue === 'boolean' && eqValue === true) {
10722
+ return true;
10723
+ }
10724
+ if (typeof eqValue === 'string' && /^active$/i.test(eqValue.trim())) {
10725
+ return true;
10726
+ }
10727
+ var inValues = Array.isArray(value.$in) ? value.$in : [];
10728
+ if (inValues.some(function (entry) { return (typeof entry === 'boolean' && entry === true)
10729
+ || (typeof entry === 'string' && /^active$/i.test(entry.trim())); })) {
10730
+ return true;
10731
+ }
10732
+ return false;
10733
+ }
10734
+ function collectAssistantActiveMatchFields(query) {
10735
+ var fields = collectMatchFieldsByCondition(query, function (field, condition) { return isAssistantActiveFieldPath(field) && isAssistantActiveCondition(condition); });
10736
+ return Array.from(new Set(fields));
10737
+ }
10738
+ function resolveReadActiveStatusFallback(query, probeDocs) {
10739
+ var fields = collectAssistantActiveMatchFields(query);
10740
+ if (!fields.length || !Array.isArray(probeDocs) || !probeDocs.length) {
10741
+ return null;
10742
+ }
10743
+ var hasAnyFieldData = fields.some(function (field) { return hasNonEmptyValue(probeDocs, field, { treatObjectLikeAsEmpty: true }); });
10744
+ if (hasAnyFieldData) {
10745
+ return null;
10746
+ }
10747
+ var stripped = stripQueryFieldPathsDeepWithMeta(query, fields);
10748
+ if (!stripped.changed || !stripped.value || typeof stripped.value !== 'object') {
10749
+ return null;
10750
+ }
10751
+ return {
10752
+ query: stripped.value,
10753
+ fields: fields
10754
+ };
10755
+ }
9927
10756
  function isChemicalFieldPath(field) {
9928
10757
  var normalized = normalizeOptionalString(field).toLowerCase();
9929
10758
  return normalized.includes('chemical');
@@ -9944,7 +10773,7 @@ function detectIdLikeValue(value) {
9944
10773
  return false;
9945
10774
  }
9946
10775
  function detectChemicalIdFromProbe(probeDocs, fields) {
9947
- var e_23, _a, e_24, _b;
10776
+ var e_25, _a, e_26, _b;
9948
10777
  if (!Array.isArray(probeDocs) || !probeDocs.length) {
9949
10778
  return false;
9950
10779
  }
@@ -9956,7 +10785,7 @@ function detectChemicalIdFromProbe(probeDocs, fields) {
9956
10785
  for (var probeDocs_1 = __values(probeDocs), probeDocs_1_1 = probeDocs_1.next(); !probeDocs_1_1.done; probeDocs_1_1 = probeDocs_1.next()) {
9957
10786
  var doc = probeDocs_1_1.value;
9958
10787
  try {
9959
- for (var targets_1 = (e_24 = void 0, __values(targets)), targets_1_1 = targets_1.next(); !targets_1_1.done; targets_1_1 = targets_1.next()) {
10788
+ for (var targets_1 = (e_26 = void 0, __values(targets)), targets_1_1 = targets_1.next(); !targets_1_1.done; targets_1_1 = targets_1.next()) {
9960
10789
  var field = targets_1_1.value;
9961
10790
  var value = getValueAtPath(doc, field);
9962
10791
  if (Array.isArray(value)) {
@@ -9969,21 +10798,21 @@ function detectChemicalIdFromProbe(probeDocs, fields) {
9969
10798
  }
9970
10799
  }
9971
10800
  }
9972
- catch (e_24_1) { e_24 = { error: e_24_1 }; }
10801
+ catch (e_26_1) { e_26 = { error: e_26_1 }; }
9973
10802
  finally {
9974
10803
  try {
9975
10804
  if (targets_1_1 && !targets_1_1.done && (_b = targets_1.return)) _b.call(targets_1);
9976
10805
  }
9977
- finally { if (e_24) throw e_24.error; }
10806
+ finally { if (e_26) throw e_26.error; }
9978
10807
  }
9979
10808
  }
9980
10809
  }
9981
- catch (e_23_1) { e_23 = { error: e_23_1 }; }
10810
+ catch (e_25_1) { e_25 = { error: e_25_1 }; }
9982
10811
  finally {
9983
10812
  try {
9984
10813
  if (probeDocs_1_1 && !probeDocs_1_1.done && (_a = probeDocs_1.return)) _a.call(probeDocs_1);
9985
10814
  }
9986
- finally { if (e_23) throw e_23.error; }
10815
+ finally { if (e_25) throw e_25.error; }
9987
10816
  }
9988
10817
  return false;
9989
10818
  }
@@ -10204,8 +11033,8 @@ function buildChemicalIdFieldCandidates(field) {
10204
11033
  }
10205
11034
  function applyChemicalNameLookupFallbackToQuery(params) {
10206
11035
  return __awaiter(this, void 0, void 0, function () {
10207
- var query, db, dbName, idClient, idCustomer, isSuperAdmin, probeDocs, chemicalFields, targetField, condition, regex, sampleDocs, collectionNames, candidates, _loop_7, candidates_2, candidates_2_1, candidate, state_5, e_25_1;
10208
- var e_25, _a;
11036
+ var query, db, dbName, idClient, idCustomer, isSuperAdmin, probeDocs, chemicalFields, targetField, condition, regex, sampleDocs, collectionNames, candidates, _loop_7, candidates_2, candidates_2_1, candidate, state_5, e_27_1;
11037
+ var e_27, _a;
10209
11038
  var _b;
10210
11039
  return __generator(this, function (_c) {
10211
11040
  switch (_c.label) {
@@ -10318,14 +11147,14 @@ function applyChemicalNameLookupFallbackToQuery(params) {
10318
11147
  return [3 /*break*/, 3];
10319
11148
  case 6: return [3 /*break*/, 9];
10320
11149
  case 7:
10321
- e_25_1 = _c.sent();
10322
- e_25 = { error: e_25_1 };
11150
+ e_27_1 = _c.sent();
11151
+ e_27 = { error: e_27_1 };
10323
11152
  return [3 /*break*/, 9];
10324
11153
  case 8:
10325
11154
  try {
10326
11155
  if (candidates_2_1 && !candidates_2_1.done && (_a = candidates_2.return)) _a.call(candidates_2);
10327
11156
  }
10328
- finally { if (e_25) throw e_25.error; }
11157
+ finally { if (e_27) throw e_27.error; }
10329
11158
  return [7 /*endfinally*/];
10330
11159
  case 9: return [2 /*return*/, null];
10331
11160
  }
@@ -10419,8 +11248,8 @@ function lookupIdsForNameMatch(params) {
10419
11248
  }
10420
11249
  function applyIdLookupFallbackToQuery(params) {
10421
11250
  return __awaiter(this, void 0, void 0, function () {
10422
- var query, db, dbName, idClient, idCustomer, isSuperAdmin, probeDocs, conditions, collectionNames, _a, conditions_1, conditions_1_1, condition, regex, baseToken, targetFieldType, nextValue, localNameField, candidates, candidates_3, candidates_3_1, candidate, candidateHasClientScope, _b, candidateProbe, lookup, targetFieldType, normalizedIds, idsForQuery, e_26_1, e_27_1;
10423
- var e_27, _c, e_26, _d;
11251
+ var query, db, dbName, idClient, idCustomer, isSuperAdmin, probeDocs, conditions, collectionNames, _a, conditions_1, conditions_1_1, condition, regex, baseToken, targetFieldType, nextValue, localNameField, candidates, candidates_3, candidates_3_1, candidate, candidateHasClientScope, _b, candidateProbe, lookup, targetFieldType, normalizedIds, idsForQuery, e_28_1, e_29_1;
11252
+ var e_29, _c, e_28, _d;
10424
11253
  var _e;
10425
11254
  return __generator(this, function (_f) {
10426
11255
  switch (_f.label) {
@@ -10490,7 +11319,7 @@ function applyIdLookupFallbackToQuery(params) {
10490
11319
  _f.label = 5;
10491
11320
  case 5:
10492
11321
  _f.trys.push([5, 14, 15, 16]);
10493
- candidates_3 = (e_26 = void 0, __values(candidates)), candidates_3_1 = candidates_3.next();
11322
+ candidates_3 = (e_28 = void 0, __values(candidates)), candidates_3_1 = candidates_3.next();
10494
11323
  _f.label = 6;
10495
11324
  case 6:
10496
11325
  if (!!candidates_3_1.done) return [3 /*break*/, 13];
@@ -10557,28 +11386,28 @@ function applyIdLookupFallbackToQuery(params) {
10557
11386
  return [3 /*break*/, 6];
10558
11387
  case 13: return [3 /*break*/, 16];
10559
11388
  case 14:
10560
- e_26_1 = _f.sent();
10561
- e_26 = { error: e_26_1 };
11389
+ e_28_1 = _f.sent();
11390
+ e_28 = { error: e_28_1 };
10562
11391
  return [3 /*break*/, 16];
10563
11392
  case 15:
10564
11393
  try {
10565
11394
  if (candidates_3_1 && !candidates_3_1.done && (_d = candidates_3.return)) _d.call(candidates_3);
10566
11395
  }
10567
- finally { if (e_26) throw e_26.error; }
11396
+ finally { if (e_28) throw e_28.error; }
10568
11397
  return [7 /*endfinally*/];
10569
11398
  case 16:
10570
11399
  conditions_1_1 = conditions_1.next();
10571
11400
  return [3 /*break*/, 4];
10572
11401
  case 17: return [3 /*break*/, 20];
10573
11402
  case 18:
10574
- e_27_1 = _f.sent();
10575
- e_27 = { error: e_27_1 };
11403
+ e_29_1 = _f.sent();
11404
+ e_29 = { error: e_29_1 };
10576
11405
  return [3 /*break*/, 20];
10577
11406
  case 19:
10578
11407
  try {
10579
11408
  if (conditions_1_1 && !conditions_1_1.done && (_c = conditions_1.return)) _c.call(conditions_1);
10580
11409
  }
10581
- finally { if (e_27) throw e_27.error; }
11410
+ finally { if (e_29) throw e_29.error; }
10582
11411
  return [7 /*endfinally*/];
10583
11412
  case 20: return [2 /*return*/, null];
10584
11413
  }
@@ -11172,6 +12001,13 @@ function resolveAssistantDefaultCollectionHints(message) {
11172
12001
  if (/\bcustomers?\b/.test(text)) {
11173
12002
  push('customers');
11174
12003
  }
12004
+ if (/\bclients?\b/.test(text)) {
12005
+ push('customers');
12006
+ push('clients');
12007
+ }
12008
+ if (/\bsupport[\s-]*tickets?\b/.test(text) || /\btickets?\b/.test(text)) {
12009
+ push('support-tickets');
12010
+ }
11175
12011
  return hints;
11176
12012
  }
11177
12013
  function buildCollectionRankingDebugFromTokens(tokens, collectionNames, max) {
@@ -11342,6 +12178,36 @@ function pickPreferredCollectionCandidate(ranked) {
11342
12178
  }
11343
12179
  return top;
11344
12180
  }
12181
+ function normalizeAssistantCollectionOverrideName(value) {
12182
+ var normalized = normalizeOptionalString(value).toLowerCase();
12183
+ if (!normalized) {
12184
+ return '';
12185
+ }
12186
+ var withoutReportPrefix = normalized.startsWith('report-')
12187
+ ? normalized.slice('report-'.length)
12188
+ : normalized;
12189
+ return stripVersionSuffix(withoutReportPrefix);
12190
+ }
12191
+ function isAssistantGenericCollectionName(value) {
12192
+ var normalized = normalizeAssistantCollectionOverrideName(value);
12193
+ if (!normalized) {
12194
+ return false;
12195
+ }
12196
+ return !normalized.includes('-') && !normalized.includes('_');
12197
+ }
12198
+ function isAssistantCollectionRefinementOf(currentCollection, genericCollection) {
12199
+ var current = normalizeAssistantCollectionOverrideName(currentCollection);
12200
+ var generic = normalizeAssistantCollectionOverrideName(genericCollection);
12201
+ if (!current || !generic || current === generic) {
12202
+ return false;
12203
+ }
12204
+ return current.startsWith("".concat(generic, "-"))
12205
+ || current.endsWith("-".concat(generic))
12206
+ || current.includes("-".concat(generic, "-"))
12207
+ || current.startsWith("".concat(generic, "_"))
12208
+ || current.endsWith("_".concat(generic))
12209
+ || current.includes("_".concat(generic, "_"));
12210
+ }
11345
12211
  function resolveAssistantCollectionOverride(collectionRanking, currentCollection) {
11346
12212
  var _a, _b;
11347
12213
  var ranked = Array.isArray(collectionRanking === null || collectionRanking === void 0 ? void 0 : collectionRanking.ranked) ? collectionRanking === null || collectionRanking === void 0 ? void 0 : collectionRanking.ranked : [];
@@ -11366,6 +12232,11 @@ function resolveAssistantCollectionOverride(collectionRanking, currentCollection
11366
12232
  return null;
11367
12233
  }
11368
12234
  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;
12235
+ if (currentScore >= AI_ASSISTANT_COLLECTION_OVERRIDE_MIN_SCORE
12236
+ && isAssistantGenericCollectionName(top.name)
12237
+ && isAssistantCollectionRefinementOf(current, top.name)) {
12238
+ return null;
12239
+ }
11369
12240
  var scoreGap = top.score - currentScore;
11370
12241
  var currentIsVersion = isVersionCollectionName(current);
11371
12242
  var topIsVersion = isVersionCollectionName(top.name);
@@ -11442,7 +12313,14 @@ var AI_ASSISTANT_BRIDGE_COLLECTION_ALIASES = {
11442
12313
  reportchemicalblends: 'chemical-blends',
11443
12314
  blend: 'chemical-blends',
11444
12315
  blends: 'chemical-blends',
11445
- invoice: 'invoices'
12316
+ supportticket: 'support-tickets',
12317
+ supporttickets: 'support-tickets',
12318
+ ticket: 'support-tickets',
12319
+ tickets: 'support-tickets',
12320
+ invoice: 'invoices',
12321
+ client: 'customers',
12322
+ clients: 'customers',
12323
+ customer: 'customers'
11446
12324
  };
11447
12325
  var AI_ASSISTANT_DIRECT_COLLECTION_FALLBACK_ALLOWLIST = new Set([
11448
12326
  'work-order-dynamics',
@@ -11450,8 +12328,154 @@ var AI_ASSISTANT_DIRECT_COLLECTION_FALLBACK_ALLOWLIST = new Set([
11450
12328
  'chemical-blends',
11451
12329
  'report-chemical-blends',
11452
12330
  'jobs',
11453
- 'customers'
12331
+ 'customers',
12332
+ 'support-tickets'
11454
12333
  ]);
12334
+ var AI_ASSISTANT_ORDER_COLLECTION_FALLBACKS = [
12335
+ 'work-order-dynamics',
12336
+ 'maintenance-orders',
12337
+ 'orders',
12338
+ 'repair-orders',
12339
+ 'reoccurring-orders'
12340
+ ];
12341
+ var AI_ASSISTANT_CUSTOMER_COLLECTION_FALLBACKS = [
12342
+ 'customers',
12343
+ 'clients',
12344
+ 'api-customers',
12345
+ 'ibp-customers',
12346
+ 'qb-customers'
12347
+ ];
12348
+ var AI_ASSISTANT_SUPPORT_COLLECTION_FALLBACKS = [
12349
+ 'support-tickets',
12350
+ 'supporttickets',
12351
+ 'support-ticket'
12352
+ ];
12353
+ var AI_ASSISTANT_INVOICE_COLLECTION_FALLBACKS = [
12354
+ 'invoices',
12355
+ 'billings',
12356
+ 'sales-taxes'
12357
+ ];
12358
+ function normalizeAssistantCollectionFamilyName(value) {
12359
+ var normalized = normalizeOptionalString(value).toLowerCase();
12360
+ if (!normalized) {
12361
+ return '';
12362
+ }
12363
+ var withoutReport = normalized.startsWith('report-') ? normalized.slice('report-'.length) : normalized;
12364
+ return stripVersionSuffix(withoutReport);
12365
+ }
12366
+ function addAssistantCollectionToTriedSet(tried, collection) {
12367
+ var normalized = normalizeOptionalString(collection);
12368
+ if (normalized) {
12369
+ tried.add(normalized);
12370
+ }
12371
+ var family = normalizeAssistantCollectionFamilyName(collection);
12372
+ if (family) {
12373
+ tried.add(family);
12374
+ }
12375
+ }
12376
+ function buildAssistantTriedCollectionSet(triedCollections) {
12377
+ var tried = new Set();
12378
+ var values = Array.isArray(triedCollections) ? triedCollections : [];
12379
+ values.forEach(function (value) {
12380
+ if (typeof value !== 'string') {
12381
+ return;
12382
+ }
12383
+ addAssistantCollectionToTriedSet(tried, value);
12384
+ });
12385
+ return tried;
12386
+ }
12387
+ function hasAssistantCollectionBeenTried(tried, collection) {
12388
+ var normalized = normalizeOptionalString(collection);
12389
+ var family = normalizeAssistantCollectionFamilyName(collection);
12390
+ return !!((normalized && tried.has(normalized)) || (family && tried.has(family)));
12391
+ }
12392
+ function buildAssistantRetryState(baseState, triedCollections, options) {
12393
+ var next = {
12394
+ triedCollections: Array.from(triedCollections)
12395
+ };
12396
+ var rootCollection = normalizeOptionalString((options === null || options === void 0 ? void 0 : options.rootCollection) || (baseState === null || baseState === void 0 ? void 0 : baseState.rootCollection));
12397
+ if (rootCollection) {
12398
+ next.rootCollection = rootCollection;
12399
+ }
12400
+ if ((options === null || options === void 0 ? void 0 : options.disableCrossCollectionRetry) === true || (baseState === null || baseState === void 0 ? void 0 : baseState.disableCrossCollectionRetry) === true) {
12401
+ next.disableCrossCollectionRetry = true;
12402
+ }
12403
+ return next;
12404
+ }
12405
+ function resolveAssistantCrossCollectionFallbackCandidates(collection) {
12406
+ var normalized = normalizeAssistantCollectionFamilyName(collection);
12407
+ if (!normalized) {
12408
+ return [];
12409
+ }
12410
+ var candidates = [];
12411
+ if (AI_ASSISTANT_ORDER_COLLECTION_FALLBACKS.includes(normalized) || normalized.includes('order')) {
12412
+ candidates = AI_ASSISTANT_ORDER_COLLECTION_FALLBACKS;
12413
+ }
12414
+ else if (AI_ASSISTANT_CUSTOMER_COLLECTION_FALLBACKS.includes(normalized) || normalized.includes('customer') || normalized.includes('client')) {
12415
+ candidates = AI_ASSISTANT_CUSTOMER_COLLECTION_FALLBACKS;
12416
+ }
12417
+ else if (AI_ASSISTANT_SUPPORT_COLLECTION_FALLBACKS.includes(normalized) || normalized.includes('ticket') || normalized.includes('support')) {
12418
+ candidates = AI_ASSISTANT_SUPPORT_COLLECTION_FALLBACKS;
12419
+ }
12420
+ else if (AI_ASSISTANT_INVOICE_COLLECTION_FALLBACKS.includes(normalized) || normalized.includes('invoice') || normalized.includes('billing')) {
12421
+ candidates = AI_ASSISTANT_INVOICE_COLLECTION_FALLBACKS;
12422
+ }
12423
+ var deduped = [];
12424
+ candidates.forEach(function (candidate) {
12425
+ if (!candidate || deduped.includes(candidate)) {
12426
+ return;
12427
+ }
12428
+ deduped.push(candidate);
12429
+ });
12430
+ return deduped;
12431
+ }
12432
+ function resolveAssistantAvailableCrossCollectionFallbacks(db, dbName, collection, triedCollections) {
12433
+ return __awaiter(this, void 0, void 0, function () {
12434
+ var candidates, collectionNames, namesByFamily, currentFamily, available;
12435
+ return __generator(this, function (_a) {
12436
+ 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)];
12443
+ case 1:
12444
+ 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];
12475
+ }
12476
+ });
12477
+ });
12478
+ }
11455
12479
  function resolveAssistantBridgeCollectionAlias(value) {
11456
12480
  var key = normalizeCollectionKey(value);
11457
12481
  return AI_ASSISTANT_BRIDGE_COLLECTION_ALIASES[key] || '';
@@ -11466,7 +12490,7 @@ function isAssistantDirectCollectionFallbackAllowed(collection) {
11466
12490
  function resolveAssistantReportBuilderBridgeCollection(collection_1, db_1) {
11467
12491
  return __awaiter(this, arguments, void 0, function (collection, db, dbName) {
11468
12492
  var normalized, alias, manager, fallback, candidates, pushCandidate, base, reportCandidate, candidates_4, candidates_4_1, candidate, model, resolved, resolvedName, model, _a, candidates_5, candidates_5_1, candidate;
11469
- var e_28, _b, e_29, _c;
12493
+ var e_30, _b, e_31, _c;
11470
12494
  var _d;
11471
12495
  if (dbName === void 0) { dbName = ''; }
11472
12496
  return __generator(this, function (_e) {
@@ -11514,12 +12538,12 @@ function resolveAssistantReportBuilderBridgeCollection(collection_1, db_1) {
11514
12538
  }
11515
12539
  }
11516
12540
  }
11517
- catch (e_28_1) { e_28 = { error: e_28_1 }; }
12541
+ catch (e_30_1) { e_30 = { error: e_30_1 }; }
11518
12542
  finally {
11519
12543
  try {
11520
12544
  if (candidates_4_1 && !candidates_4_1.done && (_b = candidates_4.return)) _b.call(candidates_4);
11521
12545
  }
11522
- finally { if (e_28) throw e_28.error; }
12546
+ finally { if (e_30) throw e_30.error; }
11523
12547
  }
11524
12548
  if (!(db && dbName)) return [3 /*break*/, 4];
11525
12549
  _e.label = 1;
@@ -11549,12 +12573,12 @@ function resolveAssistantReportBuilderBridgeCollection(collection_1, db_1) {
11549
12573
  }
11550
12574
  }
11551
12575
  }
11552
- catch (e_29_1) { e_29 = { error: e_29_1 }; }
12576
+ catch (e_31_1) { e_31 = { error: e_31_1 }; }
11553
12577
  finally {
11554
12578
  try {
11555
12579
  if (candidates_5_1 && !candidates_5_1.done && (_c = candidates_5.return)) _c.call(candidates_5);
11556
12580
  }
11557
- finally { if (e_29) throw e_29.error; }
12581
+ finally { if (e_31) throw e_31.error; }
11558
12582
  }
11559
12583
  throw new Error('AI assistant report builder bridge: Collection is not configured for report builder.');
11560
12584
  }
@@ -11562,7 +12586,7 @@ function resolveAssistantReportBuilderBridgeCollection(collection_1, db_1) {
11562
12586
  });
11563
12587
  }
11564
12588
  function findQueryDateField(query) {
11565
- var e_30, _a, e_31, _b;
12589
+ var e_32, _a, e_33, _b;
11566
12590
  if (!query || typeof query !== 'object') {
11567
12591
  return null;
11568
12592
  }
@@ -11576,12 +12600,12 @@ function findQueryDateField(query) {
11576
12600
  }
11577
12601
  }
11578
12602
  }
11579
- catch (e_30_1) { e_30 = { error: e_30_1 }; }
12603
+ catch (e_32_1) { e_32 = { error: e_32_1 }; }
11580
12604
  finally {
11581
12605
  try {
11582
12606
  if (query_1_1 && !query_1_1.done && (_a = query_1.return)) _a.call(query_1);
11583
12607
  }
11584
- finally { if (e_30) throw e_30.error; }
12608
+ finally { if (e_32) throw e_32.error; }
11585
12609
  }
11586
12610
  return null;
11587
12611
  }
@@ -11600,12 +12624,12 @@ function findQueryDateField(query) {
11600
12624
  }
11601
12625
  }
11602
12626
  }
11603
- catch (e_31_1) { e_31 = { error: e_31_1 }; }
12627
+ catch (e_33_1) { e_33 = { error: e_33_1 }; }
11604
12628
  finally {
11605
12629
  try {
11606
12630
  if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
11607
12631
  }
11608
- finally { if (e_31) throw e_31.error; }
12632
+ finally { if (e_33) throw e_33.error; }
11609
12633
  }
11610
12634
  return null;
11611
12635
  }
@@ -11854,7 +12878,7 @@ function resolveQueryDateFieldFallback(query) {
11854
12878
  return { from: dateField, to: fallback };
11855
12879
  }
11856
12880
  function containsForbiddenMongoOperators(value) {
11857
- var e_32, _a;
12881
+ var e_34, _a;
11858
12882
  if (!value || typeof value !== 'object') {
11859
12883
  return false;
11860
12884
  }
@@ -11873,12 +12897,12 @@ function containsForbiddenMongoOperators(value) {
11873
12897
  }
11874
12898
  }
11875
12899
  }
11876
- catch (e_32_1) { e_32 = { error: e_32_1 }; }
12900
+ catch (e_34_1) { e_34 = { error: e_34_1 }; }
11877
12901
  finally {
11878
12902
  try {
11879
12903
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
11880
12904
  }
11881
- finally { if (e_32) throw e_32.error; }
12905
+ finally { if (e_34) throw e_34.error; }
11882
12906
  }
11883
12907
  return false;
11884
12908
  }
@@ -12321,8 +13345,8 @@ function applyCodexStreamStatusHandler(runOptions, streamStatusHandler) {
12321
13345
  }
12322
13346
  function waitForCodexWorkerMessage(worker, streamStatusHandler) {
12323
13347
  return __awaiter(this, void 0, void 0, function () {
12324
- var _a, _b, _c, _d, message, payload, status_1, e_33_1;
12325
- var _e, e_33, _f, _g;
13348
+ var _a, _b, _c, _d, message, payload, status_1, e_35_1;
13349
+ var _e, e_35, _f, _g;
12326
13350
  return __generator(this, function (_h) {
12327
13351
  switch (_h.label) {
12328
13352
  case 0:
@@ -12349,8 +13373,8 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
12349
13373
  return [3 /*break*/, 1];
12350
13374
  case 4: return [3 /*break*/, 11];
12351
13375
  case 5:
12352
- e_33_1 = _h.sent();
12353
- e_33 = { error: e_33_1 };
13376
+ e_35_1 = _h.sent();
13377
+ e_35 = { error: e_35_1 };
12354
13378
  return [3 /*break*/, 11];
12355
13379
  case 6:
12356
13380
  _h.trys.push([6, , 9, 10]);
@@ -12361,7 +13385,7 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
12361
13385
  _h.label = 8;
12362
13386
  case 8: return [3 /*break*/, 10];
12363
13387
  case 9:
12364
- if (e_33) throw e_33.error;
13388
+ if (e_35) throw e_35.error;
12365
13389
  return [7 /*endfinally*/];
12366
13390
  case 10: return [7 /*endfinally*/];
12367
13391
  case 11: throw new CodexWorkerBootstrapError('Codex worker exited before completing.');
@@ -12371,7 +13395,7 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
12371
13395
  }
12372
13396
  function runCodexInWorkerThread(prompt, runOptions, config, streamStatusHandler) {
12373
13397
  return __awaiter(this, void 0, void 0, function () {
12374
- var streamedOptions, codexClient, workerPath, codexClient, error_5, codexClient;
13398
+ var streamedOptions, codexClient, workerPath, codexClient, error_6, codexClient;
12375
13399
  return __generator(this, function (_a) {
12376
13400
  switch (_a.label) {
12377
13401
  case 0:
@@ -12392,11 +13416,11 @@ function runCodexInWorkerThread(prompt, runOptions, config, streamStatusHandler)
12392
13416
  return [4 /*yield*/, runCodexInWorkerThreadInternal(workerPath, prompt, runOptions, config, streamStatusHandler)];
12393
13417
  case 6: return [2 /*return*/, _a.sent()];
12394
13418
  case 7:
12395
- error_5 = _a.sent();
12396
- if (!(error_5 instanceof CodexWorkerBootstrapError)) {
12397
- throw error_5;
13419
+ error_6 = _a.sent();
13420
+ if (!(error_6 instanceof CodexWorkerBootstrapError)) {
13421
+ throw error_6;
12398
13422
  }
12399
- console.error('Codex worker bootstrap failed, falling back to in-process run.', error_5);
13423
+ console.error('Codex worker bootstrap failed, falling back to in-process run.', error_6);
12400
13424
  codexClient = getAssistantCodexClient(config);
12401
13425
  return [4 /*yield*/, codexClient.run(prompt, streamedOptions)];
12402
13426
  case 8: return [2 /*return*/, _a.sent()];
@@ -12434,7 +13458,7 @@ function runCodexInWorkerThreadInternal(workerPath, prompt, runOptions, config,
12434
13458
  timeoutMs = ((sanitizedOptions === null || sanitizedOptions === void 0 ? void 0 : sanitizedOptions.timeoutMs) || resolveCodexTimeoutMs()) + 15000;
12435
13459
  timeoutController = new AbortController();
12436
13460
  timeoutPromise = (function () { return __awaiter(_this, void 0, void 0, function () {
12437
- var error_6;
13461
+ var error_7;
12438
13462
  return __generator(this, function (_a) {
12439
13463
  switch (_a.label) {
12440
13464
  case 0:
@@ -12444,11 +13468,11 @@ function runCodexInWorkerThreadInternal(workerPath, prompt, runOptions, config,
12444
13468
  _a.sent();
12445
13469
  return [2 /*return*/, { type: 'timeout' }];
12446
13470
  case 2:
12447
- error_6 = _a.sent();
12448
- if ((error_6 === null || error_6 === void 0 ? void 0 : error_6.name) === 'AbortError') {
13471
+ error_7 = _a.sent();
13472
+ if ((error_7 === null || error_7 === void 0 ? void 0 : error_7.name) === 'AbortError') {
12449
13473
  return [2 /*return*/, { type: 'aborted' }];
12450
13474
  }
12451
- throw error_6;
13475
+ throw error_7;
12452
13476
  case 3: return [2 /*return*/];
12453
13477
  }
12454
13478
  });
@@ -12789,6 +13813,8 @@ var AI_ASSISTANT_DATA_REQUEST_PATTERNS = [
12789
13813
  /\bmissing\b/,
12790
13814
  /\bgroup(ed)? by\b/,
12791
13815
  /\bbreakdown\b/,
13816
+ /\bbreak\s+up\b/,
13817
+ /\b(by|per)\s+(user|customer|client|status|driver|assignee|owner|location|type|priority)\b/,
12792
13818
  /\bby day\b/,
12793
13819
  /\bby week\b/,
12794
13820
  /\bby month\b/,
@@ -12841,7 +13867,9 @@ var AI_ASSISTANT_STRONG_DATA_PATTERNS = [
12841
13867
  /\baverage\b/,
12842
13868
  /\bavg\b/,
12843
13869
  /\bbreakdown\b/,
13870
+ /\bbreak\s+up\b/,
12844
13871
  /\bgroup(ed)? by\b/,
13872
+ /\b(by|per)\s+(user|customer|client|status|driver|assignee|owner|location|type|priority)\b/,
12845
13873
  /\bby day\b/,
12846
13874
  /\bby week\b/,
12847
13875
  /\bby month\b/,
@@ -13071,6 +14099,143 @@ function hasAssistantDatedLanguage(message) {
13071
14099
  ];
13072
14100
  return patterns.some(function (pattern) { return pattern.test(text); });
13073
14101
  }
14102
+ var AI_ASSISTANT_BREAKDOWN_DIMENSION_STOPWORDS = new Set([
14103
+ 'of',
14104
+ 'in',
14105
+ 'for',
14106
+ 'with',
14107
+ 'to',
14108
+ 'from',
14109
+ 'over',
14110
+ 'across',
14111
+ 'within',
14112
+ 'between',
14113
+ 'into',
14114
+ 'onto',
14115
+ 'through',
14116
+ 'during',
14117
+ 'and',
14118
+ 'or',
14119
+ 'that',
14120
+ 'which',
14121
+ 'who',
14122
+ 'what',
14123
+ 'when',
14124
+ 'where',
14125
+ 'while',
14126
+ 'than',
14127
+ 'then',
14128
+ 'as',
14129
+ 'is',
14130
+ 'are',
14131
+ 'was',
14132
+ 'were',
14133
+ 'be',
14134
+ 'been',
14135
+ 'being',
14136
+ 'last',
14137
+ 'past',
14138
+ 'previous',
14139
+ 'recent',
14140
+ 'current',
14141
+ 'next',
14142
+ 'this',
14143
+ 'these',
14144
+ 'those',
14145
+ 'now',
14146
+ 'today',
14147
+ 'tomorrow',
14148
+ 'yesterday',
14149
+ 'me',
14150
+ 'my',
14151
+ 'our',
14152
+ 'your',
14153
+ 'their',
14154
+ 'by'
14155
+ ]);
14156
+ function normalizeAssistantBreakdownDimension(value) {
14157
+ var e_36, _a;
14158
+ var normalized = normalizeOptionalString(value)
14159
+ .toLowerCase()
14160
+ .replace(/[^a-z0-9_\s-]+/g, ' ')
14161
+ .replace(/\s+/g, ' ')
14162
+ .trim();
14163
+ if (!normalized) {
14164
+ return '';
14165
+ }
14166
+ var tokens = normalized
14167
+ .split(/\s+/g)
14168
+ .filter(Boolean)
14169
+ .filter(function (token) { return !['the', 'a', 'an', 'each'].includes(token); });
14170
+ if (!tokens.length) {
14171
+ return '';
14172
+ }
14173
+ var kept = [];
14174
+ try {
14175
+ for (var tokens_1 = __values(tokens), tokens_1_1 = tokens_1.next(); !tokens_1_1.done; tokens_1_1 = tokens_1.next()) {
14176
+ var token = tokens_1_1.value;
14177
+ if (AI_ASSISTANT_BREAKDOWN_DIMENSION_STOPWORDS.has(token)) {
14178
+ break;
14179
+ }
14180
+ if (/^\d+$/.test(token)) {
14181
+ break;
14182
+ }
14183
+ kept.push(token);
14184
+ if (kept.length >= 3) {
14185
+ break;
14186
+ }
14187
+ }
14188
+ }
14189
+ catch (e_36_1) { e_36 = { error: e_36_1 }; }
14190
+ finally {
14191
+ try {
14192
+ if (tokens_1_1 && !tokens_1_1.done && (_a = tokens_1.return)) _a.call(tokens_1);
14193
+ }
14194
+ finally { if (e_36) throw e_36.error; }
14195
+ }
14196
+ if (!kept.length) {
14197
+ return '';
14198
+ }
14199
+ return kept.join(' ').trim();
14200
+ }
14201
+ function extractAssistantRequestedBreakdownDimensions(message) {
14202
+ var text = normalizeOptionalString(message).toLowerCase();
14203
+ if (!text) {
14204
+ return [];
14205
+ }
14206
+ var results = [];
14207
+ var seen = new Set();
14208
+ var add = function (value) {
14209
+ var normalized = normalizeAssistantBreakdownDimension(value);
14210
+ if (!normalized || seen.has(normalized)) {
14211
+ return;
14212
+ }
14213
+ seen.add(normalized);
14214
+ results.push(normalized);
14215
+ };
14216
+ var patterns = [
14217
+ /\bgroup(?:ed)?\s+by\s+([a-z0-9_-]+(?:\s+[a-z0-9_-]+){0,2})(?=\s+(?:by|per|for|of|in|with|and|or)\b|[,.!?;]|$)/gi,
14218
+ /\bbreak(?:\s+up|\s*down)?\b[\s\S]{0,80}?\bby\s+([a-z0-9_-]+(?:\s+[a-z0-9_-]+){0,2})(?=\s+(?:by|per|for|of|in|with|and|or)\b|[,.!?;]|$)/gi,
14219
+ /\b(?:by|per)\s+(?:each\s+)?([a-z0-9_-]+(?:\s+[a-z0-9_-]+){0,2})(?=\s+(?:by|per|for|of|in|with|and|or)\b|[,.!?;]|$)/gi,
14220
+ /\bfor\s+each\s+([a-z0-9_-]+(?:\s+[a-z0-9_-]+){0,2})(?=\s+(?:by|per|for|of|in|with|and|or)\b|[,.!?;]|$)/gi
14221
+ ];
14222
+ patterns.forEach(function (pattern) {
14223
+ var match = pattern.exec(text);
14224
+ while (match) {
14225
+ add(String(match[1] || ''));
14226
+ match = pattern.exec(text);
14227
+ }
14228
+ });
14229
+ return results;
14230
+ }
14231
+ function hasAssistantGroupingMetricCue(message) {
14232
+ var text = normalizeOptionalString(message).toLowerCase();
14233
+ if (!text) {
14234
+ return false;
14235
+ }
14236
+ return /\b(total|count|number|sum|avg|average|hours?|revenue|sales|billing|volume|throughput|breakdown|rank|ranking|top|how\s+many)\b/.test(text)
14237
+ || /\b(last|recent)\s+\d+\b/.test(text);
14238
+ }
13074
14239
  function hasAssistantGroupedLanguage(message) {
13075
14240
  var text = normalizeOptionalString(message).toLowerCase();
13076
14241
  if (!text) {
@@ -13078,17 +14243,29 @@ function hasAssistantGroupedLanguage(message) {
13078
14243
  }
13079
14244
  var patterns = [
13080
14245
  /\bbreakdown\b/i,
14246
+ /\bbreak\s+up\b/i,
13081
14247
  /\bgroup(?:ed)?\s+by\b/i,
13082
- /\bby\s+(day|week|month|quarter|year|status|customer|location|type)\b/i,
13083
- /\bper\s+(day|week|month|quarter|year|status|customer|location|type)\b/i,
14248
+ /\bby\s+(day|week|month|quarter|year)\b/i,
14249
+ /\bper\s+(day|week|month|quarter|year)\b/i,
13084
14250
  /\bover\s+time\b/i,
13085
14251
  /\btime\s*series\b/i,
13086
14252
  /\btrend(?:ing|s)?\b/i,
13087
14253
  /\bmonth\s+over\s+month\b/i,
13088
14254
  /\bquarter\s+over\s+quarter\b/i,
13089
- /\byear\s+over\s+year\b/i
14255
+ /\byear\s+over\s+year\b/i,
14256
+ /\btop\s+\d+\b[\s\S]{0,60}\bby\b/i
13090
14257
  ];
13091
- return patterns.some(function (pattern) { return pattern.test(text); });
14258
+ if (patterns.some(function (pattern) { return pattern.test(text); })) {
14259
+ return true;
14260
+ }
14261
+ var dimensions = extractAssistantRequestedBreakdownDimensions(text);
14262
+ if (!dimensions.length) {
14263
+ return false;
14264
+ }
14265
+ if (dimensions.length >= 2) {
14266
+ return true;
14267
+ }
14268
+ return hasAssistantGroupingMetricCue(text);
13092
14269
  }
13093
14270
  function shouldPreferAssistantListDirective(message, plannerOutput, requestClassification) {
13094
14271
  var _a, _b, _c, _d, _e;
@@ -13128,6 +14305,17 @@ function shouldEnforceAssistantDatedDirective(message, plannerOutput, requestCla
13128
14305
  }
13129
14306
  return hasAssistantDatedLanguage(message);
13130
14307
  }
14308
+ function shouldEnforceAssistantGroupedDirective(message, plannerOutput, requestClassification) {
14309
+ var _a, _b;
14310
+ if (!(requestClassification === null || requestClassification === void 0 ? void 0 : requestClassification.dataQuestion)) {
14311
+ return false;
14312
+ }
14313
+ var plannerGroupBy = normalizeOptionalString((_b = (_a = plannerOutput === null || plannerOutput === void 0 ? void 0 : plannerOutput.dataPlan) === null || _a === void 0 ? void 0 : _a.queryPlan) === null || _b === void 0 ? void 0 : _b.groupBy).toLowerCase();
14314
+ if (plannerGroupBy && plannerGroupBy !== 'none' && plannerGroupBy !== 'null') {
14315
+ return true;
14316
+ }
14317
+ return hasAssistantGroupedLanguage(message);
14318
+ }
13131
14319
  function buildAssistantDirectiveStyleHint(params) {
13132
14320
  if (params.preferList && !params.enforceDated) {
13133
14321
  return [
@@ -13137,6 +14325,17 @@ function buildAssistantDirectiveStyleHint(params) {
13137
14325
  '- If user asks for location, include location name fields (location/location_name) and id_location for lookup fallback; do not return only location_type unless explicitly requested.'
13138
14326
  ].join('\n');
13139
14327
  }
14328
+ var breakdowns = (Array.isArray(params.requestedBreakdowns) ? params.requestedBreakdowns : [])
14329
+ .map(function (value) { return normalizeOptionalString(value); })
14330
+ .filter(Boolean);
14331
+ if (!params.enforceDated && params.enforceGrouped) {
14332
+ return [
14333
+ 'Report style intent: Grouped.',
14334
+ '- Return REPORT_BUILDER_AGG (not REPORT_BUILDER_READ).',
14335
+ breakdowns.length ? "- Requested breakdown dimensions: ".concat(breakdowns.join(', '), ".") : '- Requested breakdown dimensions must be preserved exactly.',
14336
+ params.strict ? '- STRICT: do not return a flat list when grouped dimensions are requested.' : ''
14337
+ ].filter(Boolean).join('\n');
14338
+ }
13140
14339
  if (!params.enforceDated) {
13141
14340
  return '';
13142
14341
  }
@@ -13145,6 +14344,7 @@ function buildAssistantDirectiveStyleHint(params) {
13145
14344
  'Report style intent: Dated.',
13146
14345
  "Requested time grain: ".concat(grainLabel, "."),
13147
14346
  '- Return REPORT_BUILDER_AGG (not REPORT_BUILDER_READ).',
14347
+ breakdowns.length ? "- Requested breakdown dimensions: ".concat(breakdowns.join(', '), ".") : '- Preserve all explicitly requested breakdown dimensions.',
13148
14348
  '- Ensure the pipeline groups by the requested time grain and requested breakdown dimensions.',
13149
14349
  '- For "last/past N" windows, use full completed calendar-period bounds in UTC unless the user asks for period-to-date.',
13150
14350
  params.strict ? '- STRICT: if unsure, still prefer REPORT_BUILDER_AGG.' : ''
@@ -13178,7 +14378,7 @@ function resolveAssistantPlannerEnabled() {
13178
14378
  return raw === undefined ? true : raw === true;
13179
14379
  }
13180
14380
  function resolveAssistantPlannerKnownRoutes() {
13181
- var e_34, _a;
14381
+ var e_37, _a;
13182
14382
  var _b;
13183
14383
  var routes = ((_b = resolveio_server_app_1.ResolveIOServer.getClientRoutes) === null || _b === void 0 ? void 0 : _b.call(resolveio_server_app_1.ResolveIOServer)) || [];
13184
14384
  var unique = new Set();
@@ -13191,12 +14391,12 @@ function resolveAssistantPlannerKnownRoutes() {
13191
14391
  }
13192
14392
  }
13193
14393
  }
13194
- catch (e_34_1) { e_34 = { error: e_34_1 }; }
14394
+ catch (e_37_1) { e_37 = { error: e_37_1 }; }
13195
14395
  finally {
13196
14396
  try {
13197
14397
  if (routes_1_1 && !routes_1_1.done && (_a = routes_1.return)) _a.call(routes_1);
13198
14398
  }
13199
- finally { if (e_34) throw e_34.error; }
14399
+ finally { if (e_37) throw e_37.error; }
13200
14400
  }
13201
14401
  return Array.from(unique).slice(0, AI_ASSISTANT_PLANNER_MAX_ROUTES);
13202
14402
  }
@@ -13439,7 +14639,7 @@ function normalizeRouteMatchKey(value) {
13439
14639
  return normalizeRouteKey(value).toLowerCase();
13440
14640
  }
13441
14641
  function buildClientRouteIndex() {
13442
- var e_35, _a;
14642
+ var e_38, _a;
13443
14643
  var _b;
13444
14644
  var routes = ((_b = resolveio_server_app_1.ResolveIOServer.getClientRoutes) === null || _b === void 0 ? void 0 : _b.call(resolveio_server_app_1.ResolveIOServer)) || [];
13445
14645
  var set = new Set();
@@ -13458,12 +14658,12 @@ function buildClientRouteIndex() {
13458
14658
  }
13459
14659
  }
13460
14660
  }
13461
- catch (e_35_1) { e_35 = { error: e_35_1 }; }
14661
+ catch (e_38_1) { e_38 = { error: e_38_1 }; }
13462
14662
  finally {
13463
14663
  try {
13464
14664
  if (routes_2_1 && !routes_2_1.done && (_a = routes_2.return)) _a.call(routes_2);
13465
14665
  }
13466
- finally { if (e_35) throw e_35.error; }
14666
+ finally { if (e_38) throw e_38.error; }
13467
14667
  }
13468
14668
  return { set: set, map: map, size: routes.length };
13469
14669
  }
@@ -14374,6 +15574,44 @@ function normalizeAssistantRoutes(value) {
14374
15574
  return "".concat(canonical).concat(suffix);
14375
15575
  });
14376
15576
  }
15577
+ function stripAssistantEmptyMarkdownTableRows(value) {
15578
+ var lines = String(value || '').split('\n');
15579
+ var output = [];
15580
+ var index = 0;
15581
+ while (index < lines.length) {
15582
+ var header = String(lines[index] || '').trim();
15583
+ var separator = String(lines[index + 1] || '').trim();
15584
+ var isTableHeader = /^\|.+\|$/.test(header);
15585
+ var isTableSeparator = /^\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(separator);
15586
+ if (!isTableHeader || !isTableSeparator) {
15587
+ output.push(lines[index]);
15588
+ index += 1;
15589
+ continue;
15590
+ }
15591
+ var tableStart = output.length;
15592
+ output.push(lines[index]);
15593
+ output.push(lines[index + 1]);
15594
+ index += 2;
15595
+ var keptRows = 0;
15596
+ while (index < lines.length) {
15597
+ var line = String(lines[index] || '');
15598
+ if (!line.trim() || !line.includes('|')) {
15599
+ break;
15600
+ }
15601
+ var cells = line.split('|').map(function (cell) { return cell.trim(); }).filter(Boolean);
15602
+ var hasContent = cells.some(function (cell) { return cell !== '-' && cell !== '---'; });
15603
+ if (hasContent) {
15604
+ output.push(line);
15605
+ keptRows += 1;
15606
+ }
15607
+ index += 1;
15608
+ }
15609
+ if (keptRows === 0) {
15610
+ output.splice(tableStart, 2);
15611
+ }
15612
+ }
15613
+ return output.join('\n').replace(/\n{3,}/g, '\n\n').trim();
15614
+ }
14377
15615
  function sanitizeAssistantResponse(value) {
14378
15616
  var raw = normalizeOptionalString(value);
14379
15617
  if (!raw) {
@@ -14435,11 +15673,12 @@ function sanitizeAssistantResponse(value) {
14435
15673
  if (!cleaned) {
14436
15674
  return 'I can’t share code, but I can point you to files or explain behavior at a high level.';
14437
15675
  }
14438
- var normalizedCurrency = normalizeAssistantCurrencyText(cleaned);
15676
+ var tableCleaned = stripAssistantEmptyMarkdownTableRows(cleaned);
15677
+ var normalizedCurrency = normalizeAssistantCurrencyText(tableCleaned || cleaned);
14439
15678
  return normalizeAssistantRoutes(normalizedCurrency);
14440
15679
  }
14441
15680
  function evaluateAssistantGuardrails(message) {
14442
- var e_36, _a;
15681
+ var e_39, _a;
14443
15682
  var normalized = String(message || '').toLowerCase();
14444
15683
  var patterns = [
14445
15684
  {
@@ -14485,12 +15724,12 @@ function evaluateAssistantGuardrails(message) {
14485
15724
  }
14486
15725
  }
14487
15726
  }
14488
- catch (e_36_1) { e_36 = { error: e_36_1 }; }
15727
+ catch (e_39_1) { e_39 = { error: e_39_1 }; }
14489
15728
  finally {
14490
15729
  try {
14491
15730
  if (patterns_1_1 && !patterns_1_1.done && (_a = patterns_1.return)) _a.call(patterns_1);
14492
15731
  }
14493
- finally { if (e_36) throw e_36.error; }
15732
+ finally { if (e_39) throw e_39.error; }
14494
15733
  }
14495
15734
  return null;
14496
15735
  }
@@ -14605,7 +15844,7 @@ function tokenizeArithmeticExpression(expression) {
14605
15844
  return tokens;
14606
15845
  }
14607
15846
  function evaluateArithmeticExpression(expression) {
14608
- var e_37, _a, e_38, _b;
15847
+ var e_40, _a, e_41, _b;
14609
15848
  var tokens = tokenizeArithmeticExpression(expression);
14610
15849
  if (!tokens || !tokens.length) {
14611
15850
  return null;
@@ -14629,8 +15868,8 @@ function evaluateArithmeticExpression(expression) {
14629
15868
  ops.push(op);
14630
15869
  };
14631
15870
  try {
14632
- for (var tokens_1 = __values(tokens), tokens_1_1 = tokens_1.next(); !tokens_1_1.done; tokens_1_1 = tokens_1.next()) {
14633
- var token = tokens_1_1.value;
15871
+ for (var tokens_2 = __values(tokens), tokens_2_1 = tokens_2.next(); !tokens_2_1.done; tokens_2_1 = tokens_2.next()) {
15872
+ var token = tokens_2_1.value;
14634
15873
  if (token === '(') {
14635
15874
  ops.push(token);
14636
15875
  prevToken = token;
@@ -14662,12 +15901,12 @@ function evaluateArithmeticExpression(expression) {
14662
15901
  prevToken = token;
14663
15902
  }
14664
15903
  }
14665
- catch (e_37_1) { e_37 = { error: e_37_1 }; }
15904
+ catch (e_40_1) { e_40 = { error: e_40_1 }; }
14666
15905
  finally {
14667
15906
  try {
14668
- if (tokens_1_1 && !tokens_1_1.done && (_a = tokens_1.return)) _a.call(tokens_1);
15907
+ if (tokens_2_1 && !tokens_2_1.done && (_a = tokens_2.return)) _a.call(tokens_2);
14669
15908
  }
14670
- finally { if (e_37) throw e_37.error; }
15909
+ finally { if (e_40) throw e_40.error; }
14671
15910
  }
14672
15911
  while (ops.length) {
14673
15912
  var op = ops.pop();
@@ -14707,12 +15946,12 @@ function evaluateArithmeticExpression(expression) {
14707
15946
  stack.push(Number(token));
14708
15947
  }
14709
15948
  }
14710
- catch (e_38_1) { e_38 = { error: e_38_1 }; }
15949
+ catch (e_41_1) { e_41 = { error: e_41_1 }; }
14711
15950
  finally {
14712
15951
  try {
14713
15952
  if (output_1_1 && !output_1_1.done && (_b = output_1.return)) _b.call(output_1);
14714
15953
  }
14715
- finally { if (e_38) throw e_38.error; }
15954
+ finally { if (e_41) throw e_41.error; }
14716
15955
  }
14717
15956
  if (stack.length !== 1 || Number.isNaN(stack[0])) {
14718
15957
  return null;
@@ -14896,8 +16135,8 @@ function handleCodexUpload(id_conversation, file_name, content_base64, size, con
14896
16135
  }
14897
16136
  function readAttachmentContents(attachments) {
14898
16137
  return __awaiter(this, void 0, void 0, function () {
14899
- var limits, totalBytes, totalChars, chunks, cleaned, attachments_1, attachments_1_1, attachment, localPath, safe, stat, ext, name_1, type, readable, content, _a, e_39_1;
14900
- var e_39, _b;
16138
+ var limits, totalBytes, totalChars, chunks, cleaned, attachments_1, attachments_1_1, attachment, localPath, safe, stat, ext, name_1, type, readable, content, _a, e_42_1;
16139
+ var e_42, _b;
14901
16140
  return __generator(this, function (_c) {
14902
16141
  switch (_c.label) {
14903
16142
  case 0:
@@ -14976,14 +16215,14 @@ function readAttachmentContents(attachments) {
14976
16215
  return [3 /*break*/, 2];
14977
16216
  case 10: return [3 /*break*/, 13];
14978
16217
  case 11:
14979
- e_39_1 = _c.sent();
14980
- e_39 = { error: e_39_1 };
16218
+ e_42_1 = _c.sent();
16219
+ e_42 = { error: e_42_1 };
14981
16220
  return [3 /*break*/, 13];
14982
16221
  case 12:
14983
16222
  try {
14984
16223
  if (attachments_1_1 && !attachments_1_1.done && (_b = attachments_1.return)) _b.call(attachments_1);
14985
16224
  }
14986
- finally { if (e_39) throw e_39.error; }
16225
+ finally { if (e_42) throw e_42.error; }
14987
16226
  return [7 /*endfinally*/];
14988
16227
  case 13: return [2 /*return*/, {
14989
16228
  promptText: chunks.length ? "\n\nAttachments:\n".concat(chunks.join('\n\n')) : '',
@@ -15138,7 +16377,7 @@ function resolveAssistantDatabaseNameForSystemCollections() {
15138
16377
  }
15139
16378
  function updateAssistantMessageWithFallback(messageId, setPayload) {
15140
16379
  return __awaiter(this, void 0, void 0, function () {
15141
- var error_7, dbName, _a;
16380
+ var error_8, dbName, _a;
15142
16381
  return __generator(this, function (_b) {
15143
16382
  switch (_b.label) {
15144
16383
  case 0:
@@ -15153,9 +16392,9 @@ function updateAssistantMessageWithFallback(messageId, setPayload) {
15153
16392
  _b.sent();
15154
16393
  return [2 /*return*/];
15155
16394
  case 3:
15156
- error_7 = _b.sent();
15157
- if (!isAssistantTransactionCommittedError(error_7)) {
15158
- throw error_7;
16395
+ error_8 = _b.sent();
16396
+ if (!isAssistantTransactionCommittedError(error_8)) {
16397
+ throw error_8;
15159
16398
  }
15160
16399
  dbName = resolveAssistantDatabaseNameForSystemCollections();
15161
16400
  _b.label = 4;
@@ -15185,7 +16424,7 @@ function updateAssistantMessageWithFallback(messageId, setPayload) {
15185
16424
  }
15186
16425
  function touchConversation(idConversation, timestamp, lastMessageId) {
15187
16426
  return __awaiter(this, void 0, void 0, function () {
15188
- var update, error_8, dbName;
16427
+ var update, error_9, dbName;
15189
16428
  return __generator(this, function (_a) {
15190
16429
  switch (_a.label) {
15191
16430
  case 0:
@@ -15204,9 +16443,9 @@ function touchConversation(idConversation, timestamp, lastMessageId) {
15204
16443
  _a.sent();
15205
16444
  return [2 /*return*/];
15206
16445
  case 3:
15207
- error_8 = _a.sent();
15208
- if (!isAssistantTransactionCommittedError(error_8)) {
15209
- throw error_8;
16446
+ error_9 = _a.sent();
16447
+ if (!isAssistantTransactionCommittedError(error_9)) {
16448
+ throw error_9;
15210
16449
  }
15211
16450
  dbName = resolveAssistantDatabaseNameForSystemCollections();
15212
16451
  return [4 /*yield*/, resolveio_server_app_1.ResolveIOServer.getMongoConnection()
@@ -15307,7 +16546,7 @@ function estimateUsage(messages, responseText, model) {
15307
16546
  };
15308
16547
  }
15309
16548
  function evaluateGuardrails(message) {
15310
- var e_40, _a;
16549
+ var e_43, _a;
15311
16550
  var normalized = String(message || '').toLowerCase();
15312
16551
  var patterns = [
15313
16552
  { pattern: /\b(source\s*code|full\s*code|entire\s*code|repo\s*dump|repository|git\s*clone)\b/i, reason: 'Code access is restricted.' },
@@ -15329,12 +16568,12 @@ function evaluateGuardrails(message) {
15329
16568
  }
15330
16569
  }
15331
16570
  }
15332
- catch (e_40_1) { e_40 = { error: e_40_1 }; }
16571
+ catch (e_43_1) { e_43 = { error: e_43_1 }; }
15333
16572
  finally {
15334
16573
  try {
15335
16574
  if (patterns_2_1 && !patterns_2_1.done && (_a = patterns_2.return)) _a.call(patterns_2);
15336
16575
  }
15337
- finally { if (e_40) throw e_40.error; }
16576
+ finally { if (e_43) throw e_43.error; }
15338
16577
  }
15339
16578
  return null;
15340
16579
  }