@resolveio/server-lib 22.0.15 → 22.0.17

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.normalizeAssistantNowExprPlaceholders = normalizeAssistantNowExprPlaceholders;
117
118
  exports.rewriteMatchExpressionsToExpr = rewriteMatchExpressionsToExpr;
118
119
  exports.stripQueryFieldPathsDeep = stripQueryFieldPathsDeep;
119
120
  exports.stripScopedFieldsFromPipeline = stripScopedFieldsFromPipeline;
@@ -543,7 +544,8 @@ var AI_ASSISTANT_PLANNER_SYSTEM_PROMPT = [
543
544
  '5) CLASSIFY THE REQUEST:',
544
545
  ' - type = "navigation" if user asks how/where to do something in the app.',
545
546
  ' - type = "data" if user asks for totals, lists, breakdowns, counts, reports, "last N", "by month", etc.',
546
- ' - type = "program_explain" if user asks how the system works (features/process).',
547
+ ' - type = "feature_info" if user asks how the system works (features/process) without requesting data.',
548
+ ' - type = "bug_issue" if user reports wrong behavior/errors or asks for root-cause/debugging.',
547
549
  ' - type = "mixed" if both navigation + data are clearly requested.',
548
550
  '',
549
551
  '6) OUTPUT FORMAT:',
@@ -578,7 +580,7 @@ var AI_ASSISTANT_PLANNER_USER_PROMPT_TEMPLATE = [
578
580
  ' }',
579
581
  ' },',
580
582
  ' "intent": {',
581
- ' "type": "navigation" | "data" | "program_explain" | "mixed",',
583
+ ' "type": "navigation" | "data" | "feature_info" | "bug_issue" | "mixed",',
582
584
  ' "summary": string,',
583
585
  ' "confidence": number',
584
586
  ' },',
@@ -778,28 +780,31 @@ function loadAiTerminalMethods(methodManager) {
778
780
  function: function (payload) {
779
781
  return __awaiter(this, void 0, void 0, function () {
780
782
  var now, doc, result;
781
- return __generator(this, function (_a) {
782
- switch (_a.label) {
783
+ var _a;
784
+ return __generator(this, function (_b) {
785
+ switch (_b.label) {
783
786
  case 0:
784
787
  now = new Date();
785
- doc = {
786
- id_client: resolveClientIdFromConfig(payload.id_client),
787
- id_app: normalizeOptionalString(payload.id_app),
788
- title: normalizeOptionalString(payload.title) || 'New Conversation',
789
- mode: normalizeConversationMode(payload.mode),
790
- branch_enabled: payload.branch_enabled === true,
791
- branch_name: normalizeOptionalString(payload.branch_name),
792
- status: normalizeConversationStatus(payload.status),
793
- profile_id: normalizeOptionalString(payload.profile_id),
794
- metadata: payload.metadata || {},
795
- last_message_at: undefined,
796
- last_message_id: undefined,
797
- createdAt: now,
798
- updatedAt: now
799
- };
800
- return [4 /*yield*/, ai_terminal_conversation_collection_1.AiTerminalConversations.insertOne(doc)];
788
+ _a = {};
789
+ return [4 /*yield*/, resolveClientIdFromConfig(payload.id_client, this === null || this === void 0 ? void 0 : this.id_user)];
801
790
  case 1:
802
- result = _a.sent();
791
+ doc = (_a.id_client = _b.sent(),
792
+ _a.id_app = normalizeOptionalString(payload.id_app),
793
+ _a.title = normalizeOptionalString(payload.title) || 'New Conversation',
794
+ _a.mode = normalizeConversationMode(payload.mode),
795
+ _a.branch_enabled = payload.branch_enabled === true,
796
+ _a.branch_name = normalizeOptionalString(payload.branch_name),
797
+ _a.status = normalizeConversationStatus(payload.status),
798
+ _a.profile_id = normalizeOptionalString(payload.profile_id),
799
+ _a.metadata = payload.metadata || {},
800
+ _a.last_message_at = undefined,
801
+ _a.last_message_id = undefined,
802
+ _a.createdAt = now,
803
+ _a.updatedAt = now,
804
+ _a);
805
+ return [4 /*yield*/, ai_terminal_conversation_collection_1.AiTerminalConversations.insertOne(doc)];
806
+ case 2:
807
+ result = _b.sent();
803
808
  return [2 /*return*/, { id_conversation: result._id }];
804
809
  }
805
810
  });
@@ -1116,7 +1121,7 @@ function executeAiTerminalRun(payload, context) {
1116
1121
  if (!guardrailsEnabled) return [3 /*break*/, 6];
1117
1122
  guardrail = evaluateGuardrails(message);
1118
1123
  if (!(guardrail === null || guardrail === void 0 ? void 0 : guardrail.blocked)) return [3 /*break*/, 6];
1119
- return [4 /*yield*/, ensureConversation(input, 'openai')];
1124
+ return [4 /*yield*/, ensureConversation(input, 'openai', context === null || context === void 0 ? void 0 : context.id_user)];
1120
1125
  case 2:
1121
1126
  conversation_1 = _b.sent();
1122
1127
  now_1 = new Date();
@@ -1150,7 +1155,7 @@ function executeAiTerminalRun(payload, context) {
1150
1155
  message: assistantMsg,
1151
1156
  guardrails: { blocked: true, reason: guardrail.reason }
1152
1157
  }];
1153
- case 6: return [4 /*yield*/, ensureConversation(input, 'openai')];
1158
+ case 6: return [4 /*yield*/, ensureConversation(input, 'openai', context === null || context === void 0 ? void 0 : context.id_user)];
1154
1159
  case 7:
1155
1160
  conversation = _b.sent();
1156
1161
  now = new Date();
@@ -1193,8 +1198,10 @@ function executeAiTerminalRun(payload, context) {
1193
1198
  case 12:
1194
1199
  response = _b.sent();
1195
1200
  usage = response.usage || estimateUsage(messages, response.content, openaiSettings.model);
1196
- idClient = resolveClientId(conversation, input.id_client);
1197
- if (!idClient) return [3 /*break*/, 14];
1201
+ return [4 /*yield*/, resolveClientId(conversation, input.id_client, context === null || context === void 0 ? void 0 : context.id_user)];
1202
+ case 13:
1203
+ idClient = _b.sent();
1204
+ if (!idClient) return [3 /*break*/, 15];
1198
1205
  return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)({
1199
1206
  id_client: idClient,
1200
1207
  model: response.model || openaiSettings.model || 'unknown',
@@ -1204,10 +1211,10 @@ function executeAiTerminalRun(payload, context) {
1204
1211
  category: 'ai-terminal',
1205
1212
  id_conversation: conversation._id
1206
1213
  })];
1207
- case 13:
1208
- _b.sent();
1209
- _b.label = 14;
1210
1214
  case 14:
1215
+ _b.sent();
1216
+ _b.label = 15;
1217
+ case 15:
1211
1218
  userDoc = {
1212
1219
  id_conversation: conversation._id,
1213
1220
  role: 'user',
@@ -1232,20 +1239,20 @@ function executeAiTerminalRun(payload, context) {
1232
1239
  updatedAt: now
1233
1240
  };
1234
1241
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(userDoc)];
1235
- case 15:
1242
+ case 16:
1236
1243
  _b.sent();
1237
1244
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(assistantDoc)];
1238
- case 16:
1245
+ case 17:
1239
1246
  insertResult = _b.sent();
1240
1247
  return [4 /*yield*/, touchConversation(conversation._id, now, insertResult._id)];
1241
- case 17:
1248
+ case 18:
1242
1249
  _b.sent();
1243
- if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 19];
1250
+ if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 20];
1244
1251
  return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
1245
- case 18:
1252
+ case 19:
1246
1253
  _b.sent();
1247
- _b.label = 19;
1248
- case 19: return [2 /*return*/, {
1254
+ _b.label = 20;
1255
+ case 20: return [2 /*return*/, {
1249
1256
  conversation: conversation,
1250
1257
  message: assistantDoc,
1251
1258
  usage: assistantDoc.usage
@@ -1289,8 +1296,10 @@ function executeAiFormPatch(payload, context) {
1289
1296
  case 1:
1290
1297
  response = _b.sent();
1291
1298
  usage = response.usage || estimateUsage(messages, response.content, response.model || openaiSettings.model);
1292
- idClient = resolveClientIdFromConfig(input.id_client);
1293
- if (!idClient) return [3 /*break*/, 3];
1299
+ return [4 /*yield*/, resolveClientIdFromConfig(input.id_client, context === null || context === void 0 ? void 0 : context.id_user)];
1300
+ case 2:
1301
+ idClient = _b.sent();
1302
+ if (!idClient) return [3 /*break*/, 4];
1294
1303
  return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)({
1295
1304
  id_client: idClient,
1296
1305
  model: response.model || openaiSettings.model || 'unknown',
@@ -1299,10 +1308,10 @@ function executeAiFormPatch(payload, context) {
1299
1308
  total_tokens: usage.totalTokens,
1300
1309
  category: 'ai-form'
1301
1310
  })];
1302
- case 2:
1303
- _b.sent();
1304
- _b.label = 3;
1305
1311
  case 3:
1312
+ _b.sent();
1313
+ _b.label = 4;
1314
+ case 4:
1306
1315
  parsed = parseJsonObject(response.content);
1307
1316
  if (!parsed || typeof parsed !== 'object') {
1308
1317
  throw new Error('AI form patch response was not valid JSON.');
@@ -1343,7 +1352,7 @@ function executeAiAssistantCodexRun(payload, context) {
1343
1352
  codexFallbackModels = resolveCodexFallbackModels(input.config, codexModel);
1344
1353
  guardrail = evaluateAssistantGuardrails(message);
1345
1354
  if (!(guardrail === null || guardrail === void 0 ? void 0 : guardrail.blocked)) return [3 /*break*/, 5];
1346
- return [4 /*yield*/, ensureConversation(input, 'codex')];
1355
+ return [4 /*yield*/, ensureConversation(input, 'codex', context === null || context === void 0 ? void 0 : context.id_user)];
1347
1356
  case 1:
1348
1357
  conversation_2 = _d.sent();
1349
1358
  now_2 = new Date();
@@ -1383,7 +1392,7 @@ function executeAiAssistantCodexRun(payload, context) {
1383
1392
  isSuperAdmin = !!((_b = user === null || user === void 0 ? void 0 : user.roles) === null || _b === void 0 ? void 0 : _b.super_admin);
1384
1393
  hasInvoiceAccess = userHasInvoiceAccess(user);
1385
1394
  customerId = normalizeOptionalString((_c = user === null || user === void 0 ? void 0 : user.other) === null || _c === void 0 ? void 0 : _c.id_customer);
1386
- return [4 /*yield*/, ensureConversation(input, 'codex')];
1395
+ return [4 /*yield*/, ensureConversation(input, 'codex', context === null || context === void 0 ? void 0 : context.id_user)];
1387
1396
  case 7:
1388
1397
  conversation = _d.sent();
1389
1398
  if (aiWorkerDebug) {
@@ -1449,10 +1458,10 @@ function executeAiAssistantCodexRun(payload, context) {
1449
1458
  insertResult = _d.sent();
1450
1459
  assistantMessageId = (insertResult === null || insertResult === void 0 ? void 0 : insertResult._id) || (insertResult === null || insertResult === void 0 ? void 0 : insertResult.insertedId);
1451
1460
  enqueueAssistantCodexRun(function () { return __awaiter(_this, void 0, void 0, function () {
1452
- 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;
1453
- var _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
1454
- return __generator(this, function (_x) {
1455
- switch (_x.label) {
1461
+ var runStart, steps, recordStep, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, requestClassification, dataQuestion, lastDirective, toolResponseDebug, toolError, termHints, collectionHints, fieldHints, collectionTokenization, collectionRanking, collectionSelection, collectionOverride, collectionNames, plannerEnabled, plannerOutput, plannerRaw, timingBreakdown, codexUsage, accumulateCodexUsage, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, baseWeights, expandedWeights, dbName, db, _a, routeHints, rankedCollections, hintCollections, assistantContext, prompt_1, workspaceRoot, codexConfig, runOptions, plannerPrompt, plannerStart, _b, 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, finalUsage, usageClientId, usageError_1, finalAssistantDoc, setPayload;
1462
+ var _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
1463
+ return __generator(this, function (_v) {
1464
+ switch (_v.label) {
1456
1465
  case 0:
1457
1466
  runStart = Date.now();
1458
1467
  if (aiWorkerDebug) {
@@ -1481,7 +1490,8 @@ function executeAiAssistantCodexRun(payload, context) {
1481
1490
  toolResult = null;
1482
1491
  assistantDebug = null;
1483
1492
  directiveSource = 'none';
1484
- dataQuestion = isAssistantDataQuestion(message);
1493
+ requestClassification = classifyAssistantRequestType(message);
1494
+ dataQuestion = requestClassification.dataQuestion;
1485
1495
  lastDirective = null;
1486
1496
  toolResponseDebug = null;
1487
1497
  toolError = null;
@@ -1504,12 +1514,32 @@ function executeAiAssistantCodexRun(payload, context) {
1504
1514
  toolMs: 0,
1505
1515
  followupMs: 0
1506
1516
  };
1517
+ codexUsage = {
1518
+ input_tokens: 0,
1519
+ output_tokens: 0,
1520
+ total_tokens: 0
1521
+ };
1522
+ accumulateCodexUsage = function (promptText, completionText) {
1523
+ var inputTokens = (0, tokenizer_1.countTokens)(promptText || '', codexModel);
1524
+ var outputTokens = (0, tokenizer_1.countTokens)(completionText || '', codexModel);
1525
+ if (!inputTokens && !outputTokens) {
1526
+ return;
1527
+ }
1528
+ codexUsage.input_tokens += inputTokens;
1529
+ codexUsage.output_tokens += outputTokens;
1530
+ codexUsage.total_tokens += inputTokens + outputTokens;
1531
+ };
1507
1532
  contextRoute = normalizeOptionalString((_g = input === null || input === void 0 ? void 0 : input.context) === null || _g === void 0 ? void 0 : _g.route);
1508
1533
  contextMode = normalizeOptionalString((_h = input === null || input === void 0 ? void 0 : input.context) === null || _h === void 0 ? void 0 : _h.mode);
1509
1534
  recordStep('Queued', { requestId: requestId || undefined });
1510
- _x.label = 1;
1535
+ recordStep('Planning: request classification', {
1536
+ type: requestClassification.type,
1537
+ source: requestClassification.source,
1538
+ dataQuestion: dataQuestion
1539
+ });
1540
+ _v.label = 1;
1511
1541
  case 1:
1512
- _x.trys.push([1, 35, 36, 37]);
1542
+ _v.trys.push([1, 34, 35, 36]);
1513
1543
  hintSeed = [message, contextRoute].filter(Boolean).join(' ');
1514
1544
  termExpansion = expandAssistantTermSynonyms(hintSeed);
1515
1545
  hintText = termExpansion.expanded || hintSeed;
@@ -1530,19 +1560,19 @@ function executeAiAssistantCodexRun(payload, context) {
1530
1560
  recordStep('Planning: term expansion', {
1531
1561
  termMatches: termExpansion.matches.length ? termExpansion.matches : undefined
1532
1562
  });
1533
- _x.label = 2;
1563
+ _v.label = 2;
1534
1564
  case 2:
1535
- _x.trys.push([2, 4, , 5]);
1565
+ _v.trys.push([2, 4, , 5]);
1536
1566
  dbName = resolveAssistantDatabaseName(undefined, input.mongo);
1537
1567
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1538
1568
  return [4 /*yield*/, listAssistantCollections(db, dbName)];
1539
1569
  case 3:
1540
- collectionNames = _x.sent();
1570
+ collectionNames = _v.sent();
1541
1571
  collectionHints = resolveCollectionHintsFromTokens(expandedTokens, collectionNames, 5);
1542
1572
  collectionRanking = buildCollectionRankingDebugFromTokens(expandedTokens, collectionNames, 8);
1543
1573
  return [3 /*break*/, 5];
1544
1574
  case 4:
1545
- _a = _x.sent();
1575
+ _a = _v.sent();
1546
1576
  collectionHints = [];
1547
1577
  collectionRanking = collectionRanking || ((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens)
1548
1578
  ? buildCollectionRankingDebugFromTokens(collectionTokenization.expandedTokens || [], [], 0)
@@ -1578,7 +1608,7 @@ function executeAiAssistantCodexRun(payload, context) {
1578
1608
  prompt_1 = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1579
1609
  return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
1580
1610
  case 6:
1581
- workspaceRoot = _x.sent();
1611
+ workspaceRoot = _v.sent();
1582
1612
  codexConfig = resolveCodexSettings({
1583
1613
  model: codexModel,
1584
1614
  fallbackModels: codexFallbackModels
@@ -1601,7 +1631,7 @@ function executeAiAssistantCodexRun(payload, context) {
1601
1631
  approvalPolicy: 'never'
1602
1632
  }
1603
1633
  };
1604
- if (!plannerEnabled) return [3 /*break*/, 11];
1634
+ if (!plannerEnabled) return [3 /*break*/, 10];
1605
1635
  recordStep('Planning: planner prompt');
1606
1636
  plannerPrompt = buildAssistantPlannerPrompt({
1607
1637
  message: message,
@@ -1613,120 +1643,123 @@ function executeAiAssistantCodexRun(payload, context) {
1613
1643
  fieldHints: fieldHints,
1614
1644
  inputClientId: input.id_client
1615
1645
  });
1616
- _x.label = 7;
1646
+ _v.label = 7;
1617
1647
  case 7:
1618
- _x.trys.push([7, 9, , 10]);
1648
+ _v.trys.push([7, 9, , 10]);
1619
1649
  plannerStart = Date.now();
1620
1650
  return [4 /*yield*/, runCodexInWorkerThread(plannerPrompt, runOptions, codexConfig, streamProgress)];
1621
1651
  case 8:
1622
- plannerRaw = _x.sent();
1652
+ plannerRaw = _v.sent();
1653
+ accumulateCodexUsage(plannerPrompt, plannerRaw);
1623
1654
  timingBreakdown.plannerMs = Date.now() - plannerStart;
1624
1655
  plannerOutput = parseJsonObject(plannerRaw);
1625
1656
  recordStep('Planning: planner result', { parsed: !!plannerOutput });
1626
1657
  return [3 /*break*/, 10];
1627
1658
  case 9:
1628
- _b = _x.sent();
1659
+ _b = _v.sent();
1629
1660
  recordStep('Planning: planner result', { parsed: false });
1630
1661
  return [3 /*break*/, 10];
1631
1662
  case 10:
1632
- if (plannerOutput) {
1633
- intentType = normalizeOptionalString((_j = plannerOutput === null || plannerOutput === void 0 ? void 0 : plannerOutput.intent) === null || _j === void 0 ? void 0 : _j.type).toLowerCase();
1634
- shouldFetch = ((_k = plannerOutput === null || plannerOutput === void 0 ? void 0 : plannerOutput.dataPlan) === null || _k === void 0 ? void 0 : _k.shouldFetchData) === true;
1635
- if (shouldFetch || intentType === 'data' || intentType === 'mixed') {
1636
- dataQuestion = true;
1637
- }
1638
- }
1639
- _x.label = 11;
1640
- case 11:
1663
+ requestClassification = classifyAssistantRequestType(message, plannerOutput || undefined);
1664
+ dataQuestion = requestClassification.dataQuestion;
1665
+ recordStep('Planning: request classification', {
1666
+ type: requestClassification.type,
1667
+ source: requestClassification.source,
1668
+ plannerIntentType: requestClassification.plannerIntentType || undefined,
1669
+ dataQuestion: dataQuestion
1670
+ });
1641
1671
  responseText = '';
1642
1672
  directiveText = '';
1643
1673
  directive = null;
1644
- if (!dataQuestion) return [3 /*break*/, 15];
1674
+ if (!dataQuestion) return [3 /*break*/, 14];
1645
1675
  recordStep('Directive: determine tool', { type: 'data-question' });
1646
1676
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1647
- _x.label = 12;
1648
- case 12:
1649
- _x.trys.push([12, 14, , 15]);
1677
+ _v.label = 11;
1678
+ case 11:
1679
+ _v.trys.push([11, 13, , 14]);
1650
1680
  directiveStart = Date.now();
1651
1681
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1652
- case 13:
1653
- directiveText = _x.sent();
1682
+ case 12:
1683
+ directiveText = _v.sent();
1684
+ accumulateCodexUsage(directivePrompt, directiveText);
1654
1685
  timingBreakdown.directiveMs = Date.now() - directiveStart;
1655
1686
  forcedDirective = extractAssistantMongoDirective(directiveText);
1656
1687
  if (forcedDirective) {
1657
1688
  directive = forcedDirective;
1658
1689
  directiveSource = 'model';
1659
1690
  lastDirective = forcedDirective;
1660
- collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_l = directive.payload) === null || _l === void 0 ? void 0 : _l.collection) || '');
1691
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_j = directive.payload) === null || _j === void 0 ? void 0 : _j.collection) || '');
1661
1692
  recordStep('Directive resolved', {
1662
1693
  source: directiveSource,
1663
1694
  type: directive.type,
1664
- collection: normalizeOptionalString((_m = directive.payload) === null || _m === void 0 ? void 0 : _m.collection) || undefined,
1665
- permissionView: normalizeOptionalString((_o = directive.payload) === null || _o === void 0 ? void 0 : _o.permissionView) || undefined
1695
+ collection: normalizeOptionalString((_k = directive.payload) === null || _k === void 0 ? void 0 : _k.collection) || undefined,
1696
+ permissionView: normalizeOptionalString((_l = directive.payload) === null || _l === void 0 ? void 0 : _l.permissionView) || undefined
1666
1697
  });
1667
1698
  }
1668
- return [3 /*break*/, 15];
1699
+ return [3 /*break*/, 14];
1700
+ case 13:
1701
+ _c = _v.sent();
1702
+ return [3 /*break*/, 14];
1669
1703
  case 14:
1670
- _c = _x.sent();
1671
- return [3 /*break*/, 15];
1672
- case 15:
1673
- if (!!directive) return [3 /*break*/, 17];
1704
+ if (!!directive) return [3 /*break*/, 16];
1674
1705
  recordStep('Response: draft initial answer', { mode: 'full' });
1675
1706
  initialStart = Date.now();
1676
1707
  return [4 /*yield*/, runCodexInWorkerThread(prompt_1, runOptions, codexConfig, streamProgress)];
1677
- case 16:
1678
- responseText = _x.sent();
1708
+ case 15:
1709
+ responseText = _v.sent();
1710
+ accumulateCodexUsage(prompt_1, responseText);
1679
1711
  timingBreakdown.initialResponseMs = Date.now() - initialStart;
1680
1712
  directive = extractAssistantMongoDirective(responseText);
1681
1713
  if (directive) {
1682
1714
  directiveSource = 'model';
1683
1715
  lastDirective = directive;
1684
- collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_p = directive.payload) === null || _p === void 0 ? void 0 : _p.collection) || '');
1716
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_m = directive.payload) === null || _m === void 0 ? void 0 : _m.collection) || '');
1685
1717
  recordStep('Directive resolved', {
1686
1718
  source: directiveSource,
1687
1719
  type: directive.type,
1688
- collection: normalizeOptionalString((_q = directive.payload) === null || _q === void 0 ? void 0 : _q.collection) || undefined,
1689
- permissionView: normalizeOptionalString((_r = directive.payload) === null || _r === void 0 ? void 0 : _r.permissionView) || undefined
1720
+ collection: normalizeOptionalString((_o = directive.payload) === null || _o === void 0 ? void 0 : _o.collection) || undefined,
1721
+ permissionView: normalizeOptionalString((_p = directive.payload) === null || _p === void 0 ? void 0 : _p.permissionView) || undefined
1690
1722
  });
1691
1723
  }
1692
- _x.label = 17;
1693
- case 17:
1694
- if (!(!directive && dataQuestion)) return [3 /*break*/, 21];
1724
+ _v.label = 16;
1725
+ case 16:
1726
+ if (!(!directive && dataQuestion)) return [3 /*break*/, 20];
1695
1727
  recordStep('Directive: forced retry', { mode: 'directive-only' });
1696
1728
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1697
- _x.label = 18;
1698
- case 18:
1699
- _x.trys.push([18, 20, , 21]);
1729
+ _v.label = 17;
1730
+ case 17:
1731
+ _v.trys.push([17, 19, , 20]);
1700
1732
  forcedStart = Date.now();
1701
1733
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1702
- case 19:
1703
- directiveText = _x.sent();
1734
+ case 18:
1735
+ directiveText = _v.sent();
1736
+ accumulateCodexUsage(directivePrompt, directiveText);
1704
1737
  timingBreakdown.forcedDirectiveMs = Date.now() - forcedStart;
1705
1738
  forcedDirective = extractAssistantMongoDirective(directiveText);
1706
1739
  if (forcedDirective) {
1707
1740
  directive = forcedDirective;
1708
1741
  directiveSource = 'forced';
1709
1742
  lastDirective = forcedDirective;
1710
- collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_s = directive.payload) === null || _s === void 0 ? void 0 : _s.collection) || '');
1743
+ collectionSelection = buildCollectionSelectionDetail((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens) || [], normalizeOptionalString((_q = directive.payload) === null || _q === void 0 ? void 0 : _q.collection) || '');
1711
1744
  recordStep('Directive resolved', {
1712
1745
  source: directiveSource,
1713
1746
  type: directive.type,
1714
- collection: normalizeOptionalString((_t = directive.payload) === null || _t === void 0 ? void 0 : _t.collection) || undefined,
1715
- permissionView: normalizeOptionalString((_u = directive.payload) === null || _u === void 0 ? void 0 : _u.permissionView) || undefined
1747
+ collection: normalizeOptionalString((_r = directive.payload) === null || _r === void 0 ? void 0 : _r.collection) || undefined,
1748
+ permissionView: normalizeOptionalString((_s = directive.payload) === null || _s === void 0 ? void 0 : _s.permissionView) || undefined
1716
1749
  });
1717
1750
  }
1718
- return [3 /*break*/, 21];
1751
+ return [3 /*break*/, 20];
1752
+ case 19:
1753
+ _d = _v.sent();
1754
+ return [3 /*break*/, 20];
1719
1755
  case 20:
1720
- _d = _x.sent();
1721
- return [3 /*break*/, 21];
1722
- case 21:
1723
1756
  if (directive) {
1724
- requestedCollection = normalizeOptionalString((_v = directive.payload) === null || _v === void 0 ? void 0 : _v.collection);
1757
+ requestedCollection = normalizeOptionalString((_t = directive.payload) === null || _t === void 0 ? void 0 : _t.collection);
1725
1758
  collectionOverride = resolveCollectionOverrideWithContext({
1726
1759
  message: message,
1727
1760
  collectionRanking: collectionRanking,
1728
1761
  requestedCollection: requestedCollection,
1729
- permissionView: normalizeOptionalString((_w = directive.payload) === null || _w === void 0 ? void 0 : _w.permissionView) || contextRoute,
1762
+ permissionView: normalizeOptionalString((_u = directive.payload) === null || _u === void 0 ? void 0 : _u.permissionView) || contextRoute,
1730
1763
  collectionNames: collectionNames
1731
1764
  });
1732
1765
  if (collectionOverride) {
@@ -1742,7 +1775,7 @@ function executeAiAssistantCodexRun(payload, context) {
1742
1775
  if (cleanedResponseText) {
1743
1776
  assistantContent = sanitizeAssistantResponse(cleanedResponseText);
1744
1777
  }
1745
- if (!((directive === null || directive === void 0 ? void 0 : directive.payload) && AI_ASSISTANT_TOOL_MAX_STEPS > 0)) return [3 /*break*/, 33];
1778
+ if (!((directive === null || directive === void 0 ? void 0 : directive.payload) && AI_ASSISTANT_TOOL_MAX_STEPS > 0)) return [3 /*break*/, 32];
1746
1779
  effectiveDirective = collectionOverride
1747
1780
  ? __assign(__assign({}, directive), { payload: __assign(__assign({}, (directive.payload || {})), { collection: collectionOverride.to }) }) : directive;
1748
1781
  toolRequest = buildAssistantToolRequest(effectiveDirective, input);
@@ -1752,20 +1785,20 @@ function executeAiAssistantCodexRun(payload, context) {
1752
1785
  collection: normalizeOptionalString(toolRequest === null || toolRequest === void 0 ? void 0 : toolRequest.collection) || undefined,
1753
1786
  permissionView: normalizeOptionalString(toolRequest === null || toolRequest === void 0 ? void 0 : toolRequest.permissionView) || undefined
1754
1787
  });
1755
- _x.label = 22;
1756
- case 22:
1757
- _x.trys.push([22, 31, , 32]);
1788
+ _v.label = 21;
1789
+ case 21:
1790
+ _v.trys.push([21, 30, , 31]);
1758
1791
  toolStart = Date.now();
1759
- if (!(effectiveDirective.type === 'aggregate')) return [3 /*break*/, 24];
1792
+ if (!(effectiveDirective.type === 'aggregate')) return [3 /*break*/, 23];
1760
1793
  return [4 /*yield*/, executeAiAssistantReportBuilderAggregate(toolRequest, context)];
1761
- case 23:
1762
- _e = _x.sent();
1763
- return [3 /*break*/, 26];
1764
- case 24: return [4 /*yield*/, executeAiAssistantReportBuilderRead(toolRequest, context)];
1794
+ case 22:
1795
+ _e = _v.sent();
1796
+ return [3 /*break*/, 25];
1797
+ case 23: return [4 /*yield*/, executeAiAssistantReportBuilderRead(toolRequest, context)];
1798
+ case 24:
1799
+ _e = _v.sent();
1800
+ _v.label = 25;
1765
1801
  case 25:
1766
- _e = _x.sent();
1767
- _x.label = 26;
1768
- case 26:
1769
1802
  toolResponse = _e;
1770
1803
  timingBreakdown.toolMs = Date.now() - toolStart;
1771
1804
  toolResponseDebug = (toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.debug) && typeof toolResponse.debug === 'object'
@@ -1781,42 +1814,43 @@ function executeAiAssistantCodexRun(payload, context) {
1781
1814
  progressTracker.push('Drafting response');
1782
1815
  recordStep('Drafting response');
1783
1816
  followupPrompt = buildAssistantCodexToolFollowupPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, toolPayload.prompt);
1784
- _x.label = 27;
1785
- case 27:
1786
- _x.trys.push([27, 29, , 30]);
1817
+ _v.label = 26;
1818
+ case 26:
1819
+ _v.trys.push([26, 28, , 29]);
1787
1820
  followupStart = Date.now();
1788
1821
  return [4 /*yield*/, runCodexInWorkerThread(followupPrompt, runOptions, codexConfig, streamProgress)];
1789
- case 28:
1790
- followupText = _x.sent();
1822
+ case 27:
1823
+ followupText = _v.sent();
1824
+ accumulateCodexUsage(followupPrompt, followupText);
1791
1825
  timingBreakdown.followupMs = Date.now() - followupStart;
1792
1826
  assistantContent = sanitizeAssistantResponse(followupText);
1793
1827
  assistantContent = applyAssistantDisplayTableToResponse(assistantContent, toolPayload.result.output.display);
1794
- return [3 /*break*/, 30];
1795
- case 29:
1796
- _f = _x.sent();
1828
+ return [3 /*break*/, 29];
1829
+ case 28:
1830
+ _f = _v.sent();
1797
1831
  assistantContent = buildAssistantToolFallbackResponse(toolPayload.result);
1798
- return [3 /*break*/, 30];
1799
- case 30: return [3 /*break*/, 32];
1800
- case 31:
1801
- error_2 = _x.sent();
1802
- assistantContent = buildAssistantToolErrorMessage(error_2, directive, toolRequest);
1832
+ return [3 /*break*/, 29];
1833
+ case 29: return [3 /*break*/, 31];
1834
+ case 30:
1835
+ error_2 = _v.sent();
1836
+ assistantContent = buildAssistantToolErrorMessage(error_2);
1803
1837
  toolError = error_2;
1804
- return [3 /*break*/, 32];
1805
- case 32: return [3 /*break*/, 34];
1806
- case 33:
1838
+ return [3 /*break*/, 31];
1839
+ case 31: return [3 /*break*/, 33];
1840
+ case 32:
1807
1841
  progressTracker.push('Drafting response');
1808
1842
  recordStep('Drafting response');
1809
- _x.label = 34;
1810
- case 34: return [3 /*break*/, 37];
1811
- case 35:
1812
- error_3 = _x.sent();
1843
+ _v.label = 33;
1844
+ case 33: return [3 /*break*/, 36];
1845
+ case 34:
1846
+ error_3 = _v.sent();
1813
1847
  assistantContent = buildAssistantCodexErrorMessage(error_3);
1814
1848
  recordStep('Error', { message: normalizeOptionalString(error_3 === null || error_3 === void 0 ? void 0 : error_3.message) || 'Unknown error' });
1815
- return [3 /*break*/, 37];
1816
- case 36:
1849
+ return [3 /*break*/, 36];
1850
+ case 35:
1817
1851
  progressTracker.stop();
1818
1852
  return [7 /*endfinally*/];
1819
- case 37:
1853
+ case 36:
1820
1854
  if (!assistantContent) {
1821
1855
  assistantContent = buildAssistantCodexErrorMessage(null);
1822
1856
  }
@@ -1848,6 +1882,9 @@ function executeAiAssistantCodexRun(payload, context) {
1848
1882
  + timingBreakdown.followupMs;
1849
1883
  draftingMs = timingBreakdown.followupMs || timingBreakdown.initialResponseMs;
1850
1884
  assistantDebug = buildAssistantDebugPayload({
1885
+ requestType: requestClassification.type,
1886
+ requestTypeSource: requestClassification.source,
1887
+ plannerIntentType: requestClassification.plannerIntentType,
1851
1888
  dataQuestion: dataQuestion,
1852
1889
  directive: lastDirective,
1853
1890
  directiveSource: directiveSource,
@@ -1893,27 +1930,63 @@ function executeAiAssistantCodexRun(payload, context) {
1893
1930
  });
1894
1931
  }
1895
1932
  finalMetadata = __assign(__assign(__assign(__assign({ model: codexModel }, (codexFallbackModels.length ? { model_fallbacks: codexFallbackModels } : {})), (requestId ? { request_id: requestId } : {})), (toolResult ? { tool_result: toolResult } : {})), (assistantDebug ? { debug: assistantDebug } : {}));
1896
- finalAssistantDoc = __assign(__assign({}, assistantDoc), { _id: assistantMessageId, content: assistantContent, metadata: finalMetadata, updatedAt: finalNow });
1897
- if (!assistantMessageId) return [3 /*break*/, 39];
1898
- return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.updateOne({ _id: assistantMessageId }, {
1899
- $set: {
1900
- content: assistantContent,
1901
- metadata: finalMetadata,
1902
- updatedAt: finalNow
1903
- }
1904
- })];
1933
+ finalUsage = codexUsage.total_tokens > 0 ? {
1934
+ model: codexModel || 'unknown',
1935
+ input_tokens: codexUsage.input_tokens,
1936
+ output_tokens: codexUsage.output_tokens,
1937
+ total_tokens: codexUsage.total_tokens
1938
+ } : null;
1939
+ if (!finalUsage) return [3 /*break*/, 41];
1940
+ return [4 /*yield*/, resolveClientId(conversation, input.id_client, context === null || context === void 0 ? void 0 : context.id_user)];
1941
+ case 37:
1942
+ usageClientId = _v.sent();
1943
+ if (!usageClientId) return [3 /*break*/, 41];
1944
+ _v.label = 38;
1905
1945
  case 38:
1906
- _x.sent();
1907
- _x.label = 39;
1908
- case 39: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
1946
+ _v.trys.push([38, 40, , 41]);
1947
+ return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)({
1948
+ id_client: usageClientId,
1949
+ model: finalUsage.model,
1950
+ input_tokens: finalUsage.input_tokens,
1951
+ output_tokens: finalUsage.output_tokens,
1952
+ total_tokens: finalUsage.total_tokens,
1953
+ category: 'ai-terminal-codex',
1954
+ id_request: requestId || undefined,
1955
+ id_conversation: conversation._id
1956
+ })];
1957
+ case 39:
1958
+ _v.sent();
1959
+ return [3 /*break*/, 41];
1909
1960
  case 40:
1910
- _x.sent();
1911
- if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 42];
1912
- return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
1961
+ usageError_1 = _v.sent();
1962
+ console.error(new Date(), 'Failed to record codex usage', usageError_1);
1963
+ return [3 /*break*/, 41];
1913
1964
  case 41:
1914
- _x.sent();
1915
- _x.label = 42;
1916
- case 42: return [2 /*return*/, finalAssistantDoc];
1965
+ finalAssistantDoc = __assign(__assign(__assign(__assign({}, assistantDoc), { _id: assistantMessageId, content: assistantContent, metadata: finalMetadata }), (finalUsage ? { usage: finalUsage } : {})), { updatedAt: finalNow });
1966
+ if (!assistantMessageId) return [3 /*break*/, 43];
1967
+ setPayload = {
1968
+ content: assistantContent,
1969
+ metadata: finalMetadata,
1970
+ updatedAt: finalNow
1971
+ };
1972
+ if (finalUsage) {
1973
+ setPayload.usage = finalUsage;
1974
+ }
1975
+ return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.updateOne({ _id: assistantMessageId }, {
1976
+ $set: setPayload
1977
+ })];
1978
+ case 42:
1979
+ _v.sent();
1980
+ _v.label = 43;
1981
+ case 43: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
1982
+ case 44:
1983
+ _v.sent();
1984
+ if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 46];
1985
+ return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
1986
+ case 45:
1987
+ _v.sent();
1988
+ _v.label = 46;
1989
+ case 46: return [2 /*return*/, finalAssistantDoc];
1917
1990
  }
1918
1991
  });
1919
1992
  }); });
@@ -2422,7 +2495,8 @@ function executeAiAssistantMongoRead(payload, context) {
2422
2495
  }
2423
2496
  function executeAiAssistantMongoAggregate(payload, context) {
2424
2497
  return __awaiter(this, void 0, void 0, function () {
2425
- var input, rawCollection, dbName, db, collectionResolution, collection, bridgeCollection, 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, verification, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
2498
+ var input, rawCollection, dbName, db, collectionResolution, collection, bridgeCollection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, sanitizedPipeline, strippedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, executedPipeline, dateField, aggregateOptions, runAggregateWithRepair, initialAggregate, documents, probeDocs, fallback, fallbackPipeline, fallbackAggregate, fallbackDocs, createdFallback, createdPipeline, createdAggregate, createdDocs, expanded, expandedAggregate, expandedDocs, completionFallback, fallbackPipeline, fallbackAggregate, fallbackDocs, completionExprFallback, fallbackPipeline, fallbackAggregate, fallbackDocs, unwindFallback, shouldUnwind, _c, _d, fallbackPipeline, fallbackAggregate, fallbackDocs, nameFallback, fallbackPipeline, fallbackAggregate, fallbackDocs, _e, _loop_1, i, state_1, matchFields_1, _f, aliases, rewrittenPipeline, fallbackAggregate, 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, verification, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
2499
+ var _this = this;
2426
2500
  var _o, _p;
2427
2501
  return __generator(this, function (_q) {
2428
2502
  switch (_q.label) {
@@ -2506,49 +2580,85 @@ function executeAiAssistantMongoAggregate(payload, context) {
2506
2580
  pipelineWithScope = buildAssistantAggregatePipeline(scopedQuery, sanitizedPipeline);
2507
2581
  normalizedOptions = normalizeAssistantAggregateOptions(input.options);
2508
2582
  limitedPipeline = applyAssistantAggregateLimit(pipelineWithScope, normalizedOptions.limit, normalizedOptions.maxLimit, normalizedOptions.defaultLimit);
2509
- dateField = findAggregateDateField(limitedPipeline);
2510
- if (containsForbiddenMongoOperators(limitedPipeline)) {
2583
+ executedPipeline = limitedPipeline;
2584
+ dateField = findAggregateDateField(executedPipeline);
2585
+ if (containsForbiddenMongoOperators(executedPipeline)) {
2511
2586
  throw new Error('AI assistant report builder bridge: Pipeline contains restricted operators.');
2512
2587
  }
2513
2588
  aggregateOptions = __assign(__assign({}, normalizedOptions.aggregateOptions), { readPreference: AI_ASSISTANT_READ_PREFERENCE });
2514
- return [4 /*yield*/, db.collection(collection)
2515
- .aggregate(limitedPipeline, aggregateOptions)
2516
- .toArray()];
2589
+ runAggregateWithRepair = function (pipeline, stage) { return __awaiter(_this, void 0, void 0, function () {
2590
+ var docs, error_4, repaired, docs;
2591
+ return __generator(this, function (_a) {
2592
+ switch (_a.label) {
2593
+ case 0:
2594
+ _a.trys.push([0, 2, , 4]);
2595
+ return [4 /*yield*/, db.collection(collection)
2596
+ .aggregate(pipeline, aggregateOptions)
2597
+ .toArray()];
2598
+ case 1:
2599
+ docs = _a.sent();
2600
+ return [2 /*return*/, { documents: docs, pipeline: pipeline }];
2601
+ case 2:
2602
+ error_4 = _a.sent();
2603
+ if (!isAssistantDateArithmeticArgumentError(error_4)) {
2604
+ throw error_4;
2605
+ }
2606
+ repaired = repairAssistantDateArithmeticInPipeline(pipeline);
2607
+ if (!repaired.changed || containsForbiddenMongoOperators(repaired.pipeline)) {
2608
+ throw error_4;
2609
+ }
2610
+ return [4 /*yield*/, db.collection(collection)
2611
+ .aggregate(repaired.pipeline, aggregateOptions)
2612
+ .toArray()];
2613
+ case 3:
2614
+ docs = _a.sent();
2615
+ fallbackMeta.dateArithmetic = {
2616
+ attempted: true,
2617
+ used: true,
2618
+ stage: stage,
2619
+ reason: 'normalized_date_operator_args'
2620
+ };
2621
+ return [2 /*return*/, { documents: docs, pipeline: repaired.pipeline }];
2622
+ case 4: return [2 /*return*/];
2623
+ }
2624
+ });
2625
+ }); };
2626
+ return [4 /*yield*/, runAggregateWithRepair(executedPipeline, 'initial')];
2517
2627
  case 6:
2518
- documents = _q.sent();
2519
- executedPipeline = limitedPipeline;
2628
+ initialAggregate = _q.sent();
2629
+ documents = initialAggregate.documents;
2630
+ executedPipeline = initialAggregate.pipeline;
2631
+ dateField = findAggregateDateField(executedPipeline);
2520
2632
  probeDocs = null;
2521
2633
  if (!(!documents.length && dateField)) return [3 /*break*/, 10];
2522
- fallback = resolveAggregateDateFieldFallback(limitedPipeline);
2634
+ fallback = resolveAggregateDateFieldFallback(executedPipeline);
2523
2635
  if (!fallback) return [3 /*break*/, 8];
2524
2636
  fallbackMeta.dateField = __assign(__assign({}, fallback), { attempted: true, used: false });
2525
- fallbackPipeline = replaceAggregateDateField(limitedPipeline, fallback.from, fallback.to);
2637
+ fallbackPipeline = replaceAggregateDateField(executedPipeline, fallback.from, fallback.to);
2526
2638
  if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 8];
2527
- return [4 /*yield*/, db.collection(collection)
2528
- .aggregate(fallbackPipeline, aggregateOptions)
2529
- .toArray()];
2639
+ return [4 /*yield*/, runAggregateWithRepair(fallbackPipeline, 'date_field_fallback')];
2530
2640
  case 7:
2531
- fallbackDocs = _q.sent();
2641
+ fallbackAggregate = _q.sent();
2642
+ fallbackDocs = fallbackAggregate.documents;
2532
2643
  if (fallbackDocs.length) {
2533
2644
  documents = fallbackDocs;
2534
- executedPipeline = fallbackPipeline;
2645
+ executedPipeline = fallbackAggregate.pipeline;
2535
2646
  fallbackMeta.dateField.used = true;
2536
2647
  }
2537
2648
  _q.label = 8;
2538
2649
  case 8:
2539
2650
  if (!(!documents.length && dateField !== 'createdAt')) return [3 /*break*/, 10];
2540
2651
  createdFallback = { from: dateField, to: 'createdAt', attempted: true, used: false };
2541
- createdPipeline = replaceAggregateDateField(limitedPipeline, dateField, 'createdAt');
2652
+ createdPipeline = replaceAggregateDateField(executedPipeline, dateField, 'createdAt');
2542
2653
  fallbackMeta.dateFieldCreatedAt = createdFallback;
2543
2654
  if (!!containsForbiddenMongoOperators(createdPipeline)) return [3 /*break*/, 10];
2544
- return [4 /*yield*/, db.collection(collection)
2545
- .aggregate(createdPipeline, aggregateOptions)
2546
- .toArray()];
2655
+ return [4 /*yield*/, runAggregateWithRepair(createdPipeline, 'date_field_created_at')];
2547
2656
  case 9:
2548
- createdDocs = _q.sent();
2657
+ createdAggregate = _q.sent();
2658
+ createdDocs = createdAggregate.documents;
2549
2659
  if (createdDocs.length) {
2550
2660
  documents = createdDocs;
2551
- executedPipeline = createdPipeline;
2661
+ executedPipeline = createdAggregate.pipeline;
2552
2662
  fallbackMeta.dateFieldCreatedAt.used = true;
2553
2663
  }
2554
2664
  _q.label = 10;
@@ -2562,14 +2672,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2562
2672
  used: false
2563
2673
  };
2564
2674
  if (!!containsForbiddenMongoOperators(expanded.pipeline)) return [3 /*break*/, 12];
2565
- return [4 /*yield*/, db.collection(collection)
2566
- .aggregate(expanded.pipeline, aggregateOptions)
2567
- .toArray()];
2675
+ return [4 /*yield*/, runAggregateWithRepair(expanded.pipeline, 'date_fields_expanded')];
2568
2676
  case 11:
2569
- expandedDocs = _q.sent();
2677
+ expandedAggregate = _q.sent();
2678
+ expandedDocs = expandedAggregate.documents;
2570
2679
  if (expandedDocs.length) {
2571
2680
  documents = expandedDocs;
2572
- executedPipeline = expanded.pipeline;
2681
+ executedPipeline = expandedAggregate.pipeline;
2573
2682
  fallbackMeta.dateFieldsExpanded.used = true;
2574
2683
  }
2575
2684
  _q.label = 12;
@@ -2587,14 +2696,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2587
2696
  };
2588
2697
  fallbackPipeline = buildAggregateCompletionFallbackPipeline(executedPipeline, completionFallback);
2589
2698
  if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 14];
2590
- return [4 /*yield*/, db.collection(collection)
2591
- .aggregate(fallbackPipeline, aggregateOptions)
2592
- .toArray()];
2699
+ return [4 /*yield*/, runAggregateWithRepair(fallbackPipeline, 'completion_add_fields')];
2593
2700
  case 13:
2594
- fallbackDocs = _q.sent();
2701
+ fallbackAggregate = _q.sent();
2702
+ fallbackDocs = fallbackAggregate.documents;
2595
2703
  if (fallbackDocs.length) {
2596
2704
  documents = fallbackDocs;
2597
- executedPipeline = fallbackPipeline;
2705
+ executedPipeline = fallbackAggregate.pipeline;
2598
2706
  fallbackMeta.completion.used = true;
2599
2707
  }
2600
2708
  _q.label = 14;
@@ -2612,14 +2720,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2612
2720
  };
2613
2721
  fallbackPipeline = buildAggregateCompletionExprFallbackPipeline(executedPipeline, completionExprFallback);
2614
2722
  if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 16];
2615
- return [4 /*yield*/, db.collection(collection)
2616
- .aggregate(fallbackPipeline, aggregateOptions)
2617
- .toArray()];
2723
+ return [4 /*yield*/, runAggregateWithRepair(fallbackPipeline, 'completion_expr')];
2618
2724
  case 15:
2619
- fallbackDocs = _q.sent();
2725
+ fallbackAggregate = _q.sent();
2726
+ fallbackDocs = fallbackAggregate.documents;
2620
2727
  if (fallbackDocs.length) {
2621
2728
  documents = fallbackDocs;
2622
- executedPipeline = fallbackPipeline;
2729
+ executedPipeline = fallbackAggregate.pipeline;
2623
2730
  fallbackMeta.completion.used = true;
2624
2731
  }
2625
2732
  _q.label = 16;
@@ -2657,14 +2764,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2657
2764
  if (!shouldUnwind) return [3 /*break*/, 24];
2658
2765
  fallbackPipeline = buildAggregateUnwindFallbackPipeline(executedPipeline, unwindFallback);
2659
2766
  if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 23];
2660
- return [4 /*yield*/, db.collection(collection)
2661
- .aggregate(fallbackPipeline, aggregateOptions)
2662
- .toArray()];
2767
+ return [4 /*yield*/, runAggregateWithRepair(fallbackPipeline, 'unwind')];
2663
2768
  case 22:
2664
- fallbackDocs = _q.sent();
2769
+ fallbackAggregate = _q.sent();
2770
+ fallbackDocs = fallbackAggregate.documents;
2665
2771
  if (fallbackDocs.length > documents.length) {
2666
2772
  documents = fallbackDocs;
2667
- executedPipeline = fallbackPipeline;
2773
+ executedPipeline = fallbackAggregate.pipeline;
2668
2774
  fallbackMeta.unwind.used = true;
2669
2775
  }
2670
2776
  _q.label = 23;
@@ -2684,14 +2790,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2684
2790
  };
2685
2791
  fallbackPipeline = buildAggregateNameMatchFallbackPipeline(executedPipeline, nameFallback);
2686
2792
  if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 27];
2687
- return [4 /*yield*/, db.collection(collection)
2688
- .aggregate(fallbackPipeline, aggregateOptions)
2689
- .toArray()];
2793
+ return [4 /*yield*/, runAggregateWithRepair(fallbackPipeline, 'name_match')];
2690
2794
  case 26:
2691
- fallbackDocs = _q.sent();
2795
+ fallbackAggregate = _q.sent();
2796
+ fallbackDocs = fallbackAggregate.documents;
2692
2797
  if (fallbackDocs.length) {
2693
2798
  documents = fallbackDocs;
2694
- executedPipeline = fallbackPipeline;
2799
+ executedPipeline = fallbackAggregate.pipeline;
2695
2800
  fallbackMeta.nameMatch.used = true;
2696
2801
  }
2697
2802
  _q.label = 27;
@@ -2713,7 +2818,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
2713
2818
  case 29:
2714
2819
  probeDocs = _e;
2715
2820
  _loop_1 = function (i) {
2716
- var stage, chemicalLookup, rewrittenPipeline, fallbackDocs;
2821
+ var stage, chemicalLookup, rewrittenPipeline, fallbackAggregate, fallbackDocs;
2717
2822
  return __generator(this, function (_r) {
2718
2823
  switch (_r.label) {
2719
2824
  case 0:
@@ -2738,14 +2843,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2738
2843
  fallbackMeta.chemicalLookup = __assign(__assign({}, chemicalLookup.meta), { attempted: true, used: false, stage: i });
2739
2844
  rewrittenPipeline = executedPipeline.map(function (current, index) { return (index === i ? { $match: chemicalLookup.query } : current); });
2740
2845
  if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 3];
2741
- return [4 /*yield*/, db.collection(collection)
2742
- .aggregate(rewrittenPipeline, aggregateOptions)
2743
- .toArray()];
2846
+ return [4 /*yield*/, runAggregateWithRepair(rewrittenPipeline, 'chemical_lookup')];
2744
2847
  case 2:
2745
- fallbackDocs = _r.sent();
2848
+ fallbackAggregate = _r.sent();
2849
+ fallbackDocs = fallbackAggregate.documents;
2746
2850
  if (fallbackDocs.length) {
2747
2851
  documents = fallbackDocs;
2748
- executedPipeline = rewrittenPipeline;
2852
+ executedPipeline = fallbackAggregate.pipeline;
2749
2853
  fallbackMeta.chemicalLookup.used = true;
2750
2854
  return [2 /*return*/, "break"];
2751
2855
  }
@@ -2807,21 +2911,20 @@ function executeAiAssistantMongoAggregate(payload, context) {
2807
2911
  return replaceFieldPathDeep(acc, from, to);
2808
2912
  }, executedPipeline);
2809
2913
  if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 37];
2810
- return [4 /*yield*/, db.collection(collection)
2811
- .aggregate(rewrittenPipeline, aggregateOptions)
2812
- .toArray()];
2914
+ return [4 /*yield*/, runAggregateWithRepair(rewrittenPipeline, 'query_field_aliases')];
2813
2915
  case 36:
2814
- fallbackDocs = _q.sent();
2916
+ fallbackAggregate = _q.sent();
2917
+ fallbackDocs = fallbackAggregate.documents;
2815
2918
  if (fallbackDocs.length) {
2816
2919
  documents = fallbackDocs;
2817
- executedPipeline = rewrittenPipeline;
2920
+ executedPipeline = fallbackAggregate.pipeline;
2818
2921
  fallbackMeta.queryFieldAliases.used = true;
2819
2922
  }
2820
2923
  _q.label = 37;
2821
2924
  case 37:
2822
2925
  if (!!documents.length) return [3 /*break*/, 41];
2823
2926
  _loop_2 = function (i) {
2824
- var stage, _s, idLookup, rewrittenPipeline, fallbackDocs;
2927
+ var stage, _s, idLookup, rewrittenPipeline, fallbackAggregate, fallbackDocs;
2825
2928
  return __generator(this, function (_t) {
2826
2929
  switch (_t.label) {
2827
2930
  case 0:
@@ -2861,14 +2964,13 @@ function executeAiAssistantMongoAggregate(payload, context) {
2861
2964
  fallbackMeta.idLookup = __assign(__assign({}, idLookup.meta), { attempted: true, used: false, stage: i });
2862
2965
  rewrittenPipeline = executedPipeline.map(function (current, index) { return (index === i ? { $match: idLookup.query } : current); });
2863
2966
  if (!!containsForbiddenMongoOperators(rewrittenPipeline)) return [3 /*break*/, 5];
2864
- return [4 /*yield*/, db.collection(collection)
2865
- .aggregate(rewrittenPipeline, aggregateOptions)
2866
- .toArray()];
2967
+ return [4 /*yield*/, runAggregateWithRepair(rewrittenPipeline, 'id_lookup')];
2867
2968
  case 4:
2868
- fallbackDocs = _t.sent();
2969
+ fallbackAggregate = _t.sent();
2970
+ fallbackDocs = fallbackAggregate.documents;
2869
2971
  if (fallbackDocs.length) {
2870
2972
  documents = fallbackDocs;
2871
- executedPipeline = rewrittenPipeline;
2973
+ executedPipeline = fallbackAggregate.pipeline;
2872
2974
  fallbackMeta.idLookup.used = true;
2873
2975
  return [2 /*return*/, "break"];
2874
2976
  }
@@ -3902,6 +4004,7 @@ function resolveAssistantDatedReportWindow(toolResult) {
3902
4004
  function buildAssistantDebugPayload(params) {
3903
4005
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4;
3904
4006
  var notes = [];
4007
+ notes.push("Request classification: ".concat(params.requestType, " (").concat(params.requestTypeSource, ")."));
3905
4008
  if (params.dataQuestion) {
3906
4009
  notes.push('Detected a data request; tool call required.');
3907
4010
  }
@@ -4036,6 +4139,9 @@ function buildAssistantDebugPayload(params) {
4036
4139
  }
4037
4140
  var payload = {
4038
4141
  decision: {
4142
+ requestType: params.requestType,
4143
+ requestTypeSource: params.requestTypeSource,
4144
+ plannerIntentType: params.plannerIntentType || undefined,
4039
4145
  dataQuestion: params.dataQuestion,
4040
4146
  directiveSource: params.directiveSource
4041
4147
  },
@@ -4064,56 +4170,42 @@ function buildAssistantDebugPayload(params) {
4064
4170
  }
4065
4171
  return payload;
4066
4172
  }
4067
- function buildAssistantToolErrorMessage(error, directive, request) {
4068
- var _a, _b;
4173
+ function buildAssistantToolErrorMessage(error) {
4069
4174
  var rawMessage = normalizeOptionalString(error === null || error === void 0 ? void 0 : error.message) || 'Unable to access data.';
4070
4175
  var normalized = rawMessage.toLowerCase();
4071
- var collection = normalizeOptionalString(request === null || request === void 0 ? void 0 : request.collection) || normalizeOptionalString((_a = directive.payload) === null || _a === void 0 ? void 0 : _a.collection);
4072
- var routeHint = resolveAssistantErrorRouteHint(normalizeOptionalString(request === null || request === void 0 ? void 0 : request.permissionView) || normalizeOptionalString((_b = directive.payload) === null || _b === void 0 ? void 0 : _b.permissionView), collection);
4073
- var routeLine = routeHint
4074
- ? "Open ".concat(routeHint, " in the app to view this data or request access.")
4075
- : 'Request access to the related module in the app.';
4076
- if (!routeHint && collection && requiresInvoicePermission(collection)) {
4077
- routeLine = 'Open /invoice/list in the app to view this data or request access.';
4078
- }
4176
+ var cleaned = rawMessage
4177
+ .replace(/^AI assistant report builder bridge:\s*/i, '')
4178
+ .replace(/\s+/g, ' ')
4179
+ .trim()
4180
+ .replace(/\.*$/, '');
4079
4181
  if (normalized.includes('permission scope required')) {
4080
- return "I need a permission scope to access that data. ".concat(routeLine);
4182
+ return 'I couldn\'t run the data query because no permission scope was provided.';
4081
4183
  }
4082
4184
  if (normalized.includes('access denied')) {
4083
- if (collection && requiresInvoicePermission(collection)) {
4084
- return "Invoice access is required to view that data. ".concat(routeLine);
4085
- }
4086
- return "You don't have permission to view that data. ".concat(routeLine);
4185
+ return 'I couldn\'t run the data query because this account does not have permission for that dataset.';
4087
4186
  }
4088
4187
  if (normalized.includes('database access denied')) {
4089
- return "Database access is restricted for that request. ".concat(routeLine);
4188
+ return 'I couldn\'t run the data query because database access is restricted for this request.';
4090
4189
  }
4091
4190
  if (normalized.includes('undefined variable') && normalized.includes('now_minus')) {
4092
- return "The query used an unsupported relative date token. Please retry; the assistant now normalizes relative dates automatically. ".concat(routeLine);
4191
+ return 'The query used an unsupported relative date token. Please retry and I will normalize the date expression.';
4093
4192
  }
4094
4193
  if (normalized.includes('invalid character for a variable name') && (normalized.includes('now-') || normalized.includes('now+'))) {
4095
- return "The query used an unsupported relative date token. Please retry; the assistant now normalizes relative dates automatically. ".concat(routeLine);
4194
+ return 'The query used an unsupported relative date token. Please retry and I will normalize the date expression.';
4195
+ }
4196
+ if (normalized.includes('unrecognized argument to $datesubtract: date') || normalized.includes('unrecognized argument to $dateadd: date')) {
4197
+ return 'The data query failed because of an invalid date expression argument. Please retry; date arithmetic arguments are now normalized automatically.';
4096
4198
  }
4097
4199
  if (normalized.includes('report builder bridge') && normalized.includes('not configured')) {
4098
- return "That dataset is not configured for assistant data access yet. ".concat(routeLine);
4200
+ return 'That dataset is not configured for assistant data access yet.';
4099
4201
  }
4100
4202
  if (normalized.includes('collection is required')) {
4101
4203
  return 'I need a valid collection to read from. Please specify which screen or dataset you want.';
4102
4204
  }
4103
- return "I couldn't access the requested data. ".concat(routeLine);
4104
- }
4105
- function resolveAssistantErrorRouteHint(routeHint, collection) {
4106
- var normalizedHint = normalizeOptionalString(routeHint);
4107
- if (!normalizedHint) {
4108
- var fallback = resolveDefaultAssistantPermissionView(collection);
4109
- return fallback.startsWith('/report-builder') ? '' : fallback;
4110
- }
4111
- var loweredHint = normalizedHint.toLowerCase();
4112
- if (loweredHint.startsWith('/report-builder') || loweredHint === '/report' || loweredHint.startsWith('/report/')) {
4113
- var fallback = resolveDefaultAssistantPermissionView(collection);
4114
- return fallback.startsWith('/report-builder') ? '' : fallback;
4205
+ if (cleaned) {
4206
+ return "I couldn't run the data query: ".concat(cleaned, ".");
4115
4207
  }
4116
- return normalizedHint;
4208
+ return 'I couldn\'t run the requested data query.';
4117
4209
  }
4118
4210
  function deriveAssistantStreamStatus(event) {
4119
4211
  var _a;
@@ -6079,6 +6171,45 @@ function normalizeAssistantNowExprOperand(value) {
6079
6171
  },
6080
6172
  _a;
6081
6173
  }
6174
+ function normalizeAssistantDateArithmeticArgs(expression) {
6175
+ if (!expression || typeof expression !== 'object' || Array.isArray(expression)) {
6176
+ return expression;
6177
+ }
6178
+ if (expression instanceof Date || expression instanceof RegExp || isMongoObjectId(expression)) {
6179
+ return expression;
6180
+ }
6181
+ var normalizeOperatorArgs = function (operator) {
6182
+ if (!Object.prototype.hasOwnProperty.call(expression, operator)) {
6183
+ return;
6184
+ }
6185
+ var rawArgs = expression[operator];
6186
+ if (!rawArgs || typeof rawArgs !== 'object' || Array.isArray(rawArgs)) {
6187
+ return;
6188
+ }
6189
+ if (rawArgs instanceof Date || rawArgs instanceof RegExp || isMongoObjectId(rawArgs)) {
6190
+ return;
6191
+ }
6192
+ var nextArgs = __assign({}, rawArgs);
6193
+ if (!Object.prototype.hasOwnProperty.call(nextArgs, 'startDate')) {
6194
+ if (Object.prototype.hasOwnProperty.call(nextArgs, 'date')) {
6195
+ nextArgs.startDate = nextArgs.date;
6196
+ }
6197
+ else if (Object.prototype.hasOwnProperty.call(nextArgs, 'start')) {
6198
+ nextArgs.startDate = nextArgs.start;
6199
+ }
6200
+ }
6201
+ if (Object.prototype.hasOwnProperty.call(nextArgs, 'date')) {
6202
+ delete nextArgs.date;
6203
+ }
6204
+ if (Object.prototype.hasOwnProperty.call(nextArgs, 'start')) {
6205
+ delete nextArgs.start;
6206
+ }
6207
+ expression[operator] = nextArgs;
6208
+ };
6209
+ normalizeOperatorArgs('$dateAdd');
6210
+ normalizeOperatorArgs('$dateSubtract');
6211
+ return expression;
6212
+ }
6082
6213
  function normalizeAssistantNowExprPlaceholdersDeep(value) {
6083
6214
  if (Array.isArray(value)) {
6084
6215
  return value.map(function (entry) { return normalizeAssistantNowExprPlaceholdersDeep(entry); });
@@ -6096,7 +6227,38 @@ function normalizeAssistantNowExprPlaceholdersDeep(value) {
6096
6227
  Object.keys(value).forEach(function (key) {
6097
6228
  result[key] = normalizeAssistantNowExprPlaceholdersDeep(value[key]);
6098
6229
  });
6099
- return result;
6230
+ return normalizeAssistantDateArithmeticArgs(result);
6231
+ }
6232
+ function normalizeAssistantNowExprPlaceholders(value) {
6233
+ return normalizeAssistantNowExprPlaceholdersDeep(value);
6234
+ }
6235
+ function isAssistantDateArithmeticArgumentError(error) {
6236
+ var message = normalizeOptionalString(error === null || error === void 0 ? void 0 : error.message).toLowerCase();
6237
+ if (!message) {
6238
+ return false;
6239
+ }
6240
+ return message.includes('unrecognized argument to $datesubtract: date')
6241
+ || message.includes('unrecognized argument to $dateadd: date')
6242
+ || message.includes('unrecognized argument to $datesubtract: start')
6243
+ || message.includes('unrecognized argument to $dateadd: start');
6244
+ }
6245
+ function didAssistantValueChange(before, after) {
6246
+ try {
6247
+ return JSON.stringify(before) !== JSON.stringify(after);
6248
+ }
6249
+ catch (_a) {
6250
+ return true;
6251
+ }
6252
+ }
6253
+ function repairAssistantDateArithmeticInPipeline(pipeline) {
6254
+ var repairedRaw = normalizeAssistantNowExprPlaceholdersDeep(pipeline);
6255
+ var repaired = Array.isArray(repairedRaw)
6256
+ ? repairedRaw
6257
+ : pipeline;
6258
+ return {
6259
+ pipeline: repaired,
6260
+ changed: didAssistantValueChange(pipeline, repaired)
6261
+ };
6100
6262
  }
6101
6263
  function isMatchExpressionOperand(value) {
6102
6264
  if (typeof value === 'string') {
@@ -9406,7 +9568,7 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
9406
9568
  }
9407
9569
  function runCodexInWorkerThread(prompt, runOptions, config, streamStatusHandler) {
9408
9570
  return __awaiter(this, void 0, void 0, function () {
9409
- var streamedOptions, codexClient, workerPath, codexClient, error_4, codexClient;
9571
+ var streamedOptions, codexClient, workerPath, codexClient, error_5, codexClient;
9410
9572
  return __generator(this, function (_a) {
9411
9573
  switch (_a.label) {
9412
9574
  case 0:
@@ -9427,11 +9589,11 @@ function runCodexInWorkerThread(prompt, runOptions, config, streamStatusHandler)
9427
9589
  return [4 /*yield*/, runCodexInWorkerThreadInternal(workerPath, prompt, runOptions, config, streamStatusHandler)];
9428
9590
  case 6: return [2 /*return*/, _a.sent()];
9429
9591
  case 7:
9430
- error_4 = _a.sent();
9431
- if (!(error_4 instanceof CodexWorkerBootstrapError)) {
9432
- throw error_4;
9592
+ error_5 = _a.sent();
9593
+ if (!(error_5 instanceof CodexWorkerBootstrapError)) {
9594
+ throw error_5;
9433
9595
  }
9434
- console.error('Codex worker bootstrap failed, falling back to in-process run.', error_4);
9596
+ console.error('Codex worker bootstrap failed, falling back to in-process run.', error_5);
9435
9597
  codexClient = getAssistantCodexClient(config);
9436
9598
  return [4 /*yield*/, codexClient.run(prompt, streamedOptions)];
9437
9599
  case 8: return [2 /*return*/, _a.sent()];
@@ -9469,7 +9631,7 @@ function runCodexInWorkerThreadInternal(workerPath, prompt, runOptions, config,
9469
9631
  timeoutMs = ((sanitizedOptions === null || sanitizedOptions === void 0 ? void 0 : sanitizedOptions.timeoutMs) || resolveCodexTimeoutMs()) + 15000;
9470
9632
  timeoutController = new AbortController();
9471
9633
  timeoutPromise = (function () { return __awaiter(_this, void 0, void 0, function () {
9472
- var error_5;
9634
+ var error_6;
9473
9635
  return __generator(this, function (_a) {
9474
9636
  switch (_a.label) {
9475
9637
  case 0:
@@ -9479,11 +9641,11 @@ function runCodexInWorkerThreadInternal(workerPath, prompt, runOptions, config,
9479
9641
  _a.sent();
9480
9642
  return [2 /*return*/, { type: 'timeout' }];
9481
9643
  case 2:
9482
- error_5 = _a.sent();
9483
- if ((error_5 === null || error_5 === void 0 ? void 0 : error_5.name) === 'AbortError') {
9644
+ error_6 = _a.sent();
9645
+ if ((error_6 === null || error_6 === void 0 ? void 0 : error_6.name) === 'AbortError') {
9484
9646
  return [2 /*return*/, { type: 'aborted' }];
9485
9647
  }
9486
- throw error_5;
9648
+ throw error_6;
9487
9649
  case 3: return [2 /*return*/];
9488
9650
  }
9489
9651
  });
@@ -9806,34 +9968,178 @@ function resolveAssistantWorkspaceRoot() {
9806
9968
  });
9807
9969
  });
9808
9970
  }
9971
+ var AI_ASSISTANT_DATA_REQUEST_PATTERNS = [
9972
+ /\bshow\b/,
9973
+ /\blist\b/,
9974
+ /\bhow many\b/,
9975
+ /\bcount\b/,
9976
+ /\btotal\b/,
9977
+ /\bnumber of\b/,
9978
+ /\blast\b/,
9979
+ /\brecent\b/,
9980
+ /\bthis week\b/,
9981
+ /\blast month\b/,
9982
+ /\boverdue\b/,
9983
+ /\bopen\b/,
9984
+ /\bclosed\b/,
9985
+ /\bcompleted\b/,
9986
+ /\bmissing\b/,
9987
+ /\bgroup(ed)? by\b/,
9988
+ /\bbreakdown\b/,
9989
+ /\bper day\b/,
9990
+ /\bper week\b/,
9991
+ /\bper month\b/
9992
+ ];
9993
+ var AI_ASSISTANT_NAVIGATION_REQUEST_PATTERNS = [
9994
+ /\bwhere\b/,
9995
+ /\bhow do i\b/,
9996
+ /\bhow to\b/,
9997
+ /\bnavigate\b/,
9998
+ /\bgo to\b/,
9999
+ /\bwhich screen\b/,
10000
+ /\bwhich page\b/,
10001
+ /\bwhat menu\b/,
10002
+ /\broute\b/,
10003
+ /\bpath\b/,
10004
+ /\bfind\b/
10005
+ ];
10006
+ var AI_ASSISTANT_FEATURE_INFO_PATTERNS = [
10007
+ /\bwhat is\b/,
10008
+ /\bhow does\b/,
10009
+ /\bhow .* work\b/,
10010
+ /\bfeature\b/,
10011
+ /\bworkflow\b/,
10012
+ /\bprocess\b/,
10013
+ /\bexplain\b/,
10014
+ /\bdifference between\b/
10015
+ ];
10016
+ var AI_ASSISTANT_BUG_ISSUE_PATTERNS = [
10017
+ /\bbug\b/,
10018
+ /\bissue\b/,
10019
+ /\berror\b/,
10020
+ /\bexception\b/,
10021
+ /\bfail(?:ed|ing|ure)?\b/,
10022
+ /\bbroken\b/,
10023
+ /\bnot working\b/,
10024
+ /\bdoesn['’]t work\b/,
10025
+ /\bwhy is this happening\b/,
10026
+ /\broot cause\b/,
10027
+ /\bdebug\b/,
10028
+ /\binvestigat(?:e|ion)\b/,
10029
+ /\bfix\b/,
10030
+ /\bcrash(?:ed|ing)?\b/
10031
+ ];
9809
10032
  function isAssistantDataQuestion(message) {
9810
10033
  var text = normalizeOptionalString(message).toLowerCase();
9811
10034
  if (!text) {
9812
10035
  return false;
9813
10036
  }
9814
- var patterns = [
9815
- /\bshow\b/,
9816
- /\blist\b/,
9817
- /\bhow many\b/,
9818
- /\bcount\b/,
9819
- /\btotal\b/,
9820
- /\bnumber of\b/,
9821
- /\blast\b/,
9822
- /\brecent\b/,
9823
- /\bthis week\b/,
9824
- /\blast month\b/,
9825
- /\boverdue\b/,
9826
- /\bopen\b/,
9827
- /\bclosed\b/,
9828
- /\bcompleted\b/,
9829
- /\bmissing\b/,
9830
- /\bgroup(ed)? by\b/,
9831
- /\bbreakdown\b/,
9832
- /\bper day\b/,
9833
- /\bper week\b/,
9834
- /\bper month\b/
9835
- ];
9836
- return patterns.some(function (pattern) { return pattern.test(text); });
10037
+ return AI_ASSISTANT_DATA_REQUEST_PATTERNS.some(function (pattern) { return pattern.test(text); });
10038
+ }
10039
+ function isAssistantNavigationQuestion(message) {
10040
+ var text = normalizeOptionalString(message).toLowerCase();
10041
+ if (!text) {
10042
+ return false;
10043
+ }
10044
+ return AI_ASSISTANT_NAVIGATION_REQUEST_PATTERNS.some(function (pattern) { return pattern.test(text); });
10045
+ }
10046
+ function isAssistantFeatureInfoQuestion(message) {
10047
+ var text = normalizeOptionalString(message).toLowerCase();
10048
+ if (!text) {
10049
+ return false;
10050
+ }
10051
+ return AI_ASSISTANT_FEATURE_INFO_PATTERNS.some(function (pattern) { return pattern.test(text); });
10052
+ }
10053
+ function isAssistantBugIssueQuestion(message) {
10054
+ var text = normalizeOptionalString(message).toLowerCase();
10055
+ if (!text) {
10056
+ return false;
10057
+ }
10058
+ return AI_ASSISTANT_BUG_ISSUE_PATTERNS.some(function (pattern) { return pattern.test(text); });
10059
+ }
10060
+ function normalizeAssistantPlannerIntentType(value) {
10061
+ var normalized = normalizeOptionalString(value).toLowerCase();
10062
+ if (!normalized) {
10063
+ return null;
10064
+ }
10065
+ if (normalized === 'data') {
10066
+ return 'data';
10067
+ }
10068
+ if (normalized === 'navigation') {
10069
+ return 'navigation';
10070
+ }
10071
+ if (normalized === 'mixed') {
10072
+ return 'mixed';
10073
+ }
10074
+ if (normalized === 'feature_info' || normalized === 'program_explain') {
10075
+ return 'feature_info';
10076
+ }
10077
+ if (normalized === 'bug_issue') {
10078
+ return 'bug_issue';
10079
+ }
10080
+ return null;
10081
+ }
10082
+ function classifyAssistantRequestByHeuristics(message) {
10083
+ var isData = isAssistantDataQuestion(message);
10084
+ var isNavigation = isAssistantNavigationQuestion(message);
10085
+ var isBug = isAssistantBugIssueQuestion(message);
10086
+ var isFeatureInfo = isAssistantFeatureInfoQuestion(message);
10087
+ var type = 'unknown';
10088
+ if (isData && isNavigation) {
10089
+ type = 'mixed';
10090
+ }
10091
+ else if (isData) {
10092
+ type = 'data';
10093
+ }
10094
+ else if (isNavigation) {
10095
+ type = 'navigation';
10096
+ }
10097
+ else if (isBug) {
10098
+ type = 'bug_issue';
10099
+ }
10100
+ else if (isFeatureInfo) {
10101
+ type = 'feature_info';
10102
+ }
10103
+ return {
10104
+ type: type,
10105
+ dataQuestion: type === 'data' || type === 'mixed',
10106
+ source: 'heuristic'
10107
+ };
10108
+ }
10109
+ function classifyAssistantRequestType(message, plannerOutput) {
10110
+ var _a, _b;
10111
+ var heuristic = classifyAssistantRequestByHeuristics(message);
10112
+ var plannerIntentRaw = normalizeOptionalString((_a = plannerOutput === null || plannerOutput === void 0 ? void 0 : plannerOutput.intent) === null || _a === void 0 ? void 0 : _a.type).toLowerCase();
10113
+ var plannerIntent = normalizeAssistantPlannerIntentType(plannerIntentRaw);
10114
+ var plannerShouldFetch = ((_b = plannerOutput === null || plannerOutput === void 0 ? void 0 : plannerOutput.dataPlan) === null || _b === void 0 ? void 0 : _b.shouldFetchData) === true;
10115
+ if (!plannerIntent) {
10116
+ if (plannerShouldFetch) {
10117
+ return {
10118
+ type: heuristic.type === 'navigation' ? 'mixed' : 'data',
10119
+ dataQuestion: true,
10120
+ source: heuristic.type === 'navigation' ? 'merged' : 'planner',
10121
+ plannerIntentType: plannerIntentRaw || undefined
10122
+ };
10123
+ }
10124
+ return __assign(__assign({}, heuristic), { plannerIntentType: plannerIntentRaw || undefined });
10125
+ }
10126
+ var resolvedType = plannerIntent;
10127
+ var source = 'planner';
10128
+ if (plannerShouldFetch && resolvedType !== 'data' && resolvedType !== 'mixed') {
10129
+ resolvedType = resolvedType === 'navigation' ? 'mixed' : 'data';
10130
+ source = 'merged';
10131
+ }
10132
+ if (heuristic.dataQuestion && (resolvedType === 'navigation' || resolvedType === 'feature_info' || resolvedType === 'bug_issue')) {
10133
+ resolvedType = 'mixed';
10134
+ source = 'merged';
10135
+ }
10136
+ var dataQuestion = plannerShouldFetch || resolvedType === 'data' || resolvedType === 'mixed';
10137
+ return {
10138
+ type: resolvedType,
10139
+ dataQuestion: dataQuestion,
10140
+ source: source,
10141
+ plannerIntentType: plannerIntentRaw || undefined
10142
+ };
9837
10143
  }
9838
10144
  function buildAssistantCodexDirectivePrompt(message, attachmentText, historyText, contextText) {
9839
10145
  var trimmedContext = normalizeOptionalString(contextText);
@@ -10881,15 +11187,50 @@ function sanitizeConfig(source) {
10881
11187
  max_tokens: normalizeOptionalNumber(source === null || source === void 0 ? void 0 : source.max_tokens)
10882
11188
  };
10883
11189
  }
10884
- function resolveClientIdFromConfig(explicit) {
10885
- var _a;
10886
- var config = ((_a = resolveio_server_app_1.ResolveIOServer.getServerConfig) === null || _a === void 0 ? void 0 : _a.call(resolveio_server_app_1.ResolveIOServer)) || {};
10887
- return normalizeOptionalString(explicit)
10888
- || normalizeOptionalString(config['CLIENT_ID'] || config['client_id'] || process.env.CLIENT_ID || '');
11190
+ function isLikelyObjectId(value) {
11191
+ var normalized = normalizeOptionalString(value);
11192
+ return /^[a-f0-9]{24}$/i.test(normalized);
10889
11193
  }
10890
- function ensureConversation(input, mode) {
11194
+ function resolveClientIdFromConfig(explicit, contextUserId) {
10891
11195
  return __awaiter(this, void 0, void 0, function () {
10892
- var idConversation, existing, now, doc, result;
11196
+ var explicitValue, user, userClientId, _a, config, configClientId;
11197
+ var _b, _c;
11198
+ return __generator(this, function (_d) {
11199
+ switch (_d.label) {
11200
+ case 0:
11201
+ explicitValue = normalizeOptionalString(explicit);
11202
+ if (isLikelyObjectId(explicitValue)) {
11203
+ return [2 /*return*/, explicitValue];
11204
+ }
11205
+ if (!contextUserId) return [3 /*break*/, 4];
11206
+ _d.label = 1;
11207
+ case 1:
11208
+ _d.trys.push([1, 3, , 4]);
11209
+ return [4 /*yield*/, user_collection_1.Users.findById(contextUserId)];
11210
+ case 2:
11211
+ user = _d.sent();
11212
+ userClientId = normalizeOptionalString((_b = user === null || user === void 0 ? void 0 : user.other) === null || _b === void 0 ? void 0 : _b.id_client);
11213
+ if (userClientId) {
11214
+ return [2 /*return*/, userClientId];
11215
+ }
11216
+ return [3 /*break*/, 4];
11217
+ case 3:
11218
+ _a = _d.sent();
11219
+ return [3 /*break*/, 4];
11220
+ case 4:
11221
+ config = ((_c = resolveio_server_app_1.ResolveIOServer.getServerConfig) === null || _c === void 0 ? void 0 : _c.call(resolveio_server_app_1.ResolveIOServer)) || {};
11222
+ configClientId = normalizeOptionalString(config['CLIENT_ID'] || config['client_id'] || process.env.CLIENT_ID || '');
11223
+ if (configClientId) {
11224
+ return [2 /*return*/, configClientId];
11225
+ }
11226
+ return [2 /*return*/, explicitValue];
11227
+ }
11228
+ });
11229
+ });
11230
+ }
11231
+ function ensureConversation(input, mode, contextUserId) {
11232
+ return __awaiter(this, void 0, void 0, function () {
11233
+ var idConversation, existing, now, resolvedClientId, doc, result;
10893
11234
  return __generator(this, function (_a) {
10894
11235
  switch (_a.label) {
10895
11236
  case 0:
@@ -10904,8 +11245,11 @@ function ensureConversation(input, mode) {
10904
11245
  _a.label = 2;
10905
11246
  case 2:
10906
11247
  now = new Date();
11248
+ return [4 /*yield*/, resolveClientIdFromConfig(input.id_client, contextUserId)];
11249
+ case 3:
11250
+ resolvedClientId = _a.sent();
10907
11251
  doc = {
10908
- id_client: resolveClientIdFromConfig(input.id_client),
11252
+ id_client: resolvedClientId,
10909
11253
  id_app: normalizeOptionalString(input.id_app),
10910
11254
  title: 'New Conversation',
10911
11255
  mode: mode,
@@ -10917,7 +11261,7 @@ function ensureConversation(input, mode) {
10917
11261
  updatedAt: now
10918
11262
  };
10919
11263
  return [4 /*yield*/, ai_terminal_conversation_collection_1.AiTerminalConversations.insertOne(doc)];
10920
- case 3:
11264
+ case 4:
10921
11265
  result = _a.sent();
10922
11266
  return [2 /*return*/, result];
10923
11267
  }
@@ -11001,10 +11345,25 @@ function normalizeHistoryLimit(value) {
11001
11345
  }
11002
11346
  return Math.min(Math.max((0, common_1.round)(parsed), 0), 30);
11003
11347
  }
11004
- function resolveClientId(conversation, inputClientId) {
11005
- return normalizeOptionalString(inputClientId)
11006
- || normalizeOptionalString(conversation === null || conversation === void 0 ? void 0 : conversation.id_client)
11007
- || resolveClientIdFromConfig();
11348
+ function resolveClientId(conversation, inputClientId, contextUserId) {
11349
+ return __awaiter(this, void 0, void 0, function () {
11350
+ var inputValue, conversationValue;
11351
+ return __generator(this, function (_a) {
11352
+ switch (_a.label) {
11353
+ case 0:
11354
+ inputValue = normalizeOptionalString(inputClientId);
11355
+ if (isLikelyObjectId(inputValue)) {
11356
+ return [2 /*return*/, inputValue];
11357
+ }
11358
+ conversationValue = normalizeOptionalString(conversation === null || conversation === void 0 ? void 0 : conversation.id_client);
11359
+ if (isLikelyObjectId(conversationValue)) {
11360
+ return [2 /*return*/, conversationValue];
11361
+ }
11362
+ return [4 /*yield*/, resolveClientIdFromConfig(inputValue || conversationValue, contextUserId)];
11363
+ case 1: return [2 /*return*/, _a.sent()];
11364
+ }
11365
+ });
11366
+ });
11008
11367
  }
11009
11368
  function estimateUsage(messages, responseText, model) {
11010
11369
  var inputTokens = (0, tokenizer_1.countChatTokens)(messages, model);