@resolveio/server-lib 20.15.4 → 20.15.6

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.
@@ -142,9 +142,11 @@ var AI_ASSISTANT_TOOL_MAX_STEPS = 1;
142
142
  var AI_ASSISTANT_DISPLAY_MAX_COLUMNS = 12;
143
143
  var AI_ASSISTANT_DISPLAY_PREVIEW_MAX_ROWS = 20;
144
144
  var AI_ASSISTANT_DISPLAY_STRING_LIMIT = 160;
145
- var AI_ASSISTANT_PROGRESS_PLACEHOLDER = 'Thinking...';
145
+ var AI_ASSISTANT_PROGRESS_PLACEHOLDER = 'Planning...';
146
146
  var AI_ASSISTANT_PROGRESS_TICK_MS = 5000;
147
+ var AI_ASSISTANT_READ_PREFERENCE = 'secondary';
147
148
  var AI_ASSISTANT_PROGRESS_TICKS = [
149
+ 'Grabbing Data',
148
150
  'Drafting response'
149
151
  ];
150
152
  var AI_ASSISTANT_DISPLAY_PRIORITY_FIELDS = [
@@ -255,6 +257,7 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
255
257
  '- Do not assist with hacking, bypassing security, or abuse.',
256
258
  'Accuracy & tools:',
257
259
  '- Step 1 (always): determine the target collections/models/modules/workflows using context, routes, and collection hints. Assume the user is non-technical and will not provide internal names.',
260
+ '- Planning stage: regex/keyword scan the codebase for collectionName/model definitions, methods, publications, and Angular routes/modules to map user wording to internal names.',
258
261
  '- Map user wording to internal collections/fields yourself. Do not ask for property names unless required to run a query.',
259
262
  '- Do not guess or invent collections/fields. If unsure, verify in the codebase or run a small Mongo read (limit 1-5) to learn the shape.',
260
263
  '- Prefer running a small Mongo read over asking multiple questions.',
@@ -263,7 +266,9 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
263
266
  '- If a field starts with id_ and refers to another collection, treat it as a foreign key and look up the related record when needed.',
264
267
  '- When the user provides a customer, well, or chemical name, use case-insensitive regex matching to find it. Assume the name exists and try to match it before asking questions.',
265
268
  '- Use the codebase context to choose correct collections/fields/workflows and use MONGO_READ/MONGO_AGG to answer with real data when needed.',
269
+ '- Process (fast path): Queue -> Planning -> Grabbing Data -> Drafting response. Use regex/keyword matching to identify collections/models, draft a minimal query, run the tool, then format a table. This should be fast; avoid extra narration.',
266
270
  '- Assume a relevant collection exists; if verification reads return zero data, report no data found instead of interrogating the user.',
271
+ '- Never claim "no data exists" unless you resolved a collection and executed a legitimate query (with fallback date fields when needed) that returned zero rows.',
267
272
  '- For direct questions, answer first. Ask a single follow-up only if required to proceed.',
268
273
  'Data Presentation:',
269
274
  '- Output plain Markdown (NO triple backticks).',
@@ -307,6 +312,8 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
307
312
  '- Only request data when the user has permission for that module; invoice data requires invoice view access.',
308
313
  '- If the user lacks permission, answer without data and explain how to view it in the app or request access.',
309
314
  '- For simple counts or time-range totals, use MONGO_READ (includeTotal). For breakdowns, rankings, or sums grouped by a field, use MONGO_AGG.',
315
+ '- For performance, keep pipelines minimal: avoid $push arrays or large fields unless the user explicitly asks for them.',
316
+ '- For completion metrics (ex: "completed per day"), filter by completed status when applicable and use completion date fields; if completion dates are missing, fall back to createdAt/date_created and note the fallback.',
310
317
  '- Before issuing MONGO_READ or MONGO_AGG, verify the collection name and key fields by checking collection/model definitions in the current app (look for "collectionName:" and date fields like date_created/date_completed/createdAt). Do not invent collection names.',
311
318
  '- For creation-date questions when both date_created and createdAt exist, match both with $or so results are not missed.',
312
319
  '- When grouping by fields that can be arrays (drivers, deliveries, routes, chemicals), $unwind first and group by both id and name when available.',
@@ -325,6 +332,76 @@ var AI_FORM_PATCH_SYSTEM_PROMPT = [
325
332
  '- Use medium reasoning effort.'
326
333
  ].join('\n');
327
334
  var assistantCodexClient = null;
335
+ var assistantCodexRunQueue = [];
336
+ var assistantCodexRunDraining = false;
337
+ /* eslint-enable no-unused-vars */
338
+ function enqueueAssistantCodexRun(task) {
339
+ var _this = this;
340
+ assistantCodexRunQueue.push(task);
341
+ if (assistantCodexRunDraining) {
342
+ return;
343
+ }
344
+ assistantCodexRunDraining = true;
345
+ queueMicrotask(function () { return __awaiter(_this, void 0, void 0, function () {
346
+ return __generator(this, function (_a) {
347
+ switch (_a.label) {
348
+ case 0: return [4 /*yield*/, drainAssistantCodexRunQueue()];
349
+ case 1:
350
+ _a.sent();
351
+ return [2 /*return*/];
352
+ }
353
+ });
354
+ }); });
355
+ }
356
+ function drainAssistantCodexRunQueue() {
357
+ return __awaiter(this, void 0, void 0, function () {
358
+ var next, error_1;
359
+ var _this = this;
360
+ return __generator(this, function (_a) {
361
+ switch (_a.label) {
362
+ case 0:
363
+ _a.trys.push([0, , 7, 8]);
364
+ _a.label = 1;
365
+ case 1:
366
+ if (!assistantCodexRunQueue.length) return [3 /*break*/, 6];
367
+ next = assistantCodexRunQueue.shift();
368
+ if (!next) {
369
+ return [3 /*break*/, 1];
370
+ }
371
+ _a.label = 2;
372
+ case 2:
373
+ _a.trys.push([2, 4, , 5]);
374
+ return [4 /*yield*/, next()];
375
+ case 3:
376
+ _a.sent();
377
+ return [3 /*break*/, 5];
378
+ case 4:
379
+ error_1 = _a.sent();
380
+ console.error(new Date(), 'AI assistant run failed:', error_1);
381
+ return [3 /*break*/, 5];
382
+ case 5: return [3 /*break*/, 1];
383
+ case 6: return [3 /*break*/, 8];
384
+ case 7:
385
+ assistantCodexRunDraining = false;
386
+ if (assistantCodexRunQueue.length) {
387
+ assistantCodexRunDraining = true;
388
+ queueMicrotask(function () { return __awaiter(_this, void 0, void 0, function () {
389
+ return __generator(this, function (_a) {
390
+ switch (_a.label) {
391
+ case 0: return [4 /*yield*/, drainAssistantCodexRunQueue()];
392
+ case 1:
393
+ _a.sent();
394
+ return [2 /*return*/];
395
+ }
396
+ });
397
+ }); });
398
+ }
399
+ return [7 /*endfinally*/];
400
+ case 8: return [2 /*return*/];
401
+ }
402
+ });
403
+ });
404
+ }
328
405
  function loadAiTerminalMethods(methodManager) {
329
406
  methodManager.methods({
330
407
  aiTerminalConversationCreate: {
@@ -852,10 +929,11 @@ function executeAiFormPatch(payload, context) {
852
929
  }
853
930
  function executeAiAssistantCodexRun(payload, context) {
854
931
  return __awaiter(this, void 0, void 0, function () {
855
- var input, message, requestId, guardrail, conversation_2, now_2, userMsg, assistantMsg, user, isSuperAdmin, hasInvoiceAccess, customerId, conversation, now, attachments, attachmentData, historyLimit, history, _a, historyLines, collectionHints, dbName, db, hintText, _b, assistantContext, prompt, workspaceRoot, codexConfig, runOptions, userDoc, initialProgress, assistantDoc, insertResult, assistantMessageId, progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, dataQuestion, lastDirective, toolResponseDebug, toolError, responseText, directive, directiveSourceText, directivePrompt, directiveText, forcedDirective, _c, cleanedResponseText, toolRequest, toolResponse, _d, toolPayload, followupPrompt, followupText, _e, error_1, error_2, finalNow, finalMetadata, finalAssistantDoc;
856
- var _f, _g, _h;
857
- return __generator(this, function (_j) {
858
- switch (_j.label) {
932
+ var input, message, requestId, guardrail, conversation_2, now_2, userMsg, assistantMsg, user, isSuperAdmin, hasInvoiceAccess, customerId, conversation, now, attachments, attachmentData, historyLimit, history, _a, historyLines, userDoc, initialProgress, assistantDoc, insertResult, assistantMessageId;
933
+ var _this = this;
934
+ var _b, _c;
935
+ return __generator(this, function (_d) {
936
+ switch (_d.label) {
859
937
  case 0:
860
938
  input = payload || {};
861
939
  message = normalizeOptionalString(input.message);
@@ -870,7 +948,7 @@ function executeAiAssistantCodexRun(payload, context) {
870
948
  if (!(guardrail === null || guardrail === void 0 ? void 0 : guardrail.blocked)) return [3 /*break*/, 5];
871
949
  return [4 /*yield*/, ensureConversation(input, 'codex')];
872
950
  case 1:
873
- conversation_2 = _j.sent();
951
+ conversation_2 = _d.sent();
874
952
  now_2 = new Date();
875
953
  userMsg = {
876
954
  id_conversation: conversation_2._id,
@@ -890,13 +968,13 @@ function executeAiAssistantCodexRun(payload, context) {
890
968
  };
891
969
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(userMsg)];
892
970
  case 2:
893
- _j.sent();
971
+ _d.sent();
894
972
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(assistantMsg)];
895
973
  case 3:
896
- _j.sent();
974
+ _d.sent();
897
975
  return [4 /*yield*/, touchConversation(conversation_2._id, now_2)];
898
976
  case 4:
899
- _j.sent();
977
+ _d.sent();
900
978
  return [2 /*return*/, {
901
979
  conversation: conversation_2,
902
980
  message: assistantMsg,
@@ -904,27 +982,27 @@ function executeAiAssistantCodexRun(payload, context) {
904
982
  }];
905
983
  case 5: return [4 /*yield*/, user_collection_1.Users.findById(context === null || context === void 0 ? void 0 : context.id_user)];
906
984
  case 6:
907
- user = _j.sent();
908
- isSuperAdmin = !!((_f = user === null || user === void 0 ? void 0 : user.roles) === null || _f === void 0 ? void 0 : _f.super_admin);
985
+ user = _d.sent();
986
+ isSuperAdmin = !!((_b = user === null || user === void 0 ? void 0 : user.roles) === null || _b === void 0 ? void 0 : _b.super_admin);
909
987
  hasInvoiceAccess = userHasInvoiceAccess(user);
910
- customerId = normalizeOptionalString((_g = user === null || user === void 0 ? void 0 : user.other) === null || _g === void 0 ? void 0 : _g.id_customer);
988
+ customerId = normalizeOptionalString((_c = user === null || user === void 0 ? void 0 : user.other) === null || _c === void 0 ? void 0 : _c.id_customer);
911
989
  return [4 /*yield*/, ensureConversation(input, 'codex')];
912
990
  case 7:
913
- conversation = _j.sent();
991
+ conversation = _d.sent();
914
992
  now = new Date();
915
993
  attachments = Array.isArray(input.attachments) ? input.attachments : [];
916
994
  return [4 /*yield*/, readAttachmentContents(attachments)];
917
995
  case 8:
918
- attachmentData = _j.sent();
996
+ attachmentData = _d.sent();
919
997
  historyLimit = normalizeHistoryLimit(input.max_history);
920
998
  if (!(historyLimit > 0)) return [3 /*break*/, 10];
921
999
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.find({ id_conversation: conversation._id, role: { $in: ['user', 'assistant'] } }, { sort: { createdAt: 1 }, limit: historyLimit * 2 })];
922
1000
  case 9:
923
- _a = _j.sent();
1001
+ _a = _d.sent();
924
1002
  return [3 /*break*/, 11];
925
1003
  case 10:
926
1004
  _a = [];
927
- _j.label = 11;
1005
+ _d.label = 11;
928
1006
  case 11:
929
1007
  history = _a;
930
1008
  historyLines = [];
@@ -935,49 +1013,6 @@ function executeAiAssistantCodexRun(payload, context) {
935
1013
  historyLines.push("".concat(role, ": ").concat(content));
936
1014
  }
937
1015
  });
938
- collectionHints = [];
939
- _j.label = 12;
940
- case 12:
941
- _j.trys.push([12, 14, , 15]);
942
- dbName = resolveAssistantDatabaseName(undefined, input.mongo);
943
- db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
944
- hintText = [
945
- message,
946
- normalizeOptionalString((_h = input === null || input === void 0 ? void 0 : input.context) === null || _h === void 0 ? void 0 : _h.route)
947
- ].filter(Boolean).join(' ');
948
- return [4 /*yield*/, resolveAssistantCollectionHints(hintText, dbName, db)];
949
- case 13:
950
- collectionHints = _j.sent();
951
- return [3 /*break*/, 15];
952
- case 14:
953
- _b = _j.sent();
954
- collectionHints = [];
955
- return [3 /*break*/, 15];
956
- case 15:
957
- assistantContext = buildAssistantContext(input, {
958
- isSuperAdmin: isSuperAdmin,
959
- hasInvoiceAccess: hasInvoiceAccess,
960
- customerId: customerId,
961
- collectionHints: collectionHints
962
- });
963
- prompt = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
964
- return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
965
- case 16:
966
- workspaceRoot = _j.sent();
967
- codexConfig = resolveCodexSettings();
968
- runOptions = {
969
- timeoutMs: resolveCodexTimeoutMs(),
970
- threadOptions: {
971
- workingDirectory: workspaceRoot,
972
- sandboxMode: 'read-only',
973
- skipGitRepoCheck: true,
974
- modelReasoningEffort: resolveCodexThoughtLevel(),
975
- networkAccessEnabled: false,
976
- webSearchMode: 'disabled',
977
- webSearchEnabled: false,
978
- approvalPolicy: 'never'
979
- }
980
- };
981
1016
  userDoc = {
982
1017
  id_conversation: conversation._id,
983
1018
  role: 'user',
@@ -987,7 +1022,7 @@ function executeAiAssistantCodexRun(payload, context) {
987
1022
  createdAt: now,
988
1023
  updatedAt: now
989
1024
  };
990
- initialProgress = ['Thinking'];
1025
+ initialProgress = ['Planning'];
991
1026
  assistantDoc = {
992
1027
  id_conversation: conversation._id,
993
1028
  role: 'assistant',
@@ -997,154 +1032,234 @@ function executeAiAssistantCodexRun(payload, context) {
997
1032
  updatedAt: now
998
1033
  };
999
1034
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(userDoc)];
1000
- case 17:
1001
- _j.sent();
1035
+ case 12:
1036
+ _d.sent();
1002
1037
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(assistantDoc)];
1003
- case 18:
1004
- insertResult = _j.sent();
1038
+ case 13:
1039
+ insertResult = _d.sent();
1005
1040
  assistantMessageId = (insertResult === null || insertResult === void 0 ? void 0 : insertResult._id) || (insertResult === null || insertResult === void 0 ? void 0 : insertResult.insertedId);
1006
- progressTracker = createAssistantProgressTracker(assistantMessageId, initialProgress);
1007
- streamProgress = createAssistantStreamProgressHandler(progressTracker);
1008
- assistantContent = '';
1009
- toolResult = null;
1010
- assistantDebug = null;
1011
- directiveSource = 'none';
1012
- dataQuestion = isAssistantDataQuestion(message);
1013
- lastDirective = null;
1014
- toolResponseDebug = null;
1015
- toolError = null;
1016
- _j.label = 19;
1017
- case 19:
1018
- _j.trys.push([19, 38, 39, 40]);
1019
- return [4 /*yield*/, runCodexInWorkerThread(prompt, runOptions, codexConfig, streamProgress)];
1020
- case 20:
1021
- responseText = _j.sent();
1022
- directive = extractAssistantMongoDirective(responseText);
1023
- directiveSourceText = responseText;
1024
- if (directive) {
1025
- directiveSource = 'model';
1026
- lastDirective = directive;
1027
- }
1028
- if (!(!directive && dataQuestion)) return [3 /*break*/, 24];
1029
- directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1030
- _j.label = 21;
1031
- case 21:
1032
- _j.trys.push([21, 23, , 24]);
1033
- return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1034
- case 22:
1035
- directiveText = _j.sent();
1036
- forcedDirective = extractAssistantMongoDirective(directiveText);
1037
- if (forcedDirective) {
1038
- directive = forcedDirective;
1039
- directiveSourceText = directiveText;
1040
- directiveSource = 'forced';
1041
- lastDirective = forcedDirective;
1042
- }
1043
- return [3 /*break*/, 24];
1044
- case 23:
1045
- _c = _j.sent();
1046
- return [3 /*break*/, 24];
1047
- case 24:
1048
- cleanedResponseText = (directive === null || directive === void 0 ? void 0 : directive.cleaned) || directiveSourceText;
1049
- assistantContent = sanitizeAssistantResponse(cleanedResponseText);
1050
- if (!((directive === null || directive === void 0 ? void 0 : directive.payload) && AI_ASSISTANT_TOOL_MAX_STEPS > 0)) return [3 /*break*/, 36];
1051
- toolRequest = buildAssistantToolRequest(directive, input);
1052
- progressTracker.push('Looking up Data');
1053
- _j.label = 25;
1054
- case 25:
1055
- _j.trys.push([25, 34, , 35]);
1056
- if (!(directive.type === 'aggregate')) return [3 /*break*/, 27];
1057
- return [4 /*yield*/, executeAiAssistantMongoAggregate(toolRequest, context)];
1058
- case 26:
1059
- _d = _j.sent();
1060
- return [3 /*break*/, 29];
1061
- case 27: return [4 /*yield*/, executeAiAssistantMongoRead(toolRequest, context)];
1062
- case 28:
1063
- _d = _j.sent();
1064
- _j.label = 29;
1065
- case 29:
1066
- toolResponse = _d;
1067
- toolResponseDebug = (toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.debug) && typeof toolResponse.debug === 'object'
1068
- ? toolResponse.debug
1069
- : null;
1070
- toolPayload = buildAssistantToolResultPayload(directive, toolResponse);
1071
- toolResult = toolPayload.result;
1072
- progressTracker.push('Drafting response');
1073
- followupPrompt = buildAssistantCodexToolFollowupPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, toolPayload.prompt);
1074
- _j.label = 30;
1075
- case 30:
1076
- _j.trys.push([30, 32, , 33]);
1077
- return [4 /*yield*/, runCodexInWorkerThread(followupPrompt, runOptions, codexConfig, streamProgress)];
1078
- case 31:
1079
- followupText = _j.sent();
1080
- assistantContent = sanitizeAssistantResponse(followupText);
1081
- return [3 /*break*/, 33];
1082
- case 32:
1083
- _e = _j.sent();
1084
- assistantContent = buildAssistantToolFallbackResponse(toolPayload.result);
1085
- return [3 /*break*/, 33];
1086
- case 33: return [3 /*break*/, 35];
1087
- case 34:
1088
- error_1 = _j.sent();
1089
- assistantContent = buildAssistantToolErrorMessage(error_1, directive, toolRequest);
1090
- toolError = error_1;
1091
- return [3 /*break*/, 35];
1092
- case 35: return [3 /*break*/, 37];
1093
- case 36:
1094
- progressTracker.push('Drafting response');
1095
- _j.label = 37;
1096
- case 37: return [3 /*break*/, 40];
1097
- case 38:
1098
- error_2 = _j.sent();
1099
- assistantContent = buildAssistantCodexErrorMessage(error_2);
1100
- return [3 /*break*/, 40];
1101
- case 39:
1102
- progressTracker.stop();
1103
- return [7 /*endfinally*/];
1104
- case 40:
1105
- if (!assistantContent) {
1106
- assistantContent = buildAssistantCodexErrorMessage(null);
1107
- }
1108
- finalNow = new Date();
1109
- if (isSuperAdmin) {
1110
- assistantDebug = buildAssistantDebugPayload({
1111
- dataQuestion: dataQuestion,
1112
- directive: lastDirective,
1113
- directiveSource: directiveSource,
1114
- toolResult: toolResult,
1115
- toolResponseDebug: toolResponseDebug,
1116
- toolError: toolError
1117
- });
1118
- }
1119
- finalMetadata = __assign(__assign(__assign({ model: resolveCodexModel() }, (requestId ? { request_id: requestId } : {})), (toolResult ? { tool_result: toolResult } : {})), (assistantDebug ? { debug: assistantDebug } : {}));
1120
- finalAssistantDoc = __assign(__assign({}, assistantDoc), { _id: assistantMessageId, content: assistantContent, metadata: finalMetadata, updatedAt: finalNow });
1121
- if (!assistantMessageId) return [3 /*break*/, 42];
1122
- return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.updateOne({ _id: assistantMessageId }, {
1123
- $set: {
1124
- content: assistantContent,
1125
- metadata: finalMetadata,
1126
- updatedAt: finalNow
1041
+ enqueueAssistantCodexRun(function () { return __awaiter(_this, void 0, void 0, function () {
1042
+ var progressTracker, streamProgress, assistantContent, toolResult, assistantDebug, directiveSource, dataQuestion, lastDirective, toolResponseDebug, toolError, collectionHints, dbName, db, hintText, _a, assistantContext, prompt_1, workspaceRoot, codexConfig, runOptions, responseText, directiveText, directive, directivePrompt, forcedDirective, _b, directivePrompt, forcedDirective, _c, cleanedResponseText, toolRequest, toolResponse, _d, toolPayload, followupPrompt, followupText, _e, error_2, error_3, finalNow, finalMetadata, finalAssistantDoc;
1043
+ var _f;
1044
+ return __generator(this, function (_g) {
1045
+ switch (_g.label) {
1046
+ case 0:
1047
+ progressTracker = createAssistantProgressTracker(assistantMessageId, initialProgress);
1048
+ streamProgress = createAssistantStreamProgressHandler(progressTracker);
1049
+ assistantContent = '';
1050
+ toolResult = null;
1051
+ assistantDebug = null;
1052
+ directiveSource = 'none';
1053
+ dataQuestion = isAssistantDataQuestion(message);
1054
+ lastDirective = null;
1055
+ toolResponseDebug = null;
1056
+ toolError = null;
1057
+ _g.label = 1;
1058
+ case 1:
1059
+ _g.trys.push([1, 30, 31, 32]);
1060
+ collectionHints = [];
1061
+ _g.label = 2;
1062
+ case 2:
1063
+ _g.trys.push([2, 4, , 5]);
1064
+ dbName = resolveAssistantDatabaseName(undefined, input.mongo);
1065
+ db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1066
+ hintText = [
1067
+ message,
1068
+ normalizeOptionalString((_f = input === null || input === void 0 ? void 0 : input.context) === null || _f === void 0 ? void 0 : _f.route)
1069
+ ].filter(Boolean).join(' ');
1070
+ return [4 /*yield*/, resolveAssistantCollectionHints(hintText, dbName, db)];
1071
+ case 3:
1072
+ collectionHints = _g.sent();
1073
+ return [3 /*break*/, 5];
1074
+ case 4:
1075
+ _a = _g.sent();
1076
+ collectionHints = [];
1077
+ return [3 /*break*/, 5];
1078
+ case 5:
1079
+ assistantContext = buildAssistantContext(input, {
1080
+ isSuperAdmin: isSuperAdmin,
1081
+ hasInvoiceAccess: hasInvoiceAccess,
1082
+ customerId: customerId,
1083
+ collectionHints: collectionHints
1084
+ });
1085
+ prompt_1 = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1086
+ return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
1087
+ case 6:
1088
+ workspaceRoot = _g.sent();
1089
+ codexConfig = resolveCodexSettings();
1090
+ runOptions = {
1091
+ timeoutMs: resolveCodexTimeoutMs(),
1092
+ threadOptions: {
1093
+ workingDirectory: workspaceRoot,
1094
+ sandboxMode: 'read-only',
1095
+ skipGitRepoCheck: true,
1096
+ modelReasoningEffort: resolveCodexThoughtLevel(),
1097
+ networkAccessEnabled: false,
1098
+ webSearchMode: 'disabled',
1099
+ webSearchEnabled: false,
1100
+ approvalPolicy: 'never'
1101
+ }
1102
+ };
1103
+ responseText = '';
1104
+ directiveText = '';
1105
+ directive = null;
1106
+ if (!dataQuestion) return [3 /*break*/, 10];
1107
+ directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1108
+ _g.label = 7;
1109
+ case 7:
1110
+ _g.trys.push([7, 9, , 10]);
1111
+ return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1112
+ case 8:
1113
+ directiveText = _g.sent();
1114
+ forcedDirective = extractAssistantMongoDirective(directiveText);
1115
+ if (forcedDirective) {
1116
+ directive = forcedDirective;
1117
+ directiveSource = 'model';
1118
+ lastDirective = forcedDirective;
1119
+ }
1120
+ return [3 /*break*/, 10];
1121
+ case 9:
1122
+ _b = _g.sent();
1123
+ return [3 /*break*/, 10];
1124
+ case 10:
1125
+ if (!!directive) return [3 /*break*/, 12];
1126
+ return [4 /*yield*/, runCodexInWorkerThread(prompt_1, runOptions, codexConfig, streamProgress)];
1127
+ case 11:
1128
+ responseText = _g.sent();
1129
+ directive = extractAssistantMongoDirective(responseText);
1130
+ if (directive) {
1131
+ directiveSource = 'model';
1132
+ lastDirective = directive;
1133
+ }
1134
+ _g.label = 12;
1135
+ case 12:
1136
+ if (!(!directive && dataQuestion)) return [3 /*break*/, 16];
1137
+ directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
1138
+ _g.label = 13;
1139
+ case 13:
1140
+ _g.trys.push([13, 15, , 16]);
1141
+ return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, runOptions, codexConfig, streamProgress)];
1142
+ case 14:
1143
+ directiveText = _g.sent();
1144
+ forcedDirective = extractAssistantMongoDirective(directiveText);
1145
+ if (forcedDirective) {
1146
+ directive = forcedDirective;
1147
+ directiveSource = 'forced';
1148
+ lastDirective = forcedDirective;
1149
+ }
1150
+ return [3 /*break*/, 16];
1151
+ case 15:
1152
+ _c = _g.sent();
1153
+ return [3 /*break*/, 16];
1154
+ case 16:
1155
+ cleanedResponseText = (directive === null || directive === void 0 ? void 0 : directive.cleaned) || responseText;
1156
+ if (cleanedResponseText) {
1157
+ assistantContent = sanitizeAssistantResponse(cleanedResponseText);
1158
+ }
1159
+ if (!((directive === null || directive === void 0 ? void 0 : directive.payload) && AI_ASSISTANT_TOOL_MAX_STEPS > 0)) return [3 /*break*/, 28];
1160
+ toolRequest = buildAssistantToolRequest(directive, input);
1161
+ progressTracker.push('Grabbing Data');
1162
+ _g.label = 17;
1163
+ case 17:
1164
+ _g.trys.push([17, 26, , 27]);
1165
+ if (!(directive.type === 'aggregate')) return [3 /*break*/, 19];
1166
+ return [4 /*yield*/, executeAiAssistantMongoAggregate(toolRequest, context)];
1167
+ case 18:
1168
+ _d = _g.sent();
1169
+ return [3 /*break*/, 21];
1170
+ case 19: return [4 /*yield*/, executeAiAssistantMongoRead(toolRequest, context)];
1171
+ case 20:
1172
+ _d = _g.sent();
1173
+ _g.label = 21;
1174
+ case 21:
1175
+ toolResponse = _d;
1176
+ toolResponseDebug = (toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.debug) && typeof toolResponse.debug === 'object'
1177
+ ? toolResponse.debug
1178
+ : null;
1179
+ toolPayload = buildAssistantToolResultPayload(directive, toolResponse);
1180
+ toolResult = toolPayload.result;
1181
+ progressTracker.push('Drafting response');
1182
+ followupPrompt = buildAssistantCodexToolFollowupPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, toolPayload.prompt);
1183
+ _g.label = 22;
1184
+ case 22:
1185
+ _g.trys.push([22, 24, , 25]);
1186
+ return [4 /*yield*/, runCodexInWorkerThread(followupPrompt, runOptions, codexConfig, streamProgress)];
1187
+ case 23:
1188
+ followupText = _g.sent();
1189
+ assistantContent = sanitizeAssistantResponse(followupText);
1190
+ return [3 /*break*/, 25];
1191
+ case 24:
1192
+ _e = _g.sent();
1193
+ assistantContent = buildAssistantToolFallbackResponse(toolPayload.result);
1194
+ return [3 /*break*/, 25];
1195
+ case 25: return [3 /*break*/, 27];
1196
+ case 26:
1197
+ error_2 = _g.sent();
1198
+ assistantContent = buildAssistantToolErrorMessage(error_2, directive, toolRequest);
1199
+ toolError = error_2;
1200
+ return [3 /*break*/, 27];
1201
+ case 27: return [3 /*break*/, 29];
1202
+ case 28:
1203
+ progressTracker.push('Drafting response');
1204
+ _g.label = 29;
1205
+ case 29: return [3 /*break*/, 32];
1206
+ case 30:
1207
+ error_3 = _g.sent();
1208
+ assistantContent = buildAssistantCodexErrorMessage(error_3);
1209
+ return [3 /*break*/, 32];
1210
+ case 31:
1211
+ progressTracker.stop();
1212
+ return [7 /*endfinally*/];
1213
+ case 32:
1214
+ if (!assistantContent) {
1215
+ assistantContent = buildAssistantCodexErrorMessage(null);
1216
+ }
1217
+ finalNow = new Date();
1218
+ if (isSuperAdmin) {
1219
+ assistantDebug = buildAssistantDebugPayload({
1220
+ dataQuestion: dataQuestion,
1221
+ directive: lastDirective,
1222
+ directiveSource: directiveSource,
1223
+ toolResult: toolResult,
1224
+ toolResponseDebug: toolResponseDebug,
1225
+ toolError: toolError
1226
+ });
1227
+ }
1228
+ finalMetadata = __assign(__assign(__assign({ model: resolveCodexModel() }, (requestId ? { request_id: requestId } : {})), (toolResult ? { tool_result: toolResult } : {})), (assistantDebug ? { debug: assistantDebug } : {}));
1229
+ finalAssistantDoc = __assign(__assign({}, assistantDoc), { _id: assistantMessageId, content: assistantContent, metadata: finalMetadata, updatedAt: finalNow });
1230
+ if (!assistantMessageId) return [3 /*break*/, 34];
1231
+ return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.updateOne({ _id: assistantMessageId }, {
1232
+ $set: {
1233
+ content: assistantContent,
1234
+ metadata: finalMetadata,
1235
+ updatedAt: finalNow
1236
+ }
1237
+ })];
1238
+ case 33:
1239
+ _g.sent();
1240
+ _g.label = 34;
1241
+ case 34: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
1242
+ case 35:
1243
+ _g.sent();
1244
+ if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 37];
1245
+ return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
1246
+ case 36:
1247
+ _g.sent();
1248
+ _g.label = 37;
1249
+ case 37: return [2 /*return*/, finalAssistantDoc];
1127
1250
  }
1128
- })];
1129
- case 41:
1130
- _j.sent();
1131
- _j.label = 42;
1132
- case 42: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
1133
- case 43:
1134
- _j.sent();
1135
- if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 45];
1136
- return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
1137
- case 44:
1138
- _j.sent();
1139
- _j.label = 45;
1140
- case 45: return [2 /*return*/, __assign({ conversation: conversation, message: finalAssistantDoc }, (toolResult ? { tool_result: toolResult } : {}))];
1251
+ });
1252
+ }); });
1253
+ return [2 /*return*/, {
1254
+ conversation: conversation
1255
+ }];
1141
1256
  }
1142
1257
  });
1143
1258
  });
1144
1259
  }
1145
1260
  function executeAiAssistantMongoRead(payload, context) {
1146
1261
  return __awaiter(this, void 0, void 0, function () {
1147
- var input, rawCollection, dbName, db, collectionResolution, collection, _a, user, isSuperAdmin, customerId, baseQuery, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalized, documents, executedQuery, fallbackMeta, dateFallback, fallbackQuery, fallbackDocs, total, sanitizedDocuments, includeIds, display;
1262
+ var input, rawCollection, dbName, db, collectionResolution, collection, _a, user, isSuperAdmin, customerId, baseQuery, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalized, findOptions, documents, executedQuery, fallbackMeta, dateFallback, fallbackQuery, fallbackDocs, total, sanitizedDocuments, includeIds, display;
1148
1263
  var _c, _d;
1149
1264
  return __generator(this, function (_e) {
1150
1265
  switch (_e.label) {
@@ -1193,7 +1308,8 @@ function executeAiAssistantMongoRead(payload, context) {
1193
1308
  : baseQuery;
1194
1309
  scopedQuery = applyCustomerScopeFilter(clientScopedQuery, collection, customerId, isSuperAdmin);
1195
1310
  normalized = normalizeAssistantFindOptions(input.options);
1196
- return [4 /*yield*/, db.collection(collection).find(scopedQuery, normalized.findOptions).toArray()];
1311
+ findOptions = __assign(__assign({}, normalized.findOptions), { readPreference: AI_ASSISTANT_READ_PREFERENCE });
1312
+ return [4 /*yield*/, db.collection(collection).find(scopedQuery, findOptions).toArray()];
1197
1313
  case 6:
1198
1314
  documents = _e.sent();
1199
1315
  executedQuery = scopedQuery;
@@ -1203,7 +1319,7 @@ function executeAiAssistantMongoRead(payload, context) {
1203
1319
  if (!dateFallback) return [3 /*break*/, 8];
1204
1320
  fallbackQuery = replaceQueryField(scopedQuery, dateFallback.from, dateFallback.to);
1205
1321
  fallbackMeta.dateField = __assign(__assign({}, dateFallback), { attempted: true, used: false });
1206
- return [4 /*yield*/, db.collection(collection).find(fallbackQuery, normalized.findOptions).toArray()];
1322
+ return [4 /*yield*/, db.collection(collection).find(fallbackQuery, findOptions).toArray()];
1207
1323
  case 7:
1208
1324
  fallbackDocs = _e.sent();
1209
1325
  if (fallbackDocs.length) {
@@ -1215,7 +1331,7 @@ function executeAiAssistantMongoRead(payload, context) {
1215
1331
  case 8:
1216
1332
  total = null;
1217
1333
  if (!normalized.includeTotal) return [3 /*break*/, 10];
1218
- return [4 /*yield*/, db.collection(collection).countDocuments(executedQuery)];
1334
+ return [4 /*yield*/, db.collection(collection).countDocuments(executedQuery, { readPreference: AI_ASSISTANT_READ_PREFERENCE })];
1219
1335
  case 9:
1220
1336
  total = _e.sent();
1221
1337
  _e.label = 10;
@@ -1253,7 +1369,7 @@ function executeAiAssistantMongoRead(payload, context) {
1253
1369
  }
1254
1370
  function executeAiAssistantMongoAggregate(payload, context) {
1255
1371
  return __awaiter(this, void 0, void 0, function () {
1256
- var input, rawCollection, dbName, db, collectionResolution, collection, _a, user, isSuperAdmin, customerId, baseQuery, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, dateField, documents, executedPipeline, fallbackMeta, fallback, fallbackPipeline, fallbackDocs, createdFallback, createdPipeline, createdDocs, unwindFallback, fallbackPipeline, fallbackDocs, sanitizedDocuments, includeIds, display;
1372
+ var input, rawCollection, dbName, db, collectionResolution, collection, _a, user, isSuperAdmin, customerId, baseQuery, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, dateField, aggregateOptions, documents, executedPipeline, fallbackMeta, fallback, fallbackPipeline, fallbackDocs, createdFallback, createdPipeline, createdDocs, completionFallback, fallbackPipeline, fallbackDocs, unwindFallback, fallbackPipeline, fallbackDocs, sanitizedDocuments, includeIds, display;
1257
1373
  var _c, _d;
1258
1374
  return __generator(this, function (_e) {
1259
1375
  switch (_e.label) {
@@ -1309,8 +1425,9 @@ function executeAiAssistantMongoAggregate(payload, context) {
1309
1425
  if (containsForbiddenMongoOperators(limitedPipeline)) {
1310
1426
  throw new Error('AI assistant mongo aggregate: Pipeline contains restricted operators.');
1311
1427
  }
1428
+ aggregateOptions = __assign(__assign({}, normalizedOptions.aggregateOptions), { readPreference: AI_ASSISTANT_READ_PREFERENCE });
1312
1429
  return [4 /*yield*/, db.collection(collection)
1313
- .aggregate(limitedPipeline, normalizedOptions.aggregateOptions)
1430
+ .aggregate(limitedPipeline, aggregateOptions)
1314
1431
  .toArray()];
1315
1432
  case 6:
1316
1433
  documents = _e.sent();
@@ -1323,7 +1440,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
1323
1440
  fallbackPipeline = replaceAggregateDateField(limitedPipeline, fallback.from, fallback.to);
1324
1441
  if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 8];
1325
1442
  return [4 /*yield*/, db.collection(collection)
1326
- .aggregate(fallbackPipeline, normalizedOptions.aggregateOptions)
1443
+ .aggregate(fallbackPipeline, aggregateOptions)
1327
1444
  .toArray()];
1328
1445
  case 7:
1329
1446
  fallbackDocs = _e.sent();
@@ -1340,7 +1457,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
1340
1457
  fallbackMeta.dateFieldCreatedAt = createdFallback;
1341
1458
  if (!!containsForbiddenMongoOperators(createdPipeline)) return [3 /*break*/, 10];
1342
1459
  return [4 /*yield*/, db.collection(collection)
1343
- .aggregate(createdPipeline, normalizedOptions.aggregateOptions)
1460
+ .aggregate(createdPipeline, aggregateOptions)
1344
1461
  .toArray()];
1345
1462
  case 9:
1346
1463
  createdDocs = _e.sent();
@@ -1351,24 +1468,48 @@ function executeAiAssistantMongoAggregate(payload, context) {
1351
1468
  }
1352
1469
  _e.label = 10;
1353
1470
  case 10:
1354
- if (!(documents.length <= 1)) return [3 /*break*/, 12];
1471
+ if (!!documents.length) return [3 /*break*/, 12];
1472
+ completionFallback = resolveAggregateCompletionFallback(executedPipeline);
1473
+ if (!completionFallback) return [3 /*break*/, 12];
1474
+ fallbackMeta.completion = {
1475
+ field: completionFallback.field,
1476
+ sources: completionFallback.sources,
1477
+ attempted: true,
1478
+ used: false,
1479
+ statusFilter: !!completionFallback.statusFilter
1480
+ };
1481
+ fallbackPipeline = buildAggregateCompletionFallbackPipeline(executedPipeline, completionFallback);
1482
+ if (!(fallbackPipeline.length && !containsForbiddenMongoOperators(fallbackPipeline))) return [3 /*break*/, 12];
1483
+ return [4 /*yield*/, db.collection(collection)
1484
+ .aggregate(fallbackPipeline, aggregateOptions)
1485
+ .toArray()];
1486
+ case 11:
1487
+ fallbackDocs = _e.sent();
1488
+ if (fallbackDocs.length) {
1489
+ documents = fallbackDocs;
1490
+ executedPipeline = fallbackPipeline;
1491
+ fallbackMeta.completion.used = true;
1492
+ }
1493
+ _e.label = 12;
1494
+ case 12:
1495
+ if (!(documents.length <= 1)) return [3 /*break*/, 14];
1355
1496
  unwindFallback = resolveAggregateUnwindFallback(executedPipeline);
1356
- if (!unwindFallback) return [3 /*break*/, 12];
1497
+ if (!unwindFallback) return [3 /*break*/, 14];
1357
1498
  fallbackMeta.unwind = { path: unwindFallback.path, attempted: true, used: false };
1358
1499
  fallbackPipeline = buildAggregateUnwindFallbackPipeline(executedPipeline, unwindFallback);
1359
- if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 12];
1500
+ if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 14];
1360
1501
  return [4 /*yield*/, db.collection(collection)
1361
- .aggregate(fallbackPipeline, normalizedOptions.aggregateOptions)
1502
+ .aggregate(fallbackPipeline, aggregateOptions)
1362
1503
  .toArray()];
1363
- case 11:
1504
+ case 13:
1364
1505
  fallbackDocs = _e.sent();
1365
1506
  if (fallbackDocs.length > documents.length) {
1366
1507
  documents = fallbackDocs;
1367
1508
  executedPipeline = fallbackPipeline;
1368
1509
  fallbackMeta.unwind.used = true;
1369
1510
  }
1370
- _e.label = 12;
1371
- case 12:
1511
+ _e.label = 14;
1512
+ case 14:
1372
1513
  sanitizedDocuments = isSuperAdmin
1373
1514
  ? documents
1374
1515
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
@@ -1656,7 +1797,7 @@ function deriveAssistantStreamStatus(event) {
1656
1797
  return null;
1657
1798
  }
1658
1799
  if (event.type === 'thread.started' || event.type === 'turn.started') {
1659
- return 'Reviewing request';
1800
+ return 'Planning';
1660
1801
  }
1661
1802
  if (event.type === 'turn.completed') {
1662
1803
  return 'Drafting response';
@@ -1667,13 +1808,13 @@ function deriveAssistantStreamStatus(event) {
1667
1808
  return null;
1668
1809
  }
1669
1810
  if (itemType === 'mcp_tool_call') {
1670
- return 'Calling tool';
1811
+ return 'Grabbing Data';
1671
1812
  }
1672
1813
  if (itemType === 'command_execution') {
1673
- return 'Running command';
1814
+ return 'Grabbing Data';
1674
1815
  }
1675
1816
  if (itemType === 'web_search') {
1676
- return 'Searching references';
1817
+ return 'Planning';
1677
1818
  }
1678
1819
  if (itemType === 'file_change') {
1679
1820
  return 'Drafting response';
@@ -1682,7 +1823,7 @@ function deriveAssistantStreamStatus(event) {
1682
1823
  return 'Drafting response';
1683
1824
  }
1684
1825
  if (itemType === 'reasoning') {
1685
- return 'Analyzing';
1826
+ return 'Planning';
1686
1827
  }
1687
1828
  }
1688
1829
  return null;
@@ -2338,6 +2479,172 @@ function resolveAggregateDateFieldFallback(pipeline) {
2338
2479
  }
2339
2480
  return { from: dateField, to: fallback };
2340
2481
  }
2482
+ function normalizeAggregateFieldList(values) {
2483
+ var seen = new Set();
2484
+ var result = [];
2485
+ values.forEach(function (value) {
2486
+ var normalized = normalizeOptionalString(value);
2487
+ if (!normalized) {
2488
+ return;
2489
+ }
2490
+ if (seen.has(normalized)) {
2491
+ return;
2492
+ }
2493
+ seen.add(normalized);
2494
+ result.push(normalized);
2495
+ });
2496
+ return result;
2497
+ }
2498
+ function isCompletionFieldName(value) {
2499
+ return String(value || '').toLowerCase().includes('complete');
2500
+ }
2501
+ function isDateLikeFieldName(value) {
2502
+ var normalized = String(value || '').toLowerCase();
2503
+ return normalized.includes('date') || normalized.endsWith('_at') || normalized.endsWith('at');
2504
+ }
2505
+ function matchContainsField(value, field) {
2506
+ if (!value || typeof value !== 'object') {
2507
+ return false;
2508
+ }
2509
+ if (Array.isArray(value)) {
2510
+ return value.some(function (entry) { return matchContainsField(entry, field); });
2511
+ }
2512
+ return Object.keys(value).some(function (key) {
2513
+ if (key === field) {
2514
+ return true;
2515
+ }
2516
+ if (key.startsWith('$')) {
2517
+ return matchContainsField(value[key], field);
2518
+ }
2519
+ if (value[key] && typeof value[key] === 'object') {
2520
+ return matchContainsField(value[key], field);
2521
+ }
2522
+ return false;
2523
+ });
2524
+ }
2525
+ function resolveAggregateCompletionFallback(pipeline) {
2526
+ var e_1, _a;
2527
+ if (!Array.isArray(pipeline)) {
2528
+ return null;
2529
+ }
2530
+ var candidateField = '';
2531
+ var candidateSources = [];
2532
+ for (var i = 0; i < pipeline.length; i += 1) {
2533
+ var stage = pipeline[i];
2534
+ if (!stage || typeof stage !== 'object' || !stage.$addFields || typeof stage.$addFields !== 'object') {
2535
+ continue;
2536
+ }
2537
+ var addFields = stage.$addFields;
2538
+ try {
2539
+ for (var _b = (e_1 = void 0, __values(Object.keys(addFields))), _c = _b.next(); !_c.done; _c = _b.next()) {
2540
+ var key = _c.value;
2541
+ if (!isCompletionFieldName(key)) {
2542
+ continue;
2543
+ }
2544
+ var sources = extractExpressionFieldPaths(addFields[key])
2545
+ .filter(function (field) { return isDateLikeFieldName(field); });
2546
+ if (sources.length) {
2547
+ candidateField = key;
2548
+ candidateSources = sources;
2549
+ break;
2550
+ }
2551
+ }
2552
+ }
2553
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2554
+ finally {
2555
+ try {
2556
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2557
+ }
2558
+ finally { if (e_1) throw e_1.error; }
2559
+ }
2560
+ if (candidateField) {
2561
+ break;
2562
+ }
2563
+ }
2564
+ if (!candidateField || !candidateSources.length) {
2565
+ return null;
2566
+ }
2567
+ var matchIndex = -1;
2568
+ var matchCondition = null;
2569
+ var matchStage = null;
2570
+ for (var i = 0; i < pipeline.length; i += 1) {
2571
+ var stage = pipeline[i];
2572
+ if (!stage || typeof stage !== 'object' || !stage.$match || typeof stage.$match !== 'object') {
2573
+ continue;
2574
+ }
2575
+ if (Object.prototype.hasOwnProperty.call(stage.$match, candidateField)) {
2576
+ matchIndex = i;
2577
+ matchCondition = stage.$match[candidateField];
2578
+ matchStage = stage.$match;
2579
+ break;
2580
+ }
2581
+ }
2582
+ if (matchIndex === -1 || !matchStage) {
2583
+ return null;
2584
+ }
2585
+ var normalizedSources = normalizeAggregateFieldList(__spreadArray(__spreadArray([], __read(candidateSources), false), [
2586
+ 'createdAt',
2587
+ 'date_created'
2588
+ ], false));
2589
+ if (!normalizedSources.length) {
2590
+ return null;
2591
+ }
2592
+ var hasStatus = matchContainsField(matchStage, 'status') || matchContainsField(matchStage, 'state');
2593
+ var statusFilter = !hasStatus && isCompletionFieldName(candidateField)
2594
+ ? { $or: [{ status: { $regex: 'complete', $options: 'i' } }, { state: { $regex: 'complete', $options: 'i' } }] }
2595
+ : null;
2596
+ return {
2597
+ matchIndex: matchIndex,
2598
+ field: candidateField,
2599
+ sources: normalizedSources,
2600
+ matchCondition: matchCondition,
2601
+ statusFilter: statusFilter
2602
+ };
2603
+ }
2604
+ function buildAggregateCompletionFallbackPipeline(pipeline, fallback) {
2605
+ var _a;
2606
+ var buildIfNullChain = function (fields) {
2607
+ if (!fields.length) {
2608
+ return null;
2609
+ }
2610
+ var expr = "$".concat(fields[fields.length - 1]);
2611
+ for (var i = fields.length - 2; i >= 0; i -= 1) {
2612
+ expr = { $ifNull: ["$".concat(fields[i]), expr] };
2613
+ }
2614
+ return expr;
2615
+ };
2616
+ var matchStage = (_a = pipeline[fallback.matchIndex]) === null || _a === void 0 ? void 0 : _a.$match;
2617
+ if (!matchStage || typeof matchStage !== 'object') {
2618
+ return pipeline;
2619
+ }
2620
+ var orConditions = fallback.sources.map(function (field) {
2621
+ var _a;
2622
+ return (_a = {}, _a[field] = fallback.matchCondition, _a);
2623
+ });
2624
+ var nextMatch = __assign({}, matchStage);
2625
+ delete nextMatch[fallback.field];
2626
+ var andParts = [];
2627
+ if (Object.keys(nextMatch).length) {
2628
+ andParts.push(nextMatch);
2629
+ }
2630
+ andParts.push({ $or: orConditions });
2631
+ if (fallback.statusFilter) {
2632
+ andParts.push(fallback.statusFilter);
2633
+ }
2634
+ var mergedMatch = andParts.length === 1 ? andParts[0] : { $and: andParts };
2635
+ return pipeline.map(function (stage, index) {
2636
+ var _a;
2637
+ if (index === fallback.matchIndex) {
2638
+ return { $match: mergedMatch };
2639
+ }
2640
+ if (stage && typeof stage === 'object' && stage.$addFields && typeof stage.$addFields === 'object') {
2641
+ if (Object.prototype.hasOwnProperty.call(stage.$addFields, fallback.field)) {
2642
+ return __assign(__assign({}, stage), { $addFields: __assign(__assign({}, stage.$addFields), (_a = {}, _a[fallback.field] = buildIfNullChain(fallback.sources), _a)) });
2643
+ }
2644
+ }
2645
+ return stage;
2646
+ });
2647
+ }
2341
2648
  function resolveAggregateUnwindFallback(pipeline) {
2342
2649
  var groupIndex = findAggregateGroupIndex(pipeline);
2343
2650
  if (groupIndex === -1) {
@@ -2746,7 +3053,7 @@ function resolveAssistantCollectionHints(message, dbName, db) {
2746
3053
  });
2747
3054
  }
2748
3055
  function findQueryDateField(query) {
2749
- var e_1, _a, e_2, _b;
3056
+ var e_2, _a, e_3, _b;
2750
3057
  if (!query || typeof query !== 'object') {
2751
3058
  return null;
2752
3059
  }
@@ -2760,12 +3067,12 @@ function findQueryDateField(query) {
2760
3067
  }
2761
3068
  }
2762
3069
  }
2763
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
3070
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
2764
3071
  finally {
2765
3072
  try {
2766
3073
  if (query_1_1 && !query_1_1.done && (_a = query_1.return)) _a.call(query_1);
2767
3074
  }
2768
- finally { if (e_1) throw e_1.error; }
3075
+ finally { if (e_2) throw e_2.error; }
2769
3076
  }
2770
3077
  return null;
2771
3078
  }
@@ -2784,12 +3091,12 @@ function findQueryDateField(query) {
2784
3091
  }
2785
3092
  }
2786
3093
  }
2787
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
3094
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
2788
3095
  finally {
2789
3096
  try {
2790
3097
  if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
2791
3098
  }
2792
- finally { if (e_2) throw e_2.error; }
3099
+ finally { if (e_3) throw e_3.error; }
2793
3100
  }
2794
3101
  return null;
2795
3102
  }
@@ -2819,7 +3126,7 @@ function resolveQueryDateFieldFallback(query) {
2819
3126
  return { from: dateField, to: fallback };
2820
3127
  }
2821
3128
  function containsForbiddenMongoOperators(value) {
2822
- var e_3, _a;
3129
+ var e_4, _a;
2823
3130
  if (!value || typeof value !== 'object') {
2824
3131
  return false;
2825
3132
  }
@@ -2838,12 +3145,12 @@ function containsForbiddenMongoOperators(value) {
2838
3145
  }
2839
3146
  }
2840
3147
  }
2841
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
3148
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
2842
3149
  finally {
2843
3150
  try {
2844
3151
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2845
3152
  }
2846
- finally { if (e_3) throw e_3.error; }
3153
+ finally { if (e_4) throw e_4.error; }
2847
3154
  }
2848
3155
  return false;
2849
3156
  }
@@ -3077,8 +3384,8 @@ function applyCodexStreamStatusHandler(runOptions, streamStatusHandler) {
3077
3384
  }
3078
3385
  function waitForCodexWorkerMessage(worker, streamStatusHandler) {
3079
3386
  return __awaiter(this, void 0, void 0, function () {
3080
- var _a, _b, _c, _d, message, payload, status_1, e_4_1;
3081
- var _e, e_4, _f, _g;
3387
+ var _a, _b, _c, _d, message, payload, status_1, e_5_1;
3388
+ var _e, e_5, _f, _g;
3082
3389
  return __generator(this, function (_h) {
3083
3390
  switch (_h.label) {
3084
3391
  case 0:
@@ -3105,8 +3412,8 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
3105
3412
  return [3 /*break*/, 1];
3106
3413
  case 4: return [3 /*break*/, 11];
3107
3414
  case 5:
3108
- e_4_1 = _h.sent();
3109
- e_4 = { error: e_4_1 };
3415
+ e_5_1 = _h.sent();
3416
+ e_5 = { error: e_5_1 };
3110
3417
  return [3 /*break*/, 11];
3111
3418
  case 6:
3112
3419
  _h.trys.push([6, , 9, 10]);
@@ -3117,7 +3424,7 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
3117
3424
  _h.label = 8;
3118
3425
  case 8: return [3 /*break*/, 10];
3119
3426
  case 9:
3120
- if (e_4) throw e_4.error;
3427
+ if (e_5) throw e_5.error;
3121
3428
  return [7 /*endfinally*/];
3122
3429
  case 10: return [7 /*endfinally*/];
3123
3430
  case 11: throw new CodexWorkerBootstrapError('Codex worker exited before completing.');
@@ -3127,7 +3434,7 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
3127
3434
  }
3128
3435
  function runCodexInWorkerThread(prompt, runOptions, config, streamStatusHandler) {
3129
3436
  return __awaiter(this, void 0, void 0, function () {
3130
- var streamedOptions, codexClient, workerPath, codexClient, error_3, codexClient;
3437
+ var streamedOptions, codexClient, workerPath, codexClient, error_4, codexClient;
3131
3438
  return __generator(this, function (_a) {
3132
3439
  switch (_a.label) {
3133
3440
  case 0:
@@ -3148,11 +3455,11 @@ function runCodexInWorkerThread(prompt, runOptions, config, streamStatusHandler)
3148
3455
  return [4 /*yield*/, runCodexInWorkerThreadInternal(workerPath, prompt, runOptions, config, streamStatusHandler)];
3149
3456
  case 6: return [2 /*return*/, _a.sent()];
3150
3457
  case 7:
3151
- error_3 = _a.sent();
3152
- if (!(error_3 instanceof CodexWorkerBootstrapError)) {
3153
- throw error_3;
3458
+ error_4 = _a.sent();
3459
+ if (!(error_4 instanceof CodexWorkerBootstrapError)) {
3460
+ throw error_4;
3154
3461
  }
3155
- console.error('Codex worker bootstrap failed, falling back to in-process run.', error_3);
3462
+ console.error('Codex worker bootstrap failed, falling back to in-process run.', error_4);
3156
3463
  codexClient = getAssistantCodexClient();
3157
3464
  return [4 /*yield*/, codexClient.run(prompt, streamedOptions)];
3158
3465
  case 8: return [2 /*return*/, _a.sent()];
@@ -3190,7 +3497,7 @@ function runCodexInWorkerThreadInternal(workerPath, prompt, runOptions, config,
3190
3497
  timeoutMs = ((sanitizedOptions === null || sanitizedOptions === void 0 ? void 0 : sanitizedOptions.timeoutMs) || resolveCodexTimeoutMs()) + 15000;
3191
3498
  timeoutController = new AbortController();
3192
3499
  timeoutPromise = (function () { return __awaiter(_this, void 0, void 0, function () {
3193
- var error_4;
3500
+ var error_5;
3194
3501
  return __generator(this, function (_a) {
3195
3502
  switch (_a.label) {
3196
3503
  case 0:
@@ -3200,11 +3507,11 @@ function runCodexInWorkerThreadInternal(workerPath, prompt, runOptions, config,
3200
3507
  _a.sent();
3201
3508
  return [2 /*return*/, { type: 'timeout' }];
3202
3509
  case 2:
3203
- error_4 = _a.sent();
3204
- if ((error_4 === null || error_4 === void 0 ? void 0 : error_4.name) === 'AbortError') {
3510
+ error_5 = _a.sent();
3511
+ if ((error_5 === null || error_5 === void 0 ? void 0 : error_5.name) === 'AbortError') {
3205
3512
  return [2 /*return*/, { type: 'aborted' }];
3206
3513
  }
3207
- throw error_4;
3514
+ throw error_5;
3208
3515
  case 3: return [2 /*return*/];
3209
3516
  }
3210
3517
  });
@@ -3499,7 +3806,7 @@ function normalizeRouteMatchKey(value) {
3499
3806
  return normalizeRouteKey(value).toLowerCase();
3500
3807
  }
3501
3808
  function buildClientRouteIndex() {
3502
- var e_5, _a;
3809
+ var e_6, _a;
3503
3810
  var _b;
3504
3811
  var routes = ((_b = resolveio_server_app_1.ResolveIOServer.getClientRoutes) === null || _b === void 0 ? void 0 : _b.call(resolveio_server_app_1.ResolveIOServer)) || [];
3505
3812
  var set = new Set();
@@ -3518,12 +3825,12 @@ function buildClientRouteIndex() {
3518
3825
  }
3519
3826
  }
3520
3827
  }
3521
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
3828
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
3522
3829
  finally {
3523
3830
  try {
3524
3831
  if (routes_1_1 && !routes_1_1.done && (_a = routes_1.return)) _a.call(routes_1);
3525
3832
  }
3526
- finally { if (e_5) throw e_5.error; }
3833
+ finally { if (e_6) throw e_6.error; }
3527
3834
  }
3528
3835
  return { set: set, map: map, size: routes.length };
3529
3836
  }
@@ -3649,7 +3956,7 @@ function sanitizeAssistantResponse(value) {
3649
3956
  return normalizeAssistantRoutes(normalizedCurrency);
3650
3957
  }
3651
3958
  function evaluateAssistantGuardrails(message) {
3652
- var e_6, _a;
3959
+ var e_7, _a;
3653
3960
  var normalized = String(message || '').toLowerCase();
3654
3961
  var patterns = [
3655
3962
  {
@@ -3695,12 +4002,12 @@ function evaluateAssistantGuardrails(message) {
3695
4002
  }
3696
4003
  }
3697
4004
  }
3698
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
4005
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
3699
4006
  finally {
3700
4007
  try {
3701
4008
  if (patterns_1_1 && !patterns_1_1.done && (_a = patterns_1.return)) _a.call(patterns_1);
3702
4009
  }
3703
- finally { if (e_6) throw e_6.error; }
4010
+ finally { if (e_7) throw e_7.error; }
3704
4011
  }
3705
4012
  return null;
3706
4013
  }
@@ -3864,8 +4171,8 @@ function handleCodexUpload(id_conversation, file_name, content_base64, size, con
3864
4171
  }
3865
4172
  function readAttachmentContents(attachments) {
3866
4173
  return __awaiter(this, void 0, void 0, function () {
3867
- var limits, totalBytes, totalChars, chunks, cleaned, attachments_1, attachments_1_1, attachment, localPath, safe, stat, ext, name_1, type, readable, content, _a, e_7_1;
3868
- var e_7, _b;
4174
+ var limits, totalBytes, totalChars, chunks, cleaned, attachments_1, attachments_1_1, attachment, localPath, safe, stat, ext, name_1, type, readable, content, _a, e_8_1;
4175
+ var e_8, _b;
3869
4176
  return __generator(this, function (_c) {
3870
4177
  switch (_c.label) {
3871
4178
  case 0:
@@ -3944,14 +4251,14 @@ function readAttachmentContents(attachments) {
3944
4251
  return [3 /*break*/, 2];
3945
4252
  case 10: return [3 /*break*/, 13];
3946
4253
  case 11:
3947
- e_7_1 = _c.sent();
3948
- e_7 = { error: e_7_1 };
4254
+ e_8_1 = _c.sent();
4255
+ e_8 = { error: e_8_1 };
3949
4256
  return [3 /*break*/, 13];
3950
4257
  case 12:
3951
4258
  try {
3952
4259
  if (attachments_1_1 && !attachments_1_1.done && (_b = attachments_1.return)) _b.call(attachments_1);
3953
4260
  }
3954
- finally { if (e_7) throw e_7.error; }
4261
+ finally { if (e_8) throw e_8.error; }
3955
4262
  return [7 /*endfinally*/];
3956
4263
  case 13: return [2 /*return*/, {
3957
4264
  promptText: chunks.length ? "\n\nAttachments:\n".concat(chunks.join('\n\n')) : '',
@@ -4128,7 +4435,7 @@ function estimateUsage(messages, responseText, model) {
4128
4435
  };
4129
4436
  }
4130
4437
  function evaluateGuardrails(message) {
4131
- var e_8, _a;
4438
+ var e_9, _a;
4132
4439
  var normalized = String(message || '').toLowerCase();
4133
4440
  var patterns = [
4134
4441
  { 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.' },
@@ -4150,12 +4457,12 @@ function evaluateGuardrails(message) {
4150
4457
  }
4151
4458
  }
4152
4459
  }
4153
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
4460
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
4154
4461
  finally {
4155
4462
  try {
4156
4463
  if (patterns_2_1 && !patterns_2_1.done && (_a = patterns_2.return)) _a.call(patterns_2);
4157
4464
  }
4158
- finally { if (e_8) throw e_8.error; }
4465
+ finally { if (e_9) throw e_9.error; }
4159
4466
  }
4160
4467
  return null;
4161
4468
  }