@resolveio/server-lib 20.15.3 → 20.15.4

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.
@@ -133,7 +133,7 @@ var DEFAULT_MAX_FILE_MB = 50;
133
133
  var DEFAULT_MAX_TOTAL_MB = 100;
134
134
  var DEFAULT_MAX_ATTACHMENT_CHARS = 12000;
135
135
  var DEFAULT_MAX_TOTAL_ATTACHMENT_CHARS = 40000;
136
- var DEFAULT_CODEX_MODEL = 'gpt-5.2-codex';
136
+ var DEFAULT_CODEX_MODEL = 'gpt-5.1-codex-mini';
137
137
  var DEFAULT_CODEX_TIMEOUT_MS = 180000;
138
138
  var AI_ASSISTANT_MONGO_DEFAULT_LIMIT = 20;
139
139
  var AI_ASSISTANT_MONGO_MAX_LIMIT = 200;
@@ -199,6 +199,51 @@ var AI_ASSISTANT_SENSITIVE_FIELDS = [
199
199
  'roles'
200
200
  ];
201
201
  var AI_ASSISTANT_CLIENT_SCOPE_CACHE = new Map();
202
+ var AI_ASSISTANT_COLLECTION_CACHE = new Map();
203
+ var AI_ASSISTANT_COLLECTION_CACHE_TTL_MS = 5 * 60 * 1000;
204
+ var AI_ASSISTANT_COLLECTION_STOPWORDS = new Set([
205
+ 'the',
206
+ 'a',
207
+ 'an',
208
+ 'of',
209
+ 'for',
210
+ 'by',
211
+ 'with',
212
+ 'and',
213
+ 'or',
214
+ 'to',
215
+ 'from',
216
+ 'in',
217
+ 'on',
218
+ 'at',
219
+ 'last',
220
+ 'recent',
221
+ 'today',
222
+ 'week',
223
+ 'month',
224
+ 'year',
225
+ 'this',
226
+ 'that',
227
+ 'these',
228
+ 'those',
229
+ 'show',
230
+ 'list',
231
+ 'get',
232
+ 'give',
233
+ 'how',
234
+ 'many',
235
+ 'count',
236
+ 'total',
237
+ 'breakdown',
238
+ 'group',
239
+ 'grouped',
240
+ 'per',
241
+ 'open',
242
+ 'closed',
243
+ 'completed',
244
+ 'missing',
245
+ 'overdue'
246
+ ]);
202
247
  var AI_ASSISTANT_SYSTEM_PROMPT = [
203
248
  'You are the ResolveIO in-app AI assistant running with read-only access to the codebase.',
204
249
  'Core rules:',
@@ -209,11 +254,16 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
209
254
  '- If the user has a customer portal scope (other.id_customer), only discuss that customer\'s data and what is visible in their customer portal. Never reference other customers or internal/admin-only data. If asked for anything outside the portal, say it isn\'t available.',
210
255
  '- Do not assist with hacking, bypassing security, or abuse.',
211
256
  'Accuracy & tools:',
257
+ '- 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.',
258
+ '- Map user wording to internal collections/fields yourself. Do not ask for property names unless required to run a query.',
212
259
  '- 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.',
213
260
  '- Prefer running a small Mongo read over asking multiple questions.',
261
+ '- For any data request (counts, lists, breakdowns, recent/last items), you MUST run a MONGO_READ or MONGO_AGG before answering.',
214
262
  '- Ask at most one clarifying question only when required to run a query or resolve missing details.',
215
263
  '- 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
+ '- 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.',
216
265
  '- Use the codebase context to choose correct collections/fields/workflows and use MONGO_READ/MONGO_AGG to answer with real data when needed.',
266
+ '- Assume a relevant collection exists; if verification reads return zero data, report no data found instead of interrogating the user.',
217
267
  '- For direct questions, answer first. Ask a single follow-up only if required to proceed.',
218
268
  'Data Presentation:',
219
269
  '- Output plain Markdown (NO triple backticks).',
@@ -224,6 +274,7 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
224
274
  '- If `_id` & `__v` & `id_<other collection _id property>` is needed, show it as `id` and shorten (e.g., first 6-8 chars) unless asked otherwise.',
225
275
  '- Rename `createdAt` to `Created At` and `updatedAt` to `Updated At` in tables.',
226
276
  'Response style:',
277
+ '- Respond in English only. Do not include non-English text or characters unless required for JSON, links, or tool directives.',
227
278
  '- Keep responses concise: answer first, then 3-8 bullets, then a table when data is involved.',
228
279
  '- Prefer high-level explanations and point to routes instead of code. Only mention file paths if explicitly requested.',
229
280
  '- When asked where to do something, give the exact screen name and the in-app route as a standalone path starting with "/" so it can be clicked.',
@@ -261,7 +312,8 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
261
312
  '- When grouping by fields that can be arrays (drivers, deliveries, routes, chemicals), $unwind first and group by both id and name when available.',
262
313
  '- Use MONGO_READ/MONGO_AGG only to produce summaries/snapshots/health checks (not raw dumps) when permitted.',
263
314
  '- If the user explicitly asks for IDs, set options.includeIds: true.',
264
- '- Keep responses concise and use low reasoning effort.'
315
+ '- If a data question returns zero results, verify the collection/date field with a tiny read (limit 1-5) or a date field fallback before concluding there is no data.',
316
+ '- Keep responses concise and use the configured reasoning effort level (default low).'
265
317
  ].join('\n');
266
318
  var AI_FORM_PATCH_SYSTEM_PROMPT = [
267
319
  'You are the ResolveIO form patch assistant.',
@@ -800,10 +852,10 @@ function executeAiFormPatch(payload, context) {
800
852
  }
801
853
  function executeAiAssistantCodexRun(payload, context) {
802
854
  return __awaiter(this, void 0, void 0, function () {
803
- var input, message, requestId, guardrail, conversation_2, now_2, userMsg, assistantMsg, user, isSuperAdmin, hasInvoiceAccess, customerId, conversation, now, attachments, attachmentData, historyLimit, history, _a, historyLines, assistantContext, prompt, workspaceRoot, codexConfig, runOptions, userDoc, initialProgress, assistantDoc, insertResult, assistantMessageId, progressTracker, streamProgress, assistantContent, toolResult, responseText, directive, cleanedResponseText, toolRequest, toolResponse, _b, toolPayload, followupPrompt, followupText, _c, error_1, error_2, finalNow, finalMetadata, finalAssistantDoc;
804
- var _d, _e;
805
- return __generator(this, function (_f) {
806
- switch (_f.label) {
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) {
807
859
  case 0:
808
860
  input = payload || {};
809
861
  message = normalizeOptionalString(input.message);
@@ -818,7 +870,7 @@ function executeAiAssistantCodexRun(payload, context) {
818
870
  if (!(guardrail === null || guardrail === void 0 ? void 0 : guardrail.blocked)) return [3 /*break*/, 5];
819
871
  return [4 /*yield*/, ensureConversation(input, 'codex')];
820
872
  case 1:
821
- conversation_2 = _f.sent();
873
+ conversation_2 = _j.sent();
822
874
  now_2 = new Date();
823
875
  userMsg = {
824
876
  id_conversation: conversation_2._id,
@@ -838,13 +890,13 @@ function executeAiAssistantCodexRun(payload, context) {
838
890
  };
839
891
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(userMsg)];
840
892
  case 2:
841
- _f.sent();
893
+ _j.sent();
842
894
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(assistantMsg)];
843
895
  case 3:
844
- _f.sent();
896
+ _j.sent();
845
897
  return [4 /*yield*/, touchConversation(conversation_2._id, now_2)];
846
898
  case 4:
847
- _f.sent();
899
+ _j.sent();
848
900
  return [2 /*return*/, {
849
901
  conversation: conversation_2,
850
902
  message: assistantMsg,
@@ -852,27 +904,27 @@ function executeAiAssistantCodexRun(payload, context) {
852
904
  }];
853
905
  case 5: return [4 /*yield*/, user_collection_1.Users.findById(context === null || context === void 0 ? void 0 : context.id_user)];
854
906
  case 6:
855
- user = _f.sent();
856
- isSuperAdmin = !!((_d = user === null || user === void 0 ? void 0 : user.roles) === null || _d === void 0 ? void 0 : _d.super_admin);
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);
857
909
  hasInvoiceAccess = userHasInvoiceAccess(user);
858
- customerId = normalizeOptionalString((_e = user === null || user === void 0 ? void 0 : user.other) === null || _e === void 0 ? void 0 : _e.id_customer);
910
+ customerId = normalizeOptionalString((_g = user === null || user === void 0 ? void 0 : user.other) === null || _g === void 0 ? void 0 : _g.id_customer);
859
911
  return [4 /*yield*/, ensureConversation(input, 'codex')];
860
912
  case 7:
861
- conversation = _f.sent();
913
+ conversation = _j.sent();
862
914
  now = new Date();
863
915
  attachments = Array.isArray(input.attachments) ? input.attachments : [];
864
916
  return [4 /*yield*/, readAttachmentContents(attachments)];
865
917
  case 8:
866
- attachmentData = _f.sent();
918
+ attachmentData = _j.sent();
867
919
  historyLimit = normalizeHistoryLimit(input.max_history);
868
920
  if (!(historyLimit > 0)) return [3 /*break*/, 10];
869
921
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.find({ id_conversation: conversation._id, role: { $in: ['user', 'assistant'] } }, { sort: { createdAt: 1 }, limit: historyLimit * 2 })];
870
922
  case 9:
871
- _a = _f.sent();
923
+ _a = _j.sent();
872
924
  return [3 /*break*/, 11];
873
925
  case 10:
874
926
  _a = [];
875
- _f.label = 11;
927
+ _j.label = 11;
876
928
  case 11:
877
929
  history = _a;
878
930
  historyLines = [];
@@ -883,11 +935,35 @@ function executeAiAssistantCodexRun(payload, context) {
883
935
  historyLines.push("".concat(role, ": ").concat(content));
884
936
  }
885
937
  });
886
- assistantContext = buildAssistantContext(input, { isSuperAdmin: isSuperAdmin, hasInvoiceAccess: hasInvoiceAccess, customerId: customerId });
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
+ });
887
963
  prompt = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext);
888
964
  return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
889
- case 12:
890
- workspaceRoot = _f.sent();
965
+ case 16:
966
+ workspaceRoot = _j.sent();
891
967
  codexConfig = resolveCodexSettings();
892
968
  runOptions = {
893
969
  timeoutMs: resolveCodexTimeoutMs(),
@@ -895,7 +971,7 @@ function executeAiAssistantCodexRun(payload, context) {
895
971
  workingDirectory: workspaceRoot,
896
972
  sandboxMode: 'read-only',
897
973
  skipGitRepoCheck: true,
898
- modelReasoningEffort: 'low',
974
+ modelReasoningEffort: resolveCodexThoughtLevel(),
899
975
  networkAccessEnabled: false,
900
976
  webSearchMode: 'disabled',
901
977
  webSearchEnabled: false,
@@ -921,83 +997,128 @@ function executeAiAssistantCodexRun(payload, context) {
921
997
  updatedAt: now
922
998
  };
923
999
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(userDoc)];
924
- case 13:
925
- _f.sent();
1000
+ case 17:
1001
+ _j.sent();
926
1002
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(assistantDoc)];
927
- case 14:
928
- insertResult = _f.sent();
1003
+ case 18:
1004
+ insertResult = _j.sent();
929
1005
  assistantMessageId = (insertResult === null || insertResult === void 0 ? void 0 : insertResult._id) || (insertResult === null || insertResult === void 0 ? void 0 : insertResult.insertedId);
930
1006
  progressTracker = createAssistantProgressTracker(assistantMessageId, initialProgress);
931
1007
  streamProgress = createAssistantStreamProgressHandler(progressTracker);
932
1008
  assistantContent = '';
933
1009
  toolResult = null;
934
- _f.label = 15;
935
- case 15:
936
- _f.trys.push([15, 30, 31, 32]);
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]);
937
1019
  return [4 /*yield*/, runCodexInWorkerThread(prompt, runOptions, codexConfig, streamProgress)];
938
- case 16:
939
- responseText = _f.sent();
1020
+ case 20:
1021
+ responseText = _j.sent();
940
1022
  directive = extractAssistantMongoDirective(responseText);
941
- cleanedResponseText = (directive === null || directive === void 0 ? void 0 : directive.cleaned) || 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;
942
1049
  assistantContent = sanitizeAssistantResponse(cleanedResponseText);
943
- if (!((directive === null || directive === void 0 ? void 0 : directive.payload) && AI_ASSISTANT_TOOL_MAX_STEPS > 0)) return [3 /*break*/, 28];
1050
+ if (!((directive === null || directive === void 0 ? void 0 : directive.payload) && AI_ASSISTANT_TOOL_MAX_STEPS > 0)) return [3 /*break*/, 36];
944
1051
  toolRequest = buildAssistantToolRequest(directive, input);
945
1052
  progressTracker.push('Looking up Data');
946
- _f.label = 17;
947
- case 17:
948
- _f.trys.push([17, 26, , 27]);
949
- if (!(directive.type === 'aggregate')) return [3 /*break*/, 19];
1053
+ _j.label = 25;
1054
+ case 25:
1055
+ _j.trys.push([25, 34, , 35]);
1056
+ if (!(directive.type === 'aggregate')) return [3 /*break*/, 27];
950
1057
  return [4 /*yield*/, executeAiAssistantMongoAggregate(toolRequest, context)];
951
- case 18:
952
- _b = _f.sent();
953
- return [3 /*break*/, 21];
954
- case 19: return [4 /*yield*/, executeAiAssistantMongoRead(toolRequest, context)];
955
- case 20:
956
- _b = _f.sent();
957
- _f.label = 21;
958
- case 21:
959
- toolResponse = _b;
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;
960
1070
  toolPayload = buildAssistantToolResultPayload(directive, toolResponse);
961
1071
  toolResult = toolPayload.result;
962
1072
  progressTracker.push('Drafting response');
963
1073
  followupPrompt = buildAssistantCodexToolFollowupPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, toolPayload.prompt);
964
- _f.label = 22;
965
- case 22:
966
- _f.trys.push([22, 24, , 25]);
1074
+ _j.label = 30;
1075
+ case 30:
1076
+ _j.trys.push([30, 32, , 33]);
967
1077
  return [4 /*yield*/, runCodexInWorkerThread(followupPrompt, runOptions, codexConfig, streamProgress)];
968
- case 23:
969
- followupText = _f.sent();
1078
+ case 31:
1079
+ followupText = _j.sent();
970
1080
  assistantContent = sanitizeAssistantResponse(followupText);
971
- return [3 /*break*/, 25];
972
- case 24:
973
- _c = _f.sent();
1081
+ return [3 /*break*/, 33];
1082
+ case 32:
1083
+ _e = _j.sent();
974
1084
  assistantContent = buildAssistantToolFallbackResponse(toolPayload.result);
975
- return [3 /*break*/, 25];
976
- case 25: return [3 /*break*/, 27];
977
- case 26:
978
- error_1 = _f.sent();
1085
+ return [3 /*break*/, 33];
1086
+ case 33: return [3 /*break*/, 35];
1087
+ case 34:
1088
+ error_1 = _j.sent();
979
1089
  assistantContent = buildAssistantToolErrorMessage(error_1, directive, toolRequest);
980
- return [3 /*break*/, 27];
981
- case 27: return [3 /*break*/, 29];
982
- case 28:
1090
+ toolError = error_1;
1091
+ return [3 /*break*/, 35];
1092
+ case 35: return [3 /*break*/, 37];
1093
+ case 36:
983
1094
  progressTracker.push('Drafting response');
984
- _f.label = 29;
985
- case 29: return [3 /*break*/, 32];
986
- case 30:
987
- error_2 = _f.sent();
1095
+ _j.label = 37;
1096
+ case 37: return [3 /*break*/, 40];
1097
+ case 38:
1098
+ error_2 = _j.sent();
988
1099
  assistantContent = buildAssistantCodexErrorMessage(error_2);
989
- return [3 /*break*/, 32];
990
- case 31:
1100
+ return [3 /*break*/, 40];
1101
+ case 39:
991
1102
  progressTracker.stop();
992
1103
  return [7 /*endfinally*/];
993
- case 32:
1104
+ case 40:
994
1105
  if (!assistantContent) {
995
1106
  assistantContent = buildAssistantCodexErrorMessage(null);
996
1107
  }
997
1108
  finalNow = new Date();
998
- finalMetadata = __assign(__assign({ model: resolveCodexModel() }, (requestId ? { request_id: requestId } : {})), (toolResult ? { tool_result: toolResult } : {}));
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 } : {}));
999
1120
  finalAssistantDoc = __assign(__assign({}, assistantDoc), { _id: assistantMessageId, content: assistantContent, metadata: finalMetadata, updatedAt: finalNow });
1000
- if (!assistantMessageId) return [3 /*break*/, 34];
1121
+ if (!assistantMessageId) return [3 /*break*/, 42];
1001
1122
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.updateOne({ _id: assistantMessageId }, {
1002
1123
  $set: {
1003
1124
  content: assistantContent,
@@ -1005,43 +1126,47 @@ function executeAiAssistantCodexRun(payload, context) {
1005
1126
  updatedAt: finalNow
1006
1127
  }
1007
1128
  })];
1008
- case 33:
1009
- _f.sent();
1010
- _f.label = 34;
1011
- case 34: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
1012
- case 35:
1013
- _f.sent();
1014
- if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 37];
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];
1015
1136
  return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
1016
- case 36:
1017
- _f.sent();
1018
- _f.label = 37;
1019
- case 37: return [2 /*return*/, __assign({ conversation: conversation, message: finalAssistantDoc }, (toolResult ? { tool_result: toolResult } : {}))];
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 } : {}))];
1020
1141
  }
1021
1142
  });
1022
1143
  });
1023
1144
  }
1024
1145
  function executeAiAssistantMongoRead(payload, context) {
1025
1146
  return __awaiter(this, void 0, void 0, function () {
1026
- var input, collection, _a, user, isSuperAdmin, customerId, dbName, db, baseQuery, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalized, documents, total, sanitizedDocuments, includeIds, display;
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;
1027
1148
  var _c, _d;
1028
1149
  return __generator(this, function (_e) {
1029
1150
  switch (_e.label) {
1030
1151
  case 0:
1031
1152
  input = payload || {};
1032
- collection = normalizeOptionalString(input.collection);
1033
- if (!collection) {
1153
+ rawCollection = normalizeOptionalString(input.collection);
1154
+ if (!rawCollection) {
1034
1155
  throw new Error('AI assistant mongo read: Collection is required.');
1035
1156
  }
1036
- return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
1157
+ dbName = resolveAssistantDatabaseName(input.database, input.mongo);
1158
+ db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1159
+ return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
1037
1160
  case 1:
1161
+ collectionResolution = _e.sent();
1162
+ collection = collectionResolution.name || rawCollection;
1163
+ return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
1164
+ case 2:
1038
1165
  _a = _e.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1039
1166
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
1040
1167
  throw new Error('AI assistant mongo read: Access denied.');
1041
1168
  }
1042
1169
  customerId = normalizeOptionalString((_c = user === null || user === void 0 ? void 0 : user.other) === null || _c === void 0 ? void 0 : _c.id_customer);
1043
- dbName = resolveAssistantDatabaseName(input.database, input.mongo);
1044
- db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1045
1170
  baseQuery = normalizeMongoQuery(input.query);
1046
1171
  if (!isSuperAdmin && (collection === 'users' || collection === 'user-versions')) {
1047
1172
  userId = normalizeOptionalString(user === null || user === void 0 ? void 0 : user._id);
@@ -1053,15 +1178,15 @@ function executeAiAssistantMongoRead(payload, context) {
1053
1178
  };
1054
1179
  }
1055
1180
  normalizedClient = normalizeOptionalString(input.id_client);
1056
- if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 3];
1181
+ if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 4];
1057
1182
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
1058
- case 2:
1059
- _b = _e.sent();
1060
- return [3 /*break*/, 4];
1061
1183
  case 3:
1062
- _b = false;
1063
- _e.label = 4;
1184
+ _b = _e.sent();
1185
+ return [3 /*break*/, 5];
1064
1186
  case 4:
1187
+ _b = false;
1188
+ _e.label = 5;
1189
+ case 5:
1065
1190
  shouldScopeByClient = _b;
1066
1191
  clientScopedQuery = shouldScopeByClient
1067
1192
  ? applyClientScopeFilter(baseQuery, normalizedClient, isSuperAdmin)
@@ -1069,15 +1194,32 @@ function executeAiAssistantMongoRead(payload, context) {
1069
1194
  scopedQuery = applyCustomerScopeFilter(clientScopedQuery, collection, customerId, isSuperAdmin);
1070
1195
  normalized = normalizeAssistantFindOptions(input.options);
1071
1196
  return [4 /*yield*/, db.collection(collection).find(scopedQuery, normalized.findOptions).toArray()];
1072
- case 5:
1197
+ case 6:
1073
1198
  documents = _e.sent();
1199
+ executedQuery = scopedQuery;
1200
+ fallbackMeta = {};
1201
+ if (!!documents.length) return [3 /*break*/, 8];
1202
+ dateFallback = resolveQueryDateFieldFallback(scopedQuery);
1203
+ if (!dateFallback) return [3 /*break*/, 8];
1204
+ fallbackQuery = replaceQueryField(scopedQuery, dateFallback.from, dateFallback.to);
1205
+ fallbackMeta.dateField = __assign(__assign({}, dateFallback), { attempted: true, used: false });
1206
+ return [4 /*yield*/, db.collection(collection).find(fallbackQuery, normalized.findOptions).toArray()];
1207
+ case 7:
1208
+ fallbackDocs = _e.sent();
1209
+ if (fallbackDocs.length) {
1210
+ documents = fallbackDocs;
1211
+ executedQuery = fallbackQuery;
1212
+ fallbackMeta.dateField.used = true;
1213
+ }
1214
+ _e.label = 8;
1215
+ case 8:
1074
1216
  total = null;
1075
- if (!normalized.includeTotal) return [3 /*break*/, 7];
1076
- return [4 /*yield*/, db.collection(collection).countDocuments(scopedQuery)];
1077
- case 6:
1217
+ if (!normalized.includeTotal) return [3 /*break*/, 10];
1218
+ return [4 /*yield*/, db.collection(collection).countDocuments(executedQuery)];
1219
+ case 9:
1078
1220
  total = _e.sent();
1079
- _e.label = 7;
1080
- case 7:
1221
+ _e.label = 10;
1222
+ case 10:
1081
1223
  sanitizedDocuments = isSuperAdmin
1082
1224
  ? documents
1083
1225
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
@@ -1093,10 +1235,16 @@ function executeAiAssistantMongoRead(payload, context) {
1093
1235
  return [2 /*return*/, __assign({ documents: sanitizedDocuments, total: total, display: display }, (isSuperAdmin ? {
1094
1236
  debug: {
1095
1237
  collection: collection,
1238
+ collectionRequested: rawCollection,
1239
+ collectionResolved: collection,
1240
+ collectionMatched: collectionResolution.matched,
1241
+ collectionCandidates: collectionResolution.candidates,
1242
+ collectionScore: collectionResolution.score,
1096
1243
  database: dbName,
1097
- query: scopedQuery,
1244
+ query: executedQuery,
1098
1245
  options: normalized.findOptions,
1099
- includeTotal: normalized.includeTotal
1246
+ includeTotal: normalized.includeTotal,
1247
+ fallbacks: fallbackMeta
1100
1248
  }
1101
1249
  } : {}))];
1102
1250
  }
@@ -1105,25 +1253,29 @@ function executeAiAssistantMongoRead(payload, context) {
1105
1253
  }
1106
1254
  function executeAiAssistantMongoAggregate(payload, context) {
1107
1255
  return __awaiter(this, void 0, void 0, function () {
1108
- var input, collection, _a, user, isSuperAdmin, customerId, dbName, db, 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;
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;
1109
1257
  var _c, _d;
1110
1258
  return __generator(this, function (_e) {
1111
1259
  switch (_e.label) {
1112
1260
  case 0:
1113
1261
  input = payload || {};
1114
- collection = normalizeOptionalString(input.collection);
1115
- if (!collection) {
1262
+ rawCollection = normalizeOptionalString(input.collection);
1263
+ if (!rawCollection) {
1116
1264
  throw new Error('AI assistant mongo aggregate: Collection is required.');
1117
1265
  }
1118
- return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
1266
+ dbName = resolveAssistantDatabaseName(input.database, input.mongo);
1267
+ db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1268
+ return [4 /*yield*/, resolveAssistantCollectionName(db, dbName, rawCollection)];
1119
1269
  case 1:
1270
+ collectionResolution = _e.sent();
1271
+ collection = collectionResolution.name || rawCollection;
1272
+ return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
1273
+ case 2:
1120
1274
  _a = _e.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
1121
1275
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
1122
1276
  throw new Error('AI assistant mongo aggregate: Access denied.');
1123
1277
  }
1124
1278
  customerId = normalizeOptionalString((_c = user === null || user === void 0 ? void 0 : user.other) === null || _c === void 0 ? void 0 : _c.id_customer);
1125
- dbName = resolveAssistantDatabaseName(input.database, input.mongo);
1126
- db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
1127
1279
  baseQuery = normalizeMongoQuery(input.query);
1128
1280
  if (!isSuperAdmin && (collection === 'users' || collection === 'user-versions')) {
1129
1281
  userId = normalizeOptionalString(user === null || user === void 0 ? void 0 : user._id);
@@ -1135,15 +1287,15 @@ function executeAiAssistantMongoAggregate(payload, context) {
1135
1287
  };
1136
1288
  }
1137
1289
  normalizedClient = normalizeOptionalString(input.id_client);
1138
- if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 3];
1290
+ if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 4];
1139
1291
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
1140
- case 2:
1141
- _b = _e.sent();
1142
- return [3 /*break*/, 4];
1143
1292
  case 3:
1144
- _b = false;
1145
- _e.label = 4;
1293
+ _b = _e.sent();
1294
+ return [3 /*break*/, 5];
1146
1295
  case 4:
1296
+ _b = false;
1297
+ _e.label = 5;
1298
+ case 5:
1147
1299
  shouldScopeByClient = _b;
1148
1300
  clientScopedQuery = shouldScopeByClient
1149
1301
  ? applyClientScopeFilter(baseQuery, normalizedClient, isSuperAdmin)
@@ -1160,63 +1312,63 @@ function executeAiAssistantMongoAggregate(payload, context) {
1160
1312
  return [4 /*yield*/, db.collection(collection)
1161
1313
  .aggregate(limitedPipeline, normalizedOptions.aggregateOptions)
1162
1314
  .toArray()];
1163
- case 5:
1315
+ case 6:
1164
1316
  documents = _e.sent();
1165
1317
  executedPipeline = limitedPipeline;
1166
1318
  fallbackMeta = {};
1167
- if (!(!documents.length && dateField)) return [3 /*break*/, 9];
1319
+ if (!(!documents.length && dateField)) return [3 /*break*/, 10];
1168
1320
  fallback = resolveAggregateDateFieldFallback(limitedPipeline);
1169
- if (!fallback) return [3 /*break*/, 7];
1321
+ if (!fallback) return [3 /*break*/, 8];
1170
1322
  fallbackMeta.dateField = __assign(__assign({}, fallback), { attempted: true, used: false });
1171
1323
  fallbackPipeline = replaceAggregateDateField(limitedPipeline, fallback.from, fallback.to);
1172
- if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 7];
1324
+ if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 8];
1173
1325
  return [4 /*yield*/, db.collection(collection)
1174
1326
  .aggregate(fallbackPipeline, normalizedOptions.aggregateOptions)
1175
1327
  .toArray()];
1176
- case 6:
1328
+ case 7:
1177
1329
  fallbackDocs = _e.sent();
1178
1330
  if (fallbackDocs.length) {
1179
1331
  documents = fallbackDocs;
1180
1332
  executedPipeline = fallbackPipeline;
1181
1333
  fallbackMeta.dateField.used = true;
1182
1334
  }
1183
- _e.label = 7;
1184
- case 7:
1185
- if (!(!documents.length && dateField !== 'createdAt')) return [3 /*break*/, 9];
1335
+ _e.label = 8;
1336
+ case 8:
1337
+ if (!(!documents.length && dateField !== 'createdAt')) return [3 /*break*/, 10];
1186
1338
  createdFallback = { from: dateField, to: 'createdAt', attempted: true, used: false };
1187
1339
  createdPipeline = replaceAggregateDateField(limitedPipeline, dateField, 'createdAt');
1188
1340
  fallbackMeta.dateFieldCreatedAt = createdFallback;
1189
- if (!!containsForbiddenMongoOperators(createdPipeline)) return [3 /*break*/, 9];
1341
+ if (!!containsForbiddenMongoOperators(createdPipeline)) return [3 /*break*/, 10];
1190
1342
  return [4 /*yield*/, db.collection(collection)
1191
1343
  .aggregate(createdPipeline, normalizedOptions.aggregateOptions)
1192
1344
  .toArray()];
1193
- case 8:
1345
+ case 9:
1194
1346
  createdDocs = _e.sent();
1195
1347
  if (createdDocs.length) {
1196
1348
  documents = createdDocs;
1197
1349
  executedPipeline = createdPipeline;
1198
1350
  fallbackMeta.dateFieldCreatedAt.used = true;
1199
1351
  }
1200
- _e.label = 9;
1201
- case 9:
1202
- if (!(documents.length <= 1)) return [3 /*break*/, 11];
1352
+ _e.label = 10;
1353
+ case 10:
1354
+ if (!(documents.length <= 1)) return [3 /*break*/, 12];
1203
1355
  unwindFallback = resolveAggregateUnwindFallback(executedPipeline);
1204
- if (!unwindFallback) return [3 /*break*/, 11];
1356
+ if (!unwindFallback) return [3 /*break*/, 12];
1205
1357
  fallbackMeta.unwind = { path: unwindFallback.path, attempted: true, used: false };
1206
1358
  fallbackPipeline = buildAggregateUnwindFallbackPipeline(executedPipeline, unwindFallback);
1207
- if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 11];
1359
+ if (!!containsForbiddenMongoOperators(fallbackPipeline)) return [3 /*break*/, 12];
1208
1360
  return [4 /*yield*/, db.collection(collection)
1209
1361
  .aggregate(fallbackPipeline, normalizedOptions.aggregateOptions)
1210
1362
  .toArray()];
1211
- case 10:
1363
+ case 11:
1212
1364
  fallbackDocs = _e.sent();
1213
1365
  if (fallbackDocs.length > documents.length) {
1214
1366
  documents = fallbackDocs;
1215
1367
  executedPipeline = fallbackPipeline;
1216
1368
  fallbackMeta.unwind.used = true;
1217
1369
  }
1218
- _e.label = 11;
1219
- case 11:
1370
+ _e.label = 12;
1371
+ case 12:
1220
1372
  sanitizedDocuments = isSuperAdmin
1221
1373
  ? documents
1222
1374
  : documents.map(function (doc) { return redactSensitiveFields((0, common_1.deepCopy)(doc)); });
@@ -1229,6 +1381,11 @@ function executeAiAssistantMongoAggregate(payload, context) {
1229
1381
  return [2 /*return*/, __assign({ documents: sanitizedDocuments, display: display }, (isSuperAdmin ? {
1230
1382
  debug: {
1231
1383
  collection: collection,
1384
+ collectionRequested: rawCollection,
1385
+ collectionResolved: collection,
1386
+ collectionMatched: collectionResolution.matched,
1387
+ collectionCandidates: collectionResolution.candidates,
1388
+ collectionScore: collectionResolution.score,
1232
1389
  database: dbName,
1233
1390
  query: scopedQuery,
1234
1391
  options: normalizedOptions.aggregateOptions,
@@ -1299,7 +1456,7 @@ function buildAssistantToolRequest(directive, payload) {
1299
1456
  return request;
1300
1457
  }
1301
1458
  function buildAssistantToolResultPayload(directive, toolResponse) {
1302
- var _a;
1459
+ var _a, _b, _c;
1303
1460
  var directivePayload = directive.payload || {};
1304
1461
  var documents = Array.isArray(toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.documents) ? toolResponse.documents : [];
1305
1462
  var includeIds = ((_a = directivePayload === null || directivePayload === void 0 ? void 0 : directivePayload.options) === null || _a === void 0 ? void 0 : _a.includeIds) === true;
@@ -1316,17 +1473,22 @@ function buildAssistantToolResultPayload(directive, toolResponse) {
1316
1473
  });
1317
1474
  var total = typeof (toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.total) === 'number' ? toolResponse.total : null;
1318
1475
  var rowCount = documents.length || trimmedDisplay.rowCount;
1319
- var collection = normalizeOptionalString(directivePayload === null || directivePayload === void 0 ? void 0 : directivePayload.collection) || '';
1476
+ var requestedCollection = normalizeOptionalString(directivePayload === null || directivePayload === void 0 ? void 0 : directivePayload.collection);
1477
+ var resolvedCollection = normalizeOptionalString((_b = toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.debug) === null || _b === void 0 ? void 0 : _b.collectionResolved)
1478
+ || normalizeOptionalString((_c = toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.debug) === null || _c === void 0 ? void 0 : _c.collection)
1479
+ || requestedCollection
1480
+ || '';
1320
1481
  var result = {
1321
1482
  type: directive.type === 'aggregate' ? 'mongo_agg' : 'mongo_read',
1322
1483
  input: directivePayload,
1323
1484
  output: {
1324
1485
  display: trimmedDisplay,
1325
1486
  total: total !== null ? total : undefined,
1326
- collection: collection || undefined,
1487
+ collection: resolvedCollection || undefined,
1327
1488
  rowCount: rowCount,
1328
1489
  columns: trimmedDisplay.columns,
1329
- truncated: trimmedDisplay.truncated
1490
+ truncated: trimmedDisplay.truncated,
1491
+ debug: (toolResponse === null || toolResponse === void 0 ? void 0 : toolResponse.debug) && typeof toolResponse.debug === 'object' ? toolResponse.debug : undefined
1330
1492
  }
1331
1493
  };
1332
1494
  return {
@@ -1382,6 +1544,82 @@ function buildAssistantToolFallbackResponse(result) {
1382
1544
  }
1383
1545
  return lines.join('\n').trim();
1384
1546
  }
1547
+ function buildAssistantDebugPayload(params) {
1548
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
1549
+ var notes = [];
1550
+ if (params.dataQuestion) {
1551
+ notes.push('Detected a data request; tool call required.');
1552
+ }
1553
+ if (params.directiveSource === 'forced') {
1554
+ notes.push('Assistant response omitted a MONGO_* directive; ran a directive-only pass.');
1555
+ }
1556
+ var directive = params.directive;
1557
+ var directivePayload = (directive === null || directive === void 0 ? void 0 : directive.payload) || {};
1558
+ var rawCollection = normalizeOptionalString(directivePayload === null || directivePayload === void 0 ? void 0 : directivePayload.collection);
1559
+ var debugCollectionRequested = normalizeOptionalString((_a = params.toolResponseDebug) === null || _a === void 0 ? void 0 : _a.collectionRequested);
1560
+ var debugCollectionResolved = normalizeOptionalString((_b = params.toolResponseDebug) === null || _b === void 0 ? void 0 : _b.collectionResolved);
1561
+ var debugCollection = normalizeOptionalString((_c = params.toolResponseDebug) === null || _c === void 0 ? void 0 : _c.collection);
1562
+ var requestedCollection = debugCollectionRequested || rawCollection;
1563
+ var resolvedCollection = debugCollectionResolved || debugCollection || requestedCollection;
1564
+ var matchedCollection = typeof ((_d = params.toolResponseDebug) === null || _d === void 0 ? void 0 : _d.collectionMatched) === 'boolean'
1565
+ ? params.toolResponseDebug.collectionMatched
1566
+ : undefined;
1567
+ var candidateCollections = Array.isArray((_e = params.toolResponseDebug) === null || _e === void 0 ? void 0 : _e.collectionCandidates)
1568
+ ? params.toolResponseDebug.collectionCandidates.filter(Boolean)
1569
+ : [];
1570
+ if (requestedCollection && resolvedCollection && requestedCollection !== resolvedCollection) {
1571
+ notes.push("Resolved collection \"".concat(requestedCollection, "\" -> \"").concat(resolvedCollection, "\"."));
1572
+ }
1573
+ else if (matchedCollection === false && candidateCollections.length) {
1574
+ notes.push("No direct collection match; candidates: ".concat(candidateCollections.join(', '), "."));
1575
+ }
1576
+ if (((_f = params.toolResult) === null || _f === void 0 ? void 0 : _f.type) === 'mongo_agg') {
1577
+ notes.push('Used aggregation for grouped/breakdown request.');
1578
+ }
1579
+ else if (((_g = params.toolResult) === null || _g === void 0 ? void 0 : _g.type) === 'mongo_read') {
1580
+ notes.push('Used read query for list/count request.');
1581
+ }
1582
+ var fallbackInfo = (_h = params.toolResponseDebug) === null || _h === void 0 ? void 0 : _h.fallbacks;
1583
+ if ((_j = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.dateField) === null || _j === void 0 ? void 0 : _j.used) {
1584
+ notes.push("Retried with date field fallback ".concat(fallbackInfo.dateField.from, " -> ").concat(fallbackInfo.dateField.to, "."));
1585
+ }
1586
+ if ((_k = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.dateFieldCreatedAt) === null || _k === void 0 ? void 0 : _k.used) {
1587
+ notes.push("Retried with date field fallback ".concat(fallbackInfo.dateFieldCreatedAt.from, " -> ").concat(fallbackInfo.dateFieldCreatedAt.to, "."));
1588
+ }
1589
+ if ((_l = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.unwind) === null || _l === void 0 ? void 0 : _l.used) {
1590
+ notes.push("Applied unwind fallback on ".concat(fallbackInfo.unwind.path, "."));
1591
+ }
1592
+ if (params.toolError) {
1593
+ var errorMessage = ((_m = params.toolError) === null || _m === void 0 ? void 0 : _m.message) || String(params.toolError || '');
1594
+ if (errorMessage) {
1595
+ notes.push("Tool error: ".concat(errorMessage));
1596
+ }
1597
+ }
1598
+ return {
1599
+ decision: {
1600
+ dataQuestion: params.dataQuestion,
1601
+ directiveSource: params.directiveSource
1602
+ },
1603
+ directive: directive ? {
1604
+ type: directive.type,
1605
+ payload: directivePayload,
1606
+ rawLine: directive.rawLine
1607
+ } : null,
1608
+ collection: resolvedCollection || requestedCollection || undefined,
1609
+ collectionRequested: requestedCollection || undefined,
1610
+ collectionResolved: resolvedCollection || undefined,
1611
+ collectionMatched: matchedCollection,
1612
+ collectionCandidates: candidateCollections.length ? candidateCollections : undefined,
1613
+ collectionScore: typeof ((_o = params.toolResponseDebug) === null || _o === void 0 ? void 0 : _o.collectionScore) === 'number'
1614
+ ? params.toolResponseDebug.collectionScore
1615
+ : undefined,
1616
+ query: ((_p = params.toolResponseDebug) === null || _p === void 0 ? void 0 : _p.query) || undefined,
1617
+ pipeline: ((_q = params.toolResponseDebug) === null || _q === void 0 ? void 0 : _q.executedPipeline) || ((_r = params.toolResponseDebug) === null || _r === void 0 ? void 0 : _r.originalPipeline) || undefined,
1618
+ options: ((_s = params.toolResponseDebug) === null || _s === void 0 ? void 0 : _s.options) || undefined,
1619
+ fallbacks: ((_t = params.toolResponseDebug) === null || _t === void 0 ? void 0 : _t.fallbacks) || undefined,
1620
+ notes: notes
1621
+ };
1622
+ }
1385
1623
  function buildAssistantToolErrorMessage(error, directive, request) {
1386
1624
  var _a, _b;
1387
1625
  var rawMessage = normalizeOptionalString(error === null || error === void 0 ? void 0 : error.message) || 'Unable to access data.';
@@ -2006,7 +2244,18 @@ function normalizeAssistantAggregatePipeline(pipeline) {
2006
2244
  if (!Array.isArray(pipeline)) {
2007
2245
  return [];
2008
2246
  }
2009
- return pipeline.filter(function (stage) { return stage && typeof stage === 'object' && !Array.isArray(stage); });
2247
+ return pipeline
2248
+ .filter(function (stage) { return stage && typeof stage === 'object' && !Array.isArray(stage); })
2249
+ .map(function (stage) {
2250
+ var next = __assign({}, stage);
2251
+ if (next.$match && typeof next.$match === 'object') {
2252
+ next.$match = applyAssistantNameRegexToQuery(next.$match);
2253
+ }
2254
+ if (next.$geoNear && typeof next.$geoNear === 'object' && next.$geoNear.query) {
2255
+ next.$geoNear = __assign(__assign({}, next.$geoNear), { query: applyAssistantNameRegexToQuery(next.$geoNear.query) });
2256
+ }
2257
+ return next;
2258
+ });
2010
2259
  }
2011
2260
  function buildAssistantAggregatePipeline(query, pipeline) {
2012
2261
  var _a;
@@ -2275,10 +2524,302 @@ function normalizeMongoQuery(query) {
2275
2524
  if (containsForbiddenMongoOperators(normalized)) {
2276
2525
  throw new Error('AI assistant mongo read: Query contains restricted operators.');
2277
2526
  }
2278
- return normalized;
2527
+ return applyAssistantNameRegexToQuery(normalized);
2528
+ }
2529
+ function shouldApplyAssistantNameRegex(field) {
2530
+ var normalized = String(field || '').toLowerCase().trim();
2531
+ if (!normalized) {
2532
+ return false;
2533
+ }
2534
+ if (normalized.startsWith('$')) {
2535
+ return false;
2536
+ }
2537
+ if (isAssistantIdField(normalized)) {
2538
+ return false;
2539
+ }
2540
+ if (normalized === 'id' || normalized.endsWith('_id')) {
2541
+ return false;
2542
+ }
2543
+ var tokens = normalized.split(/[^a-z0-9]+/g).filter(Boolean);
2544
+ var targetTokens = new Set(['customer', 'well', 'chemical']);
2545
+ var hasTargetToken = tokens.some(function (token) { return targetTokens.has(token); });
2546
+ if (hasTargetToken) {
2547
+ return true;
2548
+ }
2549
+ if (tokens.includes('name')) {
2550
+ return true;
2551
+ }
2552
+ return /(^|[._-])name$/i.test(normalized);
2553
+ }
2554
+ function escapeRegexValue(value) {
2555
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
2556
+ }
2557
+ function applyAssistantNameRegexToQuery(query) {
2558
+ if (Array.isArray(query)) {
2559
+ return query.map(function (entry) { return applyAssistantNameRegexToQuery(entry); });
2560
+ }
2561
+ if (!query || typeof query !== 'object' || query instanceof Date || query instanceof RegExp || isMongoObjectId(query)) {
2562
+ return query;
2563
+ }
2564
+ var result = {};
2565
+ Object.keys(query).forEach(function (key) {
2566
+ var value = query[key];
2567
+ if (key.startsWith('$')) {
2568
+ result[key] = applyAssistantNameRegexToQuery(value);
2569
+ return;
2570
+ }
2571
+ if (typeof value === 'string' && shouldApplyAssistantNameRegex(key)) {
2572
+ var trimmed = value.trim();
2573
+ result[key] = trimmed ? new RegExp(escapeRegexValue(trimmed), 'i') : value;
2574
+ return;
2575
+ }
2576
+ if (value && typeof value === 'object') {
2577
+ result[key] = applyAssistantNameRegexToQuery(value);
2578
+ return;
2579
+ }
2580
+ result[key] = value;
2581
+ });
2582
+ return result;
2583
+ }
2584
+ function normalizeCollectionKey(value) {
2585
+ return String(value || '').toLowerCase().replace(/[^a-z0-9]/g, '');
2586
+ }
2587
+ function normalizeCollectionToken(token) {
2588
+ var trimmed = token.trim();
2589
+ if (!trimmed) {
2590
+ return [];
2591
+ }
2592
+ var tokens = new Set([trimmed]);
2593
+ if (trimmed.length > 4
2594
+ && trimmed.endsWith('s')
2595
+ && !trimmed.endsWith('ss')
2596
+ && !trimmed.endsWith('us')
2597
+ && !trimmed.endsWith('is')) {
2598
+ tokens.add(trimmed.slice(0, -1));
2599
+ }
2600
+ return Array.from(tokens);
2601
+ }
2602
+ function tokenizeCollectionText(value) {
2603
+ var rawTokens = String(value || '')
2604
+ .toLowerCase()
2605
+ .split(/[^a-z0-9]+/g)
2606
+ .map(function (token) { return token.trim(); })
2607
+ .filter(Boolean);
2608
+ var tokens = [];
2609
+ rawTokens.forEach(function (token) {
2610
+ normalizeCollectionToken(token).forEach(function (normalized) {
2611
+ if (!AI_ASSISTANT_COLLECTION_STOPWORDS.has(normalized)) {
2612
+ tokens.push(normalized);
2613
+ }
2614
+ });
2615
+ });
2616
+ return Array.from(new Set(tokens));
2617
+ }
2618
+ function listAssistantCollections(db, dbName) {
2619
+ return __awaiter(this, void 0, void 0, function () {
2620
+ var cacheKey, cached, now, collections, names, _a;
2621
+ return __generator(this, function (_b) {
2622
+ switch (_b.label) {
2623
+ case 0:
2624
+ cacheKey = normalizeOptionalString(dbName) || 'default';
2625
+ cached = AI_ASSISTANT_COLLECTION_CACHE.get(cacheKey);
2626
+ now = Date.now();
2627
+ if (cached && now - cached.updatedAt < AI_ASSISTANT_COLLECTION_CACHE_TTL_MS) {
2628
+ return [2 /*return*/, cached.names];
2629
+ }
2630
+ _b.label = 1;
2631
+ case 1:
2632
+ _b.trys.push([1, 3, , 4]);
2633
+ return [4 /*yield*/, db.listCollections({}, { nameOnly: true }).toArray()];
2634
+ case 2:
2635
+ collections = _b.sent();
2636
+ names = Array.isArray(collections)
2637
+ ? collections.map(function (entry) { return normalizeOptionalString(entry === null || entry === void 0 ? void 0 : entry.name); }).filter(Boolean)
2638
+ : [];
2639
+ AI_ASSISTANT_COLLECTION_CACHE.set(cacheKey, { names: names, updatedAt: now });
2640
+ return [2 /*return*/, names];
2641
+ case 3:
2642
+ _a = _b.sent();
2643
+ return [2 /*return*/, (cached === null || cached === void 0 ? void 0 : cached.names) || []];
2644
+ case 4: return [2 /*return*/];
2645
+ }
2646
+ });
2647
+ });
2648
+ }
2649
+ function scoreCollectionMatch(requestedTokens, candidateName) {
2650
+ if (!requestedTokens.length) {
2651
+ return 0;
2652
+ }
2653
+ var candidateTokens = tokenizeCollectionText(candidateName);
2654
+ if (!candidateTokens.length) {
2655
+ return 0;
2656
+ }
2657
+ var score = 0;
2658
+ requestedTokens.forEach(function (token) {
2659
+ if (candidateTokens.includes(token)) {
2660
+ score += 10;
2661
+ }
2662
+ });
2663
+ var requestedKey = normalizeCollectionKey(requestedTokens.join('-'));
2664
+ var candidateKey = normalizeCollectionKey(candidateName);
2665
+ if (candidateKey === requestedKey && requestedKey) {
2666
+ score += 50;
2667
+ }
2668
+ else if (requestedKey && (candidateKey.includes(requestedKey) || requestedKey.includes(candidateKey))) {
2669
+ score += 20;
2670
+ }
2671
+ return score;
2672
+ }
2673
+ function findBestCollectionMatch(requested, collectionNames) {
2674
+ var requestedTokens = tokenizeCollectionText(requested);
2675
+ if (!requestedTokens.length || !collectionNames.length) {
2676
+ return null;
2677
+ }
2678
+ var best = null;
2679
+ collectionNames.forEach(function (name) {
2680
+ var score = scoreCollectionMatch(requestedTokens, name);
2681
+ if (!best || score > best.score) {
2682
+ best = { name: name, score: score };
2683
+ }
2684
+ });
2685
+ return best;
2686
+ }
2687
+ function resolveAssistantCollectionName(db, dbName, requested) {
2688
+ return __awaiter(this, void 0, void 0, function () {
2689
+ var trimmed, collectionNames, best, candidates;
2690
+ return __generator(this, function (_a) {
2691
+ switch (_a.label) {
2692
+ case 0:
2693
+ trimmed = normalizeOptionalString(requested);
2694
+ if (!trimmed) {
2695
+ return [2 /*return*/, { name: '', matched: false, candidates: [], score: 0 }];
2696
+ }
2697
+ return [4 /*yield*/, listAssistantCollections(db, dbName)];
2698
+ case 1:
2699
+ collectionNames = _a.sent();
2700
+ if (collectionNames.includes(trimmed)) {
2701
+ return [2 /*return*/, { name: trimmed, matched: true, candidates: [], score: 100 }];
2702
+ }
2703
+ best = findBestCollectionMatch(trimmed, collectionNames);
2704
+ if (best && best.score >= 20) {
2705
+ return [2 /*return*/, { name: best.name, matched: true, candidates: [], score: best.score }];
2706
+ }
2707
+ candidates = collectionNames
2708
+ .map(function (name) { return ({ name: name, score: scoreCollectionMatch(tokenizeCollectionText(trimmed), name) }); })
2709
+ .filter(function (entry) { return entry.score > 0; })
2710
+ .sort(function (a, b) { return b.score - a.score; })
2711
+ .slice(0, 5)
2712
+ .map(function (entry) { return entry.name; });
2713
+ return [2 /*return*/, { name: trimmed, matched: false, candidates: candidates, score: (best === null || best === void 0 ? void 0 : best.score) || 0 }];
2714
+ }
2715
+ });
2716
+ });
2717
+ }
2718
+ function resolveAssistantCollectionHints(message, dbName, db) {
2719
+ return __awaiter(this, void 0, void 0, function () {
2720
+ var text, collectionNames, tokens;
2721
+ return __generator(this, function (_a) {
2722
+ switch (_a.label) {
2723
+ case 0:
2724
+ text = normalizeOptionalString(message);
2725
+ if (!text) {
2726
+ return [2 /*return*/, []];
2727
+ }
2728
+ return [4 /*yield*/, listAssistantCollections(db, dbName)];
2729
+ case 1:
2730
+ collectionNames = _a.sent();
2731
+ if (!collectionNames.length) {
2732
+ return [2 /*return*/, []];
2733
+ }
2734
+ tokens = tokenizeCollectionText(text);
2735
+ if (!tokens.length) {
2736
+ return [2 /*return*/, []];
2737
+ }
2738
+ return [2 /*return*/, collectionNames
2739
+ .map(function (name) { return ({ name: name, score: scoreCollectionMatch(tokens, name) }); })
2740
+ .filter(function (entry) { return entry.score > 0; })
2741
+ .sort(function (a, b) { return b.score - a.score; })
2742
+ .slice(0, 5)
2743
+ .map(function (entry) { return entry.name; })];
2744
+ }
2745
+ });
2746
+ });
2747
+ }
2748
+ function findQueryDateField(query) {
2749
+ var e_1, _a, e_2, _b;
2750
+ if (!query || typeof query !== 'object') {
2751
+ return null;
2752
+ }
2753
+ if (Array.isArray(query)) {
2754
+ try {
2755
+ for (var query_1 = __values(query), query_1_1 = query_1.next(); !query_1_1.done; query_1_1 = query_1.next()) {
2756
+ var entry = query_1_1.value;
2757
+ var found = findQueryDateField(entry);
2758
+ if (found) {
2759
+ return found;
2760
+ }
2761
+ }
2762
+ }
2763
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2764
+ finally {
2765
+ try {
2766
+ if (query_1_1 && !query_1_1.done && (_a = query_1.return)) _a.call(query_1);
2767
+ }
2768
+ finally { if (e_1) throw e_1.error; }
2769
+ }
2770
+ return null;
2771
+ }
2772
+ try {
2773
+ for (var _c = __values(Object.keys(query)), _d = _c.next(); !_d.done; _d = _c.next()) {
2774
+ var key = _d.value;
2775
+ if (key.startsWith('$')) {
2776
+ var found = findQueryDateField(query[key]);
2777
+ if (found) {
2778
+ return found;
2779
+ }
2780
+ continue;
2781
+ }
2782
+ if (AI_ASSISTANT_DATE_FALLBACKS[key]) {
2783
+ return key;
2784
+ }
2785
+ }
2786
+ }
2787
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
2788
+ finally {
2789
+ try {
2790
+ if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
2791
+ }
2792
+ finally { if (e_2) throw e_2.error; }
2793
+ }
2794
+ return null;
2795
+ }
2796
+ function replaceQueryField(query, fromField, toField) {
2797
+ if (Array.isArray(query)) {
2798
+ return query.map(function (entry) { return replaceQueryField(entry, fromField, toField); });
2799
+ }
2800
+ if (!query || typeof query !== 'object' || query instanceof Date) {
2801
+ return query;
2802
+ }
2803
+ var result = {};
2804
+ Object.keys(query).forEach(function (key) {
2805
+ var nextKey = key === fromField ? toField : key;
2806
+ result[nextKey] = replaceQueryField(query[key], fromField, toField);
2807
+ });
2808
+ return result;
2809
+ }
2810
+ function resolveQueryDateFieldFallback(query) {
2811
+ var dateField = findQueryDateField(query);
2812
+ if (!dateField) {
2813
+ return null;
2814
+ }
2815
+ var fallback = AI_ASSISTANT_DATE_FALLBACKS[dateField];
2816
+ if (!fallback) {
2817
+ return null;
2818
+ }
2819
+ return { from: dateField, to: fallback };
2279
2820
  }
2280
2821
  function containsForbiddenMongoOperators(value) {
2281
- var e_1, _a;
2822
+ var e_3, _a;
2282
2823
  if (!value || typeof value !== 'object') {
2283
2824
  return false;
2284
2825
  }
@@ -2297,12 +2838,12 @@ function containsForbiddenMongoOperators(value) {
2297
2838
  }
2298
2839
  }
2299
2840
  }
2300
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
2841
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
2301
2842
  finally {
2302
2843
  try {
2303
2844
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2304
2845
  }
2305
- finally { if (e_1) throw e_1.error; }
2846
+ finally { if (e_3) throw e_3.error; }
2306
2847
  }
2307
2848
  return false;
2308
2849
  }
@@ -2465,6 +3006,20 @@ function resolveCodexModel() {
2465
3006
  || process.env.AI_DASHBOARD_CODEX_MODEL);
2466
3007
  return raw || DEFAULT_CODEX_MODEL;
2467
3008
  }
3009
+ function resolveCodexThoughtLevel() {
3010
+ var config = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
3011
+ var raw = normalizeOptionalString(config['AI_ASSISTANT_CODEX_THOUGHT_LEVEL']
3012
+ || process.env.AI_ASSISTANT_CODEX_THOUGHT_LEVEL
3013
+ || config['AI_TERMINAL_CODEX_THOUGHT_LEVEL']
3014
+ || process.env.AI_TERMINAL_CODEX_THOUGHT_LEVEL
3015
+ || config['AI_DASHBOARD_CODEX_THOUGHT_LEVEL']
3016
+ || process.env.AI_DASHBOARD_CODEX_THOUGHT_LEVEL);
3017
+ var normalized = (raw || '').trim().toLowerCase();
3018
+ if (normalized === 'minimal' || normalized === 'low' || normalized === 'medium' || normalized === 'high' || normalized === 'xhigh') {
3019
+ return normalized;
3020
+ }
3021
+ return 'low';
3022
+ }
2468
3023
  function resolveCodexSettings() {
2469
3024
  var serverConfig = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
2470
3025
  var apiKey = (serverConfig['OPENAI_API_KEY'] || process.env.OPENAI_API_KEY || '').trim();
@@ -2522,8 +3077,8 @@ function applyCodexStreamStatusHandler(runOptions, streamStatusHandler) {
2522
3077
  }
2523
3078
  function waitForCodexWorkerMessage(worker, streamStatusHandler) {
2524
3079
  return __awaiter(this, void 0, void 0, function () {
2525
- var _a, _b, _c, _d, message, payload, status_1, e_2_1;
2526
- var _e, e_2, _f, _g;
3080
+ var _a, _b, _c, _d, message, payload, status_1, e_4_1;
3081
+ var _e, e_4, _f, _g;
2527
3082
  return __generator(this, function (_h) {
2528
3083
  switch (_h.label) {
2529
3084
  case 0:
@@ -2550,8 +3105,8 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
2550
3105
  return [3 /*break*/, 1];
2551
3106
  case 4: return [3 /*break*/, 11];
2552
3107
  case 5:
2553
- e_2_1 = _h.sent();
2554
- e_2 = { error: e_2_1 };
3108
+ e_4_1 = _h.sent();
3109
+ e_4 = { error: e_4_1 };
2555
3110
  return [3 /*break*/, 11];
2556
3111
  case 6:
2557
3112
  _h.trys.push([6, , 9, 10]);
@@ -2562,7 +3117,7 @@ function waitForCodexWorkerMessage(worker, streamStatusHandler) {
2562
3117
  _h.label = 8;
2563
3118
  case 8: return [3 /*break*/, 10];
2564
3119
  case 9:
2565
- if (e_2) throw e_2.error;
3120
+ if (e_4) throw e_4.error;
2566
3121
  return [7 /*endfinally*/];
2567
3122
  case 10: return [7 /*endfinally*/];
2568
3123
  case 11: throw new CodexWorkerBootstrapError('Codex worker exited before completing.');
@@ -2838,6 +3393,43 @@ function resolveAssistantWorkspaceRoot() {
2838
3393
  });
2839
3394
  });
2840
3395
  }
3396
+ function isAssistantDataQuestion(message) {
3397
+ var text = normalizeOptionalString(message).toLowerCase();
3398
+ if (!text) {
3399
+ return false;
3400
+ }
3401
+ var patterns = [
3402
+ /\bshow\b/,
3403
+ /\blist\b/,
3404
+ /\bhow many\b/,
3405
+ /\bcount\b/,
3406
+ /\btotal\b/,
3407
+ /\bnumber of\b/,
3408
+ /\blast\b/,
3409
+ /\brecent\b/,
3410
+ /\bthis week\b/,
3411
+ /\blast month\b/,
3412
+ /\boverdue\b/,
3413
+ /\bopen\b/,
3414
+ /\bclosed\b/,
3415
+ /\bcompleted\b/,
3416
+ /\bmissing\b/,
3417
+ /\bgroup(ed)? by\b/,
3418
+ /\bbreakdown\b/,
3419
+ /\bper day\b/,
3420
+ /\bper week\b/,
3421
+ /\bper month\b/
3422
+ ];
3423
+ return patterns.some(function (pattern) { return pattern.test(text); });
3424
+ }
3425
+ function buildAssistantCodexDirectivePrompt(message, attachmentText, historyText, contextText) {
3426
+ var trimmedContext = normalizeOptionalString(contextText);
3427
+ var contextBlock = trimmedContext ? "\n\nContext:\n".concat(trimmedContext) : '';
3428
+ var trimmedHistory = normalizeOptionalString(historyText);
3429
+ var historyBlock = trimmedHistory ? "\n\nConversation so far:\n".concat(trimmedHistory) : '';
3430
+ var instruction = '\n\nInstruction:\nReturn ONLY a single MONGO_READ or MONGO_AGG directive line. Do not include any other text.';
3431
+ return "System:\n".concat(AI_ASSISTANT_SYSTEM_PROMPT).concat(contextBlock).concat(historyBlock, "\n\nUser:\n").concat(message).concat(attachmentText || '').concat(instruction).trim();
3432
+ }
2841
3433
  function buildAssistantCodexPrompt(message, attachmentText, historyText, contextText) {
2842
3434
  var trimmedContext = normalizeOptionalString(contextText);
2843
3435
  var contextBlock = trimmedContext ? "\n\nContext:\n".concat(trimmedContext) : '';
@@ -2871,6 +3463,12 @@ function buildAssistantContext(input, userContext) {
2871
3463
  if (contextRoute) {
2872
3464
  lines.push("Current page route: ".concat(contextRoute));
2873
3465
  }
3466
+ var collectionHints = Array.isArray(userContext === null || userContext === void 0 ? void 0 : userContext.collectionHints)
3467
+ ? userContext === null || userContext === void 0 ? void 0 : userContext.collectionHints.filter(Boolean)
3468
+ : [];
3469
+ if (collectionHints.length) {
3470
+ lines.push("Collection hints: ".concat(collectionHints.join(', ')));
3471
+ }
2874
3472
  var mongoDb = normalizeOptionalString((_c = input === null || input === void 0 ? void 0 : input.mongo) === null || _c === void 0 ? void 0 : _c.database);
2875
3473
  var mongoDbs = Array.isArray((_d = input === null || input === void 0 ? void 0 : input.mongo) === null || _d === void 0 ? void 0 : _d.databases)
2876
3474
  ? input.mongo.databases.map(function (value) { return normalizeOptionalString(value); }).filter(Boolean)
@@ -2901,7 +3499,7 @@ function normalizeRouteMatchKey(value) {
2901
3499
  return normalizeRouteKey(value).toLowerCase();
2902
3500
  }
2903
3501
  function buildClientRouteIndex() {
2904
- var e_3, _a;
3502
+ var e_5, _a;
2905
3503
  var _b;
2906
3504
  var routes = ((_b = resolveio_server_app_1.ResolveIOServer.getClientRoutes) === null || _b === void 0 ? void 0 : _b.call(resolveio_server_app_1.ResolveIOServer)) || [];
2907
3505
  var set = new Set();
@@ -2920,12 +3518,12 @@ function buildClientRouteIndex() {
2920
3518
  }
2921
3519
  }
2922
3520
  }
2923
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
3521
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
2924
3522
  finally {
2925
3523
  try {
2926
3524
  if (routes_1_1 && !routes_1_1.done && (_a = routes_1.return)) _a.call(routes_1);
2927
3525
  }
2928
- finally { if (e_3) throw e_3.error; }
3526
+ finally { if (e_5) throw e_5.error; }
2929
3527
  }
2930
3528
  return { set: set, map: map, size: routes.length };
2931
3529
  }
@@ -3045,10 +3643,13 @@ function sanitizeAssistantResponse(value) {
3045
3643
  if (!cleaned) {
3046
3644
  return 'I can’t share code, but I can point you to files or explain behavior at a high level.';
3047
3645
  }
3048
- return normalizeAssistantRoutes(cleaned);
3646
+ var normalizedCurrency = cleaned.replace(/\bUSD\s*([0-9][0-9,]*(?:\.[0-9]+)?)/g, function (_match, amount) {
3647
+ return "$".concat(amount);
3648
+ });
3649
+ return normalizeAssistantRoutes(normalizedCurrency);
3049
3650
  }
3050
3651
  function evaluateAssistantGuardrails(message) {
3051
- var e_4, _a;
3652
+ var e_6, _a;
3052
3653
  var normalized = String(message || '').toLowerCase();
3053
3654
  var patterns = [
3054
3655
  {
@@ -3094,12 +3695,12 @@ function evaluateAssistantGuardrails(message) {
3094
3695
  }
3095
3696
  }
3096
3697
  }
3097
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
3698
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
3098
3699
  finally {
3099
3700
  try {
3100
3701
  if (patterns_1_1 && !patterns_1_1.done && (_a = patterns_1.return)) _a.call(patterns_1);
3101
3702
  }
3102
- finally { if (e_4) throw e_4.error; }
3703
+ finally { if (e_6) throw e_6.error; }
3103
3704
  }
3104
3705
  return null;
3105
3706
  }
@@ -3263,8 +3864,8 @@ function handleCodexUpload(id_conversation, file_name, content_base64, size, con
3263
3864
  }
3264
3865
  function readAttachmentContents(attachments) {
3265
3866
  return __awaiter(this, void 0, void 0, function () {
3266
- var limits, totalBytes, totalChars, chunks, cleaned, attachments_1, attachments_1_1, attachment, localPath, safe, stat, ext, name_1, type, readable, content, _a, e_5_1;
3267
- var e_5, _b;
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;
3268
3869
  return __generator(this, function (_c) {
3269
3870
  switch (_c.label) {
3270
3871
  case 0:
@@ -3343,14 +3944,14 @@ function readAttachmentContents(attachments) {
3343
3944
  return [3 /*break*/, 2];
3344
3945
  case 10: return [3 /*break*/, 13];
3345
3946
  case 11:
3346
- e_5_1 = _c.sent();
3347
- e_5 = { error: e_5_1 };
3947
+ e_7_1 = _c.sent();
3948
+ e_7 = { error: e_7_1 };
3348
3949
  return [3 /*break*/, 13];
3349
3950
  case 12:
3350
3951
  try {
3351
3952
  if (attachments_1_1 && !attachments_1_1.done && (_b = attachments_1.return)) _b.call(attachments_1);
3352
3953
  }
3353
- finally { if (e_5) throw e_5.error; }
3954
+ finally { if (e_7) throw e_7.error; }
3354
3955
  return [7 /*endfinally*/];
3355
3956
  case 13: return [2 /*return*/, {
3356
3957
  promptText: chunks.length ? "\n\nAttachments:\n".concat(chunks.join('\n\n')) : '',
@@ -3527,7 +4128,7 @@ function estimateUsage(messages, responseText, model) {
3527
4128
  };
3528
4129
  }
3529
4130
  function evaluateGuardrails(message) {
3530
- var e_6, _a;
4131
+ var e_8, _a;
3531
4132
  var normalized = String(message || '').toLowerCase();
3532
4133
  var patterns = [
3533
4134
  { 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.' },
@@ -3549,12 +4150,12 @@ function evaluateGuardrails(message) {
3549
4150
  }
3550
4151
  }
3551
4152
  }
3552
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
4153
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
3553
4154
  finally {
3554
4155
  try {
3555
4156
  if (patterns_2_1 && !patterns_2_1.done && (_a = patterns_2.return)) _a.call(patterns_2);
3556
4157
  }
3557
- finally { if (e_6) throw e_6.error; }
4158
+ finally { if (e_8) throw e_8.error; }
3558
4159
  }
3559
4160
  return null;
3560
4161
  }