@resolveio/server-lib 20.15.8 → 20.15.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -109,16 +109,21 @@ exports.loadAiTerminalMethods = loadAiTerminalMethods;
109
109
  exports.executeAiAssistantMongoRead = executeAiAssistantMongoRead;
110
110
  exports.executeAiAssistantMongoAggregate = executeAiAssistantMongoAggregate;
111
111
  exports.extractAssistantMongoDirective = extractAssistantMongoDirective;
112
+ exports.normalizeIdsForTargetField = normalizeIdsForTargetField;
112
113
  exports.serializeMongoValue = serializeMongoValue;
113
114
  exports.flattenForTable = flattenForTable;
114
115
  exports.buildDisplayTable = buildDisplayTable;
115
116
  exports.formatDisplayTableMarkdown = formatDisplayTableMarkdown;
117
+ exports.stripQueryFieldPathsDeep = stripQueryFieldPathsDeep;
118
+ exports.stripScopedFieldsFromPipeline = stripScopedFieldsFromPipeline;
119
+ exports.rewriteEmbeddedMatchObjects = rewriteEmbeddedMatchObjects;
116
120
  var fs_1 = require("fs");
117
121
  var events_1 = require("events");
118
122
  var os = require("os");
119
123
  var path = require("path");
120
124
  var promises_1 = require("timers/promises");
121
125
  var worker_threads_1 = require("worker_threads");
126
+ var mongodb_1 = require("mongodb");
122
127
  var simpl_schema_1 = require("simpl-schema");
123
128
  var resolveio_server_app_1 = require("../resolveio-server-app");
124
129
  var user_collection_1 = require("../collections/user.collection");
@@ -145,6 +150,11 @@ var AI_ASSISTANT_DISPLAY_STRING_LIMIT = 160;
145
150
  var AI_ASSISTANT_PROGRESS_PLACEHOLDER = 'Planning...';
146
151
  var AI_ASSISTANT_PROGRESS_TICK_MS = 5000;
147
152
  var AI_ASSISTANT_READ_PREFERENCE = 'secondary';
153
+ var AI_ASSISTANT_PROBE_LIMIT = 3;
154
+ var AI_ASSISTANT_COLLECTION_OVERRIDE_SCORE_GAP = 20;
155
+ var AI_ASSISTANT_COLLECTION_OVERRIDE_MIN_SCORE = 20;
156
+ var AI_ASSISTANT_ID_LOOKUP_MAX_RESULTS = 20;
157
+ var AI_ASSISTANT_ID_LOOKUP_CANDIDATE_LIMIT = 4;
148
158
  var AI_ASSISTANT_NAME_MATCH_FALLBACK_MAX_FIELDS = 12;
149
159
  var AI_ASSISTANT_PROGRESS_TICKS = [
150
160
  'Grabbing Data',
@@ -176,6 +186,15 @@ var AI_ASSISTANT_DATE_FALLBACKS = {
176
186
  date_invoice: 'date_invoiced',
177
187
  date_invoiced: 'date_invoice'
178
188
  };
189
+ var AI_ASSISTANT_DATE_EXPANSION_FIELDS = [
190
+ 'date',
191
+ 'date_start',
192
+ 'date_end',
193
+ 'date_original',
194
+ 'date_created',
195
+ 'createdAt',
196
+ 'updatedAt'
197
+ ];
179
198
  var AI_ASSISTANT_BLOCKED_COLLECTIONS = new Set([
180
199
  'user-groups',
181
200
  'logged-in-users',
@@ -202,6 +221,7 @@ var AI_ASSISTANT_SENSITIVE_FIELDS = [
202
221
  'roles'
203
222
  ];
204
223
  var AI_ASSISTANT_CLIENT_SCOPE_CACHE = new Map();
224
+ var AI_ASSISTANT_FIELD_INDEX_CACHE = new Map();
205
225
  var AI_ASSISTANT_COLLECTION_CACHE = new Map();
206
226
  var AI_ASSISTANT_COLLECTION_CACHE_TTL_MS = 5 * 60 * 1000;
207
227
  var AI_ASSISTANT_COLLECTION_STOPWORDS = new Set([
@@ -247,11 +267,72 @@ var AI_ASSISTANT_COLLECTION_STOPWORDS = new Set([
247
267
  'missing',
248
268
  'overdue'
249
269
  ]);
270
+ var AI_ASSISTANT_COLLECTION_DOMAIN_TOKENS = new Set([
271
+ 'blend',
272
+ 'blends',
273
+ 'chemical',
274
+ 'chemicals',
275
+ 'invoice',
276
+ 'invoices',
277
+ 'work',
278
+ 'order',
279
+ 'orders',
280
+ 'delivery',
281
+ 'deliveries',
282
+ 'truck',
283
+ 'treating',
284
+ 'route',
285
+ 'routes',
286
+ 'well',
287
+ 'wells',
288
+ 'sample',
289
+ 'samples',
290
+ 'customer',
291
+ 'customers'
292
+ ]);
293
+ var AI_ASSISTANT_COLLECTION_GENERIC_TOKENS = new Set([
294
+ 'ticket',
295
+ 'tickets',
296
+ 'report',
297
+ 'reports',
298
+ 'summary',
299
+ 'summarize',
300
+ 'recent',
301
+ 'last',
302
+ 'new',
303
+ 'created',
304
+ 'date',
305
+ 'list',
306
+ 'show'
307
+ ]);
308
+ var AI_ASSISTANT_FIELD_TOKEN_SYNONYMS = {
309
+ volume: ['quantity', 'qty', 'amount', 'gallons', 'gallon', 'liters', 'liter', 'litre'],
310
+ quantity: ['volume', 'qty', 'amount', 'gallons', 'gallon'],
311
+ product: ['item', 'chemical', 'material', 'blend', 'name', 'title', 'label'],
312
+ customer: ['client', 'account', 'company'],
313
+ well: ['location', 'site', 'pad', 'api'],
314
+ batch: ['lot'],
315
+ lot: ['batch'],
316
+ date: ['created', 'createdat', 'created_at', 'date_created', 'updated', 'updatedat', 'updated_at', 'date_updated'],
317
+ total: ['sum', 'amount', 'total_amount', 'total_quantity']
318
+ };
319
+ var AI_ASSISTANT_ID_LOOKUP_HINTS = {
320
+ customer: ['customers', 'customer-versions'],
321
+ chemical: ['chemicals', 'chemical-versions'],
322
+ well: ['wells', 'well-groups', 'production-locations', 'locations'],
323
+ location: ['locations', 'production-locations'],
324
+ invoice: ['invoices']
325
+ };
250
326
  var AI_ASSISTANT_TERM_SYNONYMS = [
251
327
  {
252
328
  label: 'truck treating jobs',
253
329
  pattern: /\btruck\s+treating\s+jobs?\b/i,
254
330
  expansions: ['truck treating deliveries', 'truck-treating-deliveries', 'truck treating route events']
331
+ },
332
+ {
333
+ label: 'blend tickets',
334
+ pattern: /\bblend(?:ing)?\s+tickets?\b/i,
335
+ expansions: ['chemical blends', 'chemical-blends', 'report-chemical-blends', 'blend batches']
255
336
  }
256
337
  ];
257
338
  var AI_ASSISTANT_SYSTEM_PROMPT = [
@@ -278,6 +359,7 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
278
359
  '- 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.',
279
360
  '- Assume a relevant collection exists; if verification reads return zero data, report no data found instead of interrogating the user.',
280
361
  '- 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
+ '- If a query returns zero rows, run a tiny probe read (limit 1-3) to validate fields and adjust filters/projection before concluding.',
281
363
  '- For direct questions, answer first. Ask a single follow-up only if required to proceed.',
282
364
  'Data Presentation:',
283
365
  '- Output plain Markdown (NO triple backticks).',
@@ -1049,10 +1131,10 @@ function executeAiAssistantCodexRun(payload, context) {
1049
1131
  insertResult = _d.sent();
1050
1132
  assistantMessageId = (insertResult === null || insertResult === void 0 ? void 0 : insertResult._id) || (insertResult === null || insertResult === void 0 ? void 0 : insertResult.insertedId);
1051
1133
  enqueueAssistantCodexRun(function () { return __awaiter(_this, void 0, void 0, function () {
1052
- var runStart, steps, recordStep, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, dataQuestion, lastDirective, toolResponseDebug, toolError, termHints, collectionHints, collectionTokenization, collectionRanking, collectionSelection, timingBreakdown, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, dbName, db, collectionNames, _a, assistantContext, prompt_1, workspaceRoot, codexConfig, runOptions, responseText, directiveText, directive, directivePrompt, directiveStart, forcedDirective, _b, initialStart, directivePrompt, forcedStart, forcedDirective, _c, cleanedResponseText, toolRequest, toolStart, toolResponse, _d, toolPayload, followupPrompt, followupStart, followupText, _e, error_2, error_3, finalNow, finishedAt, codexMs, draftingMs, finalMetadata, finalAssistantDoc;
1053
- var _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
1054
- return __generator(this, function (_s) {
1055
- switch (_s.label) {
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) {
1056
1138
  case 0:
1057
1139
  runStart = Date.now();
1058
1140
  steps = [];
@@ -1079,6 +1161,7 @@ function executeAiAssistantCodexRun(payload, context) {
1079
1161
  collectionTokenization = null;
1080
1162
  collectionRanking = null;
1081
1163
  collectionSelection = null;
1164
+ collectionOverride = null;
1082
1165
  timingBreakdown = {
1083
1166
  directiveMs: 0,
1084
1167
  initialResponseMs: 0,
@@ -1089,37 +1172,42 @@ function executeAiAssistantCodexRun(payload, context) {
1089
1172
  contextRoute = normalizeOptionalString((_f = input === null || input === void 0 ? void 0 : input.context) === null || _f === void 0 ? void 0 : _f.route);
1090
1173
  contextMode = normalizeOptionalString((_g = input === null || input === void 0 ? void 0 : input.context) === null || _g === void 0 ? void 0 : _g.mode);
1091
1174
  recordStep('Queued', { requestId: requestId || undefined });
1092
- _s.label = 1;
1175
+ _t.label = 1;
1093
1176
  case 1:
1094
- _s.trys.push([1, 30, 31, 32]);
1177
+ _t.trys.push([1, 30, 31, 32]);
1095
1178
  hintSeed = [message, contextRoute].filter(Boolean).join(' ');
1096
1179
  termExpansion = expandAssistantTermSynonyms(hintSeed);
1097
1180
  hintText = termExpansion.expanded || hintSeed;
1098
1181
  termHints = termExpansion.matches.map(function (match) { return "".concat(match.term, " -> ").concat(match.expansions.join(', ')); });
1099
1182
  baseTokens = tokenizeCollectionText(hintSeed);
1100
1183
  expandedTokens = tokenizeCollectionText(hintText);
1184
+ baseWeights = computeCollectionTokenWeights(baseTokens);
1185
+ expandedWeights = computeCollectionTokenWeights(expandedTokens);
1101
1186
  collectionTokenization = {
1102
1187
  baseText: hintSeed || undefined,
1103
1188
  expandedText: hintText || undefined,
1104
1189
  baseTokens: baseTokens.length ? baseTokens : undefined,
1105
- expandedTokens: expandedTokens.length ? expandedTokens : undefined
1190
+ expandedTokens: expandedTokens.length ? expandedTokens : undefined,
1191
+ baseTokenWeights: baseTokens.length ? baseWeights.weights : undefined,
1192
+ expandedTokenWeights: expandedTokens.length ? expandedWeights.weights : undefined,
1193
+ hasDomainTokens: expandedTokens.length ? expandedWeights.hasDomain : undefined
1106
1194
  };
1107
1195
  recordStep('Planning: term expansion', {
1108
1196
  termMatches: termExpansion.matches.length ? termExpansion.matches : undefined
1109
1197
  });
1110
- _s.label = 2;
1198
+ _t.label = 2;
1111
1199
  case 2:
1112
- _s.trys.push([2, 4, , 5]);
1200
+ _t.trys.push([2, 4, , 5]);
1113
1201
  dbName = resolveAssistantDatabaseName(undefined, input.mongo);
1114
1202
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1115
1203
  return [4 /*yield*/, listAssistantCollections(db, dbName)];
1116
1204
  case 3:
1117
- collectionNames = _s.sent();
1205
+ collectionNames = _t.sent();
1118
1206
  collectionHints = resolveCollectionHintsFromTokens(expandedTokens, collectionNames, 5);
1119
1207
  collectionRanking = buildCollectionRankingDebugFromTokens(expandedTokens, collectionNames, 8);
1120
1208
  return [3 /*break*/, 5];
1121
1209
  case 4:
1122
- _a = _s.sent();
1210
+ _a = _t.sent();
1123
1211
  collectionHints = [];
1124
1212
  collectionRanking = collectionRanking || ((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens)
1125
1213
  ? buildCollectionRankingDebugFromTokens(collectionTokenization.expandedTokens || [], [], 0)
@@ -1142,7 +1230,7 @@ function executeAiAssistantCodexRun(payload, context) {
1142
1230
  prompt_1 = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1143
1231
  return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
1144
1232
  case 6:
1145
- workspaceRoot = _s.sent();
1233
+ workspaceRoot = _t.sent();
1146
1234
  codexConfig = resolveCodexSettings();
1147
1235
  runOptions = {
1148
1236
  timeoutMs: resolveCodexTimeoutMs(),
@@ -1163,13 +1251,13 @@ function executeAiAssistantCodexRun(payload, context) {
1163
1251
  if (!dataQuestion) return [3 /*break*/, 10];
1164
1252
  recordStep('Directive: determine tool', { type: 'data-question' });
1165
1253
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1166
- _s.label = 7;
1254
+ _t.label = 7;
1167
1255
  case 7:
1168
- _s.trys.push([7, 9, , 10]);
1256
+ _t.trys.push([7, 9, , 10]);
1169
1257
  directiveStart = Date.now();
1170
1258
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1171
1259
  case 8:
1172
- directiveText = _s.sent();
1260
+ directiveText = _t.sent();
1173
1261
  timingBreakdown.directiveMs = Date.now() - directiveStart;
1174
1262
  forcedDirective = extractAssistantMongoDirective(directiveText);
1175
1263
  if (forcedDirective) {
@@ -1186,7 +1274,7 @@ function executeAiAssistantCodexRun(payload, context) {
1186
1274
  }
1187
1275
  return [3 /*break*/, 10];
1188
1276
  case 9:
1189
- _b = _s.sent();
1277
+ _b = _t.sent();
1190
1278
  return [3 /*break*/, 10];
1191
1279
  case 10:
1192
1280
  if (!!directive) return [3 /*break*/, 12];
@@ -1194,7 +1282,7 @@ function executeAiAssistantCodexRun(payload, context) {
1194
1282
  initialStart = Date.now();
1195
1283
  return [4 /*yield*/, runCodexInWorkerThread(prompt_1, runOptions, codexConfig, streamProgress)];
1196
1284
  case 11:
1197
- responseText = _s.sent();
1285
+ responseText = _t.sent();
1198
1286
  timingBreakdown.initialResponseMs = Date.now() - initialStart;
1199
1287
  directive = extractAssistantMongoDirective(responseText);
1200
1288
  if (directive) {
@@ -1208,18 +1296,18 @@ function executeAiAssistantCodexRun(payload, context) {
1208
1296
  permissionView: normalizeOptionalString((_o = directive.payload) === null || _o === void 0 ? void 0 : _o.permissionView) || undefined
1209
1297
  });
1210
1298
  }
1211
- _s.label = 12;
1299
+ _t.label = 12;
1212
1300
  case 12:
1213
1301
  if (!(!directive && dataQuestion)) return [3 /*break*/, 16];
1214
1302
  recordStep('Directive: forced retry', { mode: 'directive-only' });
1215
1303
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1216
- _s.label = 13;
1304
+ _t.label = 13;
1217
1305
  case 13:
1218
- _s.trys.push([13, 15, , 16]);
1306
+ _t.trys.push([13, 15, , 16]);
1219
1307
  forcedStart = Date.now();
1220
1308
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1221
1309
  case 14:
1222
- directiveText = _s.sent();
1310
+ directiveText = _t.sent();
1223
1311
  timingBreakdown.forcedDirectiveMs = Date.now() - forcedStart;
1224
1312
  forcedDirective = extractAssistantMongoDirective(directiveText);
1225
1313
  if (forcedDirective) {
@@ -1236,41 +1324,55 @@ function executeAiAssistantCodexRun(payload, context) {
1236
1324
  }
1237
1325
  return [3 /*break*/, 16];
1238
1326
  case 15:
1239
- _c = _s.sent();
1327
+ _c = _t.sent();
1240
1328
  return [3 /*break*/, 16];
1241
1329
  case 16:
1330
+ if (directive) {
1331
+ requestedCollection = normalizeOptionalString((_s = directive.payload) === null || _s === void 0 ? void 0 : _s.collection);
1332
+ collectionOverride = resolveAssistantCollectionOverride(collectionRanking, requestedCollection);
1333
+ if (collectionOverride) {
1334
+ recordStep('Planning: collection override', {
1335
+ from: collectionOverride.from || undefined,
1336
+ to: collectionOverride.to,
1337
+ reason: collectionOverride.reason,
1338
+ scoreGap: collectionOverride.toScore - collectionOverride.fromScore
1339
+ });
1340
+ }
1341
+ }
1242
1342
  cleanedResponseText = (directive === null || directive === void 0 ? void 0 : directive.cleaned) || responseText;
1243
1343
  if (cleanedResponseText) {
1244
1344
  assistantContent = sanitizeAssistantResponse(cleanedResponseText);
1245
1345
  }
1246
1346
  if (!((directive === null || directive === void 0 ? void 0 : directive.payload) && AI_ASSISTANT_TOOL_MAX_STEPS > 0)) return [3 /*break*/, 28];
1247
- toolRequest = buildAssistantToolRequest(directive, input);
1347
+ effectiveDirective = collectionOverride
1348
+ ? __assign(__assign({}, directive), { payload: __assign(__assign({}, (directive.payload || {})), { collection: collectionOverride.to }) }) : directive;
1349
+ toolRequest = buildAssistantToolRequest(effectiveDirective, input);
1248
1350
  progressTracker.push('Grabbing Data');
1249
1351
  recordStep('Grabbing Data: start', {
1250
- type: directive.type,
1352
+ type: effectiveDirective.type,
1251
1353
  collection: normalizeOptionalString(toolRequest === null || toolRequest === void 0 ? void 0 : toolRequest.collection) || undefined,
1252
1354
  permissionView: normalizeOptionalString(toolRequest === null || toolRequest === void 0 ? void 0 : toolRequest.permissionView) || undefined
1253
1355
  });
1254
- _s.label = 17;
1356
+ _t.label = 17;
1255
1357
  case 17:
1256
- _s.trys.push([17, 26, , 27]);
1358
+ _t.trys.push([17, 26, , 27]);
1257
1359
  toolStart = Date.now();
1258
- if (!(directive.type === 'aggregate')) return [3 /*break*/, 19];
1360
+ if (!(effectiveDirective.type === 'aggregate')) return [3 /*break*/, 19];
1259
1361
  return [4 /*yield*/, executeAiAssistantMongoAggregate(toolRequest, context)];
1260
1362
  case 18:
1261
- _d = _s.sent();
1363
+ _d = _t.sent();
1262
1364
  return [3 /*break*/, 21];
1263
1365
  case 19: return [4 /*yield*/, executeAiAssistantMongoRead(toolRequest, context)];
1264
1366
  case 20:
1265
- _d = _s.sent();
1266
- _s.label = 21;
1367
+ _d = _t.sent();
1368
+ _t.label = 21;
1267
1369
  case 21:
1268
1370
  toolResponse = _d;
1269
1371
  timingBreakdown.toolMs = Date.now() - toolStart;
1270
1372
  toolResponseDebug = (toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.debug) && typeof toolResponse.debug === 'object'
1271
1373
  ? toolResponse.debug
1272
1374
  : null;
1273
- toolPayload = buildAssistantToolResultPayload(directive, toolResponse);
1375
+ toolPayload = buildAssistantToolResultPayload(effectiveDirective, toolResponse);
1274
1376
  toolResult = toolPayload.result;
1275
1377
  recordStep('Grabbing Data: complete', {
1276
1378
  rowCount: toolPayload.result.output.rowCount,
@@ -1280,23 +1382,23 @@ function executeAiAssistantCodexRun(payload, context) {
1280
1382
  progressTracker.push('Drafting response');
1281
1383
  recordStep('Drafting response');
1282
1384
  followupPrompt = buildAssistantCodexToolFollowupPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, toolPayload.prompt);
1283
- _s.label = 22;
1385
+ _t.label = 22;
1284
1386
  case 22:
1285
- _s.trys.push([22, 24, , 25]);
1387
+ _t.trys.push([22, 24, , 25]);
1286
1388
  followupStart = Date.now();
1287
1389
  return [4 /*yield*/, runCodexInWorkerThread(followupPrompt, runOptions, codexConfig, streamProgress)];
1288
1390
  case 23:
1289
- followupText = _s.sent();
1391
+ followupText = _t.sent();
1290
1392
  timingBreakdown.followupMs = Date.now() - followupStart;
1291
1393
  assistantContent = sanitizeAssistantResponse(followupText);
1292
1394
  return [3 /*break*/, 25];
1293
1395
  case 24:
1294
- _e = _s.sent();
1396
+ _e = _t.sent();
1295
1397
  assistantContent = buildAssistantToolFallbackResponse(toolPayload.result);
1296
1398
  return [3 /*break*/, 25];
1297
1399
  case 25: return [3 /*break*/, 27];
1298
1400
  case 26:
1299
- error_2 = _s.sent();
1401
+ error_2 = _t.sent();
1300
1402
  assistantContent = buildAssistantToolErrorMessage(error_2, directive, toolRequest);
1301
1403
  toolError = error_2;
1302
1404
  return [3 /*break*/, 27];
@@ -1304,10 +1406,10 @@ function executeAiAssistantCodexRun(payload, context) {
1304
1406
  case 28:
1305
1407
  progressTracker.push('Drafting response');
1306
1408
  recordStep('Drafting response');
1307
- _s.label = 29;
1409
+ _t.label = 29;
1308
1410
  case 29: return [3 /*break*/, 32];
1309
1411
  case 30:
1310
- error_3 = _s.sent();
1412
+ error_3 = _t.sent();
1311
1413
  assistantContent = buildAssistantCodexErrorMessage(error_3);
1312
1414
  recordStep('Error', { message: normalizeOptionalString(error_3 === null || error_3 === void 0 ? void 0 : error_3.message) || 'Unknown error' });
1313
1415
  return [3 /*break*/, 32];
@@ -1333,6 +1435,7 @@ function executeAiAssistantCodexRun(payload, context) {
1333
1435
  toolResult: toolResult,
1334
1436
  toolResponseDebug: toolResponseDebug,
1335
1437
  toolError: toolError,
1438
+ collectionOverride: collectionOverride,
1336
1439
  trace: {
1337
1440
  steps: steps,
1338
1441
  planning: {
@@ -1342,7 +1445,8 @@ function executeAiAssistantCodexRun(payload, context) {
1342
1445
  collectionHints: collectionHints.length ? collectionHints : undefined,
1343
1446
  collectionTokenization: collectionTokenization || undefined,
1344
1447
  collectionRanking: collectionRanking || undefined,
1345
- collectionSelection: collectionSelection || undefined
1448
+ collectionSelection: collectionSelection || undefined,
1449
+ collectionOverride: collectionOverride || undefined
1346
1450
  },
1347
1451
  timings: {
1348
1452
  startedAt: new Date(runStart).toISOString(),
@@ -1370,16 +1474,16 @@ function executeAiAssistantCodexRun(payload, context) {
1370
1474
  }
1371
1475
  })];
1372
1476
  case 33:
1373
- _s.sent();
1374
- _s.label = 34;
1477
+ _t.sent();
1478
+ _t.label = 34;
1375
1479
  case 34: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
1376
1480
  case 35:
1377
- _s.sent();
1481
+ _t.sent();
1378
1482
  if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 37];
1379
1483
  return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
1380
1484
  case 36:
1381
- _s.sent();
1382
- _s.label = 37;
1485
+ _t.sent();
1486
+ _t.label = 37;
1383
1487
  case 37: return [2 /*return*/, finalAssistantDoc];
1384
1488
  }
1385
1489
  });
@@ -1393,10 +1497,10 @@ function executeAiAssistantCodexRun(payload, context) {
1393
1497
  }
1394
1498
  function executeAiAssistantMongoRead(payload, context) {
1395
1499
  return __awaiter(this, void 0, void 0, function () {
1396
- var input, rawCollection, dbName, db, collectionResolution, collection, _a, user, isSuperAdmin, customerId, baseQuery, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalized, findOptions, documents, executedQuery, fallbackMeta, dateFallback, fallbackQuery, fallbackDocs, expanded, fallbackDocs, total, sanitizedDocuments, includeIds, requestedFields, fieldAliases, displayDocs, priorityFields, display;
1397
- var _c, _d;
1398
- return __generator(this, function (_e) {
1399
- switch (_e.label) {
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) {
1400
1504
  case 0:
1401
1505
  input = payload || {};
1402
1506
  rawCollection = normalizeOptionalString(input.collection);
@@ -1407,16 +1511,26 @@ function executeAiAssistantMongoRead(payload, context) {
1407
1511
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1408
1512
  return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
1409
1513
  case 1:
1410
- collectionResolution = _e.sent();
1514
+ collectionResolution = _h.sent();
1411
1515
  collection = collectionResolution.name || rawCollection;
1412
1516
  return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
1413
1517
  case 2:
1414
- _a = _e.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1518
+ _a = _h.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1415
1519
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
1416
1520
  throw new Error('AI assistant mongo read: Access denied.');
1417
1521
  }
1418
- customerId = normalizeOptionalString((_c = user === null || user === void 0 ? void 0 : user.other) === null || _c === void 0 ? void 0 : _c.id_customer);
1522
+ customerId = normalizeOptionalString((_f = user === null || user === void 0 ? void 0 : user.other) === null || _f === void 0 ? void 0 : _f.id_customer);
1523
+ fallbackMeta = {};
1419
1524
  baseQuery = normalizeMongoQuery(input.query);
1525
+ if (!isSuperAdmin && customerId) {
1526
+ stripped = stripQueryFieldPathsDeepWithMeta(baseQuery, ['id_customer', 'other.id_customer']);
1527
+ baseQuery = stripped.value;
1528
+ fallbackMeta.scopeStrip = {
1529
+ attempted: true,
1530
+ fields: ['id_customer', 'other.id_customer'],
1531
+ used: stripped.changed
1532
+ };
1533
+ }
1420
1534
  if (!isSuperAdmin && (collection === 'users' || collection === 'user-versions')) {
1421
1535
  userId = normalizeOptionalString(user === null || user === void 0 ? void 0 : user._id);
1422
1536
  if (!userId) {
@@ -1430,13 +1544,22 @@ function executeAiAssistantMongoRead(payload, context) {
1430
1544
  if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 4];
1431
1545
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
1432
1546
  case 3:
1433
- _b = _e.sent();
1547
+ _b = _h.sent();
1434
1548
  return [3 /*break*/, 5];
1435
1549
  case 4:
1436
1550
  _b = false;
1437
- _e.label = 5;
1551
+ _h.label = 5;
1438
1552
  case 5:
1439
1553
  shouldScopeByClient = _b;
1554
+ if (!isSuperAdmin && shouldScopeByClient) {
1555
+ strippedClient = stripQueryFieldPathsDeepWithMeta(baseQuery, ['id_client']);
1556
+ baseQuery = strippedClient.value;
1557
+ fallbackMeta.scopeStripClient = {
1558
+ attempted: true,
1559
+ fields: ['id_client'],
1560
+ used: strippedClient.changed
1561
+ };
1562
+ }
1440
1563
  clientScopedQuery = shouldScopeByClient
1441
1564
  ? applyClientScopeFilter(baseQuery, normalizedClient, isSuperAdmin)
1442
1565
  : baseQuery;
@@ -1445,26 +1568,26 @@ function executeAiAssistantMongoRead(payload, context) {
1445
1568
  findOptions = __assign(__assign({}, normalized.findOptions), { readPreference: AI_ASSISTANT_READ_PREFERENCE });
1446
1569
  return [4 /*yield*/, db.collection(collection).find(scopedQuery, findOptions).toArray()];
1447
1570
  case 6:
1448
- documents = _e.sent();
1571
+ documents = _h.sent();
1449
1572
  executedQuery = scopedQuery;
1450
- fallbackMeta = {};
1451
- if (!!documents.length) return [3 /*break*/, 10];
1573
+ probeDocs = null;
1574
+ if (!!documents.length) return [3 /*break*/, 8];
1452
1575
  dateFallback = resolveQueryDateFieldFallback(scopedQuery);
1453
1576
  if (!dateFallback) return [3 /*break*/, 8];
1454
1577
  fallbackQuery = replaceQueryField(scopedQuery, dateFallback.from, dateFallback.to);
1455
1578
  fallbackMeta.dateField = __assign(__assign({}, dateFallback), { attempted: true, used: false });
1456
1579
  return [4 /*yield*/, db.collection(collection).find(fallbackQuery, findOptions).toArray()];
1457
1580
  case 7:
1458
- fallbackDocs = _e.sent();
1581
+ fallbackDocs = _h.sent();
1459
1582
  if (fallbackDocs.length) {
1460
1583
  documents = fallbackDocs;
1461
1584
  executedQuery = fallbackQuery;
1462
1585
  fallbackMeta.dateField.used = true;
1463
1586
  }
1464
- _e.label = 8;
1587
+ _h.label = 8;
1465
1588
  case 8:
1466
1589
  if (!!documents.length) return [3 /*break*/, 10];
1467
- expanded = expandQueryDateFallbacks(scopedQuery);
1590
+ expanded = expandQueryDateFallbacks(executedQuery);
1468
1591
  if (!expanded) return [3 /*break*/, 10];
1469
1592
  fallbackMeta.dateFieldsExpanded = {
1470
1593
  fields: expanded.fields,
@@ -1473,26 +1596,167 @@ function executeAiAssistantMongoRead(payload, context) {
1473
1596
  };
1474
1597
  return [4 /*yield*/, db.collection(collection).find(expanded.query, findOptions).toArray()];
1475
1598
  case 9:
1476
- fallbackDocs = _e.sent();
1599
+ fallbackDocs = _h.sent();
1477
1600
  if (fallbackDocs.length) {
1478
1601
  documents = fallbackDocs;
1479
1602
  executedQuery = expanded.query;
1480
1603
  fallbackMeta.dateFieldsExpanded.used = true;
1481
1604
  }
1482
- _e.label = 10;
1605
+ _h.label = 10;
1483
1606
  case 10:
1484
- total = null;
1485
- if (!normalized.includeTotal) return [3 /*break*/, 12];
1486
- return [4 /*yield*/, db.collection(collection).countDocuments(executedQuery, { readPreference: AI_ASSISTANT_READ_PREFERENCE })];
1607
+ if (!!documents.length) return [3 /*break*/, 12];
1608
+ nameFallback = resolveReadNameMatchFallback(executedQuery);
1609
+ if (!nameFallback) return [3 /*break*/, 12];
1610
+ fallbackMeta.nameMatch = {
1611
+ field: nameFallback.field,
1612
+ fields: nameFallback.fields,
1613
+ attempted: true,
1614
+ used: false
1615
+ };
1616
+ return [4 /*yield*/, db.collection(collection).find(nameFallback.query, findOptions).toArray()];
1487
1617
  case 11:
1488
- total = _e.sent();
1489
- _e.label = 12;
1618
+ fallbackDocs = _h.sent();
1619
+ if (fallbackDocs.length) {
1620
+ documents = fallbackDocs;
1621
+ executedQuery = nameFallback.query;
1622
+ fallbackMeta.nameMatch.used = true;
1623
+ }
1624
+ _h.label = 12;
1490
1625
  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];
1629
+ _c = probeDocs;
1630
+ if (_c) return [3 /*break*/, 14];
1631
+ return [4 /*yield*/, fetchAssistantProbeDocs({
1632
+ db: db,
1633
+ collection: collection,
1634
+ idClient: normalizedClient,
1635
+ idCustomer: customerId,
1636
+ isSuperAdmin: isSuperAdmin,
1637
+ includeClientScope: shouldScopeByClient
1638
+ })];
1639
+ case 13:
1640
+ _c = (_h.sent());
1641
+ _h.label = 14;
1642
+ case 14:
1643
+ 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];
1647
+ fallbackMeta.queryFieldAliases = {
1648
+ aliases: aliases,
1649
+ attempted: true,
1650
+ used: false
1651
+ };
1652
+ rewrittenQuery = Object.entries(aliases)
1653
+ .reduce(function (acc, _a) {
1654
+ var _b = __read(_a, 2), from = _b[0], to = _b[1];
1655
+ return replaceFieldPathDeep(acc, from, to);
1656
+ }, executedQuery);
1657
+ return [4 /*yield*/, db.collection(collection).find(rewrittenQuery, findOptions).toArray()];
1658
+ case 15:
1659
+ fallbackDocs = _h.sent();
1660
+ if (fallbackDocs.length) {
1661
+ documents = fallbackDocs;
1662
+ executedQuery = rewrittenQuery;
1663
+ fallbackMeta.queryFieldAliases.used = true;
1664
+ }
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];
1670
+ return [4 /*yield*/, fetchAssistantProbeDocs({
1671
+ db: db,
1672
+ collection: collection,
1673
+ idClient: normalizedClient,
1674
+ idCustomer: customerId,
1675
+ isSuperAdmin: isSuperAdmin,
1676
+ includeClientScope: shouldScopeByClient
1677
+ })];
1678
+ case 17:
1679
+ _d = (_h.sent());
1680
+ _h.label = 18;
1681
+ case 18:
1682
+ probeDocs = _d;
1683
+ return [4 /*yield*/, applyIdLookupFallbackToQuery({
1684
+ query: executedQuery,
1685
+ db: db,
1686
+ dbName: dbName,
1687
+ idClient: normalizedClient,
1688
+ idCustomer: customerId,
1689
+ isSuperAdmin: isSuperAdmin,
1690
+ probeDocs: probeDocs || undefined
1691
+ })];
1692
+ case 19:
1693
+ idLookup = _h.sent();
1694
+ if (!idLookup) return [3 /*break*/, 21];
1695
+ fallbackMeta.idLookup = __assign(__assign({}, idLookup.meta), { attempted: true, used: false });
1696
+ return [4 /*yield*/, db.collection(collection).find(idLookup.query, findOptions).toArray()];
1697
+ case 20:
1698
+ fallbackDocs = _h.sent();
1699
+ if (fallbackDocs.length) {
1700
+ documents = fallbackDocs;
1701
+ executedQuery = idLookup.query;
1702
+ fallbackMeta.idLookup.used = true;
1703
+ }
1704
+ _h.label = 21;
1705
+ case 21:
1706
+ total = null;
1707
+ if (!normalized.includeTotal) return [3 /*break*/, 23];
1708
+ 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:
1491
1713
  sanitizedDocuments = isSuperAdmin
1492
1714
  ? documents
1493
1715
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
1494
- includeIds = ((_d = input.options) === null || _d === void 0 ? void 0 : _d.includeIds) === true;
1495
- requestedFields = resolveProjectionRequestedFields(normalized.findOptions.projection);
1716
+ requestedFields = resolveProjectionRequestedFields(findOptions.projection);
1717
+ if (!(sanitizedDocuments.length && requestedFields.length)) return [3 /*break*/, 27];
1718
+ 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];
1722
+ return [4 /*yield*/, fetchAssistantProbeDocs({
1723
+ db: db,
1724
+ collection: collection,
1725
+ idClient: normalizedClient,
1726
+ idCustomer: customerId,
1727
+ isSuperAdmin: isSuperAdmin,
1728
+ includeClientScope: shouldScopeByClient
1729
+ })];
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];
1738
+ fallbackMeta.projectionAliases = {
1739
+ aliases: projectionAliases,
1740
+ attempted: true,
1741
+ used: false
1742
+ };
1743
+ expandedProjection = expandProjectionWithAliases(findOptions.projection, projectionAliases);
1744
+ if (!(expandedProjection && expandedProjection !== findOptions.projection)) return [3 /*break*/, 27];
1745
+ findOptions = __assign(__assign({}, findOptions), { projection: expandedProjection });
1746
+ normalized.findOptions.projection = expandedProjection;
1747
+ return [4 /*yield*/, db.collection(collection).find(executedQuery, findOptions).toArray()];
1748
+ case 26:
1749
+ refreshedDocs = _h.sent();
1750
+ if (refreshedDocs.length) {
1751
+ documents = refreshedDocs;
1752
+ sanitizedDocuments = isSuperAdmin
1753
+ ? refreshedDocs
1754
+ : refreshedDocs.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
1755
+ fallbackMeta.projectionAliases.used = true;
1756
+ }
1757
+ _h.label = 27;
1758
+ case 27:
1759
+ includeIds = ((_g = input.options) === null || _g === void 0 ? void 0 : _g.includeIds) === true;
1496
1760
  fieldAliases = resolveFieldAliases(sanitizedDocuments, requestedFields);
1497
1761
  displayDocs = Object.keys(fieldAliases).length
1498
1762
  ? applyFieldAliasesForDisplay(sanitizedDocuments, fieldAliases)
@@ -1533,10 +1797,10 @@ function executeAiAssistantMongoRead(payload, context) {
1533
1797
  }
1534
1798
  function executeAiAssistantMongoAggregate(payload, context) {
1535
1799
  return __awaiter(this, void 0, void 0, function () {
1536
- var input, rawCollection, dbName, db, collectionResolution, collection, _a, user, isSuperAdmin, customerId, baseQuery, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, dateField, aggregateOptions, documents, executedPipeline, fallbackMeta, fallback, fallbackPipeline, fallbackDocs, createdFallback, createdPipeline, createdDocs, completionFallback, fallbackPipeline, fallbackDocs, completionExprFallback, fallbackPipeline, fallbackDocs, unwindFallback, fallbackPipeline, fallbackDocs, nameFallback, fallbackPipeline, fallbackDocs, sanitizedDocuments, includeIds, display;
1537
- var _c, _d;
1538
- return __generator(this, function (_e) {
1539
- switch (_e.label) {
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) {
1540
1804
  case 0:
1541
1805
  input = payload || {};
1542
1806
  rawCollection = normalizeOptionalString(input.collection);
@@ -1547,16 +1811,26 @@ function executeAiAssistantMongoAggregate(payload, context) {
1547
1811
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1548
1812
  return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
1549
1813
  case 1:
1550
- collectionResolution = _e.sent();
1814
+ collectionResolution = _f.sent();
1551
1815
  collection = collectionResolution.name || rawCollection;
1552
1816
  return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
1553
1817
  case 2:
1554
- _a = _e.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1818
+ _a = _f.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1555
1819
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
1556
1820
  throw new Error('AI assistant mongo aggregate: Access denied.');
1557
1821
  }
1558
- customerId = normalizeOptionalString((_c = user === null || user === void 0 ? void 0 : user.other) === null || _c === void 0 ? void 0 : _c.id_customer);
1822
+ customerId = normalizeOptionalString((_d = user === null || user === void 0 ? void 0 : user.other) === null || _d === void 0 ? void 0 : _d.id_customer);
1823
+ fallbackMeta = {};
1559
1824
  baseQuery = normalizeMongoQuery(input.query);
1825
+ if (!isSuperAdmin && customerId) {
1826
+ stripped = stripQueryFieldPathsDeepWithMeta(baseQuery, ['id_customer', 'other.id_customer']);
1827
+ baseQuery = stripped.value;
1828
+ fallbackMeta.scopeStrip = {
1829
+ attempted: true,
1830
+ fields: ['id_customer', 'other.id_customer'],
1831
+ used: stripped.changed
1832
+ };
1833
+ }
1560
1834
  if (!isSuperAdmin && (collection === 'users' || collection === 'user-versions')) {
1561
1835
  userId = normalizeOptionalString(user === null || user === void 0 ? void 0 : user._id);
1562
1836
  if (!userId) {
@@ -1570,11 +1844,11 @@ function executeAiAssistantMongoAggregate(payload, context) {
1570
1844
  if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 4];
1571
1845
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
1572
1846
  case 3:
1573
- _b = _e.sent();
1847
+ _b = _f.sent();
1574
1848
  return [3 /*break*/, 5];
1575
1849
  case 4:
1576
1850
  _b = false;
1577
- _e.label = 5;
1851
+ _f.label = 5;
1578
1852
  case 5:
1579
1853
  shouldScopeByClient = _b;
1580
1854
  clientScopedQuery = shouldScopeByClient
@@ -1582,7 +1856,17 @@ function executeAiAssistantMongoAggregate(payload, context) {
1582
1856
  : baseQuery;
1583
1857
  scopedQuery = applyCustomerScopeFilter(clientScopedQuery, collection, customerId, isSuperAdmin);
1584
1858
  normalizedPipeline = normalizeAssistantAggregatePipeline(input.pipeline);
1585
- pipelineWithScope = buildAssistantAggregatePipeline(scopedQuery, normalizedPipeline);
1859
+ sanitizedPipeline = normalizedPipeline;
1860
+ if (!isSuperAdmin && customerId) {
1861
+ strippedPipeline = stripScopedFieldsFromPipelineWithMeta(normalizedPipeline, ['id_customer', 'other.id_customer']);
1862
+ sanitizedPipeline = strippedPipeline.pipeline;
1863
+ fallbackMeta.scopeStripPipeline = {
1864
+ attempted: true,
1865
+ fields: ['id_customer', 'other.id_customer'],
1866
+ used: strippedPipeline.changed
1867
+ };
1868
+ }
1869
+ pipelineWithScope = buildAssistantAggregatePipeline(scopedQuery, sanitizedPipeline);
1586
1870
  normalizedOptions = normalizeAssistantAggregateOptions(input.options);
1587
1871
  limitedPipeline = applyAssistantAggregateLimit(pipelineWithScope, normalizedOptions.limit, normalizedOptions.maxLimit, normalizedOptions.defaultLimit);
1588
1872
  dateField = findAggregateDateField(limitedPipeline);
@@ -1594,9 +1878,9 @@ function executeAiAssistantMongoAggregate(payload, context) {
1594
1878
  .aggregate(limitedPipeline, aggregateOptions)
1595
1879
  .toArray()];
1596
1880
  case 6:
1597
- documents = _e.sent();
1881
+ documents = _f.sent();
1598
1882
  executedPipeline = limitedPipeline;
1599
- fallbackMeta = {};
1883
+ probeDocs = null;
1600
1884
  if (!(!documents.length && dateField)) return [3 /*break*/, 10];
1601
1885
  fallback = resolveAggregateDateFieldFallback(limitedPipeline);
1602
1886
  if (!fallback) return [3 /*break*/, 8];
@@ -1607,13 +1891,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
1607
1891
  .aggregate(fallbackPipeline, aggregateOptions)
1608
1892
  .toArray()];
1609
1893
  case 7:
1610
- fallbackDocs = _e.sent();
1894
+ fallbackDocs = _f.sent();
1611
1895
  if (fallbackDocs.length) {
1612
1896
  documents = fallbackDocs;
1613
1897
  executedPipeline = fallbackPipeline;
1614
1898
  fallbackMeta.dateField.used = true;
1615
1899
  }
1616
- _e.label = 8;
1900
+ _f.label = 8;
1617
1901
  case 8:
1618
1902
  if (!(!documents.length && dateField !== 'createdAt')) return [3 /*break*/, 10];
1619
1903
  createdFallback = { from: dateField, to: 'createdAt', attempted: true, used: false };
@@ -1624,17 +1908,38 @@ function executeAiAssistantMongoAggregate(payload, context) {
1624
1908
  .aggregate(createdPipeline, aggregateOptions)
1625
1909
  .toArray()];
1626
1910
  case 9:
1627
- createdDocs = _e.sent();
1911
+ createdDocs = _f.sent();
1628
1912
  if (createdDocs.length) {
1629
1913
  documents = createdDocs;
1630
1914
  executedPipeline = createdPipeline;
1631
1915
  fallbackMeta.dateFieldCreatedAt.used = true;
1632
1916
  }
1633
- _e.label = 10;
1917
+ _f.label = 10;
1634
1918
  case 10:
1635
- if (!!documents.length) return [3 /*break*/, 14];
1919
+ if (!!documents.length) return [3 /*break*/, 12];
1920
+ expanded = expandAggregateDateMatchFallback(executedPipeline);
1921
+ if (!expanded) return [3 /*break*/, 12];
1922
+ fallbackMeta.dateFieldsExpanded = {
1923
+ fields: expanded.fields,
1924
+ attempted: true,
1925
+ used: false
1926
+ };
1927
+ if (!!containsForbiddenMongoOperators(expanded.pipeline)) return [3 /*break*/, 12];
1928
+ return [4 /*yield*/, db.collection(collection)
1929
+ .aggregate(expanded.pipeline, aggregateOptions)
1930
+ .toArray()];
1931
+ case 11:
1932
+ expandedDocs = _f.sent();
1933
+ if (expandedDocs.length) {
1934
+ documents = expandedDocs;
1935
+ executedPipeline = expanded.pipeline;
1936
+ fallbackMeta.dateFieldsExpanded.used = true;
1937
+ }
1938
+ _f.label = 12;
1939
+ case 12:
1940
+ if (!!documents.length) return [3 /*break*/, 16];
1636
1941
  completionFallback = resolveAggregateCompletionFallback(executedPipeline);
1637
- if (!completionFallback) return [3 /*break*/, 12];
1942
+ if (!completionFallback) return [3 /*break*/, 14];
1638
1943
  fallbackMeta.completion = {
1639
1944
  field: completionFallback.field,
1640
1945
  sources: completionFallback.sources,
@@ -1644,22 +1949,22 @@ function executeAiAssistantMongoAggregate(payload, context) {
1644
1949
  strategy: 'addFields'
1645
1950
  };
1646
1951
  fallbackPipeline = buildAggregateCompletionFallbackPipeline(executedPipeline, completionFallback);
1647
- if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 12];
1952
+ if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 14];
1648
1953
  return [4 /*yield*/, db.collection(collection)
1649
1954
  .aggregate(fallbackPipeline, aggregateOptions)
1650
1955
  .toArray()];
1651
- case 11:
1652
- fallbackDocs = _e.sent();
1956
+ case 13:
1957
+ fallbackDocs = _f.sent();
1653
1958
  if (fallbackDocs.length) {
1654
1959
  documents = fallbackDocs;
1655
1960
  executedPipeline = fallbackPipeline;
1656
1961
  fallbackMeta.completion.used = true;
1657
1962
  }
1658
- _e.label = 12;
1659
- case 12:
1660
- if (!!documents.length) return [3 /*break*/, 14];
1963
+ _f.label = 14;
1964
+ case 14:
1965
+ if (!!documents.length) return [3 /*break*/, 16];
1661
1966
  completionExprFallback = resolveAggregateCompletionExprFallback(executedPipeline);
1662
- if (!completionExprFallback) return [3 /*break*/, 14];
1967
+ if (!completionExprFallback) return [3 /*break*/, 16];
1663
1968
  fallbackMeta.completion = {
1664
1969
  field: completionExprFallback.field,
1665
1970
  sources: completionExprFallback.sources,
@@ -1669,40 +1974,40 @@ function executeAiAssistantMongoAggregate(payload, context) {
1669
1974
  strategy: 'expr'
1670
1975
  };
1671
1976
  fallbackPipeline = buildAggregateCompletionExprFallbackPipeline(executedPipeline, completionExprFallback);
1672
- if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 14];
1977
+ if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 16];
1673
1978
  return [4 /*yield*/, db.collection(collection)
1674
1979
  .aggregate(fallbackPipeline, aggregateOptions)
1675
1980
  .toArray()];
1676
- case 13:
1677
- fallbackDocs = _e.sent();
1981
+ case 15:
1982
+ fallbackDocs = _f.sent();
1678
1983
  if (fallbackDocs.length) {
1679
1984
  documents = fallbackDocs;
1680
1985
  executedPipeline = fallbackPipeline;
1681
1986
  fallbackMeta.completion.used = true;
1682
1987
  }
1683
- _e.label = 14;
1684
- case 14:
1685
- if (!(documents.length <= 1)) return [3 /*break*/, 16];
1988
+ _f.label = 16;
1989
+ case 16:
1990
+ if (!(documents.length <= 1)) return [3 /*break*/, 18];
1686
1991
  unwindFallback = resolveAggregateUnwindFallback(executedPipeline);
1687
- if (!unwindFallback) return [3 /*break*/, 16];
1992
+ if (!unwindFallback) return [3 /*break*/, 18];
1688
1993
  fallbackMeta.unwind = { path: unwindFallback.path, attempted: true, used: false };
1689
1994
  fallbackPipeline = buildAggregateUnwindFallbackPipeline(executedPipeline, unwindFallback);
1690
- if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 16];
1995
+ if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 18];
1691
1996
  return [4 /*yield*/, db.collection(collection)
1692
1997
  .aggregate(fallbackPipeline, aggregateOptions)
1693
1998
  .toArray()];
1694
- case 15:
1695
- fallbackDocs = _e.sent();
1999
+ case 17:
2000
+ fallbackDocs = _f.sent();
1696
2001
  if (fallbackDocs.length > documents.length) {
1697
2002
  documents = fallbackDocs;
1698
2003
  executedPipeline = fallbackPipeline;
1699
2004
  fallbackMeta.unwind.used = true;
1700
2005
  }
1701
- _e.label = 16;
1702
- case 16:
1703
- if (!!documents.length) return [3 /*break*/, 18];
2006
+ _f.label = 18;
2007
+ case 18:
2008
+ if (!!documents.length) return [3 /*break*/, 20];
1704
2009
  nameFallback = resolveAggregateNameMatchFallback(executedPipeline);
1705
- if (!nameFallback) return [3 /*break*/, 18];
2010
+ if (!nameFallback) return [3 /*break*/, 20];
1706
2011
  fallbackMeta.nameMatch = {
1707
2012
  field: nameFallback.field,
1708
2013
  fields: nameFallback.fields,
@@ -1710,23 +2015,146 @@ function executeAiAssistantMongoAggregate(payload, context) {
1710
2015
  used: false
1711
2016
  };
1712
2017
  fallbackPipeline = buildAggregateNameMatchFallbackPipeline(executedPipeline, nameFallback);
1713
- if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 18];
2018
+ if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 20];
1714
2019
  return [4 /*yield*/, db.collection(collection)
1715
2020
  .aggregate(fallbackPipeline, aggregateOptions)
1716
2021
  .toArray()];
1717
- case 17:
1718
- fallbackDocs = _e.sent();
2022
+ case 19:
2023
+ fallbackDocs = _f.sent();
1719
2024
  if (fallbackDocs.length) {
1720
2025
  documents = fallbackDocs;
1721
2026
  executedPipeline = fallbackPipeline;
1722
2027
  fallbackMeta.nameMatch.used = true;
1723
2028
  }
1724
- _e.label = 18;
1725
- case 18:
2029
+ _f.label = 20;
2030
+ case 20:
2031
+ if (!!documents.length) return [3 /*break*/, 24];
2032
+ matchFields_1 = new Set();
2033
+ (executedPipeline || []).forEach(function (stage) {
2034
+ if (stage && typeof stage === 'object' && stage.$match && typeof stage.$match === 'object') {
2035
+ extractQueryFieldPaths(stage.$match)
2036
+ .filter(function (field) { return !isAssistantIdField(field); })
2037
+ .forEach(function (field) { return matchFields_1.add(field); });
2038
+ }
2039
+ });
2040
+ if (!matchFields_1.size) return [3 /*break*/, 24];
2041
+ _c = probeDocs;
2042
+ if (_c) return [3 /*break*/, 22];
2043
+ return [4 /*yield*/, fetchAssistantProbeDocs({
2044
+ db: db,
2045
+ collection: collection,
2046
+ idClient: normalizedClient,
2047
+ idCustomer: customerId,
2048
+ isSuperAdmin: isSuperAdmin,
2049
+ includeClientScope: shouldScopeByClient
2050
+ })];
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];
2059
+ fallbackMeta.queryFieldAliases = {
2060
+ aliases: aliases,
2061
+ attempted: true,
2062
+ used: false
2063
+ };
2064
+ rewrittenPipeline = Object.entries(aliases)
2065
+ .reduce(function (acc, _a) {
2066
+ var _b = __read(_a, 2), from = _b[0], to = _b[1];
2067
+ return replaceFieldPathDeep(acc, from, to);
2068
+ }, executedPipeline);
2069
+ if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 24];
2070
+ return [4 /*yield*/, db.collection(collection)
2071
+ .aggregate(rewrittenPipeline, aggregateOptions)
2072
+ .toArray()];
2073
+ case 23:
2074
+ fallbackDocs = _f.sent();
2075
+ if (fallbackDocs.length) {
2076
+ documents = fallbackDocs;
2077
+ executedPipeline = rewrittenPipeline;
2078
+ fallbackMeta.queryFieldAliases.used = true;
2079
+ }
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) {
2087
+ case 0:
2088
+ stage = executedPipeline[i];
2089
+ if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
2090
+ return [2 /*return*/, "continue"];
2091
+ }
2092
+ _g = probeDocs;
2093
+ if (_g) return [3 /*break*/, 2];
2094
+ return [4 /*yield*/, fetchAssistantProbeDocs({
2095
+ db: db,
2096
+ collection: collection,
2097
+ idClient: normalizedClient,
2098
+ idCustomer: customerId,
2099
+ isSuperAdmin: isSuperAdmin,
2100
+ includeClientScope: shouldScopeByClient
2101
+ })];
2102
+ case 1:
2103
+ _g = (_h.sent());
2104
+ _h.label = 2;
2105
+ case 2:
2106
+ probeDocs = _g;
2107
+ return [4 /*yield*/, applyIdLookupFallbackToQuery({
2108
+ query: stage.$match,
2109
+ db: db,
2110
+ dbName: dbName,
2111
+ idClient: normalizedClient,
2112
+ idCustomer: customerId,
2113
+ isSuperAdmin: isSuperAdmin,
2114
+ probeDocs: probeDocs || undefined
2115
+ })];
2116
+ case 3:
2117
+ idLookup = _h.sent();
2118
+ if (!idLookup) {
2119
+ return [2 /*return*/, "continue"];
2120
+ }
2121
+ fallbackMeta.idLookup = __assign(__assign({}, idLookup.meta), { attempted: true, used: false, stage: i });
2122
+ rewrittenPipeline = executedPipeline.map(function (current, index) { return (index === i ? { $match: idLookup.query } : current); });
2123
+ if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 5];
2124
+ return [4 /*yield*/, db.collection(collection)
2125
+ .aggregate(rewrittenPipeline, aggregateOptions)
2126
+ .toArray()];
2127
+ case 4:
2128
+ fallbackDocs = _h.sent();
2129
+ if (fallbackDocs.length) {
2130
+ documents = fallbackDocs;
2131
+ executedPipeline = rewrittenPipeline;
2132
+ fallbackMeta.idLookup.used = true;
2133
+ return [2 /*return*/, "break"];
2134
+ }
2135
+ _h.label = 5;
2136
+ case 5: return [2 /*return*/];
2137
+ }
2138
+ });
2139
+ };
2140
+ 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:
2151
+ i += 1;
2152
+ return [3 /*break*/, 25];
2153
+ case 28:
1726
2154
  sanitizedDocuments = isSuperAdmin
1727
2155
  ? documents
1728
2156
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
1729
- includeIds = ((_d = input.options) === null || _d === void 0 ? void 0 : _d.includeIds) === true;
2157
+ includeIds = ((_e = input.options) === null || _e === void 0 ? void 0 : _e.includeIds) === true;
1730
2158
  display = buildDisplayTable(sanitizedDocuments, {
1731
2159
  includeIds: includeIds,
1732
2160
  maxColumns: AI_ASSISTANT_DISPLAY_MAX_COLUMNS,
@@ -1901,7 +2329,7 @@ function buildAssistantToolFallbackResponse(result) {
1901
2329
  return lines.join('\n').trim();
1902
2330
  }
1903
2331
  function buildAssistantDebugPayload(params) {
1904
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
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;
1905
2333
  var notes = [];
1906
2334
  if (params.dataQuestion) {
1907
2335
  notes.push('Detected a data request; tool call required.');
@@ -1909,18 +2337,24 @@ function buildAssistantDebugPayload(params) {
1909
2337
  if (params.directiveSource === 'forced') {
1910
2338
  notes.push('Assistant response omitted a MONGO_* directive; ran a directive-only pass.');
1911
2339
  }
2340
+ if ((_a = params.collectionOverride) === null || _a === void 0 ? void 0 : _a.to) {
2341
+ var from = params.collectionOverride.from ? "\"".concat(params.collectionOverride.from, "\"") : '(none)';
2342
+ var to = "\"".concat(params.collectionOverride.to, "\"");
2343
+ var reason = params.collectionOverride.reason ? " (".concat(params.collectionOverride.reason, ")") : '';
2344
+ notes.push("Collection override: ".concat(from, " -> ").concat(to).concat(reason, "."));
2345
+ }
1912
2346
  var directive = params.directive;
1913
2347
  var directivePayload = (directive === null || directive === void 0 ? void 0 : directive.payload) || {};
1914
2348
  var rawCollection = normalizeOptionalString(directivePayload === null || directivePayload === void 0 ? void 0 : directivePayload.collection);
1915
- var debugCollectionRequested = normalizeOptionalString((_a = params.toolResponseDebug) === null || _a === void 0 ? void 0 : _a.collectionRequested);
1916
- var debugCollectionResolved = normalizeOptionalString((_b = params.toolResponseDebug) === null || _b === void 0 ? void 0 : _b.collectionResolved);
1917
- var debugCollection = normalizeOptionalString((_c = params.toolResponseDebug) === null || _c === void 0 ? void 0 : _c.collection);
2349
+ var debugCollectionRequested = normalizeOptionalString((_b = params.toolResponseDebug) === null || _b === void 0 ? void 0 : _b.collectionRequested);
2350
+ var debugCollectionResolved = normalizeOptionalString((_c = params.toolResponseDebug) === null || _c === void 0 ? void 0 : _c.collectionResolved);
2351
+ var debugCollection = normalizeOptionalString((_d = params.toolResponseDebug) === null || _d === void 0 ? void 0 : _d.collection);
1918
2352
  var requestedCollection = debugCollectionRequested || rawCollection;
1919
2353
  var resolvedCollection = debugCollectionResolved || debugCollection || requestedCollection;
1920
- var matchedCollection = typeof ((_d = params.toolResponseDebug) === null || _d === void 0 ? void 0 : _d.collectionMatched) === 'boolean'
2354
+ var matchedCollection = typeof ((_e = params.toolResponseDebug) === null || _e === void 0 ? void 0 : _e.collectionMatched) === 'boolean'
1921
2355
  ? params.toolResponseDebug.collectionMatched
1922
2356
  : undefined;
1923
- var candidateCollections = Array.isArray((_e = params.toolResponseDebug) === null || _e === void 0 ? void 0 : _e.collectionCandidates)
2357
+ var candidateCollections = Array.isArray((_f = params.toolResponseDebug) === null || _f === void 0 ? void 0 : _f.collectionCandidates)
1924
2358
  ? params.toolResponseDebug.collectionCandidates.filter(Boolean)
1925
2359
  : [];
1926
2360
  if (requestedCollection && resolvedCollection && requestedCollection !== resolvedCollection) {
@@ -1929,27 +2363,27 @@ function buildAssistantDebugPayload(params) {
1929
2363
  else if (matchedCollection === false && candidateCollections.length) {
1930
2364
  notes.push("No direct collection match; candidates: ".concat(candidateCollections.join(', '), "."));
1931
2365
  }
1932
- if (((_f = params.toolResult) === null || _f === void 0 ? void 0 : _f.type) === 'mongo_agg') {
2366
+ if (((_g = params.toolResult) === null || _g === void 0 ? void 0 : _g.type) === 'mongo_agg') {
1933
2367
  notes.push('Used aggregation for grouped/breakdown request.');
1934
2368
  }
1935
- else if (((_g = params.toolResult) === null || _g === void 0 ? void 0 : _g.type) === 'mongo_read') {
2369
+ else if (((_h = params.toolResult) === null || _h === void 0 ? void 0 : _h.type) === 'mongo_read') {
1936
2370
  notes.push('Used read query for list/count request.');
1937
2371
  }
1938
- var fallbackInfo = (_h = params.toolResponseDebug) === null || _h === void 0 ? void 0 : _h.fallbacks;
1939
- if ((_j = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.dateField) === null || _j === void 0 ? void 0 : _j.used) {
2372
+ var fallbackInfo = (_j = params.toolResponseDebug) === null || _j === void 0 ? void 0 : _j.fallbacks;
2373
+ if ((_k = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.dateField) === null || _k === void 0 ? void 0 : _k.used) {
1940
2374
  notes.push("Retried with date field fallback ".concat(fallbackInfo.dateField.from, " -> ").concat(fallbackInfo.dateField.to, "."));
1941
2375
  }
1942
- if ((_k = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.dateFieldCreatedAt) === null || _k === void 0 ? void 0 : _k.used) {
2376
+ if ((_l = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.dateFieldCreatedAt) === null || _l === void 0 ? void 0 : _l.used) {
1943
2377
  notes.push("Retried with date field fallback ".concat(fallbackInfo.dateFieldCreatedAt.from, " -> ").concat(fallbackInfo.dateFieldCreatedAt.to, "."));
1944
2378
  }
1945
- if ((_l = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.completion) === null || _l === void 0 ? void 0 : _l.used) {
2379
+ if ((_m = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.completion) === null || _m === void 0 ? void 0 : _m.used) {
1946
2380
  var sources = Array.isArray(fallbackInfo.completion.sources)
1947
2381
  ? fallbackInfo.completion.sources.join(', ')
1948
2382
  : fallbackInfo.completion.field;
1949
2383
  var strategy = fallbackInfo.completion.strategy ? " (".concat(fallbackInfo.completion.strategy, ")") : '';
1950
2384
  notes.push("Applied completion fallback".concat(strategy, ": ").concat(sources, "."));
1951
2385
  }
1952
- if ((_m = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.dateFieldsExpanded) === null || _m === void 0 ? void 0 : _m.used) {
2386
+ if ((_o = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.dateFieldsExpanded) === null || _o === void 0 ? void 0 : _o.used) {
1953
2387
  var fields = Array.isArray(fallbackInfo.dateFieldsExpanded.fields)
1954
2388
  ? fallbackInfo.dateFieldsExpanded.fields.join(', ')
1955
2389
  : String(fallbackInfo.dateFieldsExpanded.fields || '');
@@ -1957,17 +2391,50 @@ function buildAssistantDebugPayload(params) {
1957
2391
  notes.push("Expanded date fields: ".concat(fields, "."));
1958
2392
  }
1959
2393
  }
1960
- if ((_o = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.unwind) === null || _o === void 0 ? void 0 : _o.used) {
2394
+ if ((_p = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.queryFieldAliases) === null || _p === void 0 ? void 0 : _p.used) {
2395
+ var entries = fallbackInfo.queryFieldAliases.aliases
2396
+ ? Object.entries(fallbackInfo.queryFieldAliases.aliases)
2397
+ .map(function (_a) {
2398
+ var _b = __read(_a, 2), from = _b[0], to = _b[1];
2399
+ return "".concat(from, " -> ").concat(to);
2400
+ })
2401
+ .join(', ')
2402
+ : '';
2403
+ if (entries) {
2404
+ notes.push("Rewrote query fields: ".concat(entries, "."));
2405
+ }
2406
+ }
2407
+ if ((_q = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.projectionAliases) === null || _q === void 0 ? void 0 : _q.used) {
2408
+ var entries = fallbackInfo.projectionAliases.aliases
2409
+ ? Object.entries(fallbackInfo.projectionAliases.aliases)
2410
+ .map(function (_a) {
2411
+ var _b = __read(_a, 2), from = _b[0], to = _b[1];
2412
+ return "".concat(from, " -> ").concat(to);
2413
+ })
2414
+ .join(', ')
2415
+ : '';
2416
+ if (entries) {
2417
+ notes.push("Expanded projection fields: ".concat(entries, "."));
2418
+ }
2419
+ }
2420
+ if ((_r = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.unwind) === null || _r === void 0 ? void 0 : _r.used) {
1961
2421
  notes.push("Applied unwind fallback on ".concat(fallbackInfo.unwind.path, "."));
1962
2422
  }
1963
- if ((_p = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.nameMatch) === null || _p === void 0 ? void 0 : _p.used) {
2423
+ if ((_s = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.nameMatch) === null || _s === void 0 ? void 0 : _s.used) {
1964
2424
  var fields = Array.isArray(fallbackInfo.nameMatch.fields)
1965
2425
  ? fallbackInfo.nameMatch.fields.join(', ')
1966
2426
  : fallbackInfo.nameMatch.field;
1967
2427
  notes.push("Expanded name match fields: ".concat(fields, "."));
1968
2428
  }
2429
+ if ((_t = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idLookup) === null || _t === void 0 ? void 0 : _t.used) {
2430
+ var field = fallbackInfo.idLookup.field || 'id';
2431
+ var strategy = fallbackInfo.idLookup.strategy || 'lookup';
2432
+ var collection = fallbackInfo.idLookup.collection ? " in ".concat(fallbackInfo.idLookup.collection) : '';
2433
+ var detail = fallbackInfo.idLookup.nameField ? " via ".concat(fallbackInfo.idLookup.nameField) : '';
2434
+ notes.push("Resolved ".concat(field, " by ").concat(strategy).concat(collection).concat(detail, "."));
2435
+ }
1969
2436
  if (params.toolError) {
1970
- var errorMessage = ((_q = params.toolError) === null || _q === void 0 ? void 0 : _q.message) || String(params.toolError || '');
2437
+ var errorMessage = ((_u = params.toolError) === null || _u === void 0 ? void 0 : _u.message) || String(params.toolError || '');
1971
2438
  if (errorMessage) {
1972
2439
  notes.push("Tool error: ".concat(errorMessage));
1973
2440
  }
@@ -1982,18 +2449,19 @@ function buildAssistantDebugPayload(params) {
1982
2449
  payload: directivePayload,
1983
2450
  rawLine: directive.rawLine
1984
2451
  } : null,
2452
+ collectionOverride: params.collectionOverride || undefined,
1985
2453
  collection: resolvedCollection || requestedCollection || undefined,
1986
2454
  collectionRequested: requestedCollection || undefined,
1987
2455
  collectionResolved: resolvedCollection || undefined,
1988
2456
  collectionMatched: matchedCollection,
1989
2457
  collectionCandidates: candidateCollections.length ? candidateCollections : undefined,
1990
- collectionScore: typeof ((_r = params.toolResponseDebug) === null || _r === void 0 ? void 0 : _r.collectionScore) === 'number'
2458
+ collectionScore: typeof ((_v = params.toolResponseDebug) === null || _v === void 0 ? void 0 : _v.collectionScore) === 'number'
1991
2459
  ? params.toolResponseDebug.collectionScore
1992
2460
  : undefined,
1993
- query: ((_s = params.toolResponseDebug) === null || _s === void 0 ? void 0 : _s.query) || undefined,
1994
- pipeline: ((_t = params.toolResponseDebug) === null || _t === void 0 ? void 0 : _t.executedPipeline) || ((_u = params.toolResponseDebug) === null || _u === void 0 ? void 0 : _u.originalPipeline) || undefined,
1995
- options: ((_v = params.toolResponseDebug) === null || _v === void 0 ? void 0 : _v.options) || undefined,
1996
- fallbacks: ((_w = params.toolResponseDebug) === null || _w === void 0 ? void 0 : _w.fallbacks) || 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,
1997
2465
  notes: notes
1998
2466
  };
1999
2467
  if (params.trace && typeof params.trace === 'object') {
@@ -2260,40 +2728,184 @@ function tokenizeFieldKey(value) {
2260
2728
  function normalizeFieldMatchKey(value) {
2261
2729
  return tokenizeFieldKey(value).join('');
2262
2730
  }
2731
+ function expandFieldTokens(tokens) {
2732
+ var expanded = new Set();
2733
+ tokens.forEach(function (token) {
2734
+ if (!token) {
2735
+ return;
2736
+ }
2737
+ expanded.add(token);
2738
+ var synonyms = AI_ASSISTANT_FIELD_TOKEN_SYNONYMS[token];
2739
+ if (Array.isArray(synonyms)) {
2740
+ synonyms.forEach(function (synonym) {
2741
+ if (synonym) {
2742
+ expanded.add(synonym);
2743
+ }
2744
+ });
2745
+ }
2746
+ });
2747
+ return Array.from(expanded);
2748
+ }
2263
2749
  function getValueAtPath(obj, path) {
2264
- var e_1, _a;
2265
2750
  if (!obj || typeof obj !== 'object') {
2266
2751
  return undefined;
2267
2752
  }
2268
2753
  var parts = String(path || '').split('.').filter(Boolean);
2269
- var current = obj;
2270
- try {
2271
- for (var parts_1 = __values(parts), parts_1_1 = parts_1.next(); !parts_1_1.done; parts_1_1 = parts_1.next()) {
2272
- var part = parts_1_1.value;
2273
- if (!current || typeof current !== 'object') {
2754
+ var walk = function (current, index) {
2755
+ if (index >= parts.length) {
2756
+ return current;
2757
+ }
2758
+ var part = parts[index];
2759
+ if (Array.isArray(current)) {
2760
+ var numeric = Number(part);
2761
+ if (!Number.isNaN(numeric) && current[numeric] !== undefined) {
2762
+ return walk(current[numeric], index + 1);
2763
+ }
2764
+ var values = current.map(function (entry) { return walk(entry, index); }).filter(function (value) { return value !== undefined; });
2765
+ if (!values.length) {
2274
2766
  return undefined;
2275
2767
  }
2276
- current = current[part];
2768
+ return values.length === 1 ? values[0] : values;
2769
+ }
2770
+ if (!current || typeof current !== 'object') {
2771
+ return undefined;
2772
+ }
2773
+ return walk(current[part], index + 1);
2774
+ };
2775
+ return walk(obj, 0);
2776
+ }
2777
+ function inferIdFieldStorageTypeFromDocs(docs, fieldPath) {
2778
+ var e_1, _a, e_2, _b;
2779
+ if (!Array.isArray(docs) || !fieldPath) {
2780
+ return 'unknown';
2781
+ }
2782
+ var sawString = false;
2783
+ try {
2784
+ for (var docs_1 = __values(docs), docs_1_1 = docs_1.next(); !docs_1_1.done; docs_1_1 = docs_1.next()) {
2785
+ var doc = docs_1_1.value;
2786
+ var value = fieldPath.includes('.')
2787
+ ? getValueAtPath(doc, fieldPath)
2788
+ : doc === null || doc === void 0 ? void 0 : doc[fieldPath];
2789
+ var queue = Array.isArray(value) ? value : [value];
2790
+ try {
2791
+ for (var queue_1 = (e_2 = void 0, __values(queue)), queue_1_1 = queue_1.next(); !queue_1_1.done; queue_1_1 = queue_1.next()) {
2792
+ var entry = queue_1_1.value;
2793
+ if (entry === null || entry === undefined) {
2794
+ continue;
2795
+ }
2796
+ if (isMongoObjectId(entry)) {
2797
+ return 'objectId';
2798
+ }
2799
+ if (typeof entry === 'string' && entry.trim()) {
2800
+ sawString = true;
2801
+ }
2802
+ }
2803
+ }
2804
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
2805
+ finally {
2806
+ try {
2807
+ if (queue_1_1 && !queue_1_1.done && (_b = queue_1.return)) _b.call(queue_1);
2808
+ }
2809
+ finally { if (e_2) throw e_2.error; }
2810
+ }
2277
2811
  }
2278
2812
  }
2279
2813
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
2280
2814
  finally {
2281
2815
  try {
2282
- if (parts_1_1 && !parts_1_1.done && (_a = parts_1.return)) _a.call(parts_1);
2816
+ if (docs_1_1 && !docs_1_1.done && (_a = docs_1.return)) _a.call(docs_1);
2283
2817
  }
2284
2818
  finally { if (e_1) throw e_1.error; }
2285
2819
  }
2286
- return current;
2820
+ return sawString ? 'string' : 'unknown';
2821
+ }
2822
+ function normalizeIdsForTargetField(ids, targetDocs, targetFieldPath, targetFieldTypeOverride) {
2823
+ if (!Array.isArray(ids) || !ids.length) {
2824
+ return [];
2825
+ }
2826
+ var targetType = targetFieldTypeOverride
2827
+ || inferIdFieldStorageTypeFromDocs(targetDocs || [], targetFieldPath);
2828
+ var normalized = [];
2829
+ var seenStrings = new Set();
2830
+ var seenObjectIds = new Set();
2831
+ var pushString = function (value) {
2832
+ var text = String(value || '').trim();
2833
+ if (!text || seenStrings.has(text)) {
2834
+ return;
2835
+ }
2836
+ seenStrings.add(text);
2837
+ normalized.push(text);
2838
+ };
2839
+ var pushObjectId = function (value) {
2840
+ if (!isMongoObjectId(value)) {
2841
+ return;
2842
+ }
2843
+ var hex = typeof value.toHexString === 'function' ? value.toHexString() : String(value || '');
2844
+ if (!hex || seenObjectIds.has(hex)) {
2845
+ return;
2846
+ }
2847
+ seenObjectIds.add(hex);
2848
+ normalized.push(value);
2849
+ };
2850
+ ids.forEach(function (value) {
2851
+ if (value === null || value === undefined) {
2852
+ return;
2853
+ }
2854
+ if (targetType === 'string') {
2855
+ if (isMongoObjectId(value)) {
2856
+ var hex = typeof value.toHexString === 'function' ? value.toHexString() : String(value || '');
2857
+ pushString(hex);
2858
+ return;
2859
+ }
2860
+ pushString(value);
2861
+ return;
2862
+ }
2863
+ if (targetType === 'objectId') {
2864
+ if (isMongoObjectId(value)) {
2865
+ pushObjectId(value);
2866
+ return;
2867
+ }
2868
+ if (typeof value === 'string' && isObjectIdString(value)) {
2869
+ try {
2870
+ pushObjectId(new mongodb_1.ObjectId(value));
2871
+ }
2872
+ catch (_a) {
2873
+ return;
2874
+ }
2875
+ }
2876
+ return;
2877
+ }
2878
+ if (isMongoObjectId(value)) {
2879
+ pushObjectId(value);
2880
+ var hex = typeof value.toHexString === 'function' ? value.toHexString() : String(value || '');
2881
+ if (hex) {
2882
+ pushString(hex);
2883
+ }
2884
+ return;
2885
+ }
2886
+ if (typeof value === 'string' && isObjectIdString(value)) {
2887
+ try {
2888
+ pushObjectId(new mongodb_1.ObjectId(value));
2889
+ }
2890
+ catch (_b) {
2891
+ // Ignore invalid object id conversions.
2892
+ }
2893
+ pushString(value);
2894
+ return;
2895
+ }
2896
+ pushString(value);
2897
+ });
2898
+ return normalized;
2287
2899
  }
2288
2900
  function hasNonEmptyValue(docs, fieldPath, options) {
2289
- var e_2, _a;
2901
+ var e_3, _a;
2290
2902
  if (!Array.isArray(docs) || !fieldPath) {
2291
2903
  return false;
2292
2904
  }
2293
2905
  var usePath = fieldPath.includes('.');
2294
2906
  try {
2295
- for (var docs_1 = __values(docs), docs_1_1 = docs_1.next(); !docs_1_1.done; docs_1_1 = docs_1.next()) {
2296
- var doc = docs_1_1.value;
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;
2297
2909
  var value = usePath ? getValueAtPath(doc, fieldPath) : doc === null || doc === void 0 ? void 0 : doc[fieldPath];
2298
2910
  if ((options === null || options === void 0 ? void 0 : options.treatObjectLikeAsEmpty) && isDisplayObjectLike(value)) {
2299
2911
  continue;
@@ -2303,12 +2915,12 @@ function hasNonEmptyValue(docs, fieldPath, options) {
2303
2915
  }
2304
2916
  }
2305
2917
  }
2306
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
2918
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
2307
2919
  finally {
2308
2920
  try {
2309
- if (docs_1_1 && !docs_1_1.done && (_a = docs_1.return)) _a.call(docs_1);
2921
+ if (docs_2_1 && !docs_2_1.done && (_a = docs_2.return)) _a.call(docs_2);
2310
2922
  }
2311
- finally { if (e_2) throw e_2.error; }
2923
+ finally { if (e_3) throw e_3.error; }
2312
2924
  }
2313
2925
  return false;
2314
2926
  }
@@ -2344,6 +2956,17 @@ function collectFieldCandidates(docs) {
2344
2956
  }
2345
2957
  var value = doc[key];
2346
2958
  addCandidate(key, value);
2959
+ if (Array.isArray(value)) {
2960
+ var nestedSamples = value.filter(function (entry) { return isPlainObject(entry); }).slice(0, 3);
2961
+ nestedSamples.forEach(function (entry) {
2962
+ Object.keys(entry).slice(0, 50).forEach(function (nestedKey) {
2963
+ if (!nestedKey) {
2964
+ return;
2965
+ }
2966
+ addCandidate("".concat(key, ".").concat(nestedKey), entry[nestedKey]);
2967
+ });
2968
+ });
2969
+ }
2347
2970
  if (isPlainObject(value) && !isMongoObjectId(value) && !(value instanceof Date)) {
2348
2971
  var nestedKeys = Object.keys(value).slice(0, 50);
2349
2972
  nestedKeys.forEach(function (nestedKey) {
@@ -2394,10 +3017,18 @@ function resolveFieldAliases(docs, requestedFields) {
2394
3017
  }
2395
3018
  else {
2396
3019
  var candidateTokens_1 = tokenizeFieldKey(path);
2397
- var requestedTokens = tokenizeFieldKey(field);
3020
+ var requestedBaseTokens = tokenizeFieldKey(field);
3021
+ var requestedTokens = expandFieldTokens(requestedBaseTokens);
2398
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;
2399
3024
  if (overlap > 0) {
2400
- score = 40 + overlap * 5;
3025
+ score = 40 + overlap * 10;
3026
+ if (baseOverlap === 0) {
3027
+ score += 10;
3028
+ }
3029
+ if (requestedBaseTokens.length <= 2) {
3030
+ score += 10;
3031
+ }
2401
3032
  }
2402
3033
  }
2403
3034
  var objectRatio = stats.objectLike / Math.max(stats.nonEmpty, 1);
@@ -2462,45 +3093,156 @@ function resolveProjectionRequestedFields(projection) {
2462
3093
  }
2463
3094
  return keys.filter(function (key) { return !isAssistantIdField(key); });
2464
3095
  }
2465
- function formatDisplayColumnName(column) {
2466
- var trimmed = String(column || '').trim();
2467
- if (!trimmed) {
2468
- return '';
2469
- }
2470
- if (trimmed === '_id') {
2471
- return 'id';
2472
- }
2473
- if (trimmed === '_group') {
2474
- return 'Group';
2475
- }
2476
- var normalized = trimmed.replace(/[\s_]+/g, '').toLowerCase();
2477
- if (normalized === 'createdat') {
2478
- return 'Created At';
3096
+ function isInclusiveProjection(projection) {
3097
+ if (!projection || typeof projection !== 'object') {
3098
+ return false;
2479
3099
  }
2480
- if (normalized === 'updatedat') {
2481
- return 'Updated At';
3100
+ var keys = Object.keys(projection);
3101
+ if (!keys.length) {
3102
+ return false;
2482
3103
  }
2483
- var parts = trimmed.split('.');
2484
- var base = parts[parts.length - 1] || trimmed;
2485
- if ((base === 'name' || base === 'title' || base === 'label') && parts.length > 1) {
2486
- return parts[parts.length - 2]
2487
- .replace(/[_-]+/g, ' ')
2488
- .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
2489
- .replace(/\s+/g, ' ')
2490
- .trim()
2491
- .replace(/\b\w/g, function (char) { return char.toUpperCase(); });
3104
+ var hasInclude = false;
3105
+ var hasExclude = false;
3106
+ keys.forEach(function (key) {
3107
+ var value = projection[key];
3108
+ if (value === 0 || value === false) {
3109
+ hasExclude = true;
3110
+ }
3111
+ else if (value === 1 || value === true) {
3112
+ hasInclude = true;
3113
+ }
3114
+ });
3115
+ return hasInclude && !hasExclude;
3116
+ }
3117
+ function expandProjectionWithAliases(projection, aliases) {
3118
+ if (!projection || !isInclusiveProjection(projection) || !aliases || !Object.keys(aliases).length) {
3119
+ return projection;
2492
3120
  }
2493
- return base
2494
- .replace(/[_-]+/g, ' ')
2495
- .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
2496
- .replace(/\s+/g, ' ')
2497
- .trim()
2498
- .replace(/\b\w/g, function (char) { return char.toUpperCase(); });
3121
+ var next = __assign({}, projection);
3122
+ Object.keys(aliases).forEach(function (target) {
3123
+ var source = aliases[target];
3124
+ if (!source) {
3125
+ return;
3126
+ }
3127
+ if (!Object.prototype.hasOwnProperty.call(next, source)) {
3128
+ next[source] = 1;
3129
+ }
3130
+ });
3131
+ return next;
2499
3132
  }
2500
- function truncateDisplayText(value, maxLength) {
2501
- if (maxLength === void 0) { maxLength = AI_ASSISTANT_DISPLAY_STRING_LIMIT; }
2502
- if (!value) {
2503
- return value;
3133
+ function collectQueryFieldPaths(value, fields) {
3134
+ if (!value || typeof value !== 'object' || value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
3135
+ return;
3136
+ }
3137
+ if (Array.isArray(value)) {
3138
+ value.forEach(function (entry) { return collectQueryFieldPaths(entry, fields); });
3139
+ return;
3140
+ }
3141
+ Object.keys(value).forEach(function (key) {
3142
+ var entry = value[key];
3143
+ if (key.startsWith('$')) {
3144
+ collectQueryFieldPaths(entry, fields);
3145
+ return;
3146
+ }
3147
+ fields.add(key);
3148
+ if (entry && typeof entry === 'object' && !Array.isArray(entry) && !isMongoObjectId(entry) && !(entry instanceof Date)) {
3149
+ var nestedKeys = Object.keys(entry).filter(function (nested) { return !nested.startsWith('$'); });
3150
+ nestedKeys.forEach(function (nested) {
3151
+ fields.add("".concat(key, ".").concat(nested));
3152
+ });
3153
+ }
3154
+ });
3155
+ }
3156
+ function extractQueryFieldPaths(query) {
3157
+ var fields = new Set();
3158
+ collectQueryFieldPaths(query, fields);
3159
+ return Array.from(fields).filter(Boolean);
3160
+ }
3161
+ function replaceFieldPathDeep(value, fromField, toField) {
3162
+ if (Array.isArray(value)) {
3163
+ return value.map(function (entry) { return replaceFieldPathDeep(entry, fromField, toField); });
3164
+ }
3165
+ if (value instanceof Date || isMongoObjectId(value)) {
3166
+ return value;
3167
+ }
3168
+ if (value && typeof value === 'object') {
3169
+ var next_1 = {};
3170
+ Object.keys(value).forEach(function (key) {
3171
+ var nextKey = key === fromField ? toField : key;
3172
+ next_1[nextKey] = replaceFieldPathDeep(value[key], fromField, toField);
3173
+ });
3174
+ return next_1;
3175
+ }
3176
+ if (typeof value === 'string') {
3177
+ if (value.startsWith("$".concat(fromField))) {
3178
+ return "$".concat(toField).concat(value.slice(fromField.length + 1));
3179
+ }
3180
+ return value;
3181
+ }
3182
+ return value;
3183
+ }
3184
+ function replaceQueryFieldCondition(query, field, condition) {
3185
+ if (Array.isArray(query)) {
3186
+ return query.map(function (entry) { return replaceQueryFieldCondition(entry, field, condition); });
3187
+ }
3188
+ if (!query || typeof query !== 'object') {
3189
+ return query;
3190
+ }
3191
+ var next = __assign({}, query);
3192
+ Object.keys(next).forEach(function (key) {
3193
+ if (key === field) {
3194
+ next[key] = condition;
3195
+ return;
3196
+ }
3197
+ if (key.startsWith('$')) {
3198
+ next[key] = replaceQueryFieldCondition(next[key], field, condition);
3199
+ return;
3200
+ }
3201
+ if (next[key] && typeof next[key] === 'object') {
3202
+ next[key] = replaceQueryFieldCondition(next[key], field, condition);
3203
+ }
3204
+ });
3205
+ return next;
3206
+ }
3207
+ function formatDisplayColumnName(column) {
3208
+ var trimmed = String(column || '').trim();
3209
+ if (!trimmed) {
3210
+ return '';
3211
+ }
3212
+ if (trimmed === '_id') {
3213
+ return 'id';
3214
+ }
3215
+ if (trimmed === '_group') {
3216
+ return 'Group';
3217
+ }
3218
+ var normalized = trimmed.replace(/[\s_]+/g, '').toLowerCase();
3219
+ if (normalized === 'createdat') {
3220
+ return 'Created At';
3221
+ }
3222
+ if (normalized === 'updatedat') {
3223
+ return 'Updated At';
3224
+ }
3225
+ var parts = trimmed.split('.');
3226
+ var base = parts[parts.length - 1] || trimmed;
3227
+ if ((base === 'name' || base === 'title' || base === 'label') && parts.length > 1) {
3228
+ return parts[parts.length - 2]
3229
+ .replace(/[_-]+/g, ' ')
3230
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
3231
+ .replace(/\s+/g, ' ')
3232
+ .trim()
3233
+ .replace(/\b\w/g, function (char) { return char.toUpperCase(); });
3234
+ }
3235
+ return base
3236
+ .replace(/[_-]+/g, ' ')
3237
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
3238
+ .replace(/\s+/g, ' ')
3239
+ .trim()
3240
+ .replace(/\b\w/g, function (char) { return char.toUpperCase(); });
3241
+ }
3242
+ function truncateDisplayText(value, maxLength) {
3243
+ if (maxLength === void 0) { maxLength = AI_ASSISTANT_DISPLAY_STRING_LIMIT; }
3244
+ if (!value) {
3245
+ return value;
2504
3246
  }
2505
3247
  if (value.length <= maxLength) {
2506
3248
  return value;
@@ -2866,10 +3608,12 @@ function normalizeAssistantAggregatePipeline(pipeline) {
2866
3608
  .map(function (stage) {
2867
3609
  var next = __assign({}, stage);
2868
3610
  if (next.$match && typeof next.$match === 'object') {
2869
- next.$match = applyAssistantNameRegexToQuery(next.$match);
3611
+ var rewritten = rewriteEmbeddedMatchObjects(next.$match);
3612
+ next.$match = applyAssistantNameRegexToQuery(rewritten);
2870
3613
  }
2871
3614
  if (next.$geoNear && typeof next.$geoNear === 'object' && next.$geoNear.query) {
2872
- next.$geoNear = __assign(__assign({}, next.$geoNear), { query: applyAssistantNameRegexToQuery(next.$geoNear.query) });
3615
+ var rewritten = rewriteEmbeddedMatchObjects(next.$geoNear.query);
3616
+ next.$geoNear = __assign(__assign({}, next.$geoNear), { query: applyAssistantNameRegexToQuery(rewritten) });
2873
3617
  }
2874
3618
  return next;
2875
3619
  });
@@ -3000,7 +3744,7 @@ function matchContainsField(value, field) {
3000
3744
  });
3001
3745
  }
3002
3746
  function resolveAggregateCompletionFallback(pipeline) {
3003
- var e_3, _a;
3747
+ var e_4, _a;
3004
3748
  if (!Array.isArray(pipeline)) {
3005
3749
  return null;
3006
3750
  }
@@ -3013,7 +3757,7 @@ function resolveAggregateCompletionFallback(pipeline) {
3013
3757
  }
3014
3758
  var addFields = stage.$addFields;
3015
3759
  try {
3016
- for (var _b = (e_3 = void 0, __values(Object.keys(addFields))), _c = _b.next(); !_c.done; _c = _b.next()) {
3760
+ for (var _b = (e_4 = void 0, __values(Object.keys(addFields))), _c = _b.next(); !_c.done; _c = _b.next()) {
3017
3761
  var key = _c.value;
3018
3762
  if (!isCompletionFieldName(key)) {
3019
3763
  continue;
@@ -3027,12 +3771,12 @@ function resolveAggregateCompletionFallback(pipeline) {
3027
3771
  }
3028
3772
  }
3029
3773
  }
3030
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
3774
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
3031
3775
  finally {
3032
3776
  try {
3033
3777
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3034
3778
  }
3035
- finally { if (e_3) throw e_3.error; }
3779
+ finally { if (e_4) throw e_4.error; }
3036
3780
  }
3037
3781
  if (candidateField) {
3038
3782
  break;
@@ -3188,7 +3932,7 @@ function buildCompletionFallbackSources(field) {
3188
3932
  ]);
3189
3933
  }
3190
3934
  function resolveAggregateCompletionExprFallback(pipeline) {
3191
- var e_4, _a;
3935
+ var e_5, _a;
3192
3936
  if (!Array.isArray(pipeline)) {
3193
3937
  return null;
3194
3938
  }
@@ -3208,7 +3952,7 @@ function resolveAggregateCompletionExprFallback(pipeline) {
3208
3952
  }
3209
3953
  if (!candidateField) {
3210
3954
  try {
3211
- for (var _b = (e_4 = void 0, __values(Object.keys(matchStage))), _c = _b.next(); !_c.done; _c = _b.next()) {
3955
+ for (var _b = (e_5 = void 0, __values(Object.keys(matchStage))), _c = _b.next(); !_c.done; _c = _b.next()) {
3212
3956
  var key = _c.value;
3213
3957
  if (key.startsWith('$')) {
3214
3958
  continue;
@@ -3223,12 +3967,12 @@ function resolveAggregateCompletionExprFallback(pipeline) {
3223
3967
  }
3224
3968
  }
3225
3969
  }
3226
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
3970
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
3227
3971
  finally {
3228
3972
  try {
3229
3973
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3230
3974
  }
3231
- finally { if (e_4) throw e_4.error; }
3975
+ finally { if (e_5) throw e_5.error; }
3232
3976
  }
3233
3977
  }
3234
3978
  if (!candidateField) {
@@ -3398,7 +4142,7 @@ function isRegexMatchCondition(value) {
3398
4142
  return false;
3399
4143
  }
3400
4144
  function findRegexMatchInMatchObject(match, prefix) {
3401
- var e_5, _a, e_6, _b;
4145
+ var e_6, _a, e_7, _b;
3402
4146
  if (prefix === void 0) { prefix = ''; }
3403
4147
  if (Array.isArray(match)) {
3404
4148
  try {
@@ -3410,12 +4154,12 @@ function findRegexMatchInMatchObject(match, prefix) {
3410
4154
  }
3411
4155
  }
3412
4156
  }
3413
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
4157
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
3414
4158
  finally {
3415
4159
  try {
3416
4160
  if (match_1_1 && !match_1_1.done && (_a = match_1.return)) _a.call(match_1);
3417
4161
  }
3418
- finally { if (e_5) throw e_5.error; }
4162
+ finally { if (e_6) throw e_6.error; }
3419
4163
  }
3420
4164
  return null;
3421
4165
  }
@@ -3446,12 +4190,12 @@ function findRegexMatchInMatchObject(match, prefix) {
3446
4190
  }
3447
4191
  }
3448
4192
  }
3449
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
4193
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
3450
4194
  finally {
3451
4195
  try {
3452
4196
  if (keys_1_1 && !keys_1_1.done && (_b = keys_1.return)) _b.call(keys_1);
3453
4197
  }
3454
- finally { if (e_6) throw e_6.error; }
4198
+ finally { if (e_7) throw e_7.error; }
3455
4199
  }
3456
4200
  return null;
3457
4201
  }
@@ -3500,6 +4244,9 @@ function expandNameFieldCandidates(field) {
3500
4244
  push(withPrefix("".concat(leaf, ".name")));
3501
4245
  push(withPrefix("".concat(leaf, ".label")));
3502
4246
  push(withPrefix("".concat(leaf, ".product")));
4247
+ if (normalized.includes('blend_chemicals')) {
4248
+ ['chemical', 'chemical_name', 'chemicalName', 'product', 'product_name', 'productName'].forEach(push);
4249
+ }
3503
4250
  }
3504
4251
  if (leafLower.includes('customer')) {
3505
4252
  [
@@ -3564,6 +4311,32 @@ function resolveAggregateNameMatchFallback(pipeline) {
3564
4311
  }
3565
4312
  return null;
3566
4313
  }
4314
+ function resolveReadNameMatchFallback(query) {
4315
+ if (!query || typeof query !== 'object') {
4316
+ return null;
4317
+ }
4318
+ var found = findRegexMatchInMatchObject(query);
4319
+ if (!found || !shouldApplyAssistantNameRegex(found.field) || isAssistantIdField(found.field)) {
4320
+ return null;
4321
+ }
4322
+ var fields = expandNameFieldCandidates(found.field);
4323
+ if (fields.length <= 1) {
4324
+ return null;
4325
+ }
4326
+ var baseMatch = stripMatchField(query, found.field);
4327
+ var orConditions = fields.map(function (field) {
4328
+ var _a;
4329
+ return (_a = {}, _a[field] = found.condition, _a);
4330
+ });
4331
+ var nextMatch = isEmptyMatchValue(baseMatch)
4332
+ ? { $or: orConditions }
4333
+ : { $and: [baseMatch, { $or: orConditions }] };
4334
+ return {
4335
+ query: nextMatch,
4336
+ field: found.field,
4337
+ fields: fields
4338
+ };
4339
+ }
3567
4340
  function isEmptyMatchValue(value) {
3568
4341
  if (value === null || value === undefined) {
3569
4342
  return true;
@@ -3611,6 +4384,454 @@ function stripMatchField(match, field) {
3611
4384
  });
3612
4385
  return result;
3613
4386
  }
4387
+ function isEmptyQueryValue(value) {
4388
+ if (value === null || value === undefined) {
4389
+ return true;
4390
+ }
4391
+ if (Array.isArray(value)) {
4392
+ return value.length === 0;
4393
+ }
4394
+ if (typeof value === 'object') {
4395
+ return Object.keys(value).length === 0;
4396
+ }
4397
+ return false;
4398
+ }
4399
+ function stripQueryFieldPathsDeepWithMeta(query, fieldsToStrip) {
4400
+ var fieldSet = new Set((fieldsToStrip || []).filter(Boolean));
4401
+ var stripValue = function (value, prefix) {
4402
+ if (Array.isArray(value)) {
4403
+ var changed_1 = false;
4404
+ var nextArray = value
4405
+ .map(function (entry) {
4406
+ var stripped = stripValue(entry, prefix);
4407
+ if (stripped.changed) {
4408
+ changed_1 = true;
4409
+ }
4410
+ return stripped.value;
4411
+ })
4412
+ .filter(function (entry) { return !isEmptyQueryValue(entry); });
4413
+ if (nextArray.length !== value.length) {
4414
+ changed_1 = true;
4415
+ }
4416
+ return { value: nextArray, changed: changed_1 };
4417
+ }
4418
+ if (!value || typeof value !== 'object' || value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
4419
+ return { value: value, changed: false };
4420
+ }
4421
+ var result = {};
4422
+ var changed = false;
4423
+ var keys = Object.keys(value);
4424
+ keys.forEach(function (key) {
4425
+ var entry = value[key];
4426
+ if (key.startsWith('$')) {
4427
+ if (Array.isArray(entry) && (key === '$and' || key === '$or' || key === '$nor')) {
4428
+ var stripped = stripValue(entry, prefix);
4429
+ var arrayValue = Array.isArray(stripped.value) ? stripped.value : [];
4430
+ if (arrayValue.length === 0) {
4431
+ changed = true;
4432
+ return;
4433
+ }
4434
+ if (arrayValue.length !== entry.length || stripped.changed) {
4435
+ changed = true;
4436
+ }
4437
+ result[key] = arrayValue;
4438
+ return;
4439
+ }
4440
+ if (entry && typeof entry === 'object') {
4441
+ var stripped = stripValue(entry, prefix);
4442
+ if (stripped.changed) {
4443
+ changed = true;
4444
+ }
4445
+ result[key] = stripped.value;
4446
+ return;
4447
+ }
4448
+ result[key] = entry;
4449
+ return;
4450
+ }
4451
+ var currentPath = prefix ? "".concat(prefix, ".").concat(key) : key;
4452
+ if (fieldSet.has(currentPath)) {
4453
+ changed = true;
4454
+ return;
4455
+ }
4456
+ if (entry && typeof entry === 'object') {
4457
+ var stripped = stripValue(entry, currentPath);
4458
+ if (stripped.changed) {
4459
+ changed = true;
4460
+ }
4461
+ if (!isEmptyQueryValue(stripped.value)) {
4462
+ result[key] = stripped.value;
4463
+ }
4464
+ else {
4465
+ changed = true;
4466
+ }
4467
+ return;
4468
+ }
4469
+ result[key] = entry;
4470
+ });
4471
+ var resultKeys = Object.keys(result);
4472
+ if (resultKeys.length === 1 && (resultKeys[0] === '$and' || resultKeys[0] === '$or')) {
4473
+ var only = result[resultKeys[0]];
4474
+ if (Array.isArray(only) && only.length === 1) {
4475
+ return { value: only[0], changed: true };
4476
+ }
4477
+ }
4478
+ return { value: result, changed: changed };
4479
+ };
4480
+ return stripValue(query, '');
4481
+ }
4482
+ function stripQueryFieldPathsDeep(query, fieldsToStrip) {
4483
+ return stripQueryFieldPathsDeepWithMeta(query, fieldsToStrip).value;
4484
+ }
4485
+ function stripScopedFieldsFromPipelineWithMeta(pipeline, fieldsToStrip) {
4486
+ if (!Array.isArray(pipeline)) {
4487
+ return { pipeline: [], changed: false };
4488
+ }
4489
+ var changed = false;
4490
+ var nextPipeline = pipeline.map(function (stage) {
4491
+ if (!stage || typeof stage !== 'object') {
4492
+ return stage;
4493
+ }
4494
+ var nextStage = stage;
4495
+ if (stage.$match && typeof stage.$match === 'object') {
4496
+ var stripped = stripQueryFieldPathsDeepWithMeta(stage.$match, fieldsToStrip);
4497
+ if (stripped.changed) {
4498
+ changed = true;
4499
+ }
4500
+ nextStage = __assign(__assign({}, nextStage), { $match: stripped.value });
4501
+ }
4502
+ if (stage.$geoNear && typeof stage.$geoNear === 'object' && stage.$geoNear.query) {
4503
+ var stripped = stripQueryFieldPathsDeepWithMeta(stage.$geoNear.query, fieldsToStrip);
4504
+ if (stripped.changed) {
4505
+ changed = true;
4506
+ }
4507
+ nextStage = __assign(__assign({}, nextStage), { $geoNear: __assign(__assign({}, stage.$geoNear), { query: stripped.value }) });
4508
+ }
4509
+ return nextStage;
4510
+ });
4511
+ return { pipeline: nextPipeline, changed: changed };
4512
+ }
4513
+ function stripScopedFieldsFromPipeline(pipeline, fieldsToStrip) {
4514
+ return stripScopedFieldsFromPipelineWithMeta(pipeline, fieldsToStrip).pipeline;
4515
+ }
4516
+ function isIdLookupCondition(value) {
4517
+ if (!value) {
4518
+ return false;
4519
+ }
4520
+ if (value instanceof RegExp) {
4521
+ return true;
4522
+ }
4523
+ if (typeof value === 'string') {
4524
+ return !isObjectIdString(value.trim());
4525
+ }
4526
+ if (typeof value === 'object') {
4527
+ return Object.prototype.hasOwnProperty.call(value, '$regex');
4528
+ }
4529
+ return false;
4530
+ }
4531
+ function collectIdFieldConditions(match) {
4532
+ var results = [];
4533
+ var visit = function (value) {
4534
+ if (Array.isArray(value)) {
4535
+ value.forEach(function (entry) { return visit(entry); });
4536
+ return;
4537
+ }
4538
+ if (!value || typeof value !== 'object') {
4539
+ return;
4540
+ }
4541
+ Object.keys(value).forEach(function (key) {
4542
+ var entry = value[key];
4543
+ if (key.startsWith('$')) {
4544
+ visit(entry);
4545
+ return;
4546
+ }
4547
+ if (isAssistantIdField(key) && isIdLookupCondition(entry)) {
4548
+ results.push({ field: key, condition: entry });
4549
+ return;
4550
+ }
4551
+ if (entry && typeof entry === 'object') {
4552
+ visit(entry);
4553
+ }
4554
+ });
4555
+ };
4556
+ visit(match);
4557
+ return results;
4558
+ }
4559
+ function resolveLocalNameFieldFromDocs(docs, baseToken) {
4560
+ var normalizedBase = normalizeOptionalString(baseToken);
4561
+ if (!normalizedBase || !Array.isArray(docs) || !docs.length) {
4562
+ return null;
4563
+ }
4564
+ if (hasNonEmptyValue(docs, normalizedBase, { treatObjectLikeAsEmpty: true })) {
4565
+ return normalizedBase;
4566
+ }
4567
+ var aliases = resolveFieldAliases(docs, [normalizedBase]);
4568
+ return aliases[normalizedBase] || null;
4569
+ }
4570
+ function buildIdFieldNameFallbackQuery(query, idField, nameField, condition) {
4571
+ var _a, _b;
4572
+ var baseMatch = stripMatchField(query, idField);
4573
+ var orConditions = [
4574
+ (_a = {}, _a[idField] = condition, _a),
4575
+ (_b = {}, _b[nameField] = condition, _b)
4576
+ ];
4577
+ var nextMatch = isEmptyMatchValue(baseMatch)
4578
+ ? { $or: orConditions }
4579
+ : { $and: [baseMatch, { $or: orConditions }] };
4580
+ return nextMatch;
4581
+ }
4582
+ function resolveIdLookupCandidates(baseToken, collectionNames) {
4583
+ var normalizedBase = normalizeOptionalString(baseToken).toLowerCase();
4584
+ if (!normalizedBase || !Array.isArray(collectionNames) || !collectionNames.length) {
4585
+ return [];
4586
+ }
4587
+ var candidates = new Set();
4588
+ var hints = AI_ASSISTANT_ID_LOOKUP_HINTS[normalizedBase] || [];
4589
+ hints.forEach(function (hint) {
4590
+ if (collectionNames.includes(hint)) {
4591
+ candidates.add(hint);
4592
+ }
4593
+ });
4594
+ var tokens = tokenizeCollectionText(normalizedBase);
4595
+ var ranked = collectionNames
4596
+ .map(function (name) { return ({ name: name, score: scoreCollectionMatch(tokens, name) }); })
4597
+ .filter(function (entry) { return entry.score > 0; })
4598
+ .sort(function (a, b) { return b.score - a.score; })
4599
+ .slice(0, AI_ASSISTANT_ID_LOOKUP_CANDIDATE_LIMIT);
4600
+ ranked.forEach(function (entry) { return candidates.add(entry.name); });
4601
+ return Array.from(candidates);
4602
+ }
4603
+ function buildNameLookupFields(baseToken, docs) {
4604
+ var normalizedBase = normalizeOptionalString(baseToken);
4605
+ var candidates = expandNameFieldCandidates(normalizedBase);
4606
+ if (!Array.isArray(docs) || !docs.length) {
4607
+ return candidates;
4608
+ }
4609
+ var available = collectFieldCandidates(docs);
4610
+ var filtered = candidates.filter(function (field) {
4611
+ var stats = available.get(field);
4612
+ return !!stats && stats.nonEmpty > 0;
4613
+ });
4614
+ return filtered.length ? filtered : candidates;
4615
+ }
4616
+ function lookupIdsForNameMatch(params) {
4617
+ return __awaiter(this, void 0, void 0, function () {
4618
+ var db, dbName, collection, baseToken, regex, idClient, idCustomer, isSuperAdmin, probeDocs, fields, query, hasClient, normalizedCustomer, hasCustomer, projection, docs, ids;
4619
+ return __generator(this, function (_a) {
4620
+ switch (_a.label) {
4621
+ case 0:
4622
+ db = params.db, dbName = params.dbName, collection = params.collection, baseToken = params.baseToken, regex = params.regex, idClient = params.idClient, idCustomer = params.idCustomer, isSuperAdmin = params.isSuperAdmin, probeDocs = params.probeDocs;
4623
+ fields = buildNameLookupFields(baseToken, probeDocs);
4624
+ if (!fields.length) {
4625
+ return [2 /*return*/, null];
4626
+ }
4627
+ query = { $or: fields.map(function (field) {
4628
+ var _a;
4629
+ return (_a = {}, _a[field] = regex, _a);
4630
+ }) };
4631
+ if (!!isSuperAdmin) return [3 /*break*/, 3];
4632
+ return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
4633
+ case 1:
4634
+ hasClient = _a.sent();
4635
+ if (hasClient) {
4636
+ query = applyClientScopeFilter(query, idClient, isSuperAdmin);
4637
+ }
4638
+ normalizedCustomer = normalizeOptionalString(idCustomer);
4639
+ if (!(normalizedCustomer && collection !== 'customers')) return [3 /*break*/, 3];
4640
+ return [4 /*yield*/, collectionHasFieldIndex(db, dbName, collection, 'id_customer')];
4641
+ case 2:
4642
+ hasCustomer = _a.sent();
4643
+ if (hasCustomer) {
4644
+ query = applyCustomerScopeFilter(query, collection, normalizedCustomer, isSuperAdmin);
4645
+ }
4646
+ _a.label = 3;
4647
+ case 3:
4648
+ projection = { _id: 1 };
4649
+ fields.forEach(function (field) {
4650
+ projection[field] = 1;
4651
+ });
4652
+ return [4 /*yield*/, db.collection(collection)
4653
+ .find(query, {
4654
+ projection: projection,
4655
+ limit: AI_ASSISTANT_ID_LOOKUP_MAX_RESULTS,
4656
+ readPreference: AI_ASSISTANT_READ_PREFERENCE
4657
+ })
4658
+ .toArray()];
4659
+ case 4:
4660
+ docs = _a.sent();
4661
+ ids = docs.map(function (doc) { return doc === null || doc === void 0 ? void 0 : doc._id; }).filter(Boolean);
4662
+ return [2 /*return*/, ids.length ? { ids: ids, fields: fields } : null];
4663
+ }
4664
+ });
4665
+ });
4666
+ }
4667
+ function applyIdLookupFallbackToQuery(params) {
4668
+ 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;
4671
+ var _e;
4672
+ return __generator(this, function (_f) {
4673
+ switch (_f.label) {
4674
+ case 0:
4675
+ query = params.query, db = params.db, dbName = params.dbName, idClient = params.idClient, idCustomer = params.idCustomer, isSuperAdmin = params.isSuperAdmin, probeDocs = params.probeDocs;
4676
+ conditions = collectIdFieldConditions(query);
4677
+ if (!conditions.length) {
4678
+ return [2 /*return*/, null];
4679
+ }
4680
+ _a = params.collectionNames;
4681
+ if (_a) return [3 /*break*/, 2];
4682
+ return [4 /*yield*/, listAssistantCollections(db, dbName)];
4683
+ case 1:
4684
+ _a = (_f.sent());
4685
+ _f.label = 2;
4686
+ case 2:
4687
+ collectionNames = _a;
4688
+ _f.label = 3;
4689
+ case 3:
4690
+ _f.trys.push([3, 18, 19, 20]);
4691
+ conditions_1 = __values(conditions), conditions_1_1 = conditions_1.next();
4692
+ _f.label = 4;
4693
+ case 4:
4694
+ if (!!conditions_1_1.done) return [3 /*break*/, 17];
4695
+ condition = conditions_1_1.value;
4696
+ regex = buildRegexFromCondition(condition.condition);
4697
+ if (!regex) {
4698
+ return [3 /*break*/, 16];
4699
+ }
4700
+ baseToken = normalizeIdFieldBase(condition.field);
4701
+ if (!baseToken) {
4702
+ return [3 /*break*/, 16];
4703
+ }
4704
+ if (baseToken === 'customer' && idCustomer) {
4705
+ targetFieldType = inferIdFieldStorageTypeFromDocs(probeDocs || [], condition.field);
4706
+ nextValue = idCustomer;
4707
+ if (targetFieldType === 'objectId' && isObjectIdString(idCustomer)) {
4708
+ try {
4709
+ nextValue = new mongodb_1.ObjectId(idCustomer);
4710
+ }
4711
+ catch (_g) {
4712
+ nextValue = idCustomer;
4713
+ }
4714
+ }
4715
+ return [2 /*return*/, {
4716
+ query: replaceQueryFieldCondition(query, condition.field, nextValue),
4717
+ meta: {
4718
+ field: condition.field,
4719
+ strategy: 'customer_scope',
4720
+ value: idCustomer,
4721
+ targetFieldType: targetFieldType
4722
+ }
4723
+ }];
4724
+ }
4725
+ localNameField = resolveLocalNameFieldFromDocs(probeDocs || [], baseToken);
4726
+ if (localNameField) {
4727
+ return [2 /*return*/, {
4728
+ query: buildIdFieldNameFallbackQuery(query, condition.field, localNameField, regex),
4729
+ meta: {
4730
+ field: condition.field,
4731
+ strategy: 'local_name',
4732
+ nameField: localNameField
4733
+ }
4734
+ }];
4735
+ }
4736
+ candidates = resolveIdLookupCandidates(baseToken, collectionNames);
4737
+ _f.label = 5;
4738
+ case 5:
4739
+ _f.trys.push([5, 14, 15, 16]);
4740
+ candidates_1 = (e_8 = void 0, __values(candidates)), candidates_1_1 = candidates_1.next();
4741
+ _f.label = 6;
4742
+ case 6:
4743
+ if (!!candidates_1_1.done) return [3 /*break*/, 13];
4744
+ candidate = candidates_1_1.value;
4745
+ if (!candidate) {
4746
+ return [3 /*break*/, 12];
4747
+ }
4748
+ if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(candidate)) {
4749
+ return [3 /*break*/, 12];
4750
+ }
4751
+ if (!idClient) return [3 /*break*/, 8];
4752
+ return [4 /*yield*/, collectionHasClientIndex(db, dbName, candidate)];
4753
+ case 7:
4754
+ _b = _f.sent();
4755
+ return [3 /*break*/, 9];
4756
+ case 8:
4757
+ _b = false;
4758
+ _f.label = 9;
4759
+ case 9:
4760
+ candidateHasClientScope = _b;
4761
+ return [4 /*yield*/, fetchAssistantProbeDocs({
4762
+ db: db,
4763
+ collection: candidate,
4764
+ idClient: idClient,
4765
+ idCustomer: idCustomer,
4766
+ isSuperAdmin: isSuperAdmin,
4767
+ includeClientScope: candidateHasClientScope
4768
+ })];
4769
+ case 10:
4770
+ candidateProbe = _f.sent();
4771
+ return [4 /*yield*/, lookupIdsForNameMatch({
4772
+ db: db,
4773
+ dbName: dbName,
4774
+ collection: candidate,
4775
+ baseToken: baseToken,
4776
+ regex: regex,
4777
+ idClient: idClient,
4778
+ idCustomer: idCustomer,
4779
+ isSuperAdmin: isSuperAdmin,
4780
+ probeDocs: candidateProbe
4781
+ })];
4782
+ case 11:
4783
+ lookup = _f.sent();
4784
+ if ((_e = lookup === null || lookup === void 0 ? void 0 : lookup.ids) === null || _e === void 0 ? void 0 : _e.length) {
4785
+ targetFieldType = inferIdFieldStorageTypeFromDocs(probeDocs || [], condition.field);
4786
+ normalizedIds = normalizeIdsForTargetField(lookup.ids, probeDocs || [], condition.field, targetFieldType);
4787
+ idsForQuery = normalizedIds.length ? normalizedIds : lookup.ids;
4788
+ return [2 /*return*/, {
4789
+ query: replaceQueryFieldCondition(query, condition.field, { $in: idsForQuery }),
4790
+ meta: {
4791
+ field: condition.field,
4792
+ strategy: 'lookup',
4793
+ collection: candidate,
4794
+ ids: lookup.ids.length,
4795
+ idsNormalized: normalizedIds.length,
4796
+ targetFieldType: targetFieldType,
4797
+ fields: lookup.fields
4798
+ }
4799
+ }];
4800
+ }
4801
+ _f.label = 12;
4802
+ case 12:
4803
+ candidates_1_1 = candidates_1.next();
4804
+ return [3 /*break*/, 6];
4805
+ case 13: return [3 /*break*/, 16];
4806
+ case 14:
4807
+ e_8_1 = _f.sent();
4808
+ e_8 = { error: e_8_1 };
4809
+ return [3 /*break*/, 16];
4810
+ case 15:
4811
+ try {
4812
+ if (candidates_1_1 && !candidates_1_1.done && (_d = candidates_1.return)) _d.call(candidates_1);
4813
+ }
4814
+ finally { if (e_8) throw e_8.error; }
4815
+ return [7 /*endfinally*/];
4816
+ case 16:
4817
+ conditions_1_1 = conditions_1.next();
4818
+ return [3 /*break*/, 4];
4819
+ case 17: return [3 /*break*/, 20];
4820
+ case 18:
4821
+ e_9_1 = _f.sent();
4822
+ e_9 = { error: e_9_1 };
4823
+ return [3 /*break*/, 20];
4824
+ case 19:
4825
+ try {
4826
+ if (conditions_1_1 && !conditions_1_1.done && (_c = conditions_1.return)) _c.call(conditions_1);
4827
+ }
4828
+ finally { if (e_9) throw e_9.error; }
4829
+ return [7 /*endfinally*/];
4830
+ case 20: return [2 /*return*/, null];
4831
+ }
4832
+ });
4833
+ });
4834
+ }
3614
4835
  function buildAggregateNameMatchFallbackPipeline(pipeline, fallback) {
3615
4836
  var _a;
3616
4837
  var matchStage = (_a = pipeline[fallback.matchIndex]) === null || _a === void 0 ? void 0 : _a.$match;
@@ -3690,12 +4911,12 @@ function replaceAggregateDateField(pipeline, fromField, toField) {
3690
4911
  return value;
3691
4912
  }
3692
4913
  if (value && typeof value === 'object') {
3693
- var next_1 = {};
4914
+ var next_2 = {};
3694
4915
  Object.keys(value).forEach(function (key) {
3695
4916
  var nextKey = key === fromField ? toField : key;
3696
- next_1[nextKey] = replacer(value[key]);
4917
+ next_2[nextKey] = replacer(value[key]);
3697
4918
  });
3698
- return next_1;
4919
+ return next_2;
3699
4920
  }
3700
4921
  if (typeof value === 'string') {
3701
4922
  if (value.startsWith("$".concat(fromField))) {
@@ -3712,7 +4933,8 @@ function normalizeMongoQuery(query) {
3712
4933
  if (containsForbiddenMongoOperators(normalized)) {
3713
4934
  throw new Error('AI assistant mongo read: Query contains restricted operators.');
3714
4935
  }
3715
- return applyAssistantNameRegexToQuery(normalized);
4936
+ var rewritten = rewriteEmbeddedMatchObjects(normalized);
4937
+ return applyAssistantNameRegexToQuery(rewritten);
3716
4938
  }
3717
4939
  function shouldApplyAssistantNameRegex(field) {
3718
4940
  var normalized = String(field || '').toLowerCase().trim();
@@ -3769,6 +4991,126 @@ function applyAssistantNameRegexToQuery(query) {
3769
4991
  });
3770
4992
  return result;
3771
4993
  }
4994
+ function isObjectIdString(value) {
4995
+ return /^[a-f0-9]{24}$/i.test(value);
4996
+ }
4997
+ function isPlainMatchObject(value) {
4998
+ return isPlainObject(value)
4999
+ && !isMongoObjectId(value)
5000
+ && !(value instanceof Date)
5001
+ && !(value instanceof RegExp);
5002
+ }
5003
+ function hasOperatorKeys(value) {
5004
+ if (!value || typeof value !== 'object') {
5005
+ return false;
5006
+ }
5007
+ return Object.keys(value).some(function (key) { return key.startsWith('$'); });
5008
+ }
5009
+ function rewriteEmbeddedMatchObjects(query) {
5010
+ var rewriteValue = function (value, allowArrayRewrite) {
5011
+ if (Array.isArray(value)) {
5012
+ if (!allowArrayRewrite) {
5013
+ return value;
5014
+ }
5015
+ return value.map(function (entry) { return rewriteValue(entry, true); });
5016
+ }
5017
+ if (!value || typeof value !== 'object' || value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
5018
+ return value;
5019
+ }
5020
+ var result = {};
5021
+ Object.keys(value).forEach(function (key) {
5022
+ var entry = value[key];
5023
+ if (key.startsWith('$')) {
5024
+ result[key] = rewriteValue(entry, true);
5025
+ return;
5026
+ }
5027
+ if (isPlainMatchObject(entry) && !Array.isArray(entry) && !hasOperatorKeys(entry)) {
5028
+ var flattened = flattenMatchObject(entry, key);
5029
+ Object.assign(result, flattened);
5030
+ return;
5031
+ }
5032
+ if (isPlainMatchObject(entry) && !Array.isArray(entry)) {
5033
+ result[key] = rewriteValue(entry, true);
5034
+ return;
5035
+ }
5036
+ if (Array.isArray(entry)) {
5037
+ result[key] = allowArrayRewrite ? entry.map(function (item) { return rewriteValue(item, true); }) : entry;
5038
+ return;
5039
+ }
5040
+ result[key] = entry;
5041
+ });
5042
+ return result;
5043
+ };
5044
+ var flattenMatchObject = function (value, prefix) {
5045
+ var result = {};
5046
+ Object.keys(value || {}).forEach(function (key) {
5047
+ var entry = value[key];
5048
+ var currentPath = "".concat(prefix, ".").concat(key);
5049
+ if (isPlainMatchObject(entry) && !Array.isArray(entry) && !hasOperatorKeys(entry)) {
5050
+ var flattened = flattenMatchObject(entry, currentPath);
5051
+ Object.assign(result, flattened);
5052
+ return;
5053
+ }
5054
+ if (isPlainMatchObject(entry) && !Array.isArray(entry)) {
5055
+ result[currentPath] = rewriteValue(entry, true);
5056
+ return;
5057
+ }
5058
+ if (Array.isArray(entry)) {
5059
+ result[currentPath] = entry;
5060
+ return;
5061
+ }
5062
+ result[currentPath] = entry;
5063
+ });
5064
+ return result;
5065
+ };
5066
+ return rewriteValue(query, true);
5067
+ }
5068
+ function buildRegexFromCondition(condition) {
5069
+ if (!condition) {
5070
+ return null;
5071
+ }
5072
+ if (condition instanceof RegExp) {
5073
+ return condition;
5074
+ }
5075
+ if (typeof condition === 'string') {
5076
+ var trimmed = condition.trim();
5077
+ if (!trimmed || isObjectIdString(trimmed)) {
5078
+ return null;
5079
+ }
5080
+ return new RegExp(escapeRegexValue(trimmed), 'i');
5081
+ }
5082
+ if (typeof condition === 'object') {
5083
+ var raw = condition.$regex;
5084
+ if (raw !== undefined) {
5085
+ var source = String(raw);
5086
+ var options = typeof condition.$options === 'string'
5087
+ ? condition.$options
5088
+ : 'i';
5089
+ try {
5090
+ return new RegExp(source, options);
5091
+ }
5092
+ catch (_a) {
5093
+ return new RegExp(escapeRegexValue(source), 'i');
5094
+ }
5095
+ }
5096
+ }
5097
+ return null;
5098
+ }
5099
+ function normalizeIdFieldBase(field) {
5100
+ var normalized = normalizeOptionalString(field).toLowerCase();
5101
+ if (!normalized) {
5102
+ return '';
5103
+ }
5104
+ var parts = normalized.split('.').filter(Boolean);
5105
+ var last = parts[parts.length - 1] || normalized;
5106
+ if (last.startsWith('id_')) {
5107
+ return last.slice(3);
5108
+ }
5109
+ if (normalized.startsWith('id_')) {
5110
+ return normalized.slice(3);
5111
+ }
5112
+ return last;
5113
+ }
3772
5114
  function normalizeCollectionKey(value) {
3773
5115
  return String(value || '').toLowerCase().replace(/[^a-z0-9]/g, '');
3774
5116
  }
@@ -3803,6 +5145,19 @@ function tokenizeCollectionText(value) {
3803
5145
  });
3804
5146
  return Array.from(new Set(tokens));
3805
5147
  }
5148
+ function computeCollectionTokenWeights(tokens) {
5149
+ var unique = Array.from(new Set(tokens));
5150
+ var hasDomain = unique.some(function (token) { return AI_ASSISTANT_COLLECTION_DOMAIN_TOKENS.has(token); });
5151
+ var weights = {};
5152
+ unique.forEach(function (token) {
5153
+ if (hasDomain && AI_ASSISTANT_COLLECTION_GENERIC_TOKENS.has(token)) {
5154
+ weights[token] = 0.4;
5155
+ return;
5156
+ }
5157
+ weights[token] = 1;
5158
+ });
5159
+ return { weights: weights, hasDomain: hasDomain };
5160
+ }
3806
5161
  function expandAssistantTermSynonyms(text) {
3807
5162
  var base = normalizeOptionalString(text);
3808
5163
  if (!base) {
@@ -3855,7 +5210,7 @@ function listAssistantCollections(db, dbName) {
3855
5210
  });
3856
5211
  });
3857
5212
  }
3858
- function scoreCollectionMatch(requestedTokens, candidateName) {
5213
+ function scoreCollectionMatch(requestedTokens, candidateName, tokenWeights) {
3859
5214
  if (!requestedTokens.length) {
3860
5215
  return 0;
3861
5216
  }
@@ -3865,8 +5220,10 @@ function scoreCollectionMatch(requestedTokens, candidateName) {
3865
5220
  }
3866
5221
  var score = 0;
3867
5222
  requestedTokens.forEach(function (token) {
5223
+ var _a;
3868
5224
  if (candidateTokens.includes(token)) {
3869
- score += 10;
5225
+ var weight = (_a = tokenWeights === null || tokenWeights === void 0 ? void 0 : tokenWeights[token]) !== null && _a !== void 0 ? _a : 1;
5226
+ score += 10 * weight;
3870
5227
  }
3871
5228
  });
3872
5229
  var requestedKey = normalizeCollectionKey(requestedTokens.join('-'));
@@ -3879,10 +5236,12 @@ function scoreCollectionMatch(requestedTokens, candidateName) {
3879
5236
  }
3880
5237
  return score;
3881
5238
  }
3882
- function scoreCollectionMatchDetailed(requestedTokens, candidateName) {
5239
+ function scoreCollectionMatchDetailed(requestedTokens, candidateName, tokenWeights) {
3883
5240
  var candidateTokens = tokenizeCollectionText(candidateName);
3884
5241
  var tokenMatches = requestedTokens.filter(function (token) { return candidateTokens.includes(token); });
3885
- var score = tokenMatches.length * 10;
5242
+ var weights = tokenWeights || {};
5243
+ var tokenScore = tokenMatches.reduce(function (sum, token) { var _a; return sum + 10 * ((_a = weights[token]) !== null && _a !== void 0 ? _a : 1); }, 0);
5244
+ var score = tokenScore;
3886
5245
  var requestedKey = normalizeCollectionKey(requestedTokens.join('-'));
3887
5246
  var candidateKey = normalizeCollectionKey(candidateName);
3888
5247
  var keyMatch = null;
@@ -3898,7 +5257,13 @@ function scoreCollectionMatchDetailed(requestedTokens, candidateName) {
3898
5257
  score: score,
3899
5258
  tokenMatches: tokenMatches,
3900
5259
  keyMatch: keyMatch,
3901
- candidateTokens: candidateTokens
5260
+ candidateTokens: candidateTokens,
5261
+ tokenScore: tokenScore,
5262
+ tokenWeights: tokenMatches.reduce(function (acc, token) {
5263
+ var _a;
5264
+ acc[token] = (_a = weights[token]) !== null && _a !== void 0 ? _a : 1;
5265
+ return acc;
5266
+ }, {})
3902
5267
  };
3903
5268
  }
3904
5269
  function resolveCollectionHintsFromTokens(tokens, collectionNames, max) {
@@ -3906,8 +5271,9 @@ function resolveCollectionHintsFromTokens(tokens, collectionNames, max) {
3906
5271
  if (!tokens.length || !collectionNames.length) {
3907
5272
  return [];
3908
5273
  }
5274
+ var weights = computeCollectionTokenWeights(tokens).weights;
3909
5275
  return collectionNames
3910
- .map(function (name) { return ({ name: name, score: scoreCollectionMatch(tokens, name) }); })
5276
+ .map(function (name) { return ({ name: name, score: scoreCollectionMatch(tokens, name, weights) }); })
3911
5277
  .filter(function (entry) { return entry.score > 0; })
3912
5278
  .sort(function (a, b) { return b.score - a.score; })
3913
5279
  .slice(0, Math.max(max, 0))
@@ -3916,21 +5282,26 @@ function resolveCollectionHintsFromTokens(tokens, collectionNames, max) {
3916
5282
  function buildCollectionRankingDebugFromTokens(tokens, collectionNames, max) {
3917
5283
  if (max === void 0) { max = 8; }
3918
5284
  var requestedKey = normalizeCollectionKey(tokens.join('-'));
5285
+ var _a = computeCollectionTokenWeights(tokens), weights = _a.weights, hasDomain = _a.hasDomain;
3919
5286
  if (!tokens.length || !collectionNames.length) {
3920
5287
  return {
3921
5288
  tokens: tokens,
3922
5289
  requestedKey: requestedKey,
5290
+ hasDomain: hasDomain,
5291
+ tokenWeights: weights,
3923
5292
  ranked: []
3924
5293
  };
3925
5294
  }
3926
5295
  var ranked = collectionNames
3927
- .map(function (name) { return (__assign({ name: name }, scoreCollectionMatchDetailed(tokens, name))); })
5296
+ .map(function (name) { return (__assign({ name: name }, scoreCollectionMatchDetailed(tokens, name, weights))); })
3928
5297
  .filter(function (entry) { return entry.score > 0; })
3929
5298
  .sort(function (a, b) { return b.score - a.score; })
3930
5299
  .slice(0, Math.max(max, 0));
3931
5300
  return {
3932
5301
  tokens: tokens,
3933
5302
  requestedKey: requestedKey,
5303
+ hasDomain: hasDomain,
5304
+ tokenWeights: weights,
3934
5305
  ranked: ranked
3935
5306
  };
3936
5307
  }
@@ -3939,13 +5310,78 @@ function buildCollectionSelectionDetail(tokens, collection) {
3939
5310
  if (!trimmed) {
3940
5311
  return null;
3941
5312
  }
3942
- var detail = scoreCollectionMatchDetailed(tokens, trimmed);
5313
+ var weights = computeCollectionTokenWeights(tokens).weights;
5314
+ var detail = scoreCollectionMatchDetailed(tokens, trimmed, weights);
3943
5315
  return {
3944
5316
  collection: trimmed,
3945
5317
  score: detail.score,
3946
5318
  tokenMatches: detail.tokenMatches,
3947
5319
  keyMatch: detail.keyMatch,
3948
- candidateTokens: detail.candidateTokens
5320
+ candidateTokens: detail.candidateTokens,
5321
+ tokenScore: detail.tokenScore,
5322
+ tokenWeights: detail.tokenWeights
5323
+ };
5324
+ }
5325
+ function isVersionCollectionName(value) {
5326
+ var normalized = normalizeOptionalString(value).toLowerCase();
5327
+ return normalized.endsWith('.versions') || normalized.endsWith('-versions') || normalized.includes('.versions.');
5328
+ }
5329
+ function pickPreferredCollectionCandidate(ranked) {
5330
+ if (!Array.isArray(ranked) || !ranked.length) {
5331
+ return null;
5332
+ }
5333
+ var top = ranked[0];
5334
+ if (!top) {
5335
+ return null;
5336
+ }
5337
+ if (!isVersionCollectionName(top.name)) {
5338
+ return top;
5339
+ }
5340
+ var nonVersion = ranked.find(function (entry) { return entry && !isVersionCollectionName(entry.name); });
5341
+ if (nonVersion && nonVersion.score >= top.score - 5) {
5342
+ return nonVersion;
5343
+ }
5344
+ return top;
5345
+ }
5346
+ function resolveAssistantCollectionOverride(collectionRanking, currentCollection) {
5347
+ var _a, _b;
5348
+ var ranked = Array.isArray(collectionRanking === null || collectionRanking === void 0 ? void 0 : collectionRanking.ranked) ? collectionRanking === null || collectionRanking === void 0 ? void 0 : collectionRanking.ranked : [];
5349
+ if (!ranked.length) {
5350
+ return null;
5351
+ }
5352
+ var top = pickPreferredCollectionCandidate(ranked);
5353
+ if (!top || top.score < AI_ASSISTANT_COLLECTION_OVERRIDE_MIN_SCORE) {
5354
+ return null;
5355
+ }
5356
+ var current = normalizeOptionalString(currentCollection);
5357
+ if (!current) {
5358
+ return {
5359
+ from: '',
5360
+ to: top.name,
5361
+ fromScore: 0,
5362
+ toScore: top.score,
5363
+ reason: 'no collection specified'
5364
+ };
5365
+ }
5366
+ if (current === top.name) {
5367
+ return null;
5368
+ }
5369
+ var currentScore = (_b = (_a = ranked.find(function (entry) { return entry.name === current; })) === null || _a === void 0 ? void 0 : _a.score) !== null && _b !== void 0 ? _b : 0;
5370
+ var scoreGap = top.score - currentScore;
5371
+ var currentIsVersion = isVersionCollectionName(current);
5372
+ var topIsVersion = isVersionCollectionName(top.name);
5373
+ if (scoreGap < AI_ASSISTANT_COLLECTION_OVERRIDE_SCORE_GAP && !(currentIsVersion && !topIsVersion)) {
5374
+ return null;
5375
+ }
5376
+ var reason = currentIsVersion && !topIsVersion
5377
+ ? 'preferred non-version collection'
5378
+ : "higher score (".concat(top.score, " vs ").concat(currentScore, ")");
5379
+ return {
5380
+ from: current,
5381
+ to: top.name,
5382
+ fromScore: currentScore,
5383
+ toScore: top.score,
5384
+ reason: reason
3949
5385
  };
3950
5386
  }
3951
5387
  function findBestCollectionMatch(requested, collectionNames) {
@@ -3994,7 +5430,7 @@ function resolveAssistantCollectionName(db, dbName, requested) {
3994
5430
  });
3995
5431
  }
3996
5432
  function findQueryDateField(query) {
3997
- var e_7, _a, e_8, _b;
5433
+ var e_10, _a, e_11, _b;
3998
5434
  if (!query || typeof query !== 'object') {
3999
5435
  return null;
4000
5436
  }
@@ -4008,12 +5444,12 @@ function findQueryDateField(query) {
4008
5444
  }
4009
5445
  }
4010
5446
  }
4011
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
5447
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
4012
5448
  finally {
4013
5449
  try {
4014
5450
  if (query_1_1 && !query_1_1.done && (_a = query_1.return)) _a.call(query_1);
4015
5451
  }
4016
- finally { if (e_7) throw e_7.error; }
5452
+ finally { if (e_10) throw e_10.error; }
4017
5453
  }
4018
5454
  return null;
4019
5455
  }
@@ -4032,12 +5468,12 @@ function findQueryDateField(query) {
4032
5468
  }
4033
5469
  }
4034
5470
  }
4035
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
5471
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
4036
5472
  finally {
4037
5473
  try {
4038
5474
  if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
4039
5475
  }
4040
- finally { if (e_8) throw e_8.error; }
5476
+ finally { if (e_11) throw e_11.error; }
4041
5477
  }
4042
5478
  return null;
4043
5479
  }
@@ -4128,15 +5564,15 @@ function expandQueryDateFallbacks(query) {
4128
5564
  };
4129
5565
  var visit = function (value) {
4130
5566
  if (Array.isArray(value)) {
4131
- var changed_1 = false;
5567
+ var changed_2 = false;
4132
5568
  var nextArray = value.map(function (entry) {
4133
5569
  var visited = visit(entry);
4134
5570
  if (visited.changed) {
4135
- changed_1 = true;
5571
+ changed_2 = true;
4136
5572
  }
4137
5573
  return visited.value;
4138
5574
  });
4139
- return { value: changed_1 ? nextArray : value, changed: changed_1 };
5575
+ return { value: changed_2 ? nextArray : value, changed: changed_2 };
4140
5576
  }
4141
5577
  if (!value || typeof value !== 'object') {
4142
5578
  return { value: value, changed: false };
@@ -4166,6 +5602,87 @@ function expandQueryDateFallbacks(query) {
4166
5602
  }
4167
5603
  return { query: result.value, fields: addedFields };
4168
5604
  }
5605
+ function buildDateFieldExpansionList(field) {
5606
+ var normalized = normalizeOptionalString(field);
5607
+ if (!normalized) {
5608
+ return [];
5609
+ }
5610
+ var expansions = new Set();
5611
+ var add = function (value) {
5612
+ if (value && value !== normalized) {
5613
+ expansions.add(value);
5614
+ }
5615
+ };
5616
+ var fallback = AI_ASSISTANT_DATE_FALLBACKS[normalized];
5617
+ if (fallback) {
5618
+ add(fallback);
5619
+ }
5620
+ if (normalized.startsWith('date_') || normalized === 'date' || normalized.endsWith('_date')) {
5621
+ AI_ASSISTANT_DATE_EXPANSION_FIELDS.forEach(add);
5622
+ }
5623
+ if (normalized === 'createdAt' || normalized === 'updatedAt') {
5624
+ AI_ASSISTANT_DATE_EXPANSION_FIELDS.forEach(add);
5625
+ }
5626
+ return Array.from(expansions);
5627
+ }
5628
+ function expandAggregateDateMatchFallback(pipeline) {
5629
+ if (!Array.isArray(pipeline)) {
5630
+ return null;
5631
+ }
5632
+ var _loop_2 = function (i) {
5633
+ var stage = pipeline[i];
5634
+ if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
5635
+ return "continue";
5636
+ }
5637
+ var matchStage = stage.$match;
5638
+ var orArray = Array.isArray(matchStage.$or) ? matchStage.$or : null;
5639
+ if (!orArray || !orArray.length) {
5640
+ return "continue";
5641
+ }
5642
+ var existingFields = new Set();
5643
+ orArray.forEach(function (entry) {
5644
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
5645
+ return;
5646
+ }
5647
+ Object.keys(entry).forEach(function (key) {
5648
+ if (!key.startsWith('$')) {
5649
+ existingFields.add(key);
5650
+ }
5651
+ });
5652
+ });
5653
+ var expandedOr = __spreadArray([], __read(orArray), false);
5654
+ var addedFields = new Set();
5655
+ orArray.forEach(function (entry) {
5656
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
5657
+ return;
5658
+ }
5659
+ var conditions = extractDateRangeConditions(entry);
5660
+ conditions.forEach(function (condition) {
5661
+ var expansions = buildDateFieldExpansionList(condition.field);
5662
+ expansions.forEach(function (field) {
5663
+ if (existingFields.has(field)) {
5664
+ return;
5665
+ }
5666
+ expandedOr = __spreadArray(__spreadArray([], __read(expandedOr), false), [replaceQueryField(entry, condition.field, field)], false);
5667
+ existingFields.add(field);
5668
+ addedFields.add(field);
5669
+ });
5670
+ });
5671
+ });
5672
+ if (!addedFields.size) {
5673
+ return { value: null };
5674
+ }
5675
+ var nextMatch = __assign(__assign({}, matchStage), { $or: expandedOr });
5676
+ var updated = pipeline.map(function (current, index) { return (index === i ? { $match: nextMatch } : current); });
5677
+ return { value: { pipeline: updated, fields: Array.from(addedFields) } };
5678
+ };
5679
+ 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;
5683
+ }
5684
+ return null;
5685
+ }
4169
5686
  function resolveQueryDateFieldFallback(query) {
4170
5687
  var dateField = findQueryDateField(query);
4171
5688
  if (!dateField) {
@@ -4178,7 +5695,7 @@ function resolveQueryDateFieldFallback(query) {
4178
5695
  return { from: dateField, to: fallback };
4179
5696
  }
4180
5697
  function containsForbiddenMongoOperators(value) {
4181
- var e_9, _a;
5698
+ var e_12, _a;
4182
5699
  if (!value || typeof value !== 'object') {
4183
5700
  return false;
4184
5701
  }
@@ -4197,12 +5714,12 @@ function containsForbiddenMongoOperators(value) {
4197
5714
  }
4198
5715
  }
4199
5716
  }
4200
- catch (e_9_1) { e_9 = { error: e_9_1 }; }
5717
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
4201
5718
  finally {
4202
5719
  try {
4203
5720
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
4204
5721
  }
4205
- finally { if (e_9) throw e_9.error; }
5722
+ finally { if (e_12) throw e_12.error; }
4206
5723
  }
4207
5724
  return false;
4208
5725
  }
@@ -4211,9 +5728,49 @@ function buildClientScopeCacheKey(dbName, collection) {
4211
5728
  var normalizedCollection = normalizeOptionalString(collection).toLowerCase();
4212
5729
  return "".concat(normalizedDb || 'db', ":").concat(normalizedCollection);
4213
5730
  }
5731
+ function buildFieldIndexCacheKey(dbName, collection, field) {
5732
+ var normalizedDb = normalizeOptionalString(dbName).toLowerCase();
5733
+ var normalizedCollection = normalizeOptionalString(collection).toLowerCase();
5734
+ var normalizedField = normalizeOptionalString(field).toLowerCase();
5735
+ return "".concat(normalizedDb || 'db', ":").concat(normalizedCollection, ":").concat(normalizedField);
5736
+ }
5737
+ function collectionHasFieldIndex(db, dbName, collection, field) {
5738
+ return __awaiter(this, void 0, void 0, function () {
5739
+ var normalizedCollection, normalizedField, cacheKey, cached, indexes, hasIndex, _a;
5740
+ return __generator(this, function (_b) {
5741
+ switch (_b.label) {
5742
+ case 0:
5743
+ normalizedCollection = normalizeOptionalString(collection);
5744
+ normalizedField = normalizeOptionalString(field);
5745
+ if (!normalizedCollection || !normalizedField) {
5746
+ return [2 /*return*/, false];
5747
+ }
5748
+ cacheKey = buildFieldIndexCacheKey(dbName, normalizedCollection, normalizedField);
5749
+ cached = AI_ASSISTANT_FIELD_INDEX_CACHE.get(cacheKey);
5750
+ if (typeof cached === 'boolean') {
5751
+ return [2 /*return*/, cached];
5752
+ }
5753
+ _b.label = 1;
5754
+ case 1:
5755
+ _b.trys.push([1, 3, , 4]);
5756
+ return [4 /*yield*/, db.collection(normalizedCollection).indexes()];
5757
+ case 2:
5758
+ indexes = _b.sent();
5759
+ hasIndex = Array.isArray(indexes)
5760
+ && indexes.some(function (entry) { return (entry === null || entry === void 0 ? void 0 : entry.key) && Object.prototype.hasOwnProperty.call(entry.key, normalizedField); });
5761
+ AI_ASSISTANT_FIELD_INDEX_CACHE.set(cacheKey, hasIndex);
5762
+ return [2 /*return*/, hasIndex];
5763
+ case 3:
5764
+ _a = _b.sent();
5765
+ return [2 /*return*/, false];
5766
+ case 4: return [2 /*return*/];
5767
+ }
5768
+ });
5769
+ });
5770
+ }
4214
5771
  function collectionHasClientIndex(db, dbName, collection) {
4215
5772
  return __awaiter(this, void 0, void 0, function () {
4216
- var normalizedCollection, cacheKey, cached, indexes, hasIndex, _a;
5773
+ var normalizedCollection, cacheKey, cached, hasIndex, _a;
4217
5774
  return __generator(this, function (_b) {
4218
5775
  switch (_b.label) {
4219
5776
  case 0:
@@ -4229,11 +5786,9 @@ function collectionHasClientIndex(db, dbName, collection) {
4229
5786
  _b.label = 1;
4230
5787
  case 1:
4231
5788
  _b.trys.push([1, 3, , 4]);
4232
- return [4 /*yield*/, db.collection(normalizedCollection).indexes()];
5789
+ return [4 /*yield*/, collectionHasFieldIndex(db, dbName, normalizedCollection, 'id_client')];
4233
5790
  case 2:
4234
- indexes = _b.sent();
4235
- hasIndex = Array.isArray(indexes)
4236
- && indexes.some(function (entry) { return (entry === null || entry === void 0 ? void 0 : entry.key) && Object.prototype.hasOwnProperty.call(entry.key, 'id_client'); });
5791
+ hasIndex = _b.sent();
4237
5792
  AI_ASSISTANT_CLIENT_SCOPE_CACHE.set(cacheKey, hasIndex);
4238
5793
  return [2 /*return*/, hasIndex];
4239
5794
  case 3:
@@ -4275,6 +5830,25 @@ function applyCustomerScopeFilter(query, collection, idCustomer, isSuperAdmin) {
4275
5830
  $and: [query, (_a = {}, _a[customerField] = normalizedCustomer, _a)]
4276
5831
  };
4277
5832
  }
5833
+ function buildAssistantProbeQuery(collection, idClient, idCustomer, isSuperAdmin, includeClientScope) {
5834
+ if (isSuperAdmin === void 0) { isSuperAdmin = false; }
5835
+ if (includeClientScope === void 0) { includeClientScope = false; }
5836
+ var query = {};
5837
+ if (includeClientScope) {
5838
+ query = applyClientScopeFilter(query, idClient, isSuperAdmin);
5839
+ }
5840
+ return applyCustomerScopeFilter(query, collection, idCustomer, isSuperAdmin);
5841
+ }
5842
+ function fetchAssistantProbeDocs(params) {
5843
+ var db = params.db, collection = params.collection, idClient = params.idClient, idCustomer = params.idCustomer, isSuperAdmin = params.isSuperAdmin, includeClientScope = params.includeClientScope;
5844
+ var probeQuery = buildAssistantProbeQuery(collection, idClient, idCustomer, isSuperAdmin, includeClientScope);
5845
+ return db.collection(collection)
5846
+ .find(probeQuery, {
5847
+ limit: AI_ASSISTANT_PROBE_LIMIT,
5848
+ readPreference: AI_ASSISTANT_READ_PREFERENCE
5849
+ })
5850
+ .toArray();
5851
+ }
4278
5852
  function userHasViewPermission(user, view) {
4279
5853
  var _a, _b, _c;
4280
5854
  if (!user || !view) {
@@ -4436,8 +6010,8 @@ function applyCodexStreamStatusHandler(runOptions, streamStatusHandler) {
4436
6010
  }
4437
6011
  function waitForCodexWorkerMessage(worker, streamStatusHandler) {
4438
6012
  return __awaiter(this, void 0, void 0, function () {
4439
- var _a, _b, _c, _d, message, payload, status_1, e_10_1;
4440
- var _e, e_10, _f, _g;
6013
+ var _a, _b, _c, _d, message, payload, status_1, e_13_1;
6014
+ var _e, e_13, _f, _g;
4441
6015
  return __generator(this, function (_h) {
4442
6016
  switch (_h.label) {
4443
6017
  case 0:
@@ -4464,8 +6038,8 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
4464
6038
  return [3 /*break*/, 1];
4465
6039
  case 4: return [3 /*break*/, 11];
4466
6040
  case 5:
4467
- e_10_1 = _h.sent();
4468
- e_10 = { error: e_10_1 };
6041
+ e_13_1 = _h.sent();
6042
+ e_13 = { error: e_13_1 };
4469
6043
  return [3 /*break*/, 11];
4470
6044
  case 6:
4471
6045
  _h.trys.push([6, , 9, 10]);
@@ -4476,7 +6050,7 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
4476
6050
  _h.label = 8;
4477
6051
  case 8: return [3 /*break*/, 10];
4478
6052
  case 9:
4479
- if (e_10) throw e_10.error;
6053
+ if (e_13) throw e_13.error;
4480
6054
  return [7 /*endfinally*/];
4481
6055
  case 10: return [7 /*endfinally*/];
4482
6056
  case 11: throw new CodexWorkerBootstrapError('Codex worker exited before completing.');
@@ -4864,7 +6438,7 @@ function normalizeRouteMatchKey(value) {
4864
6438
  return normalizeRouteKey(value).toLowerCase();
4865
6439
  }
4866
6440
  function buildClientRouteIndex() {
4867
- var e_11, _a;
6441
+ var e_14, _a;
4868
6442
  var _b;
4869
6443
  var routes = ((_b = resolveio_server_app_1.ResolveIOServer.getClientRoutes) === null || _b === void 0 ? void 0 : _b.call(resolveio_server_app_1.ResolveIOServer)) || [];
4870
6444
  var set = new Set();
@@ -4883,12 +6457,12 @@ function buildClientRouteIndex() {
4883
6457
  }
4884
6458
  }
4885
6459
  }
4886
- catch (e_11_1) { e_11 = { error: e_11_1 }; }
6460
+ catch (e_14_1) { e_14 = { error: e_14_1 }; }
4887
6461
  finally {
4888
6462
  try {
4889
6463
  if (routes_1_1 && !routes_1_1.done && (_a = routes_1.return)) _a.call(routes_1);
4890
6464
  }
4891
- finally { if (e_11) throw e_11.error; }
6465
+ finally { if (e_14) throw e_14.error; }
4892
6466
  }
4893
6467
  return { set: set, map: map, size: routes.length };
4894
6468
  }
@@ -4978,6 +6552,20 @@ function sanitizeAssistantResponse(value) {
4978
6552
  }
4979
6553
  return /^i\s+(can|will|['’]ll|am going to|['’]m going to)\s+(pull|run|query|get|fetch|look up|retrieve|grab)\b/i.test(normalized);
4980
6554
  };
6555
+ var isInternalPlanLine = function (line) {
6556
+ var trimmed = line.trim();
6557
+ if (!trimmed || trimmed.length > 120) {
6558
+ return false;
6559
+ }
6560
+ var normalized = trimmed.toLowerCase();
6561
+ var hasPhrase = /schema[-\s]?probe|query rewrite|id[-\s]?lookup|collection override|probe read|tiny probe|fallback plan/i.test(normalized);
6562
+ if (!hasPhrase) {
6563
+ return false;
6564
+ }
6565
+ var isBulletish = /^[-*•]+\s+/.test(trimmed);
6566
+ var isPlanish = /^(plan|planning|approach|strategy|steps?|todo|checklist)\b/i.test(trimmed);
6567
+ return isBulletish || isPlanish;
6568
+ };
4981
6569
  var cleanedLines = [];
4982
6570
  withoutBlocks.split('\n').forEach(function (line) {
4983
6571
  var trimmed = line.trim();
@@ -4988,6 +6576,9 @@ function sanitizeAssistantResponse(value) {
4988
6576
  if (isTentativeQueryLine(line)) {
4989
6577
  return;
4990
6578
  }
6579
+ if (isInternalPlanLine(line)) {
6580
+ return;
6581
+ }
4991
6582
  if (/^work ticket summary:/i.test(trimmed)) {
4992
6583
  return;
4993
6584
  }
@@ -5014,7 +6605,7 @@ function sanitizeAssistantResponse(value) {
5014
6605
  return normalizeAssistantRoutes(normalizedCurrency);
5015
6606
  }
5016
6607
  function evaluateAssistantGuardrails(message) {
5017
- var e_12, _a;
6608
+ var e_15, _a;
5018
6609
  var normalized = String(message || '').toLowerCase();
5019
6610
  var patterns = [
5020
6611
  {
@@ -5060,12 +6651,12 @@ function evaluateAssistantGuardrails(message) {
5060
6651
  }
5061
6652
  }
5062
6653
  }
5063
- catch (e_12_1) { e_12 = { error: e_12_1 }; }
6654
+ catch (e_15_1) { e_15 = { error: e_15_1 }; }
5064
6655
  finally {
5065
6656
  try {
5066
6657
  if (patterns_1_1 && !patterns_1_1.done && (_a = patterns_1.return)) _a.call(patterns_1);
5067
6658
  }
5068
- finally { if (e_12) throw e_12.error; }
6659
+ finally { if (e_15) throw e_15.error; }
5069
6660
  }
5070
6661
  return null;
5071
6662
  }
@@ -5180,7 +6771,7 @@ function tokenizeArithmeticExpression(expression) {
5180
6771
  return tokens;
5181
6772
  }
5182
6773
  function evaluateArithmeticExpression(expression) {
5183
- var e_13, _a, e_14, _b;
6774
+ var e_16, _a, e_17, _b;
5184
6775
  var tokens = tokenizeArithmeticExpression(expression);
5185
6776
  if (!tokens || !tokens.length) {
5186
6777
  return null;
@@ -5237,12 +6828,12 @@ function evaluateArithmeticExpression(expression) {
5237
6828
  prevToken = token;
5238
6829
  }
5239
6830
  }
5240
- catch (e_13_1) { e_13 = { error: e_13_1 }; }
6831
+ catch (e_16_1) { e_16 = { error: e_16_1 }; }
5241
6832
  finally {
5242
6833
  try {
5243
6834
  if (tokens_1_1 && !tokens_1_1.done && (_a = tokens_1.return)) _a.call(tokens_1);
5244
6835
  }
5245
- finally { if (e_13) throw e_13.error; }
6836
+ finally { if (e_16) throw e_16.error; }
5246
6837
  }
5247
6838
  while (ops.length) {
5248
6839
  var op = ops.pop();
@@ -5282,12 +6873,12 @@ function evaluateArithmeticExpression(expression) {
5282
6873
  stack.push(Number(token));
5283
6874
  }
5284
6875
  }
5285
- catch (e_14_1) { e_14 = { error: e_14_1 }; }
6876
+ catch (e_17_1) { e_17 = { error: e_17_1 }; }
5286
6877
  finally {
5287
6878
  try {
5288
6879
  if (output_1_1 && !output_1_1.done && (_b = output_1.return)) _b.call(output_1);
5289
6880
  }
5290
- finally { if (e_14) throw e_14.error; }
6881
+ finally { if (e_17) throw e_17.error; }
5291
6882
  }
5292
6883
  if (stack.length !== 1 || Number.isNaN(stack[0])) {
5293
6884
  return null;
@@ -5471,8 +7062,8 @@ function handleCodexUpload(id_conversation, file_name, content_base64, size, con
5471
7062
  }
5472
7063
  function readAttachmentContents(attachments) {
5473
7064
  return __awaiter(this, void 0, void 0, function () {
5474
- var limits, totalBytes, totalChars, chunks, cleaned, attachments_1, attachments_1_1, attachment, localPath, safe, stat, ext, name_1, type, readable, content, _a, e_15_1;
5475
- var e_15, _b;
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;
5476
7067
  return __generator(this, function (_c) {
5477
7068
  switch (_c.label) {
5478
7069
  case 0:
@@ -5551,14 +7142,14 @@ function readAttachmentContents(attachments) {
5551
7142
  return [3 /*break*/, 2];
5552
7143
  case 10: return [3 /*break*/, 13];
5553
7144
  case 11:
5554
- e_15_1 = _c.sent();
5555
- e_15 = { error: e_15_1 };
7145
+ e_18_1 = _c.sent();
7146
+ e_18 = { error: e_18_1 };
5556
7147
  return [3 /*break*/, 13];
5557
7148
  case 12:
5558
7149
  try {
5559
7150
  if (attachments_1_1 && !attachments_1_1.done && (_b = attachments_1.return)) _b.call(attachments_1);
5560
7151
  }
5561
- finally { if (e_15) throw e_15.error; }
7152
+ finally { if (e_18) throw e_18.error; }
5562
7153
  return [7 /*endfinally*/];
5563
7154
  case 13: return [2 /*return*/, {
5564
7155
  promptText: chunks.length ? "\n\nAttachments:\n".concat(chunks.join('\n\n')) : '',
@@ -5735,7 +7326,7 @@ function estimateUsage(messages, responseText, model) {
5735
7326
  };
5736
7327
  }
5737
7328
  function evaluateGuardrails(message) {
5738
- var e_16, _a;
7329
+ var e_19, _a;
5739
7330
  var normalized = String(message || '').toLowerCase();
5740
7331
  var patterns = [
5741
7332
  { 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.' },
@@ -5757,12 +7348,12 @@ function evaluateGuardrails(message) {
5757
7348
  }
5758
7349
  }
5759
7350
  }
5760
- catch (e_16_1) { e_16 = { error: e_16_1 }; }
7351
+ catch (e_19_1) { e_19 = { error: e_19_1 }; }
5761
7352
  finally {
5762
7353
  try {
5763
7354
  if (patterns_2_1 && !patterns_2_1.done && (_a = patterns_2.return)) _a.call(patterns_2);
5764
7355
  }
5765
- finally { if (e_16) throw e_16.error; }
7356
+ finally { if (e_19) throw e_19.error; }
5766
7357
  }
5767
7358
  return null;
5768
7359
  }