@resolveio/server-lib 20.15.9 → 22.0.0

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.
@@ -147,6 +147,9 @@ var AI_ASSISTANT_TOOL_MAX_STEPS = 1;
147
147
  var AI_ASSISTANT_DISPLAY_MAX_COLUMNS = 12;
148
148
  var AI_ASSISTANT_DISPLAY_PREVIEW_MAX_ROWS = 20;
149
149
  var AI_ASSISTANT_DISPLAY_STRING_LIMIT = 160;
150
+ var AI_ASSISTANT_ID_DISPLAY_LOOKUP_MAX_FIELDS = 4;
151
+ var AI_ASSISTANT_ID_DISPLAY_LOOKUP_MAX_IDS = 60;
152
+ var AI_ASSISTANT_ID_DISPLAY_LOOKUP_MAX_COLLECTIONS = 3;
150
153
  var AI_ASSISTANT_PROGRESS_PLACEHOLDER = 'Planning...';
151
154
  var AI_ASSISTANT_PROGRESS_TICK_MS = 5000;
152
155
  var AI_ASSISTANT_READ_PREFERENCE = 'secondary';
@@ -346,7 +349,9 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
346
349
  '- Do not assist with hacking, bypassing security, or abuse.',
347
350
  'Accuracy & tools:',
348
351
  '- Step 1 (always): determine the target collections/models/modules/workflows using context, routes, and collection hints. Assume the user is non-technical and will not provide internal names.',
352
+ '- Never use *.versions collections for normal requests. Only use a .versions collection when explicitly investigating a bug by checking the last ~5 updates.',
349
353
  '- Planning stage: regex/keyword scan the codebase for collectionName/model definitions, methods, publications, and Angular routes/modules to map user wording to internal names.',
354
+ '- If permissionView starts with /report/, prefer the report-* collection when both report and base collections exist.',
350
355
  '- Map user wording to internal collections/fields yourself. Do not ask for property names unless required to run a query.',
351
356
  '- Use term hints from context (synonym expansions) when mapping user language to collections.',
352
357
  '- Do not guess or invent collections/fields. If unsure, verify in the codebase or run a small Mongo read (limit 1-5) to learn the shape.',
@@ -354,12 +359,14 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
354
359
  '- For any data request (counts, lists, breakdowns, recent/last items), you MUST run a MONGO_READ or MONGO_AGG before answering.',
355
360
  '- Ask at most one clarifying question only when required to run a query or resolve missing details.',
356
361
  '- If a field starts with id_ and refers to another collection, treat it as a foreign key and look up the related record when needed.',
362
+ '- When resolving id_* fields, prefer lookup definitions from collection schemas/report-builder lookup tables to choose the target collection and name fields.',
357
363
  '- When the user provides a customer, well, or chemical name, use case-insensitive regex matching to find it. Assume the name exists and try to match it before asking questions.',
358
364
  '- Use the codebase context to choose correct collections/fields/workflows and use MONGO_READ/MONGO_AGG to answer with real data when needed.',
359
365
  '- Process (fast path): Queue -> Planning -> Grabbing Data -> Drafting response. Use regex/keyword matching to identify collections/models, draft a minimal query, run the tool, then format a table. This should be fast; avoid extra narration.',
360
366
  '- Assume a relevant collection exists; if verification reads return zero data, report no data found instead of interrogating the user.',
361
367
  '- Never claim "no data exists" unless you resolved a collection and executed a legitimate query (with fallback date fields when needed) that returned zero rows.',
362
368
  '- If a query returns zero rows, run a tiny probe read (limit 1-3) to validate fields and adjust filters/projection before concluding.',
369
+ '- For name-based filters, run a quick existence check with only the date filter first; if records exist, adjust name matching (tokenized regex or ID lookup) instead of concluding no data.',
363
370
  '- For direct questions, answer first. Ask a single follow-up only if required to proceed.',
364
371
  'Data Presentation:',
365
372
  '- Output plain Markdown (NO triple backticks).',
@@ -427,6 +434,25 @@ var assistantCodexClient = null;
427
434
  var assistantCodexRunQueue = [];
428
435
  var assistantCodexRunDraining = false;
429
436
  /* eslint-enable no-unused-vars */
437
+ function parseDebugFlag(value) {
438
+ if (value === true) {
439
+ return true;
440
+ }
441
+ if (value === false || value === null || value === undefined) {
442
+ return false;
443
+ }
444
+ if (typeof value === 'number') {
445
+ return value === 1;
446
+ }
447
+ if (typeof value === 'string') {
448
+ var normalized = value.trim().toLowerCase();
449
+ return ['1', 'true', 'yes', 'y', 'on'].includes(normalized);
450
+ }
451
+ return false;
452
+ }
453
+ function isAiWorkerDebugEnabled() {
454
+ return parseDebugFlag(process.env.AI_ASSISTANT_WORKER_DEBUG);
455
+ }
430
456
  function enqueueAssistantCodexRun(task) {
431
457
  var _this = this;
432
458
  assistantCodexRunQueue.push(task);
@@ -495,6 +521,12 @@ function drainAssistantCodexRunQueue() {
495
521
  });
496
522
  }
497
523
  function loadAiTerminalMethods(methodManager) {
524
+ var codexWorkerIndex = resolveSingleWorkerTarget(process.env.AI_ASSISTANT_CODEX_WORKER_INDEX
525
+ || process.env.CODEX_WORKER_INDEX
526
+ || process.env.WORKER_CODEX_INDEX);
527
+ var codexWorkerInstance = resolveSingleWorkerTarget(process.env.AI_ASSISTANT_CODEX_WORKER_INSTANCE
528
+ || process.env.CODEX_WORKER_INSTANCE
529
+ || process.env.WORKER_CODEX_INSTANCE);
498
530
  methodManager.methods({
499
531
  aiTerminalConversationCreate: {
500
532
  check: new simpl_schema_1.default({
@@ -726,17 +758,12 @@ function loadAiTerminalMethods(methodManager) {
726
758
  });
727
759
  }
728
760
  },
729
- aiCoderTerminalRunCodex: {
730
- check: new simpl_schema_1.default({
761
+ aiCoderTerminalRunCodex: __assign(__assign(__assign({ check: new simpl_schema_1.default({
731
762
  payload: {
732
763
  type: Object,
733
764
  blackbox: true
734
765
  }
735
- }),
736
- forceWorker: true,
737
- maxConcurrencyPerInstance: 1,
738
- timeoutOverride: resolveCodexTimeoutMs() + 15000,
739
- function: function (payload) {
766
+ }), forceWorker: true, workerQueue: 'codex' }, (codexWorkerIndex ? { targetWorkerIndex: codexWorkerIndex } : {})), (codexWorkerInstance ? { targetWorkerInstance: codexWorkerInstance } : {})), { maxConcurrencyPerInstance: 1, timeoutOverride: resolveCodexTimeoutMs() + 15000, function: function (payload) {
740
767
  return __awaiter(this, void 0, void 0, function () {
741
768
  return __generator(this, function (_a) {
742
769
  switch (_a.label) {
@@ -745,8 +772,7 @@ function loadAiTerminalMethods(methodManager) {
745
772
  }
746
773
  });
747
774
  });
748
- }
749
- },
775
+ } }),
750
776
  aiAssistantMongoRead: {
751
777
  check: new simpl_schema_1.default({
752
778
  payload: {
@@ -1021,7 +1047,7 @@ function executeAiFormPatch(payload, context) {
1021
1047
  }
1022
1048
  function executeAiAssistantCodexRun(payload, context) {
1023
1049
  return __awaiter(this, void 0, void 0, function () {
1024
- var input, message, requestId, guardrail, conversation_2, now_2, userMsg, assistantMsg, user, isSuperAdmin, hasInvoiceAccess, customerId, conversation, now, attachments, attachmentData, historyLimit, history, _a, historyLines, userDoc, initialProgress, assistantDoc, insertResult, assistantMessageId;
1050
+ var input, message, aiWorkerDebug, requestId, guardrail, conversation_2, now_2, userMsg, assistantMsg, user, isSuperAdmin, hasInvoiceAccess, customerId, conversation, now, attachments, attachmentData, historyLimit, history, _a, historyLines, userDoc, initialProgress, assistantDoc, insertResult, assistantMessageId;
1025
1051
  var _this = this;
1026
1052
  var _b, _c;
1027
1053
  return __generator(this, function (_d) {
@@ -1035,6 +1061,7 @@ function executeAiAssistantCodexRun(payload, context) {
1035
1061
  if (!(context === null || context === void 0 ? void 0 : context.id_user)) {
1036
1062
  throw new Error('Unauthorized.');
1037
1063
  }
1064
+ aiWorkerDebug = isAiWorkerDebugEnabled();
1038
1065
  requestId = normalizeOptionalString(input.request_id);
1039
1066
  guardrail = evaluateAssistantGuardrails(message);
1040
1067
  if (!(guardrail === null || guardrail === void 0 ? void 0 : guardrail.blocked)) return [3 /*break*/, 5];
@@ -1081,6 +1108,16 @@ function executeAiAssistantCodexRun(payload, context) {
1081
1108
  return [4 /*yield*/, ensureConversation(input, 'codex')];
1082
1109
  case 7:
1083
1110
  conversation = _d.sent();
1111
+ if (aiWorkerDebug) {
1112
+ console.log(new Date(), '[AI Worker Debug] codex run queued', {
1113
+ requestId: requestId || null,
1114
+ id_user: (context === null || context === void 0 ? void 0 : context.id_user) || null,
1115
+ id_conversation: (conversation === null || conversation === void 0 ? void 0 : conversation._id) || null,
1116
+ isWorkerInstance: process.env.IS_WORKER_INSTANCE || null,
1117
+ workerIndex: process.env.WORKER_INDEX || null,
1118
+ workerInstance: process.env.NODE_APP_INSTANCE || null
1119
+ });
1120
+ }
1084
1121
  now = new Date();
1085
1122
  attachments = Array.isArray(input.attachments) ? input.attachments : [];
1086
1123
  return [4 /*yield*/, readAttachmentContents(attachments)];
@@ -1131,12 +1168,23 @@ function executeAiAssistantCodexRun(payload, context) {
1131
1168
  insertResult = _d.sent();
1132
1169
  assistantMessageId = (insertResult === null || insertResult === void 0 ? void 0 : insertResult._id) || (insertResult === null || insertResult === void 0 ? void 0 : insertResult.insertedId);
1133
1170
  enqueueAssistantCodexRun(function () { return __awaiter(_this, void 0, void 0, function () {
1134
- var runStart, steps, recordStep, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, dataQuestion, lastDirective, toolResponseDebug, toolError, termHints, collectionHints, collectionTokenization, collectionRanking, collectionSelection, collectionOverride, timingBreakdown, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, baseWeights, expandedWeights, dbName, db, collectionNames, _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, finalNow, finishedAt, codexMs, draftingMs, finalMetadata, finalAssistantDoc;
1135
- var _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
1136
- return __generator(this, function (_t) {
1137
- switch (_t.label) {
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;
1172
+ var _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
1173
+ return __generator(this, function (_u) {
1174
+ switch (_u.label) {
1138
1175
  case 0:
1139
1176
  runStart = Date.now();
1177
+ if (aiWorkerDebug) {
1178
+ console.log(new Date(), '[AI Worker Debug] codex run start', {
1179
+ requestId: requestId || null,
1180
+ id_user: (context === null || context === void 0 ? void 0 : context.id_user) || null,
1181
+ id_conversation: (conversation === null || conversation === void 0 ? void 0 : conversation._id) || null,
1182
+ id_message: assistantMessageId ? String(assistantMessageId) : null,
1183
+ isWorkerInstance: process.env.IS_WORKER_INSTANCE || null,
1184
+ workerIndex: process.env.WORKER_INDEX || null,
1185
+ workerInstance: process.env.NODE_APP_INSTANCE || null
1186
+ });
1187
+ }
1140
1188
  steps = [];
1141
1189
  recordStep = function (step, details) {
1142
1190
  steps.push({
@@ -1162,6 +1210,7 @@ function executeAiAssistantCodexRun(payload, context) {
1162
1210
  collectionRanking = null;
1163
1211
  collectionSelection = null;
1164
1212
  collectionOverride = null;
1213
+ collectionNames = [];
1165
1214
  timingBreakdown = {
1166
1215
  directiveMs: 0,
1167
1216
  initialResponseMs: 0,
@@ -1172,9 +1221,9 @@ function executeAiAssistantCodexRun(payload, context) {
1172
1221
  contextRoute = normalizeOptionalString((_f = input === null || input === void 0 ? void 0 : input.context) === null || _f === void 0 ? void 0 : _f.route);
1173
1222
  contextMode = normalizeOptionalString((_g = input === null || input === void 0 ? void 0 : input.context) === null || _g === void 0 ? void 0 : _g.mode);
1174
1223
  recordStep('Queued', { requestId: requestId || undefined });
1175
- _t.label = 1;
1224
+ _u.label = 1;
1176
1225
  case 1:
1177
- _t.trys.push([1, 30, 31, 32]);
1226
+ _u.trys.push([1, 30, 31, 32]);
1178
1227
  hintSeed = [message, contextRoute].filter(Boolean).join(' ');
1179
1228
  termExpansion = expandAssistantTermSynonyms(hintSeed);
1180
1229
  hintText = termExpansion.expanded || hintSeed;
@@ -1195,19 +1244,19 @@ function executeAiAssistantCodexRun(payload, context) {
1195
1244
  recordStep('Planning: term expansion', {
1196
1245
  termMatches: termExpansion.matches.length ? termExpansion.matches : undefined
1197
1246
  });
1198
- _t.label = 2;
1247
+ _u.label = 2;
1199
1248
  case 2:
1200
- _t.trys.push([2, 4, , 5]);
1249
+ _u.trys.push([2, 4, , 5]);
1201
1250
  dbName = resolveAssistantDatabaseName(undefined, input.mongo);
1202
1251
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1203
1252
  return [4 /*yield*/, listAssistantCollections(db, dbName)];
1204
1253
  case 3:
1205
- collectionNames = _t.sent();
1254
+ collectionNames = _u.sent();
1206
1255
  collectionHints = resolveCollectionHintsFromTokens(expandedTokens, collectionNames, 5);
1207
1256
  collectionRanking = buildCollectionRankingDebugFromTokens(expandedTokens, collectionNames, 8);
1208
1257
  return [3 /*break*/, 5];
1209
1258
  case 4:
1210
- _a = _t.sent();
1259
+ _a = _u.sent();
1211
1260
  collectionHints = [];
1212
1261
  collectionRanking = collectionRanking || ((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens)
1213
1262
  ? buildCollectionRankingDebugFromTokens(collectionTokenization.expandedTokens || [], [], 0)
@@ -1230,7 +1279,7 @@ function executeAiAssistantCodexRun(payload, context) {
1230
1279
  prompt_1 = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1231
1280
  return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
1232
1281
  case 6:
1233
- workspaceRoot = _t.sent();
1282
+ workspaceRoot = _u.sent();
1234
1283
  codexConfig = resolveCodexSettings();
1235
1284
  runOptions = {
1236
1285
  timeoutMs: resolveCodexTimeoutMs(),
@@ -1251,13 +1300,13 @@ function executeAiAssistantCodexRun(payload, context) {
1251
1300
  if (!dataQuestion) return [3 /*break*/, 10];
1252
1301
  recordStep('Directive: determine tool', { type: 'data-question' });
1253
1302
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1254
- _t.label = 7;
1303
+ _u.label = 7;
1255
1304
  case 7:
1256
- _t.trys.push([7, 9, , 10]);
1305
+ _u.trys.push([7, 9, , 10]);
1257
1306
  directiveStart = Date.now();
1258
1307
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1259
1308
  case 8:
1260
- directiveText = _t.sent();
1309
+ directiveText = _u.sent();
1261
1310
  timingBreakdown.directiveMs = Date.now() - directiveStart;
1262
1311
  forcedDirective = extractAssistantMongoDirective(directiveText);
1263
1312
  if (forcedDirective) {
@@ -1274,7 +1323,7 @@ function executeAiAssistantCodexRun(payload, context) {
1274
1323
  }
1275
1324
  return [3 /*break*/, 10];
1276
1325
  case 9:
1277
- _b = _t.sent();
1326
+ _b = _u.sent();
1278
1327
  return [3 /*break*/, 10];
1279
1328
  case 10:
1280
1329
  if (!!directive) return [3 /*break*/, 12];
@@ -1282,7 +1331,7 @@ function executeAiAssistantCodexRun(payload, context) {
1282
1331
  initialStart = Date.now();
1283
1332
  return [4 /*yield*/, runCodexInWorkerThread(prompt_1, runOptions, codexConfig, streamProgress)];
1284
1333
  case 11:
1285
- responseText = _t.sent();
1334
+ responseText = _u.sent();
1286
1335
  timingBreakdown.initialResponseMs = Date.now() - initialStart;
1287
1336
  directive = extractAssistantMongoDirective(responseText);
1288
1337
  if (directive) {
@@ -1296,18 +1345,18 @@ function executeAiAssistantCodexRun(payload, context) {
1296
1345
  permissionView: normalizeOptionalString((_o = directive.payload) === null || _o === void 0 ? void 0 : _o.permissionView) || undefined
1297
1346
  });
1298
1347
  }
1299
- _t.label = 12;
1348
+ _u.label = 12;
1300
1349
  case 12:
1301
1350
  if (!(!directive && dataQuestion)) return [3 /*break*/, 16];
1302
1351
  recordStep('Directive: forced retry', { mode: 'directive-only' });
1303
1352
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1304
- _t.label = 13;
1353
+ _u.label = 13;
1305
1354
  case 13:
1306
- _t.trys.push([13, 15, , 16]);
1355
+ _u.trys.push([13, 15, , 16]);
1307
1356
  forcedStart = Date.now();
1308
1357
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1309
1358
  case 14:
1310
- directiveText = _t.sent();
1359
+ directiveText = _u.sent();
1311
1360
  timingBreakdown.forcedDirectiveMs = Date.now() - forcedStart;
1312
1361
  forcedDirective = extractAssistantMongoDirective(directiveText);
1313
1362
  if (forcedDirective) {
@@ -1324,12 +1373,18 @@ function executeAiAssistantCodexRun(payload, context) {
1324
1373
  }
1325
1374
  return [3 /*break*/, 16];
1326
1375
  case 15:
1327
- _c = _t.sent();
1376
+ _c = _u.sent();
1328
1377
  return [3 /*break*/, 16];
1329
1378
  case 16:
1330
1379
  if (directive) {
1331
1380
  requestedCollection = normalizeOptionalString((_s = directive.payload) === null || _s === void 0 ? void 0 : _s.collection);
1332
- collectionOverride = resolveAssistantCollectionOverride(collectionRanking, requestedCollection);
1381
+ collectionOverride = resolveCollectionOverrideWithContext({
1382
+ message: message,
1383
+ collectionRanking: collectionRanking,
1384
+ requestedCollection: requestedCollection,
1385
+ permissionView: normalizeOptionalString((_t = directive.payload) === null || _t === void 0 ? void 0 : _t.permissionView) || contextRoute,
1386
+ collectionNames: collectionNames
1387
+ });
1333
1388
  if (collectionOverride) {
1334
1389
  recordStep('Planning: collection override', {
1335
1390
  from: collectionOverride.from || undefined,
@@ -1353,19 +1408,19 @@ function executeAiAssistantCodexRun(payload, context) {
1353
1408
  collection: normalizeOptionalString(toolRequest === null || toolRequest === void 0 ? void 0 : toolRequest.collection) || undefined,
1354
1409
  permissionView: normalizeOptionalString(toolRequest === null || toolRequest === void 0 ? void 0 : toolRequest.permissionView) || undefined
1355
1410
  });
1356
- _t.label = 17;
1411
+ _u.label = 17;
1357
1412
  case 17:
1358
- _t.trys.push([17, 26, , 27]);
1413
+ _u.trys.push([17, 26, , 27]);
1359
1414
  toolStart = Date.now();
1360
1415
  if (!(effectiveDirective.type === 'aggregate')) return [3 /*break*/, 19];
1361
1416
  return [4 /*yield*/, executeAiAssistantMongoAggregate(toolRequest, context)];
1362
1417
  case 18:
1363
- _d = _t.sent();
1418
+ _d = _u.sent();
1364
1419
  return [3 /*break*/, 21];
1365
1420
  case 19: return [4 /*yield*/, executeAiAssistantMongoRead(toolRequest, context)];
1366
1421
  case 20:
1367
- _d = _t.sent();
1368
- _t.label = 21;
1422
+ _d = _u.sent();
1423
+ _u.label = 21;
1369
1424
  case 21:
1370
1425
  toolResponse = _d;
1371
1426
  timingBreakdown.toolMs = Date.now() - toolStart;
@@ -1382,23 +1437,23 @@ function executeAiAssistantCodexRun(payload, context) {
1382
1437
  progressTracker.push('Drafting response');
1383
1438
  recordStep('Drafting response');
1384
1439
  followupPrompt = buildAssistantCodexToolFollowupPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, toolPayload.prompt);
1385
- _t.label = 22;
1440
+ _u.label = 22;
1386
1441
  case 22:
1387
- _t.trys.push([22, 24, , 25]);
1442
+ _u.trys.push([22, 24, , 25]);
1388
1443
  followupStart = Date.now();
1389
1444
  return [4 /*yield*/, runCodexInWorkerThread(followupPrompt, runOptions, codexConfig, streamProgress)];
1390
1445
  case 23:
1391
- followupText = _t.sent();
1446
+ followupText = _u.sent();
1392
1447
  timingBreakdown.followupMs = Date.now() - followupStart;
1393
1448
  assistantContent = sanitizeAssistantResponse(followupText);
1394
1449
  return [3 /*break*/, 25];
1395
1450
  case 24:
1396
- _e = _t.sent();
1451
+ _e = _u.sent();
1397
1452
  assistantContent = buildAssistantToolFallbackResponse(toolPayload.result);
1398
1453
  return [3 /*break*/, 25];
1399
1454
  case 25: return [3 /*break*/, 27];
1400
1455
  case 26:
1401
- error_2 = _t.sent();
1456
+ error_2 = _u.sent();
1402
1457
  assistantContent = buildAssistantToolErrorMessage(error_2, directive, toolRequest);
1403
1458
  toolError = error_2;
1404
1459
  return [3 /*break*/, 27];
@@ -1406,10 +1461,10 @@ function executeAiAssistantCodexRun(payload, context) {
1406
1461
  case 28:
1407
1462
  progressTracker.push('Drafting response');
1408
1463
  recordStep('Drafting response');
1409
- _t.label = 29;
1464
+ _u.label = 29;
1410
1465
  case 29: return [3 /*break*/, 32];
1411
1466
  case 30:
1412
- error_3 = _t.sent();
1467
+ error_3 = _u.sent();
1413
1468
  assistantContent = buildAssistantCodexErrorMessage(error_3);
1414
1469
  recordStep('Error', { message: normalizeOptionalString(error_3 === null || error_3 === void 0 ? void 0 : error_3.message) || 'Unknown error' });
1415
1470
  return [3 /*break*/, 32];
@@ -1420,6 +1475,21 @@ function executeAiAssistantCodexRun(payload, context) {
1420
1475
  if (!assistantContent) {
1421
1476
  assistantContent = buildAssistantCodexErrorMessage(null);
1422
1477
  }
1478
+ if (aiWorkerDebug) {
1479
+ finishedAt = Date.now();
1480
+ console.log(new Date(), '[AI Worker Debug] codex run complete', {
1481
+ requestId: requestId || null,
1482
+ id_user: (context === null || context === void 0 ? void 0 : context.id_user) || null,
1483
+ id_conversation: (conversation === null || conversation === void 0 ? void 0 : conversation._id) || null,
1484
+ id_message: assistantMessageId ? String(assistantMessageId) : null,
1485
+ contentChars: assistantContent.length,
1486
+ totalMs: finishedAt - runStart,
1487
+ timingBreakdown: timingBreakdown,
1488
+ isWorkerInstance: process.env.IS_WORKER_INSTANCE || null,
1489
+ workerIndex: process.env.WORKER_INDEX || null,
1490
+ workerInstance: process.env.NODE_APP_INSTANCE || null
1491
+ });
1492
+ }
1423
1493
  finalNow = new Date();
1424
1494
  if (isSuperAdmin) {
1425
1495
  finishedAt = Date.now();
@@ -1474,16 +1544,16 @@ function executeAiAssistantCodexRun(payload, context) {
1474
1544
  }
1475
1545
  })];
1476
1546
  case 33:
1477
- _t.sent();
1478
- _t.label = 34;
1547
+ _u.sent();
1548
+ _u.label = 34;
1479
1549
  case 34: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
1480
1550
  case 35:
1481
- _t.sent();
1551
+ _u.sent();
1482
1552
  if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 37];
1483
1553
  return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
1484
1554
  case 36:
1485
- _t.sent();
1486
- _t.label = 37;
1555
+ _u.sent();
1556
+ _u.label = 37;
1487
1557
  case 37: return [2 /*return*/, finalAssistantDoc];
1488
1558
  }
1489
1559
  });
@@ -1497,10 +1567,10 @@ function executeAiAssistantCodexRun(payload, context) {
1497
1567
  }
1498
1568
  function executeAiAssistantMongoRead(payload, context) {
1499
1569
  return __awaiter(this, void 0, void 0, function () {
1500
- var input, rawCollection, dbName, db, collectionResolution, collection, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, strippedClient, clientScopedQuery, scopedQuery, normalized, findOptions, documents, executedQuery, probeDocs, dateFallback, fallbackQuery, fallbackDocs, expanded, fallbackDocs, nameFallback, fallbackDocs, queryFields, _c, aliases, rewrittenQuery, fallbackDocs, _d, idLookup, fallbackDocs, total, sanitizedDocuments, requestedFields, missingFields, _e, projectionAliases, expandedProjection, refreshedDocs, includeIds, fieldAliases, displayDocs, priorityFields, display;
1501
- var _f, _g;
1502
- return __generator(this, function (_h) {
1503
- switch (_h.label) {
1570
+ var input, rawCollection, dbName, db, collectionResolution, collection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, strippedClient, clientScopedQuery, scopedQuery, normalized, findOptions, documents, executedQuery, probeDocs, dateFallback, fallbackQuery, fallbackDocs, expanded, fallbackDocs, nameFallback, fallbackDocs, _c, chemicalLookup, fallbackDocs, queryFields, _d, aliases, rewrittenQuery, fallbackDocs, _e, idLookup, fallbackDocs, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, nameFields, dateFields, diagnostics, queryNoName, _f, queryNoDate, _g, _h, _j, _k, allCollections, base, alt, altCount, _l, total, sanitizedDocuments, requestedFields, missingFields, _m, projectionAliases, expandedProjection, refreshedDocs, includeIds, fieldAliases, displayDocs, idLookupDisplay, priorityFields, display;
1571
+ var _o, _p;
1572
+ return __generator(this, function (_q) {
1573
+ switch (_q.label) {
1504
1574
  case 0:
1505
1575
  input = payload || {};
1506
1576
  rawCollection = normalizeOptionalString(input.collection);
@@ -1511,15 +1581,16 @@ function executeAiAssistantMongoRead(payload, context) {
1511
1581
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1512
1582
  return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
1513
1583
  case 1:
1514
- collectionResolution = _h.sent();
1584
+ collectionResolution = _q.sent();
1515
1585
  collection = collectionResolution.name || rawCollection;
1586
+ schemaFields = getCollectionSchemaFieldNames(collection);
1516
1587
  return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
1517
1588
  case 2:
1518
- _a = _h.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1589
+ _a = _q.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1519
1590
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
1520
1591
  throw new Error('AI assistant mongo read: Access denied.');
1521
1592
  }
1522
- customerId = normalizeOptionalString((_f = user === null || user === void 0 ? void 0 : user.other) === null || _f === void 0 ? void 0 : _f.id_customer);
1593
+ customerId = normalizeOptionalString((_o = user === null || user === void 0 ? void 0 : user.other) === null || _o === void 0 ? void 0 : _o.id_customer);
1523
1594
  fallbackMeta = {};
1524
1595
  baseQuery = normalizeMongoQuery(input.query);
1525
1596
  if (!isSuperAdmin && customerId) {
@@ -1544,11 +1615,11 @@ function executeAiAssistantMongoRead(payload, context) {
1544
1615
  if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 4];
1545
1616
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
1546
1617
  case 3:
1547
- _b = _h.sent();
1618
+ _b = _q.sent();
1548
1619
  return [3 /*break*/, 5];
1549
1620
  case 4:
1550
1621
  _b = false;
1551
- _h.label = 5;
1622
+ _q.label = 5;
1552
1623
  case 5:
1553
1624
  shouldScopeByClient = _b;
1554
1625
  if (!isSuperAdmin && shouldScopeByClient) {
@@ -1568,7 +1639,7 @@ function executeAiAssistantMongoRead(payload, context) {
1568
1639
  findOptions = __assign(__assign({}, normalized.findOptions), { readPreference: AI_ASSISTANT_READ_PREFERENCE });
1569
1640
  return [4 /*yield*/, db.collection(collection).find(scopedQuery, findOptions).toArray()];
1570
1641
  case 6:
1571
- documents = _h.sent();
1642
+ documents = _q.sent();
1572
1643
  executedQuery = scopedQuery;
1573
1644
  probeDocs = null;
1574
1645
  if (!!documents.length) return [3 /*break*/, 8];
@@ -1578,13 +1649,13 @@ function executeAiAssistantMongoRead(payload, context) {
1578
1649
  fallbackMeta.dateField = __assign(__assign({}, dateFallback), { attempted: true, used: false });
1579
1650
  return [4 /*yield*/, db.collection(collection).find(fallbackQuery, findOptions).toArray()];
1580
1651
  case 7:
1581
- fallbackDocs = _h.sent();
1652
+ fallbackDocs = _q.sent();
1582
1653
  if (fallbackDocs.length) {
1583
1654
  documents = fallbackDocs;
1584
1655
  executedQuery = fallbackQuery;
1585
1656
  fallbackMeta.dateField.used = true;
1586
1657
  }
1587
- _h.label = 8;
1658
+ _q.label = 8;
1588
1659
  case 8:
1589
1660
  if (!!documents.length) return [3 /*break*/, 10];
1590
1661
  expanded = expandQueryDateFallbacks(executedQuery);
@@ -1596,13 +1667,13 @@ function executeAiAssistantMongoRead(payload, context) {
1596
1667
  };
1597
1668
  return [4 /*yield*/, db.collection(collection).find(expanded.query, findOptions).toArray()];
1598
1669
  case 9:
1599
- fallbackDocs = _h.sent();
1670
+ fallbackDocs = _q.sent();
1600
1671
  if (fallbackDocs.length) {
1601
1672
  documents = fallbackDocs;
1602
1673
  executedQuery = expanded.query;
1603
1674
  fallbackMeta.dateFieldsExpanded.used = true;
1604
1675
  }
1605
- _h.label = 10;
1676
+ _q.label = 10;
1606
1677
  case 10:
1607
1678
  if (!!documents.length) return [3 /*break*/, 12];
1608
1679
  nameFallback = resolveReadNameMatchFallback(executedQuery);
@@ -1615,17 +1686,15 @@ function executeAiAssistantMongoRead(payload, context) {
1615
1686
  };
1616
1687
  return [4 /*yield*/, db.collection(collection).find(nameFallback.query, findOptions).toArray()];
1617
1688
  case 11:
1618
- fallbackDocs = _h.sent();
1689
+ fallbackDocs = _q.sent();
1619
1690
  if (fallbackDocs.length) {
1620
1691
  documents = fallbackDocs;
1621
1692
  executedQuery = nameFallback.query;
1622
1693
  fallbackMeta.nameMatch.used = true;
1623
1694
  }
1624
- _h.label = 12;
1695
+ _q.label = 12;
1625
1696
  case 12:
1626
- if (!!documents.length) return [3 /*break*/, 16];
1627
- queryFields = extractQueryFieldPaths(executedQuery).filter(function (field) { return !isAssistantIdField(field); });
1628
- if (!queryFields.length) return [3 /*break*/, 16];
1697
+ if (!!documents.length) return [3 /*break*/, 17];
1629
1698
  _c = probeDocs;
1630
1699
  if (_c) return [3 /*break*/, 14];
1631
1700
  return [4 /*yield*/, fetchAssistantProbeDocs({
@@ -1637,13 +1706,54 @@ function executeAiAssistantMongoRead(payload, context) {
1637
1706
  includeClientScope: shouldScopeByClient
1638
1707
  })];
1639
1708
  case 13:
1640
- _c = (_h.sent());
1641
- _h.label = 14;
1709
+ _c = (_q.sent());
1710
+ _q.label = 14;
1642
1711
  case 14:
1643
1712
  probeDocs = _c;
1644
- if (!probeDocs.length) return [3 /*break*/, 16];
1645
- aliases = resolveFieldAliases(probeDocs, queryFields);
1646
- if (!Object.keys(aliases).length) return [3 /*break*/, 16];
1713
+ return [4 /*yield*/, applyChemicalNameLookupFallbackToQuery({
1714
+ query: executedQuery,
1715
+ db: db,
1716
+ dbName: dbName,
1717
+ idClient: normalizedClient,
1718
+ idCustomer: customerId,
1719
+ isSuperAdmin: isSuperAdmin,
1720
+ probeDocs: probeDocs || undefined
1721
+ })];
1722
+ case 15:
1723
+ chemicalLookup = _q.sent();
1724
+ if (!chemicalLookup) return [3 /*break*/, 17];
1725
+ fallbackMeta.chemicalLookup = __assign(__assign({}, chemicalLookup.meta), { attempted: true, used: false });
1726
+ return [4 /*yield*/, db.collection(collection).find(chemicalLookup.query, findOptions).toArray()];
1727
+ case 16:
1728
+ fallbackDocs = _q.sent();
1729
+ if (fallbackDocs.length) {
1730
+ documents = fallbackDocs;
1731
+ executedQuery = chemicalLookup.query;
1732
+ fallbackMeta.chemicalLookup.used = true;
1733
+ }
1734
+ _q.label = 17;
1735
+ case 17:
1736
+ if (!!documents.length) return [3 /*break*/, 21];
1737
+ queryFields = extractQueryFieldPaths(executedQuery).filter(function (field) { return !isAssistantIdField(field); });
1738
+ if (!queryFields.length) return [3 /*break*/, 21];
1739
+ _d = probeDocs;
1740
+ if (_d) return [3 /*break*/, 19];
1741
+ return [4 /*yield*/, fetchAssistantProbeDocs({
1742
+ db: db,
1743
+ collection: collection,
1744
+ idClient: normalizedClient,
1745
+ idCustomer: customerId,
1746
+ isSuperAdmin: isSuperAdmin,
1747
+ includeClientScope: shouldScopeByClient
1748
+ })];
1749
+ case 18:
1750
+ _d = (_q.sent());
1751
+ _q.label = 19;
1752
+ case 19:
1753
+ probeDocs = _d;
1754
+ if (!probeDocs.length) return [3 /*break*/, 21];
1755
+ aliases = resolveFieldAliases(probeDocs, queryFields, schemaFields);
1756
+ if (!Object.keys(aliases).length) return [3 /*break*/, 21];
1647
1757
  fallbackMeta.queryFieldAliases = {
1648
1758
  aliases: aliases,
1649
1759
  attempted: true,
@@ -1655,18 +1765,18 @@ function executeAiAssistantMongoRead(payload, context) {
1655
1765
  return replaceFieldPathDeep(acc, from, to);
1656
1766
  }, executedQuery);
1657
1767
  return [4 /*yield*/, db.collection(collection).find(rewrittenQuery, findOptions).toArray()];
1658
- case 15:
1659
- fallbackDocs = _h.sent();
1768
+ case 20:
1769
+ fallbackDocs = _q.sent();
1660
1770
  if (fallbackDocs.length) {
1661
1771
  documents = fallbackDocs;
1662
1772
  executedQuery = rewrittenQuery;
1663
1773
  fallbackMeta.queryFieldAliases.used = true;
1664
1774
  }
1665
- _h.label = 16;
1666
- case 16:
1667
- if (!!documents.length) return [3 /*break*/, 21];
1668
- _d = probeDocs;
1669
- if (_d) return [3 /*break*/, 18];
1775
+ _q.label = 21;
1776
+ case 21:
1777
+ if (!!documents.length) return [3 /*break*/, 26];
1778
+ _e = probeDocs;
1779
+ if (_e) return [3 /*break*/, 23];
1670
1780
  return [4 /*yield*/, fetchAssistantProbeDocs({
1671
1781
  db: db,
1672
1782
  collection: collection,
@@ -1675,11 +1785,11 @@ function executeAiAssistantMongoRead(payload, context) {
1675
1785
  isSuperAdmin: isSuperAdmin,
1676
1786
  includeClientScope: shouldScopeByClient
1677
1787
  })];
1678
- case 17:
1679
- _d = (_h.sent());
1680
- _h.label = 18;
1681
- case 18:
1682
- probeDocs = _d;
1788
+ case 22:
1789
+ _e = (_q.sent());
1790
+ _q.label = 23;
1791
+ case 23:
1792
+ probeDocs = _e;
1683
1793
  return [4 /*yield*/, applyIdLookupFallbackToQuery({
1684
1794
  query: executedQuery,
1685
1795
  db: db,
@@ -1689,36 +1799,143 @@ function executeAiAssistantMongoRead(payload, context) {
1689
1799
  isSuperAdmin: isSuperAdmin,
1690
1800
  probeDocs: probeDocs || undefined
1691
1801
  })];
1692
- case 19:
1693
- idLookup = _h.sent();
1694
- if (!idLookup) return [3 /*break*/, 21];
1802
+ case 24:
1803
+ idLookup = _q.sent();
1804
+ if (!idLookup) return [3 /*break*/, 26];
1695
1805
  fallbackMeta.idLookup = __assign(__assign({}, idLookup.meta), { attempted: true, used: false });
1696
1806
  return [4 /*yield*/, db.collection(collection).find(idLookup.query, findOptions).toArray()];
1697
- case 20:
1698
- fallbackDocs = _h.sent();
1807
+ case 25:
1808
+ fallbackDocs = _q.sent();
1699
1809
  if (fallbackDocs.length) {
1700
1810
  documents = fallbackDocs;
1701
1811
  executedQuery = idLookup.query;
1702
1812
  fallbackMeta.idLookup.used = true;
1703
1813
  }
1704
- _h.label = 21;
1705
- case 21:
1814
+ _q.label = 26;
1815
+ case 26:
1816
+ if (!!documents.length) return [3 /*break*/, 29];
1817
+ return [4 /*yield*/, resolveBaseCollectionFromReport(db, dbName, collection)];
1818
+ case 27:
1819
+ baseCollection = _q.sent();
1820
+ if (!(baseCollection && baseCollection !== collection)) return [3 /*break*/, 29];
1821
+ fallbackPayload = __assign(__assign({}, input), { collection: baseCollection });
1822
+ return [4 /*yield*/, executeAiAssistantMongoRead(fallbackPayload, context)];
1823
+ case 28:
1824
+ fallbackResult = _q.sent();
1825
+ if (Array.isArray(fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.documents) && fallbackResult.documents.length) {
1826
+ if (isSuperAdmin && (fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.debug) && typeof fallbackResult.debug === 'object') {
1827
+ existingFallbacks = fallbackResult.debug.fallbacks && typeof fallbackResult.debug.fallbacks === 'object'
1828
+ ? fallbackResult.debug.fallbacks
1829
+ : {};
1830
+ fallbackResult.debug.fallbacks = __assign(__assign({}, existingFallbacks), { reportFallback: {
1831
+ from: collection,
1832
+ to: baseCollection,
1833
+ used: true
1834
+ } });
1835
+ }
1836
+ return [2 /*return*/, fallbackResult];
1837
+ }
1838
+ if (isSuperAdmin) {
1839
+ fallbackMeta.reportFallback = { from: collection, to: baseCollection, attempted: true, used: false };
1840
+ }
1841
+ _q.label = 29;
1842
+ case 29:
1843
+ if (!(!documents.length && isSuperAdmin)) return [3 /*break*/, 46];
1844
+ nameFields = collectMatchFieldsByCondition(executedQuery, function (field, condition) { return isRegexMatchCondition(condition)
1845
+ || (typeof condition === 'string' && shouldApplyAssistantNameRegex(field)); });
1846
+ dateFields = collectMatchFieldsByCondition(executedQuery, function (_field, condition) { return isDateCondition(condition); });
1847
+ diagnostics = {
1848
+ nameFields: nameFields.length ? nameFields : undefined,
1849
+ dateFields: dateFields.length ? dateFields : undefined
1850
+ };
1851
+ _q.label = 30;
1852
+ case 30:
1853
+ _q.trys.push([30, 35, , 36]);
1854
+ if (!nameFields.length) return [3 /*break*/, 32];
1855
+ queryNoName = stripMatchFields(executedQuery, nameFields);
1856
+ _f = diagnostics;
1857
+ return [4 /*yield*/, db.collection(collection).countDocuments(queryNoName, {
1858
+ readPreference: AI_ASSISTANT_READ_PREFERENCE
1859
+ })];
1860
+ case 31:
1861
+ _f.recentCount = _q.sent();
1862
+ _q.label = 32;
1863
+ case 32:
1864
+ if (!dateFields.length) return [3 /*break*/, 34];
1865
+ queryNoDate = stripMatchFields(executedQuery, dateFields);
1866
+ _g = diagnostics;
1867
+ return [4 /*yield*/, db.collection(collection).countDocuments(queryNoDate, {
1868
+ readPreference: AI_ASSISTANT_READ_PREFERENCE
1869
+ })];
1870
+ case 33:
1871
+ _g.nameMatchCount = _q.sent();
1872
+ _q.label = 34;
1873
+ case 34: return [3 /*break*/, 36];
1874
+ case 35:
1875
+ _h = _q.sent();
1876
+ return [3 /*break*/, 36];
1877
+ case 36:
1878
+ _q.trys.push([36, 39, , 40]);
1879
+ _j = probeDocs;
1880
+ if (_j) return [3 /*break*/, 38];
1881
+ return [4 /*yield*/, fetchAssistantProbeDocs({
1882
+ db: db,
1883
+ collection: collection,
1884
+ idClient: normalizedClient,
1885
+ idCustomer: customerId,
1886
+ isSuperAdmin: isSuperAdmin,
1887
+ includeClientScope: shouldScopeByClient
1888
+ })];
1889
+ case 37:
1890
+ _j = (_q.sent());
1891
+ _q.label = 38;
1892
+ case 38:
1893
+ probeDocs = _j;
1894
+ if (probeDocs.length && nameFields.length) {
1895
+ diagnostics.chemicalIdDetected = detectChemicalIdFromProbe(probeDocs, nameFields);
1896
+ }
1897
+ return [3 /*break*/, 40];
1898
+ case 39:
1899
+ _k = _q.sent();
1900
+ return [3 /*break*/, 40];
1901
+ case 40:
1902
+ _q.trys.push([40, 44, , 45]);
1903
+ return [4 /*yield*/, listAssistantCollections(db, dbName)];
1904
+ case 41:
1905
+ allCollections = _q.sent();
1906
+ base = stripVersionSuffix(collection.startsWith('report-') ? collection.slice('report-'.length) : collection);
1907
+ alt = collection.startsWith('report-') ? base : "report-".concat(base);
1908
+ if (!(alt && alt !== collection && allCollections.includes(alt))) return [3 /*break*/, 43];
1909
+ return [4 /*yield*/, db.collection(alt).countDocuments({}, { readPreference: AI_ASSISTANT_READ_PREFERENCE })];
1910
+ case 42:
1911
+ altCount = _q.sent();
1912
+ diagnostics.alternateCollection = alt;
1913
+ diagnostics.alternateCollectionCount = altCount;
1914
+ _q.label = 43;
1915
+ case 43: return [3 /*break*/, 45];
1916
+ case 44:
1917
+ _l = _q.sent();
1918
+ return [3 /*break*/, 45];
1919
+ case 45:
1920
+ fallbackMeta.zeroDiagnostics = diagnostics;
1921
+ _q.label = 46;
1922
+ case 46:
1706
1923
  total = null;
1707
- if (!normalized.includeTotal) return [3 /*break*/, 23];
1924
+ if (!normalized.includeTotal) return [3 /*break*/, 48];
1708
1925
  return [4 /*yield*/, db.collection(collection).countDocuments(executedQuery, { readPreference: AI_ASSISTANT_READ_PREFERENCE })];
1709
- case 22:
1710
- total = _h.sent();
1711
- _h.label = 23;
1712
- case 23:
1926
+ case 47:
1927
+ total = _q.sent();
1928
+ _q.label = 48;
1929
+ case 48:
1713
1930
  sanitizedDocuments = isSuperAdmin
1714
1931
  ? documents
1715
1932
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
1716
1933
  requestedFields = resolveProjectionRequestedFields(findOptions.projection);
1717
- if (!(sanitizedDocuments.length && requestedFields.length)) return [3 /*break*/, 27];
1934
+ if (!(sanitizedDocuments.length && requestedFields.length)) return [3 /*break*/, 52];
1718
1935
  missingFields = requestedFields.filter(function (field) { return !hasNonEmptyValue(sanitizedDocuments, field, { treatObjectLikeAsEmpty: true }); });
1719
- if (!missingFields.length) return [3 /*break*/, 27];
1720
- _e = probeDocs;
1721
- if (_e) return [3 /*break*/, 25];
1936
+ if (!missingFields.length) return [3 /*break*/, 52];
1937
+ _m = probeDocs;
1938
+ if (_m) return [3 /*break*/, 50];
1722
1939
  return [4 /*yield*/, fetchAssistantProbeDocs({
1723
1940
  db: db,
1724
1941
  collection: collection,
@@ -1727,26 +1944,26 @@ function executeAiAssistantMongoRead(payload, context) {
1727
1944
  isSuperAdmin: isSuperAdmin,
1728
1945
  includeClientScope: shouldScopeByClient
1729
1946
  })];
1730
- case 24:
1731
- _e = (_h.sent());
1732
- _h.label = 25;
1733
- case 25:
1734
- probeDocs = _e;
1735
- if (!probeDocs.length) return [3 /*break*/, 27];
1736
- projectionAliases = resolveFieldAliases(probeDocs, missingFields);
1737
- if (!Object.keys(projectionAliases).length) return [3 /*break*/, 27];
1947
+ case 49:
1948
+ _m = (_q.sent());
1949
+ _q.label = 50;
1950
+ case 50:
1951
+ probeDocs = _m;
1952
+ if (!probeDocs.length) return [3 /*break*/, 52];
1953
+ projectionAliases = resolveFieldAliases(probeDocs, missingFields, schemaFields);
1954
+ if (!Object.keys(projectionAliases).length) return [3 /*break*/, 52];
1738
1955
  fallbackMeta.projectionAliases = {
1739
1956
  aliases: projectionAliases,
1740
1957
  attempted: true,
1741
1958
  used: false
1742
1959
  };
1743
1960
  expandedProjection = expandProjectionWithAliases(findOptions.projection, projectionAliases);
1744
- if (!(expandedProjection && expandedProjection !== findOptions.projection)) return [3 /*break*/, 27];
1961
+ if (!(expandedProjection && expandedProjection !== findOptions.projection)) return [3 /*break*/, 52];
1745
1962
  findOptions = __assign(__assign({}, findOptions), { projection: expandedProjection });
1746
1963
  normalized.findOptions.projection = expandedProjection;
1747
1964
  return [4 /*yield*/, db.collection(collection).find(executedQuery, findOptions).toArray()];
1748
- case 26:
1749
- refreshedDocs = _h.sent();
1965
+ case 51:
1966
+ refreshedDocs = _q.sent();
1750
1967
  if (refreshedDocs.length) {
1751
1968
  documents = refreshedDocs;
1752
1969
  sanitizedDocuments = isSuperAdmin
@@ -1754,13 +1971,30 @@ function executeAiAssistantMongoRead(payload, context) {
1754
1971
  : refreshedDocs.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
1755
1972
  fallbackMeta.projectionAliases.used = true;
1756
1973
  }
1757
- _h.label = 27;
1758
- case 27:
1759
- includeIds = ((_g = input.options) === null || _g === void 0 ? void 0 : _g.includeIds) === true;
1760
- fieldAliases = resolveFieldAliases(sanitizedDocuments, requestedFields);
1974
+ _q.label = 52;
1975
+ case 52:
1976
+ includeIds = ((_p = input.options) === null || _p === void 0 ? void 0 : _p.includeIds) === true;
1977
+ fieldAliases = resolveFieldAliases(sanitizedDocuments, requestedFields, schemaFields);
1761
1978
  displayDocs = Object.keys(fieldAliases).length
1762
1979
  ? applyFieldAliasesForDisplay(sanitizedDocuments, fieldAliases)
1763
1980
  : sanitizedDocuments;
1981
+ return [4 /*yield*/, applyIdLookupDisplayEnrichment({
1982
+ docs: displayDocs,
1983
+ collection: collection,
1984
+ db: db,
1985
+ dbName: dbName,
1986
+ idClient: normalizedClient,
1987
+ idCustomer: customerId,
1988
+ isSuperAdmin: isSuperAdmin
1989
+ })];
1990
+ case 53:
1991
+ idLookupDisplay = _q.sent();
1992
+ if (idLookupDisplay === null || idLookupDisplay === void 0 ? void 0 : idLookupDisplay.docs) {
1993
+ displayDocs = idLookupDisplay.docs;
1994
+ }
1995
+ if (idLookupDisplay === null || idLookupDisplay === void 0 ? void 0 : idLookupDisplay.meta) {
1996
+ fallbackMeta.idDisplayLookup = idLookupDisplay.meta;
1997
+ }
1764
1998
  priorityFields = requestedFields.length
1765
1999
  ? __spreadArray(__spreadArray([], __read(requestedFields), false), __read(AI_ASSISTANT_DISPLAY_PRIORITY_FIELDS), false) : AI_ASSISTANT_DISPLAY_PRIORITY_FIELDS;
1766
2000
  display = buildDisplayTable(displayDocs, {
@@ -1797,10 +2031,10 @@ function executeAiAssistantMongoRead(payload, context) {
1797
2031
  }
1798
2032
  function executeAiAssistantMongoAggregate(payload, context) {
1799
2033
  return __awaiter(this, void 0, void 0, function () {
1800
- var input, rawCollection, dbName, db, collectionResolution, collection, _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, matchFields_1, _c, aliases, rewrittenPipeline, fallbackDocs, _loop_1, i, state_1, sanitizedDocuments, includeIds, display;
1801
- var _d, _e;
1802
- return __generator(this, function (_f) {
1803
- switch (_f.label) {
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) {
1804
2038
  case 0:
1805
2039
  input = payload || {};
1806
2040
  rawCollection = normalizeOptionalString(input.collection);
@@ -1811,15 +2045,16 @@ function executeAiAssistantMongoAggregate(payload, context) {
1811
2045
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1812
2046
  return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
1813
2047
  case 1:
1814
- collectionResolution = _f.sent();
2048
+ collectionResolution = _o.sent();
1815
2049
  collection = collectionResolution.name || rawCollection;
2050
+ schemaFields = getCollectionSchemaFieldNames(collection);
1816
2051
  return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
1817
2052
  case 2:
1818
- _a = _f.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
2053
+ _a = _o.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1819
2054
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
1820
2055
  throw new Error('AI assistant mongo aggregate: Access denied.');
1821
2056
  }
1822
- customerId = normalizeOptionalString((_d = user === null || user === void 0 ? void 0 : user.other) === null || _d === void 0 ? void 0 : _d.id_customer);
2057
+ customerId = normalizeOptionalString((_l = user === null || user === void 0 ? void 0 : user.other) === null || _l === void 0 ? void 0 : _l.id_customer);
1823
2058
  fallbackMeta = {};
1824
2059
  baseQuery = normalizeMongoQuery(input.query);
1825
2060
  if (!isSuperAdmin && customerId) {
@@ -1844,11 +2079,11 @@ function executeAiAssistantMongoAggregate(payload, context) {
1844
2079
  if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 4];
1845
2080
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
1846
2081
  case 3:
1847
- _b = _f.sent();
2082
+ _b = _o.sent();
1848
2083
  return [3 /*break*/, 5];
1849
2084
  case 4:
1850
2085
  _b = false;
1851
- _f.label = 5;
2086
+ _o.label = 5;
1852
2087
  case 5:
1853
2088
  shouldScopeByClient = _b;
1854
2089
  clientScopedQuery = shouldScopeByClient
@@ -1878,7 +2113,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
1878
2113
  .aggregate(limitedPipeline, aggregateOptions)
1879
2114
  .toArray()];
1880
2115
  case 6:
1881
- documents = _f.sent();
2116
+ documents = _o.sent();
1882
2117
  executedPipeline = limitedPipeline;
1883
2118
  probeDocs = null;
1884
2119
  if (!(!documents.length && dateField)) return [3 /*break*/, 10];
@@ -1891,13 +2126,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
1891
2126
  .aggregate(fallbackPipeline, aggregateOptions)
1892
2127
  .toArray()];
1893
2128
  case 7:
1894
- fallbackDocs = _f.sent();
2129
+ fallbackDocs = _o.sent();
1895
2130
  if (fallbackDocs.length) {
1896
2131
  documents = fallbackDocs;
1897
2132
  executedPipeline = fallbackPipeline;
1898
2133
  fallbackMeta.dateField.used = true;
1899
2134
  }
1900
- _f.label = 8;
2135
+ _o.label = 8;
1901
2136
  case 8:
1902
2137
  if (!(!documents.length && dateField !== 'createdAt')) return [3 /*break*/, 10];
1903
2138
  createdFallback = { from: dateField, to: 'createdAt', attempted: true, used: false };
@@ -1908,13 +2143,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
1908
2143
  .aggregate(createdPipeline, aggregateOptions)
1909
2144
  .toArray()];
1910
2145
  case 9:
1911
- createdDocs = _f.sent();
2146
+ createdDocs = _o.sent();
1912
2147
  if (createdDocs.length) {
1913
2148
  documents = createdDocs;
1914
2149
  executedPipeline = createdPipeline;
1915
2150
  fallbackMeta.dateFieldCreatedAt.used = true;
1916
2151
  }
1917
- _f.label = 10;
2152
+ _o.label = 10;
1918
2153
  case 10:
1919
2154
  if (!!documents.length) return [3 /*break*/, 12];
1920
2155
  expanded = expandAggregateDateMatchFallback(executedPipeline);
@@ -1929,13 +2164,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
1929
2164
  .aggregate(expanded.pipeline, aggregateOptions)
1930
2165
  .toArray()];
1931
2166
  case 11:
1932
- expandedDocs = _f.sent();
2167
+ expandedDocs = _o.sent();
1933
2168
  if (expandedDocs.length) {
1934
2169
  documents = expandedDocs;
1935
2170
  executedPipeline = expanded.pipeline;
1936
2171
  fallbackMeta.dateFieldsExpanded.used = true;
1937
2172
  }
1938
- _f.label = 12;
2173
+ _o.label = 12;
1939
2174
  case 12:
1940
2175
  if (!!documents.length) return [3 /*break*/, 16];
1941
2176
  completionFallback = resolveAggregateCompletionFallback(executedPipeline);
@@ -1954,13 +2189,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
1954
2189
  .aggregate(fallbackPipeline, aggregateOptions)
1955
2190
  .toArray()];
1956
2191
  case 13:
1957
- fallbackDocs = _f.sent();
2192
+ fallbackDocs = _o.sent();
1958
2193
  if (fallbackDocs.length) {
1959
2194
  documents = fallbackDocs;
1960
2195
  executedPipeline = fallbackPipeline;
1961
2196
  fallbackMeta.completion.used = true;
1962
2197
  }
1963
- _f.label = 14;
2198
+ _o.label = 14;
1964
2199
  case 14:
1965
2200
  if (!!documents.length) return [3 /*break*/, 16];
1966
2201
  completionExprFallback = resolveAggregateCompletionExprFallback(executedPipeline);
@@ -1979,13 +2214,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
1979
2214
  .aggregate(fallbackPipeline, aggregateOptions)
1980
2215
  .toArray()];
1981
2216
  case 15:
1982
- fallbackDocs = _f.sent();
2217
+ fallbackDocs = _o.sent();
1983
2218
  if (fallbackDocs.length) {
1984
2219
  documents = fallbackDocs;
1985
2220
  executedPipeline = fallbackPipeline;
1986
2221
  fallbackMeta.completion.used = true;
1987
2222
  }
1988
- _f.label = 16;
2223
+ _o.label = 16;
1989
2224
  case 16:
1990
2225
  if (!(documents.length <= 1)) return [3 /*break*/, 18];
1991
2226
  unwindFallback = resolveAggregateUnwindFallback(executedPipeline);
@@ -1997,13 +2232,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
1997
2232
  .aggregate(fallbackPipeline, aggregateOptions)
1998
2233
  .toArray()];
1999
2234
  case 17:
2000
- fallbackDocs = _f.sent();
2235
+ fallbackDocs = _o.sent();
2001
2236
  if (fallbackDocs.length > documents.length) {
2002
2237
  documents = fallbackDocs;
2003
2238
  executedPipeline = fallbackPipeline;
2004
2239
  fallbackMeta.unwind.used = true;
2005
2240
  }
2006
- _f.label = 18;
2241
+ _o.label = 18;
2007
2242
  case 18:
2008
2243
  if (!!documents.length) return [3 /*break*/, 20];
2009
2244
  nameFallback = resolveAggregateNameMatchFallback(executedPipeline);
@@ -2020,15 +2255,87 @@ function executeAiAssistantMongoAggregate(payload, context) {
2020
2255
  .aggregate(fallbackPipeline, aggregateOptions)
2021
2256
  .toArray()];
2022
2257
  case 19:
2023
- fallbackDocs = _f.sent();
2258
+ fallbackDocs = _o.sent();
2024
2259
  if (fallbackDocs.length) {
2025
2260
  documents = fallbackDocs;
2026
2261
  executedPipeline = fallbackPipeline;
2027
2262
  fallbackMeta.nameMatch.used = true;
2028
2263
  }
2029
- _f.label = 20;
2264
+ _o.label = 20;
2030
2265
  case 20:
2031
- if (!!documents.length) return [3 /*break*/, 24];
2266
+ if (!!documents.length) return [3 /*break*/, 26];
2267
+ _c = probeDocs;
2268
+ if (_c) return [3 /*break*/, 22];
2269
+ return [4 /*yield*/, fetchAssistantProbeDocs({
2270
+ db: db,
2271
+ collection: collection,
2272
+ idClient: normalizedClient,
2273
+ idCustomer: customerId,
2274
+ isSuperAdmin: isSuperAdmin,
2275
+ includeClientScope: shouldScopeByClient
2276
+ })];
2277
+ case 21:
2278
+ _c = (_o.sent());
2279
+ _o.label = 22;
2280
+ case 22:
2281
+ probeDocs = _c;
2282
+ _loop_1 = function (i) {
2283
+ var stage, chemicalLookup, rewrittenPipeline, fallbackDocs;
2284
+ return __generator(this, function (_p) {
2285
+ switch (_p.label) {
2286
+ case 0:
2287
+ stage = executedPipeline[i];
2288
+ if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
2289
+ return [2 /*return*/, "continue"];
2290
+ }
2291
+ return [4 /*yield*/, applyChemicalNameLookupFallbackToQuery({
2292
+ query: stage.$match,
2293
+ db: db,
2294
+ dbName: dbName,
2295
+ idClient: normalizedClient,
2296
+ idCustomer: customerId,
2297
+ isSuperAdmin: isSuperAdmin,
2298
+ probeDocs: probeDocs || undefined
2299
+ })];
2300
+ case 1:
2301
+ chemicalLookup = _p.sent();
2302
+ if (!chemicalLookup) {
2303
+ return [2 /*return*/, "continue"];
2304
+ }
2305
+ fallbackMeta.chemicalLookup = __assign(__assign({}, chemicalLookup.meta), { attempted: true, used: false, stage: i });
2306
+ rewrittenPipeline = executedPipeline.map(function (current, index) { return (index === i ? { $match: chemicalLookup.query } : current); });
2307
+ if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 3];
2308
+ return [4 /*yield*/, db.collection(collection)
2309
+ .aggregate(rewrittenPipeline, aggregateOptions)
2310
+ .toArray()];
2311
+ case 2:
2312
+ fallbackDocs = _p.sent();
2313
+ if (fallbackDocs.length) {
2314
+ documents = fallbackDocs;
2315
+ executedPipeline = rewrittenPipeline;
2316
+ fallbackMeta.chemicalLookup.used = true;
2317
+ return [2 /*return*/, "break"];
2318
+ }
2319
+ _p.label = 3;
2320
+ case 3: return [2 /*return*/];
2321
+ }
2322
+ });
2323
+ };
2324
+ i = 0;
2325
+ _o.label = 23;
2326
+ case 23:
2327
+ if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 26];
2328
+ return [5 /*yield**/, _loop_1(i)];
2329
+ case 24:
2330
+ state_1 = _o.sent();
2331
+ if (state_1 === "break")
2332
+ return [3 /*break*/, 26];
2333
+ _o.label = 25;
2334
+ case 25:
2335
+ i += 1;
2336
+ return [3 /*break*/, 23];
2337
+ case 26:
2338
+ if (!!documents.length) return [3 /*break*/, 30];
2032
2339
  matchFields_1 = new Set();
2033
2340
  (executedPipeline || []).forEach(function (stage) {
2034
2341
  if (stage && typeof stage === 'object' && stage.$match && typeof stage.$match === 'object') {
@@ -2037,9 +2344,9 @@ function executeAiAssistantMongoAggregate(payload, context) {
2037
2344
  .forEach(function (field) { return matchFields_1.add(field); });
2038
2345
  }
2039
2346
  });
2040
- if (!matchFields_1.size) return [3 /*break*/, 24];
2041
- _c = probeDocs;
2042
- if (_c) return [3 /*break*/, 22];
2347
+ if (!matchFields_1.size) return [3 /*break*/, 30];
2348
+ _d = probeDocs;
2349
+ if (_d) return [3 /*break*/, 28];
2043
2350
  return [4 /*yield*/, fetchAssistantProbeDocs({
2044
2351
  db: db,
2045
2352
  collection: collection,
@@ -2048,14 +2355,14 @@ function executeAiAssistantMongoAggregate(payload, context) {
2048
2355
  isSuperAdmin: isSuperAdmin,
2049
2356
  includeClientScope: shouldScopeByClient
2050
2357
  })];
2051
- case 21:
2052
- _c = (_f.sent());
2053
- _f.label = 22;
2054
- case 22:
2055
- probeDocs = _c;
2056
- if (!probeDocs.length) return [3 /*break*/, 24];
2057
- aliases = resolveFieldAliases(probeDocs, Array.from(matchFields_1));
2058
- if (!Object.keys(aliases).length) return [3 /*break*/, 24];
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];
2364
+ aliases = resolveFieldAliases(probeDocs, Array.from(matchFields_1), schemaFields);
2365
+ if (!Object.keys(aliases).length) return [3 /*break*/, 30];
2059
2366
  fallbackMeta.queryFieldAliases = {
2060
2367
  aliases: aliases,
2061
2368
  attempted: true,
@@ -2066,31 +2373,31 @@ function executeAiAssistantMongoAggregate(payload, context) {
2066
2373
  var _b = __read(_a, 2), from = _b[0], to = _b[1];
2067
2374
  return replaceFieldPathDeep(acc, from, to);
2068
2375
  }, executedPipeline);
2069
- if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 24];
2376
+ if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 30];
2070
2377
  return [4 /*yield*/, db.collection(collection)
2071
2378
  .aggregate(rewrittenPipeline, aggregateOptions)
2072
2379
  .toArray()];
2073
- case 23:
2074
- fallbackDocs = _f.sent();
2380
+ case 29:
2381
+ fallbackDocs = _o.sent();
2075
2382
  if (fallbackDocs.length) {
2076
2383
  documents = fallbackDocs;
2077
2384
  executedPipeline = rewrittenPipeline;
2078
2385
  fallbackMeta.queryFieldAliases.used = true;
2079
2386
  }
2080
- _f.label = 24;
2081
- case 24:
2082
- if (!!documents.length) return [3 /*break*/, 28];
2083
- _loop_1 = function (i) {
2084
- var stage, _g, idLookup, rewrittenPipeline, fallbackDocs;
2085
- return __generator(this, function (_h) {
2086
- switch (_h.label) {
2387
+ _o.label = 30;
2388
+ case 30:
2389
+ if (!!documents.length) return [3 /*break*/, 34];
2390
+ _loop_2 = function (i) {
2391
+ var stage, _q, idLookup, rewrittenPipeline, fallbackDocs;
2392
+ return __generator(this, function (_r) {
2393
+ switch (_r.label) {
2087
2394
  case 0:
2088
2395
  stage = executedPipeline[i];
2089
2396
  if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
2090
2397
  return [2 /*return*/, "continue"];
2091
2398
  }
2092
- _g = probeDocs;
2093
- if (_g) return [3 /*break*/, 2];
2399
+ _q = probeDocs;
2400
+ if (_q) return [3 /*break*/, 2];
2094
2401
  return [4 /*yield*/, fetchAssistantProbeDocs({
2095
2402
  db: db,
2096
2403
  collection: collection,
@@ -2100,10 +2407,10 @@ function executeAiAssistantMongoAggregate(payload, context) {
2100
2407
  includeClientScope: shouldScopeByClient
2101
2408
  })];
2102
2409
  case 1:
2103
- _g = (_h.sent());
2104
- _h.label = 2;
2410
+ _q = (_r.sent());
2411
+ _r.label = 2;
2105
2412
  case 2:
2106
- probeDocs = _g;
2413
+ probeDocs = _q;
2107
2414
  return [4 /*yield*/, applyIdLookupFallbackToQuery({
2108
2415
  query: stage.$match,
2109
2416
  db: db,
@@ -2114,7 +2421,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
2114
2421
  probeDocs: probeDocs || undefined
2115
2422
  })];
2116
2423
  case 3:
2117
- idLookup = _h.sent();
2424
+ idLookup = _r.sent();
2118
2425
  if (!idLookup) {
2119
2426
  return [2 /*return*/, "continue"];
2120
2427
  }
@@ -2125,37 +2432,164 @@ function executeAiAssistantMongoAggregate(payload, context) {
2125
2432
  .aggregate(rewrittenPipeline, aggregateOptions)
2126
2433
  .toArray()];
2127
2434
  case 4:
2128
- fallbackDocs = _h.sent();
2435
+ fallbackDocs = _r.sent();
2129
2436
  if (fallbackDocs.length) {
2130
2437
  documents = fallbackDocs;
2131
2438
  executedPipeline = rewrittenPipeline;
2132
2439
  fallbackMeta.idLookup.used = true;
2133
2440
  return [2 /*return*/, "break"];
2134
2441
  }
2135
- _h.label = 5;
2442
+ _r.label = 5;
2136
2443
  case 5: return [2 /*return*/];
2137
2444
  }
2138
2445
  });
2139
2446
  };
2140
2447
  i = 0;
2141
- _f.label = 25;
2142
- case 25:
2143
- if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 28];
2144
- return [5 /*yield**/, _loop_1(i)];
2145
- case 26:
2146
- state_1 = _f.sent();
2147
- if (state_1 === "break")
2148
- return [3 /*break*/, 28];
2149
- _f.label = 27;
2150
- case 27:
2448
+ _o.label = 31;
2449
+ case 31:
2450
+ if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 34];
2451
+ return [5 /*yield**/, _loop_2(i)];
2452
+ case 32:
2453
+ state_2 = _o.sent();
2454
+ if (state_2 === "break")
2455
+ return [3 /*break*/, 34];
2456
+ _o.label = 33;
2457
+ case 33:
2151
2458
  i += 1;
2152
- return [3 /*break*/, 25];
2153
- case 28:
2459
+ return [3 /*break*/, 31];
2460
+ case 34:
2461
+ if (!!documents.length) return [3 /*break*/, 37];
2462
+ return [4 /*yield*/, resolveBaseCollectionFromReport(db, dbName, collection)];
2463
+ case 35:
2464
+ baseCollection = _o.sent();
2465
+ if (!(baseCollection && baseCollection !== collection)) return [3 /*break*/, 37];
2466
+ fallbackPayload = __assign(__assign({}, input), { collection: baseCollection });
2467
+ return [4 /*yield*/, executeAiAssistantMongoAggregate(fallbackPayload, context)];
2468
+ case 36:
2469
+ fallbackResult = _o.sent();
2470
+ if (Array.isArray(fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.documents) && fallbackResult.documents.length) {
2471
+ if (isSuperAdmin && (fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.debug) && typeof fallbackResult.debug === 'object') {
2472
+ existingFallbacks = fallbackResult.debug.fallbacks && typeof fallbackResult.debug.fallbacks === 'object'
2473
+ ? fallbackResult.debug.fallbacks
2474
+ : {};
2475
+ fallbackResult.debug.fallbacks = __assign(__assign({}, existingFallbacks), { reportFallback: {
2476
+ from: collection,
2477
+ to: baseCollection,
2478
+ used: true
2479
+ } });
2480
+ }
2481
+ return [2 /*return*/, fallbackResult];
2482
+ }
2483
+ if (isSuperAdmin) {
2484
+ fallbackMeta.reportFallback = { from: collection, to: baseCollection, attempted: true, used: false };
2485
+ }
2486
+ _o.label = 37;
2487
+ case 37:
2488
+ if (!(!documents.length && isSuperAdmin)) return [3 /*break*/, 54];
2489
+ matchStages = (executedPipeline || []).filter(function (stage) { return stage && typeof stage === 'object' && stage.$match && typeof stage.$match === 'object'; });
2490
+ diagnostics = {};
2491
+ if (!matchStages.length) return [3 /*break*/, 54];
2492
+ combinedMatch = matchStages.reduce(function (acc, stage) { return ({ $and: __spreadArray(__spreadArray([], __read((acc.$and || [])), false), [stage.$match], false) }); }, { $and: [] });
2493
+ nameFields = collectMatchFieldsByCondition(combinedMatch, function (field, condition) { return isRegexMatchCondition(condition)
2494
+ || (typeof condition === 'string' && shouldApplyAssistantNameRegex(field)); });
2495
+ dateFields = collectMatchFieldsByCondition(combinedMatch, function (_field, condition) { return isDateCondition(condition); });
2496
+ diagnostics.nameFields = nameFields.length ? nameFields : undefined;
2497
+ 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];
2502
+ queryNoName = stripMatchFields(combinedMatch, nameFields);
2503
+ _e = diagnostics;
2504
+ return [4 /*yield*/, db.collection(collection).countDocuments(queryNoName, {
2505
+ readPreference: AI_ASSISTANT_READ_PREFERENCE
2506
+ })];
2507
+ case 39:
2508
+ _e.recentCount = _o.sent();
2509
+ _o.label = 40;
2510
+ case 40:
2511
+ if (!dateFields.length) return [3 /*break*/, 42];
2512
+ queryNoDate = stripMatchFields(combinedMatch, dateFields);
2513
+ _f = diagnostics;
2514
+ return [4 /*yield*/, db.collection(collection).countDocuments(queryNoDate, {
2515
+ readPreference: AI_ASSISTANT_READ_PREFERENCE
2516
+ })];
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];
2528
+ return [4 /*yield*/, fetchAssistantProbeDocs({
2529
+ db: db,
2530
+ collection: collection,
2531
+ idClient: normalizedClient,
2532
+ idCustomer: customerId,
2533
+ isSuperAdmin: isSuperAdmin,
2534
+ includeClientScope: shouldScopeByClient
2535
+ })];
2536
+ case 45:
2537
+ _h = (_o.sent());
2538
+ _o.label = 46;
2539
+ case 46:
2540
+ probeDocs = _h;
2541
+ if (probeDocs.length && nameFields.length) {
2542
+ diagnostics.chemicalIdDetected = detectChemicalIdFromProbe(probeDocs, nameFields);
2543
+ }
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]);
2550
+ return [4 /*yield*/, listAssistantCollections(db, dbName)];
2551
+ case 49:
2552
+ allCollections = _o.sent();
2553
+ base = stripVersionSuffix(collection.startsWith('report-') ? collection.slice('report-'.length) : collection);
2554
+ alt = collection.startsWith('report-') ? base : "report-".concat(base);
2555
+ if (!(alt && alt !== collection && allCollections.includes(alt))) return [3 /*break*/, 51];
2556
+ return [4 /*yield*/, db.collection(alt).countDocuments({}, { readPreference: AI_ASSISTANT_READ_PREFERENCE })];
2557
+ case 50:
2558
+ altCount = _o.sent();
2559
+ diagnostics.alternateCollection = alt;
2560
+ 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:
2567
+ fallbackMeta.zeroDiagnostics = diagnostics;
2568
+ _o.label = 54;
2569
+ case 54:
2154
2570
  sanitizedDocuments = isSuperAdmin
2155
2571
  ? documents
2156
2572
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
2157
- includeIds = ((_e = input.options) === null || _e === void 0 ? void 0 : _e.includeIds) === true;
2158
- display = buildDisplayTable(sanitizedDocuments, {
2573
+ includeIds = ((_m = input.options) === null || _m === void 0 ? void 0 : _m.includeIds) === true;
2574
+ displayDocs = sanitizedDocuments;
2575
+ return [4 /*yield*/, applyIdLookupDisplayEnrichment({
2576
+ docs: displayDocs,
2577
+ collection: collection,
2578
+ db: db,
2579
+ dbName: dbName,
2580
+ idClient: normalizedClient,
2581
+ idCustomer: customerId,
2582
+ isSuperAdmin: isSuperAdmin
2583
+ })];
2584
+ case 55:
2585
+ idLookupDisplay = _o.sent();
2586
+ if (idLookupDisplay === null || idLookupDisplay === void 0 ? void 0 : idLookupDisplay.docs) {
2587
+ displayDocs = idLookupDisplay.docs;
2588
+ }
2589
+ if (idLookupDisplay === null || idLookupDisplay === void 0 ? void 0 : idLookupDisplay.meta) {
2590
+ fallbackMeta.idDisplayLookup = idLookupDisplay.meta;
2591
+ }
2592
+ display = buildDisplayTable(displayDocs, {
2159
2593
  includeIds: includeIds,
2160
2594
  maxColumns: AI_ASSISTANT_DISPLAY_MAX_COLUMNS,
2161
2595
  maxRows: normalizedOptions.limit || sanitizedDocuments.length,
@@ -2329,7 +2763,7 @@ function buildAssistantToolFallbackResponse(result) {
2329
2763
  return lines.join('\n').trim();
2330
2764
  }
2331
2765
  function buildAssistantDebugPayload(params) {
2332
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
2766
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3;
2333
2767
  var notes = [];
2334
2768
  if (params.dataQuestion) {
2335
2769
  notes.push('Detected a data request; tool call required.');
@@ -2426,15 +2860,34 @@ function buildAssistantDebugPayload(params) {
2426
2860
  : fallbackInfo.nameMatch.field;
2427
2861
  notes.push("Expanded name match fields: ".concat(fields, "."));
2428
2862
  }
2429
- if ((_t = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idLookup) === null || _t === void 0 ? void 0 : _t.used) {
2863
+ if ((_t = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.chemicalLookup) === null || _t === void 0 ? void 0 : _t.used) {
2864
+ var collection = fallbackInfo.chemicalLookup.collection ? " in ".concat(fallbackInfo.chemicalLookup.collection) : '';
2865
+ notes.push("Applied chemical lookup".concat(collection, "."));
2866
+ }
2867
+ if ((_u = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.reportFallback) === null || _u === void 0 ? void 0 : _u.used) {
2868
+ var from = fallbackInfo.reportFallback.from || 'report';
2869
+ var to = fallbackInfo.reportFallback.to || 'base';
2870
+ notes.push("Report fallback: ".concat(from, " -> ").concat(to, "."));
2871
+ }
2872
+ if ((_v = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idLookup) === null || _v === void 0 ? void 0 : _v.used) {
2430
2873
  var field = fallbackInfo.idLookup.field || 'id';
2431
2874
  var strategy = fallbackInfo.idLookup.strategy || 'lookup';
2432
2875
  var collection = fallbackInfo.idLookup.collection ? " in ".concat(fallbackInfo.idLookup.collection) : '';
2433
2876
  var detail = fallbackInfo.idLookup.nameField ? " via ".concat(fallbackInfo.idLookup.nameField) : '';
2434
2877
  notes.push("Resolved ".concat(field, " by ").concat(strategy).concat(collection).concat(detail, "."));
2435
2878
  }
2879
+ if ((_w = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idDisplayLookup) === null || _w === void 0 ? void 0 : _w.used) {
2880
+ var lookups = Array.isArray(fallbackInfo.idDisplayLookup.lookups)
2881
+ ? fallbackInfo.idDisplayLookup.lookups
2882
+ : [];
2883
+ var summary = lookups
2884
+ .map(function (entry) { return (entry === null || entry === void 0 ? void 0 : entry.displayField) || (entry === null || entry === void 0 ? void 0 : entry.field); })
2885
+ .filter(Boolean)
2886
+ .join(', ');
2887
+ notes.push(summary ? "Resolved id lookups for display: ".concat(summary, ".") : 'Resolved id lookups for display.');
2888
+ }
2436
2889
  if (params.toolError) {
2437
- var errorMessage = ((_u = params.toolError) === null || _u === void 0 ? void 0 : _u.message) || String(params.toolError || '');
2890
+ var errorMessage = ((_x = params.toolError) === null || _x === void 0 ? void 0 : _x.message) || String(params.toolError || '');
2438
2891
  if (errorMessage) {
2439
2892
  notes.push("Tool error: ".concat(errorMessage));
2440
2893
  }
@@ -2455,13 +2908,13 @@ function buildAssistantDebugPayload(params) {
2455
2908
  collectionResolved: resolvedCollection || undefined,
2456
2909
  collectionMatched: matchedCollection,
2457
2910
  collectionCandidates: candidateCollections.length ? candidateCollections : undefined,
2458
- collectionScore: typeof ((_v = params.toolResponseDebug) === null || _v === void 0 ? void 0 : _v.collectionScore) === 'number'
2911
+ collectionScore: typeof ((_y = params.toolResponseDebug) === null || _y === void 0 ? void 0 : _y.collectionScore) === 'number'
2459
2912
  ? params.toolResponseDebug.collectionScore
2460
2913
  : undefined,
2461
- query: ((_w = params.toolResponseDebug) === null || _w === void 0 ? void 0 : _w.query) || undefined,
2462
- pipeline: ((_x = params.toolResponseDebug) === null || _x === void 0 ? void 0 : _x.executedPipeline) || ((_y = params.toolResponseDebug) === null || _y === void 0 ? void 0 : _y.originalPipeline) || undefined,
2463
- options: ((_z = params.toolResponseDebug) === null || _z === void 0 ? void 0 : _z.options) || undefined,
2464
- fallbacks: ((_0 = params.toolResponseDebug) === null || _0 === void 0 ? void 0 : _0.fallbacks) || undefined,
2914
+ query: ((_z = params.toolResponseDebug) === null || _z === void 0 ? void 0 : _z.query) || undefined,
2915
+ pipeline: ((_0 = params.toolResponseDebug) === null || _0 === void 0 ? void 0 : _0.executedPipeline) || ((_1 = params.toolResponseDebug) === null || _1 === void 0 ? void 0 : _1.originalPipeline) || undefined,
2916
+ options: ((_2 = params.toolResponseDebug) === null || _2 === void 0 ? void 0 : _2.options) || undefined,
2917
+ fallbacks: ((_3 = params.toolResponseDebug) === null || _3 === void 0 ? void 0 : _3.fallbacks) || undefined,
2465
2918
  notes: notes
2466
2919
  };
2467
2920
  if (params.trace && typeof params.trace === 'object') {
@@ -2728,6 +3181,93 @@ function tokenizeFieldKey(value) {
2728
3181
  function normalizeFieldMatchKey(value) {
2729
3182
  return tokenizeFieldKey(value).join('');
2730
3183
  }
3184
+ function getCollectionSchemaFieldNames(collectionName) {
3185
+ var _a;
3186
+ var normalized = normalizeOptionalString(collectionName);
3187
+ if (!normalized) {
3188
+ return [];
3189
+ }
3190
+ try {
3191
+ var collection = (_a = resolveio_server_app_1.ResolveIOServer.getMongoManager()) === null || _a === void 0 ? void 0 : _a.collection(normalized);
3192
+ var schema = collection === null || collection === void 0 ? void 0 : collection.simplschema;
3193
+ var fields_1 = schema && typeof schema.schema === 'function'
3194
+ ? Object.keys(schema.schema())
3195
+ : [];
3196
+ var rbSchema = collection === null || collection === void 0 ? void 0 : collection.rbSchema;
3197
+ if (rbSchema && typeof rbSchema === 'object') {
3198
+ Object.keys(rbSchema).forEach(function (field) {
3199
+ if (field && !fields_1.includes(field)) {
3200
+ fields_1.push(field);
3201
+ }
3202
+ });
3203
+ }
3204
+ return fields_1;
3205
+ }
3206
+ catch (_b) {
3207
+ return [];
3208
+ }
3209
+ }
3210
+ function getCollectionLookupMappings(collectionName) {
3211
+ var _a;
3212
+ var normalized = normalizeOptionalString(collectionName);
3213
+ if (!normalized) {
3214
+ return [];
3215
+ }
3216
+ try {
3217
+ var collection = (_a = resolveio_server_app_1.ResolveIOServer.getMongoManager()) === null || _a === void 0 ? void 0 : _a.collection(normalized);
3218
+ var rbSchema_1 = collection === null || collection === void 0 ? void 0 : collection.rbSchema;
3219
+ if (!rbSchema_1 || typeof rbSchema_1 !== 'object') {
3220
+ return [];
3221
+ }
3222
+ var mappings_1 = [];
3223
+ Object.keys(rbSchema_1).forEach(function (key) {
3224
+ var entry = rbSchema_1[key];
3225
+ if (!entry || typeof entry !== 'object') {
3226
+ return;
3227
+ }
3228
+ var lookupCollection = normalizeOptionalString(entry.lookup_collection);
3229
+ var localKey = normalizeOptionalString(entry.local_key);
3230
+ if (!lookupCollection || !localKey) {
3231
+ return;
3232
+ }
3233
+ var lookupKey = normalizeOptionalString(entry.lookup_key) || '_id';
3234
+ mappings_1.push({ localKey: localKey, lookupCollection: lookupCollection, lookupKey: lookupKey });
3235
+ });
3236
+ return mappings_1;
3237
+ }
3238
+ catch (_b) {
3239
+ return [];
3240
+ }
3241
+ }
3242
+ function normalizeLookupPath(value) {
3243
+ var trimmed = normalizeOptionalString(value);
3244
+ if (!trimmed) {
3245
+ return '';
3246
+ }
3247
+ return trimmed
3248
+ .replace(/\.\$\./g, '.')
3249
+ .replace(/\.\$/g, '.')
3250
+ .replace(/\.\d+\./g, '.')
3251
+ .replace(/\.\d+$/g, '')
3252
+ .replace(/\.+/g, '.')
3253
+ .replace(/^\./, '')
3254
+ .replace(/\.$/, '');
3255
+ }
3256
+ function isUnsafeFieldAlias(requestedTokens, candidateTokens) {
3257
+ var reqSet = new Set(requestedTokens);
3258
+ var candSet = new Set(candidateTokens);
3259
+ var hasReqCreated = reqSet.has('created') || reqSet.has('create');
3260
+ var hasReqUpdated = reqSet.has('updated') || reqSet.has('update') || reqSet.has('modified') || reqSet.has('modify');
3261
+ var hasCandCreated = candSet.has('created') || candSet.has('create');
3262
+ var hasCandUpdated = candSet.has('updated') || candSet.has('update') || candSet.has('modified') || candSet.has('modify');
3263
+ if (hasReqCreated && hasCandUpdated && !hasCandCreated) {
3264
+ return true;
3265
+ }
3266
+ if (hasReqUpdated && hasCandCreated && !hasCandUpdated) {
3267
+ return true;
3268
+ }
3269
+ return false;
3270
+ }
2731
3271
  function expandFieldTokens(tokens) {
2732
3272
  var expanded = new Set();
2733
3273
  tokens.forEach(function (token) {
@@ -2897,15 +3437,406 @@ function normalizeIdsForTargetField(ids, targetDocs, targetFieldPath, targetFiel
2897
3437
  });
2898
3438
  return normalized;
2899
3439
  }
3440
+ function normalizeLookupKeyValue(value) {
3441
+ if (value === null || value === undefined) {
3442
+ return '';
3443
+ }
3444
+ if (isMongoObjectId(value)) {
3445
+ return typeof value.toHexString === 'function' ? value.toHexString() : String(value);
3446
+ }
3447
+ if (typeof value === 'string') {
3448
+ return value.trim();
3449
+ }
3450
+ return '';
3451
+ }
3452
+ function collectTopLevelIdFieldValues(docs, options) {
3453
+ var e_3, _a, e_4, _b;
3454
+ if (!Array.isArray(docs) || !docs.length) {
3455
+ return [];
3456
+ }
3457
+ var maxFields = typeof (options === null || options === void 0 ? void 0 : options.maxFields) === 'number'
3458
+ ? Math.max(options.maxFields, 0)
3459
+ : AI_ASSISTANT_ID_DISPLAY_LOOKUP_MAX_FIELDS;
3460
+ var maxIds = typeof (options === null || options === void 0 ? void 0 : options.maxIds) === 'number'
3461
+ ? Math.max(options.maxIds, 0)
3462
+ : AI_ASSISTANT_ID_DISPLAY_LOOKUP_MAX_IDS;
3463
+ var fieldMap = new Map();
3464
+ 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;
3467
+ if (!doc || typeof doc !== 'object') {
3468
+ continue;
3469
+ }
3470
+ var keys = Object.keys(doc);
3471
+ var _loop_3 = function (key) {
3472
+ if (!key || key === '_id' || key === '__v') {
3473
+ return "continue";
3474
+ }
3475
+ if (!isAssistantIdField(key)) {
3476
+ return "continue";
3477
+ }
3478
+ var value = doc[key];
3479
+ var values = Array.isArray(value) ? value : [value];
3480
+ if (!fieldMap.has(key)) {
3481
+ if (maxFields && fieldMap.size >= maxFields) {
3482
+ return "continue";
3483
+ }
3484
+ fieldMap.set(key, new Set());
3485
+ }
3486
+ var bucket = fieldMap.get(key);
3487
+ if (!bucket) {
3488
+ return "continue";
3489
+ }
3490
+ values.forEach(function (entry) {
3491
+ if (entry === null || entry === undefined) {
3492
+ return;
3493
+ }
3494
+ if (bucket.size >= maxIds) {
3495
+ return;
3496
+ }
3497
+ bucket.add(entry);
3498
+ });
3499
+ };
3500
+ 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()) {
3502
+ var key = keys_1_1.value;
3503
+ _loop_3(key);
3504
+ }
3505
+ }
3506
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
3507
+ finally {
3508
+ try {
3509
+ if (keys_1_1 && !keys_1_1.done && (_b = keys_1.return)) _b.call(keys_1);
3510
+ }
3511
+ finally { if (e_4) throw e_4.error; }
3512
+ }
3513
+ }
3514
+ }
3515
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
3516
+ finally {
3517
+ try {
3518
+ if (docs_2_1 && !docs_2_1.done && (_a = docs_2.return)) _a.call(docs_2);
3519
+ }
3520
+ finally { if (e_3) throw e_3.error; }
3521
+ }
3522
+ return Array.from(fieldMap.entries()).map(function (_a) {
3523
+ var _b = __read(_a, 2), field = _b[0], values = _b[1];
3524
+ return ({
3525
+ field: field,
3526
+ values: Array.from(values)
3527
+ });
3528
+ });
3529
+ }
3530
+ function resolveLookupDisplayField(baseToken, probeDocs, schemaFields) {
3531
+ var e_5, _a, e_6, _b;
3532
+ var normalizedBase = normalizeOptionalString(baseToken);
3533
+ if (!normalizedBase) {
3534
+ return null;
3535
+ }
3536
+ var candidates = buildNameLookupFields(normalizedBase, probeDocs || []);
3537
+ var schema = Array.isArray(schemaFields) ? schemaFields : [];
3538
+ if (schema.length) {
3539
+ var schemaCandidates = candidates.filter(function (candidate) { return schema.includes(candidate); });
3540
+ if (schemaCandidates.length) {
3541
+ try {
3542
+ for (var schemaCandidates_1 = __values(schemaCandidates), schemaCandidates_1_1 = schemaCandidates_1.next(); !schemaCandidates_1_1.done; schemaCandidates_1_1 = schemaCandidates_1.next()) {
3543
+ var candidate = schemaCandidates_1_1.value;
3544
+ if (hasNonEmptyValue(probeDocs || [], candidate, { treatObjectLikeAsEmpty: true })) {
3545
+ return candidate;
3546
+ }
3547
+ }
3548
+ }
3549
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
3550
+ finally {
3551
+ try {
3552
+ if (schemaCandidates_1_1 && !schemaCandidates_1_1.done && (_a = schemaCandidates_1.return)) _a.call(schemaCandidates_1);
3553
+ }
3554
+ finally { if (e_5) throw e_5.error; }
3555
+ }
3556
+ return schemaCandidates[0];
3557
+ }
3558
+ }
3559
+ try {
3560
+ for (var candidates_1 = __values(candidates), candidates_1_1 = candidates_1.next(); !candidates_1_1.done; candidates_1_1 = candidates_1.next()) {
3561
+ var candidate = candidates_1_1.value;
3562
+ if (hasNonEmptyValue(probeDocs || [], candidate, { treatObjectLikeAsEmpty: true })) {
3563
+ return candidate;
3564
+ }
3565
+ }
3566
+ }
3567
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
3568
+ finally {
3569
+ try {
3570
+ if (candidates_1_1 && !candidates_1_1.done && (_b = candidates_1.return)) _b.call(candidates_1);
3571
+ }
3572
+ finally { if (e_6) throw e_6.error; }
3573
+ }
3574
+ return candidates.length ? candidates[0] : null;
3575
+ }
3576
+ function resolveLookupMappingsForField(field, mappings) {
3577
+ var normalizedField = normalizeLookupPath(field);
3578
+ if (!normalizedField) {
3579
+ return [];
3580
+ }
3581
+ return mappings.filter(function (mapping) { return normalizeLookupPath(mapping.localKey) === normalizedField; });
3582
+ }
3583
+ function applyIdLookupDisplayEnrichment(params) {
3584
+ 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;
3587
+ return __generator(this, function (_b) {
3588
+ switch (_b.label) {
3589
+ case 0:
3590
+ docs = params.docs, collection = params.collection, db = params.db, dbName = params.dbName, idClient = params.idClient, idCustomer = params.idCustomer, isSuperAdmin = params.isSuperAdmin;
3591
+ if (!Array.isArray(docs) || !docs.length) {
3592
+ return [2 /*return*/, { docs: docs }];
3593
+ }
3594
+ idFields = collectTopLevelIdFieldValues(docs, {
3595
+ maxFields: AI_ASSISTANT_ID_DISPLAY_LOOKUP_MAX_FIELDS,
3596
+ maxIds: AI_ASSISTANT_ID_DISPLAY_LOOKUP_MAX_IDS
3597
+ });
3598
+ if (!idFields.length) {
3599
+ return [2 /*return*/, { docs: docs }];
3600
+ }
3601
+ lookupMappings = getCollectionLookupMappings(collection);
3602
+ return [4 /*yield*/, listAssistantCollections(db, dbName)];
3603
+ case 1:
3604
+ allCollections = _b.sent();
3605
+ collectionProbeCache = new Map();
3606
+ collectionSchemaCache = new Map();
3607
+ lookupMeta = [];
3608
+ enrichedDocs = docs.map(function (doc) { return (__assign({}, doc)); });
3609
+ _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;
3612
+ return __generator(this, function (_d) {
3613
+ switch (_d.label) {
3614
+ case 0:
3615
+ values = fieldEntry.values || [];
3616
+ if (!values.length) {
3617
+ return [2 /*return*/, "continue"];
3618
+ }
3619
+ baseToken = normalizeIdFieldBase(fieldEntry.field);
3620
+ if (!baseToken) {
3621
+ return [2 /*return*/, "continue"];
3622
+ }
3623
+ mappingMatches = resolveLookupMappingsForField(fieldEntry.field, lookupMappings);
3624
+ candidateCollections = mappingMatches.length
3625
+ ? mappingMatches.map(function (entry) { return entry.lookupCollection; })
3626
+ : resolveIdLookupCandidates(baseToken, allCollections);
3627
+ filteredCandidates = candidateCollections
3628
+ .filter(function (candidate) { return !!candidate; })
3629
+ .filter(function (candidate) { return candidate !== collection; })
3630
+ .filter(function (candidate) { return !candidate.endsWith('.versions'); })
3631
+ .filter(function (candidate) { return isSuperAdmin || !AI_ASSISTANT_BLOCKED_COLLECTIONS.has(candidate); })
3632
+ .slice(0, AI_ASSISTANT_ID_DISPLAY_LOOKUP_MAX_COLLECTIONS);
3633
+ if (!filteredCandidates.length) {
3634
+ return [2 /*return*/, "continue"];
3635
+ }
3636
+ _loop_5 = function (candidate) {
3637
+ var probeDocs, candidateHasClientScope, _e, schemaFields, nameField, mapping, lookupKey, idsForQuery, query, candidateHasClientScope, _f, lookupDocs, nameMap, displayField;
3638
+ var _g, _h;
3639
+ return __generator(this, function (_j) {
3640
+ switch (_j.label) {
3641
+ case 0:
3642
+ probeDocs = collectionProbeCache.get(candidate);
3643
+ if (!!probeDocs) return [3 /*break*/, 5];
3644
+ if (!idClient) return [3 /*break*/, 2];
3645
+ return [4 /*yield*/, collectionHasClientIndex(db, dbName, candidate)];
3646
+ case 1:
3647
+ _e = _j.sent();
3648
+ return [3 /*break*/, 3];
3649
+ case 2:
3650
+ _e = false;
3651
+ _j.label = 3;
3652
+ case 3:
3653
+ candidateHasClientScope = _e;
3654
+ return [4 /*yield*/, fetchAssistantProbeDocs({
3655
+ db: db,
3656
+ collection: candidate,
3657
+ idClient: idClient,
3658
+ idCustomer: idCustomer,
3659
+ isSuperAdmin: isSuperAdmin,
3660
+ includeClientScope: candidateHasClientScope
3661
+ })];
3662
+ case 4:
3663
+ probeDocs = _j.sent();
3664
+ collectionProbeCache.set(candidate, probeDocs);
3665
+ _j.label = 5;
3666
+ case 5:
3667
+ schemaFields = collectionSchemaCache.get(candidate)
3668
+ || getCollectionSchemaFieldNames(candidate);
3669
+ collectionSchemaCache.set(candidate, schemaFields);
3670
+ nameField = resolveLookupDisplayField(baseToken, probeDocs, schemaFields);
3671
+ if (!nameField) {
3672
+ return [2 /*return*/, "continue"];
3673
+ }
3674
+ mapping = mappingMatches.find(function (entry) { return entry.lookupCollection === candidate; });
3675
+ lookupKey = normalizeOptionalString(mapping === null || mapping === void 0 ? void 0 : mapping.lookupKey) || '_id';
3676
+ idsForQuery = normalizeIdsForTargetField(values, probeDocs, lookupKey);
3677
+ if (!idsForQuery.length) {
3678
+ return [2 /*return*/, "continue"];
3679
+ }
3680
+ query = (_g = {}, _g[lookupKey] = { $in: idsForQuery }, _g);
3681
+ if (!!isSuperAdmin) return [3 /*break*/, 9];
3682
+ if (!idClient) return [3 /*break*/, 7];
3683
+ return [4 /*yield*/, collectionHasClientIndex(db, dbName, candidate)];
3684
+ case 6:
3685
+ _f = _j.sent();
3686
+ return [3 /*break*/, 8];
3687
+ case 7:
3688
+ _f = false;
3689
+ _j.label = 8;
3690
+ case 8:
3691
+ candidateHasClientScope = _f;
3692
+ if (candidateHasClientScope) {
3693
+ query = applyClientScopeFilter(query, idClient, isSuperAdmin);
3694
+ }
3695
+ query = applyCustomerScopeFilter(query, candidate, idCustomer, isSuperAdmin);
3696
+ _j.label = 9;
3697
+ case 9: return [4 /*yield*/, db.collection(candidate).find(query, {
3698
+ projection: (_h = {}, _h[lookupKey] = 1, _h[nameField] = 1, _h),
3699
+ limit: AI_ASSISTANT_ID_DISPLAY_LOOKUP_MAX_IDS,
3700
+ readPreference: AI_ASSISTANT_READ_PREFERENCE
3701
+ }).toArray()];
3702
+ case 10:
3703
+ lookupDocs = _j.sent();
3704
+ if (!lookupDocs.length) {
3705
+ return [2 /*return*/, "continue"];
3706
+ }
3707
+ nameMap = new Map();
3708
+ lookupDocs.forEach(function (doc) {
3709
+ var _a, _b;
3710
+ var key = normalizeLookupKeyValue((_a = getValueAtPath(doc, lookupKey)) !== null && _a !== void 0 ? _a : doc === null || doc === void 0 ? void 0 : doc[lookupKey]);
3711
+ if (!key) {
3712
+ return;
3713
+ }
3714
+ var nameValue = (_b = getValueAtPath(doc, nameField)) !== null && _b !== void 0 ? _b : doc === null || doc === void 0 ? void 0 : doc[nameField];
3715
+ if (isEmptyDisplayValue(nameValue)) {
3716
+ return;
3717
+ }
3718
+ if (!nameMap.has(key)) {
3719
+ nameMap.set(key, nameValue);
3720
+ }
3721
+ });
3722
+ if (!nameMap.size) {
3723
+ return [2 /*return*/, "continue"];
3724
+ }
3725
+ displayField = baseToken;
3726
+ enrichedDocs = enrichedDocs.map(function (doc) {
3727
+ var _a;
3728
+ var rawValue = doc === null || doc === void 0 ? void 0 : doc[fieldEntry.field];
3729
+ if (rawValue === undefined || rawValue === null) {
3730
+ return doc;
3731
+ }
3732
+ if (!displayField || !isEmptyDisplayValue(doc === null || doc === void 0 ? void 0 : doc[displayField])) {
3733
+ return doc;
3734
+ }
3735
+ var valuesToResolve = Array.isArray(rawValue) ? rawValue : [rawValue];
3736
+ var resolved = valuesToResolve
3737
+ .map(function (value) { return nameMap.get(normalizeLookupKeyValue(value)); })
3738
+ .filter(function (value) { return !isEmptyDisplayValue(value); });
3739
+ if (!resolved.length) {
3740
+ return doc;
3741
+ }
3742
+ return __assign(__assign({}, doc), (_a = {}, _a[displayField] = resolved.length === 1 ? resolved[0] : resolved, _a));
3743
+ });
3744
+ lookupMeta.push({
3745
+ field: fieldEntry.field,
3746
+ displayField: displayField,
3747
+ collection: candidate,
3748
+ nameField: nameField,
3749
+ idCount: values.length,
3750
+ matched: nameMap.size,
3751
+ strategy: mapping ? 'schema' : 'token'
3752
+ });
3753
+ return [2 /*return*/, "break"];
3754
+ }
3755
+ });
3756
+ };
3757
+ _d.label = 1;
3758
+ case 1:
3759
+ _d.trys.push([1, 6, 7, 8]);
3760
+ filteredCandidates_1 = (e_8 = void 0, __values(filteredCandidates)), filteredCandidates_1_1 = filteredCandidates_1.next();
3761
+ _d.label = 2;
3762
+ case 2:
3763
+ if (!!filteredCandidates_1_1.done) return [3 /*break*/, 5];
3764
+ candidate = filteredCandidates_1_1.value;
3765
+ return [5 /*yield**/, _loop_5(candidate)];
3766
+ case 3:
3767
+ state_3 = _d.sent();
3768
+ if (state_3 === "break")
3769
+ return [3 /*break*/, 5];
3770
+ _d.label = 4;
3771
+ case 4:
3772
+ filteredCandidates_1_1 = filteredCandidates_1.next();
3773
+ return [3 /*break*/, 2];
3774
+ case 5: return [3 /*break*/, 8];
3775
+ case 6:
3776
+ e_8_1 = _d.sent();
3777
+ e_8 = { error: e_8_1 };
3778
+ return [3 /*break*/, 8];
3779
+ case 7:
3780
+ try {
3781
+ if (filteredCandidates_1_1 && !filteredCandidates_1_1.done && (_c = filteredCandidates_1.return)) _c.call(filteredCandidates_1);
3782
+ }
3783
+ finally { if (e_8) throw e_8.error; }
3784
+ return [7 /*endfinally*/];
3785
+ case 8: return [2 /*return*/];
3786
+ }
3787
+ });
3788
+ };
3789
+ _b.label = 2;
3790
+ case 2:
3791
+ _b.trys.push([2, 7, 8, 9]);
3792
+ idFields_1 = __values(idFields), idFields_1_1 = idFields_1.next();
3793
+ _b.label = 3;
3794
+ case 3:
3795
+ if (!!idFields_1_1.done) return [3 /*break*/, 6];
3796
+ fieldEntry = idFields_1_1.value;
3797
+ return [5 /*yield**/, _loop_4(fieldEntry)];
3798
+ case 4:
3799
+ _b.sent();
3800
+ _b.label = 5;
3801
+ case 5:
3802
+ idFields_1_1 = idFields_1.next();
3803
+ return [3 /*break*/, 3];
3804
+ case 6: return [3 /*break*/, 9];
3805
+ case 7:
3806
+ e_7_1 = _b.sent();
3807
+ e_7 = { error: e_7_1 };
3808
+ return [3 /*break*/, 9];
3809
+ case 8:
3810
+ try {
3811
+ if (idFields_1_1 && !idFields_1_1.done && (_a = idFields_1.return)) _a.call(idFields_1);
3812
+ }
3813
+ finally { if (e_7) throw e_7.error; }
3814
+ return [7 /*endfinally*/];
3815
+ case 9:
3816
+ if (!lookupMeta.length) {
3817
+ return [2 /*return*/, { docs: enrichedDocs }];
3818
+ }
3819
+ return [2 /*return*/, {
3820
+ docs: enrichedDocs,
3821
+ meta: {
3822
+ attempted: true,
3823
+ used: true,
3824
+ lookups: lookupMeta
3825
+ }
3826
+ }];
3827
+ }
3828
+ });
3829
+ });
3830
+ }
2900
3831
  function hasNonEmptyValue(docs, fieldPath, options) {
2901
- var e_3, _a;
3832
+ var e_9, _a;
2902
3833
  if (!Array.isArray(docs) || !fieldPath) {
2903
3834
  return false;
2904
3835
  }
2905
3836
  var usePath = fieldPath.includes('.');
2906
3837
  try {
2907
- for (var docs_2 = __values(docs), docs_2_1 = docs_2.next(); !docs_2_1.done; docs_2_1 = docs_2.next()) {
2908
- var doc = docs_2_1.value;
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;
2909
3840
  var value = usePath ? getValueAtPath(doc, fieldPath) : doc === null || doc === void 0 ? void 0 : doc[fieldPath];
2910
3841
  if ((options === null || options === void 0 ? void 0 : options.treatObjectLikeAsEmpty) && isDisplayObjectLike(value)) {
2911
3842
  continue;
@@ -2915,12 +3846,12 @@ function hasNonEmptyValue(docs, fieldPath, options) {
2915
3846
  }
2916
3847
  }
2917
3848
  }
2918
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
3849
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
2919
3850
  finally {
2920
3851
  try {
2921
- if (docs_2_1 && !docs_2_1.done && (_a = docs_2.return)) _a.call(docs_2);
3852
+ if (docs_3_1 && !docs_3_1.done && (_a = docs_3.return)) _a.call(docs_3);
2922
3853
  }
2923
- finally { if (e_3) throw e_3.error; }
3854
+ finally { if (e_9) throw e_9.error; }
2924
3855
  }
2925
3856
  return false;
2926
3857
  }
@@ -2980,7 +3911,7 @@ function collectFieldCandidates(docs) {
2980
3911
  });
2981
3912
  return candidates;
2982
3913
  }
2983
- function resolveFieldAliases(docs, requestedFields) {
3914
+ function resolveFieldAliases(docs, requestedFields, schemaFields) {
2984
3915
  var aliases = {};
2985
3916
  if (!Array.isArray(docs) || !requestedFields.length) {
2986
3917
  return aliases;
@@ -2990,11 +3921,24 @@ function resolveFieldAliases(docs, requestedFields) {
2990
3921
  return aliases;
2991
3922
  }
2992
3923
  var candidates = collectFieldCandidates(docs);
3924
+ var schemaFieldList = Array.isArray(schemaFields) ? schemaFields.filter(Boolean) : [];
3925
+ var candidateFieldList = schemaFieldList.length ? schemaFieldList : Array.from(candidates.keys());
2993
3926
  missing.forEach(function (field) {
2994
3927
  var normalizedRequested = normalizeFieldMatchKey(field);
2995
3928
  if (!normalizedRequested) {
2996
3929
  return;
2997
3930
  }
3931
+ var requestedBaseTokens = tokenizeFieldKey(field);
3932
+ var requestedHasType = requestedBaseTokens.includes('type');
3933
+ var hasNonTypeCandidate = requestedBaseTokens.length
3934
+ ? candidateFieldList.some(function (candidateField) {
3935
+ var tokens = tokenizeFieldKey(candidateField);
3936
+ if (tokens.includes('type')) {
3937
+ return false;
3938
+ }
3939
+ return requestedBaseTokens.some(function (token) { return tokens.includes(token); });
3940
+ })
3941
+ : false;
2998
3942
  var bestPath = '';
2999
3943
  var bestScore = 0;
3000
3944
  candidates.forEach(function (stats, path) {
@@ -3004,6 +3948,13 @@ function resolveFieldAliases(docs, requestedFields) {
3004
3948
  if (isAssistantIdField(path)) {
3005
3949
  return;
3006
3950
  }
3951
+ var candidateTokens = tokenizeFieldKey(path);
3952
+ if (isUnsafeFieldAlias(requestedBaseTokens, candidateTokens)) {
3953
+ return;
3954
+ }
3955
+ if (!requestedHasType && candidateTokens.includes('type') && hasNonTypeCandidate) {
3956
+ return;
3957
+ }
3007
3958
  var normalizedCandidate = stats.normalized || normalizeFieldMatchKey(path);
3008
3959
  if (!normalizedCandidate) {
3009
3960
  return;
@@ -3016,11 +3967,9 @@ function resolveFieldAliases(docs, requestedFields) {
3016
3967
  score = 70;
3017
3968
  }
3018
3969
  else {
3019
- var candidateTokens_1 = tokenizeFieldKey(path);
3020
- var requestedBaseTokens = tokenizeFieldKey(field);
3021
3970
  var requestedTokens = expandFieldTokens(requestedBaseTokens);
3022
- var overlap = requestedTokens.filter(function (token) { return candidateTokens_1.includes(token); }).length;
3023
- var baseOverlap = requestedBaseTokens.filter(function (token) { return candidateTokens_1.includes(token); }).length;
3971
+ var overlap = requestedTokens.filter(function (token) { return candidateTokens.includes(token); }).length;
3972
+ var baseOverlap = requestedBaseTokens.filter(function (token) { return candidateTokens.includes(token); }).length;
3024
3973
  if (overlap > 0) {
3025
3974
  score = 40 + overlap * 10;
3026
3975
  if (baseOverlap === 0) {
@@ -3744,7 +4693,7 @@ function matchContainsField(value, field) {
3744
4693
  });
3745
4694
  }
3746
4695
  function resolveAggregateCompletionFallback(pipeline) {
3747
- var e_4, _a;
4696
+ var e_10, _a;
3748
4697
  if (!Array.isArray(pipeline)) {
3749
4698
  return null;
3750
4699
  }
@@ -3757,7 +4706,7 @@ function resolveAggregateCompletionFallback(pipeline) {
3757
4706
  }
3758
4707
  var addFields = stage.$addFields;
3759
4708
  try {
3760
- for (var _b = (e_4 = void 0, __values(Object.keys(addFields))), _c = _b.next(); !_c.done; _c = _b.next()) {
4709
+ for (var _b = (e_10 = void 0, __values(Object.keys(addFields))), _c = _b.next(); !_c.done; _c = _b.next()) {
3761
4710
  var key = _c.value;
3762
4711
  if (!isCompletionFieldName(key)) {
3763
4712
  continue;
@@ -3771,12 +4720,12 @@ function resolveAggregateCompletionFallback(pipeline) {
3771
4720
  }
3772
4721
  }
3773
4722
  }
3774
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
4723
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
3775
4724
  finally {
3776
4725
  try {
3777
4726
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3778
4727
  }
3779
- finally { if (e_4) throw e_4.error; }
4728
+ finally { if (e_10) throw e_10.error; }
3780
4729
  }
3781
4730
  if (candidateField) {
3782
4731
  break;
@@ -3932,7 +4881,7 @@ function buildCompletionFallbackSources(field) {
3932
4881
  ]);
3933
4882
  }
3934
4883
  function resolveAggregateCompletionExprFallback(pipeline) {
3935
- var e_5, _a;
4884
+ var e_11, _a;
3936
4885
  if (!Array.isArray(pipeline)) {
3937
4886
  return null;
3938
4887
  }
@@ -3952,7 +4901,7 @@ function resolveAggregateCompletionExprFallback(pipeline) {
3952
4901
  }
3953
4902
  if (!candidateField) {
3954
4903
  try {
3955
- for (var _b = (e_5 = void 0, __values(Object.keys(matchStage))), _c = _b.next(); !_c.done; _c = _b.next()) {
4904
+ for (var _b = (e_11 = void 0, __values(Object.keys(matchStage))), _c = _b.next(); !_c.done; _c = _b.next()) {
3956
4905
  var key = _c.value;
3957
4906
  if (key.startsWith('$')) {
3958
4907
  continue;
@@ -3967,12 +4916,12 @@ function resolveAggregateCompletionExprFallback(pipeline) {
3967
4916
  }
3968
4917
  }
3969
4918
  }
3970
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
4919
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
3971
4920
  finally {
3972
4921
  try {
3973
4922
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3974
4923
  }
3975
- finally { if (e_5) throw e_5.error; }
4924
+ finally { if (e_11) throw e_11.error; }
3976
4925
  }
3977
4926
  }
3978
4927
  if (!candidateField) {
@@ -4142,7 +5091,7 @@ function isRegexMatchCondition(value) {
4142
5091
  return false;
4143
5092
  }
4144
5093
  function findRegexMatchInMatchObject(match, prefix) {
4145
- var e_6, _a, e_7, _b;
5094
+ var e_12, _a, e_13, _b;
4146
5095
  if (prefix === void 0) { prefix = ''; }
4147
5096
  if (Array.isArray(match)) {
4148
5097
  try {
@@ -4154,12 +5103,12 @@ function findRegexMatchInMatchObject(match, prefix) {
4154
5103
  }
4155
5104
  }
4156
5105
  }
4157
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
5106
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
4158
5107
  finally {
4159
5108
  try {
4160
5109
  if (match_1_1 && !match_1_1.done && (_a = match_1.return)) _a.call(match_1);
4161
5110
  }
4162
- finally { if (e_6) throw e_6.error; }
5111
+ finally { if (e_12) throw e_12.error; }
4163
5112
  }
4164
5113
  return null;
4165
5114
  }
@@ -4168,8 +5117,8 @@ function findRegexMatchInMatchObject(match, prefix) {
4168
5117
  }
4169
5118
  var keys = Object.keys(match);
4170
5119
  try {
4171
- for (var keys_1 = __values(keys), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
4172
- var key = keys_1_1.value;
5120
+ for (var keys_2 = __values(keys), keys_2_1 = keys_2.next(); !keys_2_1.done; keys_2_1 = keys_2.next()) {
5121
+ var key = keys_2_1.value;
4173
5122
  var value = match[key];
4174
5123
  if (key.startsWith('$')) {
4175
5124
  var found = findRegexMatchInMatchObject(value, prefix);
@@ -4190,12 +5139,12 @@ function findRegexMatchInMatchObject(match, prefix) {
4190
5139
  }
4191
5140
  }
4192
5141
  }
4193
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
5142
+ catch (e_13_1) { e_13 = { error: e_13_1 }; }
4194
5143
  finally {
4195
5144
  try {
4196
- if (keys_1_1 && !keys_1_1.done && (_b = keys_1.return)) _b.call(keys_1);
5145
+ if (keys_2_1 && !keys_2_1.done && (_b = keys_2.return)) _b.call(keys_2);
4197
5146
  }
4198
- finally { if (e_7) throw e_7.error; }
5147
+ finally { if (e_13) throw e_13.error; }
4199
5148
  }
4200
5149
  return null;
4201
5150
  }
@@ -4384,6 +5333,173 @@ function stripMatchField(match, field) {
4384
5333
  });
4385
5334
  return result;
4386
5335
  }
5336
+ function collectMatchFieldsByCondition(match, predicate, prefix) {
5337
+ if (prefix === void 0) { prefix = ''; }
5338
+ var results = [];
5339
+ if (Array.isArray(match)) {
5340
+ match.forEach(function (entry) {
5341
+ results.push.apply(results, __spreadArray([], __read(collectMatchFieldsByCondition(entry, predicate, prefix)), false));
5342
+ });
5343
+ return results;
5344
+ }
5345
+ if (!match || typeof match !== 'object') {
5346
+ return results;
5347
+ }
5348
+ Object.keys(match).forEach(function (key) {
5349
+ var value = match[key];
5350
+ if (key.startsWith('$')) {
5351
+ results.push.apply(results, __spreadArray([], __read(collectMatchFieldsByCondition(value, predicate, prefix)), false));
5352
+ return;
5353
+ }
5354
+ var currentPath = prefix ? "".concat(prefix, ".").concat(key) : key;
5355
+ if (predicate(currentPath, value)) {
5356
+ results.push(currentPath);
5357
+ }
5358
+ if (value && typeof value === 'object') {
5359
+ results.push.apply(results, __spreadArray([], __read(collectMatchFieldsByCondition(value, predicate, currentPath)), false));
5360
+ }
5361
+ });
5362
+ return results;
5363
+ }
5364
+ function findMatchConditionForField(match, targetField, prefix) {
5365
+ var e_14, _a, e_15, _b;
5366
+ if (prefix === void 0) { prefix = ''; }
5367
+ if (!match || typeof match !== 'object') {
5368
+ return undefined;
5369
+ }
5370
+ if (Array.isArray(match)) {
5371
+ try {
5372
+ for (var match_2 = __values(match), match_2_1 = match_2.next(); !match_2_1.done; match_2_1 = match_2.next()) {
5373
+ var entry = match_2_1.value;
5374
+ var found = findMatchConditionForField(entry, targetField, prefix);
5375
+ if (found !== undefined) {
5376
+ return found;
5377
+ }
5378
+ }
5379
+ }
5380
+ catch (e_14_1) { e_14 = { error: e_14_1 }; }
5381
+ finally {
5382
+ try {
5383
+ if (match_2_1 && !match_2_1.done && (_a = match_2.return)) _a.call(match_2);
5384
+ }
5385
+ finally { if (e_14) throw e_14.error; }
5386
+ }
5387
+ return undefined;
5388
+ }
5389
+ try {
5390
+ for (var _c = __values(Object.keys(match)), _d = _c.next(); !_d.done; _d = _c.next()) {
5391
+ var key = _d.value;
5392
+ var value = match[key];
5393
+ if (key.startsWith('$')) {
5394
+ var found = findMatchConditionForField(value, targetField, prefix);
5395
+ if (found !== undefined) {
5396
+ return found;
5397
+ }
5398
+ continue;
5399
+ }
5400
+ var currentPath = prefix ? "".concat(prefix, ".").concat(key) : key;
5401
+ if (currentPath === targetField) {
5402
+ return value;
5403
+ }
5404
+ if (value && typeof value === 'object') {
5405
+ var found = findMatchConditionForField(value, targetField, currentPath);
5406
+ if (found !== undefined) {
5407
+ return found;
5408
+ }
5409
+ }
5410
+ }
5411
+ }
5412
+ catch (e_15_1) { e_15 = { error: e_15_1 }; }
5413
+ finally {
5414
+ try {
5415
+ if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
5416
+ }
5417
+ finally { if (e_15) throw e_15.error; }
5418
+ }
5419
+ return undefined;
5420
+ }
5421
+ function stripMatchFields(match, fields) {
5422
+ var result = match;
5423
+ fields.forEach(function (field) {
5424
+ result = stripMatchField(result, field);
5425
+ });
5426
+ return result;
5427
+ }
5428
+ function isDateCondition(value) {
5429
+ if (!value) {
5430
+ return false;
5431
+ }
5432
+ if (value instanceof Date) {
5433
+ return true;
5434
+ }
5435
+ if (typeof value === 'object' && !Array.isArray(value)) {
5436
+ return hasDateRangeOperators(value);
5437
+ }
5438
+ return false;
5439
+ }
5440
+ function isChemicalFieldPath(field) {
5441
+ var normalized = normalizeOptionalString(field).toLowerCase();
5442
+ return normalized.includes('chemical');
5443
+ }
5444
+ function detectIdLikeValue(value) {
5445
+ if (!value) {
5446
+ return false;
5447
+ }
5448
+ if (isMongoObjectId(value)) {
5449
+ return true;
5450
+ }
5451
+ if (typeof value === 'string' && isObjectIdString(value)) {
5452
+ return true;
5453
+ }
5454
+ if (isPlainObject(value)) {
5455
+ return true;
5456
+ }
5457
+ return false;
5458
+ }
5459
+ function detectChemicalIdFromProbe(probeDocs, fields) {
5460
+ var e_16, _a, e_17, _b;
5461
+ if (!Array.isArray(probeDocs) || !probeDocs.length) {
5462
+ return false;
5463
+ }
5464
+ var targets = fields.filter(function (field) { return isChemicalFieldPath(field); });
5465
+ if (!targets.length) {
5466
+ return false;
5467
+ }
5468
+ try {
5469
+ for (var probeDocs_1 = __values(probeDocs), probeDocs_1_1 = probeDocs_1.next(); !probeDocs_1_1.done; probeDocs_1_1 = probeDocs_1.next()) {
5470
+ var doc = probeDocs_1_1.value;
5471
+ 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()) {
5473
+ var field = targets_1_1.value;
5474
+ var value = getValueAtPath(doc, field);
5475
+ if (Array.isArray(value)) {
5476
+ if (value.some(function (entry) { return detectIdLikeValue(entry); })) {
5477
+ return true;
5478
+ }
5479
+ }
5480
+ else if (detectIdLikeValue(value)) {
5481
+ return true;
5482
+ }
5483
+ }
5484
+ }
5485
+ catch (e_17_1) { e_17 = { error: e_17_1 }; }
5486
+ finally {
5487
+ try {
5488
+ if (targets_1_1 && !targets_1_1.done && (_b = targets_1.return)) _b.call(targets_1);
5489
+ }
5490
+ finally { if (e_17) throw e_17.error; }
5491
+ }
5492
+ }
5493
+ }
5494
+ catch (e_16_1) { e_16 = { error: e_16_1 }; }
5495
+ finally {
5496
+ try {
5497
+ if (probeDocs_1_1 && !probeDocs_1_1.done && (_a = probeDocs_1.return)) _a.call(probeDocs_1);
5498
+ }
5499
+ finally { if (e_16) throw e_16.error; }
5500
+ }
5501
+ return false;
5502
+ }
4387
5503
  function isEmptyQueryValue(value) {
4388
5504
  if (value === null || value === undefined) {
4389
5505
  return true;
@@ -4579,6 +5695,155 @@ function buildIdFieldNameFallbackQuery(query, idField, nameField, condition) {
4579
5695
  : { $and: [baseMatch, { $or: orConditions }] };
4580
5696
  return nextMatch;
4581
5697
  }
5698
+ function buildChemicalIdFieldCandidates(field) {
5699
+ var normalized = normalizeOptionalString(field);
5700
+ if (!normalized) {
5701
+ return [];
5702
+ }
5703
+ var parts = normalized.split('.').filter(Boolean);
5704
+ var leaf = parts[parts.length - 1] || normalized;
5705
+ var prefix = parts.length > 1 ? parts.slice(0, -1).join('.') : '';
5706
+ var withPrefix = function (value) { return (prefix ? "".concat(prefix, ".").concat(value) : value); };
5707
+ var candidates = new Set();
5708
+ candidates.add(normalized);
5709
+ if (!leaf.startsWith('id_')) {
5710
+ candidates.add(withPrefix('id_chemical'));
5711
+ candidates.add(withPrefix('chemical_id'));
5712
+ candidates.add(withPrefix('chemicalId'));
5713
+ candidates.add(withPrefix('idChemical'));
5714
+ }
5715
+ return Array.from(candidates);
5716
+ }
5717
+ function applyChemicalNameLookupFallbackToQuery(params) {
5718
+ 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;
5721
+ var _b;
5722
+ return __generator(this, function (_c) {
5723
+ switch (_c.label) {
5724
+ case 0:
5725
+ query = params.query, db = params.db, dbName = params.dbName, idClient = params.idClient, idCustomer = params.idCustomer, isSuperAdmin = params.isSuperAdmin, probeDocs = params.probeDocs;
5726
+ chemicalFields = collectMatchFieldsByCondition(query, function (field, condition) { return (isRegexMatchCondition(condition) && isChemicalFieldPath(field)); });
5727
+ if (!chemicalFields.length) {
5728
+ return [2 /*return*/, null];
5729
+ }
5730
+ targetField = chemicalFields[0];
5731
+ condition = findMatchConditionForField(query, targetField);
5732
+ regex = buildRegexFromCondition(condition);
5733
+ if (!regex) {
5734
+ return [2 /*return*/, null];
5735
+ }
5736
+ sampleDocs = Array.isArray(probeDocs) ? probeDocs : [];
5737
+ if (!detectChemicalIdFromProbe(sampleDocs, [targetField])) {
5738
+ return [2 /*return*/, null];
5739
+ }
5740
+ return [4 /*yield*/, listAssistantCollections(db, dbName)];
5741
+ case 1:
5742
+ collectionNames = _c.sent();
5743
+ candidates = resolveIdLookupCandidates('chemical', collectionNames);
5744
+ _loop_6 = function (candidate) {
5745
+ var candidateHasClientScope, _d, candidateProbe, lookup, idFields, baseMatch, orConditions, nextMatch;
5746
+ return __generator(this, function (_e) {
5747
+ switch (_e.label) {
5748
+ case 0:
5749
+ if (!candidate) {
5750
+ return [2 /*return*/, "continue"];
5751
+ }
5752
+ if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(candidate)) {
5753
+ return [2 /*return*/, "continue"];
5754
+ }
5755
+ if (!idClient) return [3 /*break*/, 2];
5756
+ return [4 /*yield*/, collectionHasClientIndex(db, dbName, candidate)];
5757
+ case 1:
5758
+ _d = _e.sent();
5759
+ return [3 /*break*/, 3];
5760
+ case 2:
5761
+ _d = false;
5762
+ _e.label = 3;
5763
+ case 3:
5764
+ candidateHasClientScope = _d;
5765
+ return [4 /*yield*/, fetchAssistantProbeDocs({
5766
+ db: db,
5767
+ collection: candidate,
5768
+ idClient: idClient,
5769
+ idCustomer: idCustomer,
5770
+ isSuperAdmin: isSuperAdmin,
5771
+ includeClientScope: candidateHasClientScope
5772
+ })];
5773
+ case 4:
5774
+ candidateProbe = _e.sent();
5775
+ return [4 /*yield*/, lookupIdsForNameMatch({
5776
+ db: db,
5777
+ dbName: dbName,
5778
+ collection: candidate,
5779
+ baseToken: 'chemical',
5780
+ regex: regex,
5781
+ idClient: idClient,
5782
+ idCustomer: idCustomer,
5783
+ isSuperAdmin: isSuperAdmin,
5784
+ probeDocs: candidateProbe
5785
+ })];
5786
+ case 5:
5787
+ lookup = _e.sent();
5788
+ if ((_b = lookup === null || lookup === void 0 ? void 0 : lookup.ids) === null || _b === void 0 ? void 0 : _b.length) {
5789
+ idFields = buildChemicalIdFieldCandidates(targetField);
5790
+ baseMatch = stripMatchField(query, targetField);
5791
+ orConditions = idFields.map(function (field) {
5792
+ var _a;
5793
+ return (_a = {}, _a[field] = { $in: lookup.ids }, _a);
5794
+ });
5795
+ nextMatch = isEmptyMatchValue(baseMatch)
5796
+ ? { $or: orConditions }
5797
+ : { $and: [baseMatch, { $or: orConditions }] };
5798
+ return [2 /*return*/, { value: {
5799
+ query: nextMatch,
5800
+ meta: {
5801
+ field: targetField,
5802
+ strategy: 'chemical_lookup',
5803
+ collection: candidate,
5804
+ ids: lookup.ids.length,
5805
+ fields: lookup.fields,
5806
+ idFields: idFields
5807
+ }
5808
+ } }];
5809
+ }
5810
+ return [2 /*return*/];
5811
+ }
5812
+ });
5813
+ };
5814
+ _c.label = 2;
5815
+ case 2:
5816
+ _c.trys.push([2, 7, 8, 9]);
5817
+ candidates_2 = __values(candidates), candidates_2_1 = candidates_2.next();
5818
+ _c.label = 3;
5819
+ case 3:
5820
+ if (!!candidates_2_1.done) return [3 /*break*/, 6];
5821
+ candidate = candidates_2_1.value;
5822
+ return [5 /*yield**/, _loop_6(candidate)];
5823
+ case 4:
5824
+ state_4 = _c.sent();
5825
+ if (typeof state_4 === "object")
5826
+ return [2 /*return*/, state_4.value];
5827
+ _c.label = 5;
5828
+ case 5:
5829
+ candidates_2_1 = candidates_2.next();
5830
+ return [3 /*break*/, 3];
5831
+ case 6: return [3 /*break*/, 9];
5832
+ case 7:
5833
+ e_18_1 = _c.sent();
5834
+ e_18 = { error: e_18_1 };
5835
+ return [3 /*break*/, 9];
5836
+ case 8:
5837
+ try {
5838
+ if (candidates_2_1 && !candidates_2_1.done && (_a = candidates_2.return)) _a.call(candidates_2);
5839
+ }
5840
+ finally { if (e_18) throw e_18.error; }
5841
+ return [7 /*endfinally*/];
5842
+ case 9: return [2 /*return*/, null];
5843
+ }
5844
+ });
5845
+ });
5846
+ }
4582
5847
  function resolveIdLookupCandidates(baseToken, collectionNames) {
4583
5848
  var normalizedBase = normalizeOptionalString(baseToken).toLowerCase();
4584
5849
  if (!normalizedBase || !Array.isArray(collectionNames) || !collectionNames.length) {
@@ -4666,8 +5931,8 @@ function lookupIdsForNameMatch(params) {
4666
5931
  }
4667
5932
  function applyIdLookupFallbackToQuery(params) {
4668
5933
  return __awaiter(this, void 0, void 0, function () {
4669
- var query, db, dbName, idClient, idCustomer, isSuperAdmin, probeDocs, conditions, collectionNames, _a, conditions_1, conditions_1_1, condition, regex, baseToken, targetFieldType, nextValue, localNameField, candidates, candidates_1, candidates_1_1, candidate, candidateHasClientScope, _b, candidateProbe, lookup, targetFieldType, normalizedIds, idsForQuery, e_8_1, e_9_1;
4670
- var e_9, _c, e_8, _d;
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;
4671
5936
  var _e;
4672
5937
  return __generator(this, function (_f) {
4673
5938
  switch (_f.label) {
@@ -4737,11 +6002,11 @@ function applyIdLookupFallbackToQuery(params) {
4737
6002
  _f.label = 5;
4738
6003
  case 5:
4739
6004
  _f.trys.push([5, 14, 15, 16]);
4740
- candidates_1 = (e_8 = void 0, __values(candidates)), candidates_1_1 = candidates_1.next();
6005
+ candidates_3 = (e_19 = void 0, __values(candidates)), candidates_3_1 = candidates_3.next();
4741
6006
  _f.label = 6;
4742
6007
  case 6:
4743
- if (!!candidates_1_1.done) return [3 /*break*/, 13];
4744
- candidate = candidates_1_1.value;
6008
+ if (!!candidates_3_1.done) return [3 /*break*/, 13];
6009
+ candidate = candidates_3_1.value;
4745
6010
  if (!candidate) {
4746
6011
  return [3 /*break*/, 12];
4747
6012
  }
@@ -4800,32 +6065,32 @@ function applyIdLookupFallbackToQuery(params) {
4800
6065
  }
4801
6066
  _f.label = 12;
4802
6067
  case 12:
4803
- candidates_1_1 = candidates_1.next();
6068
+ candidates_3_1 = candidates_3.next();
4804
6069
  return [3 /*break*/, 6];
4805
6070
  case 13: return [3 /*break*/, 16];
4806
6071
  case 14:
4807
- e_8_1 = _f.sent();
4808
- e_8 = { error: e_8_1 };
6072
+ e_19_1 = _f.sent();
6073
+ e_19 = { error: e_19_1 };
4809
6074
  return [3 /*break*/, 16];
4810
6075
  case 15:
4811
6076
  try {
4812
- if (candidates_1_1 && !candidates_1_1.done && (_d = candidates_1.return)) _d.call(candidates_1);
6077
+ if (candidates_3_1 && !candidates_3_1.done && (_d = candidates_3.return)) _d.call(candidates_3);
4813
6078
  }
4814
- finally { if (e_8) throw e_8.error; }
6079
+ finally { if (e_19) throw e_19.error; }
4815
6080
  return [7 /*endfinally*/];
4816
6081
  case 16:
4817
6082
  conditions_1_1 = conditions_1.next();
4818
6083
  return [3 /*break*/, 4];
4819
6084
  case 17: return [3 /*break*/, 20];
4820
6085
  case 18:
4821
- e_9_1 = _f.sent();
4822
- e_9 = { error: e_9_1 };
6086
+ e_20_1 = _f.sent();
6087
+ e_20 = { error: e_20_1 };
4823
6088
  return [3 /*break*/, 20];
4824
6089
  case 19:
4825
6090
  try {
4826
6091
  if (conditions_1_1 && !conditions_1_1.done && (_c = conditions_1.return)) _c.call(conditions_1);
4827
6092
  }
4828
- finally { if (e_9) throw e_9.error; }
6093
+ finally { if (e_20) throw e_20.error; }
4829
6094
  return [7 /*endfinally*/];
4830
6095
  case 20: return [2 /*return*/, null];
4831
6096
  }
@@ -4964,6 +6229,14 @@ function shouldApplyAssistantNameRegex(field) {
4964
6229
  function escapeRegexValue(value) {
4965
6230
  return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
4966
6231
  }
6232
+ function buildTokenizedRegex(value) {
6233
+ var tokens = tokenizeFieldKey(value).filter(function (token) { return token.length; });
6234
+ if (tokens.length <= 1) {
6235
+ return new RegExp(escapeRegexValue(value), 'i');
6236
+ }
6237
+ var tokenPattern = tokens.map(function (token) { return escapeRegexValue(token); }).join('[\\s\\-_]*.*');
6238
+ return new RegExp(tokenPattern, 'i');
6239
+ }
4967
6240
  function applyAssistantNameRegexToQuery(query) {
4968
6241
  if (Array.isArray(query)) {
4969
6242
  return query.map(function (entry) { return applyAssistantNameRegexToQuery(entry); });
@@ -4980,7 +6253,7 @@ function applyAssistantNameRegexToQuery(query) {
4980
6253
  }
4981
6254
  if (typeof value === 'string' && shouldApplyAssistantNameRegex(key)) {
4982
6255
  var trimmed = value.trim();
4983
- result[key] = trimmed ? new RegExp(escapeRegexValue(trimmed), 'i') : value;
6256
+ result[key] = trimmed ? buildTokenizedRegex(trimmed) : value;
4984
6257
  return;
4985
6258
  }
4986
6259
  if (value && typeof value === 'object') {
@@ -5007,12 +6280,13 @@ function hasOperatorKeys(value) {
5007
6280
  return Object.keys(value).some(function (key) { return key.startsWith('$'); });
5008
6281
  }
5009
6282
  function rewriteEmbeddedMatchObjects(query) {
5010
- var rewriteValue = function (value, allowArrayRewrite) {
6283
+ var rewriteValue = function (value, allowArrayRewrite, inOperator) {
6284
+ if (inOperator === void 0) { inOperator = false; }
5011
6285
  if (Array.isArray(value)) {
5012
6286
  if (!allowArrayRewrite) {
5013
6287
  return value;
5014
6288
  }
5015
- return value.map(function (entry) { return rewriteValue(entry, true); });
6289
+ return value.map(function (entry) { return rewriteValue(entry, true, inOperator); });
5016
6290
  }
5017
6291
  if (!value || typeof value !== 'object' || value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
5018
6292
  return value;
@@ -5021,38 +6295,38 @@ function rewriteEmbeddedMatchObjects(query) {
5021
6295
  Object.keys(value).forEach(function (key) {
5022
6296
  var entry = value[key];
5023
6297
  if (key.startsWith('$')) {
5024
- result[key] = rewriteValue(entry, true);
6298
+ result[key] = rewriteValue(entry, true, true);
5025
6299
  return;
5026
6300
  }
5027
- if (isPlainMatchObject(entry) && !Array.isArray(entry) && !hasOperatorKeys(entry)) {
5028
- var flattened = flattenMatchObject(entry, key);
6301
+ if (!inOperator && isPlainMatchObject(entry) && !Array.isArray(entry) && !hasOperatorKeys(entry)) {
6302
+ var flattened = flattenMatchObject(entry, key, inOperator);
5029
6303
  Object.assign(result, flattened);
5030
6304
  return;
5031
6305
  }
5032
6306
  if (isPlainMatchObject(entry) && !Array.isArray(entry)) {
5033
- result[key] = rewriteValue(entry, true);
6307
+ result[key] = rewriteValue(entry, true, inOperator);
5034
6308
  return;
5035
6309
  }
5036
6310
  if (Array.isArray(entry)) {
5037
- result[key] = allowArrayRewrite ? entry.map(function (item) { return rewriteValue(item, true); }) : entry;
6311
+ result[key] = allowArrayRewrite ? entry.map(function (item) { return rewriteValue(item, true, inOperator); }) : entry;
5038
6312
  return;
5039
6313
  }
5040
6314
  result[key] = entry;
5041
6315
  });
5042
6316
  return result;
5043
6317
  };
5044
- var flattenMatchObject = function (value, prefix) {
6318
+ var flattenMatchObject = function (value, prefix, inOperator) {
5045
6319
  var result = {};
5046
6320
  Object.keys(value || {}).forEach(function (key) {
5047
6321
  var entry = value[key];
5048
6322
  var currentPath = "".concat(prefix, ".").concat(key);
5049
6323
  if (isPlainMatchObject(entry) && !Array.isArray(entry) && !hasOperatorKeys(entry)) {
5050
- var flattened = flattenMatchObject(entry, currentPath);
6324
+ var flattened = flattenMatchObject(entry, currentPath, inOperator);
5051
6325
  Object.assign(result, flattened);
5052
6326
  return;
5053
6327
  }
5054
6328
  if (isPlainMatchObject(entry) && !Array.isArray(entry)) {
5055
- result[currentPath] = rewriteValue(entry, true);
6329
+ result[currentPath] = rewriteValue(entry, true, inOperator);
5056
6330
  return;
5057
6331
  }
5058
6332
  if (Array.isArray(entry)) {
@@ -5234,6 +6508,9 @@ function scoreCollectionMatch(requestedTokens, candidateName, tokenWeights) {
5234
6508
  else if (requestedKey && (candidateKey.includes(requestedKey) || requestedKey.includes(candidateKey))) {
5235
6509
  score += 20;
5236
6510
  }
6511
+ if (isVersionCollectionName(candidateName)) {
6512
+ score -= 15;
6513
+ }
5237
6514
  return score;
5238
6515
  }
5239
6516
  function scoreCollectionMatchDetailed(requestedTokens, candidateName, tokenWeights) {
@@ -5253,6 +6530,9 @@ function scoreCollectionMatchDetailed(requestedTokens, candidateName, tokenWeigh
5253
6530
  score += 20;
5254
6531
  keyMatch = 'partial';
5255
6532
  }
6533
+ if (isVersionCollectionName(candidateName)) {
6534
+ score -= 15;
6535
+ }
5256
6536
  return {
5257
6537
  score: score,
5258
6538
  tokenMatches: tokenMatches,
@@ -5326,6 +6606,115 @@ function isVersionCollectionName(value) {
5326
6606
  var normalized = normalizeOptionalString(value).toLowerCase();
5327
6607
  return normalized.endsWith('.versions') || normalized.endsWith('-versions') || normalized.includes('.versions.');
5328
6608
  }
6609
+ function stripVersionSuffix(value) {
6610
+ var normalized = normalizeOptionalString(value);
6611
+ if (!normalized) {
6612
+ return '';
6613
+ }
6614
+ if (normalized.endsWith('.versions')) {
6615
+ return normalized.slice(0, -'.versions'.length);
6616
+ }
6617
+ if (normalized.endsWith('-versions')) {
6618
+ return normalized.slice(0, -'-versions'.length);
6619
+ }
6620
+ return normalized;
6621
+ }
6622
+ function shouldAllowVersionCollections(message) {
6623
+ var normalized = normalizeOptionalString(message).toLowerCase();
6624
+ if (!normalized) {
6625
+ return false;
6626
+ }
6627
+ if (!normalized.includes('bug')) {
6628
+ return false;
6629
+ }
6630
+ return /(last\s*(5|five)\s+updates|version|history|audit)/i.test(normalized);
6631
+ }
6632
+ function resolveReportCollectionName(permissionView, collectionNames, currentCollection) {
6633
+ var normalizedView = normalizeOptionalString(permissionView).toLowerCase();
6634
+ if (!normalizedView.startsWith('/report/')) {
6635
+ return null;
6636
+ }
6637
+ var current = stripVersionSuffix(normalizeOptionalString(currentCollection));
6638
+ var reportCollection = current.startsWith('report-') ? current : "report-".concat(current);
6639
+ if (collectionNames.includes(reportCollection)) {
6640
+ return reportCollection;
6641
+ }
6642
+ var routeTail = normalizedView.replace('/report/', '').replace(/\//g, '-');
6643
+ var routeCandidate = routeTail ? "report-".concat(routeTail) : '';
6644
+ if (routeCandidate && collectionNames.includes(routeCandidate)) {
6645
+ return routeCandidate;
6646
+ }
6647
+ return null;
6648
+ }
6649
+ function resolveBaseCollectionFromReport(db, dbName, collection) {
6650
+ return __awaiter(this, void 0, void 0, function () {
6651
+ var normalized, base, names;
6652
+ return __generator(this, function (_a) {
6653
+ switch (_a.label) {
6654
+ case 0:
6655
+ normalized = normalizeOptionalString(collection);
6656
+ if (!normalized.startsWith('report-')) {
6657
+ return [2 /*return*/, null];
6658
+ }
6659
+ base = stripVersionSuffix(normalized.slice('report-'.length));
6660
+ if (!base) {
6661
+ return [2 /*return*/, null];
6662
+ }
6663
+ return [4 /*yield*/, listAssistantCollections(db, dbName)];
6664
+ case 1:
6665
+ names = _a.sent();
6666
+ return [2 /*return*/, names.includes(base) ? base : null];
6667
+ }
6668
+ });
6669
+ });
6670
+ }
6671
+ function resolveCollectionOverrideWithContext(params) {
6672
+ var requested = normalizeOptionalString(params.requestedCollection);
6673
+ var allowVersions = shouldAllowVersionCollections(params.message);
6674
+ var collectionNames = Array.isArray(params.collectionNames) ? params.collectionNames : [];
6675
+ var permissionView = normalizeOptionalString(params.permissionView);
6676
+ if (permissionView) {
6677
+ var reportPreferred = resolveReportCollectionName(permissionView, collectionNames, requested);
6678
+ if (reportPreferred && reportPreferred !== requested) {
6679
+ return {
6680
+ from: requested,
6681
+ to: reportPreferred,
6682
+ fromScore: 0,
6683
+ toScore: 0,
6684
+ reason: 'report route preference'
6685
+ };
6686
+ }
6687
+ }
6688
+ if (!allowVersions && isVersionCollectionName(requested)) {
6689
+ var base = stripVersionSuffix(requested);
6690
+ if (base && collectionNames.includes(base)) {
6691
+ return {
6692
+ from: requested,
6693
+ to: base,
6694
+ fromScore: 0,
6695
+ toScore: 0,
6696
+ reason: 'avoid versions collection'
6697
+ };
6698
+ }
6699
+ }
6700
+ var rankingOverride = resolveAssistantCollectionOverride(params.collectionRanking, requested);
6701
+ if (rankingOverride) {
6702
+ if (!allowVersions && isVersionCollectionName(rankingOverride.to)) {
6703
+ var base = stripVersionSuffix(rankingOverride.to);
6704
+ if (base && collectionNames.includes(base)) {
6705
+ return {
6706
+ from: requested,
6707
+ to: base,
6708
+ fromScore: rankingOverride.fromScore,
6709
+ toScore: rankingOverride.toScore,
6710
+ reason: 'avoid versions collection'
6711
+ };
6712
+ }
6713
+ }
6714
+ return rankingOverride;
6715
+ }
6716
+ return null;
6717
+ }
5329
6718
  function pickPreferredCollectionCandidate(ranked) {
5330
6719
  if (!Array.isArray(ranked) || !ranked.length) {
5331
6720
  return null;
@@ -5430,7 +6819,7 @@ function resolveAssistantCollectionName(db, dbName, requested) {
5430
6819
  });
5431
6820
  }
5432
6821
  function findQueryDateField(query) {
5433
- var e_10, _a, e_11, _b;
6822
+ var e_21, _a, e_22, _b;
5434
6823
  if (!query || typeof query !== 'object') {
5435
6824
  return null;
5436
6825
  }
@@ -5444,12 +6833,12 @@ function findQueryDateField(query) {
5444
6833
  }
5445
6834
  }
5446
6835
  }
5447
- catch (e_10_1) { e_10 = { error: e_10_1 }; }
6836
+ catch (e_21_1) { e_21 = { error: e_21_1 }; }
5448
6837
  finally {
5449
6838
  try {
5450
6839
  if (query_1_1 && !query_1_1.done && (_a = query_1.return)) _a.call(query_1);
5451
6840
  }
5452
- finally { if (e_10) throw e_10.error; }
6841
+ finally { if (e_21) throw e_21.error; }
5453
6842
  }
5454
6843
  return null;
5455
6844
  }
@@ -5468,12 +6857,12 @@ function findQueryDateField(query) {
5468
6857
  }
5469
6858
  }
5470
6859
  }
5471
- catch (e_11_1) { e_11 = { error: e_11_1 }; }
6860
+ catch (e_22_1) { e_22 = { error: e_22_1 }; }
5472
6861
  finally {
5473
6862
  try {
5474
6863
  if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
5475
6864
  }
5476
- finally { if (e_11) throw e_11.error; }
6865
+ finally { if (e_22) throw e_22.error; }
5477
6866
  }
5478
6867
  return null;
5479
6868
  }
@@ -5629,7 +7018,7 @@ function expandAggregateDateMatchFallback(pipeline) {
5629
7018
  if (!Array.isArray(pipeline)) {
5630
7019
  return null;
5631
7020
  }
5632
- var _loop_2 = function (i) {
7021
+ var _loop_7 = function (i) {
5633
7022
  var stage = pipeline[i];
5634
7023
  if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
5635
7024
  return "continue";
@@ -5677,9 +7066,9 @@ function expandAggregateDateMatchFallback(pipeline) {
5677
7066
  return { value: { pipeline: updated, fields: Array.from(addedFields) } };
5678
7067
  };
5679
7068
  for (var i = 0; i < pipeline.length; i += 1) {
5680
- var state_2 = _loop_2(i);
5681
- if (typeof state_2 === "object")
5682
- return state_2.value;
7069
+ var state_5 = _loop_7(i);
7070
+ if (typeof state_5 === "object")
7071
+ return state_5.value;
5683
7072
  }
5684
7073
  return null;
5685
7074
  }
@@ -5695,7 +7084,7 @@ function resolveQueryDateFieldFallback(query) {
5695
7084
  return { from: dateField, to: fallback };
5696
7085
  }
5697
7086
  function containsForbiddenMongoOperators(value) {
5698
- var e_12, _a;
7087
+ var e_23, _a;
5699
7088
  if (!value || typeof value !== 'object') {
5700
7089
  return false;
5701
7090
  }
@@ -5714,12 +7103,12 @@ function containsForbiddenMongoOperators(value) {
5714
7103
  }
5715
7104
  }
5716
7105
  }
5717
- catch (e_12_1) { e_12 = { error: e_12_1 }; }
7106
+ catch (e_23_1) { e_23 = { error: e_23_1 }; }
5718
7107
  finally {
5719
7108
  try {
5720
7109
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
5721
7110
  }
5722
- finally { if (e_12) throw e_12.error; }
7111
+ finally { if (e_23) throw e_23.error; }
5723
7112
  }
5724
7113
  return false;
5725
7114
  }
@@ -6010,8 +7399,8 @@ function applyCodexStreamStatusHandler(runOptions, streamStatusHandler) {
6010
7399
  }
6011
7400
  function waitForCodexWorkerMessage(worker, streamStatusHandler) {
6012
7401
  return __awaiter(this, void 0, void 0, function () {
6013
- var _a, _b, _c, _d, message, payload, status_1, e_13_1;
6014
- var _e, e_13, _f, _g;
7402
+ var _a, _b, _c, _d, message, payload, status_1, e_24_1;
7403
+ var _e, e_24, _f, _g;
6015
7404
  return __generator(this, function (_h) {
6016
7405
  switch (_h.label) {
6017
7406
  case 0:
@@ -6038,8 +7427,8 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
6038
7427
  return [3 /*break*/, 1];
6039
7428
  case 4: return [3 /*break*/, 11];
6040
7429
  case 5:
6041
- e_13_1 = _h.sent();
6042
- e_13 = { error: e_13_1 };
7430
+ e_24_1 = _h.sent();
7431
+ e_24 = { error: e_24_1 };
6043
7432
  return [3 /*break*/, 11];
6044
7433
  case 6:
6045
7434
  _h.trys.push([6, , 9, 10]);
@@ -6050,7 +7439,7 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
6050
7439
  _h.label = 8;
6051
7440
  case 8: return [3 /*break*/, 10];
6052
7441
  case 9:
6053
- if (e_13) throw e_13.error;
7442
+ if (e_24) throw e_24.error;
6054
7443
  return [7 /*endfinally*/];
6055
7444
  case 10: return [7 /*endfinally*/];
6056
7445
  case 11: throw new CodexWorkerBootstrapError('Codex worker exited before completing.');
@@ -6438,7 +7827,7 @@ function normalizeRouteMatchKey(value) {
6438
7827
  return normalizeRouteKey(value).toLowerCase();
6439
7828
  }
6440
7829
  function buildClientRouteIndex() {
6441
- var e_14, _a;
7830
+ var e_25, _a;
6442
7831
  var _b;
6443
7832
  var routes = ((_b = resolveio_server_app_1.ResolveIOServer.getClientRoutes) === null || _b === void 0 ? void 0 : _b.call(resolveio_server_app_1.ResolveIOServer)) || [];
6444
7833
  var set = new Set();
@@ -6457,12 +7846,12 @@ function buildClientRouteIndex() {
6457
7846
  }
6458
7847
  }
6459
7848
  }
6460
- catch (e_14_1) { e_14 = { error: e_14_1 }; }
7849
+ catch (e_25_1) { e_25 = { error: e_25_1 }; }
6461
7850
  finally {
6462
7851
  try {
6463
7852
  if (routes_1_1 && !routes_1_1.done && (_a = routes_1.return)) _a.call(routes_1);
6464
7853
  }
6465
- finally { if (e_14) throw e_14.error; }
7854
+ finally { if (e_25) throw e_25.error; }
6466
7855
  }
6467
7856
  return { set: set, map: map, size: routes.length };
6468
7857
  }
@@ -6605,7 +7994,7 @@ function sanitizeAssistantResponse(value) {
6605
7994
  return normalizeAssistantRoutes(normalizedCurrency);
6606
7995
  }
6607
7996
  function evaluateAssistantGuardrails(message) {
6608
- var e_15, _a;
7997
+ var e_26, _a;
6609
7998
  var normalized = String(message || '').toLowerCase();
6610
7999
  var patterns = [
6611
8000
  {
@@ -6651,12 +8040,12 @@ function evaluateAssistantGuardrails(message) {
6651
8040
  }
6652
8041
  }
6653
8042
  }
6654
- catch (e_15_1) { e_15 = { error: e_15_1 }; }
8043
+ catch (e_26_1) { e_26 = { error: e_26_1 }; }
6655
8044
  finally {
6656
8045
  try {
6657
8046
  if (patterns_1_1 && !patterns_1_1.done && (_a = patterns_1.return)) _a.call(patterns_1);
6658
8047
  }
6659
- finally { if (e_15) throw e_15.error; }
8048
+ finally { if (e_26) throw e_26.error; }
6660
8049
  }
6661
8050
  return null;
6662
8051
  }
@@ -6771,7 +8160,7 @@ function tokenizeArithmeticExpression(expression) {
6771
8160
  return tokens;
6772
8161
  }
6773
8162
  function evaluateArithmeticExpression(expression) {
6774
- var e_16, _a, e_17, _b;
8163
+ var e_27, _a, e_28, _b;
6775
8164
  var tokens = tokenizeArithmeticExpression(expression);
6776
8165
  if (!tokens || !tokens.length) {
6777
8166
  return null;
@@ -6828,12 +8217,12 @@ function evaluateArithmeticExpression(expression) {
6828
8217
  prevToken = token;
6829
8218
  }
6830
8219
  }
6831
- catch (e_16_1) { e_16 = { error: e_16_1 }; }
8220
+ catch (e_27_1) { e_27 = { error: e_27_1 }; }
6832
8221
  finally {
6833
8222
  try {
6834
8223
  if (tokens_1_1 && !tokens_1_1.done && (_a = tokens_1.return)) _a.call(tokens_1);
6835
8224
  }
6836
- finally { if (e_16) throw e_16.error; }
8225
+ finally { if (e_27) throw e_27.error; }
6837
8226
  }
6838
8227
  while (ops.length) {
6839
8228
  var op = ops.pop();
@@ -6873,12 +8262,12 @@ function evaluateArithmeticExpression(expression) {
6873
8262
  stack.push(Number(token));
6874
8263
  }
6875
8264
  }
6876
- catch (e_17_1) { e_17 = { error: e_17_1 }; }
8265
+ catch (e_28_1) { e_28 = { error: e_28_1 }; }
6877
8266
  finally {
6878
8267
  try {
6879
8268
  if (output_1_1 && !output_1_1.done && (_b = output_1.return)) _b.call(output_1);
6880
8269
  }
6881
- finally { if (e_17) throw e_17.error; }
8270
+ finally { if (e_28) throw e_28.error; }
6882
8271
  }
6883
8272
  if (stack.length !== 1 || Number.isNaN(stack[0])) {
6884
8273
  return null;
@@ -7062,8 +8451,8 @@ function handleCodexUpload(id_conversation, file_name, content_base64, size, con
7062
8451
  }
7063
8452
  function readAttachmentContents(attachments) {
7064
8453
  return __awaiter(this, void 0, void 0, function () {
7065
- var limits, totalBytes, totalChars, chunks, cleaned, attachments_1, attachments_1_1, attachment, localPath, safe, stat, ext, name_1, type, readable, content, _a, e_18_1;
7066
- var e_18, _b;
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;
7067
8456
  return __generator(this, function (_c) {
7068
8457
  switch (_c.label) {
7069
8458
  case 0:
@@ -7142,14 +8531,14 @@ function readAttachmentContents(attachments) {
7142
8531
  return [3 /*break*/, 2];
7143
8532
  case 10: return [3 /*break*/, 13];
7144
8533
  case 11:
7145
- e_18_1 = _c.sent();
7146
- e_18 = { error: e_18_1 };
8534
+ e_29_1 = _c.sent();
8535
+ e_29 = { error: e_29_1 };
7147
8536
  return [3 /*break*/, 13];
7148
8537
  case 12:
7149
8538
  try {
7150
8539
  if (attachments_1_1 && !attachments_1_1.done && (_b = attachments_1.return)) _b.call(attachments_1);
7151
8540
  }
7152
- finally { if (e_18) throw e_18.error; }
8541
+ finally { if (e_29) throw e_29.error; }
7153
8542
  return [7 /*endfinally*/];
7154
8543
  case 13: return [2 /*return*/, {
7155
8544
  promptText: chunks.length ? "\n\nAttachments:\n".concat(chunks.join('\n\n')) : '',
@@ -7270,6 +8659,17 @@ function normalizeOptionalString(value) {
7270
8659
  var raw = typeof value === 'string' ? value.trim() : '';
7271
8660
  return raw || '';
7272
8661
  }
8662
+ function resolveSingleWorkerTarget(value) {
8663
+ var normalized = normalizeOptionalString(value);
8664
+ if (!normalized) {
8665
+ return '';
8666
+ }
8667
+ var parts = normalized.split(',').map(function (part) { return part.trim(); }).filter(Boolean);
8668
+ if (parts.length !== 1) {
8669
+ return '';
8670
+ }
8671
+ return parts[0];
8672
+ }
7273
8673
  function normalizeConversationMode(value) {
7274
8674
  var normalized = normalizeOptionalString(value).toLowerCase();
7275
8675
  if (normalized === 'codex') {
@@ -7326,7 +8726,7 @@ function estimateUsage(messages, responseText, model) {
7326
8726
  };
7327
8727
  }
7328
8728
  function evaluateGuardrails(message) {
7329
- var e_19, _a;
8729
+ var e_30, _a;
7330
8730
  var normalized = String(message || '').toLowerCase();
7331
8731
  var patterns = [
7332
8732
  { 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.' },
@@ -7348,12 +8748,12 @@ function evaluateGuardrails(message) {
7348
8748
  }
7349
8749
  }
7350
8750
  }
7351
- catch (e_19_1) { e_19 = { error: e_19_1 }; }
8751
+ catch (e_30_1) { e_30 = { error: e_30_1 }; }
7352
8752
  finally {
7353
8753
  try {
7354
8754
  if (patterns_2_1 && !patterns_2_1.done && (_a = patterns_2.return)) _a.call(patterns_2);
7355
8755
  }
7356
- finally { if (e_19) throw e_19.error; }
8756
+ finally { if (e_30) throw e_30.error; }
7357
8757
  }
7358
8758
  return null;
7359
8759
  }