@resolveio/server-lib 22.0.5 → 22.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -114,6 +114,7 @@ exports.serializeMongoValue = serializeMongoValue;
114
114
  exports.flattenForTable = flattenForTable;
115
115
  exports.buildDisplayTable = buildDisplayTable;
116
116
  exports.formatDisplayTableMarkdown = formatDisplayTableMarkdown;
117
+ exports.rewriteMatchExpressionsToExpr = rewriteMatchExpressionsToExpr;
117
118
  exports.stripQueryFieldPathsDeep = stripQueryFieldPathsDeep;
118
119
  exports.stripScopedFieldsFromPipeline = stripScopedFieldsFromPipeline;
119
120
  exports.rewriteEmbeddedMatchObjects = rewriteEmbeddedMatchObjects;
@@ -161,6 +162,8 @@ var AI_ASSISTANT_ID_LOOKUP_CANDIDATE_LIMIT = 4;
161
162
  var AI_ASSISTANT_NAME_MATCH_FALLBACK_MAX_FIELDS = 12;
162
163
  var AI_ASSISTANT_CONTEXT_MAX_COLLECTIONS = 3;
163
164
  var AI_ASSISTANT_CONTEXT_MAX_FIELDS_PER_COLLECTION = 24;
165
+ var AI_ASSISTANT_PLANNER_MAX_ROUTES = 200;
166
+ var AI_ASSISTANT_PLANNER_DEBUG_MAX_CHARS = 2000;
164
167
  var AI_ASSISTANT_LOCALE = 'en-US';
165
168
  var AI_ASSISTANT_CURRENCY_CODE = 'USD';
166
169
  var AI_ASSISTANT_PROGRESS_TICKS = [
@@ -449,6 +452,153 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
449
452
  '- If a data question returns zero results, verify the collection/date field with a tiny read (limit 1-5) or a date field fallback before concluding there is no data.',
450
453
  '- Keep responses concise and use the configured reasoning effort level (default low).'
451
454
  ].join('\n');
455
+ var AI_ASSISTANT_PLANNER_SYSTEM_PROMPT = [
456
+ 'You are ResolveIO Assistant Planner. Your job is to produce a permissions-aware execution plan for the user\'s request.',
457
+ '',
458
+ 'HARD RULES (must follow):',
459
+ '1) PERMISSIONS FIRST: Determine access tier before planning anything.',
460
+ ' - If user.roles.super_admin === true: tier = "super_admin" (full access).',
461
+ ' - Else if user.other.id_customer exists (non-empty): tier = "customer_portal" (restrict to that customer\'s data + their views).',
462
+ ' - Else: tier = "client_user" (restrict to their views; client-scoped data).',
463
+ '',
464
+ '2) NEVER suggest pages/routes the user cannot access.',
465
+ ' - Only recommend routes that match their allowed views.',
466
+ ' - If route inventory is provided (KnownRoutes), choose from it. Do not invent new routes.',
467
+ ' - If no allowed route exists, propose the closest allowed route OR tell them they need access.',
468
+ '',
469
+ '3) DATA ACCESS MUST MATCH PERMISSIONS:',
470
+ ' - super_admin: no scope restriction required.',
471
+ ' - customer_portal: apply customer scope (id_customer or other.id_customer) to all data plans.',
472
+ ' - client_user: apply client scope (id_client) to all data plans.',
473
+ ' - Never propose querying blocked/sensitive collections if the user lacks permission.',
474
+ '',
475
+ '4) PERMISSION MATCHING:',
476
+ ' - Do NOT hardcode invoice access to "/report/invoice".',
477
+ ' - For invoice-related data or navigation, permission is satisfied if ANY user view contains "invoice" case-insensitive.',
478
+ ' (General rule: for an entity token X, permission is satisfied if any view contains X case-insensitive.)',
479
+ ' - If permission checks are ambiguous, choose the safest restriction and explain.',
480
+ '',
481
+ '5) CLASSIFY THE REQUEST:',
482
+ ' - type = "navigation" if user asks how/where to do something in the app.',
483
+ ' - type = "data" if user asks for totals, lists, breakdowns, counts, reports, "last N", "by month", etc.',
484
+ ' - type = "program_explain" if user asks how the system works (features/process).',
485
+ ' - type = "mixed" if both navigation + data are clearly requested.',
486
+ '',
487
+ '6) OUTPUT FORMAT:',
488
+ ' - Return ONLY a single JSON object (no markdown, no extra text).',
489
+ ' - The JSON must match the schema provided in the user prompt.',
490
+ ' - Be explicit and actionable. Prefer more guidance over less.',
491
+ ' - If data is requested: output a dataPlan but DO NOT write a raw Mongo pipeline. Your output is a QueryPlan that a deterministic builder will convert.',
492
+ '',
493
+ '7) USER-TONE PLANNING:',
494
+ ' - If user name is available, personalize greeting.',
495
+ ' - If group names are available, reference them in the plan (e.g., "Drivers group").',
496
+ ' - Always propose next steps from where they are (currentRoute if provided).',
497
+ ' - End plan with 1-2 engaging follow-up questions the assistant can ask the user.',
498
+ '',
499
+ '8) DO NOT run shell commands or read repo files in this planning step. Use only the provided context.'
500
+ ].join('\n');
501
+ var AI_ASSISTANT_PLANNER_USER_PROMPT_TEMPLATE = [
502
+ 'You MUST return JSON only, matching this schema:',
503
+ '',
504
+ '{',
505
+ ' "access": {',
506
+ ' "tier": "super_admin" | "customer_portal" | "client_user",',
507
+ ' "isSuperAdmin": boolean,',
508
+ ' "customerId": string | null,',
509
+ ' "clientId": string | null,',
510
+ ' "userDisplayName": string | null,',
511
+ ' "groupNames": string[],',
512
+ ' "allowedViews": string[],',
513
+ ' "permissionRules": {',
514
+ ' "entityPermissionMatch": "views_contains_token_case_insensitive",',
515
+ ' "invoicePermissionRegex": "invoice"',
516
+ ' }',
517
+ ' },',
518
+ ' "intent": {',
519
+ ' "type": "navigation" | "data" | "program_explain" | "mixed",',
520
+ ' "summary": string,',
521
+ ' "confidence": number',
522
+ ' },',
523
+ ' "navigationPlan": {',
524
+ ' "startingRoute": string | null,',
525
+ ' "recommendedRoutes": Array<{',
526
+ ' "route": string,',
527
+ ' "reason": string,',
528
+ ' "requiresViewToken": string',
529
+ ' }>,',
530
+ ' "stepByStep": string[],',
531
+ ' "deepLinks": Array<{',
532
+ ' "label": string,',
533
+ ' "route": string,',
534
+ ' "reason": string',
535
+ ' }>',
536
+ ' },',
537
+ ' "dataPlan": {',
538
+ ' "shouldFetchData": boolean,',
539
+ ' "permissionCheck": {',
540
+ ' "requiredViewToken": string | null,',
541
+ ' "allowed": boolean,',
542
+ ' "reason": string',
543
+ ' },',
544
+ ' "entity": string | null,',
545
+ ' "metric": string | null,',
546
+ ' "timeRange": {',
547
+ ' "type": "last_n_months" | "custom" | "all_time" | null,',
548
+ ' "n": number | null,',
549
+ ' "startDateISO": string | null,',
550
+ ' "endDateISO": string | null,',
551
+ ' "grain": "day" | "week" | "month" | "quarter" | null',
552
+ ' },',
553
+ ' "scoping": {',
554
+ ' "applyClientScope": boolean,',
555
+ ' "applyCustomerScope": boolean,',
556
+ ' "customerScopeField": "id_customer" | "other.id_customer" | null,',
557
+ ' "clientScopeField": "id_client" | null',
558
+ ' },',
559
+ ' "queryPlan": {',
560
+ ' "preferredCollections": string[],',
561
+ ' "fallbackCollections": string[],',
562
+ ' "dateFieldPreferences": string[],',
563
+ ' "amountFieldPreferences": string[],',
564
+ ' "statusStrategy": "none" | "paid_like" | "open_like" | "closed_like",',
565
+ ' "groupBy": string | null,',
566
+ ' "sort": string | null,',
567
+ ' "limit": number | null',
568
+ ' },',
569
+ ' "validationChecklist": string[]',
570
+ ' },',
571
+ ' "assistantResponsePlan": {',
572
+ ' "greeting": string,',
573
+ ' "whatINeedToSayFirst": string,',
574
+ ' "responseMustInclude": string[],',
575
+ ' "followUpQuestions": string[]',
576
+ ' }',
577
+ '}',
578
+ '',
579
+ 'Now produce a plan for the following request + context.',
580
+ '',
581
+ 'Today (ISO): {{today_iso}}',
582
+ 'User request: {{user_message}}',
583
+ '',
584
+ 'Current route (may be null): {{current_route}}',
585
+ 'Known routes (may be empty): {{known_routes_json_array}}',
586
+ '',
587
+ 'User object (sanitized): {{user_json}}',
588
+ 'Notes:',
589
+ '- user.roles.super_admin may exist',
590
+ '- user.roles.groups may include { name, views: [] }',
591
+ '- user.roles.miscs may include views strings',
592
+ '- user.other.id_customer may exist for customer portal users',
593
+ '',
594
+ 'Collection hints (may be empty): {{collection_hints_json_array}}',
595
+ 'Field hints (may be empty): {{field_hints_json_array}}',
596
+ '',
597
+ 'Important:',
598
+ '- If invoice-related, permission is satisfied if ANY allowed view contains "invoice" case-insensitive.',
599
+ '- Do not output raw Mongo pipelines. Output a QueryPlan + validation checklist only.',
600
+ '- Navigation steps must only reference routes that match allowed views (or known routes if provided).'
601
+ ].join('\n');
452
602
  var AI_FORM_PATCH_SYSTEM_PROMPT = [
453
603
  'You are the ResolveIO form patch assistant.',
454
604
  '- Your job is to map the user request to the provided form fields.',
@@ -1196,10 +1346,10 @@ function executeAiAssistantCodexRun(payload, context) {
1196
1346
  insertResult = _d.sent();
1197
1347
  assistantMessageId = (insertResult === null || insertResult === void 0 ? void 0 : insertResult._id) || (insertResult === null || insertResult === void 0 ? void 0 : insertResult.insertedId);
1198
1348
  enqueueAssistantCodexRun(function () { return __awaiter(_this, void 0, void 0, function () {
1199
- var runStart, steps, recordStep, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, dataQuestion, lastDirective, toolResponseDebug, toolError, termHints, collectionHints, fieldHints, collectionTokenization, collectionRanking, collectionSelection, collectionOverride, collectionNames, timingBreakdown, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, baseWeights, expandedWeights, dbName, db, _a, routeHints, rankedCollections, hintCollections, assistantContext, prompt_1, workspaceRoot, codexConfig, runOptions, responseText, directiveText, directive, directivePrompt, directiveStart, forcedDirective, _b, initialStart, directivePrompt, forcedStart, forcedDirective, _c, requestedCollection, cleanedResponseText, effectiveDirective, toolRequest, toolStart, toolResponse, _d, toolPayload, followupPrompt, followupStart, followupText, _e, error_2, error_3, finishedAt, finalNow, finishedAt, codexMs, draftingMs, finalMetadata, finalAssistantDoc;
1200
- var _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
1201
- return __generator(this, function (_u) {
1202
- switch (_u.label) {
1349
+ var runStart, steps, recordStep, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, dataQuestion, lastDirective, toolResponseDebug, toolError, termHints, collectionHints, fieldHints, collectionTokenization, collectionRanking, collectionSelection, collectionOverride, collectionNames, plannerEnabled, plannerOutput, plannerRaw, timingBreakdown, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, baseWeights, expandedWeights, dbName, db, _a, routeHints, rankedCollections, hintCollections, assistantContext, prompt_1, workspaceRoot, codexConfig, runOptions, plannerPrompt, plannerStart, _b, intentType, shouldFetch, responseText, directiveText, directive, directivePrompt, directiveStart, forcedDirective, _c, initialStart, directivePrompt, forcedStart, forcedDirective, _d, requestedCollection, cleanedResponseText, effectiveDirective, toolRequest, toolStart, toolResponse, _e, toolPayload, followupPrompt, followupStart, followupText, _f, error_2, error_3, finishedAt, finalNow, finishedAt, codexMs, draftingMs, finalMetadata, finalAssistantDoc;
1350
+ var _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
1351
+ return __generator(this, function (_x) {
1352
+ switch (_x.label) {
1203
1353
  case 0:
1204
1354
  runStart = Date.now();
1205
1355
  if (aiWorkerDebug) {
@@ -1240,19 +1390,23 @@ function executeAiAssistantCodexRun(payload, context) {
1240
1390
  collectionSelection = null;
1241
1391
  collectionOverride = null;
1242
1392
  collectionNames = [];
1393
+ plannerEnabled = resolveAssistantPlannerEnabled();
1394
+ plannerOutput = null;
1395
+ plannerRaw = '';
1243
1396
  timingBreakdown = {
1397
+ plannerMs: 0,
1244
1398
  directiveMs: 0,
1245
1399
  initialResponseMs: 0,
1246
1400
  forcedDirectiveMs: 0,
1247
1401
  toolMs: 0,
1248
1402
  followupMs: 0
1249
1403
  };
1250
- contextRoute = normalizeOptionalString((_f = input === null || input === void 0 ? void 0 : input.context) === null || _f === void 0 ? void 0 : _f.route);
1251
- contextMode = normalizeOptionalString((_g = input === null || input === void 0 ? void 0 : input.context) === null || _g === void 0 ? void 0 : _g.mode);
1404
+ contextRoute = normalizeOptionalString((_g = input === null || input === void 0 ? void 0 : input.context) === null || _g === void 0 ? void 0 : _g.route);
1405
+ contextMode = normalizeOptionalString((_h = input === null || input === void 0 ? void 0 : input.context) === null || _h === void 0 ? void 0 : _h.mode);
1252
1406
  recordStep('Queued', { requestId: requestId || undefined });
1253
- _u.label = 1;
1407
+ _x.label = 1;
1254
1408
  case 1:
1255
- _u.trys.push([1, 30, 31, 32]);
1409
+ _x.trys.push([1, 35, 36, 37]);
1256
1410
  hintSeed = [message, contextRoute].filter(Boolean).join(' ');
1257
1411
  termExpansion = expandAssistantTermSynonyms(hintSeed);
1258
1412
  hintText = termExpansion.expanded || hintSeed;
@@ -1273,19 +1427,19 @@ function executeAiAssistantCodexRun(payload, context) {
1273
1427
  recordStep('Planning: term expansion', {
1274
1428
  termMatches: termExpansion.matches.length ? termExpansion.matches : undefined
1275
1429
  });
1276
- _u.label = 2;
1430
+ _x.label = 2;
1277
1431
  case 2:
1278
- _u.trys.push([2, 4, , 5]);
1432
+ _x.trys.push([2, 4, , 5]);
1279
1433
  dbName = resolveAssistantDatabaseName(undefined, input.mongo);
1280
1434
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1281
1435
  return [4 /*yield*/, listAssistantCollections(db, dbName)];
1282
1436
  case 3:
1283
- collectionNames = _u.sent();
1437
+ collectionNames = _x.sent();
1284
1438
  collectionHints = resolveCollectionHintsFromTokens(expandedTokens, collectionNames, 5);
1285
1439
  collectionRanking = buildCollectionRankingDebugFromTokens(expandedTokens, collectionNames, 8);
1286
1440
  return [3 /*break*/, 5];
1287
1441
  case 4:
1288
- _a = _u.sent();
1442
+ _a = _x.sent();
1289
1443
  collectionHints = [];
1290
1444
  collectionRanking = collectionRanking || ((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens)
1291
1445
  ? buildCollectionRankingDebugFromTokens(collectionTokenization.expandedTokens || [], [], 0)
@@ -1320,7 +1474,7 @@ function executeAiAssistantCodexRun(payload, context) {
1320
1474
  prompt_1 = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1321
1475
  return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
1322
1476
  case 6:
1323
- workspaceRoot = _u.sent();
1477
+ workspaceRoot = _x.sent();
1324
1478
  codexConfig = resolveCodexSettings();
1325
1479
  runOptions = {
1326
1480
  timeoutMs: resolveCodexTimeoutMs(),
@@ -1335,95 +1489,132 @@ function executeAiAssistantCodexRun(payload, context) {
1335
1489
  approvalPolicy: 'never'
1336
1490
  }
1337
1491
  };
1492
+ if (!plannerEnabled) return [3 /*break*/, 11];
1493
+ recordStep('Planning: planner prompt');
1494
+ plannerPrompt = buildAssistantPlannerPrompt({
1495
+ message: message,
1496
+ attachmentText: attachmentData.promptText,
1497
+ contextRoute: contextRoute,
1498
+ knownRoutes: resolveAssistantPlannerKnownRoutes(),
1499
+ user: user,
1500
+ collectionHints: collectionHints,
1501
+ fieldHints: fieldHints,
1502
+ inputClientId: input.id_client
1503
+ });
1504
+ _x.label = 7;
1505
+ case 7:
1506
+ _x.trys.push([7, 9, , 10]);
1507
+ plannerStart = Date.now();
1508
+ return [4 /*yield*/, runCodexInWorkerThread(plannerPrompt, runOptions, codexConfig, streamProgress)];
1509
+ case 8:
1510
+ plannerRaw = _x.sent();
1511
+ timingBreakdown.plannerMs = Date.now() - plannerStart;
1512
+ plannerOutput = parseJsonObject(plannerRaw);
1513
+ recordStep('Planning: planner result', { parsed: !!plannerOutput });
1514
+ return [3 /*break*/, 10];
1515
+ case 9:
1516
+ _b = _x.sent();
1517
+ recordStep('Planning: planner result', { parsed: false });
1518
+ return [3 /*break*/, 10];
1519
+ case 10:
1520
+ if (plannerOutput) {
1521
+ intentType = normalizeOptionalString((_j = plannerOutput === null || plannerOutput === void 0 ? void 0 : plannerOutput.intent) === null || _j === void 0 ? void 0 : _j.type).toLowerCase();
1522
+ shouldFetch = ((_k = plannerOutput === null || plannerOutput === void 0 ? void 0 : plannerOutput.dataPlan) === null || _k === void 0 ? void 0 : _k.shouldFetchData) === true;
1523
+ if (shouldFetch || intentType === 'data' || intentType === 'mixed') {
1524
+ dataQuestion = true;
1525
+ }
1526
+ }
1527
+ _x.label = 11;
1528
+ case 11:
1338
1529
  responseText = '';
1339
1530
  directiveText = '';
1340
1531
  directive = null;
1341
- if (!dataQuestion) return [3 /*break*/, 10];
1532
+ if (!dataQuestion) return [3 /*break*/, 15];
1342
1533
  recordStep('Directive: determine tool', { type: 'data-question' });
1343
1534
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1344
- _u.label = 7;
1345
- case 7:
1346
- _u.trys.push([7, 9, , 10]);
1535
+ _x.label = 12;
1536
+ case 12:
1537
+ _x.trys.push([12, 14, , 15]);
1347
1538
  directiveStart = Date.now();
1348
1539
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1349
- case 8:
1350
- directiveText = _u.sent();
1540
+ case 13:
1541
+ directiveText = _x.sent();
1351
1542
  timingBreakdown.directiveMs = Date.now() - directiveStart;
1352
1543
  forcedDirective = extractAssistantMongoDirective(directiveText);
1353
1544
  if (forcedDirective) {
1354
1545
  directive = forcedDirective;
1355
1546
  directiveSource = 'model';
1356
1547
  lastDirective = forcedDirective;
1357
- collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_h = directive.payload) === null || _h === void 0 ? void 0 : _h.collection) || '');
1548
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_l = directive.payload) === null || _l === void 0 ? void 0 : _l.collection) || '');
1358
1549
  recordStep('Directive resolved', {
1359
1550
  source: directiveSource,
1360
1551
  type: directive.type,
1361
- collection: normalizeOptionalString((_j = directive.payload) === null || _j === void 0 ? void 0 : _j.collection) || undefined,
1362
- permissionView: normalizeOptionalString((_k = directive.payload) === null || _k === void 0 ? void 0 : _k.permissionView) || undefined
1552
+ collection: normalizeOptionalString((_m = directive.payload) === null || _m === void 0 ? void 0 : _m.collection) || undefined,
1553
+ permissionView: normalizeOptionalString((_o = directive.payload) === null || _o === void 0 ? void 0 : _o.permissionView) || undefined
1363
1554
  });
1364
1555
  }
1365
- return [3 /*break*/, 10];
1366
- case 9:
1367
- _b = _u.sent();
1368
- return [3 /*break*/, 10];
1369
- case 10:
1370
- if (!!directive) return [3 /*break*/, 12];
1556
+ return [3 /*break*/, 15];
1557
+ case 14:
1558
+ _c = _x.sent();
1559
+ return [3 /*break*/, 15];
1560
+ case 15:
1561
+ if (!!directive) return [3 /*break*/, 17];
1371
1562
  recordStep('Response: draft initial answer', { mode: 'full' });
1372
1563
  initialStart = Date.now();
1373
1564
  return [4 /*yield*/, runCodexInWorkerThread(prompt_1, runOptions, codexConfig, streamProgress)];
1374
- case 11:
1375
- responseText = _u.sent();
1565
+ case 16:
1566
+ responseText = _x.sent();
1376
1567
  timingBreakdown.initialResponseMs = Date.now() - initialStart;
1377
1568
  directive = extractAssistantMongoDirective(responseText);
1378
1569
  if (directive) {
1379
1570
  directiveSource = 'model';
1380
1571
  lastDirective = directive;
1381
- collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_l = directive.payload) === null || _l === void 0 ? void 0 : _l.collection) || '');
1572
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_p = directive.payload) === null || _p === void 0 ? void 0 : _p.collection) || '');
1382
1573
  recordStep('Directive resolved', {
1383
1574
  source: directiveSource,
1384
1575
  type: directive.type,
1385
- collection: normalizeOptionalString((_m = directive.payload) === null || _m === void 0 ? void 0 : _m.collection) || undefined,
1386
- permissionView: normalizeOptionalString((_o = directive.payload) === null || _o === void 0 ? void 0 : _o.permissionView) || undefined
1576
+ collection: normalizeOptionalString((_q = directive.payload) === null || _q === void 0 ? void 0 : _q.collection) || undefined,
1577
+ permissionView: normalizeOptionalString((_r = directive.payload) === null || _r === void 0 ? void 0 : _r.permissionView) || undefined
1387
1578
  });
1388
1579
  }
1389
- _u.label = 12;
1390
- case 12:
1391
- if (!(!directive && dataQuestion)) return [3 /*break*/, 16];
1580
+ _x.label = 17;
1581
+ case 17:
1582
+ if (!(!directive && dataQuestion)) return [3 /*break*/, 21];
1392
1583
  recordStep('Directive: forced retry', { mode: 'directive-only' });
1393
1584
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1394
- _u.label = 13;
1395
- case 13:
1396
- _u.trys.push([13, 15, , 16]);
1585
+ _x.label = 18;
1586
+ case 18:
1587
+ _x.trys.push([18, 20, , 21]);
1397
1588
  forcedStart = Date.now();
1398
1589
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1399
- case 14:
1400
- directiveText = _u.sent();
1590
+ case 19:
1591
+ directiveText = _x.sent();
1401
1592
  timingBreakdown.forcedDirectiveMs = Date.now() - forcedStart;
1402
1593
  forcedDirective = extractAssistantMongoDirective(directiveText);
1403
1594
  if (forcedDirective) {
1404
1595
  directive = forcedDirective;
1405
1596
  directiveSource = 'forced';
1406
1597
  lastDirective = forcedDirective;
1407
- collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_p = directive.payload) === null || _p === void 0 ? void 0 : _p.collection) || '');
1598
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_s = directive.payload) === null || _s === void 0 ? void 0 : _s.collection) || '');
1408
1599
  recordStep('Directive resolved', {
1409
1600
  source: directiveSource,
1410
1601
  type: directive.type,
1411
- collection: normalizeOptionalString((_q = directive.payload) === null || _q === void 0 ? void 0 : _q.collection) || undefined,
1412
- permissionView: normalizeOptionalString((_r = directive.payload) === null || _r === void 0 ? void 0 : _r.permissionView) || undefined
1602
+ collection: normalizeOptionalString((_t = directive.payload) === null || _t === void 0 ? void 0 : _t.collection) || undefined,
1603
+ permissionView: normalizeOptionalString((_u = directive.payload) === null || _u === void 0 ? void 0 : _u.permissionView) || undefined
1413
1604
  });
1414
1605
  }
1415
- return [3 /*break*/, 16];
1416
- case 15:
1417
- _c = _u.sent();
1418
- return [3 /*break*/, 16];
1419
- case 16:
1606
+ return [3 /*break*/, 21];
1607
+ case 20:
1608
+ _d = _x.sent();
1609
+ return [3 /*break*/, 21];
1610
+ case 21:
1420
1611
  if (directive) {
1421
- requestedCollection = normalizeOptionalString((_s = directive.payload) === null || _s === void 0 ? void 0 : _s.collection);
1612
+ requestedCollection = normalizeOptionalString((_v = directive.payload) === null || _v === void 0 ? void 0 : _v.collection);
1422
1613
  collectionOverride = resolveCollectionOverrideWithContext({
1423
1614
  message: message,
1424
1615
  collectionRanking: collectionRanking,
1425
1616
  requestedCollection: requestedCollection,
1426
- permissionView: normalizeOptionalString((_t = directive.payload) === null || _t === void 0 ? void 0 : _t.permissionView) || contextRoute,
1617
+ permissionView: normalizeOptionalString((_w = directive.payload) === null || _w === void 0 ? void 0 : _w.permissionView) || contextRoute,
1427
1618
  collectionNames: collectionNames
1428
1619
  });
1429
1620
  if (collectionOverride) {
@@ -1439,7 +1630,7 @@ function executeAiAssistantCodexRun(payload, context) {
1439
1630
  if (cleanedResponseText) {
1440
1631
  assistantContent = sanitizeAssistantResponse(cleanedResponseText);
1441
1632
  }
1442
- if (!((directive === null || directive === void 0 ? void 0 : directive.payload) && AI_ASSISTANT_TOOL_MAX_STEPS > 0)) return [3 /*break*/, 28];
1633
+ if (!((directive === null || directive === void 0 ? void 0 : directive.payload) && AI_ASSISTANT_TOOL_MAX_STEPS > 0)) return [3 /*break*/, 33];
1443
1634
  effectiveDirective = collectionOverride
1444
1635
  ? __assign(__assign({}, directive), { payload: __assign(__assign({}, (directive.payload || {})), { collection: collectionOverride.to }) }) : directive;
1445
1636
  toolRequest = buildAssistantToolRequest(effectiveDirective, input);
@@ -1449,21 +1640,21 @@ function executeAiAssistantCodexRun(payload, context) {
1449
1640
  collection: normalizeOptionalString(toolRequest === null || toolRequest === void 0 ? void 0 : toolRequest.collection) || undefined,
1450
1641
  permissionView: normalizeOptionalString(toolRequest === null || toolRequest === void 0 ? void 0 : toolRequest.permissionView) || undefined
1451
1642
  });
1452
- _u.label = 17;
1453
- case 17:
1454
- _u.trys.push([17, 26, , 27]);
1643
+ _x.label = 22;
1644
+ case 22:
1645
+ _x.trys.push([22, 31, , 32]);
1455
1646
  toolStart = Date.now();
1456
- if (!(effectiveDirective.type === 'aggregate')) return [3 /*break*/, 19];
1647
+ if (!(effectiveDirective.type === 'aggregate')) return [3 /*break*/, 24];
1457
1648
  return [4 /*yield*/, executeAiAssistantMongoAggregate(toolRequest, context)];
1458
- case 18:
1459
- _d = _u.sent();
1460
- return [3 /*break*/, 21];
1461
- case 19: return [4 /*yield*/, executeAiAssistantMongoRead(toolRequest, context)];
1462
- case 20:
1463
- _d = _u.sent();
1464
- _u.label = 21;
1465
- case 21:
1466
- toolResponse = _d;
1649
+ case 23:
1650
+ _e = _x.sent();
1651
+ return [3 /*break*/, 26];
1652
+ case 24: return [4 /*yield*/, executeAiAssistantMongoRead(toolRequest, context)];
1653
+ case 25:
1654
+ _e = _x.sent();
1655
+ _x.label = 26;
1656
+ case 26:
1657
+ toolResponse = _e;
1467
1658
  timingBreakdown.toolMs = Date.now() - toolStart;
1468
1659
  toolResponseDebug = (toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.debug) && typeof toolResponse.debug === 'object'
1469
1660
  ? toolResponse.debug
@@ -1478,42 +1669,42 @@ function executeAiAssistantCodexRun(payload, context) {
1478
1669
  progressTracker.push('Drafting response');
1479
1670
  recordStep('Drafting response');
1480
1671
  followupPrompt = buildAssistantCodexToolFollowupPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, toolPayload.prompt);
1481
- _u.label = 22;
1482
- case 22:
1483
- _u.trys.push([22, 24, , 25]);
1672
+ _x.label = 27;
1673
+ case 27:
1674
+ _x.trys.push([27, 29, , 30]);
1484
1675
  followupStart = Date.now();
1485
1676
  return [4 /*yield*/, runCodexInWorkerThread(followupPrompt, runOptions, codexConfig, streamProgress)];
1486
- case 23:
1487
- followupText = _u.sent();
1677
+ case 28:
1678
+ followupText = _x.sent();
1488
1679
  timingBreakdown.followupMs = Date.now() - followupStart;
1489
1680
  assistantContent = sanitizeAssistantResponse(followupText);
1490
1681
  assistantContent = applyAssistantDisplayTableToResponse(assistantContent, toolPayload.result.output.display);
1491
- return [3 /*break*/, 25];
1492
- case 24:
1493
- _e = _u.sent();
1682
+ return [3 /*break*/, 30];
1683
+ case 29:
1684
+ _f = _x.sent();
1494
1685
  assistantContent = buildAssistantToolFallbackResponse(toolPayload.result);
1495
- return [3 /*break*/, 25];
1496
- case 25: return [3 /*break*/, 27];
1497
- case 26:
1498
- error_2 = _u.sent();
1686
+ return [3 /*break*/, 30];
1687
+ case 30: return [3 /*break*/, 32];
1688
+ case 31:
1689
+ error_2 = _x.sent();
1499
1690
  assistantContent = buildAssistantToolErrorMessage(error_2, directive, toolRequest);
1500
1691
  toolError = error_2;
1501
- return [3 /*break*/, 27];
1502
- case 27: return [3 /*break*/, 29];
1503
- case 28:
1692
+ return [3 /*break*/, 32];
1693
+ case 32: return [3 /*break*/, 34];
1694
+ case 33:
1504
1695
  progressTracker.push('Drafting response');
1505
1696
  recordStep('Drafting response');
1506
- _u.label = 29;
1507
- case 29: return [3 /*break*/, 32];
1508
- case 30:
1509
- error_3 = _u.sent();
1697
+ _x.label = 34;
1698
+ case 34: return [3 /*break*/, 37];
1699
+ case 35:
1700
+ error_3 = _x.sent();
1510
1701
  assistantContent = buildAssistantCodexErrorMessage(error_3);
1511
1702
  recordStep('Error', { message: normalizeOptionalString(error_3 === null || error_3 === void 0 ? void 0 : error_3.message) || 'Unknown error' });
1512
- return [3 /*break*/, 32];
1513
- case 31:
1703
+ return [3 /*break*/, 37];
1704
+ case 36:
1514
1705
  progressTracker.stop();
1515
1706
  return [7 /*endfinally*/];
1516
- case 32:
1707
+ case 37:
1517
1708
  if (!assistantContent) {
1518
1709
  assistantContent = buildAssistantCodexErrorMessage(null);
1519
1710
  }
@@ -1536,6 +1727,7 @@ function executeAiAssistantCodexRun(payload, context) {
1536
1727
  if (isSuperAdmin) {
1537
1728
  finishedAt = Date.now();
1538
1729
  codexMs = timingBreakdown.directiveMs
1730
+ + timingBreakdown.plannerMs
1539
1731
  + timingBreakdown.initialResponseMs
1540
1732
  + timingBreakdown.forcedDirectiveMs
1541
1733
  + timingBreakdown.followupMs;
@@ -1559,7 +1751,15 @@ function executeAiAssistantCodexRun(payload, context) {
1559
1751
  collectionTokenization: collectionTokenization || undefined,
1560
1752
  collectionRanking: collectionRanking || undefined,
1561
1753
  collectionSelection: collectionSelection || undefined,
1562
- collectionOverride: collectionOverride || undefined
1754
+ collectionOverride: collectionOverride || undefined,
1755
+ planner: plannerEnabled ? {
1756
+ enabled: true,
1757
+ parsed: !!plannerOutput,
1758
+ output: plannerOutput || undefined,
1759
+ raw: !plannerOutput && plannerRaw
1760
+ ? plannerRaw.slice(0, AI_ASSISTANT_PLANNER_DEBUG_MAX_CHARS)
1761
+ : undefined
1762
+ } : undefined
1563
1763
  },
1564
1764
  timings: {
1565
1765
  startedAt: new Date(runStart).toISOString(),
@@ -1568,6 +1768,7 @@ function executeAiAssistantCodexRun(payload, context) {
1568
1768
  codexMs: codexMs,
1569
1769
  draftingMs: draftingMs,
1570
1770
  toolMs: timingBreakdown.toolMs,
1771
+ plannerMs: timingBreakdown.plannerMs,
1571
1772
  directiveMs: timingBreakdown.directiveMs,
1572
1773
  initialResponseMs: timingBreakdown.initialResponseMs,
1573
1774
  forcedDirectiveMs: timingBreakdown.forcedDirectiveMs,
@@ -1578,7 +1779,7 @@ function executeAiAssistantCodexRun(payload, context) {
1578
1779
  }
1579
1780
  finalMetadata = __assign(__assign(__assign({ model: resolveCodexModel() }, (requestId ? { request_id: requestId } : {})), (toolResult ? { tool_result: toolResult } : {})), (assistantDebug ? { debug: assistantDebug } : {}));
1580
1781
  finalAssistantDoc = __assign(__assign({}, assistantDoc), { _id: assistantMessageId, content: assistantContent, metadata: finalMetadata, updatedAt: finalNow });
1581
- if (!assistantMessageId) return [3 /*break*/, 34];
1782
+ if (!assistantMessageId) return [3 /*break*/, 39];
1582
1783
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.updateOne({ _id: assistantMessageId }, {
1583
1784
  $set: {
1584
1785
  content: assistantContent,
@@ -1586,18 +1787,18 @@ function executeAiAssistantCodexRun(payload, context) {
1586
1787
  updatedAt: finalNow
1587
1788
  }
1588
1789
  })];
1589
- case 33:
1590
- _u.sent();
1591
- _u.label = 34;
1592
- case 34: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
1593
- case 35:
1594
- _u.sent();
1595
- if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 37];
1790
+ case 38:
1791
+ _x.sent();
1792
+ _x.label = 39;
1793
+ case 39: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
1794
+ case 40:
1795
+ _x.sent();
1796
+ if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 42];
1596
1797
  return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
1597
- case 36:
1598
- _u.sent();
1599
- _u.label = 37;
1600
- case 37: return [2 /*return*/, finalAssistantDoc];
1798
+ case 41:
1799
+ _x.sent();
1800
+ _x.label = 42;
1801
+ case 42: return [2 /*return*/, finalAssistantDoc];
1601
1802
  }
1602
1803
  });
1603
1804
  }); });
@@ -2074,10 +2275,10 @@ function executeAiAssistantMongoRead(payload, context) {
2074
2275
  }
2075
2276
  function executeAiAssistantMongoAggregate(payload, context) {
2076
2277
  return __awaiter(this, void 0, void 0, function () {
2077
- var input, rawCollection, dbName, db, collectionResolution, collection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, sanitizedPipeline, strippedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, dateField, aggregateOptions, documents, executedPipeline, probeDocs, fallback, fallbackPipeline, fallbackDocs, createdFallback, createdPipeline, createdDocs, expanded, expandedDocs, completionFallback, fallbackPipeline, fallbackDocs, completionExprFallback, fallbackPipeline, fallbackDocs, unwindFallback, fallbackPipeline, fallbackDocs, nameFallback, fallbackPipeline, fallbackDocs, _c, _loop_1, i, state_1, matchFields_1, _d, aliases, rewrittenPipeline, fallbackDocs, _loop_2, i, state_2, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, matchStages, diagnostics, combinedMatch, nameFields, dateFields, queryNoName, _e, queryNoDate, _f, _g, _h, _j, allCollections, base, alt, altCount, _k, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
2078
- var _l, _m;
2079
- return __generator(this, function (_o) {
2080
- switch (_o.label) {
2278
+ var input, rawCollection, dbName, db, collectionResolution, collection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, sanitizedPipeline, strippedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, dateField, aggregateOptions, documents, executedPipeline, probeDocs, fallback, fallbackPipeline, fallbackDocs, createdFallback, createdPipeline, createdDocs, expanded, expandedDocs, completionFallback, fallbackPipeline, fallbackDocs, completionExprFallback, fallbackPipeline, fallbackDocs, unwindFallback, shouldUnwind, _c, _d, fallbackPipeline, fallbackDocs, nameFallback, fallbackPipeline, fallbackDocs, _e, _loop_1, i, state_1, matchFields_1, _f, aliases, rewrittenPipeline, fallbackDocs, _loop_2, i, state_2, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, matchStages, diagnostics, combinedMatch, nameFields, dateFields, queryNoName, _g, queryNoDate, _h, _j, _k, _l, allCollections, base, alt, altCount, _m, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
2279
+ var _o, _p;
2280
+ return __generator(this, function (_q) {
2281
+ switch (_q.label) {
2081
2282
  case 0:
2082
2283
  input = payload || {};
2083
2284
  rawCollection = normalizeOptionalString(input.collection);
@@ -2088,16 +2289,16 @@ function executeAiAssistantMongoAggregate(payload, context) {
2088
2289
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
2089
2290
  return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
2090
2291
  case 1:
2091
- collectionResolution = _o.sent();
2292
+ collectionResolution = _q.sent();
2092
2293
  collection = collectionResolution.name || rawCollection;
2093
2294
  schemaFields = getCollectionSchemaFieldNames(collection);
2094
2295
  return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
2095
2296
  case 2:
2096
- _a = _o.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
2297
+ _a = _q.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
2097
2298
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
2098
2299
  throw new Error('AI assistant mongo aggregate: Access denied.');
2099
2300
  }
2100
- customerId = normalizeOptionalString((_l = user === null || user === void 0 ? void 0 : user.other) === null || _l === void 0 ? void 0 : _l.id_customer);
2301
+ customerId = normalizeOptionalString((_o = user === null || user === void 0 ? void 0 : user.other) === null || _o === void 0 ? void 0 : _o.id_customer);
2101
2302
  fallbackMeta = {};
2102
2303
  baseQuery = normalizeMongoQuery(input.query);
2103
2304
  if (!isSuperAdmin && customerId) {
@@ -2122,18 +2323,18 @@ function executeAiAssistantMongoAggregate(payload, context) {
2122
2323
  if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 4];
2123
2324
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
2124
2325
  case 3:
2125
- _b = _o.sent();
2326
+ _b = _q.sent();
2126
2327
  return [3 /*break*/, 5];
2127
2328
  case 4:
2128
2329
  _b = false;
2129
- _o.label = 5;
2330
+ _q.label = 5;
2130
2331
  case 5:
2131
2332
  shouldScopeByClient = _b;
2132
2333
  clientScopedQuery = shouldScopeByClient
2133
2334
  ? applyClientScopeFilter(baseQuery, normalizedClient, isSuperAdmin)
2134
2335
  : baseQuery;
2135
2336
  scopedQuery = applyCustomerScopeFilter(clientScopedQuery, collection, customerId, isSuperAdmin);
2136
- normalizedPipeline = normalizeAssistantAggregatePipeline(input.pipeline);
2337
+ normalizedPipeline = normalizeAssistantAggregatePipeline(input.pipeline, collection);
2137
2338
  sanitizedPipeline = normalizedPipeline;
2138
2339
  if (!isSuperAdmin && customerId) {
2139
2340
  strippedPipeline = stripScopedFieldsFromPipelineWithMeta(normalizedPipeline, ['id_customer', 'other.id_customer']);
@@ -2156,7 +2357,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
2156
2357
  .aggregate(limitedPipeline, aggregateOptions)
2157
2358
  .toArray()];
2158
2359
  case 6:
2159
- documents = _o.sent();
2360
+ documents = _q.sent();
2160
2361
  executedPipeline = limitedPipeline;
2161
2362
  probeDocs = null;
2162
2363
  if (!(!documents.length && dateField)) return [3 /*break*/, 10];
@@ -2169,13 +2370,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2169
2370
  .aggregate(fallbackPipeline, aggregateOptions)
2170
2371
  .toArray()];
2171
2372
  case 7:
2172
- fallbackDocs = _o.sent();
2373
+ fallbackDocs = _q.sent();
2173
2374
  if (fallbackDocs.length) {
2174
2375
  documents = fallbackDocs;
2175
2376
  executedPipeline = fallbackPipeline;
2176
2377
  fallbackMeta.dateField.used = true;
2177
2378
  }
2178
- _o.label = 8;
2379
+ _q.label = 8;
2179
2380
  case 8:
2180
2381
  if (!(!documents.length && dateField !== 'createdAt')) return [3 /*break*/, 10];
2181
2382
  createdFallback = { from: dateField, to: 'createdAt', attempted: true, used: false };
@@ -2186,13 +2387,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2186
2387
  .aggregate(createdPipeline, aggregateOptions)
2187
2388
  .toArray()];
2188
2389
  case 9:
2189
- createdDocs = _o.sent();
2390
+ createdDocs = _q.sent();
2190
2391
  if (createdDocs.length) {
2191
2392
  documents = createdDocs;
2192
2393
  executedPipeline = createdPipeline;
2193
2394
  fallbackMeta.dateFieldCreatedAt.used = true;
2194
2395
  }
2195
- _o.label = 10;
2396
+ _q.label = 10;
2196
2397
  case 10:
2197
2398
  if (!!documents.length) return [3 /*break*/, 12];
2198
2399
  expanded = expandAggregateDateMatchFallback(executedPipeline);
@@ -2207,13 +2408,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2207
2408
  .aggregate(expanded.pipeline, aggregateOptions)
2208
2409
  .toArray()];
2209
2410
  case 11:
2210
- expandedDocs = _o.sent();
2411
+ expandedDocs = _q.sent();
2211
2412
  if (expandedDocs.length) {
2212
2413
  documents = expandedDocs;
2213
2414
  executedPipeline = expanded.pipeline;
2214
2415
  fallbackMeta.dateFieldsExpanded.used = true;
2215
2416
  }
2216
- _o.label = 12;
2417
+ _q.label = 12;
2217
2418
  case 12:
2218
2419
  if (!!documents.length) return [3 /*break*/, 16];
2219
2420
  completionFallback = resolveAggregateCompletionFallback(executedPipeline);
@@ -2232,13 +2433,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2232
2433
  .aggregate(fallbackPipeline, aggregateOptions)
2233
2434
  .toArray()];
2234
2435
  case 13:
2235
- fallbackDocs = _o.sent();
2436
+ fallbackDocs = _q.sent();
2236
2437
  if (fallbackDocs.length) {
2237
2438
  documents = fallbackDocs;
2238
2439
  executedPipeline = fallbackPipeline;
2239
2440
  fallbackMeta.completion.used = true;
2240
2441
  }
2241
- _o.label = 14;
2442
+ _q.label = 14;
2242
2443
  case 14:
2243
2444
  if (!!documents.length) return [3 /*break*/, 16];
2244
2445
  completionExprFallback = resolveAggregateCompletionExprFallback(executedPipeline);
@@ -2257,35 +2458,66 @@ function executeAiAssistantMongoAggregate(payload, context) {
2257
2458
  .aggregate(fallbackPipeline, aggregateOptions)
2258
2459
  .toArray()];
2259
2460
  case 15:
2260
- fallbackDocs = _o.sent();
2461
+ fallbackDocs = _q.sent();
2261
2462
  if (fallbackDocs.length) {
2262
2463
  documents = fallbackDocs;
2263
2464
  executedPipeline = fallbackPipeline;
2264
2465
  fallbackMeta.completion.used = true;
2265
2466
  }
2266
- _o.label = 16;
2467
+ _q.label = 16;
2267
2468
  case 16:
2268
- if (!(documents.length <= 1)) return [3 /*break*/, 18];
2469
+ if (!(documents.length <= 1)) return [3 /*break*/, 25];
2269
2470
  unwindFallback = resolveAggregateUnwindFallback(executedPipeline);
2270
- if (!unwindFallback) return [3 /*break*/, 18];
2471
+ if (!unwindFallback) return [3 /*break*/, 25];
2271
2472
  fallbackMeta.unwind = { path: unwindFallback.path, attempted: true, used: false };
2473
+ shouldUnwind = false;
2474
+ _q.label = 17;
2475
+ case 17:
2476
+ _q.trys.push([17, 20, , 21]);
2477
+ _c = probeDocs;
2478
+ if (_c) return [3 /*break*/, 19];
2479
+ return [4 /*yield*/, fetchAssistantProbeDocs({
2480
+ db: db,
2481
+ collection: collection,
2482
+ idClient: normalizedClient,
2483
+ idCustomer: customerId,
2484
+ isSuperAdmin: isSuperAdmin,
2485
+ includeClientScope: shouldScopeByClient
2486
+ })];
2487
+ case 18:
2488
+ _c = (_q.sent());
2489
+ _q.label = 19;
2490
+ case 19:
2491
+ probeDocs = _c;
2492
+ shouldUnwind = probeDocs.length ? hasArrayValueAtPath(probeDocs, unwindFallback.path) : false;
2493
+ return [3 /*break*/, 21];
2494
+ case 20:
2495
+ _d = _q.sent();
2496
+ shouldUnwind = false;
2497
+ return [3 /*break*/, 21];
2498
+ case 21:
2499
+ if (!shouldUnwind) return [3 /*break*/, 24];
2272
2500
  fallbackPipeline = buildAggregateUnwindFallbackPipeline(executedPipeline, unwindFallback);
2273
- if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 18];
2501
+ if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 23];
2274
2502
  return [4 /*yield*/, db.collection(collection)
2275
2503
  .aggregate(fallbackPipeline, aggregateOptions)
2276
2504
  .toArray()];
2277
- case 17:
2278
- fallbackDocs = _o.sent();
2505
+ case 22:
2506
+ fallbackDocs = _q.sent();
2279
2507
  if (fallbackDocs.length > documents.length) {
2280
2508
  documents = fallbackDocs;
2281
2509
  executedPipeline = fallbackPipeline;
2282
2510
  fallbackMeta.unwind.used = true;
2283
2511
  }
2284
- _o.label = 18;
2285
- case 18:
2286
- if (!!documents.length) return [3 /*break*/, 20];
2512
+ _q.label = 23;
2513
+ case 23: return [3 /*break*/, 25];
2514
+ case 24:
2515
+ fallbackMeta.unwind.skipped = 'not_array';
2516
+ _q.label = 25;
2517
+ case 25:
2518
+ if (!!documents.length) return [3 /*break*/, 27];
2287
2519
  nameFallback = resolveAggregateNameMatchFallback(executedPipeline);
2288
- if (!nameFallback) return [3 /*break*/, 20];
2520
+ if (!nameFallback) return [3 /*break*/, 27];
2289
2521
  fallbackMeta.nameMatch = {
2290
2522
  field: nameFallback.field,
2291
2523
  fields: nameFallback.fields,
@@ -2293,22 +2525,22 @@ function executeAiAssistantMongoAggregate(payload, context) {
2293
2525
  used: false
2294
2526
  };
2295
2527
  fallbackPipeline = buildAggregateNameMatchFallbackPipeline(executedPipeline, nameFallback);
2296
- if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 20];
2528
+ if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 27];
2297
2529
  return [4 /*yield*/, db.collection(collection)
2298
2530
  .aggregate(fallbackPipeline, aggregateOptions)
2299
2531
  .toArray()];
2300
- case 19:
2301
- fallbackDocs = _o.sent();
2532
+ case 26:
2533
+ fallbackDocs = _q.sent();
2302
2534
  if (fallbackDocs.length) {
2303
2535
  documents = fallbackDocs;
2304
2536
  executedPipeline = fallbackPipeline;
2305
2537
  fallbackMeta.nameMatch.used = true;
2306
2538
  }
2307
- _o.label = 20;
2308
- case 20:
2309
- if (!!documents.length) return [3 /*break*/, 26];
2310
- _c = probeDocs;
2311
- if (_c) return [3 /*break*/, 22];
2539
+ _q.label = 27;
2540
+ case 27:
2541
+ if (!!documents.length) return [3 /*break*/, 33];
2542
+ _e = probeDocs;
2543
+ if (_e) return [3 /*break*/, 29];
2312
2544
  return [4 /*yield*/, fetchAssistantProbeDocs({
2313
2545
  db: db,
2314
2546
  collection: collection,
@@ -2317,15 +2549,15 @@ function executeAiAssistantMongoAggregate(payload, context) {
2317
2549
  isSuperAdmin: isSuperAdmin,
2318
2550
  includeClientScope: shouldScopeByClient
2319
2551
  })];
2320
- case 21:
2321
- _c = (_o.sent());
2322
- _o.label = 22;
2323
- case 22:
2324
- probeDocs = _c;
2552
+ case 28:
2553
+ _e = (_q.sent());
2554
+ _q.label = 29;
2555
+ case 29:
2556
+ probeDocs = _e;
2325
2557
  _loop_1 = function (i) {
2326
2558
  var stage, chemicalLookup, rewrittenPipeline, fallbackDocs;
2327
- return __generator(this, function (_p) {
2328
- switch (_p.label) {
2559
+ return __generator(this, function (_r) {
2560
+ switch (_r.label) {
2329
2561
  case 0:
2330
2562
  stage = executedPipeline[i];
2331
2563
  if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
@@ -2341,7 +2573,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
2341
2573
  probeDocs: probeDocs || undefined
2342
2574
  })];
2343
2575
  case 1:
2344
- chemicalLookup = _p.sent();
2576
+ chemicalLookup = _r.sent();
2345
2577
  if (!chemicalLookup) {
2346
2578
  return [2 /*return*/, "continue"];
2347
2579
  }
@@ -2352,33 +2584,33 @@ function executeAiAssistantMongoAggregate(payload, context) {
2352
2584
  .aggregate(rewrittenPipeline, aggregateOptions)
2353
2585
  .toArray()];
2354
2586
  case 2:
2355
- fallbackDocs = _p.sent();
2587
+ fallbackDocs = _r.sent();
2356
2588
  if (fallbackDocs.length) {
2357
2589
  documents = fallbackDocs;
2358
2590
  executedPipeline = rewrittenPipeline;
2359
2591
  fallbackMeta.chemicalLookup.used = true;
2360
2592
  return [2 /*return*/, "break"];
2361
2593
  }
2362
- _p.label = 3;
2594
+ _r.label = 3;
2363
2595
  case 3: return [2 /*return*/];
2364
2596
  }
2365
2597
  });
2366
2598
  };
2367
2599
  i = 0;
2368
- _o.label = 23;
2369
- case 23:
2370
- if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 26];
2600
+ _q.label = 30;
2601
+ case 30:
2602
+ if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 33];
2371
2603
  return [5 /*yield**/, _loop_1(i)];
2372
- case 24:
2373
- state_1 = _o.sent();
2604
+ case 31:
2605
+ state_1 = _q.sent();
2374
2606
  if (state_1 === "break")
2375
- return [3 /*break*/, 26];
2376
- _o.label = 25;
2377
- case 25:
2607
+ return [3 /*break*/, 33];
2608
+ _q.label = 32;
2609
+ case 32:
2378
2610
  i += 1;
2379
- return [3 /*break*/, 23];
2380
- case 26:
2381
- if (!!documents.length) return [3 /*break*/, 30];
2611
+ return [3 /*break*/, 30];
2612
+ case 33:
2613
+ if (!!documents.length) return [3 /*break*/, 37];
2382
2614
  matchFields_1 = new Set();
2383
2615
  (executedPipeline || []).forEach(function (stage) {
2384
2616
  if (stage && typeof stage === 'object' && stage.$match && typeof stage.$match === 'object') {
@@ -2387,9 +2619,9 @@ function executeAiAssistantMongoAggregate(payload, context) {
2387
2619
  .forEach(function (field) { return matchFields_1.add(field); });
2388
2620
  }
2389
2621
  });
2390
- if (!matchFields_1.size) return [3 /*break*/, 30];
2391
- _d = probeDocs;
2392
- if (_d) return [3 /*break*/, 28];
2622
+ if (!matchFields_1.size) return [3 /*break*/, 37];
2623
+ _f = probeDocs;
2624
+ if (_f) return [3 /*break*/, 35];
2393
2625
  return [4 /*yield*/, fetchAssistantProbeDocs({
2394
2626
  db: db,
2395
2627
  collection: collection,
@@ -2398,14 +2630,14 @@ function executeAiAssistantMongoAggregate(payload, context) {
2398
2630
  isSuperAdmin: isSuperAdmin,
2399
2631
  includeClientScope: shouldScopeByClient
2400
2632
  })];
2401
- case 27:
2402
- _d = (_o.sent());
2403
- _o.label = 28;
2404
- case 28:
2405
- probeDocs = _d;
2406
- if (!probeDocs.length) return [3 /*break*/, 30];
2633
+ case 34:
2634
+ _f = (_q.sent());
2635
+ _q.label = 35;
2636
+ case 35:
2637
+ probeDocs = _f;
2638
+ if (!probeDocs.length) return [3 /*break*/, 37];
2407
2639
  aliases = resolveFieldAliases(probeDocs, Array.from(matchFields_1), schemaFields);
2408
- if (!Object.keys(aliases).length) return [3 /*break*/, 30];
2640
+ if (!Object.keys(aliases).length) return [3 /*break*/, 37];
2409
2641
  fallbackMeta.queryFieldAliases = {
2410
2642
  aliases: aliases,
2411
2643
  attempted: true,
@@ -2416,31 +2648,31 @@ function executeAiAssistantMongoAggregate(payload, context) {
2416
2648
  var _b = __read(_a, 2), from = _b[0], to = _b[1];
2417
2649
  return replaceFieldPathDeep(acc, from, to);
2418
2650
  }, executedPipeline);
2419
- if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 30];
2651
+ if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 37];
2420
2652
  return [4 /*yield*/, db.collection(collection)
2421
2653
  .aggregate(rewrittenPipeline, aggregateOptions)
2422
2654
  .toArray()];
2423
- case 29:
2424
- fallbackDocs = _o.sent();
2655
+ case 36:
2656
+ fallbackDocs = _q.sent();
2425
2657
  if (fallbackDocs.length) {
2426
2658
  documents = fallbackDocs;
2427
2659
  executedPipeline = rewrittenPipeline;
2428
2660
  fallbackMeta.queryFieldAliases.used = true;
2429
2661
  }
2430
- _o.label = 30;
2431
- case 30:
2432
- if (!!documents.length) return [3 /*break*/, 34];
2662
+ _q.label = 37;
2663
+ case 37:
2664
+ if (!!documents.length) return [3 /*break*/, 41];
2433
2665
  _loop_2 = function (i) {
2434
- var stage, _q, idLookup, rewrittenPipeline, fallbackDocs;
2435
- return __generator(this, function (_r) {
2436
- switch (_r.label) {
2666
+ var stage, _s, idLookup, rewrittenPipeline, fallbackDocs;
2667
+ return __generator(this, function (_t) {
2668
+ switch (_t.label) {
2437
2669
  case 0:
2438
2670
  stage = executedPipeline[i];
2439
2671
  if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
2440
2672
  return [2 /*return*/, "continue"];
2441
2673
  }
2442
- _q = probeDocs;
2443
- if (_q) return [3 /*break*/, 2];
2674
+ _s = probeDocs;
2675
+ if (_s) return [3 /*break*/, 2];
2444
2676
  return [4 /*yield*/, fetchAssistantProbeDocs({
2445
2677
  db: db,
2446
2678
  collection: collection,
@@ -2450,10 +2682,10 @@ function executeAiAssistantMongoAggregate(payload, context) {
2450
2682
  includeClientScope: shouldScopeByClient
2451
2683
  })];
2452
2684
  case 1:
2453
- _q = (_r.sent());
2454
- _r.label = 2;
2685
+ _s = (_t.sent());
2686
+ _t.label = 2;
2455
2687
  case 2:
2456
- probeDocs = _q;
2688
+ probeDocs = _s;
2457
2689
  return [4 /*yield*/, applyIdLookupFallbackToQuery({
2458
2690
  query: stage.$match,
2459
2691
  db: db,
@@ -2464,7 +2696,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
2464
2696
  probeDocs: probeDocs || undefined
2465
2697
  })];
2466
2698
  case 3:
2467
- idLookup = _r.sent();
2699
+ idLookup = _t.sent();
2468
2700
  if (!idLookup) {
2469
2701
  return [2 /*return*/, "continue"];
2470
2702
  }
@@ -2475,41 +2707,41 @@ function executeAiAssistantMongoAggregate(payload, context) {
2475
2707
  .aggregate(rewrittenPipeline, aggregateOptions)
2476
2708
  .toArray()];
2477
2709
  case 4:
2478
- fallbackDocs = _r.sent();
2710
+ fallbackDocs = _t.sent();
2479
2711
  if (fallbackDocs.length) {
2480
2712
  documents = fallbackDocs;
2481
2713
  executedPipeline = rewrittenPipeline;
2482
2714
  fallbackMeta.idLookup.used = true;
2483
2715
  return [2 /*return*/, "break"];
2484
2716
  }
2485
- _r.label = 5;
2717
+ _t.label = 5;
2486
2718
  case 5: return [2 /*return*/];
2487
2719
  }
2488
2720
  });
2489
2721
  };
2490
2722
  i = 0;
2491
- _o.label = 31;
2492
- case 31:
2493
- if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 34];
2723
+ _q.label = 38;
2724
+ case 38:
2725
+ if (!(i < (executedPipeline || []).length)) return [3 /*break*/, 41];
2494
2726
  return [5 /*yield**/, _loop_2(i)];
2495
- case 32:
2496
- state_2 = _o.sent();
2727
+ case 39:
2728
+ state_2 = _q.sent();
2497
2729
  if (state_2 === "break")
2498
- return [3 /*break*/, 34];
2499
- _o.label = 33;
2500
- case 33:
2730
+ return [3 /*break*/, 41];
2731
+ _q.label = 40;
2732
+ case 40:
2501
2733
  i += 1;
2502
- return [3 /*break*/, 31];
2503
- case 34:
2504
- if (!!documents.length) return [3 /*break*/, 37];
2734
+ return [3 /*break*/, 38];
2735
+ case 41:
2736
+ if (!!documents.length) return [3 /*break*/, 44];
2505
2737
  return [4 /*yield*/, resolveBaseCollectionFromReport(db, dbName, collection)];
2506
- case 35:
2507
- baseCollection = _o.sent();
2508
- if (!(baseCollection && baseCollection !== collection)) return [3 /*break*/, 37];
2738
+ case 42:
2739
+ baseCollection = _q.sent();
2740
+ if (!(baseCollection && baseCollection !== collection)) return [3 /*break*/, 44];
2509
2741
  fallbackPayload = __assign(__assign({}, input), { collection: baseCollection });
2510
2742
  return [4 /*yield*/, executeAiAssistantMongoAggregate(fallbackPayload, context)];
2511
- case 36:
2512
- fallbackResult = _o.sent();
2743
+ case 43:
2744
+ fallbackResult = _q.sent();
2513
2745
  if (Array.isArray(fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.documents) && fallbackResult.documents.length) {
2514
2746
  if (isSuperAdmin && (fallbackResult === null || fallbackResult === void 0 ? void 0 : fallbackResult.debug) && typeof fallbackResult.debug === 'object') {
2515
2747
  existingFallbacks = fallbackResult.debug.fallbacks && typeof fallbackResult.debug.fallbacks === 'object'
@@ -2526,48 +2758,48 @@ function executeAiAssistantMongoAggregate(payload, context) {
2526
2758
  if (isSuperAdmin) {
2527
2759
  fallbackMeta.reportFallback = { from: collection, to: baseCollection, attempted: true, used: false };
2528
2760
  }
2529
- _o.label = 37;
2530
- case 37:
2531
- if (!(!documents.length && isSuperAdmin)) return [3 /*break*/, 54];
2761
+ _q.label = 44;
2762
+ case 44:
2763
+ if (!(!documents.length && isSuperAdmin)) return [3 /*break*/, 61];
2532
2764
  matchStages = (executedPipeline || []).filter(function (stage) { return stage && typeof stage === 'object' && stage.$match && typeof stage.$match === 'object'; });
2533
2765
  diagnostics = {};
2534
- if (!matchStages.length) return [3 /*break*/, 54];
2766
+ if (!matchStages.length) return [3 /*break*/, 61];
2535
2767
  combinedMatch = matchStages.reduce(function (acc, stage) { return ({ $and: __spreadArray(__spreadArray([], __read((acc.$and || [])), false), [stage.$match], false) }); }, { $and: [] });
2536
2768
  nameFields = collectMatchFieldsByCondition(combinedMatch, function (field, condition) { return isRegexMatchCondition(condition)
2537
2769
  || (typeof condition === 'string' && shouldApplyAssistantNameRegex(field)); });
2538
2770
  dateFields = collectMatchFieldsByCondition(combinedMatch, function (_field, condition) { return isDateCondition(condition); });
2539
2771
  diagnostics.nameFields = nameFields.length ? nameFields : undefined;
2540
2772
  diagnostics.dateFields = dateFields.length ? dateFields : undefined;
2541
- _o.label = 38;
2542
- case 38:
2543
- _o.trys.push([38, 43, , 44]);
2544
- if (!nameFields.length) return [3 /*break*/, 40];
2773
+ _q.label = 45;
2774
+ case 45:
2775
+ _q.trys.push([45, 50, , 51]);
2776
+ if (!nameFields.length) return [3 /*break*/, 47];
2545
2777
  queryNoName = stripMatchFields(combinedMatch, nameFields);
2546
- _e = diagnostics;
2778
+ _g = diagnostics;
2547
2779
  return [4 /*yield*/, db.collection(collection).countDocuments(queryNoName, {
2548
2780
  readPreference: AI_ASSISTANT_READ_PREFERENCE
2549
2781
  })];
2550
- case 39:
2551
- _e.recentCount = _o.sent();
2552
- _o.label = 40;
2553
- case 40:
2554
- if (!dateFields.length) return [3 /*break*/, 42];
2782
+ case 46:
2783
+ _g.recentCount = _q.sent();
2784
+ _q.label = 47;
2785
+ case 47:
2786
+ if (!dateFields.length) return [3 /*break*/, 49];
2555
2787
  queryNoDate = stripMatchFields(combinedMatch, dateFields);
2556
- _f = diagnostics;
2788
+ _h = diagnostics;
2557
2789
  return [4 /*yield*/, db.collection(collection).countDocuments(queryNoDate, {
2558
2790
  readPreference: AI_ASSISTANT_READ_PREFERENCE
2559
2791
  })];
2560
- case 41:
2561
- _f.nameMatchCount = _o.sent();
2562
- _o.label = 42;
2563
- case 42: return [3 /*break*/, 44];
2564
- case 43:
2565
- _g = _o.sent();
2566
- return [3 /*break*/, 44];
2567
- case 44:
2568
- _o.trys.push([44, 47, , 48]);
2569
- _h = probeDocs;
2570
- if (_h) return [3 /*break*/, 46];
2792
+ case 48:
2793
+ _h.nameMatchCount = _q.sent();
2794
+ _q.label = 49;
2795
+ case 49: return [3 /*break*/, 51];
2796
+ case 50:
2797
+ _j = _q.sent();
2798
+ return [3 /*break*/, 51];
2799
+ case 51:
2800
+ _q.trys.push([51, 54, , 55]);
2801
+ _k = probeDocs;
2802
+ if (_k) return [3 /*break*/, 53];
2571
2803
  return [4 /*yield*/, fetchAssistantProbeDocs({
2572
2804
  db: db,
2573
2805
  collection: collection,
@@ -2576,44 +2808,44 @@ function executeAiAssistantMongoAggregate(payload, context) {
2576
2808
  isSuperAdmin: isSuperAdmin,
2577
2809
  includeClientScope: shouldScopeByClient
2578
2810
  })];
2579
- case 45:
2580
- _h = (_o.sent());
2581
- _o.label = 46;
2582
- case 46:
2583
- probeDocs = _h;
2811
+ case 52:
2812
+ _k = (_q.sent());
2813
+ _q.label = 53;
2814
+ case 53:
2815
+ probeDocs = _k;
2584
2816
  if (probeDocs.length && nameFields.length) {
2585
2817
  diagnostics.chemicalIdDetected = detectChemicalIdFromProbe(probeDocs, nameFields);
2586
2818
  }
2587
- return [3 /*break*/, 48];
2588
- case 47:
2589
- _j = _o.sent();
2590
- return [3 /*break*/, 48];
2591
- case 48:
2592
- _o.trys.push([48, 52, , 53]);
2819
+ return [3 /*break*/, 55];
2820
+ case 54:
2821
+ _l = _q.sent();
2822
+ return [3 /*break*/, 55];
2823
+ case 55:
2824
+ _q.trys.push([55, 59, , 60]);
2593
2825
  return [4 /*yield*/, listAssistantCollections(db, dbName)];
2594
- case 49:
2595
- allCollections = _o.sent();
2826
+ case 56:
2827
+ allCollections = _q.sent();
2596
2828
  base = stripVersionSuffix(collection.startsWith('report-') ? collection.slice('report-'.length) : collection);
2597
2829
  alt = collection.startsWith('report-') ? base : "report-".concat(base);
2598
- if (!(alt && alt !== collection && allCollections.includes(alt))) return [3 /*break*/, 51];
2830
+ if (!(alt && alt !== collection && allCollections.includes(alt))) return [3 /*break*/, 58];
2599
2831
  return [4 /*yield*/, db.collection(alt).countDocuments({}, { readPreference: AI_ASSISTANT_READ_PREFERENCE })];
2600
- case 50:
2601
- altCount = _o.sent();
2832
+ case 57:
2833
+ altCount = _q.sent();
2602
2834
  diagnostics.alternateCollection = alt;
2603
2835
  diagnostics.alternateCollectionCount = altCount;
2604
- _o.label = 51;
2605
- case 51: return [3 /*break*/, 53];
2606
- case 52:
2607
- _k = _o.sent();
2608
- return [3 /*break*/, 53];
2609
- case 53:
2836
+ _q.label = 58;
2837
+ case 58: return [3 /*break*/, 60];
2838
+ case 59:
2839
+ _m = _q.sent();
2840
+ return [3 /*break*/, 60];
2841
+ case 60:
2610
2842
  fallbackMeta.zeroDiagnostics = diagnostics;
2611
- _o.label = 54;
2612
- case 54:
2843
+ _q.label = 61;
2844
+ case 61:
2613
2845
  sanitizedDocuments = isSuperAdmin
2614
2846
  ? documents
2615
2847
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
2616
- includeIds = ((_m = input.options) === null || _m === void 0 ? void 0 : _m.includeIds) === true;
2848
+ includeIds = ((_p = input.options) === null || _p === void 0 ? void 0 : _p.includeIds) === true;
2617
2849
  displayDocs = sanitizedDocuments;
2618
2850
  return [4 /*yield*/, applyIdLookupDisplayEnrichment({
2619
2851
  docs: displayDocs,
@@ -2624,8 +2856,8 @@ function executeAiAssistantMongoAggregate(payload, context) {
2624
2856
  idCustomer: customerId,
2625
2857
  isSuperAdmin: isSuperAdmin
2626
2858
  })];
2627
- case 55:
2628
- idLookupDisplay = _o.sent();
2859
+ case 62:
2860
+ idLookupDisplay = _q.sent();
2629
2861
  if (idLookupDisplay === null || idLookupDisplay === void 0 ? void 0 : idLookupDisplay.docs) {
2630
2862
  displayDocs = idLookupDisplay.docs;
2631
2863
  }
@@ -3357,21 +3589,44 @@ function getValueAtPath(obj, path) {
3357
3589
  };
3358
3590
  return walk(obj, 0);
3359
3591
  }
3592
+ function hasArrayValueAtPath(docs, path) {
3593
+ var e_1, _a;
3594
+ if (!Array.isArray(docs) || !docs.length || !path) {
3595
+ return false;
3596
+ }
3597
+ try {
3598
+ for (var docs_1 = __values(docs), docs_1_1 = docs_1.next(); !docs_1_1.done; docs_1_1 = docs_1.next()) {
3599
+ var doc = docs_1_1.value;
3600
+ var value = getValueAtPath(doc, path);
3601
+ if (Array.isArray(value)) {
3602
+ return true;
3603
+ }
3604
+ }
3605
+ }
3606
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3607
+ finally {
3608
+ try {
3609
+ if (docs_1_1 && !docs_1_1.done && (_a = docs_1.return)) _a.call(docs_1);
3610
+ }
3611
+ finally { if (e_1) throw e_1.error; }
3612
+ }
3613
+ return false;
3614
+ }
3360
3615
  function inferIdFieldStorageTypeFromDocs(docs, fieldPath) {
3361
- var e_1, _a, e_2, _b;
3616
+ var e_2, _a, e_3, _b;
3362
3617
  if (!Array.isArray(docs) || !fieldPath) {
3363
3618
  return 'unknown';
3364
3619
  }
3365
3620
  var sawString = false;
3366
3621
  try {
3367
- for (var docs_1 = __values(docs), docs_1_1 = docs_1.next(); !docs_1_1.done; docs_1_1 = docs_1.next()) {
3368
- var doc = docs_1_1.value;
3622
+ for (var docs_2 = __values(docs), docs_2_1 = docs_2.next(); !docs_2_1.done; docs_2_1 = docs_2.next()) {
3623
+ var doc = docs_2_1.value;
3369
3624
  var value = fieldPath.includes('.')
3370
3625
  ? getValueAtPath(doc, fieldPath)
3371
3626
  : doc === null || doc === void 0 ? void 0 : doc[fieldPath];
3372
3627
  var queue = Array.isArray(value) ? value : [value];
3373
3628
  try {
3374
- 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()) {
3629
+ for (var queue_1 = (e_3 = void 0, __values(queue)), queue_1_1 = queue_1.next(); !queue_1_1.done; queue_1_1 = queue_1.next()) {
3375
3630
  var entry = queue_1_1.value;
3376
3631
  if (entry === null || entry === undefined) {
3377
3632
  continue;
@@ -3384,21 +3639,21 @@ function inferIdFieldStorageTypeFromDocs(docs, fieldPath) {
3384
3639
  }
3385
3640
  }
3386
3641
  }
3387
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
3642
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
3388
3643
  finally {
3389
3644
  try {
3390
3645
  if (queue_1_1 && !queue_1_1.done && (_b = queue_1.return)) _b.call(queue_1);
3391
3646
  }
3392
- finally { if (e_2) throw e_2.error; }
3647
+ finally { if (e_3) throw e_3.error; }
3393
3648
  }
3394
3649
  }
3395
3650
  }
3396
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
3651
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
3397
3652
  finally {
3398
3653
  try {
3399
- if (docs_1_1 && !docs_1_1.done && (_a = docs_1.return)) _a.call(docs_1);
3654
+ if (docs_2_1 && !docs_2_1.done && (_a = docs_2.return)) _a.call(docs_2);
3400
3655
  }
3401
- finally { if (e_1) throw e_1.error; }
3656
+ finally { if (e_2) throw e_2.error; }
3402
3657
  }
3403
3658
  return sawString ? 'string' : 'unknown';
3404
3659
  }
@@ -3493,7 +3748,7 @@ function normalizeLookupKeyValue(value) {
3493
3748
  return '';
3494
3749
  }
3495
3750
  function collectTopLevelIdFieldValues(docs, options) {
3496
- var e_3, _a, e_4, _b;
3751
+ var e_4, _a, e_5, _b;
3497
3752
  if (!Array.isArray(docs) || !docs.length) {
3498
3753
  return [];
3499
3754
  }
@@ -3505,8 +3760,8 @@ function collectTopLevelIdFieldValues(docs, options) {
3505
3760
  : AI_ASSISTANT_ID_DISPLAY_LOOKUP_MAX_IDS;
3506
3761
  var fieldMap = new Map();
3507
3762
  try {
3508
- for (var docs_2 = __values(docs), docs_2_1 = docs_2.next(); !docs_2_1.done; docs_2_1 = docs_2.next()) {
3509
- var doc = docs_2_1.value;
3763
+ for (var docs_3 = __values(docs), docs_3_1 = docs_3.next(); !docs_3_1.done; docs_3_1 = docs_3.next()) {
3764
+ var doc = docs_3_1.value;
3510
3765
  if (!doc || typeof doc !== 'object') {
3511
3766
  continue;
3512
3767
  }
@@ -3541,26 +3796,26 @@ function collectTopLevelIdFieldValues(docs, options) {
3541
3796
  });
3542
3797
  };
3543
3798
  try {
3544
- for (var keys_1 = (e_4 = void 0, __values(keys)), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
3799
+ for (var keys_1 = (e_5 = void 0, __values(keys)), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
3545
3800
  var key = keys_1_1.value;
3546
3801
  _loop_3(key);
3547
3802
  }
3548
3803
  }
3549
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
3804
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
3550
3805
  finally {
3551
3806
  try {
3552
3807
  if (keys_1_1 && !keys_1_1.done && (_b = keys_1.return)) _b.call(keys_1);
3553
3808
  }
3554
- finally { if (e_4) throw e_4.error; }
3809
+ finally { if (e_5) throw e_5.error; }
3555
3810
  }
3556
3811
  }
3557
3812
  }
3558
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
3813
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
3559
3814
  finally {
3560
3815
  try {
3561
- if (docs_2_1 && !docs_2_1.done && (_a = docs_2.return)) _a.call(docs_2);
3816
+ if (docs_3_1 && !docs_3_1.done && (_a = docs_3.return)) _a.call(docs_3);
3562
3817
  }
3563
- finally { if (e_3) throw e_3.error; }
3818
+ finally { if (e_4) throw e_4.error; }
3564
3819
  }
3565
3820
  return Array.from(fieldMap.entries()).map(function (_a) {
3566
3821
  var _b = __read(_a, 2), field = _b[0], values = _b[1];
@@ -3571,7 +3826,7 @@ function collectTopLevelIdFieldValues(docs, options) {
3571
3826
  });
3572
3827
  }
3573
3828
  function resolveLookupDisplayField(baseToken, probeDocs, schemaFields) {
3574
- var e_5, _a, e_6, _b;
3829
+ var e_6, _a, e_7, _b;
3575
3830
  var normalizedBase = normalizeOptionalString(baseToken);
3576
3831
  if (!normalizedBase) {
3577
3832
  return null;
@@ -3589,12 +3844,12 @@ function resolveLookupDisplayField(baseToken, probeDocs, schemaFields) {
3589
3844
  }
3590
3845
  }
3591
3846
  }
3592
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
3847
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
3593
3848
  finally {
3594
3849
  try {
3595
3850
  if (schemaCandidates_1_1 && !schemaCandidates_1_1.done && (_a = schemaCandidates_1.return)) _a.call(schemaCandidates_1);
3596
3851
  }
3597
- finally { if (e_5) throw e_5.error; }
3852
+ finally { if (e_6) throw e_6.error; }
3598
3853
  }
3599
3854
  return schemaCandidates[0];
3600
3855
  }
@@ -3607,12 +3862,12 @@ function resolveLookupDisplayField(baseToken, probeDocs, schemaFields) {
3607
3862
  }
3608
3863
  }
3609
3864
  }
3610
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
3865
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
3611
3866
  finally {
3612
3867
  try {
3613
3868
  if (candidates_1_1 && !candidates_1_1.done && (_b = candidates_1.return)) _b.call(candidates_1);
3614
3869
  }
3615
- finally { if (e_6) throw e_6.error; }
3870
+ finally { if (e_7) throw e_7.error; }
3616
3871
  }
3617
3872
  return candidates.length ? candidates[0] : null;
3618
3873
  }
@@ -3625,8 +3880,8 @@ function resolveLookupMappingsForField(field, mappings) {
3625
3880
  }
3626
3881
  function applyIdLookupDisplayEnrichment(params) {
3627
3882
  return __awaiter(this, void 0, void 0, function () {
3628
- var docs, collection, db, dbName, idClient, idCustomer, isSuperAdmin, idFields, lookupMappings, allCollections, collectionProbeCache, collectionSchemaCache, lookupMeta, enrichedDocs, _loop_4, idFields_1, idFields_1_1, fieldEntry, e_7_1;
3629
- var e_7, _a;
3883
+ var docs, collection, db, dbName, idClient, idCustomer, isSuperAdmin, idFields, lookupMappings, allCollections, collectionProbeCache, collectionSchemaCache, lookupMeta, enrichedDocs, _loop_4, idFields_1, idFields_1_1, fieldEntry, e_8_1;
3884
+ var e_8, _a;
3630
3885
  return __generator(this, function (_b) {
3631
3886
  switch (_b.label) {
3632
3887
  case 0:
@@ -3650,8 +3905,8 @@ function applyIdLookupDisplayEnrichment(params) {
3650
3905
  lookupMeta = [];
3651
3906
  enrichedDocs = docs.map(function (doc) { return (__assign({}, doc)); });
3652
3907
  _loop_4 = function (fieldEntry) {
3653
- var values, baseToken, mappingMatches, candidateCollections, filteredCandidates, _loop_5, filteredCandidates_1, filteredCandidates_1_1, candidate, state_3, e_8_1;
3654
- var e_8, _c;
3908
+ var values, baseToken, mappingMatches, candidateCollections, filteredCandidates, _loop_5, filteredCandidates_1, filteredCandidates_1_1, candidate, state_3, e_9_1;
3909
+ var e_9, _c;
3655
3910
  return __generator(this, function (_d) {
3656
3911
  switch (_d.label) {
3657
3912
  case 0:
@@ -3800,7 +4055,7 @@ function applyIdLookupDisplayEnrichment(params) {
3800
4055
  _d.label = 1;
3801
4056
  case 1:
3802
4057
  _d.trys.push([1, 6, 7, 8]);
3803
- filteredCandidates_1 = (e_8 = void 0, __values(filteredCandidates)), filteredCandidates_1_1 = filteredCandidates_1.next();
4058
+ filteredCandidates_1 = (e_9 = void 0, __values(filteredCandidates)), filteredCandidates_1_1 = filteredCandidates_1.next();
3804
4059
  _d.label = 2;
3805
4060
  case 2:
3806
4061
  if (!!filteredCandidates_1_1.done) return [3 /*break*/, 5];
@@ -3816,14 +4071,14 @@ function applyIdLookupDisplayEnrichment(params) {
3816
4071
  return [3 /*break*/, 2];
3817
4072
  case 5: return [3 /*break*/, 8];
3818
4073
  case 6:
3819
- e_8_1 = _d.sent();
3820
- e_8 = { error: e_8_1 };
4074
+ e_9_1 = _d.sent();
4075
+ e_9 = { error: e_9_1 };
3821
4076
  return [3 /*break*/, 8];
3822
4077
  case 7:
3823
4078
  try {
3824
4079
  if (filteredCandidates_1_1 && !filteredCandidates_1_1.done && (_c = filteredCandidates_1.return)) _c.call(filteredCandidates_1);
3825
4080
  }
3826
- finally { if (e_8) throw e_8.error; }
4081
+ finally { if (e_9) throw e_9.error; }
3827
4082
  return [7 /*endfinally*/];
3828
4083
  case 8: return [2 /*return*/];
3829
4084
  }
@@ -3846,14 +4101,14 @@ function applyIdLookupDisplayEnrichment(params) {
3846
4101
  return [3 /*break*/, 3];
3847
4102
  case 6: return [3 /*break*/, 9];
3848
4103
  case 7:
3849
- e_7_1 = _b.sent();
3850
- e_7 = { error: e_7_1 };
4104
+ e_8_1 = _b.sent();
4105
+ e_8 = { error: e_8_1 };
3851
4106
  return [3 /*break*/, 9];
3852
4107
  case 8:
3853
4108
  try {
3854
4109
  if (idFields_1_1 && !idFields_1_1.done && (_a = idFields_1.return)) _a.call(idFields_1);
3855
4110
  }
3856
- finally { if (e_7) throw e_7.error; }
4111
+ finally { if (e_8) throw e_8.error; }
3857
4112
  return [7 /*endfinally*/];
3858
4113
  case 9:
3859
4114
  if (!lookupMeta.length) {
@@ -3872,14 +4127,14 @@ function applyIdLookupDisplayEnrichment(params) {
3872
4127
  });
3873
4128
  }
3874
4129
  function hasNonEmptyValue(docs, fieldPath, options) {
3875
- var e_9, _a;
4130
+ var e_10, _a;
3876
4131
  if (!Array.isArray(docs) || !fieldPath) {
3877
4132
  return false;
3878
4133
  }
3879
4134
  var usePath = fieldPath.includes('.');
3880
4135
  try {
3881
- for (var docs_3 = __values(docs), docs_3_1 = docs_3.next(); !docs_3_1.done; docs_3_1 = docs_3.next()) {
3882
- var doc = docs_3_1.value;
4136
+ for (var docs_4 = __values(docs), docs_4_1 = docs_4.next(); !docs_4_1.done; docs_4_1 = docs_4.next()) {
4137
+ var doc = docs_4_1.value;
3883
4138
  var value = usePath ? getValueAtPath(doc, fieldPath) : doc === null || doc === void 0 ? void 0 : doc[fieldPath];
3884
4139
  if ((options === null || options === void 0 ? void 0 : options.treatObjectLikeAsEmpty) && isDisplayObjectLike(value)) {
3885
4140
  continue;
@@ -3889,12 +4144,12 @@ function hasNonEmptyValue(docs, fieldPath, options) {
3889
4144
  }
3890
4145
  }
3891
4146
  }
3892
- catch (e_9_1) { e_9 = { error: e_9_1 }; }
4147
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
3893
4148
  finally {
3894
4149
  try {
3895
- if (docs_3_1 && !docs_3_1.done && (_a = docs_3.return)) _a.call(docs_3);
4150
+ if (docs_4_1 && !docs_4_1.done && (_a = docs_4.return)) _a.call(docs_4);
3896
4151
  }
3897
- finally { if (e_9) throw e_9.error; }
4152
+ finally { if (e_10) throw e_10.error; }
3898
4153
  }
3899
4154
  return false;
3900
4155
  }
@@ -4166,35 +4421,45 @@ function replaceFieldPathDeep(value, fromField, toField) {
4166
4421
  return next_1;
4167
4422
  }
4168
4423
  if (typeof value === 'string') {
4169
- if (value.startsWith("$".concat(fromField))) {
4170
- return "$".concat(toField).concat(value.slice(fromField.length + 1));
4424
+ var fromRef = "$".concat(fromField);
4425
+ if (value === fromRef) {
4426
+ return "$".concat(toField);
4427
+ }
4428
+ if (value.startsWith("".concat(fromRef, "."))) {
4429
+ return "$".concat(toField).concat(value.slice(fromRef.length));
4171
4430
  }
4172
4431
  return value;
4173
4432
  }
4174
4433
  return value;
4175
4434
  }
4176
4435
  function replaceQueryFieldCondition(query, field, condition) {
4177
- if (Array.isArray(query)) {
4178
- return query.map(function (entry) { return replaceQueryFieldCondition(entry, field, condition); });
4179
- }
4180
- if (!query || typeof query !== 'object') {
4181
- return query;
4182
- }
4183
- var next = __assign({}, query);
4184
- Object.keys(next).forEach(function (key) {
4185
- if (key === field) {
4186
- next[key] = condition;
4187
- return;
4188
- }
4189
- if (key.startsWith('$')) {
4190
- next[key] = replaceQueryFieldCondition(next[key], field, condition);
4191
- return;
4436
+ var hasPath = field.includes('.');
4437
+ var replaceValue = function (value, prefix) {
4438
+ if (Array.isArray(value)) {
4439
+ return value.map(function (entry) { return replaceValue(entry, prefix); });
4192
4440
  }
4193
- if (next[key] && typeof next[key] === 'object') {
4194
- next[key] = replaceQueryFieldCondition(next[key], field, condition);
4441
+ if (!value || typeof value !== 'object') {
4442
+ return value;
4195
4443
  }
4196
- });
4197
- return next;
4444
+ var next = __assign({}, value);
4445
+ Object.keys(next).forEach(function (key) {
4446
+ var currentPath = prefix ? "".concat(prefix, ".").concat(key) : key;
4447
+ var matches = hasPath ? currentPath === field : key === field;
4448
+ if (matches) {
4449
+ next[key] = condition;
4450
+ return;
4451
+ }
4452
+ if (key.startsWith('$')) {
4453
+ next[key] = replaceValue(next[key], prefix);
4454
+ return;
4455
+ }
4456
+ if (next[key] && typeof next[key] === 'object') {
4457
+ next[key] = replaceValue(next[key], currentPath);
4458
+ }
4459
+ });
4460
+ return next;
4461
+ };
4462
+ return replaceValue(query, '');
4198
4463
  }
4199
4464
  function formatDisplayColumnName(column) {
4200
4465
  var trimmed = String(column || '').trim();
@@ -4748,21 +5013,154 @@ function sanitizeAssistantProjection(projection) {
4748
5013
  }
4749
5014
  return projection;
4750
5015
  }
4751
- function normalizeAssistantAggregatePipeline(pipeline) {
5016
+ var AGG_MATCH_EXPR_OPERATORS = new Set(['$eq', '$ne', '$gt', '$gte', '$lt', '$lte']);
5017
+ function isMatchExpressionOperand(value) {
5018
+ if (typeof value === 'string') {
5019
+ return value.startsWith('$$');
5020
+ }
5021
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
5022
+ return false;
5023
+ }
5024
+ if (value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
5025
+ return false;
5026
+ }
5027
+ return Object.keys(value).some(function (key) { return key.startsWith('$'); });
5028
+ }
5029
+ function mergeMatchExpr(existing, clauses) {
5030
+ if (!clauses.length) {
5031
+ return existing;
5032
+ }
5033
+ if (!existing) {
5034
+ return clauses.length === 1 ? clauses[0] : { $and: clauses };
5035
+ }
5036
+ if (existing && typeof existing === 'object' && !Array.isArray(existing)) {
5037
+ var existingAnd = existing.$and;
5038
+ if (Array.isArray(existingAnd)) {
5039
+ return __assign(__assign({}, existing), { $and: __spreadArray(__spreadArray([], __read(existingAnd), false), __read(clauses), false) });
5040
+ }
5041
+ }
5042
+ return { $and: __spreadArray([existing], __read(clauses), false) };
5043
+ }
5044
+ function rewriteMatchExpressionsToExpr(match) {
5045
+ var rewriteValue = function (value) {
5046
+ if (Array.isArray(value)) {
5047
+ return value.map(function (entry) { return rewriteValue(entry); });
5048
+ }
5049
+ if (!value || typeof value !== 'object' || value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
5050
+ return value;
5051
+ }
5052
+ var result = {};
5053
+ var exprClauses = [];
5054
+ Object.keys(value).forEach(function (key) {
5055
+ var entry = value[key];
5056
+ if (key === '$expr') {
5057
+ result[key] = entry;
5058
+ return;
5059
+ }
5060
+ if (key.startsWith('$')) {
5061
+ result[key] = rewriteValue(entry);
5062
+ return;
5063
+ }
5064
+ if (entry && typeof entry === 'object' && !Array.isArray(entry) && !(entry instanceof Date) && !(entry instanceof RegExp) && !isMongoObjectId(entry)) {
5065
+ var nextEntry_1 = __assign({}, entry);
5066
+ var moved_1 = false;
5067
+ Object.keys(nextEntry_1).forEach(function (op) {
5068
+ var _a;
5069
+ if (!AGG_MATCH_EXPR_OPERATORS.has(op)) {
5070
+ return;
5071
+ }
5072
+ var operand = nextEntry_1[op];
5073
+ if (isMatchExpressionOperand(operand)) {
5074
+ exprClauses.push((_a = {}, _a[op] = ["$".concat(key), operand], _a));
5075
+ delete nextEntry_1[op];
5076
+ moved_1 = true;
5077
+ }
5078
+ });
5079
+ if (Object.keys(nextEntry_1).length) {
5080
+ result[key] = rewriteValue(nextEntry_1);
5081
+ }
5082
+ else if (!moved_1) {
5083
+ result[key] = entry;
5084
+ }
5085
+ return;
5086
+ }
5087
+ if (typeof entry === 'string' && entry.startsWith('$$')) {
5088
+ exprClauses.push({ $eq: ["$".concat(key), entry] });
5089
+ return;
5090
+ }
5091
+ result[key] = entry;
5092
+ });
5093
+ if (exprClauses.length) {
5094
+ result.$expr = mergeMatchExpr(result.$expr, exprClauses);
5095
+ }
5096
+ return result;
5097
+ };
5098
+ return rewriteValue(match);
5099
+ }
5100
+ function buildInvoiceStatusRegex(value) {
5101
+ var normalized = String(value || '').toLowerCase();
5102
+ if (!normalized) {
5103
+ return null;
5104
+ }
5105
+ var tokens = normalized.split(/[^a-z0-9]+/g).filter(Boolean);
5106
+ if (!tokens.includes('paid') || !tokens.includes('closed')) {
5107
+ return null;
5108
+ }
5109
+ return /paid|closed/i;
5110
+ }
5111
+ function normalizeInvoiceStatusMatch(match) {
5112
+ var rewriteValue = function (value) {
5113
+ if (Array.isArray(value)) {
5114
+ return value.map(function (entry) { return rewriteValue(entry); });
5115
+ }
5116
+ if (!value || typeof value !== 'object' || value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
5117
+ return value;
5118
+ }
5119
+ var result = {};
5120
+ Object.keys(value).forEach(function (key) {
5121
+ var entry = value[key];
5122
+ if (key.startsWith('$')) {
5123
+ result[key] = rewriteValue(entry);
5124
+ return;
5125
+ }
5126
+ var field = key.split('.').pop() || key;
5127
+ if (field === 'status' && typeof entry === 'string') {
5128
+ var regex = buildInvoiceStatusRegex(entry);
5129
+ if (regex) {
5130
+ result[key] = regex;
5131
+ return;
5132
+ }
5133
+ }
5134
+ if (entry && typeof entry === 'object') {
5135
+ result[key] = rewriteValue(entry);
5136
+ return;
5137
+ }
5138
+ result[key] = entry;
5139
+ });
5140
+ return result;
5141
+ };
5142
+ return rewriteValue(match);
5143
+ }
5144
+ function normalizeAssistantAggregatePipeline(pipeline, collection) {
4752
5145
  if (!Array.isArray(pipeline)) {
4753
5146
  return [];
4754
5147
  }
5148
+ var isInvoiceCollection = ['invoice', 'invoices', 'invoice-versions'].includes(String(collection || '').toLowerCase());
4755
5149
  return pipeline
4756
5150
  .filter(function (stage) { return stage && typeof stage === 'object' && !Array.isArray(stage); })
4757
5151
  .map(function (stage) {
4758
5152
  var next = __assign({}, stage);
4759
5153
  if (next.$match && typeof next.$match === 'object') {
4760
5154
  var rewritten = rewriteEmbeddedMatchObjects(next.$match);
4761
- next.$match = applyAssistantNameRegexToQuery(rewritten);
5155
+ var exprRewritten = rewriteMatchExpressionsToExpr(rewritten);
5156
+ var statusNormalized = isInvoiceCollection ? normalizeInvoiceStatusMatch(exprRewritten) : exprRewritten;
5157
+ next.$match = applyAssistantNameRegexToQuery(statusNormalized);
4762
5158
  }
4763
5159
  if (next.$geoNear && typeof next.$geoNear === 'object' && next.$geoNear.query) {
4764
5160
  var rewritten = rewriteEmbeddedMatchObjects(next.$geoNear.query);
4765
- next.$geoNear = __assign(__assign({}, next.$geoNear), { query: applyAssistantNameRegexToQuery(rewritten) });
5161
+ var exprRewritten = rewriteMatchExpressionsToExpr(rewritten);
5162
+ var statusNormalized = isInvoiceCollection ? normalizeInvoiceStatusMatch(exprRewritten) : exprRewritten;
5163
+ next.$geoNear = __assign(__assign({}, next.$geoNear), { query: applyAssistantNameRegexToQuery(statusNormalized) });
4766
5164
  }
4767
5165
  return next;
4768
5166
  });
@@ -4815,7 +5213,7 @@ function findAggregateLimit(pipeline) {
4815
5213
  }
4816
5214
  var limit = stage.$limit;
4817
5215
  if (typeof limit === 'number' && Number.isFinite(limit)) {
4818
- return limit;
5216
+ return { index: i, limit: limit };
4819
5217
  }
4820
5218
  }
4821
5219
  return null;
@@ -4828,12 +5226,13 @@ function applyAssistantAggregateLimit(pipeline, limit, maxLimit, defaultLimit) {
4828
5226
  ? Math.min(limit, maxLimit)
4829
5227
  : defaultLimit;
4830
5228
  var existingLimit = findAggregateLimit(normalizedPipeline);
4831
- if (existingLimit === null) {
5229
+ if (!existingLimit) {
4832
5230
  normalizedPipeline.push({ $limit: requestedLimit });
4833
5231
  return normalizedPipeline;
4834
5232
  }
4835
- if (existingLimit > maxLimit) {
4836
- normalizedPipeline.push({ $limit: maxLimit });
5233
+ if (existingLimit.limit > maxLimit) {
5234
+ var stage = normalizedPipeline[existingLimit.index];
5235
+ normalizedPipeline[existingLimit.index] = __assign(__assign({}, stage), { $limit: maxLimit });
4837
5236
  }
4838
5237
  return normalizedPipeline;
4839
5238
  }
@@ -4893,7 +5292,7 @@ function matchContainsField(value, field) {
4893
5292
  });
4894
5293
  }
4895
5294
  function resolveAggregateCompletionFallback(pipeline) {
4896
- var e_10, _a;
5295
+ var e_11, _a;
4897
5296
  if (!Array.isArray(pipeline)) {
4898
5297
  return null;
4899
5298
  }
@@ -4906,7 +5305,7 @@ function resolveAggregateCompletionFallback(pipeline) {
4906
5305
  }
4907
5306
  var addFields = stage.$addFields;
4908
5307
  try {
4909
- for (var _b = (e_10 = void 0, __values(Object.keys(addFields))), _c = _b.next(); !_c.done; _c = _b.next()) {
5308
+ for (var _b = (e_11 = void 0, __values(Object.keys(addFields))), _c = _b.next(); !_c.done; _c = _b.next()) {
4910
5309
  var key = _c.value;
4911
5310
  if (!isCompletionFieldName(key)) {
4912
5311
  continue;
@@ -4920,12 +5319,12 @@ function resolveAggregateCompletionFallback(pipeline) {
4920
5319
  }
4921
5320
  }
4922
5321
  }
4923
- catch (e_10_1) { e_10 = { error: e_10_1 }; }
5322
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
4924
5323
  finally {
4925
5324
  try {
4926
5325
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
4927
5326
  }
4928
- finally { if (e_10) throw e_10.error; }
5327
+ finally { if (e_11) throw e_11.error; }
4929
5328
  }
4930
5329
  if (candidateField) {
4931
5330
  break;
@@ -5081,7 +5480,7 @@ function buildCompletionFallbackSources(field) {
5081
5480
  ]);
5082
5481
  }
5083
5482
  function resolveAggregateCompletionExprFallback(pipeline) {
5084
- var e_11, _a;
5483
+ var e_12, _a;
5085
5484
  if (!Array.isArray(pipeline)) {
5086
5485
  return null;
5087
5486
  }
@@ -5101,7 +5500,7 @@ function resolveAggregateCompletionExprFallback(pipeline) {
5101
5500
  }
5102
5501
  if (!candidateField) {
5103
5502
  try {
5104
- for (var _b = (e_11 = void 0, __values(Object.keys(matchStage))), _c = _b.next(); !_c.done; _c = _b.next()) {
5503
+ for (var _b = (e_12 = void 0, __values(Object.keys(matchStage))), _c = _b.next(); !_c.done; _c = _b.next()) {
5105
5504
  var key = _c.value;
5106
5505
  if (key.startsWith('$')) {
5107
5506
  continue;
@@ -5116,12 +5515,12 @@ function resolveAggregateCompletionExprFallback(pipeline) {
5116
5515
  }
5117
5516
  }
5118
5517
  }
5119
- catch (e_11_1) { e_11 = { error: e_11_1 }; }
5518
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
5120
5519
  finally {
5121
5520
  try {
5122
5521
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
5123
5522
  }
5124
- finally { if (e_11) throw e_11.error; }
5523
+ finally { if (e_12) throw e_12.error; }
5125
5524
  }
5126
5525
  }
5127
5526
  if (!candidateField) {
@@ -5291,7 +5690,7 @@ function isRegexMatchCondition(value) {
5291
5690
  return false;
5292
5691
  }
5293
5692
  function findRegexMatchInMatchObject(match, prefix) {
5294
- var e_12, _a, e_13, _b;
5693
+ var e_13, _a, e_14, _b;
5295
5694
  if (prefix === void 0) { prefix = ''; }
5296
5695
  if (Array.isArray(match)) {
5297
5696
  try {
@@ -5303,12 +5702,12 @@ function findRegexMatchInMatchObject(match, prefix) {
5303
5702
  }
5304
5703
  }
5305
5704
  }
5306
- catch (e_12_1) { e_12 = { error: e_12_1 }; }
5705
+ catch (e_13_1) { e_13 = { error: e_13_1 }; }
5307
5706
  finally {
5308
5707
  try {
5309
5708
  if (match_1_1 && !match_1_1.done && (_a = match_1.return)) _a.call(match_1);
5310
5709
  }
5311
- finally { if (e_12) throw e_12.error; }
5710
+ finally { if (e_13) throw e_13.error; }
5312
5711
  }
5313
5712
  return null;
5314
5713
  }
@@ -5339,12 +5738,12 @@ function findRegexMatchInMatchObject(match, prefix) {
5339
5738
  }
5340
5739
  }
5341
5740
  }
5342
- catch (e_13_1) { e_13 = { error: e_13_1 }; }
5741
+ catch (e_14_1) { e_14 = { error: e_14_1 }; }
5343
5742
  finally {
5344
5743
  try {
5345
5744
  if (keys_2_1 && !keys_2_1.done && (_b = keys_2.return)) _b.call(keys_2);
5346
5745
  }
5347
- finally { if (e_13) throw e_13.error; }
5746
+ finally { if (e_14) throw e_14.error; }
5348
5747
  }
5349
5748
  return null;
5350
5749
  }
@@ -5499,39 +5898,45 @@ function isEmptyMatchValue(value) {
5499
5898
  return false;
5500
5899
  }
5501
5900
  function stripMatchField(match, field) {
5502
- if (Array.isArray(match)) {
5503
- var strippedArray = match
5504
- .map(function (entry) { return stripMatchField(entry, field); })
5505
- .filter(function (entry) { return !isEmptyMatchValue(entry); });
5506
- return strippedArray;
5507
- }
5508
- if (!match || typeof match !== 'object') {
5509
- return match;
5510
- }
5511
- var result = {};
5512
- Object.keys(match).forEach(function (key) {
5513
- if (key === field) {
5514
- return;
5901
+ var hasPath = field.includes('.');
5902
+ var stripValue = function (value, prefix) {
5903
+ if (Array.isArray(value)) {
5904
+ var strippedArray = value
5905
+ .map(function (entry) { return stripValue(entry, prefix); })
5906
+ .filter(function (entry) { return !isEmptyMatchValue(entry); });
5907
+ return strippedArray;
5515
5908
  }
5516
- var value = match[key];
5517
- if (key.startsWith('$')) {
5518
- var stripped = stripMatchField(value, field);
5519
- if (isEmptyMatchValue(stripped) && (key === '$and' || key === '$or')) {
5909
+ if (!value || typeof value !== 'object') {
5910
+ return value;
5911
+ }
5912
+ var result = {};
5913
+ Object.keys(value).forEach(function (key) {
5914
+ var entry = value[key];
5915
+ var currentPath = prefix ? "".concat(prefix, ".").concat(key) : key;
5916
+ var matches = hasPath ? currentPath === field : key === field;
5917
+ if (matches) {
5520
5918
  return;
5521
5919
  }
5522
- result[key] = stripped;
5523
- return;
5524
- }
5525
- if (value && typeof value === 'object') {
5526
- var stripped = stripMatchField(value, field);
5527
- if (!isEmptyMatchValue(stripped)) {
5920
+ if (key.startsWith('$')) {
5921
+ var stripped = stripValue(entry, prefix);
5922
+ if (isEmptyMatchValue(stripped) && (key === '$and' || key === '$or')) {
5923
+ return;
5924
+ }
5528
5925
  result[key] = stripped;
5926
+ return;
5529
5927
  }
5530
- return;
5531
- }
5532
- result[key] = value;
5533
- });
5534
- return result;
5928
+ if (entry && typeof entry === 'object') {
5929
+ var stripped = stripValue(entry, currentPath);
5930
+ if (!isEmptyMatchValue(stripped)) {
5931
+ result[key] = stripped;
5932
+ }
5933
+ return;
5934
+ }
5935
+ result[key] = entry;
5936
+ });
5937
+ return result;
5938
+ };
5939
+ return stripValue(match, '');
5535
5940
  }
5536
5941
  function collectMatchFieldsByCondition(match, predicate, prefix) {
5537
5942
  if (prefix === void 0) { prefix = ''; }
@@ -5562,7 +5967,7 @@ function collectMatchFieldsByCondition(match, predicate, prefix) {
5562
5967
  return results;
5563
5968
  }
5564
5969
  function findMatchConditionForField(match, targetField, prefix) {
5565
- var e_14, _a, e_15, _b;
5970
+ var e_15, _a, e_16, _b;
5566
5971
  if (prefix === void 0) { prefix = ''; }
5567
5972
  if (!match || typeof match !== 'object') {
5568
5973
  return undefined;
@@ -5577,12 +5982,12 @@ function findMatchConditionForField(match, targetField, prefix) {
5577
5982
  }
5578
5983
  }
5579
5984
  }
5580
- catch (e_14_1) { e_14 = { error: e_14_1 }; }
5985
+ catch (e_15_1) { e_15 = { error: e_15_1 }; }
5581
5986
  finally {
5582
5987
  try {
5583
5988
  if (match_2_1 && !match_2_1.done && (_a = match_2.return)) _a.call(match_2);
5584
5989
  }
5585
- finally { if (e_14) throw e_14.error; }
5990
+ finally { if (e_15) throw e_15.error; }
5586
5991
  }
5587
5992
  return undefined;
5588
5993
  }
@@ -5609,12 +6014,12 @@ function findMatchConditionForField(match, targetField, prefix) {
5609
6014
  }
5610
6015
  }
5611
6016
  }
5612
- catch (e_15_1) { e_15 = { error: e_15_1 }; }
6017
+ catch (e_16_1) { e_16 = { error: e_16_1 }; }
5613
6018
  finally {
5614
6019
  try {
5615
6020
  if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
5616
6021
  }
5617
- finally { if (e_15) throw e_15.error; }
6022
+ finally { if (e_16) throw e_16.error; }
5618
6023
  }
5619
6024
  return undefined;
5620
6025
  }
@@ -5657,7 +6062,7 @@ function detectIdLikeValue(value) {
5657
6062
  return false;
5658
6063
  }
5659
6064
  function detectChemicalIdFromProbe(probeDocs, fields) {
5660
- var e_16, _a, e_17, _b;
6065
+ var e_17, _a, e_18, _b;
5661
6066
  if (!Array.isArray(probeDocs) || !probeDocs.length) {
5662
6067
  return false;
5663
6068
  }
@@ -5669,7 +6074,7 @@ function detectChemicalIdFromProbe(probeDocs, fields) {
5669
6074
  for (var probeDocs_1 = __values(probeDocs), probeDocs_1_1 = probeDocs_1.next(); !probeDocs_1_1.done; probeDocs_1_1 = probeDocs_1.next()) {
5670
6075
  var doc = probeDocs_1_1.value;
5671
6076
  try {
5672
- for (var targets_1 = (e_17 = void 0, __values(targets)), targets_1_1 = targets_1.next(); !targets_1_1.done; targets_1_1 = targets_1.next()) {
6077
+ for (var targets_1 = (e_18 = void 0, __values(targets)), targets_1_1 = targets_1.next(); !targets_1_1.done; targets_1_1 = targets_1.next()) {
5673
6078
  var field = targets_1_1.value;
5674
6079
  var value = getValueAtPath(doc, field);
5675
6080
  if (Array.isArray(value)) {
@@ -5682,21 +6087,21 @@ function detectChemicalIdFromProbe(probeDocs, fields) {
5682
6087
  }
5683
6088
  }
5684
6089
  }
5685
- catch (e_17_1) { e_17 = { error: e_17_1 }; }
6090
+ catch (e_18_1) { e_18 = { error: e_18_1 }; }
5686
6091
  finally {
5687
6092
  try {
5688
6093
  if (targets_1_1 && !targets_1_1.done && (_b = targets_1.return)) _b.call(targets_1);
5689
6094
  }
5690
- finally { if (e_17) throw e_17.error; }
6095
+ finally { if (e_18) throw e_18.error; }
5691
6096
  }
5692
6097
  }
5693
6098
  }
5694
- catch (e_16_1) { e_16 = { error: e_16_1 }; }
6099
+ catch (e_17_1) { e_17 = { error: e_17_1 }; }
5695
6100
  finally {
5696
6101
  try {
5697
6102
  if (probeDocs_1_1 && !probeDocs_1_1.done && (_a = probeDocs_1.return)) _a.call(probeDocs_1);
5698
6103
  }
5699
- finally { if (e_16) throw e_16.error; }
6104
+ finally { if (e_17) throw e_17.error; }
5700
6105
  }
5701
6106
  return false;
5702
6107
  }
@@ -5846,9 +6251,9 @@ function isIdLookupCondition(value) {
5846
6251
  }
5847
6252
  function collectIdFieldConditions(match) {
5848
6253
  var results = [];
5849
- var visit = function (value) {
6254
+ var visit = function (value, prefix) {
5850
6255
  if (Array.isArray(value)) {
5851
- value.forEach(function (entry) { return visit(entry); });
6256
+ value.forEach(function (entry) { return visit(entry, prefix); });
5852
6257
  return;
5853
6258
  }
5854
6259
  if (!value || typeof value !== 'object') {
@@ -5857,19 +6262,20 @@ function collectIdFieldConditions(match) {
5857
6262
  Object.keys(value).forEach(function (key) {
5858
6263
  var entry = value[key];
5859
6264
  if (key.startsWith('$')) {
5860
- visit(entry);
6265
+ visit(entry, prefix);
5861
6266
  return;
5862
6267
  }
6268
+ var currentPath = prefix ? "".concat(prefix, ".").concat(key) : key;
5863
6269
  if (isAssistantIdField(key) && isIdLookupCondition(entry)) {
5864
- results.push({ field: key, condition: entry });
6270
+ results.push({ field: currentPath, condition: entry });
5865
6271
  return;
5866
6272
  }
5867
6273
  if (entry && typeof entry === 'object') {
5868
- visit(entry);
6274
+ visit(entry, currentPath);
5869
6275
  }
5870
6276
  });
5871
6277
  };
5872
- visit(match);
6278
+ visit(match, '');
5873
6279
  return results;
5874
6280
  }
5875
6281
  function resolveLocalNameFieldFromDocs(docs, baseToken) {
@@ -5916,8 +6322,8 @@ function buildChemicalIdFieldCandidates(field) {
5916
6322
  }
5917
6323
  function applyChemicalNameLookupFallbackToQuery(params) {
5918
6324
  return __awaiter(this, void 0, void 0, function () {
5919
- var query, db, dbName, idClient, idCustomer, isSuperAdmin, probeDocs, chemicalFields, targetField, condition, regex, sampleDocs, collectionNames, candidates, _loop_6, candidates_2, candidates_2_1, candidate, state_4, e_18_1;
5920
- var e_18, _a;
6325
+ var query, db, dbName, idClient, idCustomer, isSuperAdmin, probeDocs, chemicalFields, targetField, condition, regex, sampleDocs, collectionNames, candidates, _loop_6, candidates_2, candidates_2_1, candidate, state_4, e_19_1;
6326
+ var e_19, _a;
5921
6327
  var _b;
5922
6328
  return __generator(this, function (_c) {
5923
6329
  switch (_c.label) {
@@ -6030,14 +6436,14 @@ function applyChemicalNameLookupFallbackToQuery(params) {
6030
6436
  return [3 /*break*/, 3];
6031
6437
  case 6: return [3 /*break*/, 9];
6032
6438
  case 7:
6033
- e_18_1 = _c.sent();
6034
- e_18 = { error: e_18_1 };
6439
+ e_19_1 = _c.sent();
6440
+ e_19 = { error: e_19_1 };
6035
6441
  return [3 /*break*/, 9];
6036
6442
  case 8:
6037
6443
  try {
6038
6444
  if (candidates_2_1 && !candidates_2_1.done && (_a = candidates_2.return)) _a.call(candidates_2);
6039
6445
  }
6040
- finally { if (e_18) throw e_18.error; }
6446
+ finally { if (e_19) throw e_19.error; }
6041
6447
  return [7 /*endfinally*/];
6042
6448
  case 9: return [2 /*return*/, null];
6043
6449
  }
@@ -6131,8 +6537,8 @@ function lookupIdsForNameMatch(params) {
6131
6537
  }
6132
6538
  function applyIdLookupFallbackToQuery(params) {
6133
6539
  return __awaiter(this, void 0, void 0, function () {
6134
- var query, db, dbName, idClient, idCustomer, isSuperAdmin, probeDocs, conditions, collectionNames, _a, conditions_1, conditions_1_1, condition, regex, baseToken, targetFieldType, nextValue, localNameField, candidates, candidates_3, candidates_3_1, candidate, candidateHasClientScope, _b, candidateProbe, lookup, targetFieldType, normalizedIds, idsForQuery, e_19_1, e_20_1;
6135
- var e_20, _c, e_19, _d;
6540
+ var query, db, dbName, idClient, idCustomer, isSuperAdmin, probeDocs, conditions, collectionNames, _a, conditions_1, conditions_1_1, condition, regex, baseToken, targetFieldType, nextValue, localNameField, candidates, candidates_3, candidates_3_1, candidate, candidateHasClientScope, _b, candidateProbe, lookup, targetFieldType, normalizedIds, idsForQuery, e_20_1, e_21_1;
6541
+ var e_21, _c, e_20, _d;
6136
6542
  var _e;
6137
6543
  return __generator(this, function (_f) {
6138
6544
  switch (_f.label) {
@@ -6202,7 +6608,7 @@ function applyIdLookupFallbackToQuery(params) {
6202
6608
  _f.label = 5;
6203
6609
  case 5:
6204
6610
  _f.trys.push([5, 14, 15, 16]);
6205
- candidates_3 = (e_19 = void 0, __values(candidates)), candidates_3_1 = candidates_3.next();
6611
+ candidates_3 = (e_20 = void 0, __values(candidates)), candidates_3_1 = candidates_3.next();
6206
6612
  _f.label = 6;
6207
6613
  case 6:
6208
6614
  if (!!candidates_3_1.done) return [3 /*break*/, 13];
@@ -6269,28 +6675,28 @@ function applyIdLookupFallbackToQuery(params) {
6269
6675
  return [3 /*break*/, 6];
6270
6676
  case 13: return [3 /*break*/, 16];
6271
6677
  case 14:
6272
- e_19_1 = _f.sent();
6273
- e_19 = { error: e_19_1 };
6678
+ e_20_1 = _f.sent();
6679
+ e_20 = { error: e_20_1 };
6274
6680
  return [3 /*break*/, 16];
6275
6681
  case 15:
6276
6682
  try {
6277
6683
  if (candidates_3_1 && !candidates_3_1.done && (_d = candidates_3.return)) _d.call(candidates_3);
6278
6684
  }
6279
- finally { if (e_19) throw e_19.error; }
6685
+ finally { if (e_20) throw e_20.error; }
6280
6686
  return [7 /*endfinally*/];
6281
6687
  case 16:
6282
6688
  conditions_1_1 = conditions_1.next();
6283
6689
  return [3 /*break*/, 4];
6284
6690
  case 17: return [3 /*break*/, 20];
6285
6691
  case 18:
6286
- e_20_1 = _f.sent();
6287
- e_20 = { error: e_20_1 };
6692
+ e_21_1 = _f.sent();
6693
+ e_21 = { error: e_21_1 };
6288
6694
  return [3 /*break*/, 20];
6289
6695
  case 19:
6290
6696
  try {
6291
6697
  if (conditions_1_1 && !conditions_1_1.done && (_c = conditions_1.return)) _c.call(conditions_1);
6292
6698
  }
6293
- finally { if (e_20) throw e_20.error; }
6699
+ finally { if (e_21) throw e_21.error; }
6294
6700
  return [7 /*endfinally*/];
6295
6701
  case 20: return [2 /*return*/, null];
6296
6702
  }
@@ -6384,8 +6790,12 @@ function replaceAggregateDateField(pipeline, fromField, toField) {
6384
6790
  return next_2;
6385
6791
  }
6386
6792
  if (typeof value === 'string') {
6387
- if (value.startsWith("$".concat(fromField))) {
6388
- return "$".concat(toField).concat(value.slice(fromField.length + 1));
6793
+ var fromRef = "$".concat(fromField);
6794
+ if (value === fromRef) {
6795
+ return "$".concat(toField);
6796
+ }
6797
+ if (value.startsWith("".concat(fromRef, "."))) {
6798
+ return "$".concat(toField).concat(value.slice(fromRef.length));
6389
6799
  }
6390
6800
  return value;
6391
6801
  }
@@ -6437,8 +6847,17 @@ function buildTokenizedRegex(value) {
6437
6847
  var tokenPattern = tokens.map(function (token) { return escapeRegexValue(token); }).join('[\\s\\-_]*.*');
6438
6848
  return new RegExp(tokenPattern, 'i');
6439
6849
  }
6440
- function applyAssistantNameRegexToQuery(query) {
6850
+ function applyAssistantNameRegexToQuery(query, fieldContext) {
6441
6851
  if (Array.isArray(query)) {
6852
+ if (fieldContext && shouldApplyAssistantNameRegex(fieldContext)) {
6853
+ return query.map(function (entry) {
6854
+ if (typeof entry === 'string') {
6855
+ var trimmed = entry.trim();
6856
+ return trimmed ? buildTokenizedRegex(trimmed) : entry;
6857
+ }
6858
+ return applyAssistantNameRegexToQuery(entry, fieldContext);
6859
+ });
6860
+ }
6442
6861
  return query.map(function (entry) { return applyAssistantNameRegexToQuery(entry); });
6443
6862
  }
6444
6863
  if (!query || typeof query !== 'object' || query instanceof Date || query instanceof RegExp || isMongoObjectId(query)) {
@@ -6448,7 +6867,7 @@ function applyAssistantNameRegexToQuery(query) {
6448
6867
  Object.keys(query).forEach(function (key) {
6449
6868
  var value = query[key];
6450
6869
  if (key.startsWith('$')) {
6451
- result[key] = applyAssistantNameRegexToQuery(value);
6870
+ result[key] = applyAssistantNameRegexToQuery(value, fieldContext);
6452
6871
  return;
6453
6872
  }
6454
6873
  if (typeof value === 'string' && shouldApplyAssistantNameRegex(key)) {
@@ -6457,7 +6876,7 @@ function applyAssistantNameRegexToQuery(query) {
6457
6876
  return;
6458
6877
  }
6459
6878
  if (value && typeof value === 'object') {
6460
- result[key] = applyAssistantNameRegexToQuery(value);
6879
+ result[key] = applyAssistantNameRegexToQuery(value, key);
6461
6880
  return;
6462
6881
  }
6463
6882
  result[key] = value;
@@ -6480,13 +6899,13 @@ function hasOperatorKeys(value) {
6480
6899
  return Object.keys(value).some(function (key) { return key.startsWith('$'); });
6481
6900
  }
6482
6901
  function rewriteEmbeddedMatchObjects(query) {
6483
- var rewriteValue = function (value, allowArrayRewrite, inOperator) {
6484
- if (inOperator === void 0) { inOperator = false; }
6902
+ var isLogicalOperatorKey = function (key) { return key === '$or' || key === '$and' || key === '$nor'; };
6903
+ var rewriteValue = function (value, allowArrayRewrite, context) {
6485
6904
  if (Array.isArray(value)) {
6486
6905
  if (!allowArrayRewrite) {
6487
6906
  return value;
6488
6907
  }
6489
- return value.map(function (entry) { return rewriteValue(entry, true, inOperator); });
6908
+ return value.map(function (entry) { return rewriteValue(entry, true, context); });
6490
6909
  }
6491
6910
  if (!value || typeof value !== 'object' || value instanceof Date || value instanceof RegExp || isMongoObjectId(value)) {
6492
6911
  return value;
@@ -6495,38 +6914,39 @@ function rewriteEmbeddedMatchObjects(query) {
6495
6914
  Object.keys(value).forEach(function (key) {
6496
6915
  var entry = value[key];
6497
6916
  if (key.startsWith('$')) {
6498
- result[key] = rewriteValue(entry, true, true);
6917
+ var nextContext = isLogicalOperatorKey(key) ? 'logical' : 'fieldOperator';
6918
+ result[key] = rewriteValue(entry, true, nextContext);
6499
6919
  return;
6500
6920
  }
6501
- if (!inOperator && isPlainMatchObject(entry) && !Array.isArray(entry) && !hasOperatorKeys(entry)) {
6502
- var flattened = flattenMatchObject(entry, key, inOperator);
6921
+ if (context !== 'fieldOperator' && isPlainMatchObject(entry) && !Array.isArray(entry) && !hasOperatorKeys(entry)) {
6922
+ var flattened = flattenMatchObject(entry, key, context);
6503
6923
  Object.assign(result, flattened);
6504
6924
  return;
6505
6925
  }
6506
6926
  if (isPlainMatchObject(entry) && !Array.isArray(entry)) {
6507
- result[key] = rewriteValue(entry, true, inOperator);
6927
+ result[key] = rewriteValue(entry, true, context);
6508
6928
  return;
6509
6929
  }
6510
6930
  if (Array.isArray(entry)) {
6511
- result[key] = allowArrayRewrite ? entry.map(function (item) { return rewriteValue(item, true, inOperator); }) : entry;
6931
+ result[key] = allowArrayRewrite ? entry.map(function (item) { return rewriteValue(item, true, context); }) : entry;
6512
6932
  return;
6513
6933
  }
6514
6934
  result[key] = entry;
6515
6935
  });
6516
6936
  return result;
6517
6937
  };
6518
- var flattenMatchObject = function (value, prefix, inOperator) {
6938
+ var flattenMatchObject = function (value, prefix, context) {
6519
6939
  var result = {};
6520
6940
  Object.keys(value || {}).forEach(function (key) {
6521
6941
  var entry = value[key];
6522
6942
  var currentPath = "".concat(prefix, ".").concat(key);
6523
6943
  if (isPlainMatchObject(entry) && !Array.isArray(entry) && !hasOperatorKeys(entry)) {
6524
- var flattened = flattenMatchObject(entry, currentPath, inOperator);
6944
+ var flattened = flattenMatchObject(entry, currentPath, context);
6525
6945
  Object.assign(result, flattened);
6526
6946
  return;
6527
6947
  }
6528
6948
  if (isPlainMatchObject(entry) && !Array.isArray(entry)) {
6529
- result[currentPath] = rewriteValue(entry, true, inOperator);
6949
+ result[currentPath] = rewriteValue(entry, true, context);
6530
6950
  return;
6531
6951
  }
6532
6952
  if (Array.isArray(entry)) {
@@ -6537,7 +6957,7 @@ function rewriteEmbeddedMatchObjects(query) {
6537
6957
  });
6538
6958
  return result;
6539
6959
  };
6540
- return rewriteValue(query, true);
6960
+ return rewriteValue(query, true, 'root');
6541
6961
  }
6542
6962
  function buildRegexFromCondition(condition) {
6543
6963
  if (!condition) {
@@ -7072,7 +7492,7 @@ function resolveAssistantCollectionName(db, dbName, requested) {
7072
7492
  });
7073
7493
  }
7074
7494
  function findQueryDateField(query) {
7075
- var e_21, _a, e_22, _b;
7495
+ var e_22, _a, e_23, _b;
7076
7496
  if (!query || typeof query !== 'object') {
7077
7497
  return null;
7078
7498
  }
@@ -7086,12 +7506,12 @@ function findQueryDateField(query) {
7086
7506
  }
7087
7507
  }
7088
7508
  }
7089
- catch (e_21_1) { e_21 = { error: e_21_1 }; }
7509
+ catch (e_22_1) { e_22 = { error: e_22_1 }; }
7090
7510
  finally {
7091
7511
  try {
7092
7512
  if (query_1_1 && !query_1_1.done && (_a = query_1.return)) _a.call(query_1);
7093
7513
  }
7094
- finally { if (e_21) throw e_21.error; }
7514
+ finally { if (e_22) throw e_22.error; }
7095
7515
  }
7096
7516
  return null;
7097
7517
  }
@@ -7110,12 +7530,12 @@ function findQueryDateField(query) {
7110
7530
  }
7111
7531
  }
7112
7532
  }
7113
- catch (e_22_1) { e_22 = { error: e_22_1 }; }
7533
+ catch (e_23_1) { e_23 = { error: e_23_1 }; }
7114
7534
  finally {
7115
7535
  try {
7116
7536
  if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
7117
7537
  }
7118
- finally { if (e_22) throw e_22.error; }
7538
+ finally { if (e_23) throw e_23.error; }
7119
7539
  }
7120
7540
  return null;
7121
7541
  }
@@ -7337,7 +7757,7 @@ function resolveQueryDateFieldFallback(query) {
7337
7757
  return { from: dateField, to: fallback };
7338
7758
  }
7339
7759
  function containsForbiddenMongoOperators(value) {
7340
- var e_23, _a;
7760
+ var e_24, _a;
7341
7761
  if (!value || typeof value !== 'object') {
7342
7762
  return false;
7343
7763
  }
@@ -7356,12 +7776,12 @@ function containsForbiddenMongoOperators(value) {
7356
7776
  }
7357
7777
  }
7358
7778
  }
7359
- catch (e_23_1) { e_23 = { error: e_23_1 }; }
7779
+ catch (e_24_1) { e_24 = { error: e_24_1 }; }
7360
7780
  finally {
7361
7781
  try {
7362
7782
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
7363
7783
  }
7364
- finally { if (e_23) throw e_23.error; }
7784
+ finally { if (e_24) throw e_24.error; }
7365
7785
  }
7366
7786
  return false;
7367
7787
  }
@@ -7652,8 +8072,8 @@ function applyCodexStreamStatusHandler(runOptions, streamStatusHandler) {
7652
8072
  }
7653
8073
  function waitForCodexWorkerMessage(worker, streamStatusHandler) {
7654
8074
  return __awaiter(this, void 0, void 0, function () {
7655
- var _a, _b, _c, _d, message, payload, status_1, e_24_1;
7656
- var _e, e_24, _f, _g;
8075
+ var _a, _b, _c, _d, message, payload, status_1, e_25_1;
8076
+ var _e, e_25, _f, _g;
7657
8077
  return __generator(this, function (_h) {
7658
8078
  switch (_h.label) {
7659
8079
  case 0:
@@ -7680,8 +8100,8 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
7680
8100
  return [3 /*break*/, 1];
7681
8101
  case 4: return [3 /*break*/, 11];
7682
8102
  case 5:
7683
- e_24_1 = _h.sent();
7684
- e_24 = { error: e_24_1 };
8103
+ e_25_1 = _h.sent();
8104
+ e_25 = { error: e_25_1 };
7685
8105
  return [3 /*break*/, 11];
7686
8106
  case 6:
7687
8107
  _h.trys.push([6, , 9, 10]);
@@ -7692,7 +8112,7 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
7692
8112
  _h.label = 8;
7693
8113
  case 8: return [3 /*break*/, 10];
7694
8114
  case 9:
7695
- if (e_24) throw e_24.error;
8115
+ if (e_25) throw e_25.error;
7696
8116
  return [7 /*endfinally*/];
7697
8117
  case 10: return [7 /*endfinally*/];
7698
8118
  case 11: throw new CodexWorkerBootstrapError('Codex worker exited before completing.');
@@ -8145,6 +8565,88 @@ function buildAssistantCodexPrompt(message, attachmentText, historyText, context
8145
8565
  var historyBlock = trimmedHistory ? "\n\nConversation so far:\n".concat(trimmedHistory) : '';
8146
8566
  return "System:\n".concat(AI_ASSISTANT_SYSTEM_PROMPT).concat(contextBlock).concat(historyBlock, "\n\nUser:\n").concat(message).concat(attachmentText || '').trim();
8147
8567
  }
8568
+ function resolveAssistantPlannerEnabled() {
8569
+ var _a;
8570
+ var config = ((_a = resolveio_server_app_1.ResolveIOServer.getServerConfig) === null || _a === void 0 ? void 0 : _a.call(resolveio_server_app_1.ResolveIOServer)) || {};
8571
+ var raw = normalizeOptionalBoolean(config['AI_ASSISTANT_CODEX_PLANNER_ENABLED']
8572
+ || process.env.AI_ASSISTANT_CODEX_PLANNER_ENABLED);
8573
+ return raw === undefined ? true : raw === true;
8574
+ }
8575
+ function resolveAssistantPlannerKnownRoutes() {
8576
+ var e_26, _a;
8577
+ var _b;
8578
+ var routes = ((_b = resolveio_server_app_1.ResolveIOServer.getClientRoutes) === null || _b === void 0 ? void 0 : _b.call(resolveio_server_app_1.ResolveIOServer)) || [];
8579
+ var unique = new Set();
8580
+ try {
8581
+ for (var routes_1 = __values(routes), routes_1_1 = routes_1.next(); !routes_1_1.done; routes_1_1 = routes_1.next()) {
8582
+ var route = routes_1_1.value;
8583
+ var normalized = normalizeRouteKey(route);
8584
+ if (normalized) {
8585
+ unique.add(normalized);
8586
+ }
8587
+ }
8588
+ }
8589
+ catch (e_26_1) { e_26 = { error: e_26_1 }; }
8590
+ finally {
8591
+ try {
8592
+ if (routes_1_1 && !routes_1_1.done && (_a = routes_1.return)) _a.call(routes_1);
8593
+ }
8594
+ finally { if (e_26) throw e_26.error; }
8595
+ }
8596
+ return Array.from(unique).slice(0, AI_ASSISTANT_PLANNER_MAX_ROUTES);
8597
+ }
8598
+ function buildAssistantPlannerUserSnapshot(user, inputClientId) {
8599
+ var _a, _b, _c, _d, _e;
8600
+ var groups = Array.isArray((_a = user === null || user === void 0 ? void 0 : user.roles) === null || _a === void 0 ? void 0 : _a.groups)
8601
+ ? user.roles.groups.map(function (group) { return ({
8602
+ name: normalizeOptionalString(group === null || group === void 0 ? void 0 : group.name) || undefined,
8603
+ views: Array.isArray(group === null || group === void 0 ? void 0 : group.views) ? group.views.filter(Boolean) : []
8604
+ }); })
8605
+ : [];
8606
+ var miscs = Array.isArray((_b = user === null || user === void 0 ? void 0 : user.roles) === null || _b === void 0 ? void 0 : _b.miscs)
8607
+ ? user.roles.miscs.filter(Boolean)
8608
+ : [];
8609
+ var other = {};
8610
+ var customerId = normalizeOptionalString((_c = user === null || user === void 0 ? void 0 : user.other) === null || _c === void 0 ? void 0 : _c.id_customer);
8611
+ if (customerId) {
8612
+ other.id_customer = customerId;
8613
+ }
8614
+ var clientId = normalizeOptionalString(inputClientId) || normalizeOptionalString((_d = user === null || user === void 0 ? void 0 : user.other) === null || _d === void 0 ? void 0 : _d.id_client);
8615
+ var snapshot = {
8616
+ _id: (user === null || user === void 0 ? void 0 : user._id) ? String(user._id) : undefined,
8617
+ username: normalizeOptionalString(user === null || user === void 0 ? void 0 : user.username) || undefined,
8618
+ fullname: normalizeOptionalString(user === null || user === void 0 ? void 0 : user.fullname) || undefined,
8619
+ roles: {
8620
+ super_admin: !!((_e = user === null || user === void 0 ? void 0 : user.roles) === null || _e === void 0 ? void 0 : _e.super_admin),
8621
+ groups: groups,
8622
+ miscs: miscs
8623
+ }
8624
+ };
8625
+ if (Object.keys(other).length) {
8626
+ snapshot.other = other;
8627
+ }
8628
+ if (clientId) {
8629
+ snapshot.id_client = clientId;
8630
+ }
8631
+ return snapshot;
8632
+ }
8633
+ function buildAssistantPlannerPrompt(params) {
8634
+ var todayIso = new Date().toISOString().slice(0, 10);
8635
+ var userMessage = "".concat(params.message || '').concat(params.attachmentText || '').trim();
8636
+ var currentRoute = normalizeOptionalString(params.contextRoute || '') || 'null';
8637
+ var userSnapshot = buildAssistantPlannerUserSnapshot(params.user, params.inputClientId);
8638
+ var templateData = {
8639
+ today_iso: todayIso,
8640
+ user_message: userMessage || '',
8641
+ current_route: currentRoute,
8642
+ known_routes_json_array: JSON.stringify(params.knownRoutes || []),
8643
+ user_json: JSON.stringify(userSnapshot || {}),
8644
+ collection_hints_json_array: JSON.stringify(params.collectionHints || []),
8645
+ field_hints_json_array: JSON.stringify(params.fieldHints || [])
8646
+ };
8647
+ var userPrompt = applyTemplate(AI_ASSISTANT_PLANNER_USER_PROMPT_TEMPLATE, templateData);
8648
+ return "System:\n".concat(AI_ASSISTANT_PLANNER_SYSTEM_PROMPT, "\n\nUser:\n").concat(userPrompt).trim();
8649
+ }
8148
8650
  function buildAssistantContext(input, userContext) {
8149
8651
  var _a, _b, _c, _d, _e, _f;
8150
8652
  var lines = [];
@@ -8300,14 +8802,14 @@ function normalizeRouteMatchKey(value) {
8300
8802
  return normalizeRouteKey(value).toLowerCase();
8301
8803
  }
8302
8804
  function buildClientRouteIndex() {
8303
- var e_25, _a;
8805
+ var e_27, _a;
8304
8806
  var _b;
8305
8807
  var routes = ((_b = resolveio_server_app_1.ResolveIOServer.getClientRoutes) === null || _b === void 0 ? void 0 : _b.call(resolveio_server_app_1.ResolveIOServer)) || [];
8306
8808
  var set = new Set();
8307
8809
  var map = new Map();
8308
8810
  try {
8309
- for (var routes_1 = __values(routes), routes_1_1 = routes_1.next(); !routes_1_1.done; routes_1_1 = routes_1.next()) {
8310
- var route = routes_1_1.value;
8811
+ for (var routes_2 = __values(routes), routes_2_1 = routes_2.next(); !routes_2_1.done; routes_2_1 = routes_2.next()) {
8812
+ var route = routes_2_1.value;
8311
8813
  var normalized = normalizeRouteKey(route);
8312
8814
  if (!normalized) {
8313
8815
  continue;
@@ -8319,12 +8821,12 @@ function buildClientRouteIndex() {
8319
8821
  }
8320
8822
  }
8321
8823
  }
8322
- catch (e_25_1) { e_25 = { error: e_25_1 }; }
8824
+ catch (e_27_1) { e_27 = { error: e_27_1 }; }
8323
8825
  finally {
8324
8826
  try {
8325
- if (routes_1_1 && !routes_1_1.done && (_a = routes_1.return)) _a.call(routes_1);
8827
+ if (routes_2_1 && !routes_2_1.done && (_a = routes_2.return)) _a.call(routes_2);
8326
8828
  }
8327
- finally { if (e_25) throw e_25.error; }
8829
+ finally { if (e_27) throw e_27.error; }
8328
8830
  }
8329
8831
  return { set: set, map: map, size: routes.length };
8330
8832
  }
@@ -8471,7 +8973,7 @@ function sanitizeAssistantResponse(value) {
8471
8973
  return normalizeAssistantRoutes(normalizedCurrency);
8472
8974
  }
8473
8975
  function evaluateAssistantGuardrails(message) {
8474
- var e_26, _a;
8976
+ var e_28, _a;
8475
8977
  var normalized = String(message || '').toLowerCase();
8476
8978
  var patterns = [
8477
8979
  {
@@ -8517,12 +9019,12 @@ function evaluateAssistantGuardrails(message) {
8517
9019
  }
8518
9020
  }
8519
9021
  }
8520
- catch (e_26_1) { e_26 = { error: e_26_1 }; }
9022
+ catch (e_28_1) { e_28 = { error: e_28_1 }; }
8521
9023
  finally {
8522
9024
  try {
8523
9025
  if (patterns_1_1 && !patterns_1_1.done && (_a = patterns_1.return)) _a.call(patterns_1);
8524
9026
  }
8525
- finally { if (e_26) throw e_26.error; }
9027
+ finally { if (e_28) throw e_28.error; }
8526
9028
  }
8527
9029
  return null;
8528
9030
  }
@@ -8637,7 +9139,7 @@ function tokenizeArithmeticExpression(expression) {
8637
9139
  return tokens;
8638
9140
  }
8639
9141
  function evaluateArithmeticExpression(expression) {
8640
- var e_27, _a, e_28, _b;
9142
+ var e_29, _a, e_30, _b;
8641
9143
  var tokens = tokenizeArithmeticExpression(expression);
8642
9144
  if (!tokens || !tokens.length) {
8643
9145
  return null;
@@ -8694,12 +9196,12 @@ function evaluateArithmeticExpression(expression) {
8694
9196
  prevToken = token;
8695
9197
  }
8696
9198
  }
8697
- catch (e_27_1) { e_27 = { error: e_27_1 }; }
9199
+ catch (e_29_1) { e_29 = { error: e_29_1 }; }
8698
9200
  finally {
8699
9201
  try {
8700
9202
  if (tokens_1_1 && !tokens_1_1.done && (_a = tokens_1.return)) _a.call(tokens_1);
8701
9203
  }
8702
- finally { if (e_27) throw e_27.error; }
9204
+ finally { if (e_29) throw e_29.error; }
8703
9205
  }
8704
9206
  while (ops.length) {
8705
9207
  var op = ops.pop();
@@ -8739,12 +9241,12 @@ function evaluateArithmeticExpression(expression) {
8739
9241
  stack.push(Number(token));
8740
9242
  }
8741
9243
  }
8742
- catch (e_28_1) { e_28 = { error: e_28_1 }; }
9244
+ catch (e_30_1) { e_30 = { error: e_30_1 }; }
8743
9245
  finally {
8744
9246
  try {
8745
9247
  if (output_1_1 && !output_1_1.done && (_b = output_1.return)) _b.call(output_1);
8746
9248
  }
8747
- finally { if (e_28) throw e_28.error; }
9249
+ finally { if (e_30) throw e_30.error; }
8748
9250
  }
8749
9251
  if (stack.length !== 1 || Number.isNaN(stack[0])) {
8750
9252
  return null;
@@ -8928,8 +9430,8 @@ function handleCodexUpload(id_conversation, file_name, content_base64, size, con
8928
9430
  }
8929
9431
  function readAttachmentContents(attachments) {
8930
9432
  return __awaiter(this, void 0, void 0, function () {
8931
- var limits, totalBytes, totalChars, chunks, cleaned, attachments_1, attachments_1_1, attachment, localPath, safe, stat, ext, name_1, type, readable, content, _a, e_29_1;
8932
- var e_29, _b;
9433
+ var limits, totalBytes, totalChars, chunks, cleaned, attachments_1, attachments_1_1, attachment, localPath, safe, stat, ext, name_1, type, readable, content, _a, e_31_1;
9434
+ var e_31, _b;
8933
9435
  return __generator(this, function (_c) {
8934
9436
  switch (_c.label) {
8935
9437
  case 0:
@@ -9008,14 +9510,14 @@ function readAttachmentContents(attachments) {
9008
9510
  return [3 /*break*/, 2];
9009
9511
  case 10: return [3 /*break*/, 13];
9010
9512
  case 11:
9011
- e_29_1 = _c.sent();
9012
- e_29 = { error: e_29_1 };
9513
+ e_31_1 = _c.sent();
9514
+ e_31 = { error: e_31_1 };
9013
9515
  return [3 /*break*/, 13];
9014
9516
  case 12:
9015
9517
  try {
9016
9518
  if (attachments_1_1 && !attachments_1_1.done && (_b = attachments_1.return)) _b.call(attachments_1);
9017
9519
  }
9018
- finally { if (e_29) throw e_29.error; }
9520
+ finally { if (e_31) throw e_31.error; }
9019
9521
  return [7 /*endfinally*/];
9020
9522
  case 13: return [2 /*return*/, {
9021
9523
  promptText: chunks.length ? "\n\nAttachments:\n".concat(chunks.join('\n\n')) : '',
@@ -9203,7 +9705,7 @@ function estimateUsage(messages, responseText, model) {
9203
9705
  };
9204
9706
  }
9205
9707
  function evaluateGuardrails(message) {
9206
- var e_30, _a;
9708
+ var e_32, _a;
9207
9709
  var normalized = String(message || '').toLowerCase();
9208
9710
  var patterns = [
9209
9711
  { 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.' },
@@ -9225,12 +9727,12 @@ function evaluateGuardrails(message) {
9225
9727
  }
9226
9728
  }
9227
9729
  }
9228
- catch (e_30_1) { e_30 = { error: e_30_1 }; }
9730
+ catch (e_32_1) { e_32 = { error: e_32_1 }; }
9229
9731
  finally {
9230
9732
  try {
9231
9733
  if (patterns_2_1 && !patterns_2_1.done && (_a = patterns_2.return)) _a.call(patterns_2);
9232
9734
  }
9233
- finally { if (e_30) throw e_30.error; }
9735
+ finally { if (e_32) throw e_32.error; }
9234
9736
  }
9235
9737
  return null;
9236
9738
  }