@resolveio/server-lib 22.0.4 → 22.0.6

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.
@@ -114,6 +114,7 @@ exports.serializeMongoValue = serializeMongoValue;
114
114
  exports.flattenForTable = flattenForTable;
115
115
  exports.buildDisplayTable = buildDisplayTable;
116
116
  exports.formatDisplayTableMarkdown = formatDisplayTableMarkdown;
117
+ exports.rewriteMatchExpressionsToExpr = rewriteMatchExpressionsToExpr;
117
118
  exports.stripQueryFieldPathsDeep = stripQueryFieldPathsDeep;
118
119
  exports.stripScopedFieldsFromPipeline = stripScopedFieldsFromPipeline;
119
120
  exports.rewriteEmbeddedMatchObjects = rewriteEmbeddedMatchObjects;
@@ -159,6 +160,10 @@ var AI_ASSISTANT_COLLECTION_OVERRIDE_MIN_SCORE = 20;
159
160
  var AI_ASSISTANT_ID_LOOKUP_MAX_RESULTS = 20;
160
161
  var AI_ASSISTANT_ID_LOOKUP_CANDIDATE_LIMIT = 4;
161
162
  var AI_ASSISTANT_NAME_MATCH_FALLBACK_MAX_FIELDS = 12;
163
+ var AI_ASSISTANT_CONTEXT_MAX_COLLECTIONS = 3;
164
+ var AI_ASSISTANT_CONTEXT_MAX_FIELDS_PER_COLLECTION = 24;
165
+ var AI_ASSISTANT_LOCALE = 'en-US';
166
+ var AI_ASSISTANT_CURRENCY_CODE = 'USD';
162
167
  var AI_ASSISTANT_PROGRESS_TICKS = [
163
168
  'Grabbing Data',
164
169
  'Drafting response'
@@ -277,6 +282,18 @@ var AI_ASSISTANT_COLLECTION_DOMAIN_TOKENS = new Set([
277
282
  'chemicals',
278
283
  'invoice',
279
284
  'invoices',
285
+ 'revenue',
286
+ 'revenues',
287
+ 'sales',
288
+ 'sale',
289
+ 'billing',
290
+ 'billings',
291
+ 'payment',
292
+ 'payments',
293
+ 'paid',
294
+ 'income',
295
+ 'finance',
296
+ 'financial',
280
297
  'work',
281
298
  'order',
282
299
  'orders',
@@ -317,7 +334,11 @@ var AI_ASSISTANT_FIELD_TOKEN_SYNONYMS = {
317
334
  batch: ['lot'],
318
335
  lot: ['batch'],
319
336
  date: ['created', 'createdat', 'created_at', 'date_created', 'updated', 'updatedat', 'updated_at', 'date_updated'],
320
- total: ['sum', 'amount', 'total_amount', 'total_quantity']
337
+ total: ['sum', 'amount', 'total_amount', 'total_quantity'],
338
+ revenue: ['sales', 'billing', 'paid', 'payment', 'total', 'amount', 'grand', 'subtotal', 'sub_total', 'paid_total', 'grand_total'],
339
+ sales: ['revenue', 'billing', 'paid', 'payment', 'total', 'amount', 'grand', 'subtotal', 'sub_total'],
340
+ billing: ['revenue', 'sales', 'paid', 'payment', 'total', 'amount', 'grand', 'subtotal', 'sub_total'],
341
+ payment: ['paid', 'revenue', 'sales', 'billing', 'total', 'amount']
321
342
  };
322
343
  var AI_ASSISTANT_ID_LOOKUP_HINTS = {
323
344
  customer: ['customers', 'customer-versions'],
@@ -336,6 +357,11 @@ var AI_ASSISTANT_TERM_SYNONYMS = [
336
357
  label: 'blend tickets',
337
358
  pattern: /\bblend(?:ing)?\s+tickets?\b/i,
338
359
  expansions: ['chemical blends', 'chemical-blends', 'report-chemical-blends', 'blend batches']
360
+ },
361
+ {
362
+ label: 'revenue',
363
+ pattern: /\b(revenue|sales|billing)\b/i,
364
+ expansions: ['invoice', 'invoices', 'paid invoices', 'invoice payments', 'billing', 'sales']
339
365
  }
340
366
  ];
341
367
  var AI_ASSISTANT_SYSTEM_PROMPT = [
@@ -372,6 +398,7 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
372
398
  '- Output plain Markdown (NO triple backticks).',
373
399
  '- When you reference database results, summarize first, then include a Markdown table.',
374
400
  '- When presenting record lists or aggregates, produce a Markdown table (pipes).',
401
+ '- Format currency as $1,234.56 (no USD prefix) with two decimals.',
375
402
  '- Never show raw JSON dumps.',
376
403
  '- Do not invent placeholders like "Not available" or "N/A". If a value is missing in tool results, leave the cell blank or omit the column and note it briefly.',
377
404
  '- Do not include `_id` & `__v` & `id_<other collection _id property>` in tables by default.',
@@ -406,6 +433,8 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
406
433
  '- If you need grouped/aggregated data (totals by user, rankings, trends), end your response with a single line exactly in this format:',
407
434
  '- MONGO_AGG: {"collection":"<name>","pipeline":[...],"options":{"allowDiskUse":true,"limit":20},"permissionView":"</route>"}',
408
435
  '- For invoice data, set permissionView to an invoice route (ex: /invoice/list or /report/invoice).',
436
+ '- For revenue/sales/billing questions, use invoices and sum paid_total (fallback to grand_total) with date_paid and Paid/Closed status when available.',
437
+ '- For relative date ranges (last/past/recent), include an upper bound <= $$NOW unless the user specifies a future end date.',
409
438
  '- Keep queries minimal, read-only, and avoid user/credential data unless the user is a super admin.',
410
439
  '- Assume you are not a super admin unless explicitly told otherwise.',
411
440
  '- Only request data when the user has permission for that module; invoice data requires invoice view access.',
@@ -1168,7 +1197,7 @@ function executeAiAssistantCodexRun(payload, context) {
1168
1197
  insertResult = _d.sent();
1169
1198
  assistantMessageId = (insertResult === null || insertResult === void 0 ? void 0 : insertResult._id) || (insertResult === null || insertResult === void 0 ? void 0 : insertResult.insertedId);
1170
1199
  enqueueAssistantCodexRun(function () { return __awaiter(_this, void 0, void 0, function () {
1171
- var runStart, steps, recordStep, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, dataQuestion, lastDirective, toolResponseDebug, toolError, termHints, collectionHints, collectionTokenization, collectionRanking, collectionSelection, collectionOverride, collectionNames, timingBreakdown, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, baseWeights, expandedWeights, dbName, db, _a, assistantContext, prompt_1, workspaceRoot, codexConfig, runOptions, responseText, directiveText, directive, directivePrompt, directiveStart, forcedDirective, _b, initialStart, directivePrompt, forcedStart, forcedDirective, _c, requestedCollection, cleanedResponseText, effectiveDirective, toolRequest, toolStart, toolResponse, _d, toolPayload, followupPrompt, followupStart, followupText, _e, error_2, error_3, finishedAt, finalNow, finishedAt, codexMs, draftingMs, finalMetadata, finalAssistantDoc;
1200
+ var runStart, steps, recordStep, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, dataQuestion, lastDirective, toolResponseDebug, toolError, termHints, collectionHints, fieldHints, collectionTokenization, collectionRanking, collectionSelection, collectionOverride, collectionNames, timingBreakdown, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, baseWeights, expandedWeights, dbName, db, _a, routeHints, rankedCollections, hintCollections, assistantContext, prompt_1, workspaceRoot, codexConfig, runOptions, responseText, directiveText, directive, directivePrompt, directiveStart, forcedDirective, _b, initialStart, directivePrompt, forcedStart, forcedDirective, _c, requestedCollection, cleanedResponseText, effectiveDirective, toolRequest, toolStart, toolResponse, _d, toolPayload, followupPrompt, followupStart, followupText, _e, error_2, error_3, finishedAt, finalNow, finishedAt, codexMs, draftingMs, finalMetadata, finalAssistantDoc;
1172
1201
  var _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
1173
1202
  return __generator(this, function (_u) {
1174
1203
  switch (_u.label) {
@@ -1206,6 +1235,7 @@ function executeAiAssistantCodexRun(payload, context) {
1206
1235
  toolError = null;
1207
1236
  termHints = [];
1208
1237
  collectionHints = [];
1238
+ fieldHints = [];
1209
1239
  collectionTokenization = null;
1210
1240
  collectionRanking = null;
1211
1241
  collectionSelection = null;
@@ -1263,18 +1293,30 @@ function executeAiAssistantCodexRun(payload, context) {
1263
1293
  : null);
1264
1294
  return [3 /*break*/, 5];
1265
1295
  case 5:
1296
+ routeHints = resolveCollectionHintsFromRoute(contextRoute, collectionNames);
1297
+ if (routeHints.length) {
1298
+ collectionHints = mergeAssistantHintValues(routeHints, collectionHints);
1299
+ }
1300
+ rankedCollections = Array.isArray(collectionRanking === null || collectionRanking === void 0 ? void 0 : collectionRanking.ranked)
1301
+ ? collectionRanking === null || collectionRanking === void 0 ? void 0 : collectionRanking.ranked.map(function (entry) { return entry.name; })
1302
+ : [];
1303
+ hintCollections = mergeAssistantHintValues(collectionHints, rankedCollections)
1304
+ .slice(0, AI_ASSISTANT_CONTEXT_MAX_COLLECTIONS);
1305
+ fieldHints = buildAssistantFieldHints(message, hintCollections);
1266
1306
  recordStep('Planning: collection hints', {
1267
1307
  contextRoute: contextRoute || undefined,
1268
1308
  contextMode: contextMode || undefined,
1269
1309
  collectionHints: collectionHints.length ? collectionHints : undefined,
1270
- termHints: termHints.length ? termHints : undefined
1310
+ termHints: termHints.length ? termHints : undefined,
1311
+ fieldHints: fieldHints.length ? fieldHints : undefined
1271
1312
  });
1272
1313
  assistantContext = buildAssistantContext(input, {
1273
1314
  isSuperAdmin: isSuperAdmin,
1274
1315
  hasInvoiceAccess: hasInvoiceAccess,
1275
1316
  customerId: customerId,
1276
1317
  collectionHints: collectionHints,
1277
- termHints: termHints
1318
+ termHints: termHints,
1319
+ fieldHints: fieldHints
1278
1320
  });
1279
1321
  prompt_1 = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1280
1322
  return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
@@ -1446,6 +1488,7 @@ function executeAiAssistantCodexRun(payload, context) {
1446
1488
  followupText = _u.sent();
1447
1489
  timingBreakdown.followupMs = Date.now() - followupStart;
1448
1490
  assistantContent = sanitizeAssistantResponse(followupText);
1491
+ assistantContent = applyAssistantDisplayTableToResponse(assistantContent, toolPayload.result.output.display);
1449
1492
  return [3 /*break*/, 25];
1450
1493
  case 24:
1451
1494
  _e = _u.sent();
@@ -1513,6 +1556,7 @@ function executeAiAssistantCodexRun(payload, context) {
1513
1556
  contextRoute: contextRoute || undefined,
1514
1557
  termHints: termHints.length ? termHints : undefined,
1515
1558
  collectionHints: collectionHints.length ? collectionHints : undefined,
1559
+ fieldHints: fieldHints.length ? fieldHints : undefined,
1516
1560
  collectionTokenization: collectionTokenization || undefined,
1517
1561
  collectionRanking: collectionRanking || undefined,
1518
1562
  collectionSelection: collectionSelection || undefined,
@@ -2031,10 +2075,10 @@ function executeAiAssistantMongoRead(payload, context) {
2031
2075
  }
2032
2076
  function executeAiAssistantMongoAggregate(payload, context) {
2033
2077
  return __awaiter(this, void 0, void 0, function () {
2034
- var input, rawCollection, dbName, db, collectionResolution, collection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, sanitizedPipeline, strippedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, dateField, aggregateOptions, documents, executedPipeline, probeDocs, fallback, fallbackPipeline, fallbackDocs, createdFallback, createdPipeline, createdDocs, expanded, expandedDocs, completionFallback, fallbackPipeline, fallbackDocs, completionExprFallback, fallbackPipeline, fallbackDocs, unwindFallback, fallbackPipeline, fallbackDocs, nameFallback, fallbackPipeline, fallbackDocs, _c, _loop_1, i, state_1, matchFields_1, _d, aliases, rewrittenPipeline, fallbackDocs, _loop_2, i, state_2, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, matchStages, diagnostics, combinedMatch, nameFields, dateFields, queryNoName, _e, queryNoDate, _f, _g, _h, _j, allCollections, base, alt, altCount, _k, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
2035
- var _l, _m;
2036
- return __generator(this, function (_o) {
2037
- switch (_o.label) {
2078
+ var input, rawCollection, dbName, db, collectionResolution, collection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, sanitizedPipeline, strippedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, dateField, aggregateOptions, documents, executedPipeline, probeDocs, fallback, fallbackPipeline, fallbackDocs, createdFallback, createdPipeline, createdDocs, expanded, expandedDocs, completionFallback, fallbackPipeline, fallbackDocs, completionExprFallback, fallbackPipeline, fallbackDocs, unwindFallback, shouldUnwind, _c, _d, fallbackPipeline, fallbackDocs, nameFallback, fallbackPipeline, fallbackDocs, _e, _loop_1, i, state_1, matchFields_1, _f, aliases, rewrittenPipeline, fallbackDocs, _loop_2, i, state_2, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, matchStages, diagnostics, combinedMatch, nameFields, dateFields, queryNoName, _g, queryNoDate, _h, _j, _k, _l, allCollections, base, alt, altCount, _m, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
2079
+ var _o, _p;
2080
+ return __generator(this, function (_q) {
2081
+ switch (_q.label) {
2038
2082
  case 0:
2039
2083
  input = payload || {};
2040
2084
  rawCollection = normalizeOptionalString(input.collection);
@@ -2045,16 +2089,16 @@ function executeAiAssistantMongoAggregate(payload, context) {
2045
2089
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
2046
2090
  return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
2047
2091
  case 1:
2048
- collectionResolution = _o.sent();
2092
+ collectionResolution = _q.sent();
2049
2093
  collection = collectionResolution.name || rawCollection;
2050
2094
  schemaFields = getCollectionSchemaFieldNames(collection);
2051
2095
  return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
2052
2096
  case 2:
2053
- _a = _o.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
2097
+ _a = _q.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
2054
2098
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
2055
2099
  throw new Error('AI assistant mongo aggregate: Access denied.');
2056
2100
  }
2057
- customerId = normalizeOptionalString((_l = user === null || user === void 0 ? void 0 : user.other) === null || _l === void 0 ? void 0 : _l.id_customer);
2101
+ customerId = normalizeOptionalString((_o = user === null || user === void 0 ? void 0 : user.other) === null || _o === void 0 ? void 0 : _o.id_customer);
2058
2102
  fallbackMeta = {};
2059
2103
  baseQuery = normalizeMongoQuery(input.query);
2060
2104
  if (!isSuperAdmin && customerId) {
@@ -2079,18 +2123,18 @@ function executeAiAssistantMongoAggregate(payload, context) {
2079
2123
  if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 4];
2080
2124
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
2081
2125
  case 3:
2082
- _b = _o.sent();
2126
+ _b = _q.sent();
2083
2127
  return [3 /*break*/, 5];
2084
2128
  case 4:
2085
2129
  _b = false;
2086
- _o.label = 5;
2130
+ _q.label = 5;
2087
2131
  case 5:
2088
2132
  shouldScopeByClient = _b;
2089
2133
  clientScopedQuery = shouldScopeByClient
2090
2134
  ? applyClientScopeFilter(baseQuery, normalizedClient, isSuperAdmin)
2091
2135
  : baseQuery;
2092
2136
  scopedQuery = applyCustomerScopeFilter(clientScopedQuery, collection, customerId, isSuperAdmin);
2093
- normalizedPipeline = normalizeAssistantAggregatePipeline(input.pipeline);
2137
+ normalizedPipeline = normalizeAssistantAggregatePipeline(input.pipeline, collection);
2094
2138
  sanitizedPipeline = normalizedPipeline;
2095
2139
  if (!isSuperAdmin && customerId) {
2096
2140
  strippedPipeline = stripScopedFieldsFromPipelineWithMeta(normalizedPipeline, ['id_customer', 'other.id_customer']);
@@ -2113,7 +2157,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
2113
2157
  .aggregate(limitedPipeline, aggregateOptions)
2114
2158
  .toArray()];
2115
2159
  case 6:
2116
- documents = _o.sent();
2160
+ documents = _q.sent();
2117
2161
  executedPipeline = limitedPipeline;
2118
2162
  probeDocs = null;
2119
2163
  if (!(!documents.length && dateField)) return [3 /*break*/, 10];
@@ -2126,13 +2170,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2126
2170
  .aggregate(fallbackPipeline, aggregateOptions)
2127
2171
  .toArray()];
2128
2172
  case 7:
2129
- fallbackDocs = _o.sent();
2173
+ fallbackDocs = _q.sent();
2130
2174
  if (fallbackDocs.length) {
2131
2175
  documents = fallbackDocs;
2132
2176
  executedPipeline = fallbackPipeline;
2133
2177
  fallbackMeta.dateField.used = true;
2134
2178
  }
2135
- _o.label = 8;
2179
+ _q.label = 8;
2136
2180
  case 8:
2137
2181
  if (!(!documents.length && dateField !== 'createdAt')) return [3 /*break*/, 10];
2138
2182
  createdFallback = { from: dateField, to: 'createdAt', attempted: true, used: false };
@@ -2143,13 +2187,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2143
2187
  .aggregate(createdPipeline, aggregateOptions)
2144
2188
  .toArray()];
2145
2189
  case 9:
2146
- createdDocs = _o.sent();
2190
+ createdDocs = _q.sent();
2147
2191
  if (createdDocs.length) {
2148
2192
  documents = createdDocs;
2149
2193
  executedPipeline = createdPipeline;
2150
2194
  fallbackMeta.dateFieldCreatedAt.used = true;
2151
2195
  }
2152
- _o.label = 10;
2196
+ _q.label = 10;
2153
2197
  case 10:
2154
2198
  if (!!documents.length) return [3 /*break*/, 12];
2155
2199
  expanded = expandAggregateDateMatchFallback(executedPipeline);
@@ -2164,13 +2208,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2164
2208
  .aggregate(expanded.pipeline, aggregateOptions)
2165
2209
  .toArray()];
2166
2210
  case 11:
2167
- expandedDocs = _o.sent();
2211
+ expandedDocs = _q.sent();
2168
2212
  if (expandedDocs.length) {
2169
2213
  documents = expandedDocs;
2170
2214
  executedPipeline = expanded.pipeline;
2171
2215
  fallbackMeta.dateFieldsExpanded.used = true;
2172
2216
  }
2173
- _o.label = 12;
2217
+ _q.label = 12;
2174
2218
  case 12:
2175
2219
  if (!!documents.length) return [3 /*break*/, 16];
2176
2220
  completionFallback = resolveAggregateCompletionFallback(executedPipeline);
@@ -2189,13 +2233,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2189
2233
  .aggregate(fallbackPipeline, aggregateOptions)
2190
2234
  .toArray()];
2191
2235
  case 13:
2192
- fallbackDocs = _o.sent();
2236
+ fallbackDocs = _q.sent();
2193
2237
  if (fallbackDocs.length) {
2194
2238
  documents = fallbackDocs;
2195
2239
  executedPipeline = fallbackPipeline;
2196
2240
  fallbackMeta.completion.used = true;
2197
2241
  }
2198
- _o.label = 14;
2242
+ _q.label = 14;
2199
2243
  case 14:
2200
2244
  if (!!documents.length) return [3 /*break*/, 16];
2201
2245
  completionExprFallback = resolveAggregateCompletionExprFallback(executedPipeline);
@@ -2214,35 +2258,66 @@ function executeAiAssistantMongoAggregate(payload, context) {
2214
2258
  .aggregate(fallbackPipeline, aggregateOptions)
2215
2259
  .toArray()];
2216
2260
  case 15:
2217
- fallbackDocs = _o.sent();
2261
+ fallbackDocs = _q.sent();
2218
2262
  if (fallbackDocs.length) {
2219
2263
  documents = fallbackDocs;
2220
2264
  executedPipeline = fallbackPipeline;
2221
2265
  fallbackMeta.completion.used = true;
2222
2266
  }
2223
- _o.label = 16;
2267
+ _q.label = 16;
2224
2268
  case 16:
2225
- if (!(documents.length <= 1)) return [3 /*break*/, 18];
2269
+ if (!(documents.length <= 1)) return [3 /*break*/, 25];
2226
2270
  unwindFallback = resolveAggregateUnwindFallback(executedPipeline);
2227
- if (!unwindFallback) return [3 /*break*/, 18];
2271
+ if (!unwindFallback) return [3 /*break*/, 25];
2228
2272
  fallbackMeta.unwind = { path: unwindFallback.path, attempted: true, used: false };
2273
+ shouldUnwind = false;
2274
+ _q.label = 17;
2275
+ case 17:
2276
+ _q.trys.push([17, 20, , 21]);
2277
+ _c = probeDocs;
2278
+ if (_c) return [3 /*break*/, 19];
2279
+ return [4 /*yield*/, fetchAssistantProbeDocs({
2280
+ db: db,
2281
+ collection: collection,
2282
+ idClient: normalizedClient,
2283
+ idCustomer: customerId,
2284
+ isSuperAdmin: isSuperAdmin,
2285
+ includeClientScope: shouldScopeByClient
2286
+ })];
2287
+ case 18:
2288
+ _c = (_q.sent());
2289
+ _q.label = 19;
2290
+ case 19:
2291
+ probeDocs = _c;
2292
+ shouldUnwind = probeDocs.length ? hasArrayValueAtPath(probeDocs, unwindFallback.path) : false;
2293
+ return [3 /*break*/, 21];
2294
+ case 20:
2295
+ _d = _q.sent();
2296
+ shouldUnwind = false;
2297
+ return [3 /*break*/, 21];
2298
+ case 21:
2299
+ if (!shouldUnwind) return [3 /*break*/, 24];
2229
2300
  fallbackPipeline = buildAggregateUnwindFallbackPipeline(executedPipeline, unwindFallback);
2230
- if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 18];
2301
+ if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 23];
2231
2302
  return [4 /*yield*/, db.collection(collection)
2232
2303
  .aggregate(fallbackPipeline, aggregateOptions)
2233
2304
  .toArray()];
2234
- case 17:
2235
- fallbackDocs = _o.sent();
2305
+ case 22:
2306
+ fallbackDocs = _q.sent();
2236
2307
  if (fallbackDocs.length > documents.length) {
2237
2308
  documents = fallbackDocs;
2238
2309
  executedPipeline = fallbackPipeline;
2239
2310
  fallbackMeta.unwind.used = true;
2240
2311
  }
2241
- _o.label = 18;
2242
- case 18:
2243
- if (!!documents.length) return [3 /*break*/, 20];
2312
+ _q.label = 23;
2313
+ case 23: return [3 /*break*/, 25];
2314
+ case 24:
2315
+ fallbackMeta.unwind.skipped = 'not_array';
2316
+ _q.label = 25;
2317
+ case 25:
2318
+ if (!!documents.length) return [3 /*break*/, 27];
2244
2319
  nameFallback = resolveAggregateNameMatchFallback(executedPipeline);
2245
- if (!nameFallback) return [3 /*break*/, 20];
2320
+ if (!nameFallback) return [3 /*break*/, 27];
2246
2321
  fallbackMeta.nameMatch = {
2247
2322
  field: nameFallback.field,
2248
2323
  fields: nameFallback.fields,
@@ -2250,22 +2325,22 @@ function executeAiAssistantMongoAggregate(payload, context) {
2250
2325
  used: false
2251
2326
  };
2252
2327
  fallbackPipeline = buildAggregateNameMatchFallbackPipeline(executedPipeline, nameFallback);
2253
- if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 20];
2328
+ if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 27];
2254
2329
  return [4 /*yield*/, db.collection(collection)
2255
2330
  .aggregate(fallbackPipeline, aggregateOptions)
2256
2331
  .toArray()];
2257
- case 19:
2258
- fallbackDocs = _o.sent();
2332
+ case 26:
2333
+ fallbackDocs = _q.sent();
2259
2334
  if (fallbackDocs.length) {
2260
2335
  documents = fallbackDocs;
2261
2336
  executedPipeline = fallbackPipeline;
2262
2337
  fallbackMeta.nameMatch.used = true;
2263
2338
  }
2264
- _o.label = 20;
2265
- case 20:
2266
- if (!!documents.length) return [3 /*break*/, 26];
2267
- _c = probeDocs;
2268
- if (_c) return [3 /*break*/, 22];
2339
+ _q.label = 27;
2340
+ case 27:
2341
+ if (!!documents.length) return [3 /*break*/, 33];
2342
+ _e = probeDocs;
2343
+ if (_e) return [3 /*break*/, 29];
2269
2344
  return [4 /*yield*/, fetchAssistantProbeDocs({
2270
2345
  db: db,
2271
2346
  collection: collection,
@@ -2274,15 +2349,15 @@ function executeAiAssistantMongoAggregate(payload, context) {
2274
2349
  isSuperAdmin: isSuperAdmin,
2275
2350
  includeClientScope: shouldScopeByClient
2276
2351
  })];
2277
- case 21:
2278
- _c = (_o.sent());
2279
- _o.label = 22;
2280
- case 22:
2281
- probeDocs = _c;
2352
+ case 28:
2353
+ _e = (_q.sent());
2354
+ _q.label = 29;
2355
+ case 29:
2356
+ probeDocs = _e;
2282
2357
  _loop_1 = function (i) {
2283
2358
  var stage, chemicalLookup, rewrittenPipeline, fallbackDocs;
2284
- return __generator(this, function (_p) {
2285
- switch (_p.label) {
2359
+ return __generator(this, function (_r) {
2360
+ switch (_r.label) {
2286
2361
  case 0:
2287
2362
  stage = executedPipeline[i];
2288
2363
  if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
@@ -2298,7 +2373,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
2298
2373
  probeDocs: probeDocs || undefined
2299
2374
  })];
2300
2375
  case 1:
2301
- chemicalLookup = _p.sent();
2376
+ chemicalLookup = _r.sent();
2302
2377
  if (!chemicalLookup) {
2303
2378
  return [2 /*return*/, "continue"];
2304
2379
  }
@@ -2309,33 +2384,33 @@ function executeAiAssistantMongoAggregate(payload, context) {
2309
2384
  .aggregate(rewrittenPipeline, aggregateOptions)
2310
2385
  .toArray()];
2311
2386
  case 2:
2312
- fallbackDocs = _p.sent();
2387
+ fallbackDocs = _r.sent();
2313
2388
  if (fallbackDocs.length) {
2314
2389
  documents = fallbackDocs;
2315
2390
  executedPipeline = rewrittenPipeline;
2316
2391
  fallbackMeta.chemicalLookup.used = true;
2317
2392
  return [2 /*return*/, "break"];
2318
2393
  }
2319
- _p.label = 3;
2394
+ _r.label = 3;
2320
2395
  case 3: return [2 /*return*/];
2321
2396
  }
2322
2397
  });
2323
2398
  };
2324
2399
  i = 0;
2325
- _o.label = 23;
2326
- case 23:
2327
- if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 26];
2400
+ _q.label = 30;
2401
+ case 30:
2402
+ if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 33];
2328
2403
  return [5 /*yield**/, _loop_1(i)];
2329
- case 24:
2330
- state_1 = _o.sent();
2404
+ case 31:
2405
+ state_1 = _q.sent();
2331
2406
  if (state_1 === "break")
2332
- return [3 /*break*/, 26];
2333
- _o.label = 25;
2334
- case 25:
2407
+ return [3 /*break*/, 33];
2408
+ _q.label = 32;
2409
+ case 32:
2335
2410
  i += 1;
2336
- return [3 /*break*/, 23];
2337
- case 26:
2338
- if (!!documents.length) return [3 /*break*/, 30];
2411
+ return [3 /*break*/, 30];
2412
+ case 33:
2413
+ if (!!documents.length) return [3 /*break*/, 37];
2339
2414
  matchFields_1 = new Set();
2340
2415
  (executedPipeline || []).forEach(function (stage) {
2341
2416
  if (stage && typeof stage === 'object' && stage.$match && typeof stage.$match === 'object') {
@@ -2344,9 +2419,9 @@ function executeAiAssistantMongoAggregate(payload, context) {
2344
2419
  .forEach(function (field) { return matchFields_1.add(field); });
2345
2420
  }
2346
2421
  });
2347
- if (!matchFields_1.size) return [3 /*break*/, 30];
2348
- _d = probeDocs;
2349
- if (_d) return [3 /*break*/, 28];
2422
+ if (!matchFields_1.size) return [3 /*break*/, 37];
2423
+ _f = probeDocs;
2424
+ if (_f) return [3 /*break*/, 35];
2350
2425
  return [4 /*yield*/, fetchAssistantProbeDocs({
2351
2426
  db: db,
2352
2427
  collection: collection,
@@ -2355,14 +2430,14 @@ function executeAiAssistantMongoAggregate(payload, context) {
2355
2430
  isSuperAdmin: isSuperAdmin,
2356
2431
  includeClientScope: shouldScopeByClient
2357
2432
  })];
2358
- case 27:
2359
- _d = (_o.sent());
2360
- _o.label = 28;
2361
- case 28:
2362
- probeDocs = _d;
2363
- if (!probeDocs.length) return [3 /*break*/, 30];
2433
+ case 34:
2434
+ _f = (_q.sent());
2435
+ _q.label = 35;
2436
+ case 35:
2437
+ probeDocs = _f;
2438
+ if (!probeDocs.length) return [3 /*break*/, 37];
2364
2439
  aliases = resolveFieldAliases(probeDocs, Array.from(matchFields_1), schemaFields);
2365
- if (!Object.keys(aliases).length) return [3 /*break*/, 30];
2440
+ if (!Object.keys(aliases).length) return [3 /*break*/, 37];
2366
2441
  fallbackMeta.queryFieldAliases = {
2367
2442
  aliases: aliases,
2368
2443
  attempted: true,
@@ -2373,31 +2448,31 @@ function executeAiAssistantMongoAggregate(payload, context) {
2373
2448
  var _b = __read(_a, 2), from = _b[0], to = _b[1];
2374
2449
  return replaceFieldPathDeep(acc, from, to);
2375
2450
  }, executedPipeline);
2376
- if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 30];
2451
+ if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 37];
2377
2452
  return [4 /*yield*/, db.collection(collection)
2378
2453
  .aggregate(rewrittenPipeline, aggregateOptions)
2379
2454
  .toArray()];
2380
- case 29:
2381
- fallbackDocs = _o.sent();
2455
+ case 36:
2456
+ fallbackDocs = _q.sent();
2382
2457
  if (fallbackDocs.length) {
2383
2458
  documents = fallbackDocs;
2384
2459
  executedPipeline = rewrittenPipeline;
2385
2460
  fallbackMeta.queryFieldAliases.used = true;
2386
2461
  }
2387
- _o.label = 30;
2388
- case 30:
2389
- if (!!documents.length) return [3 /*break*/, 34];
2462
+ _q.label = 37;
2463
+ case 37:
2464
+ if (!!documents.length) return [3 /*break*/, 41];
2390
2465
  _loop_2 = function (i) {
2391
- var stage, _q, idLookup, rewrittenPipeline, fallbackDocs;
2392
- return __generator(this, function (_r) {
2393
- switch (_r.label) {
2466
+ var stage, _s, idLookup, rewrittenPipeline, fallbackDocs;
2467
+ return __generator(this, function (_t) {
2468
+ switch (_t.label) {
2394
2469
  case 0:
2395
2470
  stage = executedPipeline[i];
2396
2471
  if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
2397
2472
  return [2 /*return*/, "continue"];
2398
2473
  }
2399
- _q = probeDocs;
2400
- if (_q) return [3 /*break*/, 2];
2474
+ _s = probeDocs;
2475
+ if (_s) return [3 /*break*/, 2];
2401
2476
  return [4 /*yield*/, fetchAssistantProbeDocs({
2402
2477
  db: db,
2403
2478
  collection: collection,
@@ -2407,10 +2482,10 @@ function executeAiAssistantMongoAggregate(payload, context) {
2407
2482
  includeClientScope: shouldScopeByClient
2408
2483
  })];
2409
2484
  case 1:
2410
- _q = (_r.sent());
2411
- _r.label = 2;
2485
+ _s = (_t.sent());
2486
+ _t.label = 2;
2412
2487
  case 2:
2413
- probeDocs = _q;
2488
+ probeDocs = _s;
2414
2489
  return [4 /*yield*/, applyIdLookupFallbackToQuery({
2415
2490
  query: stage.$match,
2416
2491
  db: db,
@@ -2421,7 +2496,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
2421
2496
  probeDocs: probeDocs || undefined
2422
2497
  })];
2423
2498
  case 3:
2424
- idLookup = _r.sent();
2499
+ idLookup = _t.sent();
2425
2500
  if (!idLookup) {
2426
2501
  return [2 /*return*/, "continue"];
2427
2502
  }
@@ -2432,41 +2507,41 @@ function executeAiAssistantMongoAggregate(payload, context) {
2432
2507
  .aggregate(rewrittenPipeline, aggregateOptions)
2433
2508
  .toArray()];
2434
2509
  case 4:
2435
- fallbackDocs = _r.sent();
2510
+ fallbackDocs = _t.sent();
2436
2511
  if (fallbackDocs.length) {
2437
2512
  documents = fallbackDocs;
2438
2513
  executedPipeline = rewrittenPipeline;
2439
2514
  fallbackMeta.idLookup.used = true;
2440
2515
  return [2 /*return*/, "break"];
2441
2516
  }
2442
- _r.label = 5;
2517
+ _t.label = 5;
2443
2518
  case 5: return [2 /*return*/];
2444
2519
  }
2445
2520
  });
2446
2521
  };
2447
2522
  i = 0;
2448
- _o.label = 31;
2449
- case 31:
2450
- if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 34];
2523
+ _q.label = 38;
2524
+ case 38:
2525
+ if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 41];
2451
2526
  return [5 /*yield**/, _loop_2(i)];
2452
- case 32:
2453
- state_2 = _o.sent();
2527
+ case 39:
2528
+ state_2 = _q.sent();
2454
2529
  if (state_2 === "break")
2455
- return [3 /*break*/, 34];
2456
- _o.label = 33;
2457
- case 33:
2530
+ return [3 /*break*/, 41];
2531
+ _q.label = 40;
2532
+ case 40:
2458
2533
  i += 1;
2459
- return [3 /*break*/, 31];
2460
- case 34:
2461
- if (!!documents.length) return [3 /*break*/, 37];
2534
+ return [3 /*break*/, 38];
2535
+ case 41:
2536
+ if (!!documents.length) return [3 /*break*/, 44];
2462
2537
  return [4 /*yield*/, resolveBaseCollectionFromReport(db, dbName, collection)];
2463
- case 35:
2464
- baseCollection = _o.sent();
2465
- if (!(baseCollection && baseCollection !== collection)) return [3 /*break*/, 37];
2538
+ case 42:
2539
+ baseCollection = _q.sent();
2540
+ if (!(baseCollection && baseCollection !== collection)) return [3 /*break*/, 44];
2466
2541
  fallbackPayload = __assign(__assign({}, input), { collection: baseCollection });
2467
2542
  return [4 /*yield*/, executeAiAssistantMongoAggregate(fallbackPayload, context)];
2468
- case 36:
2469
- fallbackResult = _o.sent();
2543
+ case 43:
2544
+ fallbackResult = _q.sent();
2470
2545
  if (Array.isArray(fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.documents) && fallbackResult.documents.length) {
2471
2546
  if (isSuperAdmin && (fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.debug) && typeof fallbackResult.debug === 'object') {
2472
2547
  existingFallbacks = fallbackResult.debug.fallbacks && typeof fallbackResult.debug.fallbacks === 'object'
@@ -2483,48 +2558,48 @@ function executeAiAssistantMongoAggregate(payload, context) {
2483
2558
  if (isSuperAdmin) {
2484
2559
  fallbackMeta.reportFallback = { from: collection, to: baseCollection, attempted: true, used: false };
2485
2560
  }
2486
- _o.label = 37;
2487
- case 37:
2488
- if (!(!documents.length && isSuperAdmin)) return [3 /*break*/, 54];
2561
+ _q.label = 44;
2562
+ case 44:
2563
+ if (!(!documents.length && isSuperAdmin)) return [3 /*break*/, 61];
2489
2564
  matchStages = (executedPipeline || []).filter(function (stage) { return stage && typeof stage === 'object' && stage.$match && typeof stage.$match === 'object'; });
2490
2565
  diagnostics = {};
2491
- if (!matchStages.length) return [3 /*break*/, 54];
2566
+ if (!matchStages.length) return [3 /*break*/, 61];
2492
2567
  combinedMatch = matchStages.reduce(function (acc, stage) { return ({ $and: __spreadArray(__spreadArray([], __read((acc.$and || [])), false), [stage.$match], false) }); }, { $and: [] });
2493
2568
  nameFields = collectMatchFieldsByCondition(combinedMatch, function (field, condition) { return isRegexMatchCondition(condition)
2494
2569
  || (typeof condition === 'string' && shouldApplyAssistantNameRegex(field)); });
2495
2570
  dateFields = collectMatchFieldsByCondition(combinedMatch, function (_field, condition) { return isDateCondition(condition); });
2496
2571
  diagnostics.nameFields = nameFields.length ? nameFields : undefined;
2497
2572
  diagnostics.dateFields = dateFields.length ? dateFields : undefined;
2498
- _o.label = 38;
2499
- case 38:
2500
- _o.trys.push([38, 43, , 44]);
2501
- if (!nameFields.length) return [3 /*break*/, 40];
2573
+ _q.label = 45;
2574
+ case 45:
2575
+ _q.trys.push([45, 50, , 51]);
2576
+ if (!nameFields.length) return [3 /*break*/, 47];
2502
2577
  queryNoName = stripMatchFields(combinedMatch, nameFields);
2503
- _e = diagnostics;
2578
+ _g = diagnostics;
2504
2579
  return [4 /*yield*/, db.collection(collection).countDocuments(queryNoName, {
2505
2580
  readPreference: AI_ASSISTANT_READ_PREFERENCE
2506
2581
  })];
2507
- case 39:
2508
- _e.recentCount = _o.sent();
2509
- _o.label = 40;
2510
- case 40:
2511
- if (!dateFields.length) return [3 /*break*/, 42];
2582
+ case 46:
2583
+ _g.recentCount = _q.sent();
2584
+ _q.label = 47;
2585
+ case 47:
2586
+ if (!dateFields.length) return [3 /*break*/, 49];
2512
2587
  queryNoDate = stripMatchFields(combinedMatch, dateFields);
2513
- _f = diagnostics;
2588
+ _h = diagnostics;
2514
2589
  return [4 /*yield*/, db.collection(collection).countDocuments(queryNoDate, {
2515
2590
  readPreference: AI_ASSISTANT_READ_PREFERENCE
2516
2591
  })];
2517
- case 41:
2518
- _f.nameMatchCount = _o.sent();
2519
- _o.label = 42;
2520
- case 42: return [3 /*break*/, 44];
2521
- case 43:
2522
- _g = _o.sent();
2523
- return [3 /*break*/, 44];
2524
- case 44:
2525
- _o.trys.push([44, 47, , 48]);
2526
- _h = probeDocs;
2527
- if (_h) return [3 /*break*/, 46];
2592
+ case 48:
2593
+ _h.nameMatchCount = _q.sent();
2594
+ _q.label = 49;
2595
+ case 49: return [3 /*break*/, 51];
2596
+ case 50:
2597
+ _j = _q.sent();
2598
+ return [3 /*break*/, 51];
2599
+ case 51:
2600
+ _q.trys.push([51, 54, , 55]);
2601
+ _k = probeDocs;
2602
+ if (_k) return [3 /*break*/, 53];
2528
2603
  return [4 /*yield*/, fetchAssistantProbeDocs({
2529
2604
  db: db,
2530
2605
  collection: collection,
@@ -2533,44 +2608,44 @@ function executeAiAssistantMongoAggregate(payload, context) {
2533
2608
  isSuperAdmin: isSuperAdmin,
2534
2609
  includeClientScope: shouldScopeByClient
2535
2610
  })];
2536
- case 45:
2537
- _h = (_o.sent());
2538
- _o.label = 46;
2539
- case 46:
2540
- probeDocs = _h;
2611
+ case 52:
2612
+ _k = (_q.sent());
2613
+ _q.label = 53;
2614
+ case 53:
2615
+ probeDocs = _k;
2541
2616
  if (probeDocs.length && nameFields.length) {
2542
2617
  diagnostics.chemicalIdDetected = detectChemicalIdFromProbe(probeDocs, nameFields);
2543
2618
  }
2544
- return [3 /*break*/, 48];
2545
- case 47:
2546
- _j = _o.sent();
2547
- return [3 /*break*/, 48];
2548
- case 48:
2549
- _o.trys.push([48, 52, , 53]);
2619
+ return [3 /*break*/, 55];
2620
+ case 54:
2621
+ _l = _q.sent();
2622
+ return [3 /*break*/, 55];
2623
+ case 55:
2624
+ _q.trys.push([55, 59, , 60]);
2550
2625
  return [4 /*yield*/, listAssistantCollections(db, dbName)];
2551
- case 49:
2552
- allCollections = _o.sent();
2626
+ case 56:
2627
+ allCollections = _q.sent();
2553
2628
  base = stripVersionSuffix(collection.startsWith('report-') ? collection.slice('report-'.length) : collection);
2554
2629
  alt = collection.startsWith('report-') ? base : "report-".concat(base);
2555
- if (!(alt && alt !== collection && allCollections.includes(alt))) return [3 /*break*/, 51];
2630
+ if (!(alt && alt !== collection && allCollections.includes(alt))) return [3 /*break*/, 58];
2556
2631
  return [4 /*yield*/, db.collection(alt).countDocuments({}, { readPreference: AI_ASSISTANT_READ_PREFERENCE })];
2557
- case 50:
2558
- altCount = _o.sent();
2632
+ case 57:
2633
+ altCount = _q.sent();
2559
2634
  diagnostics.alternateCollection = alt;
2560
2635
  diagnostics.alternateCollectionCount = altCount;
2561
- _o.label = 51;
2562
- case 51: return [3 /*break*/, 53];
2563
- case 52:
2564
- _k = _o.sent();
2565
- return [3 /*break*/, 53];
2566
- case 53:
2636
+ _q.label = 58;
2637
+ case 58: return [3 /*break*/, 60];
2638
+ case 59:
2639
+ _m = _q.sent();
2640
+ return [3 /*break*/, 60];
2641
+ case 60:
2567
2642
  fallbackMeta.zeroDiagnostics = diagnostics;
2568
- _o.label = 54;
2569
- case 54:
2643
+ _q.label = 61;
2644
+ case 61:
2570
2645
  sanitizedDocuments = isSuperAdmin
2571
2646
  ? documents
2572
2647
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
2573
- includeIds = ((_m = input.options) === null || _m === void 0 ? void 0 : _m.includeIds) === true;
2648
+ includeIds = ((_p = input.options) === null || _p === void 0 ? void 0 : _p.includeIds) === true;
2574
2649
  displayDocs = sanitizedDocuments;
2575
2650
  return [4 /*yield*/, applyIdLookupDisplayEnrichment({
2576
2651
  docs: displayDocs,
@@ -2581,8 +2656,8 @@ function executeAiAssistantMongoAggregate(payload, context) {
2581
2656
  idCustomer: customerId,
2582
2657
  isSuperAdmin: isSuperAdmin
2583
2658
  })];
2584
- case 55:
2585
- idLookupDisplay = _o.sent();
2659
+ case 62:
2660
+ idLookupDisplay = _q.sent();
2586
2661
  if (idLookupDisplay === null || idLookupDisplay === void 0 ? void 0 : idLookupDisplay.docs) {
2587
2662
  displayDocs = idLookupDisplay.docs;
2588
2663
  }
@@ -3314,21 +3389,44 @@ function getValueAtPath(obj, path) {
3314
3389
  };
3315
3390
  return walk(obj, 0);
3316
3391
  }
3392
+ function hasArrayValueAtPath(docs, path) {
3393
+ var e_1, _a;
3394
+ if (!Array.isArray(docs) || !docs.length || !path) {
3395
+ return false;
3396
+ }
3397
+ try {
3398
+ for (var docs_1 = __values(docs), docs_1_1 = docs_1.next(); !docs_1_1.done; docs_1_1 = docs_1.next()) {
3399
+ var doc = docs_1_1.value;
3400
+ var value = getValueAtPath(doc, path);
3401
+ if (Array.isArray(value)) {
3402
+ return true;
3403
+ }
3404
+ }
3405
+ }
3406
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3407
+ finally {
3408
+ try {
3409
+ if (docs_1_1 && !docs_1_1.done && (_a = docs_1.return)) _a.call(docs_1);
3410
+ }
3411
+ finally { if (e_1) throw e_1.error; }
3412
+ }
3413
+ return false;
3414
+ }
3317
3415
  function inferIdFieldStorageTypeFromDocs(docs, fieldPath) {
3318
- var e_1, _a, e_2, _b;
3416
+ var e_2, _a, e_3, _b;
3319
3417
  if (!Array.isArray(docs) || !fieldPath) {
3320
3418
  return 'unknown';
3321
3419
  }
3322
3420
  var sawString = false;
3323
3421
  try {
3324
- for (var docs_1 = __values(docs), docs_1_1 = docs_1.next(); !docs_1_1.done; docs_1_1 = docs_1.next()) {
3325
- var doc = docs_1_1.value;
3422
+ for (var docs_2 = __values(docs), docs_2_1 = docs_2.next(); !docs_2_1.done; docs_2_1 = docs_2.next()) {
3423
+ var doc = docs_2_1.value;
3326
3424
  var value = fieldPath.includes('.')
3327
3425
  ? getValueAtPath(doc, fieldPath)
3328
3426
  : doc === null || doc === void 0 ? void 0 : doc[fieldPath];
3329
3427
  var queue = Array.isArray(value) ? value : [value];
3330
3428
  try {
3331
- for (var queue_1 = (e_2 = void 0, __values(queue)), queue_1_1 = queue_1.next(); !queue_1_1.done; queue_1_1 = queue_1.next()) {
3429
+ for (var queue_1 = (e_3 = void 0, __values(queue)), queue_1_1 = queue_1.next(); !queue_1_1.done; queue_1_1 = queue_1.next()) {
3332
3430
  var entry = queue_1_1.value;
3333
3431
  if (entry === null || entry === undefined) {
3334
3432
  continue;
@@ -3341,21 +3439,21 @@ function inferIdFieldStorageTypeFromDocs(docs, fieldPath) {
3341
3439
  }
3342
3440
  }
3343
3441
  }
3344
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
3442
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
3345
3443
  finally {
3346
3444
  try {
3347
3445
  if (queue_1_1 && !queue_1_1.done && (_b = queue_1.return)) _b.call(queue_1);
3348
3446
  }
3349
- finally { if (e_2) throw e_2.error; }
3447
+ finally { if (e_3) throw e_3.error; }
3350
3448
  }
3351
3449
  }
3352
3450
  }
3353
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
3451
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
3354
3452
  finally {
3355
3453
  try {
3356
- if (docs_1_1 && !docs_1_1.done && (_a = docs_1.return)) _a.call(docs_1);
3454
+ if (docs_2_1 && !docs_2_1.done && (_a = docs_2.return)) _a.call(docs_2);
3357
3455
  }
3358
- finally { if (e_1) throw e_1.error; }
3456
+ finally { if (e_2) throw e_2.error; }
3359
3457
  }
3360
3458
  return sawString ? 'string' : 'unknown';
3361
3459
  }
@@ -3450,7 +3548,7 @@ function normalizeLookupKeyValue(value) {
3450
3548
  return '';
3451
3549
  }
3452
3550
  function collectTopLevelIdFieldValues(docs, options) {
3453
- var e_3, _a, e_4, _b;
3551
+ var e_4, _a, e_5, _b;
3454
3552
  if (!Array.isArray(docs) || !docs.length) {
3455
3553
  return [];
3456
3554
  }
@@ -3462,8 +3560,8 @@ function collectTopLevelIdFieldValues(docs, options) {
3462
3560
  : AI_ASSISTANT_ID_DISPLAY_LOOKUP_MAX_IDS;
3463
3561
  var fieldMap = new Map();
3464
3562
  try {
3465
- for (var docs_2 = __values(docs), docs_2_1 = docs_2.next(); !docs_2_1.done; docs_2_1 = docs_2.next()) {
3466
- var doc = docs_2_1.value;
3563
+ for (var docs_3 = __values(docs), docs_3_1 = docs_3.next(); !docs_3_1.done; docs_3_1 = docs_3.next()) {
3564
+ var doc = docs_3_1.value;
3467
3565
  if (!doc || typeof doc !== 'object') {
3468
3566
  continue;
3469
3567
  }
@@ -3498,26 +3596,26 @@ function collectTopLevelIdFieldValues(docs, options) {
3498
3596
  });
3499
3597
  };
3500
3598
  try {
3501
- for (var keys_1 = (e_4 = void 0, __values(keys)), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
3599
+ for (var keys_1 = (e_5 = void 0, __values(keys)), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
3502
3600
  var key = keys_1_1.value;
3503
3601
  _loop_3(key);
3504
3602
  }
3505
3603
  }
3506
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
3604
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
3507
3605
  finally {
3508
3606
  try {
3509
3607
  if (keys_1_1 && !keys_1_1.done && (_b = keys_1.return)) _b.call(keys_1);
3510
3608
  }
3511
- finally { if (e_4) throw e_4.error; }
3609
+ finally { if (e_5) throw e_5.error; }
3512
3610
  }
3513
3611
  }
3514
3612
  }
3515
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
3613
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
3516
3614
  finally {
3517
3615
  try {
3518
- if (docs_2_1 && !docs_2_1.done && (_a = docs_2.return)) _a.call(docs_2);
3616
+ if (docs_3_1 && !docs_3_1.done && (_a = docs_3.return)) _a.call(docs_3);
3519
3617
  }
3520
- finally { if (e_3) throw e_3.error; }
3618
+ finally { if (e_4) throw e_4.error; }
3521
3619
  }
3522
3620
  return Array.from(fieldMap.entries()).map(function (_a) {
3523
3621
  var _b = __read(_a, 2), field = _b[0], values = _b[1];
@@ -3528,7 +3626,7 @@ function collectTopLevelIdFieldValues(docs, options) {
3528
3626
  });
3529
3627
  }
3530
3628
  function resolveLookupDisplayField(baseToken, probeDocs, schemaFields) {
3531
- var e_5, _a, e_6, _b;
3629
+ var e_6, _a, e_7, _b;
3532
3630
  var normalizedBase = normalizeOptionalString(baseToken);
3533
3631
  if (!normalizedBase) {
3534
3632
  return null;
@@ -3546,12 +3644,12 @@ function resolveLookupDisplayField(baseToken, probeDocs, schemaFields) {
3546
3644
  }
3547
3645
  }
3548
3646
  }
3549
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
3647
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
3550
3648
  finally {
3551
3649
  try {
3552
3650
  if (schemaCandidates_1_1 && !schemaCandidates_1_1.done && (_a = schemaCandidates_1.return)) _a.call(schemaCandidates_1);
3553
3651
  }
3554
- finally { if (e_5) throw e_5.error; }
3652
+ finally { if (e_6) throw e_6.error; }
3555
3653
  }
3556
3654
  return schemaCandidates[0];
3557
3655
  }
@@ -3564,12 +3662,12 @@ function resolveLookupDisplayField(baseToken, probeDocs, schemaFields) {
3564
3662
  }
3565
3663
  }
3566
3664
  }
3567
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
3665
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
3568
3666
  finally {
3569
3667
  try {
3570
3668
  if (candidates_1_1 && !candidates_1_1.done && (_b = candidates_1.return)) _b.call(candidates_1);
3571
3669
  }
3572
- finally { if (e_6) throw e_6.error; }
3670
+ finally { if (e_7) throw e_7.error; }
3573
3671
  }
3574
3672
  return candidates.length ? candidates[0] : null;
3575
3673
  }
@@ -3582,8 +3680,8 @@ function resolveLookupMappingsForField(field, mappings) {
3582
3680
  }
3583
3681
  function applyIdLookupDisplayEnrichment(params) {
3584
3682
  return __awaiter(this, void 0, void 0, function () {
3585
- var docs, collection, db, dbName, idClient, idCustomer, isSuperAdmin, idFields, lookupMappings, allCollections, collectionProbeCache, collectionSchemaCache, lookupMeta, enrichedDocs, _loop_4, idFields_1, idFields_1_1, fieldEntry, e_7_1;
3586
- var e_7, _a;
3683
+ var docs, collection, db, dbName, idClient, idCustomer, isSuperAdmin, idFields, lookupMappings, allCollections, collectionProbeCache, collectionSchemaCache, lookupMeta, enrichedDocs, _loop_4, idFields_1, idFields_1_1, fieldEntry, e_8_1;
3684
+ var e_8, _a;
3587
3685
  return __generator(this, function (_b) {
3588
3686
  switch (_b.label) {
3589
3687
  case 0:
@@ -3607,8 +3705,8 @@ function applyIdLookupDisplayEnrichment(params) {
3607
3705
  lookupMeta = [];
3608
3706
  enrichedDocs = docs.map(function (doc) { return (__assign({}, doc)); });
3609
3707
  _loop_4 = function (fieldEntry) {
3610
- var values, baseToken, mappingMatches, candidateCollections, filteredCandidates, _loop_5, filteredCandidates_1, filteredCandidates_1_1, candidate, state_3, e_8_1;
3611
- var e_8, _c;
3708
+ var values, baseToken, mappingMatches, candidateCollections, filteredCandidates, _loop_5, filteredCandidates_1, filteredCandidates_1_1, candidate, state_3, e_9_1;
3709
+ var e_9, _c;
3612
3710
  return __generator(this, function (_d) {
3613
3711
  switch (_d.label) {
3614
3712
  case 0:
@@ -3757,7 +3855,7 @@ function applyIdLookupDisplayEnrichment(params) {
3757
3855
  _d.label = 1;
3758
3856
  case 1:
3759
3857
  _d.trys.push([1, 6, 7, 8]);
3760
- filteredCandidates_1 = (e_8 = void 0, __values(filteredCandidates)), filteredCandidates_1_1 = filteredCandidates_1.next();
3858
+ filteredCandidates_1 = (e_9 = void 0, __values(filteredCandidates)), filteredCandidates_1_1 = filteredCandidates_1.next();
3761
3859
  _d.label = 2;
3762
3860
  case 2:
3763
3861
  if (!!filteredCandidates_1_1.done) return [3 /*break*/, 5];
@@ -3773,14 +3871,14 @@ function applyIdLookupDisplayEnrichment(params) {
3773
3871
  return [3 /*break*/, 2];
3774
3872
  case 5: return [3 /*break*/, 8];
3775
3873
  case 6:
3776
- e_8_1 = _d.sent();
3777
- e_8 = { error: e_8_1 };
3874
+ e_9_1 = _d.sent();
3875
+ e_9 = { error: e_9_1 };
3778
3876
  return [3 /*break*/, 8];
3779
3877
  case 7:
3780
3878
  try {
3781
3879
  if (filteredCandidates_1_1 && !filteredCandidates_1_1.done && (_c = filteredCandidates_1.return)) _c.call(filteredCandidates_1);
3782
3880
  }
3783
- finally { if (e_8) throw e_8.error; }
3881
+ finally { if (e_9) throw e_9.error; }
3784
3882
  return [7 /*endfinally*/];
3785
3883
  case 8: return [2 /*return*/];
3786
3884
  }
@@ -3803,14 +3901,14 @@ function applyIdLookupDisplayEnrichment(params) {
3803
3901
  return [3 /*break*/, 3];
3804
3902
  case 6: return [3 /*break*/, 9];
3805
3903
  case 7:
3806
- e_7_1 = _b.sent();
3807
- e_7 = { error: e_7_1 };
3904
+ e_8_1 = _b.sent();
3905
+ e_8 = { error: e_8_1 };
3808
3906
  return [3 /*break*/, 9];
3809
3907
  case 8:
3810
3908
  try {
3811
3909
  if (idFields_1_1 && !idFields_1_1.done && (_a = idFields_1.return)) _a.call(idFields_1);
3812
3910
  }
3813
- finally { if (e_7) throw e_7.error; }
3911
+ finally { if (e_8) throw e_8.error; }
3814
3912
  return [7 /*endfinally*/];
3815
3913
  case 9:
3816
3914
  if (!lookupMeta.length) {
@@ -3829,14 +3927,14 @@ function applyIdLookupDisplayEnrichment(params) {
3829
3927
  });
3830
3928
  }
3831
3929
  function hasNonEmptyValue(docs, fieldPath, options) {
3832
- var e_9, _a;
3930
+ var e_10, _a;
3833
3931
  if (!Array.isArray(docs) || !fieldPath) {
3834
3932
  return false;
3835
3933
  }
3836
3934
  var usePath = fieldPath.includes('.');
3837
3935
  try {
3838
- for (var docs_3 = __values(docs), docs_3_1 = docs_3.next(); !docs_3_1.done; docs_3_1 = docs_3.next()) {
3839
- var doc = docs_3_1.value;
3936
+ for (var docs_4 = __values(docs), docs_4_1 = docs_4.next(); !docs_4_1.done; docs_4_1 = docs_4.next()) {
3937
+ var doc = docs_4_1.value;
3840
3938
  var value = usePath ? getValueAtPath(doc, fieldPath) : doc === null || doc === void 0 ? void 0 : doc[fieldPath];
3841
3939
  if ((options === null || options === void 0 ? void 0 : options.treatObjectLikeAsEmpty) && isDisplayObjectLike(value)) {
3842
3940
  continue;
@@ -3846,12 +3944,12 @@ function hasNonEmptyValue(docs, fieldPath, options) {
3846
3944
  }
3847
3945
  }
3848
3946
  }
3849
- catch (e_9_1) { e_9 = { error: e_9_1 }; }
3947
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
3850
3948
  finally {
3851
3949
  try {
3852
- if (docs_3_1 && !docs_3_1.done && (_a = docs_3.return)) _a.call(docs_3);
3950
+ if (docs_4_1 && !docs_4_1.done && (_a = docs_4.return)) _a.call(docs_4);
3853
3951
  }
3854
- finally { if (e_9) throw e_9.error; }
3952
+ finally { if (e_10) throw e_10.error; }
3855
3953
  }
3856
3954
  return false;
3857
3955
  }
@@ -4123,35 +4221,45 @@ function replaceFieldPathDeep(value, fromField, toField) {
4123
4221
  return next_1;
4124
4222
  }
4125
4223
  if (typeof value === 'string') {
4126
- if (value.startsWith("$".concat(fromField))) {
4127
- return "$".concat(toField).concat(value.slice(fromField.length + 1));
4224
+ var fromRef = "$".concat(fromField);
4225
+ if (value === fromRef) {
4226
+ return "$".concat(toField);
4227
+ }
4228
+ if (value.startsWith("".concat(fromRef, "."))) {
4229
+ return "$".concat(toField).concat(value.slice(fromRef.length));
4128
4230
  }
4129
4231
  return value;
4130
4232
  }
4131
4233
  return value;
4132
4234
  }
4133
4235
  function replaceQueryFieldCondition(query, field, condition) {
4134
- if (Array.isArray(query)) {
4135
- return query.map(function (entry) { return replaceQueryFieldCondition(entry, field, condition); });
4136
- }
4137
- if (!query || typeof query !== 'object') {
4138
- return query;
4139
- }
4140
- var next = __assign({}, query);
4141
- Object.keys(next).forEach(function (key) {
4142
- if (key === field) {
4143
- next[key] = condition;
4144
- return;
4145
- }
4146
- if (key.startsWith('$')) {
4147
- next[key] = replaceQueryFieldCondition(next[key], field, condition);
4148
- return;
4236
+ var hasPath = field.includes('.');
4237
+ var replaceValue = function (value, prefix) {
4238
+ if (Array.isArray(value)) {
4239
+ return value.map(function (entry) { return replaceValue(entry, prefix); });
4149
4240
  }
4150
- if (next[key] && typeof next[key] === 'object') {
4151
- next[key] = replaceQueryFieldCondition(next[key], field, condition);
4241
+ if (!value || typeof value !== 'object') {
4242
+ return value;
4152
4243
  }
4153
- });
4154
- return next;
4244
+ var next = __assign({}, value);
4245
+ Object.keys(next).forEach(function (key) {
4246
+ var currentPath = prefix ? "".concat(prefix, ".").concat(key) : key;
4247
+ var matches = hasPath ? currentPath === field : key === field;
4248
+ if (matches) {
4249
+ next[key] = condition;
4250
+ return;
4251
+ }
4252
+ if (key.startsWith('$')) {
4253
+ next[key] = replaceValue(next[key], prefix);
4254
+ return;
4255
+ }
4256
+ if (next[key] && typeof next[key] === 'object') {
4257
+ next[key] = replaceValue(next[key], currentPath);
4258
+ }
4259
+ });
4260
+ return next;
4261
+ };
4262
+ return replaceValue(query, '');
4155
4263
  }
4156
4264
  function formatDisplayColumnName(column) {
4157
4265
  var trimmed = String(column || '').trim();
@@ -4402,50 +4510,207 @@ function trimDisplayTable(display, options) {
4402
4510
  }) : [];
4403
4511
  return __assign(__assign({}, display), { columns: columns, rows: rows, truncated: display.truncated || display.columns.length > maxColumns || rowsSource.length > maxRows });
4404
4512
  }
4405
- function formatDisplayTableMarkdown(display) {
4406
- if (!display || !Array.isArray(display.columns) || !display.columns.length) {
4407
- return '';
4513
+ var assistantCurrencyFormatter = null;
4514
+ var assistantNumberFormatter = null;
4515
+ var assistantPercentFormatter = null;
4516
+ function getAssistantCurrencyFormatter() {
4517
+ if (!assistantCurrencyFormatter) {
4518
+ assistantCurrencyFormatter = new Intl.NumberFormat(AI_ASSISTANT_LOCALE, {
4519
+ style: 'currency',
4520
+ currency: AI_ASSISTANT_CURRENCY_CODE,
4521
+ minimumFractionDigits: 2,
4522
+ maximumFractionDigits: 2
4523
+ });
4408
4524
  }
4409
- var header = "| ".concat(display.columns.join(' | '), " |");
4410
- var separator = "| ".concat(display.columns.map(function () { return '---'; }).join(' | '), " |");
4411
- var rows = (display.rows || []).map(function (row) {
4412
- var cells = display.columns.map(function (column) { return escapeMarkdownCell(row === null || row === void 0 ? void 0 : row[column]); });
4413
- return "| ".concat(cells.join(' | '), " |");
4414
- });
4415
- return __spreadArray([header, separator], __read(rows), false).join('\n').trim();
4525
+ return assistantCurrencyFormatter;
4416
4526
  }
4417
- function escapeMarkdownCell(value) {
4418
- var raw = value === null || value === undefined ? '' : String(value);
4419
- return raw.replace(/\|/g, '\\|').replace(/\r?\n/g, ' ').trim();
4527
+ function getAssistantNumberFormatter() {
4528
+ if (!assistantNumberFormatter) {
4529
+ assistantNumberFormatter = new Intl.NumberFormat(AI_ASSISTANT_LOCALE, {
4530
+ minimumFractionDigits: 0,
4531
+ maximumFractionDigits: 2
4532
+ });
4533
+ }
4534
+ return assistantNumberFormatter;
4420
4535
  }
4421
- function isEmptyDisplayValue(value) {
4422
- if (value === null || value === undefined) {
4423
- return true;
4536
+ function getAssistantPercentFormatter() {
4537
+ if (!assistantPercentFormatter) {
4538
+ assistantPercentFormatter = new Intl.NumberFormat(AI_ASSISTANT_LOCALE, {
4539
+ style: 'percent',
4540
+ minimumFractionDigits: 0,
4541
+ maximumFractionDigits: 2
4542
+ });
4424
4543
  }
4425
- if (typeof value === 'string') {
4426
- return !value.trim();
4544
+ return assistantPercentFormatter;
4545
+ }
4546
+ function resolveAssistantNumericValue(value) {
4547
+ if (typeof value === 'number' && Number.isFinite(value)) {
4548
+ return value;
4427
4549
  }
4428
- if (Array.isArray(value)) {
4429
- return value.length === 0;
4550
+ if (typeof value === 'string') {
4551
+ var cleaned = value.replace(/[^0-9.+-]/g, '');
4552
+ if (!cleaned) {
4553
+ return null;
4554
+ }
4555
+ var parsed = Number(cleaned);
4556
+ return Number.isFinite(parsed) ? parsed : null;
4430
4557
  }
4431
- return false;
4558
+ return null;
4432
4559
  }
4433
- function isDisplayObjectLike(value) {
4434
- if (value === null || value === undefined) {
4560
+ function isAssistantPercentColumn(column) {
4561
+ return /(percent|pct|percentage|ratio|rate)\b/.test(column);
4562
+ }
4563
+ function isAssistantCurrencyColumn(column) {
4564
+ return /(amount|total|price|cost|balance|fee|revenue|invoice|usd|tax|subtotal|paid|billing|sales)\b/.test(column);
4565
+ }
4566
+ function isAssistantDateColumn(column) {
4567
+ return /(date|time|created|updated|timestamp|at)\b/.test(column);
4568
+ }
4569
+ function isAssistantLikelyDateValue(value) {
4570
+ if (!value) {
4435
4571
  return false;
4436
4572
  }
4437
4573
  if (value instanceof Date) {
4438
- return false;
4574
+ return true;
4439
4575
  }
4440
- if (isMongoObjectId(value)) {
4441
- return false;
4576
+ if (typeof value === 'string') {
4577
+ if (!/[0-9]/.test(value)) {
4578
+ return false;
4579
+ }
4580
+ var parsed = Date.parse(value);
4581
+ return !Number.isNaN(parsed);
4442
4582
  }
4443
- return typeof value === 'object';
4583
+ return false;
4444
4584
  }
4445
- function ensureAssistantReadAccess(context, permissionView, collection) {
4446
- return __awaiter(this, void 0, void 0, function () {
4447
- var idUser, user, isSuperAdmin, normalizedPermission, normalizedCollection;
4448
- var _a;
4585
+ function formatAssistantDateValue(value) {
4586
+ var dateValue = value instanceof Date ? value : new Date(value);
4587
+ if (Number.isNaN(dateValue.getTime())) {
4588
+ return String(value);
4589
+ }
4590
+ var iso = dateValue.toISOString();
4591
+ var _a = __read(iso.split('T'), 2), datePart = _a[0], timePart = _a[1];
4592
+ if (!timePart) {
4593
+ return datePart || iso;
4594
+ }
4595
+ var trimmed = timePart.replace('Z', '');
4596
+ if (trimmed.startsWith('00:00:00')) {
4597
+ return datePart;
4598
+ }
4599
+ return "".concat(datePart, " ").concat(trimmed.slice(0, 5));
4600
+ }
4601
+ function formatAssistantDisplayCell(value, column) {
4602
+ if (value === null || value === undefined || value === '') {
4603
+ return '';
4604
+ }
4605
+ if (Array.isArray(value)) {
4606
+ return value.map(function (item) { return formatAssistantDisplayCell(item, column); }).filter(Boolean).join(', ');
4607
+ }
4608
+ var columnKey = String(column || '').toLowerCase();
4609
+ if (isAssistantDateColumn(columnKey) && isAssistantLikelyDateValue(value)) {
4610
+ return formatAssistantDateValue(value);
4611
+ }
4612
+ var numericValue = resolveAssistantNumericValue(value);
4613
+ if (numericValue !== null) {
4614
+ if (isAssistantPercentColumn(columnKey)) {
4615
+ var percentValue = numericValue > 1 && numericValue <= 100 ? numericValue / 100 : numericValue;
4616
+ try {
4617
+ return getAssistantPercentFormatter().format(percentValue);
4618
+ }
4619
+ catch (_a) {
4620
+ return "".concat((0, common_1.round)(percentValue * 100), "%");
4621
+ }
4622
+ }
4623
+ if (isAssistantCurrencyColumn(columnKey)) {
4624
+ try {
4625
+ return getAssistantCurrencyFormatter().format(numericValue);
4626
+ }
4627
+ catch (_b) {
4628
+ return "$".concat(numericValue.toFixed(2));
4629
+ }
4630
+ }
4631
+ try {
4632
+ return getAssistantNumberFormatter().format(numericValue);
4633
+ }
4634
+ catch (_c) {
4635
+ return String(numericValue);
4636
+ }
4637
+ }
4638
+ if (isAssistantLikelyDateValue(value) && isAssistantDateColumn(columnKey)) {
4639
+ return formatAssistantDateValue(value);
4640
+ }
4641
+ return String(value);
4642
+ }
4643
+ function formatDisplayTableMarkdown(display) {
4644
+ if (!display || !Array.isArray(display.columns) || !display.columns.length) {
4645
+ return '';
4646
+ }
4647
+ var header = "| ".concat(display.columns.join(' | '), " |");
4648
+ var separator = "| ".concat(display.columns.map(function () { return '---'; }).join(' | '), " |");
4649
+ var rows = (display.rows || []).map(function (row) {
4650
+ var cells = display.columns.map(function (column) {
4651
+ var rawValue = row === null || row === void 0 ? void 0 : row[column];
4652
+ var formatted = formatAssistantDisplayCell(rawValue, column);
4653
+ return escapeMarkdownCell(formatted);
4654
+ });
4655
+ return "| ".concat(cells.join(' | '), " |");
4656
+ });
4657
+ return __spreadArray([header, separator], __read(rows), false).join('\n').trim();
4658
+ }
4659
+ function stripAssistantMarkdownTables(value) {
4660
+ var raw = normalizeOptionalString(value);
4661
+ if (!raw) {
4662
+ return '';
4663
+ }
4664
+ var tablePattern = /(^|\n)\|[^\n]*\|\n\|[ \t:-|]+\|\n(?:\|[^\n]*\|\n?)*/g;
4665
+ var cleaned = raw.replace(tablePattern, '\n').trim();
4666
+ return cleaned;
4667
+ }
4668
+ function applyAssistantDisplayTableToResponse(value, display) {
4669
+ if (!display || !Array.isArray(display.rows) || !display.rows.length) {
4670
+ return value;
4671
+ }
4672
+ var table = formatDisplayTableMarkdown(display);
4673
+ if (!table) {
4674
+ return value;
4675
+ }
4676
+ var cleaned = stripAssistantMarkdownTables(value);
4677
+ if (!cleaned) {
4678
+ return table;
4679
+ }
4680
+ return "".concat(cleaned.trim(), "\n\n").concat(table).trim();
4681
+ }
4682
+ function escapeMarkdownCell(value) {
4683
+ var raw = value === null || value === undefined ? '' : String(value);
4684
+ return raw.replace(/\|/g, '\\|').replace(/\r?\n/g, ' ').trim();
4685
+ }
4686
+ function isEmptyDisplayValue(value) {
4687
+ if (value === null || value === undefined) {
4688
+ return true;
4689
+ }
4690
+ if (typeof value === 'string') {
4691
+ return !value.trim();
4692
+ }
4693
+ if (Array.isArray(value)) {
4694
+ return value.length === 0;
4695
+ }
4696
+ return false;
4697
+ }
4698
+ function isDisplayObjectLike(value) {
4699
+ if (value === null || value === undefined) {
4700
+ return false;
4701
+ }
4702
+ if (value instanceof Date) {
4703
+ return false;
4704
+ }
4705
+ if (isMongoObjectId(value)) {
4706
+ return false;
4707
+ }
4708
+ return typeof value === 'object';
4709
+ }
4710
+ function ensureAssistantReadAccess(context, permissionView, collection) {
4711
+ return __awaiter(this, void 0, void 0, function () {
4712
+ var idUser, user, isSuperAdmin, normalizedPermission, normalizedCollection;
4713
+ var _a;
4449
4714
  return __generator(this, function (_b) {
4450
4715
  switch (_b.label) {
4451
4716
  case 0:
@@ -4548,21 +4813,154 @@ function sanitizeAssistantProjection(projection) {
4548
4813
  }
4549
4814
  return projection;
4550
4815
  }
4551
- function normalizeAssistantAggregatePipeline(pipeline) {
4816
+ var AGG_MATCH_EXPR_OPERATORS = new Set(['$eq', '$ne', '$gt', '$gte', '$lt', '$lte']);
4817
+ function isMatchExpressionOperand(value) {
4818
+ if (typeof value === 'string') {
4819
+ return value.startsWith('$$');
4820
+ }
4821
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
4822
+ return false;
4823
+ }
4824
+ if (value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
4825
+ return false;
4826
+ }
4827
+ return Object.keys(value).some(function (key) { return key.startsWith('$'); });
4828
+ }
4829
+ function mergeMatchExpr(existing, clauses) {
4830
+ if (!clauses.length) {
4831
+ return existing;
4832
+ }
4833
+ if (!existing) {
4834
+ return clauses.length === 1 ? clauses[0] : { $and: clauses };
4835
+ }
4836
+ if (existing && typeof existing === 'object' && !Array.isArray(existing)) {
4837
+ var existingAnd = existing.$and;
4838
+ if (Array.isArray(existingAnd)) {
4839
+ return __assign(__assign({}, existing), { $and: __spreadArray(__spreadArray([], __read(existingAnd), false), __read(clauses), false) });
4840
+ }
4841
+ }
4842
+ return { $and: __spreadArray([existing], __read(clauses), false) };
4843
+ }
4844
+ function rewriteMatchExpressionsToExpr(match) {
4845
+ var rewriteValue = function (value) {
4846
+ if (Array.isArray(value)) {
4847
+ return value.map(function (entry) { return rewriteValue(entry); });
4848
+ }
4849
+ if (!value || typeof value !== 'object' || value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
4850
+ return value;
4851
+ }
4852
+ var result = {};
4853
+ var exprClauses = [];
4854
+ Object.keys(value).forEach(function (key) {
4855
+ var entry = value[key];
4856
+ if (key === '$expr') {
4857
+ result[key] = entry;
4858
+ return;
4859
+ }
4860
+ if (key.startsWith('$')) {
4861
+ result[key] = rewriteValue(entry);
4862
+ return;
4863
+ }
4864
+ if (entry && typeof entry === 'object' && !Array.isArray(entry) && !(entry instanceof Date) && !(entry instanceof RegExp) && !isMongoObjectId(entry)) {
4865
+ var nextEntry_1 = __assign({}, entry);
4866
+ var moved_1 = false;
4867
+ Object.keys(nextEntry_1).forEach(function (op) {
4868
+ var _a;
4869
+ if (!AGG_MATCH_EXPR_OPERATORS.has(op)) {
4870
+ return;
4871
+ }
4872
+ var operand = nextEntry_1[op];
4873
+ if (isMatchExpressionOperand(operand)) {
4874
+ exprClauses.push((_a = {}, _a[op] = ["$".concat(key), operand], _a));
4875
+ delete nextEntry_1[op];
4876
+ moved_1 = true;
4877
+ }
4878
+ });
4879
+ if (Object.keys(nextEntry_1).length) {
4880
+ result[key] = rewriteValue(nextEntry_1);
4881
+ }
4882
+ else if (!moved_1) {
4883
+ result[key] = entry;
4884
+ }
4885
+ return;
4886
+ }
4887
+ if (typeof entry === 'string' && entry.startsWith('$$')) {
4888
+ exprClauses.push({ $eq: ["$".concat(key), entry] });
4889
+ return;
4890
+ }
4891
+ result[key] = entry;
4892
+ });
4893
+ if (exprClauses.length) {
4894
+ result.$expr = mergeMatchExpr(result.$expr, exprClauses);
4895
+ }
4896
+ return result;
4897
+ };
4898
+ return rewriteValue(match);
4899
+ }
4900
+ function buildInvoiceStatusRegex(value) {
4901
+ var normalized = String(value || '').toLowerCase();
4902
+ if (!normalized) {
4903
+ return null;
4904
+ }
4905
+ var tokens = normalized.split(/[^a-z0-9]+/g).filter(Boolean);
4906
+ if (!tokens.includes('paid') || !tokens.includes('closed')) {
4907
+ return null;
4908
+ }
4909
+ return /paid|closed/i;
4910
+ }
4911
+ function normalizeInvoiceStatusMatch(match) {
4912
+ var rewriteValue = function (value) {
4913
+ if (Array.isArray(value)) {
4914
+ return value.map(function (entry) { return rewriteValue(entry); });
4915
+ }
4916
+ if (!value || typeof value !== 'object' || value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
4917
+ return value;
4918
+ }
4919
+ var result = {};
4920
+ Object.keys(value).forEach(function (key) {
4921
+ var entry = value[key];
4922
+ if (key.startsWith('$')) {
4923
+ result[key] = rewriteValue(entry);
4924
+ return;
4925
+ }
4926
+ var field = key.split('.').pop() || key;
4927
+ if (field === 'status' && typeof entry === 'string') {
4928
+ var regex = buildInvoiceStatusRegex(entry);
4929
+ if (regex) {
4930
+ result[key] = regex;
4931
+ return;
4932
+ }
4933
+ }
4934
+ if (entry && typeof entry === 'object') {
4935
+ result[key] = rewriteValue(entry);
4936
+ return;
4937
+ }
4938
+ result[key] = entry;
4939
+ });
4940
+ return result;
4941
+ };
4942
+ return rewriteValue(match);
4943
+ }
4944
+ function normalizeAssistantAggregatePipeline(pipeline, collection) {
4552
4945
  if (!Array.isArray(pipeline)) {
4553
4946
  return [];
4554
4947
  }
4948
+ var isInvoiceCollection = ['invoice', 'invoices', 'invoice-versions'].includes(String(collection || '').toLowerCase());
4555
4949
  return pipeline
4556
4950
  .filter(function (stage) { return stage && typeof stage === 'object' && !Array.isArray(stage); })
4557
4951
  .map(function (stage) {
4558
4952
  var next = __assign({}, stage);
4559
4953
  if (next.$match && typeof next.$match === 'object') {
4560
4954
  var rewritten = rewriteEmbeddedMatchObjects(next.$match);
4561
- next.$match = applyAssistantNameRegexToQuery(rewritten);
4955
+ var exprRewritten = rewriteMatchExpressionsToExpr(rewritten);
4956
+ var statusNormalized = isInvoiceCollection ? normalizeInvoiceStatusMatch(exprRewritten) : exprRewritten;
4957
+ next.$match = applyAssistantNameRegexToQuery(statusNormalized);
4562
4958
  }
4563
4959
  if (next.$geoNear && typeof next.$geoNear === 'object' && next.$geoNear.query) {
4564
4960
  var rewritten = rewriteEmbeddedMatchObjects(next.$geoNear.query);
4565
- next.$geoNear = __assign(__assign({}, next.$geoNear), { query: applyAssistantNameRegexToQuery(rewritten) });
4961
+ var exprRewritten = rewriteMatchExpressionsToExpr(rewritten);
4962
+ var statusNormalized = isInvoiceCollection ? normalizeInvoiceStatusMatch(exprRewritten) : exprRewritten;
4963
+ next.$geoNear = __assign(__assign({}, next.$geoNear), { query: applyAssistantNameRegexToQuery(statusNormalized) });
4566
4964
  }
4567
4965
  return next;
4568
4966
  });
@@ -4615,7 +5013,7 @@ function findAggregateLimit(pipeline) {
4615
5013
  }
4616
5014
  var limit = stage.$limit;
4617
5015
  if (typeof limit === 'number' && Number.isFinite(limit)) {
4618
- return limit;
5016
+ return { index: i, limit: limit };
4619
5017
  }
4620
5018
  }
4621
5019
  return null;
@@ -4628,12 +5026,13 @@ function applyAssistantAggregateLimit(pipeline, limit, maxLimit, defaultLimit) {
4628
5026
  ? Math.min(limit, maxLimit)
4629
5027
  : defaultLimit;
4630
5028
  var existingLimit = findAggregateLimit(normalizedPipeline);
4631
- if (existingLimit === null) {
5029
+ if (!existingLimit) {
4632
5030
  normalizedPipeline.push({ $limit: requestedLimit });
4633
5031
  return normalizedPipeline;
4634
5032
  }
4635
- if (existingLimit > maxLimit) {
4636
- normalizedPipeline.push({ $limit: maxLimit });
5033
+ if (existingLimit.limit > maxLimit) {
5034
+ var stage = normalizedPipeline[existingLimit.index];
5035
+ normalizedPipeline[existingLimit.index] = __assign(__assign({}, stage), { $limit: maxLimit });
4637
5036
  }
4638
5037
  return normalizedPipeline;
4639
5038
  }
@@ -4693,7 +5092,7 @@ function matchContainsField(value, field) {
4693
5092
  });
4694
5093
  }
4695
5094
  function resolveAggregateCompletionFallback(pipeline) {
4696
- var e_10, _a;
5095
+ var e_11, _a;
4697
5096
  if (!Array.isArray(pipeline)) {
4698
5097
  return null;
4699
5098
  }
@@ -4706,7 +5105,7 @@ function resolveAggregateCompletionFallback(pipeline) {
4706
5105
  }
4707
5106
  var addFields = stage.$addFields;
4708
5107
  try {
4709
- for (var _b = (e_10 = void 0, __values(Object.keys(addFields))), _c = _b.next(); !_c.done; _c = _b.next()) {
5108
+ for (var _b = (e_11 = void 0, __values(Object.keys(addFields))), _c = _b.next(); !_c.done; _c = _b.next()) {
4710
5109
  var key = _c.value;
4711
5110
  if (!isCompletionFieldName(key)) {
4712
5111
  continue;
@@ -4720,12 +5119,12 @@ function resolveAggregateCompletionFallback(pipeline) {
4720
5119
  }
4721
5120
  }
4722
5121
  }
4723
- catch (e_10_1) { e_10 = { error: e_10_1 }; }
5122
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
4724
5123
  finally {
4725
5124
  try {
4726
5125
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
4727
5126
  }
4728
- finally { if (e_10) throw e_10.error; }
5127
+ finally { if (e_11) throw e_11.error; }
4729
5128
  }
4730
5129
  if (candidateField) {
4731
5130
  break;
@@ -4881,7 +5280,7 @@ function buildCompletionFallbackSources(field) {
4881
5280
  ]);
4882
5281
  }
4883
5282
  function resolveAggregateCompletionExprFallback(pipeline) {
4884
- var e_11, _a;
5283
+ var e_12, _a;
4885
5284
  if (!Array.isArray(pipeline)) {
4886
5285
  return null;
4887
5286
  }
@@ -4901,7 +5300,7 @@ function resolveAggregateCompletionExprFallback(pipeline) {
4901
5300
  }
4902
5301
  if (!candidateField) {
4903
5302
  try {
4904
- for (var _b = (e_11 = void 0, __values(Object.keys(matchStage))), _c = _b.next(); !_c.done; _c = _b.next()) {
5303
+ for (var _b = (e_12 = void 0, __values(Object.keys(matchStage))), _c = _b.next(); !_c.done; _c = _b.next()) {
4905
5304
  var key = _c.value;
4906
5305
  if (key.startsWith('$')) {
4907
5306
  continue;
@@ -4916,12 +5315,12 @@ function resolveAggregateCompletionExprFallback(pipeline) {
4916
5315
  }
4917
5316
  }
4918
5317
  }
4919
- catch (e_11_1) { e_11 = { error: e_11_1 }; }
5318
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
4920
5319
  finally {
4921
5320
  try {
4922
5321
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
4923
5322
  }
4924
- finally { if (e_11) throw e_11.error; }
5323
+ finally { if (e_12) throw e_12.error; }
4925
5324
  }
4926
5325
  }
4927
5326
  if (!candidateField) {
@@ -5091,7 +5490,7 @@ function isRegexMatchCondition(value) {
5091
5490
  return false;
5092
5491
  }
5093
5492
  function findRegexMatchInMatchObject(match, prefix) {
5094
- var e_12, _a, e_13, _b;
5493
+ var e_13, _a, e_14, _b;
5095
5494
  if (prefix === void 0) { prefix = ''; }
5096
5495
  if (Array.isArray(match)) {
5097
5496
  try {
@@ -5103,12 +5502,12 @@ function findRegexMatchInMatchObject(match, prefix) {
5103
5502
  }
5104
5503
  }
5105
5504
  }
5106
- catch (e_12_1) { e_12 = { error: e_12_1 }; }
5505
+ catch (e_13_1) { e_13 = { error: e_13_1 }; }
5107
5506
  finally {
5108
5507
  try {
5109
5508
  if (match_1_1 && !match_1_1.done && (_a = match_1.return)) _a.call(match_1);
5110
5509
  }
5111
- finally { if (e_12) throw e_12.error; }
5510
+ finally { if (e_13) throw e_13.error; }
5112
5511
  }
5113
5512
  return null;
5114
5513
  }
@@ -5139,12 +5538,12 @@ function findRegexMatchInMatchObject(match, prefix) {
5139
5538
  }
5140
5539
  }
5141
5540
  }
5142
- catch (e_13_1) { e_13 = { error: e_13_1 }; }
5541
+ catch (e_14_1) { e_14 = { error: e_14_1 }; }
5143
5542
  finally {
5144
5543
  try {
5145
5544
  if (keys_2_1 && !keys_2_1.done && (_b = keys_2.return)) _b.call(keys_2);
5146
5545
  }
5147
- finally { if (e_13) throw e_13.error; }
5546
+ finally { if (e_14) throw e_14.error; }
5148
5547
  }
5149
5548
  return null;
5150
5549
  }
@@ -5299,39 +5698,45 @@ function isEmptyMatchValue(value) {
5299
5698
  return false;
5300
5699
  }
5301
5700
  function stripMatchField(match, field) {
5302
- if (Array.isArray(match)) {
5303
- var strippedArray = match
5304
- .map(function (entry) { return stripMatchField(entry, field); })
5305
- .filter(function (entry) { return !isEmptyMatchValue(entry); });
5306
- return strippedArray;
5307
- }
5308
- if (!match || typeof match !== 'object') {
5309
- return match;
5310
- }
5311
- var result = {};
5312
- Object.keys(match).forEach(function (key) {
5313
- if (key === field) {
5314
- return;
5701
+ var hasPath = field.includes('.');
5702
+ var stripValue = function (value, prefix) {
5703
+ if (Array.isArray(value)) {
5704
+ var strippedArray = value
5705
+ .map(function (entry) { return stripValue(entry, prefix); })
5706
+ .filter(function (entry) { return !isEmptyMatchValue(entry); });
5707
+ return strippedArray;
5315
5708
  }
5316
- var value = match[key];
5317
- if (key.startsWith('$')) {
5318
- var stripped = stripMatchField(value, field);
5319
- if (isEmptyMatchValue(stripped) && (key === '$and' || key === '$or')) {
5709
+ if (!value || typeof value !== 'object') {
5710
+ return value;
5711
+ }
5712
+ var result = {};
5713
+ Object.keys(value).forEach(function (key) {
5714
+ var entry = value[key];
5715
+ var currentPath = prefix ? "".concat(prefix, ".").concat(key) : key;
5716
+ var matches = hasPath ? currentPath === field : key === field;
5717
+ if (matches) {
5320
5718
  return;
5321
5719
  }
5322
- result[key] = stripped;
5323
- return;
5324
- }
5325
- if (value && typeof value === 'object') {
5326
- var stripped = stripMatchField(value, field);
5327
- if (!isEmptyMatchValue(stripped)) {
5720
+ if (key.startsWith('$')) {
5721
+ var stripped = stripValue(entry, prefix);
5722
+ if (isEmptyMatchValue(stripped) && (key === '$and' || key === '$or')) {
5723
+ return;
5724
+ }
5328
5725
  result[key] = stripped;
5726
+ return;
5329
5727
  }
5330
- return;
5331
- }
5332
- result[key] = value;
5333
- });
5334
- return result;
5728
+ if (entry && typeof entry === 'object') {
5729
+ var stripped = stripValue(entry, currentPath);
5730
+ if (!isEmptyMatchValue(stripped)) {
5731
+ result[key] = stripped;
5732
+ }
5733
+ return;
5734
+ }
5735
+ result[key] = entry;
5736
+ });
5737
+ return result;
5738
+ };
5739
+ return stripValue(match, '');
5335
5740
  }
5336
5741
  function collectMatchFieldsByCondition(match, predicate, prefix) {
5337
5742
  if (prefix === void 0) { prefix = ''; }
@@ -5362,7 +5767,7 @@ function collectMatchFieldsByCondition(match, predicate, prefix) {
5362
5767
  return results;
5363
5768
  }
5364
5769
  function findMatchConditionForField(match, targetField, prefix) {
5365
- var e_14, _a, e_15, _b;
5770
+ var e_15, _a, e_16, _b;
5366
5771
  if (prefix === void 0) { prefix = ''; }
5367
5772
  if (!match || typeof match !== 'object') {
5368
5773
  return undefined;
@@ -5377,12 +5782,12 @@ function findMatchConditionForField(match, targetField, prefix) {
5377
5782
  }
5378
5783
  }
5379
5784
  }
5380
- catch (e_14_1) { e_14 = { error: e_14_1 }; }
5785
+ catch (e_15_1) { e_15 = { error: e_15_1 }; }
5381
5786
  finally {
5382
5787
  try {
5383
5788
  if (match_2_1 && !match_2_1.done && (_a = match_2.return)) _a.call(match_2);
5384
5789
  }
5385
- finally { if (e_14) throw e_14.error; }
5790
+ finally { if (e_15) throw e_15.error; }
5386
5791
  }
5387
5792
  return undefined;
5388
5793
  }
@@ -5409,12 +5814,12 @@ function findMatchConditionForField(match, targetField, prefix) {
5409
5814
  }
5410
5815
  }
5411
5816
  }
5412
- catch (e_15_1) { e_15 = { error: e_15_1 }; }
5817
+ catch (e_16_1) { e_16 = { error: e_16_1 }; }
5413
5818
  finally {
5414
5819
  try {
5415
5820
  if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
5416
5821
  }
5417
- finally { if (e_15) throw e_15.error; }
5822
+ finally { if (e_16) throw e_16.error; }
5418
5823
  }
5419
5824
  return undefined;
5420
5825
  }
@@ -5457,7 +5862,7 @@ function detectIdLikeValue(value) {
5457
5862
  return false;
5458
5863
  }
5459
5864
  function detectChemicalIdFromProbe(probeDocs, fields) {
5460
- var e_16, _a, e_17, _b;
5865
+ var e_17, _a, e_18, _b;
5461
5866
  if (!Array.isArray(probeDocs) || !probeDocs.length) {
5462
5867
  return false;
5463
5868
  }
@@ -5469,7 +5874,7 @@ function detectChemicalIdFromProbe(probeDocs, fields) {
5469
5874
  for (var probeDocs_1 = __values(probeDocs), probeDocs_1_1 = probeDocs_1.next(); !probeDocs_1_1.done; probeDocs_1_1 = probeDocs_1.next()) {
5470
5875
  var doc = probeDocs_1_1.value;
5471
5876
  try {
5472
- for (var targets_1 = (e_17 = void 0, __values(targets)), targets_1_1 = targets_1.next(); !targets_1_1.done; targets_1_1 = targets_1.next()) {
5877
+ for (var targets_1 = (e_18 = void 0, __values(targets)), targets_1_1 = targets_1.next(); !targets_1_1.done; targets_1_1 = targets_1.next()) {
5473
5878
  var field = targets_1_1.value;
5474
5879
  var value = getValueAtPath(doc, field);
5475
5880
  if (Array.isArray(value)) {
@@ -5482,21 +5887,21 @@ function detectChemicalIdFromProbe(probeDocs, fields) {
5482
5887
  }
5483
5888
  }
5484
5889
  }
5485
- catch (e_17_1) { e_17 = { error: e_17_1 }; }
5890
+ catch (e_18_1) { e_18 = { error: e_18_1 }; }
5486
5891
  finally {
5487
5892
  try {
5488
5893
  if (targets_1_1 && !targets_1_1.done && (_b = targets_1.return)) _b.call(targets_1);
5489
5894
  }
5490
- finally { if (e_17) throw e_17.error; }
5895
+ finally { if (e_18) throw e_18.error; }
5491
5896
  }
5492
5897
  }
5493
5898
  }
5494
- catch (e_16_1) { e_16 = { error: e_16_1 }; }
5899
+ catch (e_17_1) { e_17 = { error: e_17_1 }; }
5495
5900
  finally {
5496
5901
  try {
5497
5902
  if (probeDocs_1_1 && !probeDocs_1_1.done && (_a = probeDocs_1.return)) _a.call(probeDocs_1);
5498
5903
  }
5499
- finally { if (e_16) throw e_16.error; }
5904
+ finally { if (e_17) throw e_17.error; }
5500
5905
  }
5501
5906
  return false;
5502
5907
  }
@@ -5646,9 +6051,9 @@ function isIdLookupCondition(value) {
5646
6051
  }
5647
6052
  function collectIdFieldConditions(match) {
5648
6053
  var results = [];
5649
- var visit = function (value) {
6054
+ var visit = function (value, prefix) {
5650
6055
  if (Array.isArray(value)) {
5651
- value.forEach(function (entry) { return visit(entry); });
6056
+ value.forEach(function (entry) { return visit(entry, prefix); });
5652
6057
  return;
5653
6058
  }
5654
6059
  if (!value || typeof value !== 'object') {
@@ -5657,19 +6062,20 @@ function collectIdFieldConditions(match) {
5657
6062
  Object.keys(value).forEach(function (key) {
5658
6063
  var entry = value[key];
5659
6064
  if (key.startsWith('$')) {
5660
- visit(entry);
6065
+ visit(entry, prefix);
5661
6066
  return;
5662
6067
  }
6068
+ var currentPath = prefix ? "".concat(prefix, ".").concat(key) : key;
5663
6069
  if (isAssistantIdField(key) && isIdLookupCondition(entry)) {
5664
- results.push({ field: key, condition: entry });
6070
+ results.push({ field: currentPath, condition: entry });
5665
6071
  return;
5666
6072
  }
5667
6073
  if (entry && typeof entry === 'object') {
5668
- visit(entry);
6074
+ visit(entry, currentPath);
5669
6075
  }
5670
6076
  });
5671
6077
  };
5672
- visit(match);
6078
+ visit(match, '');
5673
6079
  return results;
5674
6080
  }
5675
6081
  function resolveLocalNameFieldFromDocs(docs, baseToken) {
@@ -5716,8 +6122,8 @@ function buildChemicalIdFieldCandidates(field) {
5716
6122
  }
5717
6123
  function applyChemicalNameLookupFallbackToQuery(params) {
5718
6124
  return __awaiter(this, void 0, void 0, function () {
5719
- var query, db, dbName, idClient, idCustomer, isSuperAdmin, probeDocs, chemicalFields, targetField, condition, regex, sampleDocs, collectionNames, candidates, _loop_6, candidates_2, candidates_2_1, candidate, state_4, e_18_1;
5720
- var e_18, _a;
6125
+ var query, db, dbName, idClient, idCustomer, isSuperAdmin, probeDocs, chemicalFields, targetField, condition, regex, sampleDocs, collectionNames, candidates, _loop_6, candidates_2, candidates_2_1, candidate, state_4, e_19_1;
6126
+ var e_19, _a;
5721
6127
  var _b;
5722
6128
  return __generator(this, function (_c) {
5723
6129
  switch (_c.label) {
@@ -5830,14 +6236,14 @@ function applyChemicalNameLookupFallbackToQuery(params) {
5830
6236
  return [3 /*break*/, 3];
5831
6237
  case 6: return [3 /*break*/, 9];
5832
6238
  case 7:
5833
- e_18_1 = _c.sent();
5834
- e_18 = { error: e_18_1 };
6239
+ e_19_1 = _c.sent();
6240
+ e_19 = { error: e_19_1 };
5835
6241
  return [3 /*break*/, 9];
5836
6242
  case 8:
5837
6243
  try {
5838
6244
  if (candidates_2_1 && !candidates_2_1.done && (_a = candidates_2.return)) _a.call(candidates_2);
5839
6245
  }
5840
- finally { if (e_18) throw e_18.error; }
6246
+ finally { if (e_19) throw e_19.error; }
5841
6247
  return [7 /*endfinally*/];
5842
6248
  case 9: return [2 /*return*/, null];
5843
6249
  }
@@ -5931,8 +6337,8 @@ function lookupIdsForNameMatch(params) {
5931
6337
  }
5932
6338
  function applyIdLookupFallbackToQuery(params) {
5933
6339
  return __awaiter(this, void 0, void 0, function () {
5934
- 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_19_1, e_20_1;
5935
- var e_20, _c, e_19, _d;
6340
+ 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_20_1, e_21_1;
6341
+ var e_21, _c, e_20, _d;
5936
6342
  var _e;
5937
6343
  return __generator(this, function (_f) {
5938
6344
  switch (_f.label) {
@@ -6002,7 +6408,7 @@ function applyIdLookupFallbackToQuery(params) {
6002
6408
  _f.label = 5;
6003
6409
  case 5:
6004
6410
  _f.trys.push([5, 14, 15, 16]);
6005
- candidates_3 = (e_19 = void 0, __values(candidates)), candidates_3_1 = candidates_3.next();
6411
+ candidates_3 = (e_20 = void 0, __values(candidates)), candidates_3_1 = candidates_3.next();
6006
6412
  _f.label = 6;
6007
6413
  case 6:
6008
6414
  if (!!candidates_3_1.done) return [3 /*break*/, 13];
@@ -6069,28 +6475,28 @@ function applyIdLookupFallbackToQuery(params) {
6069
6475
  return [3 /*break*/, 6];
6070
6476
  case 13: return [3 /*break*/, 16];
6071
6477
  case 14:
6072
- e_19_1 = _f.sent();
6073
- e_19 = { error: e_19_1 };
6478
+ e_20_1 = _f.sent();
6479
+ e_20 = { error: e_20_1 };
6074
6480
  return [3 /*break*/, 16];
6075
6481
  case 15:
6076
6482
  try {
6077
6483
  if (candidates_3_1 && !candidates_3_1.done && (_d = candidates_3.return)) _d.call(candidates_3);
6078
6484
  }
6079
- finally { if (e_19) throw e_19.error; }
6485
+ finally { if (e_20) throw e_20.error; }
6080
6486
  return [7 /*endfinally*/];
6081
6487
  case 16:
6082
6488
  conditions_1_1 = conditions_1.next();
6083
6489
  return [3 /*break*/, 4];
6084
6490
  case 17: return [3 /*break*/, 20];
6085
6491
  case 18:
6086
- e_20_1 = _f.sent();
6087
- e_20 = { error: e_20_1 };
6492
+ e_21_1 = _f.sent();
6493
+ e_21 = { error: e_21_1 };
6088
6494
  return [3 /*break*/, 20];
6089
6495
  case 19:
6090
6496
  try {
6091
6497
  if (conditions_1_1 && !conditions_1_1.done && (_c = conditions_1.return)) _c.call(conditions_1);
6092
6498
  }
6093
- finally { if (e_20) throw e_20.error; }
6499
+ finally { if (e_21) throw e_21.error; }
6094
6500
  return [7 /*endfinally*/];
6095
6501
  case 20: return [2 /*return*/, null];
6096
6502
  }
@@ -6184,8 +6590,12 @@ function replaceAggregateDateField(pipeline, fromField, toField) {
6184
6590
  return next_2;
6185
6591
  }
6186
6592
  if (typeof value === 'string') {
6187
- if (value.startsWith("$".concat(fromField))) {
6188
- return "$".concat(toField).concat(value.slice(fromField.length + 1));
6593
+ var fromRef = "$".concat(fromField);
6594
+ if (value === fromRef) {
6595
+ return "$".concat(toField);
6596
+ }
6597
+ if (value.startsWith("".concat(fromRef, "."))) {
6598
+ return "$".concat(toField).concat(value.slice(fromRef.length));
6189
6599
  }
6190
6600
  return value;
6191
6601
  }
@@ -6237,8 +6647,17 @@ function buildTokenizedRegex(value) {
6237
6647
  var tokenPattern = tokens.map(function (token) { return escapeRegexValue(token); }).join('[\\s\\-_]*.*');
6238
6648
  return new RegExp(tokenPattern, 'i');
6239
6649
  }
6240
- function applyAssistantNameRegexToQuery(query) {
6650
+ function applyAssistantNameRegexToQuery(query, fieldContext) {
6241
6651
  if (Array.isArray(query)) {
6652
+ if (fieldContext && shouldApplyAssistantNameRegex(fieldContext)) {
6653
+ return query.map(function (entry) {
6654
+ if (typeof entry === 'string') {
6655
+ var trimmed = entry.trim();
6656
+ return trimmed ? buildTokenizedRegex(trimmed) : entry;
6657
+ }
6658
+ return applyAssistantNameRegexToQuery(entry, fieldContext);
6659
+ });
6660
+ }
6242
6661
  return query.map(function (entry) { return applyAssistantNameRegexToQuery(entry); });
6243
6662
  }
6244
6663
  if (!query || typeof query !== 'object' || query instanceof Date || query instanceof RegExp || isMongoObjectId(query)) {
@@ -6248,7 +6667,7 @@ function applyAssistantNameRegexToQuery(query) {
6248
6667
  Object.keys(query).forEach(function (key) {
6249
6668
  var value = query[key];
6250
6669
  if (key.startsWith('$')) {
6251
- result[key] = applyAssistantNameRegexToQuery(value);
6670
+ result[key] = applyAssistantNameRegexToQuery(value, fieldContext);
6252
6671
  return;
6253
6672
  }
6254
6673
  if (typeof value === 'string' && shouldApplyAssistantNameRegex(key)) {
@@ -6257,7 +6676,7 @@ function applyAssistantNameRegexToQuery(query) {
6257
6676
  return;
6258
6677
  }
6259
6678
  if (value && typeof value === 'object') {
6260
- result[key] = applyAssistantNameRegexToQuery(value);
6679
+ result[key] = applyAssistantNameRegexToQuery(value, key);
6261
6680
  return;
6262
6681
  }
6263
6682
  result[key] = value;
@@ -6280,13 +6699,13 @@ function hasOperatorKeys(value) {
6280
6699
  return Object.keys(value).some(function (key) { return key.startsWith('$'); });
6281
6700
  }
6282
6701
  function rewriteEmbeddedMatchObjects(query) {
6283
- var rewriteValue = function (value, allowArrayRewrite, inOperator) {
6284
- if (inOperator === void 0) { inOperator = false; }
6702
+ var isLogicalOperatorKey = function (key) { return key === '$or' || key === '$and' || key === '$nor'; };
6703
+ var rewriteValue = function (value, allowArrayRewrite, context) {
6285
6704
  if (Array.isArray(value)) {
6286
6705
  if (!allowArrayRewrite) {
6287
6706
  return value;
6288
6707
  }
6289
- return value.map(function (entry) { return rewriteValue(entry, true, inOperator); });
6708
+ return value.map(function (entry) { return rewriteValue(entry, true, context); });
6290
6709
  }
6291
6710
  if (!value || typeof value !== 'object' || value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
6292
6711
  return value;
@@ -6295,38 +6714,39 @@ function rewriteEmbeddedMatchObjects(query) {
6295
6714
  Object.keys(value).forEach(function (key) {
6296
6715
  var entry = value[key];
6297
6716
  if (key.startsWith('$')) {
6298
- result[key] = rewriteValue(entry, true, true);
6717
+ var nextContext = isLogicalOperatorKey(key) ? 'logical' : 'fieldOperator';
6718
+ result[key] = rewriteValue(entry, true, nextContext);
6299
6719
  return;
6300
6720
  }
6301
- if (!inOperator && isPlainMatchObject(entry) && !Array.isArray(entry) && !hasOperatorKeys(entry)) {
6302
- var flattened = flattenMatchObject(entry, key, inOperator);
6721
+ if (context !== 'fieldOperator' && isPlainMatchObject(entry) && !Array.isArray(entry) && !hasOperatorKeys(entry)) {
6722
+ var flattened = flattenMatchObject(entry, key, context);
6303
6723
  Object.assign(result, flattened);
6304
6724
  return;
6305
6725
  }
6306
6726
  if (isPlainMatchObject(entry) && !Array.isArray(entry)) {
6307
- result[key] = rewriteValue(entry, true, inOperator);
6727
+ result[key] = rewriteValue(entry, true, context);
6308
6728
  return;
6309
6729
  }
6310
6730
  if (Array.isArray(entry)) {
6311
- result[key] = allowArrayRewrite ? entry.map(function (item) { return rewriteValue(item, true, inOperator); }) : entry;
6731
+ result[key] = allowArrayRewrite ? entry.map(function (item) { return rewriteValue(item, true, context); }) : entry;
6312
6732
  return;
6313
6733
  }
6314
6734
  result[key] = entry;
6315
6735
  });
6316
6736
  return result;
6317
6737
  };
6318
- var flattenMatchObject = function (value, prefix, inOperator) {
6738
+ var flattenMatchObject = function (value, prefix, context) {
6319
6739
  var result = {};
6320
6740
  Object.keys(value || {}).forEach(function (key) {
6321
6741
  var entry = value[key];
6322
6742
  var currentPath = "".concat(prefix, ".").concat(key);
6323
6743
  if (isPlainMatchObject(entry) && !Array.isArray(entry) && !hasOperatorKeys(entry)) {
6324
- var flattened = flattenMatchObject(entry, currentPath, inOperator);
6744
+ var flattened = flattenMatchObject(entry, currentPath, context);
6325
6745
  Object.assign(result, flattened);
6326
6746
  return;
6327
6747
  }
6328
6748
  if (isPlainMatchObject(entry) && !Array.isArray(entry)) {
6329
- result[currentPath] = rewriteValue(entry, true, inOperator);
6749
+ result[currentPath] = rewriteValue(entry, true, context);
6330
6750
  return;
6331
6751
  }
6332
6752
  if (Array.isArray(entry)) {
@@ -6337,7 +6757,7 @@ function rewriteEmbeddedMatchObjects(query) {
6337
6757
  });
6338
6758
  return result;
6339
6759
  };
6340
- return rewriteValue(query, true);
6760
+ return rewriteValue(query, true, 'root');
6341
6761
  }
6342
6762
  function buildRegexFromCondition(condition) {
6343
6763
  if (!condition) {
@@ -6559,6 +6979,59 @@ function resolveCollectionHintsFromTokens(tokens, collectionNames, max) {
6559
6979
  .slice(0, Math.max(max, 0))
6560
6980
  .map(function (entry) { return entry.name; });
6561
6981
  }
6982
+ function mergeAssistantHintValues() {
6983
+ var groups = [];
6984
+ for (var _i = 0; _i < arguments.length; _i++) {
6985
+ groups[_i] = arguments[_i];
6986
+ }
6987
+ var result = [];
6988
+ var seen = new Set();
6989
+ groups.forEach(function (group) {
6990
+ if (!Array.isArray(group)) {
6991
+ return;
6992
+ }
6993
+ group.forEach(function (value) {
6994
+ var normalized = normalizeOptionalString(value);
6995
+ if (!normalized || seen.has(normalized)) {
6996
+ return;
6997
+ }
6998
+ seen.add(normalized);
6999
+ result.push(normalized);
7000
+ });
7001
+ });
7002
+ return result;
7003
+ }
7004
+ function resolveCollectionHintsFromRoute(route, collectionNames) {
7005
+ var normalizedRoute = normalizeOptionalString(route);
7006
+ if (!normalizedRoute || !collectionNames.length) {
7007
+ return [];
7008
+ }
7009
+ var parts = normalizedRoute.toLowerCase().split(/[/?#]+/g).filter(Boolean);
7010
+ var hints = [];
7011
+ parts.forEach(function (part) {
7012
+ var cleaned = part.replace(/[^a-z0-9_-]/g, '');
7013
+ if (!cleaned) {
7014
+ return;
7015
+ }
7016
+ var base = cleaned.replace(/^-+|-+$/g, '');
7017
+ if (!base) {
7018
+ return;
7019
+ }
7020
+ if (collectionNames.includes(base)) {
7021
+ hints.push(base);
7022
+ }
7023
+ if (!base.endsWith('s') && collectionNames.includes("".concat(base, "s"))) {
7024
+ hints.push("".concat(base, "s"));
7025
+ }
7026
+ if (collectionNames.includes("report-".concat(base))) {
7027
+ hints.push("report-".concat(base));
7028
+ }
7029
+ if (!base.endsWith('s') && collectionNames.includes("report-".concat(base, "s"))) {
7030
+ hints.push("report-".concat(base, "s"));
7031
+ }
7032
+ });
7033
+ return mergeAssistantHintValues(hints);
7034
+ }
6562
7035
  function buildCollectionRankingDebugFromTokens(tokens, collectionNames, max) {
6563
7036
  if (max === void 0) { max = 8; }
6564
7037
  var requestedKey = normalizeCollectionKey(tokens.join('-'));
@@ -6819,7 +7292,7 @@ function resolveAssistantCollectionName(db, dbName, requested) {
6819
7292
  });
6820
7293
  }
6821
7294
  function findQueryDateField(query) {
6822
- var e_21, _a, e_22, _b;
7295
+ var e_22, _a, e_23, _b;
6823
7296
  if (!query || typeof query !== 'object') {
6824
7297
  return null;
6825
7298
  }
@@ -6833,12 +7306,12 @@ function findQueryDateField(query) {
6833
7306
  }
6834
7307
  }
6835
7308
  }
6836
- catch (e_21_1) { e_21 = { error: e_21_1 }; }
7309
+ catch (e_22_1) { e_22 = { error: e_22_1 }; }
6837
7310
  finally {
6838
7311
  try {
6839
7312
  if (query_1_1 && !query_1_1.done && (_a = query_1.return)) _a.call(query_1);
6840
7313
  }
6841
- finally { if (e_21) throw e_21.error; }
7314
+ finally { if (e_22) throw e_22.error; }
6842
7315
  }
6843
7316
  return null;
6844
7317
  }
@@ -6857,12 +7330,12 @@ function findQueryDateField(query) {
6857
7330
  }
6858
7331
  }
6859
7332
  }
6860
- catch (e_22_1) { e_22 = { error: e_22_1 }; }
7333
+ catch (e_23_1) { e_23 = { error: e_23_1 }; }
6861
7334
  finally {
6862
7335
  try {
6863
7336
  if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
6864
7337
  }
6865
- finally { if (e_22) throw e_22.error; }
7338
+ finally { if (e_23) throw e_23.error; }
6866
7339
  }
6867
7340
  return null;
6868
7341
  }
@@ -7084,7 +7557,7 @@ function resolveQueryDateFieldFallback(query) {
7084
7557
  return { from: dateField, to: fallback };
7085
7558
  }
7086
7559
  function containsForbiddenMongoOperators(value) {
7087
- var e_23, _a;
7560
+ var e_24, _a;
7088
7561
  if (!value || typeof value !== 'object') {
7089
7562
  return false;
7090
7563
  }
@@ -7103,12 +7576,12 @@ function containsForbiddenMongoOperators(value) {
7103
7576
  }
7104
7577
  }
7105
7578
  }
7106
- catch (e_23_1) { e_23 = { error: e_23_1 }; }
7579
+ catch (e_24_1) { e_24 = { error: e_24_1 }; }
7107
7580
  finally {
7108
7581
  try {
7109
7582
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
7110
7583
  }
7111
- finally { if (e_23) throw e_23.error; }
7584
+ finally { if (e_24) throw e_24.error; }
7112
7585
  }
7113
7586
  return false;
7114
7587
  }
@@ -7399,8 +7872,8 @@ function applyCodexStreamStatusHandler(runOptions, streamStatusHandler) {
7399
7872
  }
7400
7873
  function waitForCodexWorkerMessage(worker, streamStatusHandler) {
7401
7874
  return __awaiter(this, void 0, void 0, function () {
7402
- var _a, _b, _c, _d, message, payload, status_1, e_24_1;
7403
- var _e, e_24, _f, _g;
7875
+ var _a, _b, _c, _d, message, payload, status_1, e_25_1;
7876
+ var _e, e_25, _f, _g;
7404
7877
  return __generator(this, function (_h) {
7405
7878
  switch (_h.label) {
7406
7879
  case 0:
@@ -7427,8 +7900,8 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
7427
7900
  return [3 /*break*/, 1];
7428
7901
  case 4: return [3 /*break*/, 11];
7429
7902
  case 5:
7430
- e_24_1 = _h.sent();
7431
- e_24 = { error: e_24_1 };
7903
+ e_25_1 = _h.sent();
7904
+ e_25 = { error: e_25_1 };
7432
7905
  return [3 /*break*/, 11];
7433
7906
  case 6:
7434
7907
  _h.trys.push([6, , 9, 10]);
@@ -7439,7 +7912,7 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
7439
7912
  _h.label = 8;
7440
7913
  case 8: return [3 /*break*/, 10];
7441
7914
  case 9:
7442
- if (e_24) throw e_24.error;
7915
+ if (e_25) throw e_25.error;
7443
7916
  return [7 /*endfinally*/];
7444
7917
  case 10: return [7 /*endfinally*/];
7445
7918
  case 11: throw new CodexWorkerBootstrapError('Codex worker exited before completing.');
@@ -7682,31 +8155,164 @@ function pathExists(target) {
7682
8155
  });
7683
8156
  });
7684
8157
  }
7685
- function resolveAssistantWorkspaceRoot() {
8158
+ function directoryExists(target) {
7686
8159
  return __awaiter(this, void 0, void 0, function () {
7687
- var config, configured, candidate, stat, _a;
8160
+ var stat, _a;
7688
8161
  return __generator(this, function (_b) {
7689
8162
  switch (_b.label) {
8163
+ case 0:
8164
+ _b.trys.push([0, 2, , 3]);
8165
+ return [4 /*yield*/, fs_1.promises.stat(target)];
8166
+ case 1:
8167
+ stat = _b.sent();
8168
+ return [2 /*return*/, stat.isDirectory()];
8169
+ case 2:
8170
+ _a = _b.sent();
8171
+ return [2 /*return*/, false];
8172
+ case 3: return [2 /*return*/];
8173
+ }
8174
+ });
8175
+ });
8176
+ }
8177
+ function isAssistantPathUnderRoot(target, root) {
8178
+ if (!target || !root) {
8179
+ return false;
8180
+ }
8181
+ var relative = path.relative(root, target);
8182
+ if (!relative) {
8183
+ return true;
8184
+ }
8185
+ return !relative.startsWith('..') && !path.isAbsolute(relative);
8186
+ }
8187
+ function isAssistantProjectRoot(candidate) {
8188
+ return __awaiter(this, void 0, void 0, function () {
8189
+ var serverPath, angularPath, _a, hasServer, hasPackage;
8190
+ return __generator(this, function (_b) {
8191
+ switch (_b.label) {
8192
+ case 0:
8193
+ if (!candidate) {
8194
+ return [2 /*return*/, false];
8195
+ }
8196
+ return [4 /*yield*/, directoryExists(candidate)];
8197
+ case 1:
8198
+ if (!(_b.sent())) {
8199
+ return [2 /*return*/, false];
8200
+ }
8201
+ serverPath = path.join(candidate, 'server');
8202
+ angularPath = path.join(candidate, 'angular');
8203
+ return [4 /*yield*/, directoryExists(serverPath)];
8204
+ case 2:
8205
+ _a = (_b.sent());
8206
+ if (!_a) return [3 /*break*/, 4];
8207
+ return [4 /*yield*/, directoryExists(angularPath)];
8208
+ case 3:
8209
+ _a = (_b.sent());
8210
+ _b.label = 4;
8211
+ case 4:
8212
+ if (_a) {
8213
+ return [2 /*return*/, true];
8214
+ }
8215
+ return [4 /*yield*/, directoryExists(serverPath)];
8216
+ case 5:
8217
+ hasServer = _b.sent();
8218
+ return [4 /*yield*/, pathExists(path.join(candidate, 'package.json'))];
8219
+ case 6:
8220
+ hasPackage = _b.sent();
8221
+ return [2 /*return*/, hasServer && hasPackage];
8222
+ }
8223
+ });
8224
+ });
8225
+ }
8226
+ function resolveAssistantProjectRoot(clientDir) {
8227
+ return __awaiter(this, void 0, void 0, function () {
8228
+ var normalized, resolved, root, parts, i, candidate;
8229
+ return __generator(this, function (_a) {
8230
+ switch (_a.label) {
8231
+ case 0:
8232
+ normalized = normalizeOptionalString(clientDir);
8233
+ if (!normalized) {
8234
+ return [2 /*return*/, ''];
8235
+ }
8236
+ resolved = path.resolve(normalized);
8237
+ root = path.parse(resolved).root || path.sep;
8238
+ parts = resolved.slice(root.length).split(path.sep).filter(Boolean);
8239
+ if (!parts.length) {
8240
+ return [2 /*return*/, ''];
8241
+ }
8242
+ i = parts.length;
8243
+ _a.label = 1;
8244
+ case 1:
8245
+ if (!(i >= 1)) return [3 /*break*/, 4];
8246
+ candidate = path.join.apply(path, __spreadArray([root], __read(parts.slice(0, i)), false));
8247
+ return [4 /*yield*/, isAssistantProjectRoot(candidate)];
8248
+ case 2:
8249
+ if (_a.sent()) {
8250
+ return [2 /*return*/, candidate];
8251
+ }
8252
+ _a.label = 3;
8253
+ case 3:
8254
+ i -= 1;
8255
+ return [3 /*break*/, 1];
8256
+ case 4: return [2 /*return*/, ''];
8257
+ }
8258
+ });
8259
+ });
8260
+ }
8261
+ function resolveAssistantWorkspaceRoot() {
8262
+ return __awaiter(this, void 0, void 0, function () {
8263
+ var config, configured, configuredRoot, clientDir, resolvedClientDir, projectRoot, _a, candidate, stat, _b;
8264
+ return __generator(this, function (_c) {
8265
+ switch (_c.label) {
7690
8266
  case 0:
7691
8267
  config = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
7692
8268
  configured = normalizeOptionalString(config['AI_ASSISTANT_WORKSPACE_ROOT']
7693
8269
  || process.env.AI_ASSISTANT_WORKSPACE_ROOT
7694
8270
  || config['CODEX_WORKSPACE_ROOT']
7695
8271
  || process.env.CODEX_WORKSPACE_ROOT);
7696
- candidate = configured || resolveio_server_app_1.ResolveIOServer.getClientDir() || process.cwd();
7697
- stat = null;
7698
- _b.label = 1;
8272
+ configuredRoot = configured ? path.resolve(configured) : '';
8273
+ clientDir = normalizeOptionalString(resolveio_server_app_1.ResolveIOServer.getClientDir());
8274
+ resolvedClientDir = clientDir ? path.resolve(clientDir) : '';
8275
+ if (!resolvedClientDir) return [3 /*break*/, 2];
8276
+ return [4 /*yield*/, resolveAssistantProjectRoot(resolvedClientDir)];
7699
8277
  case 1:
7700
- _b.trys.push([1, 3, , 4]);
7701
- return [4 /*yield*/, fs_1.promises.stat(candidate)];
8278
+ _a = _c.sent();
8279
+ return [3 /*break*/, 3];
7702
8280
  case 2:
7703
- stat = _b.sent();
7704
- return [3 /*break*/, 4];
8281
+ _a = '';
8282
+ _c.label = 3;
7705
8283
  case 3:
7706
- _a = _b.sent();
8284
+ projectRoot = _a;
8285
+ candidate = configuredRoot || projectRoot || resolvedClientDir || process.cwd();
8286
+ if (configuredRoot) {
8287
+ if (projectRoot && isAssistantPathUnderRoot(projectRoot, configuredRoot)) {
8288
+ candidate = projectRoot;
8289
+ }
8290
+ else if (projectRoot && isAssistantPathUnderRoot(configuredRoot, projectRoot)) {
8291
+ candidate = configuredRoot;
8292
+ }
8293
+ else {
8294
+ candidate = configuredRoot;
8295
+ }
8296
+ }
8297
+ else if (projectRoot) {
8298
+ candidate = projectRoot;
8299
+ }
8300
+ else if (resolvedClientDir) {
8301
+ candidate = resolvedClientDir;
8302
+ }
7707
8303
  stat = null;
7708
- return [3 /*break*/, 4];
8304
+ _c.label = 4;
7709
8305
  case 4:
8306
+ _c.trys.push([4, 6, , 7]);
8307
+ return [4 /*yield*/, fs_1.promises.stat(candidate)];
8308
+ case 5:
8309
+ stat = _c.sent();
8310
+ return [3 /*break*/, 7];
8311
+ case 6:
8312
+ _b = _c.sent();
8313
+ stat = null;
8314
+ return [3 /*break*/, 7];
8315
+ case 7:
7710
8316
  if (!stat || !stat.isDirectory()) {
7711
8317
  throw new Error('AI assistant workspace root not found.');
7712
8318
  }
@@ -7797,6 +8403,14 @@ function buildAssistantContext(input, userContext) {
7797
8403
  if (termHints.length) {
7798
8404
  lines.push("Term hints: ".concat(termHints.join('; ')));
7799
8405
  }
8406
+ var fieldHints = Array.isArray(userContext === null || userContext === void 0 ? void 0 : userContext.fieldHints)
8407
+ ? userContext.fieldHints.filter(Boolean)
8408
+ : [];
8409
+ if (fieldHints.length) {
8410
+ fieldHints.forEach(function (hint) {
8411
+ lines.push(hint);
8412
+ });
8413
+ }
7800
8414
  var mongoDb = normalizeOptionalString((_c = input === null || input === void 0 ? void 0 : input.mongo) === null || _c === void 0 ? void 0 : _c.database);
7801
8415
  var mongoDbs = Array.isArray((_d = input === null || input === void 0 ? void 0 : input.mongo) === null || _d === void 0 ? void 0 : _d.databases)
7802
8416
  ? input.mongo.databases.map(function (value) { return normalizeOptionalString(value); }).filter(Boolean)
@@ -7814,6 +8428,85 @@ function buildAssistantContext(input, userContext) {
7814
8428
  }
7815
8429
  return lines.join('\n');
7816
8430
  }
8431
+ function buildAssistantFieldHints(message, collectionNames, options) {
8432
+ var normalizedMessage = normalizeOptionalString(message);
8433
+ if (!normalizedMessage || !Array.isArray(collectionNames) || !collectionNames.length) {
8434
+ return [];
8435
+ }
8436
+ var maxCollections = typeof (options === null || options === void 0 ? void 0 : options.maxCollections) === 'number'
8437
+ ? Math.max(options.maxCollections, 0)
8438
+ : AI_ASSISTANT_CONTEXT_MAX_COLLECTIONS;
8439
+ var maxFields = typeof (options === null || options === void 0 ? void 0 : options.maxFields) === 'number'
8440
+ ? Math.max(options.maxFields, 0)
8441
+ : AI_ASSISTANT_CONTEXT_MAX_FIELDS_PER_COLLECTION;
8442
+ if (!maxCollections || !maxFields) {
8443
+ return [];
8444
+ }
8445
+ var baseTokens = tokenizeFieldKey(normalizedMessage);
8446
+ var expandedTokens = expandFieldTokens(baseTokens);
8447
+ var tokenSet = new Set(expandedTokens);
8448
+ [
8449
+ 'date',
8450
+ 'status',
8451
+ 'total',
8452
+ 'amount',
8453
+ 'paid',
8454
+ 'balance',
8455
+ 'grand',
8456
+ 'subtotal',
8457
+ 'invoice',
8458
+ 'revenue',
8459
+ 'sales',
8460
+ 'billing',
8461
+ 'payment'
8462
+ ].forEach(function (token) { return tokenSet.add(token); });
8463
+ var hints = [];
8464
+ var candidates = collectionNames.filter(Boolean).slice(0, maxCollections);
8465
+ candidates.forEach(function (collection) {
8466
+ var fields = getCollectionSchemaFieldNames(collection);
8467
+ if (!fields.length) {
8468
+ return;
8469
+ }
8470
+ var scored = fields
8471
+ .filter(function (field) { return field && !shouldRedactField(field); })
8472
+ .map(function (field) {
8473
+ var tokens = tokenizeFieldKey(field);
8474
+ if (!tokens.length) {
8475
+ return null;
8476
+ }
8477
+ var score = tokens.filter(function (token) { return tokenSet.has(token); }).length;
8478
+ var hasDate = tokens.includes('date');
8479
+ var hasStatus = tokens.includes('status');
8480
+ var hasTotal = tokens.includes('total') || tokens.includes('amount') || tokens.includes('paid') || tokens.includes('balance');
8481
+ if (score === 0 && (hasDate || hasStatus || hasTotal)) {
8482
+ score = 1;
8483
+ }
8484
+ if (score <= 0) {
8485
+ return null;
8486
+ }
8487
+ if (isAssistantIdField(field)) {
8488
+ score -= 1;
8489
+ }
8490
+ if (field.includes('.$.') && score < 2) {
8491
+ return null;
8492
+ }
8493
+ return { field: field, score: score };
8494
+ })
8495
+ .filter(function (entry) { return !!entry; })
8496
+ .sort(function (a, b) {
8497
+ if (a.score !== b.score) {
8498
+ return b.score - a.score;
8499
+ }
8500
+ return a.field.localeCompare(b.field);
8501
+ })
8502
+ .slice(0, maxFields)
8503
+ .map(function (entry) { return entry.field; });
8504
+ if (scored.length) {
8505
+ hints.push("Field hints (".concat(collection, "): ").concat(scored.join(', ')));
8506
+ }
8507
+ });
8508
+ return hints;
8509
+ }
7817
8510
  var cachedClientRouteIndex = null;
7818
8511
  function normalizeRouteKey(value) {
7819
8512
  var trimmed = normalizeOptionalString(value);
@@ -7827,7 +8520,7 @@ function normalizeRouteMatchKey(value) {
7827
8520
  return normalizeRouteKey(value).toLowerCase();
7828
8521
  }
7829
8522
  function buildClientRouteIndex() {
7830
- var e_25, _a;
8523
+ var e_26, _a;
7831
8524
  var _b;
7832
8525
  var routes = ((_b = resolveio_server_app_1.ResolveIOServer.getClientRoutes) === null || _b === void 0 ? void 0 : _b.call(resolveio_server_app_1.ResolveIOServer)) || [];
7833
8526
  var set = new Set();
@@ -7846,12 +8539,12 @@ function buildClientRouteIndex() {
7846
8539
  }
7847
8540
  }
7848
8541
  }
7849
- catch (e_25_1) { e_25 = { error: e_25_1 }; }
8542
+ catch (e_26_1) { e_26 = { error: e_26_1 }; }
7850
8543
  finally {
7851
8544
  try {
7852
8545
  if (routes_1_1 && !routes_1_1.done && (_a = routes_1.return)) _a.call(routes_1);
7853
8546
  }
7854
- finally { if (e_25) throw e_25.error; }
8547
+ finally { if (e_26) throw e_26.error; }
7855
8548
  }
7856
8549
  return { set: set, map: map, size: routes.length };
7857
8550
  }
@@ -7988,13 +8681,17 @@ function sanitizeAssistantResponse(value) {
7988
8681
  if (!cleaned) {
7989
8682
  return 'I can’t share code, but I can point you to files or explain behavior at a high level.';
7990
8683
  }
7991
- var normalizedCurrency = cleaned.replace(/\bUSD\s*([0-9][0-9,]*(?:\.[0-9]+)?)/g, function (_match, amount) {
8684
+ var normalizedCurrency = cleaned
8685
+ .replace(/\bUSD(?:\s|&nbsp;|&#160;|[\u00A0\u202F\u2007])*\$?\s*([-+]?[0-9][0-9,]*(?:\.[0-9]+)?)/g, function (_match, amount) {
8686
+ return "$".concat(amount);
8687
+ })
8688
+ .replace(/\bUS\$\s*([-+]?[0-9][0-9,]*(?:\.[0-9]+)?)/g, function (_match, amount) {
7992
8689
  return "$".concat(amount);
7993
8690
  });
7994
8691
  return normalizeAssistantRoutes(normalizedCurrency);
7995
8692
  }
7996
8693
  function evaluateAssistantGuardrails(message) {
7997
- var e_26, _a;
8694
+ var e_27, _a;
7998
8695
  var normalized = String(message || '').toLowerCase();
7999
8696
  var patterns = [
8000
8697
  {
@@ -8040,12 +8737,12 @@ function evaluateAssistantGuardrails(message) {
8040
8737
  }
8041
8738
  }
8042
8739
  }
8043
- catch (e_26_1) { e_26 = { error: e_26_1 }; }
8740
+ catch (e_27_1) { e_27 = { error: e_27_1 }; }
8044
8741
  finally {
8045
8742
  try {
8046
8743
  if (patterns_1_1 && !patterns_1_1.done && (_a = patterns_1.return)) _a.call(patterns_1);
8047
8744
  }
8048
- finally { if (e_26) throw e_26.error; }
8745
+ finally { if (e_27) throw e_27.error; }
8049
8746
  }
8050
8747
  return null;
8051
8748
  }
@@ -8160,7 +8857,7 @@ function tokenizeArithmeticExpression(expression) {
8160
8857
  return tokens;
8161
8858
  }
8162
8859
  function evaluateArithmeticExpression(expression) {
8163
- var e_27, _a, e_28, _b;
8860
+ var e_28, _a, e_29, _b;
8164
8861
  var tokens = tokenizeArithmeticExpression(expression);
8165
8862
  if (!tokens || !tokens.length) {
8166
8863
  return null;
@@ -8217,12 +8914,12 @@ function evaluateArithmeticExpression(expression) {
8217
8914
  prevToken = token;
8218
8915
  }
8219
8916
  }
8220
- catch (e_27_1) { e_27 = { error: e_27_1 }; }
8917
+ catch (e_28_1) { e_28 = { error: e_28_1 }; }
8221
8918
  finally {
8222
8919
  try {
8223
8920
  if (tokens_1_1 && !tokens_1_1.done && (_a = tokens_1.return)) _a.call(tokens_1);
8224
8921
  }
8225
- finally { if (e_27) throw e_27.error; }
8922
+ finally { if (e_28) throw e_28.error; }
8226
8923
  }
8227
8924
  while (ops.length) {
8228
8925
  var op = ops.pop();
@@ -8262,12 +8959,12 @@ function evaluateArithmeticExpression(expression) {
8262
8959
  stack.push(Number(token));
8263
8960
  }
8264
8961
  }
8265
- catch (e_28_1) { e_28 = { error: e_28_1 }; }
8962
+ catch (e_29_1) { e_29 = { error: e_29_1 }; }
8266
8963
  finally {
8267
8964
  try {
8268
8965
  if (output_1_1 && !output_1_1.done && (_b = output_1.return)) _b.call(output_1);
8269
8966
  }
8270
- finally { if (e_28) throw e_28.error; }
8967
+ finally { if (e_29) throw e_29.error; }
8271
8968
  }
8272
8969
  if (stack.length !== 1 || Number.isNaN(stack[0])) {
8273
8970
  return null;
@@ -8451,8 +9148,8 @@ function handleCodexUpload(id_conversation, file_name, content_base64, size, con
8451
9148
  }
8452
9149
  function readAttachmentContents(attachments) {
8453
9150
  return __awaiter(this, void 0, void 0, function () {
8454
- var limits, totalBytes, totalChars, chunks, cleaned, attachments_1, attachments_1_1, attachment, localPath, safe, stat, ext, name_1, type, readable, content, _a, e_29_1;
8455
- var e_29, _b;
9151
+ var limits, totalBytes, totalChars, chunks, cleaned, attachments_1, attachments_1_1, attachment, localPath, safe, stat, ext, name_1, type, readable, content, _a, e_30_1;
9152
+ var e_30, _b;
8456
9153
  return __generator(this, function (_c) {
8457
9154
  switch (_c.label) {
8458
9155
  case 0:
@@ -8531,14 +9228,14 @@ function readAttachmentContents(attachments) {
8531
9228
  return [3 /*break*/, 2];
8532
9229
  case 10: return [3 /*break*/, 13];
8533
9230
  case 11:
8534
- e_29_1 = _c.sent();
8535
- e_29 = { error: e_29_1 };
9231
+ e_30_1 = _c.sent();
9232
+ e_30 = { error: e_30_1 };
8536
9233
  return [3 /*break*/, 13];
8537
9234
  case 12:
8538
9235
  try {
8539
9236
  if (attachments_1_1 && !attachments_1_1.done && (_b = attachments_1.return)) _b.call(attachments_1);
8540
9237
  }
8541
- finally { if (e_29) throw e_29.error; }
9238
+ finally { if (e_30) throw e_30.error; }
8542
9239
  return [7 /*endfinally*/];
8543
9240
  case 13: return [2 /*return*/, {
8544
9241
  promptText: chunks.length ? "\n\nAttachments:\n".concat(chunks.join('\n\n')) : '',
@@ -8726,7 +9423,7 @@ function estimateUsage(messages, responseText, model) {
8726
9423
  };
8727
9424
  }
8728
9425
  function evaluateGuardrails(message) {
8729
- var e_30, _a;
9426
+ var e_31, _a;
8730
9427
  var normalized = String(message || '').toLowerCase();
8731
9428
  var patterns = [
8732
9429
  { 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.' },
@@ -8748,12 +9445,12 @@ function evaluateGuardrails(message) {
8748
9445
  }
8749
9446
  }
8750
9447
  }
8751
- catch (e_30_1) { e_30 = { error: e_30_1 }; }
9448
+ catch (e_31_1) { e_31 = { error: e_31_1 }; }
8752
9449
  finally {
8753
9450
  try {
8754
9451
  if (patterns_2_1 && !patterns_2_1.done && (_a = patterns_2.return)) _a.call(patterns_2);
8755
9452
  }
8756
- finally { if (e_30) throw e_30.error; }
9453
+ finally { if (e_31) throw e_31.error; }
8757
9454
  }
8758
9455
  return null;
8759
9456
  }