@resolveio/server-lib 20.15.7 → 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,12 @@ 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;
158
+ var AI_ASSISTANT_NAME_MATCH_FALLBACK_MAX_FIELDS = 12;
148
159
  var AI_ASSISTANT_PROGRESS_TICKS = [
149
160
  'Grabbing Data',
150
161
  'Drafting response'
@@ -175,6 +186,15 @@ var AI_ASSISTANT_DATE_FALLBACKS = {
175
186
  date_invoice: 'date_invoiced',
176
187
  date_invoiced: 'date_invoice'
177
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
+ ];
178
198
  var AI_ASSISTANT_BLOCKED_COLLECTIONS = new Set([
179
199
  'user-groups',
180
200
  'logged-in-users',
@@ -201,6 +221,7 @@ var AI_ASSISTANT_SENSITIVE_FIELDS = [
201
221
  'roles'
202
222
  ];
203
223
  var AI_ASSISTANT_CLIENT_SCOPE_CACHE = new Map();
224
+ var AI_ASSISTANT_FIELD_INDEX_CACHE = new Map();
204
225
  var AI_ASSISTANT_COLLECTION_CACHE = new Map();
205
226
  var AI_ASSISTANT_COLLECTION_CACHE_TTL_MS = 5 * 60 * 1000;
206
227
  var AI_ASSISTANT_COLLECTION_STOPWORDS = new Set([
@@ -246,11 +267,72 @@ var AI_ASSISTANT_COLLECTION_STOPWORDS = new Set([
246
267
  'missing',
247
268
  'overdue'
248
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
+ };
249
326
  var AI_ASSISTANT_TERM_SYNONYMS = [
250
327
  {
251
328
  label: 'truck treating jobs',
252
329
  pattern: /\btruck\s+treating\s+jobs?\b/i,
253
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']
254
336
  }
255
337
  ];
256
338
  var AI_ASSISTANT_SYSTEM_PROMPT = [
@@ -277,6 +359,7 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
277
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.',
278
360
  '- Assume a relevant collection exists; if verification reads return zero data, report no data found instead of interrogating the user.',
279
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.',
280
363
  '- For direct questions, answer first. Ask a single follow-up only if required to proceed.',
281
364
  'Data Presentation:',
282
365
  '- Output plain Markdown (NO triple backticks).',
@@ -1048,10 +1131,10 @@ function executeAiAssistantCodexRun(payload, context) {
1048
1131
  insertResult = _d.sent();
1049
1132
  assistantMessageId = (insertResult === null || insertResult === void 0 ? void 0 : insertResult._id) || (insertResult === null || insertResult === void 0 ? void 0 : insertResult.insertedId);
1050
1133
  enqueueAssistantCodexRun(function () { return __awaiter(_this, void 0, void 0, function () {
1051
- var runStart, steps, recordStep, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, dataQuestion, lastDirective, toolResponseDebug, toolError, termHints, collectionHints, contextRoute, contextMode, hintSeed, termExpansion, hintText, dbName, db, _a, assistantContext, prompt_1, workspaceRoot, codexConfig, runOptions, responseText, directiveText, directive, directivePrompt, forcedDirective, _b, directivePrompt, forcedDirective, _c, cleanedResponseText, toolRequest, toolResponse, _d, toolPayload, followupPrompt, followupText, _e, error_2, error_3, finalNow, finishedAt, finalMetadata, finalAssistantDoc;
1052
- var _f, _g, _h, _j, _k, _l, _m, _o;
1053
- return __generator(this, function (_p) {
1054
- switch (_p.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) {
1055
1138
  case 0:
1056
1139
  runStart = Date.now();
1057
1140
  steps = [];
@@ -1075,31 +1158,60 @@ function executeAiAssistantCodexRun(payload, context) {
1075
1158
  toolError = null;
1076
1159
  termHints = [];
1077
1160
  collectionHints = [];
1161
+ collectionTokenization = null;
1162
+ collectionRanking = null;
1163
+ collectionSelection = null;
1164
+ collectionOverride = null;
1165
+ timingBreakdown = {
1166
+ directiveMs: 0,
1167
+ initialResponseMs: 0,
1168
+ forcedDirectiveMs: 0,
1169
+ toolMs: 0,
1170
+ followupMs: 0
1171
+ };
1078
1172
  contextRoute = normalizeOptionalString((_f = input === null || input === void 0 ? void 0 : input.context) === null || _f === void 0 ? void 0 : _f.route);
1079
1173
  contextMode = normalizeOptionalString((_g = input === null || input === void 0 ? void 0 : input.context) === null || _g === void 0 ? void 0 : _g.mode);
1080
1174
  recordStep('Queued', { requestId: requestId || undefined });
1081
- _p.label = 1;
1175
+ _t.label = 1;
1082
1176
  case 1:
1083
- _p.trys.push([1, 30, 31, 32]);
1177
+ _t.trys.push([1, 30, 31, 32]);
1084
1178
  hintSeed = [message, contextRoute].filter(Boolean).join(' ');
1085
1179
  termExpansion = expandAssistantTermSynonyms(hintSeed);
1086
1180
  hintText = termExpansion.expanded || hintSeed;
1087
1181
  termHints = termExpansion.matches.map(function (match) { return "".concat(match.term, " -> ").concat(match.expansions.join(', ')); });
1182
+ baseTokens = tokenizeCollectionText(hintSeed);
1183
+ expandedTokens = tokenizeCollectionText(hintText);
1184
+ baseWeights = computeCollectionTokenWeights(baseTokens);
1185
+ expandedWeights = computeCollectionTokenWeights(expandedTokens);
1186
+ collectionTokenization = {
1187
+ baseText: hintSeed || undefined,
1188
+ expandedText: hintText || undefined,
1189
+ baseTokens: baseTokens.length ? baseTokens : 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
1194
+ };
1088
1195
  recordStep('Planning: term expansion', {
1089
1196
  termMatches: termExpansion.matches.length ? termExpansion.matches : undefined
1090
1197
  });
1091
- _p.label = 2;
1198
+ _t.label = 2;
1092
1199
  case 2:
1093
- _p.trys.push([2, 4, , 5]);
1200
+ _t.trys.push([2, 4, , 5]);
1094
1201
  dbName = resolveAssistantDatabaseName(undefined, input.mongo);
1095
1202
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1096
- return [4 /*yield*/, resolveAssistantCollectionHints(hintText, dbName, db)];
1203
+ return [4 /*yield*/, listAssistantCollections(db, dbName)];
1097
1204
  case 3:
1098
- collectionHints = _p.sent();
1205
+ collectionNames = _t.sent();
1206
+ collectionHints = resolveCollectionHintsFromTokens(expandedTokens, collectionNames, 5);
1207
+ collectionRanking = buildCollectionRankingDebugFromTokens(expandedTokens, collectionNames, 8);
1099
1208
  return [3 /*break*/, 5];
1100
1209
  case 4:
1101
- _a = _p.sent();
1210
+ _a = _t.sent();
1102
1211
  collectionHints = [];
1212
+ collectionRanking = collectionRanking || ((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens)
1213
+ ? buildCollectionRankingDebugFromTokens(collectionTokenization.expandedTokens || [], [], 0)
1214
+ : null);
1103
1215
  return [3 /*break*/, 5];
1104
1216
  case 5:
1105
1217
  recordStep('Planning: collection hints', {
@@ -1118,7 +1230,7 @@ function executeAiAssistantCodexRun(payload, context) {
1118
1230
  prompt_1 = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1119
1231
  return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
1120
1232
  case 6:
1121
- workspaceRoot = _p.sent();
1233
+ workspaceRoot = _t.sent();
1122
1234
  codexConfig = resolveCodexSettings();
1123
1235
  runOptions = {
1124
1236
  timeoutMs: resolveCodexTimeoutMs(),
@@ -1139,103 +1251,128 @@ function executeAiAssistantCodexRun(payload, context) {
1139
1251
  if (!dataQuestion) return [3 /*break*/, 10];
1140
1252
  recordStep('Directive: determine tool', { type: 'data-question' });
1141
1253
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1142
- _p.label = 7;
1254
+ _t.label = 7;
1143
1255
  case 7:
1144
- _p.trys.push([7, 9, , 10]);
1256
+ _t.trys.push([7, 9, , 10]);
1257
+ directiveStart = Date.now();
1145
1258
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1146
1259
  case 8:
1147
- directiveText = _p.sent();
1260
+ directiveText = _t.sent();
1261
+ timingBreakdown.directiveMs = Date.now() - directiveStart;
1148
1262
  forcedDirective = extractAssistantMongoDirective(directiveText);
1149
1263
  if (forcedDirective) {
1150
1264
  directive = forcedDirective;
1151
1265
  directiveSource = 'model';
1152
1266
  lastDirective = forcedDirective;
1267
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_h = directive.payload) === null || _h === void 0 ? void 0 : _h.collection) || '');
1153
1268
  recordStep('Directive resolved', {
1154
1269
  source: directiveSource,
1155
1270
  type: directive.type,
1156
- collection: normalizeOptionalString((_h = directive.payload) === null || _h === void 0 ? void 0 : _h.collection) || undefined,
1157
- permissionView: normalizeOptionalString((_j = directive.payload) === null || _j === void 0 ? void 0 : _j.permissionView) || undefined
1271
+ collection: normalizeOptionalString((_j = directive.payload) === null || _j === void 0 ? void 0 : _j.collection) || undefined,
1272
+ permissionView: normalizeOptionalString((_k = directive.payload) === null || _k === void 0 ? void 0 : _k.permissionView) || undefined
1158
1273
  });
1159
1274
  }
1160
1275
  return [3 /*break*/, 10];
1161
1276
  case 9:
1162
- _b = _p.sent();
1277
+ _b = _t.sent();
1163
1278
  return [3 /*break*/, 10];
1164
1279
  case 10:
1165
1280
  if (!!directive) return [3 /*break*/, 12];
1166
1281
  recordStep('Response: draft initial answer', { mode: 'full' });
1282
+ initialStart = Date.now();
1167
1283
  return [4 /*yield*/, runCodexInWorkerThread(prompt_1, runOptions, codexConfig, streamProgress)];
1168
1284
  case 11:
1169
- responseText = _p.sent();
1285
+ responseText = _t.sent();
1286
+ timingBreakdown.initialResponseMs = Date.now() - initialStart;
1170
1287
  directive = extractAssistantMongoDirective(responseText);
1171
1288
  if (directive) {
1172
1289
  directiveSource = 'model';
1173
1290
  lastDirective = directive;
1291
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_l = directive.payload) === null || _l === void 0 ? void 0 : _l.collection) || '');
1174
1292
  recordStep('Directive resolved', {
1175
1293
  source: directiveSource,
1176
1294
  type: directive.type,
1177
- collection: normalizeOptionalString((_k = directive.payload) === null || _k === void 0 ? void 0 : _k.collection) || undefined,
1178
- permissionView: normalizeOptionalString((_l = directive.payload) === null || _l === void 0 ? void 0 : _l.permissionView) || undefined
1295
+ collection: normalizeOptionalString((_m = directive.payload) === null || _m === void 0 ? void 0 : _m.collection) || undefined,
1296
+ permissionView: normalizeOptionalString((_o = directive.payload) === null || _o === void 0 ? void 0 : _o.permissionView) || undefined
1179
1297
  });
1180
1298
  }
1181
- _p.label = 12;
1299
+ _t.label = 12;
1182
1300
  case 12:
1183
1301
  if (!(!directive && dataQuestion)) return [3 /*break*/, 16];
1184
1302
  recordStep('Directive: forced retry', { mode: 'directive-only' });
1185
1303
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1186
- _p.label = 13;
1304
+ _t.label = 13;
1187
1305
  case 13:
1188
- _p.trys.push([13, 15, , 16]);
1306
+ _t.trys.push([13, 15, , 16]);
1307
+ forcedStart = Date.now();
1189
1308
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1190
1309
  case 14:
1191
- directiveText = _p.sent();
1310
+ directiveText = _t.sent();
1311
+ timingBreakdown.forcedDirectiveMs = Date.now() - forcedStart;
1192
1312
  forcedDirective = extractAssistantMongoDirective(directiveText);
1193
1313
  if (forcedDirective) {
1194
1314
  directive = forcedDirective;
1195
1315
  directiveSource = 'forced';
1196
1316
  lastDirective = forcedDirective;
1317
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_p = directive.payload) === null || _p === void 0 ? void 0 : _p.collection) || '');
1197
1318
  recordStep('Directive resolved', {
1198
1319
  source: directiveSource,
1199
1320
  type: directive.type,
1200
- collection: normalizeOptionalString((_m = directive.payload) === null || _m === void 0 ? void 0 : _m.collection) || undefined,
1201
- permissionView: normalizeOptionalString((_o = directive.payload) === null || _o === void 0 ? void 0 : _o.permissionView) || undefined
1321
+ collection: normalizeOptionalString((_q = directive.payload) === null || _q === void 0 ? void 0 : _q.collection) || undefined,
1322
+ permissionView: normalizeOptionalString((_r = directive.payload) === null || _r === void 0 ? void 0 : _r.permissionView) || undefined
1202
1323
  });
1203
1324
  }
1204
1325
  return [3 /*break*/, 16];
1205
1326
  case 15:
1206
- _c = _p.sent();
1327
+ _c = _t.sent();
1207
1328
  return [3 /*break*/, 16];
1208
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
+ }
1209
1342
  cleanedResponseText = (directive === null || directive === void 0 ? void 0 : directive.cleaned) || responseText;
1210
1343
  if (cleanedResponseText) {
1211
1344
  assistantContent = sanitizeAssistantResponse(cleanedResponseText);
1212
1345
  }
1213
1346
  if (!((directive === null || directive === void 0 ? void 0 : directive.payload) && AI_ASSISTANT_TOOL_MAX_STEPS > 0)) return [3 /*break*/, 28];
1214
- 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);
1215
1350
  progressTracker.push('Grabbing Data');
1216
1351
  recordStep('Grabbing Data: start', {
1217
- type: directive.type,
1352
+ type: effectiveDirective.type,
1218
1353
  collection: normalizeOptionalString(toolRequest === null || toolRequest === void 0 ? void 0 : toolRequest.collection) || undefined,
1219
1354
  permissionView: normalizeOptionalString(toolRequest === null || toolRequest === void 0 ? void 0 : toolRequest.permissionView) || undefined
1220
1355
  });
1221
- _p.label = 17;
1356
+ _t.label = 17;
1222
1357
  case 17:
1223
- _p.trys.push([17, 26, , 27]);
1224
- if (!(directive.type === 'aggregate')) return [3 /*break*/, 19];
1358
+ _t.trys.push([17, 26, , 27]);
1359
+ toolStart = Date.now();
1360
+ if (!(effectiveDirective.type === 'aggregate')) return [3 /*break*/, 19];
1225
1361
  return [4 /*yield*/, executeAiAssistantMongoAggregate(toolRequest, context)];
1226
1362
  case 18:
1227
- _d = _p.sent();
1363
+ _d = _t.sent();
1228
1364
  return [3 /*break*/, 21];
1229
1365
  case 19: return [4 /*yield*/, executeAiAssistantMongoRead(toolRequest, context)];
1230
1366
  case 20:
1231
- _d = _p.sent();
1232
- _p.label = 21;
1367
+ _d = _t.sent();
1368
+ _t.label = 21;
1233
1369
  case 21:
1234
1370
  toolResponse = _d;
1371
+ timingBreakdown.toolMs = Date.now() - toolStart;
1235
1372
  toolResponseDebug = (toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.debug) && typeof toolResponse.debug === 'object'
1236
1373
  ? toolResponse.debug
1237
1374
  : null;
1238
- toolPayload = buildAssistantToolResultPayload(directive, toolResponse);
1375
+ toolPayload = buildAssistantToolResultPayload(effectiveDirective, toolResponse);
1239
1376
  toolResult = toolPayload.result;
1240
1377
  recordStep('Grabbing Data: complete', {
1241
1378
  rowCount: toolPayload.result.output.rowCount,
@@ -1245,21 +1382,23 @@ function executeAiAssistantCodexRun(payload, context) {
1245
1382
  progressTracker.push('Drafting response');
1246
1383
  recordStep('Drafting response');
1247
1384
  followupPrompt = buildAssistantCodexToolFollowupPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, toolPayload.prompt);
1248
- _p.label = 22;
1385
+ _t.label = 22;
1249
1386
  case 22:
1250
- _p.trys.push([22, 24, , 25]);
1387
+ _t.trys.push([22, 24, , 25]);
1388
+ followupStart = Date.now();
1251
1389
  return [4 /*yield*/, runCodexInWorkerThread(followupPrompt, runOptions, codexConfig, streamProgress)];
1252
1390
  case 23:
1253
- followupText = _p.sent();
1391
+ followupText = _t.sent();
1392
+ timingBreakdown.followupMs = Date.now() - followupStart;
1254
1393
  assistantContent = sanitizeAssistantResponse(followupText);
1255
1394
  return [3 /*break*/, 25];
1256
1395
  case 24:
1257
- _e = _p.sent();
1396
+ _e = _t.sent();
1258
1397
  assistantContent = buildAssistantToolFallbackResponse(toolPayload.result);
1259
1398
  return [3 /*break*/, 25];
1260
1399
  case 25: return [3 /*break*/, 27];
1261
1400
  case 26:
1262
- error_2 = _p.sent();
1401
+ error_2 = _t.sent();
1263
1402
  assistantContent = buildAssistantToolErrorMessage(error_2, directive, toolRequest);
1264
1403
  toolError = error_2;
1265
1404
  return [3 /*break*/, 27];
@@ -1267,10 +1406,10 @@ function executeAiAssistantCodexRun(payload, context) {
1267
1406
  case 28:
1268
1407
  progressTracker.push('Drafting response');
1269
1408
  recordStep('Drafting response');
1270
- _p.label = 29;
1409
+ _t.label = 29;
1271
1410
  case 29: return [3 /*break*/, 32];
1272
1411
  case 30:
1273
- error_3 = _p.sent();
1412
+ error_3 = _t.sent();
1274
1413
  assistantContent = buildAssistantCodexErrorMessage(error_3);
1275
1414
  recordStep('Error', { message: normalizeOptionalString(error_3 === null || error_3 === void 0 ? void 0 : error_3.message) || 'Unknown error' });
1276
1415
  return [3 /*break*/, 32];
@@ -1284,6 +1423,11 @@ function executeAiAssistantCodexRun(payload, context) {
1284
1423
  finalNow = new Date();
1285
1424
  if (isSuperAdmin) {
1286
1425
  finishedAt = Date.now();
1426
+ codexMs = timingBreakdown.directiveMs
1427
+ + timingBreakdown.initialResponseMs
1428
+ + timingBreakdown.forcedDirectiveMs
1429
+ + timingBreakdown.followupMs;
1430
+ draftingMs = timingBreakdown.followupMs || timingBreakdown.initialResponseMs;
1287
1431
  assistantDebug = buildAssistantDebugPayload({
1288
1432
  dataQuestion: dataQuestion,
1289
1433
  directive: lastDirective,
@@ -1291,18 +1435,30 @@ function executeAiAssistantCodexRun(payload, context) {
1291
1435
  toolResult: toolResult,
1292
1436
  toolResponseDebug: toolResponseDebug,
1293
1437
  toolError: toolError,
1438
+ collectionOverride: collectionOverride,
1294
1439
  trace: {
1295
1440
  steps: steps,
1296
1441
  planning: {
1297
1442
  contextMode: contextMode || undefined,
1298
1443
  contextRoute: contextRoute || undefined,
1299
1444
  termHints: termHints.length ? termHints : undefined,
1300
- collectionHints: collectionHints.length ? collectionHints : undefined
1445
+ collectionHints: collectionHints.length ? collectionHints : undefined,
1446
+ collectionTokenization: collectionTokenization || undefined,
1447
+ collectionRanking: collectionRanking || undefined,
1448
+ collectionSelection: collectionSelection || undefined,
1449
+ collectionOverride: collectionOverride || undefined
1301
1450
  },
1302
1451
  timings: {
1303
1452
  startedAt: new Date(runStart).toISOString(),
1304
1453
  finishedAt: new Date(finishedAt).toISOString(),
1305
- totalMs: finishedAt - runStart
1454
+ totalMs: finishedAt - runStart,
1455
+ codexMs: codexMs,
1456
+ draftingMs: draftingMs,
1457
+ toolMs: timingBreakdown.toolMs,
1458
+ directiveMs: timingBreakdown.directiveMs,
1459
+ initialResponseMs: timingBreakdown.initialResponseMs,
1460
+ forcedDirectiveMs: timingBreakdown.forcedDirectiveMs,
1461
+ followupMs: timingBreakdown.followupMs
1306
1462
  }
1307
1463
  }
1308
1464
  });
@@ -1318,16 +1474,16 @@ function executeAiAssistantCodexRun(payload, context) {
1318
1474
  }
1319
1475
  })];
1320
1476
  case 33:
1321
- _p.sent();
1322
- _p.label = 34;
1477
+ _t.sent();
1478
+ _t.label = 34;
1323
1479
  case 34: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
1324
1480
  case 35:
1325
- _p.sent();
1481
+ _t.sent();
1326
1482
  if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 37];
1327
1483
  return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
1328
1484
  case 36:
1329
- _p.sent();
1330
- _p.label = 37;
1485
+ _t.sent();
1486
+ _t.label = 37;
1331
1487
  case 37: return [2 /*return*/, finalAssistantDoc];
1332
1488
  }
1333
1489
  });
@@ -1341,10 +1497,10 @@ function executeAiAssistantCodexRun(payload, context) {
1341
1497
  }
1342
1498
  function executeAiAssistantMongoRead(payload, context) {
1343
1499
  return __awaiter(this, void 0, void 0, function () {
1344
- 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, total, sanitizedDocuments, includeIds, requestedFields, fieldAliases, displayDocs, priorityFields, display;
1345
- var _c, _d;
1346
- return __generator(this, function (_e) {
1347
- 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) {
1348
1504
  case 0:
1349
1505
  input = payload || {};
1350
1506
  rawCollection = normalizeOptionalString(input.collection);
@@ -1355,16 +1511,26 @@ function executeAiAssistantMongoRead(payload, context) {
1355
1511
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1356
1512
  return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
1357
1513
  case 1:
1358
- collectionResolution = _e.sent();
1514
+ collectionResolution = _h.sent();
1359
1515
  collection = collectionResolution.name || rawCollection;
1360
1516
  return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
1361
1517
  case 2:
1362
- _a = _e.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1518
+ _a = _h.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1363
1519
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
1364
1520
  throw new Error('AI assistant mongo read: Access denied.');
1365
1521
  }
1366
- 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 = {};
1367
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
+ }
1368
1534
  if (!isSuperAdmin && (collection === 'users' || collection === 'user-versions')) {
1369
1535
  userId = normalizeOptionalString(user === null || user === void 0 ? void 0 : user._id);
1370
1536
  if (!userId) {
@@ -1378,13 +1544,22 @@ function executeAiAssistantMongoRead(payload, context) {
1378
1544
  if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 4];
1379
1545
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
1380
1546
  case 3:
1381
- _b = _e.sent();
1547
+ _b = _h.sent();
1382
1548
  return [3 /*break*/, 5];
1383
1549
  case 4:
1384
1550
  _b = false;
1385
- _e.label = 5;
1551
+ _h.label = 5;
1386
1552
  case 5:
1387
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
+ }
1388
1563
  clientScopedQuery = shouldScopeByClient
1389
1564
  ? applyClientScopeFilter(baseQuery, normalizedClient, isSuperAdmin)
1390
1565
  : baseQuery;
@@ -1393,9 +1568,9 @@ function executeAiAssistantMongoRead(payload, context) {
1393
1568
  findOptions = __assign(__assign({}, normalized.findOptions), { readPreference: AI_ASSISTANT_READ_PREFERENCE });
1394
1569
  return [4 /*yield*/, db.collection(collection).find(scopedQuery, findOptions).toArray()];
1395
1570
  case 6:
1396
- documents = _e.sent();
1571
+ documents = _h.sent();
1397
1572
  executedQuery = scopedQuery;
1398
- fallbackMeta = {};
1573
+ probeDocs = null;
1399
1574
  if (!!documents.length) return [3 /*break*/, 8];
1400
1575
  dateFallback = resolveQueryDateFieldFallback(scopedQuery);
1401
1576
  if (!dateFallback) return [3 /*break*/, 8];
@@ -1403,26 +1578,185 @@ function executeAiAssistantMongoRead(payload, context) {
1403
1578
  fallbackMeta.dateField = __assign(__assign({}, dateFallback), { attempted: true, used: false });
1404
1579
  return [4 /*yield*/, db.collection(collection).find(fallbackQuery, findOptions).toArray()];
1405
1580
  case 7:
1406
- fallbackDocs = _e.sent();
1581
+ fallbackDocs = _h.sent();
1407
1582
  if (fallbackDocs.length) {
1408
1583
  documents = fallbackDocs;
1409
1584
  executedQuery = fallbackQuery;
1410
1585
  fallbackMeta.dateField.used = true;
1411
1586
  }
1412
- _e.label = 8;
1587
+ _h.label = 8;
1413
1588
  case 8:
1414
- total = null;
1415
- if (!normalized.includeTotal) return [3 /*break*/, 10];
1416
- return [4 /*yield*/, db.collection(collection).countDocuments(executedQuery, { readPreference: AI_ASSISTANT_READ_PREFERENCE })];
1589
+ if (!!documents.length) return [3 /*break*/, 10];
1590
+ expanded = expandQueryDateFallbacks(executedQuery);
1591
+ if (!expanded) return [3 /*break*/, 10];
1592
+ fallbackMeta.dateFieldsExpanded = {
1593
+ fields: expanded.fields,
1594
+ attempted: true,
1595
+ used: false
1596
+ };
1597
+ return [4 /*yield*/, db.collection(collection).find(expanded.query, findOptions).toArray()];
1417
1598
  case 9:
1418
- total = _e.sent();
1419
- _e.label = 10;
1599
+ fallbackDocs = _h.sent();
1600
+ if (fallbackDocs.length) {
1601
+ documents = fallbackDocs;
1602
+ executedQuery = expanded.query;
1603
+ fallbackMeta.dateFieldsExpanded.used = true;
1604
+ }
1605
+ _h.label = 10;
1420
1606
  case 10:
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()];
1617
+ case 11:
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;
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:
1421
1713
  sanitizedDocuments = isSuperAdmin
1422
1714
  ? documents
1423
1715
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
1424
- includeIds = ((_d = input.options) === null || _d === void 0 ? void 0 : _d.includeIds) === true;
1425
- 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;
1426
1760
  fieldAliases = resolveFieldAliases(sanitizedDocuments, requestedFields);
1427
1761
  displayDocs = Object.keys(fieldAliases).length
1428
1762
  ? applyFieldAliasesForDisplay(sanitizedDocuments, fieldAliases)
@@ -1433,7 +1767,8 @@ function executeAiAssistantMongoRead(payload, context) {
1433
1767
  includeIds: includeIds,
1434
1768
  maxColumns: AI_ASSISTANT_DISPLAY_MAX_COLUMNS,
1435
1769
  maxRows: normalized.findOptions.limit,
1436
- priorityFields: priorityFields
1770
+ priorityFields: priorityFields,
1771
+ includeGroupFromId: false
1437
1772
  });
1438
1773
  if (total !== null) {
1439
1774
  display.total = total;
@@ -1462,10 +1797,10 @@ function executeAiAssistantMongoRead(payload, context) {
1462
1797
  }
1463
1798
  function executeAiAssistantMongoAggregate(payload, context) {
1464
1799
  return __awaiter(this, void 0, void 0, function () {
1465
- 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, unwindFallback, fallbackPipeline, fallbackDocs, sanitizedDocuments, includeIds, display;
1466
- var _c, _d;
1467
- return __generator(this, function (_e) {
1468
- 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) {
1469
1804
  case 0:
1470
1805
  input = payload || {};
1471
1806
  rawCollection = normalizeOptionalString(input.collection);
@@ -1476,16 +1811,26 @@ function executeAiAssistantMongoAggregate(payload, context) {
1476
1811
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1477
1812
  return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
1478
1813
  case 1:
1479
- collectionResolution = _e.sent();
1814
+ collectionResolution = _f.sent();
1480
1815
  collection = collectionResolution.name || rawCollection;
1481
1816
  return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
1482
1817
  case 2:
1483
- _a = _e.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1818
+ _a = _f.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1484
1819
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
1485
1820
  throw new Error('AI assistant mongo aggregate: Access denied.');
1486
1821
  }
1487
- 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 = {};
1488
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
+ }
1489
1834
  if (!isSuperAdmin && (collection === 'users' || collection === 'user-versions')) {
1490
1835
  userId = normalizeOptionalString(user === null || user === void 0 ? void 0 : user._id);
1491
1836
  if (!userId) {
@@ -1499,11 +1844,11 @@ function executeAiAssistantMongoAggregate(payload, context) {
1499
1844
  if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 4];
1500
1845
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
1501
1846
  case 3:
1502
- _b = _e.sent();
1847
+ _b = _f.sent();
1503
1848
  return [3 /*break*/, 5];
1504
1849
  case 4:
1505
1850
  _b = false;
1506
- _e.label = 5;
1851
+ _f.label = 5;
1507
1852
  case 5:
1508
1853
  shouldScopeByClient = _b;
1509
1854
  clientScopedQuery = shouldScopeByClient
@@ -1511,7 +1856,17 @@ function executeAiAssistantMongoAggregate(payload, context) {
1511
1856
  : baseQuery;
1512
1857
  scopedQuery = applyCustomerScopeFilter(clientScopedQuery, collection, customerId, isSuperAdmin);
1513
1858
  normalizedPipeline = normalizeAssistantAggregatePipeline(input.pipeline);
1514
- 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);
1515
1870
  normalizedOptions = normalizeAssistantAggregateOptions(input.options);
1516
1871
  limitedPipeline = applyAssistantAggregateLimit(pipelineWithScope, normalizedOptions.limit, normalizedOptions.maxLimit, normalizedOptions.defaultLimit);
1517
1872
  dateField = findAggregateDateField(limitedPipeline);
@@ -1523,9 +1878,9 @@ function executeAiAssistantMongoAggregate(payload, context) {
1523
1878
  .aggregate(limitedPipeline, aggregateOptions)
1524
1879
  .toArray()];
1525
1880
  case 6:
1526
- documents = _e.sent();
1881
+ documents = _f.sent();
1527
1882
  executedPipeline = limitedPipeline;
1528
- fallbackMeta = {};
1883
+ probeDocs = null;
1529
1884
  if (!(!documents.length && dateField)) return [3 /*break*/, 10];
1530
1885
  fallback = resolveAggregateDateFieldFallback(limitedPipeline);
1531
1886
  if (!fallback) return [3 /*break*/, 8];
@@ -1536,13 +1891,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
1536
1891
  .aggregate(fallbackPipeline, aggregateOptions)
1537
1892
  .toArray()];
1538
1893
  case 7:
1539
- fallbackDocs = _e.sent();
1894
+ fallbackDocs = _f.sent();
1540
1895
  if (fallbackDocs.length) {
1541
1896
  documents = fallbackDocs;
1542
1897
  executedPipeline = fallbackPipeline;
1543
1898
  fallbackMeta.dateField.used = true;
1544
1899
  }
1545
- _e.label = 8;
1900
+ _f.label = 8;
1546
1901
  case 8:
1547
1902
  if (!(!documents.length && dateField !== 'createdAt')) return [3 /*break*/, 10];
1548
1903
  createdFallback = { from: dateField, to: 'createdAt', attempted: true, used: false };
@@ -1553,64 +1908,258 @@ function executeAiAssistantMongoAggregate(payload, context) {
1553
1908
  .aggregate(createdPipeline, aggregateOptions)
1554
1909
  .toArray()];
1555
1910
  case 9:
1556
- createdDocs = _e.sent();
1911
+ createdDocs = _f.sent();
1557
1912
  if (createdDocs.length) {
1558
1913
  documents = createdDocs;
1559
1914
  executedPipeline = createdPipeline;
1560
1915
  fallbackMeta.dateFieldCreatedAt.used = true;
1561
1916
  }
1562
- _e.label = 10;
1917
+ _f.label = 10;
1563
1918
  case 10:
1564
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];
1565
1941
  completionFallback = resolveAggregateCompletionFallback(executedPipeline);
1566
- if (!completionFallback) return [3 /*break*/, 12];
1942
+ if (!completionFallback) return [3 /*break*/, 14];
1567
1943
  fallbackMeta.completion = {
1568
1944
  field: completionFallback.field,
1569
1945
  sources: completionFallback.sources,
1570
1946
  attempted: true,
1571
1947
  used: false,
1572
- statusFilter: !!completionFallback.statusFilter
1948
+ statusFilter: !!completionFallback.statusFilter,
1949
+ strategy: 'addFields'
1573
1950
  };
1574
1951
  fallbackPipeline = buildAggregateCompletionFallbackPipeline(executedPipeline, completionFallback);
1575
- if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 12];
1952
+ if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 14];
1576
1953
  return [4 /*yield*/, db.collection(collection)
1577
1954
  .aggregate(fallbackPipeline, aggregateOptions)
1578
1955
  .toArray()];
1579
- case 11:
1580
- fallbackDocs = _e.sent();
1956
+ case 13:
1957
+ fallbackDocs = _f.sent();
1581
1958
  if (fallbackDocs.length) {
1582
1959
  documents = fallbackDocs;
1583
1960
  executedPipeline = fallbackPipeline;
1584
1961
  fallbackMeta.completion.used = true;
1585
1962
  }
1586
- _e.label = 12;
1587
- case 12:
1588
- if (!(documents.length <= 1)) return [3 /*break*/, 14];
1963
+ _f.label = 14;
1964
+ case 14:
1965
+ if (!!documents.length) return [3 /*break*/, 16];
1966
+ completionExprFallback = resolveAggregateCompletionExprFallback(executedPipeline);
1967
+ if (!completionExprFallback) return [3 /*break*/, 16];
1968
+ fallbackMeta.completion = {
1969
+ field: completionExprFallback.field,
1970
+ sources: completionExprFallback.sources,
1971
+ attempted: true,
1972
+ used: false,
1973
+ statusFilter: !!completionExprFallback.statusFilter,
1974
+ strategy: 'expr'
1975
+ };
1976
+ fallbackPipeline = buildAggregateCompletionExprFallbackPipeline(executedPipeline, completionExprFallback);
1977
+ if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 16];
1978
+ return [4 /*yield*/, db.collection(collection)
1979
+ .aggregate(fallbackPipeline, aggregateOptions)
1980
+ .toArray()];
1981
+ case 15:
1982
+ fallbackDocs = _f.sent();
1983
+ if (fallbackDocs.length) {
1984
+ documents = fallbackDocs;
1985
+ executedPipeline = fallbackPipeline;
1986
+ fallbackMeta.completion.used = true;
1987
+ }
1988
+ _f.label = 16;
1989
+ case 16:
1990
+ if (!(documents.length <= 1)) return [3 /*break*/, 18];
1589
1991
  unwindFallback = resolveAggregateUnwindFallback(executedPipeline);
1590
- if (!unwindFallback) return [3 /*break*/, 14];
1992
+ if (!unwindFallback) return [3 /*break*/, 18];
1591
1993
  fallbackMeta.unwind = { path: unwindFallback.path, attempted: true, used: false };
1592
1994
  fallbackPipeline = buildAggregateUnwindFallbackPipeline(executedPipeline, unwindFallback);
1593
- if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 14];
1995
+ if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 18];
1594
1996
  return [4 /*yield*/, db.collection(collection)
1595
1997
  .aggregate(fallbackPipeline, aggregateOptions)
1596
1998
  .toArray()];
1597
- case 13:
1598
- fallbackDocs = _e.sent();
1999
+ case 17:
2000
+ fallbackDocs = _f.sent();
1599
2001
  if (fallbackDocs.length > documents.length) {
1600
2002
  documents = fallbackDocs;
1601
2003
  executedPipeline = fallbackPipeline;
1602
2004
  fallbackMeta.unwind.used = true;
1603
2005
  }
1604
- _e.label = 14;
1605
- case 14:
2006
+ _f.label = 18;
2007
+ case 18:
2008
+ if (!!documents.length) return [3 /*break*/, 20];
2009
+ nameFallback = resolveAggregateNameMatchFallback(executedPipeline);
2010
+ if (!nameFallback) return [3 /*break*/, 20];
2011
+ fallbackMeta.nameMatch = {
2012
+ field: nameFallback.field,
2013
+ fields: nameFallback.fields,
2014
+ attempted: true,
2015
+ used: false
2016
+ };
2017
+ fallbackPipeline = buildAggregateNameMatchFallbackPipeline(executedPipeline, nameFallback);
2018
+ if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 20];
2019
+ return [4 /*yield*/, db.collection(collection)
2020
+ .aggregate(fallbackPipeline, aggregateOptions)
2021
+ .toArray()];
2022
+ case 19:
2023
+ fallbackDocs = _f.sent();
2024
+ if (fallbackDocs.length) {
2025
+ documents = fallbackDocs;
2026
+ executedPipeline = fallbackPipeline;
2027
+ fallbackMeta.nameMatch.used = true;
2028
+ }
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:
1606
2154
  sanitizedDocuments = isSuperAdmin
1607
2155
  ? documents
1608
2156
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
1609
- 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;
1610
2158
  display = buildDisplayTable(sanitizedDocuments, {
1611
2159
  includeIds: includeIds,
1612
2160
  maxColumns: AI_ASSISTANT_DISPLAY_MAX_COLUMNS,
1613
- maxRows: normalizedOptions.limit || sanitizedDocuments.length
2161
+ maxRows: normalizedOptions.limit || sanitizedDocuments.length,
2162
+ includeGroupFromId: true
1614
2163
  });
1615
2164
  return [2 /*return*/, __assign({ documents: sanitizedDocuments, display: display }, (isSuperAdmin ? {
1616
2165
  debug: {
@@ -1699,7 +2248,8 @@ function buildAssistantToolResultPayload(directive, toolResponse) {
1699
2248
  : buildDisplayTable(documents, {
1700
2249
  includeIds: includeIds,
1701
2250
  maxColumns: AI_ASSISTANT_DISPLAY_MAX_COLUMNS,
1702
- maxRows: AI_ASSISTANT_DISPLAY_PREVIEW_MAX_ROWS
2251
+ maxRows: AI_ASSISTANT_DISPLAY_PREVIEW_MAX_ROWS,
2252
+ includeGroupFromId: directive.type === 'aggregate'
1703
2253
  });
1704
2254
  var trimmedDisplay = trimDisplayTable(display, {
1705
2255
  maxColumns: AI_ASSISTANT_DISPLAY_MAX_COLUMNS,
@@ -1779,7 +2329,7 @@ function buildAssistantToolFallbackResponse(result) {
1779
2329
  return lines.join('\n').trim();
1780
2330
  }
1781
2331
  function buildAssistantDebugPayload(params) {
1782
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
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;
1783
2333
  var notes = [];
1784
2334
  if (params.dataQuestion) {
1785
2335
  notes.push('Detected a data request; tool call required.');
@@ -1787,18 +2337,24 @@ function buildAssistantDebugPayload(params) {
1787
2337
  if (params.directiveSource === 'forced') {
1788
2338
  notes.push('Assistant response omitted a MONGO_* directive; ran a directive-only pass.');
1789
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
+ }
1790
2346
  var directive = params.directive;
1791
2347
  var directivePayload = (directive === null || directive === void 0 ? void 0 : directive.payload) || {};
1792
2348
  var rawCollection = normalizeOptionalString(directivePayload === null || directivePayload === void 0 ? void 0 : directivePayload.collection);
1793
- var debugCollectionRequested = normalizeOptionalString((_a = params.toolResponseDebug) === null || _a === void 0 ? void 0 : _a.collectionRequested);
1794
- var debugCollectionResolved = normalizeOptionalString((_b = params.toolResponseDebug) === null || _b === void 0 ? void 0 : _b.collectionResolved);
1795
- 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);
1796
2352
  var requestedCollection = debugCollectionRequested || rawCollection;
1797
2353
  var resolvedCollection = debugCollectionResolved || debugCollection || requestedCollection;
1798
- 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'
1799
2355
  ? params.toolResponseDebug.collectionMatched
1800
2356
  : undefined;
1801
- 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)
1802
2358
  ? params.toolResponseDebug.collectionCandidates.filter(Boolean)
1803
2359
  : [];
1804
2360
  if (requestedCollection && resolvedCollection && requestedCollection !== resolvedCollection) {
@@ -1807,24 +2363,78 @@ function buildAssistantDebugPayload(params) {
1807
2363
  else if (matchedCollection === false && candidateCollections.length) {
1808
2364
  notes.push("No direct collection match; candidates: ".concat(candidateCollections.join(', '), "."));
1809
2365
  }
1810
- 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') {
1811
2367
  notes.push('Used aggregation for grouped/breakdown request.');
1812
2368
  }
1813
- 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') {
1814
2370
  notes.push('Used read query for list/count request.');
1815
2371
  }
1816
- var fallbackInfo = (_h = params.toolResponseDebug) === null || _h === void 0 ? void 0 : _h.fallbacks;
1817
- 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) {
1818
2374
  notes.push("Retried with date field fallback ".concat(fallbackInfo.dateField.from, " -> ").concat(fallbackInfo.dateField.to, "."));
1819
2375
  }
1820
- 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) {
1821
2377
  notes.push("Retried with date field fallback ".concat(fallbackInfo.dateFieldCreatedAt.from, " -> ").concat(fallbackInfo.dateFieldCreatedAt.to, "."));
1822
2378
  }
1823
- if ((_l = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.unwind) === 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) {
2380
+ var sources = Array.isArray(fallbackInfo.completion.sources)
2381
+ ? fallbackInfo.completion.sources.join(', ')
2382
+ : fallbackInfo.completion.field;
2383
+ var strategy = fallbackInfo.completion.strategy ? " (".concat(fallbackInfo.completion.strategy, ")") : '';
2384
+ notes.push("Applied completion fallback".concat(strategy, ": ").concat(sources, "."));
2385
+ }
2386
+ if ((_o = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.dateFieldsExpanded) === null || _o === void 0 ? void 0 : _o.used) {
2387
+ var fields = Array.isArray(fallbackInfo.dateFieldsExpanded.fields)
2388
+ ? fallbackInfo.dateFieldsExpanded.fields.join(', ')
2389
+ : String(fallbackInfo.dateFieldsExpanded.fields || '');
2390
+ if (fields) {
2391
+ notes.push("Expanded date fields: ".concat(fields, "."));
2392
+ }
2393
+ }
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) {
1824
2421
  notes.push("Applied unwind fallback on ".concat(fallbackInfo.unwind.path, "."));
1825
2422
  }
2423
+ if ((_s = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.nameMatch) === null || _s === void 0 ? void 0 : _s.used) {
2424
+ var fields = Array.isArray(fallbackInfo.nameMatch.fields)
2425
+ ? fallbackInfo.nameMatch.fields.join(', ')
2426
+ : fallbackInfo.nameMatch.field;
2427
+ notes.push("Expanded name match fields: ".concat(fields, "."));
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
+ }
1826
2436
  if (params.toolError) {
1827
- var errorMessage = ((_m = params.toolError) === null || _m === void 0 ? void 0 : _m.message) || String(params.toolError || '');
2437
+ var errorMessage = ((_u = params.toolError) === null || _u === void 0 ? void 0 : _u.message) || String(params.toolError || '');
1828
2438
  if (errorMessage) {
1829
2439
  notes.push("Tool error: ".concat(errorMessage));
1830
2440
  }
@@ -1839,18 +2449,19 @@ function buildAssistantDebugPayload(params) {
1839
2449
  payload: directivePayload,
1840
2450
  rawLine: directive.rawLine
1841
2451
  } : null,
2452
+ collectionOverride: params.collectionOverride || undefined,
1842
2453
  collection: resolvedCollection || requestedCollection || undefined,
1843
2454
  collectionRequested: requestedCollection || undefined,
1844
2455
  collectionResolved: resolvedCollection || undefined,
1845
2456
  collectionMatched: matchedCollection,
1846
2457
  collectionCandidates: candidateCollections.length ? candidateCollections : undefined,
1847
- collectionScore: typeof ((_o = params.toolResponseDebug) === null || _o === void 0 ? void 0 : _o.collectionScore) === 'number'
2458
+ collectionScore: typeof ((_v = params.toolResponseDebug) === null || _v === void 0 ? void 0 : _v.collectionScore) === 'number'
1848
2459
  ? params.toolResponseDebug.collectionScore
1849
2460
  : undefined,
1850
- query: ((_p = params.toolResponseDebug) === null || _p === void 0 ? void 0 : _p.query) || undefined,
1851
- pipeline: ((_q = params.toolResponseDebug) === null || _q === void 0 ? void 0 : _q.executedPipeline) || ((_r = params.toolResponseDebug) === null || _r === void 0 ? void 0 : _r.originalPipeline) || undefined,
1852
- options: ((_s = params.toolResponseDebug) === null || _s === void 0 ? void 0 : _s.options) || undefined,
1853
- fallbacks: ((_t = params.toolResponseDebug) === null || _t === void 0 ? void 0 : _t.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,
1854
2465
  notes: notes
1855
2466
  };
1856
2467
  if (params.trace && typeof params.trace === 'object') {
@@ -2117,40 +2728,184 @@ function tokenizeFieldKey(value) {
2117
2728
  function normalizeFieldMatchKey(value) {
2118
2729
  return tokenizeFieldKey(value).join('');
2119
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
+ }
2120
2749
  function getValueAtPath(obj, path) {
2121
- var e_1, _a;
2122
2750
  if (!obj || typeof obj !== 'object') {
2123
2751
  return undefined;
2124
2752
  }
2125
2753
  var parts = String(path || '').split('.').filter(Boolean);
2126
- var current = obj;
2127
- try {
2128
- for (var parts_1 = __values(parts), parts_1_1 = parts_1.next(); !parts_1_1.done; parts_1_1 = parts_1.next()) {
2129
- var part = parts_1_1.value;
2130
- 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) {
2131
2766
  return undefined;
2132
2767
  }
2133
- 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
+ }
2134
2811
  }
2135
2812
  }
2136
2813
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
2137
2814
  finally {
2138
2815
  try {
2139
- 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);
2140
2817
  }
2141
2818
  finally { if (e_1) throw e_1.error; }
2142
2819
  }
2143
- 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;
2144
2899
  }
2145
2900
  function hasNonEmptyValue(docs, fieldPath, options) {
2146
- var e_2, _a;
2901
+ var e_3, _a;
2147
2902
  if (!Array.isArray(docs) || !fieldPath) {
2148
2903
  return false;
2149
2904
  }
2150
2905
  var usePath = fieldPath.includes('.');
2151
2906
  try {
2152
- for (var docs_1 = __values(docs), docs_1_1 = docs_1.next(); !docs_1_1.done; docs_1_1 = docs_1.next()) {
2153
- 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;
2154
2909
  var value = usePath ? getValueAtPath(doc, fieldPath) : doc === null || doc === void 0 ? void 0 : doc[fieldPath];
2155
2910
  if ((options === null || options === void 0 ? void 0 : options.treatObjectLikeAsEmpty) && isDisplayObjectLike(value)) {
2156
2911
  continue;
@@ -2160,12 +2915,12 @@ function hasNonEmptyValue(docs, fieldPath, options) {
2160
2915
  }
2161
2916
  }
2162
2917
  }
2163
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
2918
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
2164
2919
  finally {
2165
2920
  try {
2166
- 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);
2167
2922
  }
2168
- finally { if (e_2) throw e_2.error; }
2923
+ finally { if (e_3) throw e_3.error; }
2169
2924
  }
2170
2925
  return false;
2171
2926
  }
@@ -2201,6 +2956,17 @@ function collectFieldCandidates(docs) {
2201
2956
  }
2202
2957
  var value = doc[key];
2203
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
+ }
2204
2970
  if (isPlainObject(value) && !isMongoObjectId(value) && !(value instanceof Date)) {
2205
2971
  var nestedKeys = Object.keys(value).slice(0, 50);
2206
2972
  nestedKeys.forEach(function (nestedKey) {
@@ -2251,10 +3017,18 @@ function resolveFieldAliases(docs, requestedFields) {
2251
3017
  }
2252
3018
  else {
2253
3019
  var candidateTokens_1 = tokenizeFieldKey(path);
2254
- var requestedTokens = tokenizeFieldKey(field);
3020
+ var requestedBaseTokens = tokenizeFieldKey(field);
3021
+ var requestedTokens = expandFieldTokens(requestedBaseTokens);
2255
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;
2256
3024
  if (overlap > 0) {
2257
- 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
+ }
2258
3032
  }
2259
3033
  }
2260
3034
  var objectRatio = stats.objectLike / Math.max(stats.nonEmpty, 1);
@@ -2319,32 +3093,143 @@ function resolveProjectionRequestedFields(projection) {
2319
3093
  }
2320
3094
  return keys.filter(function (key) { return !isAssistantIdField(key); });
2321
3095
  }
2322
- function formatDisplayColumnName(column) {
2323
- var trimmed = String(column || '').trim();
2324
- if (!trimmed) {
2325
- return '';
3096
+ function isInclusiveProjection(projection) {
3097
+ if (!projection || typeof projection !== 'object') {
3098
+ return false;
2326
3099
  }
2327
- if (trimmed === '_id') {
2328
- return 'id';
3100
+ var keys = Object.keys(projection);
3101
+ if (!keys.length) {
3102
+ return false;
2329
3103
  }
2330
- if (trimmed === '_group') {
2331
- return 'Group';
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;
2332
3120
  }
2333
- var normalized = trimmed.replace(/[\s_]+/g, '').toLowerCase();
2334
- if (normalized === 'createdat') {
2335
- return 'Created At';
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;
3132
+ }
3133
+ function collectQueryFieldPaths(value, fields) {
3134
+ if (!value || typeof value !== 'object' || value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
3135
+ return;
2336
3136
  }
2337
- if (normalized === 'updatedat') {
2338
- return 'Updated At';
3137
+ if (Array.isArray(value)) {
3138
+ value.forEach(function (entry) { return collectQueryFieldPaths(entry, fields); });
3139
+ return;
2339
3140
  }
2340
- var parts = trimmed.split('.');
2341
- var base = parts[parts.length - 1] || trimmed;
2342
- if ((base === 'name' || base === 'title' || base === 'label') && parts.length > 1) {
2343
- return parts[parts.length - 2]
2344
- .replace(/[_-]+/g, ' ')
2345
- .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
2346
- .replace(/\s+/g, ' ')
2347
- .trim()
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()
2348
3233
  .replace(/\b\w/g, function (char) { return char.toUpperCase(); });
2349
3234
  }
2350
3235
  return base
@@ -2415,14 +3300,17 @@ function serializeMongoValue(value, maxLength) {
2415
3300
  }
2416
3301
  return truncateDisplayText(String(value), maxLength);
2417
3302
  }
2418
- function flattenForTable(doc) {
3303
+ function flattenForTable(doc, options) {
2419
3304
  var result = {};
2420
3305
  if (!doc || typeof doc !== 'object') {
2421
3306
  return result;
2422
3307
  }
2423
3308
  if (Object.prototype.hasOwnProperty.call(doc, '_id')) {
2424
3309
  var idValue_1 = doc._id;
2425
- if (idValue_1 !== null && idValue_1 !== undefined) {
3310
+ if (options === null || options === void 0 ? void 0 : options.includeIds) {
3311
+ result._id = idValue_1;
3312
+ }
3313
+ if ((options === null || options === void 0 ? void 0 : options.includeGroupFromId) && idValue_1 !== null && idValue_1 !== undefined) {
2426
3314
  if (isPlainObject(idValue_1) && !isMongoObjectId(idValue_1) && !(idValue_1 instanceof Date)) {
2427
3315
  Object.keys(idValue_1).forEach(function (key) {
2428
3316
  if (!key || Object.prototype.hasOwnProperty.call(result, key)) {
@@ -2465,7 +3353,12 @@ function flattenForTable(doc) {
2465
3353
  return result;
2466
3354
  }
2467
3355
  function buildDisplayTable(docs, options) {
2468
- var rowsRaw = Array.isArray(docs) ? docs.map(function (doc) { return flattenForTable(doc); }) : [];
3356
+ var rowsRaw = Array.isArray(docs)
3357
+ ? docs.map(function (doc) { return flattenForTable(doc, {
3358
+ includeIds: (options === null || options === void 0 ? void 0 : options.includeIds) === true,
3359
+ includeGroupFromId: (options === null || options === void 0 ? void 0 : options.includeGroupFromId) === true
3360
+ }); })
3361
+ : [];
2469
3362
  var stats = new Map();
2470
3363
  rowsRaw.forEach(function (row) {
2471
3364
  Object.keys(row).forEach(function (key) {
@@ -2715,10 +3608,12 @@ function normalizeAssistantAggregatePipeline(pipeline) {
2715
3608
  .map(function (stage) {
2716
3609
  var next = __assign({}, stage);
2717
3610
  if (next.$match && typeof next.$match === 'object') {
2718
- next.$match = applyAssistantNameRegexToQuery(next.$match);
3611
+ var rewritten = rewriteEmbeddedMatchObjects(next.$match);
3612
+ next.$match = applyAssistantNameRegexToQuery(rewritten);
2719
3613
  }
2720
3614
  if (next.$geoNear && typeof next.$geoNear === 'object' && next.$geoNear.query) {
2721
- 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) });
2722
3617
  }
2723
3618
  return next;
2724
3619
  });
@@ -2821,7 +3716,8 @@ function normalizeAggregateFieldList(values) {
2821
3716
  return result;
2822
3717
  }
2823
3718
  function isCompletionFieldName(value) {
2824
- return String(value || '').toLowerCase().includes('complete');
3719
+ var normalized = String(value || '').toLowerCase();
3720
+ return normalized.includes('complete') || normalized.includes('close');
2825
3721
  }
2826
3722
  function isDateLikeFieldName(value) {
2827
3723
  var normalized = String(value || '').toLowerCase();
@@ -2848,7 +3744,7 @@ function matchContainsField(value, field) {
2848
3744
  });
2849
3745
  }
2850
3746
  function resolveAggregateCompletionFallback(pipeline) {
2851
- var e_3, _a;
3747
+ var e_4, _a;
2852
3748
  if (!Array.isArray(pipeline)) {
2853
3749
  return null;
2854
3750
  }
@@ -2861,7 +3757,7 @@ function resolveAggregateCompletionFallback(pipeline) {
2861
3757
  }
2862
3758
  var addFields = stage.$addFields;
2863
3759
  try {
2864
- 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()) {
2865
3761
  var key = _c.value;
2866
3762
  if (!isCompletionFieldName(key)) {
2867
3763
  continue;
@@ -2875,12 +3771,12 @@ function resolveAggregateCompletionFallback(pipeline) {
2875
3771
  }
2876
3772
  }
2877
3773
  }
2878
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
3774
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
2879
3775
  finally {
2880
3776
  try {
2881
3777
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2882
3778
  }
2883
- finally { if (e_3) throw e_3.error; }
3779
+ finally { if (e_4) throw e_4.error; }
2884
3780
  }
2885
3781
  if (candidateField) {
2886
3782
  break;
@@ -2926,18 +3822,18 @@ function resolveAggregateCompletionFallback(pipeline) {
2926
3822
  statusFilter: statusFilter
2927
3823
  };
2928
3824
  }
3825
+ function buildIfNullChain(fields) {
3826
+ if (!fields.length) {
3827
+ return null;
3828
+ }
3829
+ var expr = "$".concat(fields[fields.length - 1]);
3830
+ for (var i = fields.length - 2; i >= 0; i -= 1) {
3831
+ expr = { $ifNull: ["$".concat(fields[i]), expr] };
3832
+ }
3833
+ return expr;
3834
+ }
2929
3835
  function buildAggregateCompletionFallbackPipeline(pipeline, fallback) {
2930
3836
  var _a;
2931
- var buildIfNullChain = function (fields) {
2932
- if (!fields.length) {
2933
- return null;
2934
- }
2935
- var expr = "$".concat(fields[fields.length - 1]);
2936
- for (var i = fields.length - 2; i >= 0; i -= 1) {
2937
- expr = { $ifNull: ["$".concat(fields[i]), expr] };
2938
- }
2939
- return expr;
2940
- };
2941
3837
  var matchStage = (_a = pipeline[fallback.matchIndex]) === null || _a === void 0 ? void 0 : _a.$match;
2942
3838
  if (!matchStage || typeof matchStage !== 'object') {
2943
3839
  return pipeline;
@@ -2970,6 +3866,163 @@ function buildAggregateCompletionFallbackPipeline(pipeline, fallback) {
2970
3866
  return stage;
2971
3867
  });
2972
3868
  }
3869
+ function normalizeCompletionStatusValue(value) {
3870
+ var normalized = String(value || '').toLowerCase();
3871
+ if (!normalized) {
3872
+ return null;
3873
+ }
3874
+ if (normalized.includes('complete')) {
3875
+ return 'complete';
3876
+ }
3877
+ if (normalized.includes('close')) {
3878
+ return 'close';
3879
+ }
3880
+ return null;
3881
+ }
3882
+ function applyCompletionStatusRegexFallback(match) {
3883
+ if (Array.isArray(match)) {
3884
+ return match.map(function (entry) { return applyCompletionStatusRegexFallback(entry); });
3885
+ }
3886
+ if (!match || typeof match !== 'object') {
3887
+ return match;
3888
+ }
3889
+ var result = {};
3890
+ Object.keys(match).forEach(function (key) {
3891
+ var value = match[key];
3892
+ if (key === 'status' || key === 'state') {
3893
+ if (typeof value === 'string') {
3894
+ var token = normalizeCompletionStatusValue(value);
3895
+ if (token) {
3896
+ result[key] = { $regex: token, $options: 'i' };
3897
+ return;
3898
+ }
3899
+ }
3900
+ result[key] = value;
3901
+ return;
3902
+ }
3903
+ if (key.startsWith('$')) {
3904
+ result[key] = applyCompletionStatusRegexFallback(value);
3905
+ return;
3906
+ }
3907
+ if (value && typeof value === 'object') {
3908
+ result[key] = applyCompletionStatusRegexFallback(value);
3909
+ return;
3910
+ }
3911
+ result[key] = value;
3912
+ });
3913
+ return result;
3914
+ }
3915
+ function buildCompletionFallbackSources(field) {
3916
+ return normalizeAggregateFieldList([
3917
+ field,
3918
+ 'date_completed',
3919
+ 'date_closed',
3920
+ 'completedAt',
3921
+ 'closedAt',
3922
+ 'completed_at',
3923
+ 'closed_at',
3924
+ 'date_completed_at',
3925
+ 'date_closed_at',
3926
+ 'completion_date',
3927
+ 'completed_date',
3928
+ 'date_finished',
3929
+ 'finished_at',
3930
+ 'createdAt',
3931
+ 'date_created'
3932
+ ]);
3933
+ }
3934
+ function resolveAggregateCompletionExprFallback(pipeline) {
3935
+ var e_5, _a;
3936
+ if (!Array.isArray(pipeline)) {
3937
+ return null;
3938
+ }
3939
+ for (var i = 0; i < pipeline.length; i += 1) {
3940
+ var stage = pipeline[i];
3941
+ if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
3942
+ continue;
3943
+ }
3944
+ var matchStage = stage.$match;
3945
+ var candidateField = '';
3946
+ if (matchStage.$expr) {
3947
+ var exprFields = extractExpressionFieldPaths(matchStage.$expr)
3948
+ .filter(function (field) { return isCompletionFieldName(field); });
3949
+ if (exprFields.length) {
3950
+ candidateField = exprFields[0];
3951
+ }
3952
+ }
3953
+ if (!candidateField) {
3954
+ try {
3955
+ for (var _b = (e_5 = void 0, __values(Object.keys(matchStage))), _c = _b.next(); !_c.done; _c = _b.next()) {
3956
+ var key = _c.value;
3957
+ if (key.startsWith('$')) {
3958
+ continue;
3959
+ }
3960
+ if (!isCompletionFieldName(key)) {
3961
+ continue;
3962
+ }
3963
+ var entry = matchStage[key];
3964
+ if (hasDateRangeOperators(entry) || entry instanceof Date) {
3965
+ candidateField = key;
3966
+ break;
3967
+ }
3968
+ }
3969
+ }
3970
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
3971
+ finally {
3972
+ try {
3973
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3974
+ }
3975
+ finally { if (e_5) throw e_5.error; }
3976
+ }
3977
+ }
3978
+ if (!candidateField) {
3979
+ continue;
3980
+ }
3981
+ var sources = buildCompletionFallbackSources(candidateField);
3982
+ if (!sources.length) {
3983
+ return null;
3984
+ }
3985
+ var hasStatus = matchContainsField(matchStage, 'status') || matchContainsField(matchStage, 'state');
3986
+ var statusFilter = !hasStatus
3987
+ ? { $or: [{ status: { $regex: 'complete', $options: 'i' } }, { state: { $regex: 'complete', $options: 'i' } }] }
3988
+ : null;
3989
+ return {
3990
+ matchIndex: i,
3991
+ field: candidateField,
3992
+ sources: sources,
3993
+ statusFilter: statusFilter
3994
+ };
3995
+ }
3996
+ return null;
3997
+ }
3998
+ function buildAggregateCompletionExprFallbackPipeline(pipeline, fallback) {
3999
+ var _a;
4000
+ var _b;
4001
+ var targetField = 'completed_at_effective';
4002
+ var replacedPipeline = replaceAggregateDateField(pipeline, fallback.field, targetField);
4003
+ var matchStage = (_b = replacedPipeline[fallback.matchIndex]) === null || _b === void 0 ? void 0 : _b.$match;
4004
+ if (!matchStage || typeof matchStage !== 'object') {
4005
+ return replacedPipeline;
4006
+ }
4007
+ var baseMatch = applyCompletionStatusRegexFallback(matchStage);
4008
+ var nextMatch = fallback.statusFilter ? { $and: [baseMatch, fallback.statusFilter] } : baseMatch;
4009
+ var addFieldsStage = { $addFields: (_a = {}, _a[targetField] = buildIfNullChain(fallback.sources), _a) };
4010
+ var alreadyHasField = replacedPipeline
4011
+ .slice(0, fallback.matchIndex)
4012
+ .some(function (stage) { return stage && typeof stage === 'object' && stage.$addFields && Object.prototype.hasOwnProperty.call(stage.$addFields, targetField); });
4013
+ var output = [];
4014
+ replacedPipeline.forEach(function (stage, index) {
4015
+ if (index === fallback.matchIndex) {
4016
+ if (!alreadyHasField) {
4017
+ output.push(addFieldsStage);
4018
+ }
4019
+ output.push({ $match: nextMatch });
4020
+ return;
4021
+ }
4022
+ output.push(stage);
4023
+ });
4024
+ return output;
4025
+ }
2973
4026
  function resolveAggregateUnwindFallback(pipeline) {
2974
4027
  var groupIndex = findAggregateGroupIndex(pipeline);
2975
4028
  if (groupIndex === -1) {
@@ -3076,47 +4129,771 @@ function buildAggregateUnwindFallbackPipeline(pipeline, fallback) {
3076
4129
  };
3077
4130
  return __spreadArray(__spreadArray(__spreadArray([], __read(before), false), [unwindStage], false), __read(after), false);
3078
4131
  }
3079
- function findAggregateDateField(pipeline) {
3080
- var fields = new Set();
3081
- (pipeline || []).forEach(function (stage) {
3082
- if (!stage || typeof stage !== 'object') {
4132
+ function isRegexMatchCondition(value) {
4133
+ if (!value) {
4134
+ return false;
4135
+ }
4136
+ if (value instanceof RegExp) {
4137
+ return true;
4138
+ }
4139
+ if (typeof value === 'object' && !Array.isArray(value)) {
4140
+ return Object.prototype.hasOwnProperty.call(value, '$regex');
4141
+ }
4142
+ return false;
4143
+ }
4144
+ function findRegexMatchInMatchObject(match, prefix) {
4145
+ var e_6, _a, e_7, _b;
4146
+ if (prefix === void 0) { prefix = ''; }
4147
+ if (Array.isArray(match)) {
4148
+ try {
4149
+ for (var match_1 = __values(match), match_1_1 = match_1.next(); !match_1_1.done; match_1_1 = match_1.next()) {
4150
+ var entry = match_1_1.value;
4151
+ var found = findRegexMatchInMatchObject(entry, prefix);
4152
+ if (found) {
4153
+ return found;
4154
+ }
4155
+ }
4156
+ }
4157
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
4158
+ finally {
4159
+ try {
4160
+ if (match_1_1 && !match_1_1.done && (_a = match_1.return)) _a.call(match_1);
4161
+ }
4162
+ finally { if (e_6) throw e_6.error; }
4163
+ }
4164
+ return null;
4165
+ }
4166
+ if (!match || typeof match !== 'object') {
4167
+ return null;
4168
+ }
4169
+ var keys = Object.keys(match);
4170
+ try {
4171
+ for (var keys_1 = __values(keys), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
4172
+ var key = keys_1_1.value;
4173
+ var value = match[key];
4174
+ if (key.startsWith('$')) {
4175
+ var found = findRegexMatchInMatchObject(value, prefix);
4176
+ if (found) {
4177
+ return found;
4178
+ }
4179
+ continue;
4180
+ }
4181
+ var currentPath = prefix ? "".concat(prefix, ".").concat(key) : key;
4182
+ if (isRegexMatchCondition(value)) {
4183
+ return { field: currentPath, condition: value };
4184
+ }
4185
+ if (value && typeof value === 'object') {
4186
+ var found = findRegexMatchInMatchObject(value, currentPath);
4187
+ if (found) {
4188
+ return found;
4189
+ }
4190
+ }
4191
+ }
4192
+ }
4193
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
4194
+ finally {
4195
+ try {
4196
+ if (keys_1_1 && !keys_1_1.done && (_b = keys_1.return)) _b.call(keys_1);
4197
+ }
4198
+ finally { if (e_7) throw e_7.error; }
4199
+ }
4200
+ return null;
4201
+ }
4202
+ function expandNameFieldCandidates(field) {
4203
+ var normalized = normalizeOptionalString(field);
4204
+ if (!normalized) {
4205
+ return [];
4206
+ }
4207
+ var parts = normalized.split('.').filter(Boolean);
4208
+ var leaf = parts[parts.length - 1] || normalized;
4209
+ var prefix = parts.length > 1 ? parts.slice(0, -1).join('.') : '';
4210
+ var withPrefix = function (value) { return (prefix ? "".concat(prefix, ".").concat(value) : value); };
4211
+ var candidates = [];
4212
+ var seen = new Set();
4213
+ var push = function (value) {
4214
+ if (!value) {
3083
4215
  return;
3084
4216
  }
3085
- if (stage.$match && typeof stage.$match === 'object') {
3086
- collectDateFieldsFromMatch(stage.$match, fields);
4217
+ if (seen.has(value)) {
4218
+ return;
3087
4219
  }
3088
- });
3089
- if (fields.size !== 1) {
4220
+ seen.add(value);
4221
+ candidates.push(value);
4222
+ };
4223
+ push(normalized);
4224
+ var leafLower = leaf.toLowerCase();
4225
+ var genericVariants = ['name', 'title', 'label', 'display_name', 'displayName', 'description'];
4226
+ genericVariants.forEach(function (variant) { return push(withPrefix(variant)); });
4227
+ if (!leafLower.endsWith('name')) {
4228
+ push(withPrefix("".concat(leaf, "_name")));
4229
+ push(withPrefix("".concat(leaf, "Name")));
4230
+ }
4231
+ if (leafLower.includes('chemical')) {
4232
+ [
4233
+ 'chemical',
4234
+ 'chemical_name',
4235
+ 'chemicalName',
4236
+ 'chem_name',
4237
+ 'chemName',
4238
+ 'product',
4239
+ 'product_name',
4240
+ 'productName',
4241
+ 'material',
4242
+ 'blend_name'
4243
+ ].forEach(function (variant) { return push(withPrefix(variant)); });
4244
+ push(withPrefix("".concat(leaf, ".name")));
4245
+ push(withPrefix("".concat(leaf, ".label")));
4246
+ push(withPrefix("".concat(leaf, ".product")));
4247
+ if (normalized.includes('blend_chemicals')) {
4248
+ ['chemical', 'chemical_name', 'chemicalName', 'product', 'product_name', 'productName'].forEach(push);
4249
+ }
4250
+ }
4251
+ if (leafLower.includes('customer')) {
4252
+ [
4253
+ 'customer',
4254
+ 'customer_name',
4255
+ 'customerName',
4256
+ 'company',
4257
+ 'company_name',
4258
+ 'companyName',
4259
+ 'account',
4260
+ 'account_name',
4261
+ 'accountName',
4262
+ 'name'
4263
+ ].forEach(function (variant) { return push(withPrefix(variant)); });
4264
+ push(withPrefix("".concat(leaf, ".name")));
4265
+ }
4266
+ if (leafLower.includes('well')) {
4267
+ [
4268
+ 'well',
4269
+ 'well_name',
4270
+ 'wellName',
4271
+ 'name',
4272
+ 'site',
4273
+ 'site_name',
4274
+ 'siteName',
4275
+ 'pad',
4276
+ 'pad_name',
4277
+ 'padName',
4278
+ 'api',
4279
+ 'api_number',
4280
+ 'apiNumber',
4281
+ 'well_number',
4282
+ 'wellNumber'
4283
+ ].forEach(function (variant) { return push(withPrefix(variant)); });
4284
+ push(withPrefix("".concat(leaf, ".name")));
4285
+ }
4286
+ return candidates.slice(0, AI_ASSISTANT_NAME_MATCH_FALLBACK_MAX_FIELDS);
4287
+ }
4288
+ function resolveAggregateNameMatchFallback(pipeline) {
4289
+ if (!Array.isArray(pipeline)) {
3090
4290
  return null;
3091
4291
  }
3092
- return Array.from(fields)[0];
4292
+ for (var i = 0; i < pipeline.length; i += 1) {
4293
+ var stage = pipeline[i];
4294
+ if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
4295
+ continue;
4296
+ }
4297
+ var found = findRegexMatchInMatchObject(stage.$match);
4298
+ if (!found || !shouldApplyAssistantNameRegex(found.field)) {
4299
+ continue;
4300
+ }
4301
+ var fields = expandNameFieldCandidates(found.field);
4302
+ if (fields.length <= 1) {
4303
+ continue;
4304
+ }
4305
+ return {
4306
+ matchIndex: i,
4307
+ field: found.field,
4308
+ condition: found.condition,
4309
+ fields: fields
4310
+ };
4311
+ }
4312
+ return null;
3093
4313
  }
3094
- function collectDateFieldsFromMatch(value, fields) {
3095
- if (!value || typeof value !== 'object') {
3096
- return;
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
+ }
4340
+ function isEmptyMatchValue(value) {
4341
+ if (value === null || value === undefined) {
4342
+ return true;
3097
4343
  }
3098
4344
  if (Array.isArray(value)) {
3099
- value.forEach(function (entry) { return collectDateFieldsFromMatch(entry, fields); });
3100
- return;
4345
+ return value.length === 0;
3101
4346
  }
3102
- Object.keys(value).forEach(function (key) {
3103
- var entry = value[key];
3104
- if (Object.prototype.hasOwnProperty.call(AI_ASSISTANT_DATE_FALLBACKS, key)) {
3105
- if (hasDateRangeOperators(entry) || entry instanceof Date) {
3106
- fields.add(key);
3107
- }
4347
+ if (typeof value === 'object') {
4348
+ return Object.keys(value).length === 0;
4349
+ }
4350
+ return false;
4351
+ }
4352
+ function stripMatchField(match, field) {
4353
+ if (Array.isArray(match)) {
4354
+ var strippedArray = match
4355
+ .map(function (entry) { return stripMatchField(entry, field); })
4356
+ .filter(function (entry) { return !isEmptyMatchValue(entry); });
4357
+ return strippedArray;
4358
+ }
4359
+ if (!match || typeof match !== 'object') {
4360
+ return match;
4361
+ }
4362
+ var result = {};
4363
+ Object.keys(match).forEach(function (key) {
4364
+ if (key === field) {
3108
4365
  return;
3109
4366
  }
4367
+ var value = match[key];
3110
4368
  if (key.startsWith('$')) {
3111
- collectDateFieldsFromMatch(entry, fields);
4369
+ var stripped = stripMatchField(value, field);
4370
+ if (isEmptyMatchValue(stripped) && (key === '$and' || key === '$or')) {
4371
+ return;
4372
+ }
4373
+ result[key] = stripped;
3112
4374
  return;
3113
4375
  }
3114
- if (entry && typeof entry === 'object') {
3115
- collectDateFieldsFromMatch(entry, fields);
4376
+ if (value && typeof value === 'object') {
4377
+ var stripped = stripMatchField(value, field);
4378
+ if (!isEmptyMatchValue(stripped)) {
4379
+ result[key] = stripped;
4380
+ }
4381
+ return;
3116
4382
  }
4383
+ result[key] = value;
3117
4384
  });
4385
+ return result;
3118
4386
  }
3119
- function hasDateRangeOperators(value) {
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
+ }
4835
+ function buildAggregateNameMatchFallbackPipeline(pipeline, fallback) {
4836
+ var _a;
4837
+ var matchStage = (_a = pipeline[fallback.matchIndex]) === null || _a === void 0 ? void 0 : _a.$match;
4838
+ if (!matchStage || typeof matchStage !== 'object') {
4839
+ return pipeline;
4840
+ }
4841
+ var baseMatch = stripMatchField(matchStage, fallback.field);
4842
+ var orConditions = fallback.fields.map(function (field) {
4843
+ var _a;
4844
+ return (_a = {}, _a[field] = fallback.condition, _a);
4845
+ });
4846
+ var nextMatch = isEmptyMatchValue(baseMatch)
4847
+ ? { $or: orConditions }
4848
+ : { $and: [baseMatch, { $or: orConditions }] };
4849
+ return pipeline.map(function (stage, index) {
4850
+ if (index === fallback.matchIndex) {
4851
+ return { $match: nextMatch };
4852
+ }
4853
+ return stage;
4854
+ });
4855
+ }
4856
+ function findAggregateDateField(pipeline) {
4857
+ var fields = new Set();
4858
+ (pipeline || []).forEach(function (stage) {
4859
+ if (!stage || typeof stage !== 'object') {
4860
+ return;
4861
+ }
4862
+ if (stage.$match && typeof stage.$match === 'object') {
4863
+ collectDateFieldsFromMatch(stage.$match, fields);
4864
+ }
4865
+ });
4866
+ if (fields.size !== 1) {
4867
+ return null;
4868
+ }
4869
+ return Array.from(fields)[0];
4870
+ }
4871
+ function collectDateFieldsFromMatch(value, fields) {
4872
+ if (!value || typeof value !== 'object') {
4873
+ return;
4874
+ }
4875
+ if (Array.isArray(value)) {
4876
+ value.forEach(function (entry) { return collectDateFieldsFromMatch(entry, fields); });
4877
+ return;
4878
+ }
4879
+ Object.keys(value).forEach(function (key) {
4880
+ var entry = value[key];
4881
+ if (Object.prototype.hasOwnProperty.call(AI_ASSISTANT_DATE_FALLBACKS, key)) {
4882
+ if (hasDateRangeOperators(entry) || entry instanceof Date) {
4883
+ fields.add(key);
4884
+ }
4885
+ return;
4886
+ }
4887
+ if (key.startsWith('$')) {
4888
+ collectDateFieldsFromMatch(entry, fields);
4889
+ return;
4890
+ }
4891
+ if (entry && typeof entry === 'object') {
4892
+ collectDateFieldsFromMatch(entry, fields);
4893
+ }
4894
+ });
4895
+ }
4896
+ function hasDateRangeOperators(value) {
3120
4897
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
3121
4898
  return false;
3122
4899
  }
@@ -3134,12 +4911,12 @@ function replaceAggregateDateField(pipeline, fromField, toField) {
3134
4911
  return value;
3135
4912
  }
3136
4913
  if (value && typeof value === 'object') {
3137
- var next_1 = {};
4914
+ var next_2 = {};
3138
4915
  Object.keys(value).forEach(function (key) {
3139
4916
  var nextKey = key === fromField ? toField : key;
3140
- next_1[nextKey] = replacer(value[key]);
4917
+ next_2[nextKey] = replacer(value[key]);
3141
4918
  });
3142
- return next_1;
4919
+ return next_2;
3143
4920
  }
3144
4921
  if (typeof value === 'string') {
3145
4922
  if (value.startsWith("$".concat(fromField))) {
@@ -3156,7 +4933,8 @@ function normalizeMongoQuery(query) {
3156
4933
  if (containsForbiddenMongoOperators(normalized)) {
3157
4934
  throw new Error('AI assistant mongo read: Query contains restricted operators.');
3158
4935
  }
3159
- return applyAssistantNameRegexToQuery(normalized);
4936
+ var rewritten = rewriteEmbeddedMatchObjects(normalized);
4937
+ return applyAssistantNameRegexToQuery(rewritten);
3160
4938
  }
3161
4939
  function shouldApplyAssistantNameRegex(field) {
3162
4940
  var normalized = String(field || '').toLowerCase().trim();
@@ -3213,6 +4991,126 @@ function applyAssistantNameRegexToQuery(query) {
3213
4991
  });
3214
4992
  return result;
3215
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
+ }
3216
5114
  function normalizeCollectionKey(value) {
3217
5115
  return String(value || '').toLowerCase().replace(/[^a-z0-9]/g, '');
3218
5116
  }
@@ -3247,6 +5145,19 @@ function tokenizeCollectionText(value) {
3247
5145
  });
3248
5146
  return Array.from(new Set(tokens));
3249
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
+ }
3250
5161
  function expandAssistantTermSynonyms(text) {
3251
5162
  var base = normalizeOptionalString(text);
3252
5163
  if (!base) {
@@ -3299,29 +5210,179 @@ function listAssistantCollections(db, dbName) {
3299
5210
  });
3300
5211
  });
3301
5212
  }
3302
- function scoreCollectionMatch(requestedTokens, candidateName) {
5213
+ function scoreCollectionMatch(requestedTokens, candidateName, tokenWeights) {
3303
5214
  if (!requestedTokens.length) {
3304
5215
  return 0;
3305
5216
  }
3306
- var candidateTokens = tokenizeCollectionText(candidateName);
3307
- if (!candidateTokens.length) {
3308
- return 0;
5217
+ var candidateTokens = tokenizeCollectionText(candidateName);
5218
+ if (!candidateTokens.length) {
5219
+ return 0;
5220
+ }
5221
+ var score = 0;
5222
+ requestedTokens.forEach(function (token) {
5223
+ var _a;
5224
+ if (candidateTokens.includes(token)) {
5225
+ var weight = (_a = tokenWeights === null || tokenWeights === void 0 ? void 0 : tokenWeights[token]) !== null && _a !== void 0 ? _a : 1;
5226
+ score += 10 * weight;
5227
+ }
5228
+ });
5229
+ var requestedKey = normalizeCollectionKey(requestedTokens.join('-'));
5230
+ var candidateKey = normalizeCollectionKey(candidateName);
5231
+ if (candidateKey === requestedKey && requestedKey) {
5232
+ score += 50;
5233
+ }
5234
+ else if (requestedKey && (candidateKey.includes(requestedKey) || requestedKey.includes(candidateKey))) {
5235
+ score += 20;
5236
+ }
5237
+ return score;
5238
+ }
5239
+ function scoreCollectionMatchDetailed(requestedTokens, candidateName, tokenWeights) {
5240
+ var candidateTokens = tokenizeCollectionText(candidateName);
5241
+ var tokenMatches = requestedTokens.filter(function (token) { return candidateTokens.includes(token); });
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;
5245
+ var requestedKey = normalizeCollectionKey(requestedTokens.join('-'));
5246
+ var candidateKey = normalizeCollectionKey(candidateName);
5247
+ var keyMatch = null;
5248
+ if (candidateKey === requestedKey && requestedKey) {
5249
+ score += 50;
5250
+ keyMatch = 'exact';
5251
+ }
5252
+ else if (requestedKey && (candidateKey.includes(requestedKey) || requestedKey.includes(candidateKey))) {
5253
+ score += 20;
5254
+ keyMatch = 'partial';
5255
+ }
5256
+ return {
5257
+ score: score,
5258
+ tokenMatches: tokenMatches,
5259
+ keyMatch: keyMatch,
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
+ }, {})
5267
+ };
5268
+ }
5269
+ function resolveCollectionHintsFromTokens(tokens, collectionNames, max) {
5270
+ if (max === void 0) { max = 5; }
5271
+ if (!tokens.length || !collectionNames.length) {
5272
+ return [];
5273
+ }
5274
+ var weights = computeCollectionTokenWeights(tokens).weights;
5275
+ return collectionNames
5276
+ .map(function (name) { return ({ name: name, score: scoreCollectionMatch(tokens, name, weights) }); })
5277
+ .filter(function (entry) { return entry.score > 0; })
5278
+ .sort(function (a, b) { return b.score - a.score; })
5279
+ .slice(0, Math.max(max, 0))
5280
+ .map(function (entry) { return entry.name; });
5281
+ }
5282
+ function buildCollectionRankingDebugFromTokens(tokens, collectionNames, max) {
5283
+ if (max === void 0) { max = 8; }
5284
+ var requestedKey = normalizeCollectionKey(tokens.join('-'));
5285
+ var _a = computeCollectionTokenWeights(tokens), weights = _a.weights, hasDomain = _a.hasDomain;
5286
+ if (!tokens.length || !collectionNames.length) {
5287
+ return {
5288
+ tokens: tokens,
5289
+ requestedKey: requestedKey,
5290
+ hasDomain: hasDomain,
5291
+ tokenWeights: weights,
5292
+ ranked: []
5293
+ };
5294
+ }
5295
+ var ranked = collectionNames
5296
+ .map(function (name) { return (__assign({ name: name }, scoreCollectionMatchDetailed(tokens, name, weights))); })
5297
+ .filter(function (entry) { return entry.score > 0; })
5298
+ .sort(function (a, b) { return b.score - a.score; })
5299
+ .slice(0, Math.max(max, 0));
5300
+ return {
5301
+ tokens: tokens,
5302
+ requestedKey: requestedKey,
5303
+ hasDomain: hasDomain,
5304
+ tokenWeights: weights,
5305
+ ranked: ranked
5306
+ };
5307
+ }
5308
+ function buildCollectionSelectionDetail(tokens, collection) {
5309
+ var trimmed = normalizeOptionalString(collection);
5310
+ if (!trimmed) {
5311
+ return null;
5312
+ }
5313
+ var weights = computeCollectionTokenWeights(tokens).weights;
5314
+ var detail = scoreCollectionMatchDetailed(tokens, trimmed, weights);
5315
+ return {
5316
+ collection: trimmed,
5317
+ score: detail.score,
5318
+ tokenMatches: detail.tokenMatches,
5319
+ keyMatch: detail.keyMatch,
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;
3309
5355
  }
3310
- var score = 0;
3311
- requestedTokens.forEach(function (token) {
3312
- if (candidateTokens.includes(token)) {
3313
- score += 10;
3314
- }
3315
- });
3316
- var requestedKey = normalizeCollectionKey(requestedTokens.join('-'));
3317
- var candidateKey = normalizeCollectionKey(candidateName);
3318
- if (candidateKey === requestedKey && requestedKey) {
3319
- score += 50;
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
+ };
3320
5365
  }
3321
- else if (requestedKey && (candidateKey.includes(requestedKey) || requestedKey.includes(candidateKey))) {
3322
- score += 20;
5366
+ if (current === top.name) {
5367
+ return null;
3323
5368
  }
3324
- return score;
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
5385
+ };
3325
5386
  }
3326
5387
  function findBestCollectionMatch(requested, collectionNames) {
3327
5388
  var requestedTokens = tokenizeCollectionText(requested);
@@ -3368,38 +5429,8 @@ function resolveAssistantCollectionName(db, dbName, requested) {
3368
5429
  });
3369
5430
  });
3370
5431
  }
3371
- function resolveAssistantCollectionHints(message, dbName, db) {
3372
- return __awaiter(this, void 0, void 0, function () {
3373
- var text, collectionNames, tokens;
3374
- return __generator(this, function (_a) {
3375
- switch (_a.label) {
3376
- case 0:
3377
- text = normalizeOptionalString(message);
3378
- if (!text) {
3379
- return [2 /*return*/, []];
3380
- }
3381
- return [4 /*yield*/, listAssistantCollections(db, dbName)];
3382
- case 1:
3383
- collectionNames = _a.sent();
3384
- if (!collectionNames.length) {
3385
- return [2 /*return*/, []];
3386
- }
3387
- tokens = tokenizeCollectionText(text);
3388
- if (!tokens.length) {
3389
- return [2 /*return*/, []];
3390
- }
3391
- return [2 /*return*/, collectionNames
3392
- .map(function (name) { return ({ name: name, score: scoreCollectionMatch(tokens, name) }); })
3393
- .filter(function (entry) { return entry.score > 0; })
3394
- .sort(function (a, b) { return b.score - a.score; })
3395
- .slice(0, 5)
3396
- .map(function (entry) { return entry.name; })];
3397
- }
3398
- });
3399
- });
3400
- }
3401
5432
  function findQueryDateField(query) {
3402
- var e_4, _a, e_5, _b;
5433
+ var e_10, _a, e_11, _b;
3403
5434
  if (!query || typeof query !== 'object') {
3404
5435
  return null;
3405
5436
  }
@@ -3413,12 +5444,12 @@ function findQueryDateField(query) {
3413
5444
  }
3414
5445
  }
3415
5446
  }
3416
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
5447
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
3417
5448
  finally {
3418
5449
  try {
3419
5450
  if (query_1_1 && !query_1_1.done && (_a = query_1.return)) _a.call(query_1);
3420
5451
  }
3421
- finally { if (e_4) throw e_4.error; }
5452
+ finally { if (e_10) throw e_10.error; }
3422
5453
  }
3423
5454
  return null;
3424
5455
  }
@@ -3437,12 +5468,12 @@ function findQueryDateField(query) {
3437
5468
  }
3438
5469
  }
3439
5470
  }
3440
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
5471
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
3441
5472
  finally {
3442
5473
  try {
3443
5474
  if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
3444
5475
  }
3445
- finally { if (e_5) throw e_5.error; }
5476
+ finally { if (e_11) throw e_11.error; }
3446
5477
  }
3447
5478
  return null;
3448
5479
  }
@@ -3460,6 +5491,198 @@ function replaceQueryField(query, fromField, toField) {
3460
5491
  });
3461
5492
  return result;
3462
5493
  }
5494
+ function extractDateRangeConditions(query) {
5495
+ if (!query || typeof query !== 'object' || query instanceof Date) {
5496
+ return [];
5497
+ }
5498
+ var results = [];
5499
+ Object.keys(query).forEach(function (key) {
5500
+ if (key.startsWith('$')) {
5501
+ return;
5502
+ }
5503
+ var value = query[key];
5504
+ if (value instanceof Date) {
5505
+ results.push({ field: key, condition: value });
5506
+ return;
5507
+ }
5508
+ if (value && typeof value === 'object' && hasDateRangeOperators(value)) {
5509
+ results.push({ field: key, condition: value });
5510
+ }
5511
+ });
5512
+ return results;
5513
+ }
5514
+ function expandQueryDateFallbacks(query) {
5515
+ if (!query || typeof query !== 'object') {
5516
+ return null;
5517
+ }
5518
+ var addedFields = [];
5519
+ var pushField = function (field) {
5520
+ if (!field) {
5521
+ return;
5522
+ }
5523
+ if (addedFields.includes(field)) {
5524
+ return;
5525
+ }
5526
+ addedFields.push(field);
5527
+ };
5528
+ var expandOrArray = function (orArray) {
5529
+ var existingFields = new Set();
5530
+ orArray.forEach(function (entry) {
5531
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
5532
+ return;
5533
+ }
5534
+ Object.keys(entry).forEach(function (key) {
5535
+ if (!key.startsWith('$')) {
5536
+ existingFields.add(key);
5537
+ }
5538
+ });
5539
+ });
5540
+ var extended = __spreadArray([], __read(orArray), false);
5541
+ orArray.forEach(function (entry) {
5542
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
5543
+ return;
5544
+ }
5545
+ var dateConditions = extractDateRangeConditions(entry);
5546
+ dateConditions.forEach(function (condition) {
5547
+ var fallback = AI_ASSISTANT_DATE_FALLBACKS[condition.field];
5548
+ if (fallback && !existingFields.has(fallback)) {
5549
+ extended = __spreadArray(__spreadArray([], __read(extended), false), [replaceQueryField(entry, condition.field, fallback)], false);
5550
+ existingFields.add(fallback);
5551
+ pushField(fallback);
5552
+ }
5553
+ });
5554
+ if (!existingFields.has('date_original')) {
5555
+ var candidate = dateConditions.find(function (condition) { return condition.field.startsWith('date_') && condition.field !== 'date_original'; });
5556
+ if (candidate) {
5557
+ extended = __spreadArray(__spreadArray([], __read(extended), false), [replaceQueryField(entry, candidate.field, 'date_original')], false);
5558
+ existingFields.add('date_original');
5559
+ pushField('date_original');
5560
+ }
5561
+ }
5562
+ });
5563
+ return extended;
5564
+ };
5565
+ var visit = function (value) {
5566
+ if (Array.isArray(value)) {
5567
+ var changed_2 = false;
5568
+ var nextArray = value.map(function (entry) {
5569
+ var visited = visit(entry);
5570
+ if (visited.changed) {
5571
+ changed_2 = true;
5572
+ }
5573
+ return visited.value;
5574
+ });
5575
+ return { value: changed_2 ? nextArray : value, changed: changed_2 };
5576
+ }
5577
+ if (!value || typeof value !== 'object') {
5578
+ return { value: value, changed: false };
5579
+ }
5580
+ var changed = false;
5581
+ var next = __assign({}, value);
5582
+ Object.keys(value).forEach(function (key) {
5583
+ if (key === '$or' && Array.isArray(value.$or)) {
5584
+ var expanded = expandOrArray(value.$or);
5585
+ if (expanded.length !== value.$or.length) {
5586
+ next.$or = expanded;
5587
+ changed = true;
5588
+ }
5589
+ return;
5590
+ }
5591
+ var visited = visit(value[key]);
5592
+ if (visited.changed) {
5593
+ next[key] = visited.value;
5594
+ changed = true;
5595
+ }
5596
+ });
5597
+ return { value: changed ? next : value, changed: changed };
5598
+ };
5599
+ var result = visit(query);
5600
+ if (!result.changed || !addedFields.length) {
5601
+ return null;
5602
+ }
5603
+ return { query: result.value, fields: addedFields };
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
+ }
3463
5686
  function resolveQueryDateFieldFallback(query) {
3464
5687
  var dateField = findQueryDateField(query);
3465
5688
  if (!dateField) {
@@ -3472,7 +5695,7 @@ function resolveQueryDateFieldFallback(query) {
3472
5695
  return { from: dateField, to: fallback };
3473
5696
  }
3474
5697
  function containsForbiddenMongoOperators(value) {
3475
- var e_6, _a;
5698
+ var e_12, _a;
3476
5699
  if (!value || typeof value !== 'object') {
3477
5700
  return false;
3478
5701
  }
@@ -3491,12 +5714,12 @@ function containsForbiddenMongoOperators(value) {
3491
5714
  }
3492
5715
  }
3493
5716
  }
3494
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
5717
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
3495
5718
  finally {
3496
5719
  try {
3497
5720
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3498
5721
  }
3499
- finally { if (e_6) throw e_6.error; }
5722
+ finally { if (e_12) throw e_12.error; }
3500
5723
  }
3501
5724
  return false;
3502
5725
  }
@@ -3505,9 +5728,49 @@ function buildClientScopeCacheKey(dbName, collection) {
3505
5728
  var normalizedCollection = normalizeOptionalString(collection).toLowerCase();
3506
5729
  return "".concat(normalizedDb || 'db', ":").concat(normalizedCollection);
3507
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
+ }
3508
5771
  function collectionHasClientIndex(db, dbName, collection) {
3509
5772
  return __awaiter(this, void 0, void 0, function () {
3510
- var normalizedCollection, cacheKey, cached, indexes, hasIndex, _a;
5773
+ var normalizedCollection, cacheKey, cached, hasIndex, _a;
3511
5774
  return __generator(this, function (_b) {
3512
5775
  switch (_b.label) {
3513
5776
  case 0:
@@ -3523,11 +5786,9 @@ function collectionHasClientIndex(db, dbName, collection) {
3523
5786
  _b.label = 1;
3524
5787
  case 1:
3525
5788
  _b.trys.push([1, 3, , 4]);
3526
- return [4 /*yield*/, db.collection(normalizedCollection).indexes()];
5789
+ return [4 /*yield*/, collectionHasFieldIndex(db, dbName, normalizedCollection, 'id_client')];
3527
5790
  case 2:
3528
- indexes = _b.sent();
3529
- hasIndex = Array.isArray(indexes)
3530
- && 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();
3531
5792
  AI_ASSISTANT_CLIENT_SCOPE_CACHE.set(cacheKey, hasIndex);
3532
5793
  return [2 /*return*/, hasIndex];
3533
5794
  case 3:
@@ -3569,6 +5830,25 @@ function applyCustomerScopeFilter(query, collection, idCustomer, isSuperAdmin) {
3569
5830
  $and: [query, (_a = {}, _a[customerField] = normalizedCustomer, _a)]
3570
5831
  };
3571
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
+ }
3572
5852
  function userHasViewPermission(user, view) {
3573
5853
  var _a, _b, _c;
3574
5854
  if (!user || !view) {
@@ -3730,8 +6010,8 @@ function applyCodexStreamStatusHandler(runOptions, streamStatusHandler) {
3730
6010
  }
3731
6011
  function waitForCodexWorkerMessage(worker, streamStatusHandler) {
3732
6012
  return __awaiter(this, void 0, void 0, function () {
3733
- var _a, _b, _c, _d, message, payload, status_1, e_7_1;
3734
- var _e, e_7, _f, _g;
6013
+ var _a, _b, _c, _d, message, payload, status_1, e_13_1;
6014
+ var _e, e_13, _f, _g;
3735
6015
  return __generator(this, function (_h) {
3736
6016
  switch (_h.label) {
3737
6017
  case 0:
@@ -3758,8 +6038,8 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
3758
6038
  return [3 /*break*/, 1];
3759
6039
  case 4: return [3 /*break*/, 11];
3760
6040
  case 5:
3761
- e_7_1 = _h.sent();
3762
- e_7 = { error: e_7_1 };
6041
+ e_13_1 = _h.sent();
6042
+ e_13 = { error: e_13_1 };
3763
6043
  return [3 /*break*/, 11];
3764
6044
  case 6:
3765
6045
  _h.trys.push([6, , 9, 10]);
@@ -3770,7 +6050,7 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
3770
6050
  _h.label = 8;
3771
6051
  case 8: return [3 /*break*/, 10];
3772
6052
  case 9:
3773
- if (e_7) throw e_7.error;
6053
+ if (e_13) throw e_13.error;
3774
6054
  return [7 /*endfinally*/];
3775
6055
  case 10: return [7 /*endfinally*/];
3776
6056
  case 11: throw new CodexWorkerBootstrapError('Codex worker exited before completing.');
@@ -4158,7 +6438,7 @@ function normalizeRouteMatchKey(value) {
4158
6438
  return normalizeRouteKey(value).toLowerCase();
4159
6439
  }
4160
6440
  function buildClientRouteIndex() {
4161
- var e_8, _a;
6441
+ var e_14, _a;
4162
6442
  var _b;
4163
6443
  var routes = ((_b = resolveio_server_app_1.ResolveIOServer.getClientRoutes) === null || _b === void 0 ? void 0 : _b.call(resolveio_server_app_1.ResolveIOServer)) || [];
4164
6444
  var set = new Set();
@@ -4177,12 +6457,12 @@ function buildClientRouteIndex() {
4177
6457
  }
4178
6458
  }
4179
6459
  }
4180
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
6460
+ catch (e_14_1) { e_14 = { error: e_14_1 }; }
4181
6461
  finally {
4182
6462
  try {
4183
6463
  if (routes_1_1 && !routes_1_1.done && (_a = routes_1.return)) _a.call(routes_1);
4184
6464
  }
4185
- finally { if (e_8) throw e_8.error; }
6465
+ finally { if (e_14) throw e_14.error; }
4186
6466
  }
4187
6467
  return { set: set, map: map, size: routes.length };
4188
6468
  }
@@ -4272,6 +6552,20 @@ function sanitizeAssistantResponse(value) {
4272
6552
  }
4273
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);
4274
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
+ };
4275
6569
  var cleanedLines = [];
4276
6570
  withoutBlocks.split('\n').forEach(function (line) {
4277
6571
  var trimmed = line.trim();
@@ -4282,6 +6576,9 @@ function sanitizeAssistantResponse(value) {
4282
6576
  if (isTentativeQueryLine(line)) {
4283
6577
  return;
4284
6578
  }
6579
+ if (isInternalPlanLine(line)) {
6580
+ return;
6581
+ }
4285
6582
  if (/^work ticket summary:/i.test(trimmed)) {
4286
6583
  return;
4287
6584
  }
@@ -4308,7 +6605,7 @@ function sanitizeAssistantResponse(value) {
4308
6605
  return normalizeAssistantRoutes(normalizedCurrency);
4309
6606
  }
4310
6607
  function evaluateAssistantGuardrails(message) {
4311
- var e_9, _a;
6608
+ var e_15, _a;
4312
6609
  var normalized = String(message || '').toLowerCase();
4313
6610
  var patterns = [
4314
6611
  {
@@ -4354,12 +6651,12 @@ function evaluateAssistantGuardrails(message) {
4354
6651
  }
4355
6652
  }
4356
6653
  }
4357
- catch (e_9_1) { e_9 = { error: e_9_1 }; }
6654
+ catch (e_15_1) { e_15 = { error: e_15_1 }; }
4358
6655
  finally {
4359
6656
  try {
4360
6657
  if (patterns_1_1 && !patterns_1_1.done && (_a = patterns_1.return)) _a.call(patterns_1);
4361
6658
  }
4362
- finally { if (e_9) throw e_9.error; }
6659
+ finally { if (e_15) throw e_15.error; }
4363
6660
  }
4364
6661
  return null;
4365
6662
  }
@@ -4446,20 +6743,262 @@ function normalizeAiFormFields(fields) {
4446
6743
  })
4447
6744
  .filter(function (field) { return !!field; });
4448
6745
  }
6746
+ function tokenizeArithmeticExpression(expression) {
6747
+ var tokens = [];
6748
+ var i = 0;
6749
+ while (i < expression.length) {
6750
+ var char = expression[i];
6751
+ if (/\s/.test(char)) {
6752
+ i += 1;
6753
+ continue;
6754
+ }
6755
+ if (/[()+\-*/]/.test(char)) {
6756
+ tokens.push(char);
6757
+ i += 1;
6758
+ continue;
6759
+ }
6760
+ if (/\d|\./.test(char)) {
6761
+ var j = i + 1;
6762
+ while (j < expression.length && /[\d.]/.test(expression[j])) {
6763
+ j += 1;
6764
+ }
6765
+ tokens.push(expression.slice(i, j));
6766
+ i = j;
6767
+ continue;
6768
+ }
6769
+ return null;
6770
+ }
6771
+ return tokens;
6772
+ }
6773
+ function evaluateArithmeticExpression(expression) {
6774
+ var e_16, _a, e_17, _b;
6775
+ var tokens = tokenizeArithmeticExpression(expression);
6776
+ if (!tokens || !tokens.length) {
6777
+ return null;
6778
+ }
6779
+ var output = [];
6780
+ var ops = [];
6781
+ var precedence = { '+': 1, '-': 1, '*': 2, '/': 2 };
6782
+ var prevToken = '';
6783
+ var pushOperator = function (op) {
6784
+ while (ops.length) {
6785
+ var top_1 = ops[ops.length - 1];
6786
+ if (top_1 === '(') {
6787
+ break;
6788
+ }
6789
+ if ((precedence[top_1] || 0) >= (precedence[op] || 0)) {
6790
+ output.push(ops.pop());
6791
+ continue;
6792
+ }
6793
+ break;
6794
+ }
6795
+ ops.push(op);
6796
+ };
6797
+ try {
6798
+ for (var tokens_1 = __values(tokens), tokens_1_1 = tokens_1.next(); !tokens_1_1.done; tokens_1_1 = tokens_1.next()) {
6799
+ var token = tokens_1_1.value;
6800
+ if (token === '(') {
6801
+ ops.push(token);
6802
+ prevToken = token;
6803
+ continue;
6804
+ }
6805
+ if (token === ')') {
6806
+ while (ops.length && ops[ops.length - 1] !== '(') {
6807
+ output.push(ops.pop());
6808
+ }
6809
+ if (!ops.length) {
6810
+ return null;
6811
+ }
6812
+ ops.pop();
6813
+ prevToken = token;
6814
+ continue;
6815
+ }
6816
+ if (precedence[token]) {
6817
+ if (!prevToken || prevToken === '(' || precedence[prevToken]) {
6818
+ output.push('0');
6819
+ }
6820
+ pushOperator(token);
6821
+ prevToken = token;
6822
+ continue;
6823
+ }
6824
+ if (!/^\d+(\.\d+)?$/.test(token)) {
6825
+ return null;
6826
+ }
6827
+ output.push(token);
6828
+ prevToken = token;
6829
+ }
6830
+ }
6831
+ catch (e_16_1) { e_16 = { error: e_16_1 }; }
6832
+ finally {
6833
+ try {
6834
+ if (tokens_1_1 && !tokens_1_1.done && (_a = tokens_1.return)) _a.call(tokens_1);
6835
+ }
6836
+ finally { if (e_16) throw e_16.error; }
6837
+ }
6838
+ while (ops.length) {
6839
+ var op = ops.pop();
6840
+ if (op === '(' || op === ')') {
6841
+ return null;
6842
+ }
6843
+ output.push(op);
6844
+ }
6845
+ var stack = [];
6846
+ try {
6847
+ for (var output_1 = __values(output), output_1_1 = output_1.next(); !output_1_1.done; output_1_1 = output_1.next()) {
6848
+ var token = output_1_1.value;
6849
+ if (precedence[token]) {
6850
+ if (stack.length < 2) {
6851
+ return null;
6852
+ }
6853
+ var b = stack.pop();
6854
+ var a = stack.pop();
6855
+ switch (token) {
6856
+ case '+':
6857
+ stack.push(a + b);
6858
+ break;
6859
+ case '-':
6860
+ stack.push(a - b);
6861
+ break;
6862
+ case '*':
6863
+ stack.push(a * b);
6864
+ break;
6865
+ case '/':
6866
+ stack.push(a / b);
6867
+ break;
6868
+ default:
6869
+ return null;
6870
+ }
6871
+ continue;
6872
+ }
6873
+ stack.push(Number(token));
6874
+ }
6875
+ }
6876
+ catch (e_17_1) { e_17 = { error: e_17_1 }; }
6877
+ finally {
6878
+ try {
6879
+ if (output_1_1 && !output_1_1.done && (_b = output_1.return)) _b.call(output_1);
6880
+ }
6881
+ finally { if (e_17) throw e_17.error; }
6882
+ }
6883
+ if (stack.length !== 1 || Number.isNaN(stack[0])) {
6884
+ return null;
6885
+ }
6886
+ return stack[0];
6887
+ }
6888
+ function resolveDateExpression(expression) {
6889
+ var trimmed = String(expression || '').trim();
6890
+ if (!trimmed) {
6891
+ return null;
6892
+ }
6893
+ var quotedMatch = trimmed.match(/^['"](.+?)['"]$/);
6894
+ if (quotedMatch) {
6895
+ var date = new Date(quotedMatch[1]);
6896
+ return Number.isNaN(date.getTime()) ? null : date.toISOString();
6897
+ }
6898
+ if (trimmed === 'Date.now()') {
6899
+ return new Date(Date.now()).toISOString();
6900
+ }
6901
+ var nowMatch = trimmed.match(/^Date\.now\(\)\s*([+-])\s*(.+)$/);
6902
+ if (nowMatch) {
6903
+ var delta = evaluateArithmeticExpression(nowMatch[2]);
6904
+ if (delta === null) {
6905
+ return null;
6906
+ }
6907
+ var base = Date.now();
6908
+ var computed = nowMatch[1] === '-' ? base - delta : base + delta;
6909
+ return new Date(computed).toISOString();
6910
+ }
6911
+ var numeric = evaluateArithmeticExpression(trimmed);
6912
+ if (numeric !== null) {
6913
+ var date = new Date(numeric);
6914
+ return Number.isNaN(date.getTime()) ? null : date.toISOString();
6915
+ }
6916
+ return null;
6917
+ }
6918
+ function replaceNewDateExpressions(input) {
6919
+ var output = '';
6920
+ var index = 0;
6921
+ while (index < input.length) {
6922
+ var start = input.indexOf('new Date(', index);
6923
+ if (start === -1) {
6924
+ output += input.slice(index);
6925
+ break;
6926
+ }
6927
+ output += input.slice(index, start);
6928
+ var cursor = start + 'new Date('.length;
6929
+ var depth = 1;
6930
+ while (cursor < input.length && depth > 0) {
6931
+ var char = input[cursor];
6932
+ if (char === '(') {
6933
+ depth += 1;
6934
+ }
6935
+ else if (char === ')') {
6936
+ depth -= 1;
6937
+ }
6938
+ cursor += 1;
6939
+ }
6940
+ if (depth !== 0) {
6941
+ output += input.slice(start);
6942
+ break;
6943
+ }
6944
+ var inner = input.slice(start + 'new Date('.length, cursor - 1);
6945
+ var iso = resolveDateExpression(inner);
6946
+ if (iso) {
6947
+ output += "{\"$date\":\"".concat(iso, "\"}");
6948
+ }
6949
+ else {
6950
+ output += input.slice(start, cursor);
6951
+ }
6952
+ index = cursor;
6953
+ }
6954
+ return output;
6955
+ }
6956
+ function replaceIsoDateExpressions(input) {
6957
+ return input.replace(/ISODate\(([^)]+)\)/g, function (_match, inner) {
6958
+ var iso = resolveDateExpression(inner);
6959
+ return iso ? "{\"$date\":\"".concat(iso, "\"}") : _match;
6960
+ });
6961
+ }
6962
+ function preprocessJsonLike(content) {
6963
+ var normalized = content;
6964
+ normalized = replaceNewDateExpressions(normalized);
6965
+ normalized = replaceIsoDateExpressions(normalized);
6966
+ return normalized;
6967
+ }
6968
+ function convertExtendedDates(value) {
6969
+ if (Array.isArray(value)) {
6970
+ return value.map(function (entry) { return convertExtendedDates(entry); });
6971
+ }
6972
+ if (!value || typeof value !== 'object') {
6973
+ return value;
6974
+ }
6975
+ var keys = Object.keys(value);
6976
+ if (keys.length === 1 && keys[0] === '$date') {
6977
+ var raw = value.$date;
6978
+ var date = new Date(raw);
6979
+ return Number.isNaN(date.getTime()) ? value : date;
6980
+ }
6981
+ var output = {};
6982
+ keys.forEach(function (key) {
6983
+ output[key] = convertExtendedDates(value[key]);
6984
+ });
6985
+ return output;
6986
+ }
4449
6987
  function parseJsonObject(content) {
4450
6988
  if (!content || typeof content !== 'string') {
4451
6989
  return null;
4452
6990
  }
6991
+ var normalized = preprocessJsonLike(content);
4453
6992
  try {
4454
- return JSON.parse(content);
6993
+ return convertExtendedDates(JSON.parse(normalized));
4455
6994
  }
4456
6995
  catch (_a) {
4457
- var match = content.match(/\{[\s\S]*\}/);
6996
+ var match = normalized.match(/\{[\s\S]*\}/);
4458
6997
  if (!match) {
4459
6998
  return null;
4460
6999
  }
4461
7000
  try {
4462
- return JSON.parse(match[0]);
7001
+ return convertExtendedDates(JSON.parse(match[0]));
4463
7002
  }
4464
7003
  catch (_b) {
4465
7004
  return null;
@@ -4523,8 +7062,8 @@ function handleCodexUpload(id_conversation, file_name, content_base64, size, con
4523
7062
  }
4524
7063
  function readAttachmentContents(attachments) {
4525
7064
  return __awaiter(this, void 0, void 0, function () {
4526
- var limits, totalBytes, totalChars, chunks, cleaned, attachments_1, attachments_1_1, attachment, localPath, safe, stat, ext, name_1, type, readable, content, _a, e_10_1;
4527
- var e_10, _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;
4528
7067
  return __generator(this, function (_c) {
4529
7068
  switch (_c.label) {
4530
7069
  case 0:
@@ -4603,14 +7142,14 @@ function readAttachmentContents(attachments) {
4603
7142
  return [3 /*break*/, 2];
4604
7143
  case 10: return [3 /*break*/, 13];
4605
7144
  case 11:
4606
- e_10_1 = _c.sent();
4607
- e_10 = { error: e_10_1 };
7145
+ e_18_1 = _c.sent();
7146
+ e_18 = { error: e_18_1 };
4608
7147
  return [3 /*break*/, 13];
4609
7148
  case 12:
4610
7149
  try {
4611
7150
  if (attachments_1_1 && !attachments_1_1.done && (_b = attachments_1.return)) _b.call(attachments_1);
4612
7151
  }
4613
- finally { if (e_10) throw e_10.error; }
7152
+ finally { if (e_18) throw e_18.error; }
4614
7153
  return [7 /*endfinally*/];
4615
7154
  case 13: return [2 /*return*/, {
4616
7155
  promptText: chunks.length ? "\n\nAttachments:\n".concat(chunks.join('\n\n')) : '',
@@ -4787,7 +7326,7 @@ function estimateUsage(messages, responseText, model) {
4787
7326
  };
4788
7327
  }
4789
7328
  function evaluateGuardrails(message) {
4790
- var e_11, _a;
7329
+ var e_19, _a;
4791
7330
  var normalized = String(message || '').toLowerCase();
4792
7331
  var patterns = [
4793
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.' },
@@ -4809,12 +7348,12 @@ function evaluateGuardrails(message) {
4809
7348
  }
4810
7349
  }
4811
7350
  }
4812
- catch (e_11_1) { e_11 = { error: e_11_1 }; }
7351
+ catch (e_19_1) { e_19 = { error: e_19_1 }; }
4813
7352
  finally {
4814
7353
  try {
4815
7354
  if (patterns_2_1 && !patterns_2_1.done && (_a = patterns_2.return)) _a.call(patterns_2);
4816
7355
  }
4817
- finally { if (e_11) throw e_11.error; }
7356
+ finally { if (e_19) throw e_19.error; }
4818
7357
  }
4819
7358
  return null;
4820
7359
  }