@resolveio/server-lib 22.1.32 → 22.2.0

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.
@@ -88,8 +88,9 @@ var simpl_schema_1 = require("simpl-schema");
88
88
  var user_collection_1 = require("../collections/user.collection");
89
89
  var openai_usage_ledger_manager_1 = require("../managers/openai-usage-ledger.manager");
90
90
  var resolveio_server_app_1 = require("../resolveio-server-app");
91
- var openai_client_1 = require("../services/openai-client");
91
+ var codex_client_1 = require("../services/codex-client");
92
92
  var common_1 = require("../util/common");
93
+ var tokenizer_1 = require("../util/tokenizer");
93
94
  var DEFAULT_LIMIT = 100;
94
95
  var MAX_LIMIT = 2000;
95
96
  var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;
@@ -729,7 +730,7 @@ function normalizeRiskReview(operation, payload, model, requestId) {
729
730
  ? Math.max(0, Math.min(1, normalizedConfidence))
730
731
  : 0.6;
731
732
  var summary = normalizeOptionalString(payload === null || payload === void 0 ? void 0 : payload.summary)
732
- || "Codex review marked this operation as ".concat(riskLevel, " risk.");
733
+ || "AI review marked this operation as ".concat(riskLevel, " risk.");
733
734
  var reasons = normalizeRiskList(payload === null || payload === void 0 ? void 0 : payload.reasons);
734
735
  var suggestedChecks = normalizeRiskList(payload === null || payload === void 0 ? void 0 : payload.suggested_checks);
735
736
  var shouldBlock = (payload === null || payload === void 0 ? void 0 : payload.should_block) === true || riskLevel === 'critical';
@@ -783,6 +784,26 @@ function resolveRiskReviewSettings() {
783
784
  retryDelayMs: retryDelayMs
784
785
  };
785
786
  }
787
+ function buildCodexPrompt(systemPrompt, userPrompt) {
788
+ return "System:\n".concat(systemPrompt, "\n\nUser:\n").concat(userPrompt).trim();
789
+ }
790
+ function buildCodexClient(settings) {
791
+ var fallbackModels = [];
792
+ var fallback = normalizeOptionalString(settings.fallbackModel);
793
+ if (fallback && fallback !== settings.model) {
794
+ fallbackModels.push(fallback);
795
+ }
796
+ return new codex_client_1.CodexClient(__assign(__assign({ apiKey: settings.apiKey, baseUrl: settings.baseUrl, model: settings.model }, (fallbackModels.length ? { fallbackModel: fallbackModels[0], fallbackModels: fallbackModels } : {})), { maxRetries: (0, common_1.round)(settings.maxRetries || 0), retryDelayMs: (0, common_1.round)(settings.retryDelayMs || 0) }));
797
+ }
798
+ function estimateCodexUsage(messages, responseText, model) {
799
+ var inputTokens = (0, tokenizer_1.countChatTokens)(messages, model);
800
+ var outputTokens = (0, tokenizer_1.countTokens)(responseText || '', model);
801
+ return {
802
+ inputTokens: inputTokens,
803
+ outputTokens: outputTokens,
804
+ totalTokens: inputTokens + outputTokens
805
+ };
806
+ }
786
807
  function buildRiskReviewPrompt(input) {
787
808
  var payload = {
788
809
  database: input.database,
@@ -803,7 +824,7 @@ function buildRiskReviewPrompt(input) {
803
824
  }
804
825
  function reviewOperationRisk(input) {
805
826
  return __awaiter(this, void 0, void 0, function () {
806
- var settings, client, systemPrompt, response, payload, err_1, detail;
827
+ var settings, client, systemPrompt, userPrompt, prompt, responseText, payload, err_1, detail;
807
828
  return __generator(this, function (_a) {
808
829
  switch (_a.label) {
809
830
  case 0:
@@ -812,19 +833,9 @@ function reviewOperationRisk(input) {
812
833
  return [2 /*return*/, buildDisabledRiskReview(input.operation)];
813
834
  }
814
835
  if (!settings.apiKey) {
815
- return [2 /*return*/, buildFallbackRiskReview(input.operation, 'AI risk review unavailable: OPENAI_API_KEY is missing.')];
836
+ return [2 /*return*/, buildFallbackRiskReview(input.operation, 'AI risk review unavailable: AI API key is missing.')];
816
837
  }
817
- client = new openai_client_1.OpenAIClient({
818
- apiKey: settings.apiKey,
819
- baseUrl: settings.baseUrl,
820
- model: settings.model,
821
- fallbackModel: settings.fallbackModel,
822
- temperature: 0.1,
823
- maxTokens: settings.maxTokens,
824
- maxRetries: (0, common_1.round)(settings.maxRetries),
825
- retryDelayMs: (0, common_1.round)(settings.retryDelayMs),
826
- responseFormat: 'json'
827
- });
838
+ client = buildCodexClient(settings);
828
839
  systemPrompt = [
829
840
  'You are a MongoDB operation safety reviewer for a production SaaS application.',
830
841
  'Respond with a single JSON object only.',
@@ -837,20 +848,27 @@ function reviewOperationRisk(input) {
837
848
  'confidence (number between 0 and 1).',
838
849
  'Keep summary concise (<= 220 chars).'
839
850
  ].join(' ');
851
+ userPrompt = buildRiskReviewPrompt(input);
852
+ prompt = buildCodexPrompt(systemPrompt, userPrompt);
840
853
  _a.label = 1;
841
854
  case 1:
842
855
  _a.trys.push([1, 3, , 4]);
843
- return [4 /*yield*/, client.chat([
844
- { role: 'system', content: systemPrompt },
845
- { role: 'user', content: buildRiskReviewPrompt(input) }
846
- ], {
856
+ return [4 /*yield*/, client.run(prompt, {
847
857
  timeoutMs: (0, common_1.round)(settings.timeoutMs),
848
- responseFormat: 'json'
858
+ threadOptions: {
859
+ model: settings.model,
860
+ sandboxMode: 'read-only',
861
+ skipGitRepoCheck: true,
862
+ networkAccessEnabled: false,
863
+ webSearchMode: 'disabled',
864
+ webSearchEnabled: false,
865
+ approvalPolicy: 'never'
866
+ }
849
867
  })];
850
868
  case 2:
851
- response = _a.sent();
852
- payload = parseRiskReviewPayload(response.content);
853
- return [2 /*return*/, normalizeRiskReview(input.operation, payload, response.model || settings.model, response.requestId || '')];
869
+ responseText = _a.sent();
870
+ payload = parseRiskReviewPayload(responseText);
871
+ return [2 /*return*/, normalizeRiskReview(input.operation, payload, settings.model, '')];
854
872
  case 3:
855
873
  err_1 = _a.sent();
856
874
  detail = (err_1 === null || err_1 === void 0 ? void 0 : err_1.message) ? String(err_1.message) : 'Unknown AI review error';
@@ -1147,7 +1165,7 @@ function resolveUsageClientId(idClientInput, idUser) {
1147
1165
  }
1148
1166
  function executeMongoExplorerAi(payload, context) {
1149
1167
  return __awaiter(this, void 0, void 0, function () {
1150
- var input, prompt, database, db, availableCollections, listed, selectedCollection, availableFields, settings, maxResults, client, response, parsed, action, collection, plan, removedRestrictedStages, optionsRaw, aggregateLimit, pipelineResult, aggregateOptions, aggregateRows, rows, query, options, findOptions, rows, total, _a, usage, idClient;
1168
+ var input, prompt, database, db, availableCollections, listed, selectedCollection, availableFields, settings, maxResults, client, messages, responseText, parsed, action, collection, plan, removedRestrictedStages, optionsRaw, aggregateLimit, pipelineResult, aggregateOptions, aggregateRows, rows, query, options, findOptions, rows, total, _a, usage, idClient;
1151
1169
  var _b;
1152
1170
  return __generator(this, function (_c) {
1153
1171
  switch (_c.label) {
@@ -1180,39 +1198,38 @@ function executeMongoExplorerAi(payload, context) {
1180
1198
  }
1181
1199
  settings = resolveMongoExplorerAiSettings();
1182
1200
  if (!settings.apiKey) {
1183
- throw new Error('OpenAI API key missing. Add OPENAI_API_KEY to server config.');
1201
+ throw new Error('AI API key missing. Add an AI API key to server config.');
1184
1202
  }
1185
1203
  maxResults = normalizeAiResultLimit(input.max_results, 100);
1186
- client = new openai_client_1.OpenAIClient({
1187
- apiKey: settings.apiKey,
1188
- baseUrl: settings.baseUrl,
1189
- model: settings.model,
1190
- fallbackModel: settings.fallbackModel,
1191
- temperature: 0.1,
1192
- maxTokens: (0, common_1.round)(settings.maxTokens),
1193
- maxRetries: (0, common_1.round)(settings.maxRetries),
1194
- retryDelayMs: (0, common_1.round)(settings.retryDelayMs),
1195
- responseFormat: 'json'
1196
- });
1197
- return [4 /*yield*/, client.chat([
1198
- { role: 'system', content: buildMongoExplorerAiSystemPrompt() },
1199
- {
1200
- role: 'user',
1201
- content: buildMongoExplorerAiUserPrompt({
1202
- prompt: prompt,
1203
- selectedCollection: selectedCollection,
1204
- availableCollections: availableCollections,
1205
- availableFields: availableFields,
1206
- maxResults: maxResults
1207
- })
1208
- }
1209
- ], {
1204
+ client = buildCodexClient(settings);
1205
+ messages = [
1206
+ { role: 'system', content: buildMongoExplorerAiSystemPrompt() },
1207
+ {
1208
+ role: 'user',
1209
+ content: buildMongoExplorerAiUserPrompt({
1210
+ prompt: prompt,
1211
+ selectedCollection: selectedCollection,
1212
+ availableCollections: availableCollections,
1213
+ availableFields: availableFields,
1214
+ maxResults: maxResults
1215
+ })
1216
+ }
1217
+ ];
1218
+ return [4 /*yield*/, client.run(buildCodexPrompt(messages[0].content, messages[1].content), {
1210
1219
  timeoutMs: (0, common_1.round)(settings.timeoutMs),
1211
- responseFormat: 'json'
1220
+ threadOptions: {
1221
+ model: settings.model,
1222
+ sandboxMode: 'read-only',
1223
+ skipGitRepoCheck: true,
1224
+ networkAccessEnabled: false,
1225
+ webSearchMode: 'disabled',
1226
+ webSearchEnabled: false,
1227
+ approvalPolicy: 'never'
1228
+ }
1212
1229
  })];
1213
1230
  case 3:
1214
- response = _c.sent();
1215
- parsed = parseAiPlanPayload(response.content);
1231
+ responseText = _c.sent();
1232
+ parsed = parseAiPlanPayload(responseText);
1216
1233
  action = normalizeAiAction((parsed === null || parsed === void 0 ? void 0 : parsed.action) || (Array.isArray(parsed === null || parsed === void 0 ? void 0 : parsed.pipeline) ? 'aggregate' : 'find'));
1217
1234
  collection = resolveCollectionFromList((parsed === null || parsed === void 0 ? void 0 : parsed.collection) || (parsed === null || parsed === void 0 ? void 0 : parsed.collection_name), availableCollections, selectedCollection || availableCollections[0]);
1218
1235
  if (!collection) {
@@ -1285,19 +1302,19 @@ function executeMongoExplorerAi(payload, context) {
1285
1302
  _c.label = 10;
1286
1303
  case 10:
1287
1304
  plan.notes = buildMongoExplorerAiNotes(parsed === null || parsed === void 0 ? void 0 : parsed.notes, plan.action, plan.collection, Array.isArray(plan.documents) ? plan.documents.length : 0, typeof plan.total === 'number' ? plan.total : null, removedRestrictedStages);
1288
- usage = response.usage || { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
1305
+ usage = estimateCodexUsage(messages, responseText, settings.model);
1289
1306
  return [4 /*yield*/, resolveUsageClientId(input.id_client, context === null || context === void 0 ? void 0 : context.id_user)];
1290
1307
  case 11:
1291
1308
  idClient = _c.sent();
1292
1309
  if (!(idClient && usage.totalTokens)) return [3 /*break*/, 13];
1293
1310
  return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)({
1294
1311
  id_client: idClient,
1295
- model: response.model || settings.model || 'unknown',
1312
+ model: settings.model || 'unknown',
1296
1313
  input_tokens: usage.inputTokens || 0,
1297
1314
  output_tokens: usage.outputTokens || 0,
1298
1315
  total_tokens: usage.totalTokens || 0,
1299
1316
  category: 'mongo-explorer-ai',
1300
- id_request: response.requestId || ''
1317
+ id_request: ''
1301
1318
  })];
1302
1319
  case 12:
1303
1320
  _c.sent();
@@ -1305,7 +1322,7 @@ function executeMongoExplorerAi(payload, context) {
1305
1322
  case 13: return [2 /*return*/, {
1306
1323
  notes: plan.notes,
1307
1324
  plan: plan,
1308
- model: response.model || settings.model,
1325
+ model: settings.model,
1309
1326
  usage: {
1310
1327
  input_tokens: usage.inputTokens || 0,
1311
1328
  output_tokens: usage.outputTokens || 0,