@resolveio/server-lib 22.3.151 → 22.3.153

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.
@@ -170,6 +170,7 @@ var promises_1 = require("timers/promises");
170
170
  var worker_threads_1 = require("worker_threads");
171
171
  var child_process_1 = require("child_process");
172
172
  var util_1 = require("util");
173
+ var crypto_1 = require("crypto");
173
174
  var mongodb_1 = require("mongodb");
174
175
  var simpl_schema_1 = require("simpl-schema");
175
176
  var resolveio_server_app_1 = require("../resolveio-server-app");
@@ -181,9 +182,11 @@ var common_1 = require("../util/common");
181
182
  var tokenizer_1 = require("../util/tokenizer");
182
183
  var codex_client_1 = require("../services/codex-client");
183
184
  var openai_usage_ledger_manager_1 = require("../managers/openai-usage-ledger.manager");
185
+ var ai_run_evidence_manager_1 = require("../managers/ai-run-evidence.manager");
184
186
  var assistant_core_heuristics_1 = require("../ai/assistant-core-heuristics");
185
187
  var resolveio_platform_intelligence_memory_1 = require("../ai/resolveio-platform-intelligence-memory");
186
188
  var ai_qa_policy_1 = require("../util/ai-qa-policy");
189
+ var ai_run_evidence_adapters_1 = require("../util/ai-run-evidence-adapters");
187
190
  var DEFAULT_MAX_FILE_MB = 50;
188
191
  var DEFAULT_MAX_TOTAL_MB = 100;
189
192
  var DEFAULT_MAX_ATTACHMENT_CHARS = 12000;
@@ -1361,7 +1364,7 @@ function loadAiTerminalMethods(methodManager) {
1361
1364
  }
1362
1365
  function executeAiTerminalRun(payload, context) {
1363
1366
  return __awaiter(this, void 0, void 0, function () {
1364
- var input, message, requestId, identityGuardrail, conversation_1, now_1, userMsg, assistantMsg, isSuperAdmin, guardrailsEnabled, guardrail, conversation_2, now_2, userMsg, assistantMsg, conversation, now, attachments, attachmentData, config, systemPrompt, userPromptTemplate, userPrompt, historyLimit, history, _a, messages, codexModel, codexFallbackModels, codexSettings, client, responseText, usage, idClient, userDoc, assistantDoc, insertResult;
1367
+ var input, message, requestId, identityGuardrail, conversation_1, now_1, userMsg, assistantMsg, isSuperAdmin, guardrailsEnabled, guardrail, conversation_2, now_2, userMsg, assistantMsg, conversation, now, attachments, attachmentData, config, systemPrompt, userPromptTemplate, userPrompt, historyLimit, history, _a, messages, codexModel, codexFallbackModels, codexSettings, client, responseText, usage, idClient, usageLedgerEntry, userDoc, assistantDoc, userInsertResult, insertResult, assistantMessageId, userMessageId;
1365
1368
  return __generator(this, function (_b) {
1366
1369
  switch (_b.label) {
1367
1370
  case 0:
@@ -1510,24 +1513,23 @@ function executeAiTerminalRun(payload, context) {
1510
1513
  return [4 /*yield*/, resolveClientId(conversation, input.id_client, context === null || context === void 0 ? void 0 : context.id_user)];
1511
1514
  case 18:
1512
1515
  idClient = _b.sent();
1513
- return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)({
1514
- id_client: idClient || '',
1515
- model: codexModel || 'unknown',
1516
- input_tokens: usage.inputTokens,
1517
- output_tokens: usage.outputTokens,
1518
- total_tokens: usage.totalTokens,
1519
- category: 'ai-terminal',
1520
- id_conversation: conversation._id,
1521
- usage_source: 'ai_assistant',
1522
- usage_surface: 'assistant',
1523
- usage_phase: 'chat',
1524
- cost_basis: 'estimated_tokens',
1525
- id_app: String((conversation === null || conversation === void 0 ? void 0 : conversation.id_app) || ''),
1526
- metadata: {
1527
- conversationId: conversation._id,
1528
- requestId: input.request_id || ''
1529
- }
1530
- })];
1516
+ usageLedgerEntry = buildAssistantAIRunUsageLedgerEntry({
1517
+ idClient: idClient || '',
1518
+ model: codexModel || 'unknown',
1519
+ inputTokens: usage.inputTokens,
1520
+ outputTokens: usage.outputTokens,
1521
+ totalTokens: usage.totalTokens,
1522
+ category: 'ai-terminal',
1523
+ conversationId: conversation._id,
1524
+ requestId: input.request_id || '',
1525
+ usagePhase: 'chat',
1526
+ idApp: String((conversation === null || conversation === void 0 ? void 0 : conversation.id_app) || ''),
1527
+ metadata: {
1528
+ conversationId: conversation._id,
1529
+ requestId: input.request_id || ''
1530
+ }
1531
+ });
1532
+ return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)(usageLedgerEntry)];
1531
1533
  case 19:
1532
1534
  _b.sent();
1533
1535
  userDoc = {
@@ -1555,19 +1557,33 @@ function executeAiTerminalRun(payload, context) {
1555
1557
  };
1556
1558
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(userDoc)];
1557
1559
  case 20:
1558
- _b.sent();
1560
+ userInsertResult = _b.sent();
1559
1561
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(assistantDoc)];
1560
1562
  case 21:
1561
1563
  insertResult = _b.sent();
1562
- return [4 /*yield*/, touchConversation(conversation._id, now, insertResult._id)];
1564
+ assistantMessageId = String((insertResult === null || insertResult === void 0 ? void 0 : insertResult._id) || (insertResult === null || insertResult === void 0 ? void 0 : insertResult.insertedId) || '');
1565
+ userMessageId = String((userInsertResult === null || userInsertResult === void 0 ? void 0 : userInsertResult._id) || (userInsertResult === null || userInsertResult === void 0 ? void 0 : userInsertResult.insertedId) || '');
1566
+ return [4 /*yield*/, touchConversation(conversation._id, now, assistantMessageId)];
1563
1567
  case 22:
1564
1568
  _b.sent();
1565
- if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 24];
1566
- return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
1569
+ return [4 /*yield*/, recordAssistantAnswerAIRun({
1570
+ runId: buildAssistantAIRunId('chat', [conversation._id, assistantMessageId || input.request_id]),
1571
+ requestId: input.request_id,
1572
+ messageId: assistantMessageId,
1573
+ conversation: conversation,
1574
+ userMessage: __assign(__assign({}, userDoc), { _id: userMessageId || undefined }),
1575
+ assistantMessage: __assign(__assign({}, assistantDoc), { _id: assistantMessageId || undefined }),
1576
+ usageLedgerEntry: usageLedgerEntry,
1577
+ now: now
1578
+ })];
1567
1579
  case 23:
1568
1580
  _b.sent();
1569
- _b.label = 24;
1570
- case 24: return [2 /*return*/, {
1581
+ if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 25];
1582
+ return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
1583
+ case 24:
1584
+ _b.sent();
1585
+ _b.label = 25;
1586
+ case 25: return [2 /*return*/, {
1571
1587
  conversation: conversation,
1572
1588
  message: assistantDoc,
1573
1589
  usage: assistantDoc.usage
@@ -1578,7 +1594,7 @@ function executeAiTerminalRun(payload, context) {
1578
1594
  }
1579
1595
  function executeAiFormPatch(payload, context) {
1580
1596
  return __awaiter(this, void 0, void 0, function () {
1581
- var input, message, allowedFields, guardrail, systemPrompt, userPrompt, messages, config, codexModel, codexFallbackModels, codexSettings, client, responseText, usage, idClient, parsed;
1597
+ var input, message, allowedFields, guardrail, systemPrompt, userPrompt, messages, config, codexModel, codexFallbackModels, codexSettings, client, responseText, usage, idClient, usageLedgerEntry, parsed, formRunId;
1582
1598
  var _a;
1583
1599
  return __generator(this, function (_b) {
1584
1600
  switch (_b.label) {
@@ -1628,27 +1644,62 @@ function executeAiFormPatch(payload, context) {
1628
1644
  return [4 /*yield*/, resolveClientIdFromConfig(input.id_client, context === null || context === void 0 ? void 0 : context.id_user)];
1629
1645
  case 2:
1630
1646
  idClient = _b.sent();
1631
- return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)({
1632
- id_client: idClient || '',
1633
- model: codexModel || 'unknown',
1634
- input_tokens: usage.inputTokens,
1635
- output_tokens: usage.outputTokens,
1636
- total_tokens: usage.totalTokens,
1637
- category: 'ai-form',
1638
- usage_source: 'ai_assistant',
1639
- usage_surface: 'assistant',
1640
- usage_phase: 'form_patch',
1641
- cost_basis: 'estimated_tokens',
1642
- metadata: {
1643
- route: input.route || ''
1644
- }
1645
- })];
1647
+ usageLedgerEntry = buildAssistantAIRunUsageLedgerEntry({
1648
+ idClient: idClient || '',
1649
+ model: codexModel || 'unknown',
1650
+ inputTokens: usage.inputTokens,
1651
+ outputTokens: usage.outputTokens,
1652
+ totalTokens: usage.totalTokens,
1653
+ category: 'ai-form',
1654
+ requestId: (0, crypto_1.createHash)('sha1').update("".concat(input.route || '', ":").concat(message, ":").concat(responseText)).digest('hex').slice(0, 24),
1655
+ usagePhase: 'form_patch',
1656
+ idApp: input.id_app || '',
1657
+ metadata: {
1658
+ route: input.route || ''
1659
+ }
1660
+ });
1661
+ return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)(usageLedgerEntry)];
1646
1662
  case 3:
1647
1663
  _b.sent();
1648
1664
  parsed = parseJsonObject(responseText);
1649
1665
  if (!parsed || typeof parsed !== 'object') {
1650
1666
  throw new Error('AI form patch response was not valid JSON.');
1651
1667
  }
1668
+ formRunId = buildAssistantAIRunId('form_patch', [input.route, usageLedgerEntry.id_request]);
1669
+ return [4 /*yield*/, recordAssistantAnswerAIRun({
1670
+ runId: formRunId,
1671
+ requestId: String(usageLedgerEntry.id_request || ''),
1672
+ messageId: formRunId,
1673
+ conversation: {
1674
+ _id: "ai-form:".concat(usageLedgerEntry.id_request),
1675
+ id_app: input.id_app || '',
1676
+ title: input.route ? "AI form patch: ".concat(input.route) : 'AI form patch',
1677
+ status: 'complete',
1678
+ updatedAt: new Date()
1679
+ },
1680
+ userMessage: {
1681
+ _id: "".concat(formRunId, ":user"),
1682
+ role: 'user',
1683
+ content: message,
1684
+ createdAt: new Date()
1685
+ },
1686
+ assistantMessage: {
1687
+ _id: "".concat(formRunId, ":assistant"),
1688
+ role: 'assistant',
1689
+ content: responseText,
1690
+ usage: {
1691
+ model: codexModel || 'unknown',
1692
+ input_tokens: usage.inputTokens,
1693
+ output_tokens: usage.outputTokens,
1694
+ total_tokens: usage.totalTokens
1695
+ },
1696
+ createdAt: new Date()
1697
+ },
1698
+ usageLedgerEntry: usageLedgerEntry,
1699
+ now: new Date()
1700
+ })];
1701
+ case 4:
1702
+ _b.sent();
1652
1703
  return [2 /*return*/, {
1653
1704
  patch: (_a = parsed.patch) !== null && _a !== void 0 ? _a : parsed,
1654
1705
  notes: normalizeOptionalString(parsed.notes) || undefined,
@@ -1665,7 +1716,7 @@ function executeAiFormPatch(payload, context) {
1665
1716
  }
1666
1717
  function executeAiAssistantCodexRun(payload, context) {
1667
1718
  return __awaiter(this, void 0, void 0, function () {
1668
- var input, message, aiWorkerDebug, requestId, codexModel, codexFallbackModels, user, isSuperAdmin, guardrail, conversation_3, now_3, userMsg, assistantMsg, canViewDebug, hasInvoiceAccess, customerId, conversation, now, attachments, navigationFastPath, userMsg, assistantMsg, assistantInsert, assistantMessageId_1, changeHistoryFastPath, changeHistoryFastPathBypassedReason, userMsg, assistantMsg, assistantInsert, assistantMessageId_2, userMsg, assistantMsg, assistantInsert, assistantMessageId_3, attachmentData, historyLines, recentToolError, userDoc, initialProgress, assistantDoc, insertResult, assistantMessageId;
1719
+ var input, message, aiWorkerDebug, requestId, codexModel, codexFallbackModels, user, isSuperAdmin, guardrail, conversation_3, now_3, userMsg, assistantMsg, canViewDebug, hasInvoiceAccess, customerId, conversation, now, attachments, navigationFastPath, userMsg, assistantMsg, assistantInsert, assistantMessageId_1, changeHistoryFastPath, changeHistoryFastPathBypassedReason, userMsg, assistantMsg, assistantInsert, assistantMessageId_2, userMsg, assistantMsg, assistantInsert, assistantMessageId_3, attachmentData, historyLines, recentToolError, userDoc, initialProgress, assistantDoc, userInsertResult, userMessageId, insertResult, assistantMessageId;
1669
1720
  var _this = this;
1670
1721
  var _a, _b, _c;
1671
1722
  return __generator(this, function (_d) {
@@ -1911,16 +1962,17 @@ function executeAiAssistantCodexRun(payload, context) {
1911
1962
  };
1912
1963
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(userDoc)];
1913
1964
  case 22:
1914
- _d.sent();
1965
+ userInsertResult = _d.sent();
1966
+ userMessageId = (userInsertResult === null || userInsertResult === void 0 ? void 0 : userInsertResult._id) || (userInsertResult === null || userInsertResult === void 0 ? void 0 : userInsertResult.insertedId);
1915
1967
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(assistantDoc)];
1916
1968
  case 23:
1917
1969
  insertResult = _d.sent();
1918
1970
  assistantMessageId = (insertResult === null || insertResult === void 0 ? void 0 : insertResult._id) || (insertResult === null || insertResult === void 0 ? void 0 : insertResult.insertedId);
1919
1971
  enqueueAssistantCodexRun(function () { return __awaiter(_this, void 0, void 0, function () {
1920
- var runStart, fastModeEnabled, alwaysAllowProbeEnabled, plannerEnabled, runBudgetMs, assistantMongoMaxTimeMs, assistantSystemPrompt, runDeadlineMs, steps, recordStep, requestClassification, dataQuestion, progressTracker, streamProgress, remainingRunBudgetMs, hasRunBudget, applyCodexStageBudget, assistantContent, toolResult, assistantDebug, directiveSource, lastDirective, heuristicDirectivePrecomputed, usedDeterministicHeuristicFastPath, requestedTimeGrain, requestedBreakdownDimensions, enforceDatedDirective, enforceGroupedDirective, datedDirectiveRetryUsed, datedDirectiveResolved, toolResponseDebug, toolError, toolTelemetry, termHints, collectionHints, fieldHints, schemaHints, methodHints, publicationHints, collectionTokenization, collectionRanking, collectionSelection, collectionOverride, collectionNames, plannerUsed, plannerSkipReason, plannerOutput, plannerRaw, timingBreakdown, codexUsage, accumulateCodexUsage, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, baseWeights, expandedWeights, dbName, db, surfaceHints, _a, allowedRoutes, rankedAllowedRoutes, routeHints, appCollectionHints, rankedCollectionHints, rankedCollections, hintCollections, schemaHintCollections, assistantContext, hasDeterministicHeuristicFastPath, prompt_1, workspaceRoot, codexConfig, runOptions, plannerRunOptions, shouldRunPlanner, plannerBudgetAvailable, plannerPrompt, plannerStart, _b, preferListDirective, directiveStyleHint, directivePromptMode, responseText, directiveText, directive, heuristicDirectiveFastPath, directivePrompt, directiveStart, forcedDirective, _c, initialStart, extractedDirective, error_2, directivePrompt, forcedStart, forcedDirective, _d, strictDirectivePrompt, strictStart, strictDirectiveText, strictDirective, strictDirectiveIsDated, shouldUseStrictDirective, _e, guardDirectivePrompt, guardStart, guardDirectiveText, guardDirective, _f, groupedDirectivePrompt, groupedStart, groupedDirectiveText, groupedDirective, _g, heuristicDirective, requestedCollection, allowCollectionOverride, cleanedResponseText, deniedModuleByIntent, permissionLabel, effectiveDirective, effectiveDirectiveMetadata, directiveAcknowledgementText, directiveProgressMessages, deterministicDataIntentDirective, rankedCollections_1, directiveHintsBase_1, buildToolRequestForDirective, executionDirective, probeFieldHints, aggregateProbeDisabled, probeEnabled, probeBudgetAllowed, probeDirective, probeRequest, probeStart, probeResponse, _h, probeDurationMs, probeRowCount, probeRewrite, probeError_1, probeDurationMs, probeErrorMessage, toolRequest, requestedToolCollection, toolStart, toolResponse, _j, toolDurationMs, toolPayload, resolvedToolCollection, zeroRowResult, followupCodexEnabled, skipFollowupCodex, followupPrompt, followupStart, followupText, _k, error_3, errorMessage, existingFinal, error_4, runBudgetExceeded, includeToolExecutionTelemetry, toolExecutionTelemetry, finishedAt, finalNow, finishedAt, codexMs, draftingMs, finalMetadata, finalUsage, usageClientId, usageError_1, finalAssistantDoc, setPayload, finalizeError_1, failedAt, fallbackContent, failureMetadata, persistError_1, _l;
1921
- var _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21;
1922
- return __generator(this, function (_22) {
1923
- switch (_22.label) {
1972
+ var runStart, fastModeEnabled, alwaysAllowProbeEnabled, plannerEnabled, runBudgetMs, assistantMongoMaxTimeMs, assistantSystemPrompt, runDeadlineMs, steps, recordStep, requestClassification, dataQuestion, progressTracker, streamProgress, remainingRunBudgetMs, hasRunBudget, applyCodexStageBudget, assistantContent, toolResult, assistantDebug, directiveSource, lastDirective, heuristicDirectivePrecomputed, usedDeterministicHeuristicFastPath, requestedTimeGrain, requestedBreakdownDimensions, enforceDatedDirective, enforceGroupedDirective, datedDirectiveRetryUsed, datedDirectiveResolved, toolResponseDebug, toolError, toolTelemetry, termHints, collectionHints, fieldHints, schemaHints, methodHints, publicationHints, collectionTokenization, collectionRanking, collectionSelection, collectionOverride, collectionNames, plannerUsed, plannerSkipReason, plannerOutput, plannerRaw, timingBreakdown, codexUsage, accumulateCodexUsage, contextRoute, contextMode, hintSeed, termExpansion, hintText, baseTokens, expandedTokens, baseWeights, expandedWeights, dbName, db, surfaceHints, _a, allowedRoutes, rankedAllowedRoutes, routeHints, appCollectionHints, rankedCollectionHints, rankedCollections, hintCollections, schemaHintCollections, assistantContext, hasDeterministicHeuristicFastPath, prompt_1, workspaceRoot, codexConfig, runOptions, plannerRunOptions, shouldRunPlanner, plannerBudgetAvailable, plannerPrompt, plannerStart, _b, preferListDirective, directiveStyleHint, directivePromptMode, responseText, directiveText, directive, heuristicDirectiveFastPath, directivePrompt, directiveStart, forcedDirective, _c, initialStart, extractedDirective, error_2, directivePrompt, forcedStart, forcedDirective, _d, strictDirectivePrompt, strictStart, strictDirectiveText, strictDirective, strictDirectiveIsDated, shouldUseStrictDirective, _e, guardDirectivePrompt, guardStart, guardDirectiveText, guardDirective, _f, groupedDirectivePrompt, groupedStart, groupedDirectiveText, groupedDirective, _g, heuristicDirective, requestedCollection, allowCollectionOverride, cleanedResponseText, deniedModuleByIntent, permissionLabel, effectiveDirective, effectiveDirectiveMetadata, directiveAcknowledgementText, directiveProgressMessages, deterministicDataIntentDirective, rankedCollections_1, directiveHintsBase_1, buildToolRequestForDirective, executionDirective, probeFieldHints, aggregateProbeDisabled, probeEnabled, probeBudgetAllowed, probeDirective, probeRequest, probeStart, probeResponse, _h, probeDurationMs, probeRowCount, probeRewrite, probeError_1, probeDurationMs, probeErrorMessage, toolRequest, requestedToolCollection, toolStart, toolResponse, _j, toolDurationMs, toolPayload, resolvedToolCollection, zeroRowResult, followupCodexEnabled, skipFollowupCodex, followupPrompt, followupStart, followupText, _k, error_3, errorMessage, existingFinal, error_4, runBudgetExceeded, includeToolExecutionTelemetry, toolExecutionTelemetry, finishedAt, finalNow, finishedAt, codexMs, draftingMs, finalMetadata, finalUsage, finalUsageLedgerEntry, usageClientId, usageError_1, finalAssistantDoc, setPayload, finalizeError_1, failedAt, fallbackContent, failureMetadata, persistError_1, _l;
1973
+ var _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22;
1974
+ return __generator(this, function (_23) {
1975
+ switch (_23.label) {
1924
1976
  case 0:
1925
1977
  runStart = Date.now();
1926
1978
  fastModeEnabled = resolveAssistantFastModeEnabled(input.config);
@@ -2061,9 +2113,9 @@ function executeAiAssistantCodexRun(payload, context) {
2061
2113
  source: requestClassification.source,
2062
2114
  dataQuestion: dataQuestion
2063
2115
  });
2064
- _22.label = 1;
2116
+ _23.label = 1;
2065
2117
  case 1:
2066
- _22.trys.push([1, 68, 69, 70]);
2118
+ _23.trys.push([1, 68, 69, 70]);
2067
2119
  hintSeed = [message, contextRoute].filter(Boolean).join(' ');
2068
2120
  termExpansion = expandAssistantTermSynonyms(hintSeed);
2069
2121
  hintText = termExpansion.expanded || hintSeed;
@@ -2084,19 +2136,19 @@ function executeAiAssistantCodexRun(payload, context) {
2084
2136
  recordStep('Planning: term expansion', {
2085
2137
  termMatches: termExpansion.matches.length ? termExpansion.matches : undefined
2086
2138
  });
2087
- _22.label = 2;
2139
+ _23.label = 2;
2088
2140
  case 2:
2089
- _22.trys.push([2, 5, , 6]);
2141
+ _23.trys.push([2, 5, , 6]);
2090
2142
  dbName = resolveAssistantDatabaseName(undefined, input.mongo);
2091
2143
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
2092
2144
  return [4 /*yield*/, listAssistantCollections(db, dbName)];
2093
2145
  case 3:
2094
- collectionNames = _22.sent();
2146
+ collectionNames = _23.sent();
2095
2147
  collectionHints = resolveCollectionHintsFromTokens(expandedTokens, collectionNames, 5);
2096
2148
  collectionRanking = buildCollectionRankingDebugFromTokens(expandedTokens, collectionNames, 8);
2097
2149
  return [4 /*yield*/, resolveAssistantSurfaceHints(hintSeed, contextRoute, collectionNames)];
2098
2150
  case 4:
2099
- surfaceHints = _22.sent();
2151
+ surfaceHints = _23.sent();
2100
2152
  methodHints = surfaceHints.methodHints;
2101
2153
  publicationHints = surfaceHints.publicationHints;
2102
2154
  if (surfaceHints.collectionHints.length) {
@@ -2104,7 +2156,7 @@ function executeAiAssistantCodexRun(payload, context) {
2104
2156
  }
2105
2157
  return [3 /*break*/, 6];
2106
2158
  case 5:
2107
- _a = _22.sent();
2159
+ _a = _23.sent();
2108
2160
  collectionHints = [];
2109
2161
  collectionRanking = collectionRanking || ((collectionTokenization === null || collectionTokenization === void 0 ? void 0 : collectionTokenization.expandedTokens)
2110
2162
  ? buildCollectionRankingDebugFromTokens(collectionTokenization.expandedTokens || [], [], 0)
@@ -2184,7 +2236,7 @@ function executeAiAssistantCodexRun(payload, context) {
2184
2236
  prompt_1 = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, assistantSystemPrompt);
2185
2237
  return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
2186
2238
  case 7:
2187
- workspaceRoot = _22.sent();
2239
+ workspaceRoot = _23.sent();
2188
2240
  codexConfig = resolveCodexSettings({
2189
2241
  model: codexModel,
2190
2242
  fallbackModels: codexFallbackModels
@@ -2233,20 +2285,20 @@ function executeAiAssistantCodexRun(payload, context) {
2233
2285
  publicationHints: publicationHints,
2234
2286
  inputClientId: input.id_client
2235
2287
  });
2236
- _22.label = 8;
2288
+ _23.label = 8;
2237
2289
  case 8:
2238
- _22.trys.push([8, 10, , 11]);
2290
+ _23.trys.push([8, 10, , 11]);
2239
2291
  plannerStart = Date.now();
2240
2292
  return [4 /*yield*/, runCodexInWorkerThread(plannerPrompt, applyCodexStageBudget(plannerRunOptions), codexConfig, streamProgress)];
2241
2293
  case 9:
2242
- plannerRaw = _22.sent();
2294
+ plannerRaw = _23.sent();
2243
2295
  accumulateCodexUsage(plannerPrompt, plannerRaw);
2244
2296
  timingBreakdown.plannerMs = Date.now() - plannerStart;
2245
2297
  plannerOutput = parseJsonObject(plannerRaw);
2246
2298
  recordStep('Planning: planner result', { parsed: !!plannerOutput });
2247
2299
  return [3 /*break*/, 11];
2248
2300
  case 10:
2249
- _b = _22.sent();
2301
+ _b = _23.sent();
2250
2302
  recordStep('Planning: planner result', { parsed: false });
2251
2303
  return [3 /*break*/, 11];
2252
2304
  case 11: return [3 /*break*/, 13];
@@ -2266,7 +2318,7 @@ function executeAiAssistantCodexRun(payload, context) {
2266
2318
  }
2267
2319
  recordStep('Planning: planner skipped', { reason: plannerSkipReason });
2268
2320
  }
2269
- _22.label = 13;
2321
+ _23.label = 13;
2270
2322
  case 13:
2271
2323
  requestClassification = classifyAssistantRequestType(message, plannerOutput || undefined);
2272
2324
  dataQuestion = requestClassification.dataQuestion;
@@ -2322,13 +2374,13 @@ function executeAiAssistantCodexRun(payload, context) {
2322
2374
  recordStep('Directive: determine tool', { type: 'data-question' });
2323
2375
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, directiveStyleHint, directivePromptMode, assistantSystemPrompt);
2324
2376
  if (!hasRunBudget('Directive: determine tool')) return [3 /*break*/, 17];
2325
- _22.label = 14;
2377
+ _23.label = 14;
2326
2378
  case 14:
2327
- _22.trys.push([14, 16, , 17]);
2379
+ _23.trys.push([14, 16, , 17]);
2328
2380
  directiveStart = Date.now();
2329
2381
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, applyCodexStageBudget(runOptions), codexConfig, streamProgress)];
2330
2382
  case 15:
2331
- directiveText = _22.sent();
2383
+ directiveText = _23.sent();
2332
2384
  accumulateCodexUsage(directivePrompt, directiveText);
2333
2385
  timingBreakdown.directiveMs = Date.now() - directiveStart;
2334
2386
  forcedDirective = extractAssistantMongoDirective(directiveText);
@@ -2346,19 +2398,19 @@ function executeAiAssistantCodexRun(payload, context) {
2346
2398
  }
2347
2399
  return [3 /*break*/, 17];
2348
2400
  case 16:
2349
- _c = _22.sent();
2401
+ _c = _23.sent();
2350
2402
  return [3 /*break*/, 17];
2351
2403
  case 17:
2352
2404
  if (!(!directive && !dataQuestion)) return [3 /*break*/, 21];
2353
2405
  recordStep('Response: draft initial answer', { mode: 'full' });
2354
2406
  if (!hasRunBudget('Response: initial draft')) return [3 /*break*/, 21];
2355
- _22.label = 18;
2407
+ _23.label = 18;
2356
2408
  case 18:
2357
- _22.trys.push([18, 20, , 21]);
2409
+ _23.trys.push([18, 20, , 21]);
2358
2410
  initialStart = Date.now();
2359
2411
  return [4 /*yield*/, runCodexInWorkerThread(prompt_1, applyCodexStageBudget(runOptions), codexConfig, streamProgress)];
2360
2412
  case 19:
2361
- responseText = _22.sent();
2413
+ responseText = _23.sent();
2362
2414
  accumulateCodexUsage(prompt_1, responseText);
2363
2415
  timingBreakdown.initialResponseMs = Date.now() - initialStart;
2364
2416
  extractedDirective = extractAssistantMongoDirective(responseText);
@@ -2376,7 +2428,7 @@ function executeAiAssistantCodexRun(payload, context) {
2376
2428
  }
2377
2429
  return [3 /*break*/, 21];
2378
2430
  case 20:
2379
- error_2 = _22.sent();
2431
+ error_2 = _23.sent();
2380
2432
  recordStep('Response: initial draft failed', {
2381
2433
  message: normalizeOptionalString(error_2 === null || error_2 === void 0 ? void 0 : error_2.message) || 'Unknown error'
2382
2434
  });
@@ -2386,13 +2438,13 @@ function executeAiAssistantCodexRun(payload, context) {
2386
2438
  recordStep('Directive: forced retry', { mode: 'directive-only' });
2387
2439
  directivePrompt = buildAssistantCodexDirectivePrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, directiveStyleHint, directivePromptMode, assistantSystemPrompt);
2388
2440
  if (!hasRunBudget('Directive: forced retry')) return [3 /*break*/, 25];
2389
- _22.label = 22;
2441
+ _23.label = 22;
2390
2442
  case 22:
2391
- _22.trys.push([22, 24, , 25]);
2443
+ _23.trys.push([22, 24, , 25]);
2392
2444
  forcedStart = Date.now();
2393
2445
  return [4 /*yield*/, runCodexInWorkerThread(directivePrompt, applyCodexStageBudget(runOptions), codexConfig, streamProgress)];
2394
2446
  case 23:
2395
- directiveText = _22.sent();
2447
+ directiveText = _23.sent();
2396
2448
  accumulateCodexUsage(directivePrompt, directiveText);
2397
2449
  timingBreakdown.forcedDirectiveMs = Date.now() - forcedStart;
2398
2450
  forcedDirective = extractAssistantMongoDirective(directiveText);
@@ -2410,7 +2462,7 @@ function executeAiAssistantCodexRun(payload, context) {
2410
2462
  }
2411
2463
  return [3 /*break*/, 25];
2412
2464
  case 24:
2413
- _d = _22.sent();
2465
+ _d = _23.sent();
2414
2466
  return [3 /*break*/, 25];
2415
2467
  case 25:
2416
2468
  if (!(directive
@@ -2429,13 +2481,13 @@ function executeAiAssistantCodexRun(payload, context) {
2429
2481
  strict: true
2430
2482
  }), 'aggregate_only', assistantSystemPrompt);
2431
2483
  if (!hasRunBudget('Directive: dated retry')) return [3 /*break*/, 29];
2432
- _22.label = 26;
2484
+ _23.label = 26;
2433
2485
  case 26:
2434
- _22.trys.push([26, 28, , 29]);
2486
+ _23.trys.push([26, 28, , 29]);
2435
2487
  strictStart = Date.now();
2436
2488
  return [4 /*yield*/, runCodexInWorkerThread(strictDirectivePrompt, applyCodexStageBudget(runOptions), codexConfig, streamProgress)];
2437
2489
  case 27:
2438
- strictDirectiveText = _22.sent();
2490
+ strictDirectiveText = _23.sent();
2439
2491
  accumulateCodexUsage(strictDirectivePrompt, strictDirectiveText);
2440
2492
  timingBreakdown.forcedDirectiveMs += Date.now() - strictStart;
2441
2493
  strictDirective = extractAssistantMongoDirective(strictDirectiveText);
@@ -2458,7 +2510,7 @@ function executeAiAssistantCodexRun(payload, context) {
2458
2510
  }
2459
2511
  return [3 /*break*/, 29];
2460
2512
  case 28:
2461
- _e = _22.sent();
2513
+ _e = _23.sent();
2462
2514
  return [3 /*break*/, 29];
2463
2515
  case 29:
2464
2516
  if (!(directive
@@ -2477,13 +2529,13 @@ function executeAiAssistantCodexRun(payload, context) {
2477
2529
  strict: true
2478
2530
  }), 'aggregate_only', assistantSystemPrompt);
2479
2531
  if (!hasRunBudget('Directive: dated guard retry')) return [3 /*break*/, 33];
2480
- _22.label = 30;
2532
+ _23.label = 30;
2481
2533
  case 30:
2482
- _22.trys.push([30, 32, , 33]);
2534
+ _23.trys.push([30, 32, , 33]);
2483
2535
  guardStart = Date.now();
2484
2536
  return [4 /*yield*/, runCodexInWorkerThread(guardDirectivePrompt, applyCodexStageBudget(runOptions), codexConfig, streamProgress)];
2485
2537
  case 31:
2486
- guardDirectiveText = _22.sent();
2538
+ guardDirectiveText = _23.sent();
2487
2539
  accumulateCodexUsage(guardDirectivePrompt, guardDirectiveText);
2488
2540
  timingBreakdown.forcedDirectiveMs += Date.now() - guardStart;
2489
2541
  guardDirective = extractAssistantMongoDirective(guardDirectiveText);
@@ -2504,7 +2556,7 @@ function executeAiAssistantCodexRun(payload, context) {
2504
2556
  }
2505
2557
  return [3 /*break*/, 33];
2506
2558
  case 32:
2507
- _f = _22.sent();
2559
+ _f = _23.sent();
2508
2560
  return [3 /*break*/, 33];
2509
2561
  case 33:
2510
2562
  if (!(directive
@@ -2523,13 +2575,13 @@ function executeAiAssistantCodexRun(payload, context) {
2523
2575
  strict: true
2524
2576
  }), 'aggregate_only', assistantSystemPrompt);
2525
2577
  if (!hasRunBudget('Directive: grouped guard retry')) return [3 /*break*/, 37];
2526
- _22.label = 34;
2578
+ _23.label = 34;
2527
2579
  case 34:
2528
- _22.trys.push([34, 36, , 37]);
2580
+ _23.trys.push([34, 36, , 37]);
2529
2581
  groupedStart = Date.now();
2530
2582
  return [4 /*yield*/, runCodexInWorkerThread(groupedDirectivePrompt, applyCodexStageBudget(runOptions), codexConfig, streamProgress)];
2531
2583
  case 35:
2532
- groupedDirectiveText = _22.sent();
2584
+ groupedDirectiveText = _23.sent();
2533
2585
  accumulateCodexUsage(groupedDirectivePrompt, groupedDirectiveText);
2534
2586
  timingBreakdown.forcedDirectiveMs += Date.now() - groupedStart;
2535
2587
  groupedDirective = extractAssistantMongoDirective(groupedDirectiveText);
@@ -2553,7 +2605,7 @@ function executeAiAssistantCodexRun(payload, context) {
2553
2605
  }
2554
2606
  return [3 /*break*/, 37];
2555
2607
  case 36:
2556
- _g = _22.sent();
2608
+ _g = _23.sent();
2557
2609
  return [3 /*break*/, 37];
2558
2610
  case 37:
2559
2611
  if (!directive && dataQuestion) {
@@ -2674,9 +2726,9 @@ function executeAiAssistantCodexRun(payload, context) {
2674
2726
  directiveProgressMessages.slice(0, 2).forEach(function (messageText) { return progressTracker.push(messageText); });
2675
2727
  executionDirective = effectiveDirective;
2676
2728
  probeFieldHints = [];
2677
- _22.label = 39;
2729
+ _23.label = 39;
2678
2730
  case 39:
2679
- _22.trys.push([39, 64, , 65]);
2731
+ _23.trys.push([39, 64, , 65]);
2680
2732
  if (!(!alwaysAllowProbeEnabled && !hasRunBudget('Grabbing Data', AI_ASSISTANT_MONGO_MIN_STAGE_BUDGET_MS))) return [3 /*break*/, 40];
2681
2733
  assistantContent = buildAssistantRunBudgetExceededMessage();
2682
2734
  toolTelemetry.final = {
@@ -2708,18 +2760,18 @@ function executeAiAssistantCodexRun(payload, context) {
2708
2760
  attempted: true
2709
2761
  };
2710
2762
  probeStart = Date.now();
2711
- _22.label = 41;
2763
+ _23.label = 41;
2712
2764
  case 41:
2713
- _22.trys.push([41, 46, , 47]);
2765
+ _23.trys.push([41, 46, , 47]);
2714
2766
  if (!(probeDirective.type === 'aggregate')) return [3 /*break*/, 43];
2715
2767
  return [4 /*yield*/, executeAiAssistantReportBuilderAggregate(probeRequest, context)];
2716
2768
  case 42:
2717
- _h = _22.sent();
2769
+ _h = _23.sent();
2718
2770
  return [3 /*break*/, 45];
2719
2771
  case 43: return [4 /*yield*/, executeAiAssistantReportBuilderRead(probeRequest, context)];
2720
2772
  case 44:
2721
- _h = _22.sent();
2722
- _22.label = 45;
2773
+ _h = _23.sent();
2774
+ _23.label = 45;
2723
2775
  case 45:
2724
2776
  probeResponse = _h;
2725
2777
  probeDurationMs = Date.now() - probeStart;
@@ -2751,7 +2803,7 @@ function executeAiAssistantCodexRun(payload, context) {
2751
2803
  }
2752
2804
  return [3 /*break*/, 47];
2753
2805
  case 46:
2754
- probeError_1 = _22.sent();
2806
+ probeError_1 = _23.sent();
2755
2807
  probeDurationMs = Date.now() - probeStart;
2756
2808
  probeErrorMessage = normalizeOptionalString(probeError_1 === null || probeError_1 === void 0 ? void 0 : probeError_1.message) || 'Unknown error';
2757
2809
  toolTelemetry.probe = {
@@ -2770,7 +2822,7 @@ function executeAiAssistantCodexRun(payload, context) {
2770
2822
  attempted: false,
2771
2823
  skippedReason: 'probe_directive_missing_payload'
2772
2824
  };
2773
- _22.label = 49;
2825
+ _23.label = 49;
2774
2826
  case 49: return [3 /*break*/, 51];
2775
2827
  case 50:
2776
2828
  if (probeEnabled) {
@@ -2785,7 +2837,7 @@ function executeAiAssistantCodexRun(payload, context) {
2785
2837
  skippedReason: 'aggregate_probe_disabled'
2786
2838
  };
2787
2839
  }
2788
- _22.label = 51;
2840
+ _23.label = 51;
2789
2841
  case 51:
2790
2842
  if (!(!alwaysAllowProbeEnabled && !hasRunBudget('Grabbing Data: final', AI_ASSISTANT_MONGO_MIN_STAGE_BUDGET_MS))) return [3 /*break*/, 52];
2791
2843
  assistantContent = buildAssistantRunBudgetExceededMessage();
@@ -2815,12 +2867,12 @@ function executeAiAssistantCodexRun(payload, context) {
2815
2867
  if (!(executionDirective.type === 'aggregate')) return [3 /*break*/, 54];
2816
2868
  return [4 /*yield*/, executeAiAssistantReportBuilderAggregate(toolRequest, context)];
2817
2869
  case 53:
2818
- _j = _22.sent();
2870
+ _j = _23.sent();
2819
2871
  return [3 /*break*/, 56];
2820
2872
  case 54: return [4 /*yield*/, executeAiAssistantReportBuilderRead(toolRequest, context)];
2821
2873
  case 55:
2822
- _j = _22.sent();
2823
- _22.label = 56;
2874
+ _j = _23.sent();
2875
+ _23.label = 56;
2824
2876
  case 56:
2825
2877
  toolResponse = _j;
2826
2878
  toolDurationMs = Date.now() - toolStart;
@@ -2871,20 +2923,20 @@ function executeAiAssistantCodexRun(payload, context) {
2871
2923
  recordStep('Drafting response');
2872
2924
  followupPrompt = buildAssistantCodexToolFollowupPrompt(message, attachmentData.promptText, historyLines.join('\n'), assistantContext, toolPayload.prompt, assistantSystemPrompt);
2873
2925
  if (!hasRunBudget('Drafting response: followup')) return [3 /*break*/, 62];
2874
- _22.label = 58;
2926
+ _23.label = 58;
2875
2927
  case 58:
2876
- _22.trys.push([58, 60, , 61]);
2928
+ _23.trys.push([58, 60, , 61]);
2877
2929
  followupStart = Date.now();
2878
2930
  return [4 /*yield*/, runCodexInWorkerThread(followupPrompt, applyCodexStageBudget(runOptions), codexConfig, streamProgress)];
2879
2931
  case 59:
2880
- followupText = _22.sent();
2932
+ followupText = _23.sent();
2881
2933
  accumulateCodexUsage(followupPrompt, followupText);
2882
2934
  timingBreakdown.followupMs = Date.now() - followupStart;
2883
2935
  assistantContent = sanitizeAssistantResponse(followupText);
2884
2936
  assistantContent = applyAssistantDisplayTableToResponse(assistantContent, toolPayload.result.output.display);
2885
2937
  return [3 /*break*/, 61];
2886
2938
  case 60:
2887
- _k = _22.sent();
2939
+ _k = _23.sent();
2888
2940
  assistantContent = buildAssistantToolFallbackResponse(toolPayload.result);
2889
2941
  assistantContent = applyAssistantDisplayTableToResponse(assistantContent, toolPayload.result.output.display);
2890
2942
  return [3 /*break*/, 61];
@@ -2892,10 +2944,10 @@ function executeAiAssistantCodexRun(payload, context) {
2892
2944
  case 62:
2893
2945
  assistantContent = buildAssistantToolFallbackResponse(toolPayload.result);
2894
2946
  assistantContent = applyAssistantDisplayTableToResponse(assistantContent, toolPayload.result.output.display);
2895
- _22.label = 63;
2947
+ _23.label = 63;
2896
2948
  case 63: return [3 /*break*/, 65];
2897
2949
  case 64:
2898
- error_3 = _22.sent();
2950
+ error_3 = _23.sent();
2899
2951
  assistantContent = buildAssistantToolErrorMessage(error_3);
2900
2952
  toolError = error_3;
2901
2953
  errorMessage = normalizeOptionalString(error_3 === null || error_3 === void 0 ? void 0 : error_3.message) || 'Unknown error';
@@ -2909,10 +2961,10 @@ function executeAiAssistantCodexRun(payload, context) {
2909
2961
  case 66:
2910
2962
  progressTracker.push('Drafting response');
2911
2963
  recordStep('Drafting response');
2912
- _22.label = 67;
2964
+ _23.label = 67;
2913
2965
  case 67: return [3 /*break*/, 70];
2914
2966
  case 68:
2915
- error_4 = _22.sent();
2967
+ error_4 = _23.sent();
2916
2968
  assistantContent = buildAssistantCodexErrorMessage(error_4);
2917
2969
  recordStep('Error', { message: normalizeOptionalString(error_4 === null || error_4 === void 0 ? void 0 : error_4.message) || 'Unknown error' });
2918
2970
  return [3 /*break*/, 70];
@@ -2963,9 +3015,9 @@ function executeAiAssistantCodexRun(payload, context) {
2963
3015
  });
2964
3016
  }
2965
3017
  finalNow = new Date();
2966
- _22.label = 71;
3018
+ _23.label = 71;
2967
3019
  case 71:
2968
- _22.trys.push([71, 82, , 93]);
3020
+ _23.trys.push([71, 83, , 94]);
2969
3021
  if (canViewDebug) {
2970
3022
  finishedAt = Date.now();
2971
3023
  codexMs = timingBreakdown.directiveMs
@@ -3048,39 +3100,38 @@ function executeAiAssistantCodexRun(payload, context) {
3048
3100
  output_tokens: codexUsage.output_tokens,
3049
3101
  total_tokens: codexUsage.total_tokens
3050
3102
  } : null;
3103
+ finalUsageLedgerEntry = null;
3051
3104
  if (!finalUsage) return [3 /*break*/, 76];
3052
3105
  return [4 /*yield*/, resolveClientId(conversation, input.id_client, context === null || context === void 0 ? void 0 : context.id_user)];
3053
3106
  case 72:
3054
- usageClientId = _22.sent();
3055
- _22.label = 73;
3107
+ usageClientId = _23.sent();
3108
+ _23.label = 73;
3056
3109
  case 73:
3057
- _22.trys.push([73, 75, , 76]);
3058
- return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)({
3059
- id_client: usageClientId || '',
3060
- model: finalUsage.model,
3061
- input_tokens: finalUsage.input_tokens,
3062
- output_tokens: finalUsage.output_tokens,
3063
- total_tokens: finalUsage.total_tokens,
3064
- category: 'ai-terminal-codex',
3065
- id_request: requestId || undefined,
3066
- id_conversation: conversation._id,
3067
- usage_source: 'ai_assistant',
3068
- usage_surface: 'assistant',
3069
- usage_phase: 'codex_query',
3070
- cost_basis: 'estimated_tokens',
3071
- id_app: String((conversation === null || conversation === void 0 ? void 0 : conversation.id_app) || ''),
3072
- metadata: {
3073
- conversationId: conversation._id,
3074
- requestId: requestId || '',
3075
- plannerUsed: plannerUsed,
3076
- toolMode: toolTelemetry.mode
3077
- }
3078
- })];
3110
+ _23.trys.push([73, 75, , 76]);
3111
+ finalUsageLedgerEntry = buildAssistantAIRunUsageLedgerEntry({
3112
+ idClient: usageClientId || '',
3113
+ model: finalUsage.model,
3114
+ inputTokens: finalUsage.input_tokens,
3115
+ outputTokens: finalUsage.output_tokens,
3116
+ totalTokens: finalUsage.total_tokens,
3117
+ category: 'ai-terminal-codex',
3118
+ conversationId: conversation._id,
3119
+ requestId: requestId || undefined,
3120
+ usagePhase: 'codex_query',
3121
+ idApp: String((conversation === null || conversation === void 0 ? void 0 : conversation.id_app) || ''),
3122
+ metadata: {
3123
+ conversationId: conversation._id,
3124
+ requestId: requestId || '',
3125
+ plannerUsed: plannerUsed,
3126
+ toolMode: toolTelemetry.mode
3127
+ }
3128
+ });
3129
+ return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)(finalUsageLedgerEntry)];
3079
3130
  case 74:
3080
- _22.sent();
3131
+ _23.sent();
3081
3132
  return [3 /*break*/, 76];
3082
3133
  case 75:
3083
- usageError_1 = _22.sent();
3134
+ usageError_1 = _23.sent();
3084
3135
  console.error(new Date(), 'Failed to record AI usage', usageError_1);
3085
3136
  return [3 /*break*/, 76];
3086
3137
  case 76:
@@ -3096,58 +3147,76 @@ function executeAiAssistantCodexRun(payload, context) {
3096
3147
  }
3097
3148
  return [4 /*yield*/, updateAssistantMessageWithFallback(assistantMessageId, setPayload)];
3098
3149
  case 77:
3099
- _22.sent();
3100
- _22.label = 78;
3150
+ _23.sent();
3151
+ _23.label = 78;
3101
3152
  case 78: return [4 /*yield*/, touchConversation(conversation._id, finalNow, assistantMessageId ? String(assistantMessageId) : undefined)];
3102
3153
  case 79:
3103
- _22.sent();
3104
- if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 81];
3105
- return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
3154
+ _23.sent();
3155
+ return [4 /*yield*/, recordAssistantAnswerAIRun({
3156
+ runId: buildAssistantAIRunId('codex_query', [conversation._id, assistantMessageId || requestId]),
3157
+ requestId: requestId || undefined,
3158
+ messageId: assistantMessageId ? String(assistantMessageId) : undefined,
3159
+ conversation: conversation,
3160
+ userMessage: __assign(__assign({}, userDoc), { _id: userMessageId ? String(userMessageId) : undefined }),
3161
+ assistantMessage: finalAssistantDoc,
3162
+ usageLedgerEntry: finalUsageLedgerEntry || undefined,
3163
+ correctnessChecks: ((_22 = toolTelemetry === null || toolTelemetry === void 0 ? void 0 : toolTelemetry.outcome) === null || _22 === void 0 ? void 0 : _22.error) ? [{
3164
+ assertion: 'assistant_tool_execution',
3165
+ status: 'fail',
3166
+ observed: toolTelemetry.outcome.error,
3167
+ message: 'Assistant tool execution reported an error.'
3168
+ }] : [],
3169
+ now: finalNow
3170
+ })];
3106
3171
  case 80:
3107
- _22.sent();
3108
- _22.label = 81;
3109
- case 81: return [2 /*return*/, finalAssistantDoc];
3110
- case 82:
3111
- finalizeError_1 = _22.sent();
3172
+ _23.sent();
3173
+ if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 82];
3174
+ return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
3175
+ case 81:
3176
+ _23.sent();
3177
+ _23.label = 82;
3178
+ case 82: return [2 /*return*/, finalAssistantDoc];
3179
+ case 83:
3180
+ finalizeError_1 = _23.sent();
3112
3181
  failedAt = new Date();
3113
3182
  fallbackContent = assistantContent || buildAssistantCodexErrorMessage(finalizeError_1);
3114
3183
  failureMetadata = __assign(__assign(__assign(__assign(__assign({ model: codexModel }, (codexFallbackModels.length ? { model_fallbacks: codexFallbackModels } : {})), (requestId ? { request_id: requestId } : {})), { pending: false, failed: true }), (toolExecutionTelemetry ? { tool_execution: toolExecutionTelemetry } : {})), { error_message: normalizeOptionalString(finalizeError_1 === null || finalizeError_1 === void 0 ? void 0 : finalizeError_1.message) || 'Unknown error' });
3115
- _22.label = 83;
3116
- case 83:
3117
- _22.trys.push([83, 87, , 88]);
3118
- if (!assistantMessageId) return [3 /*break*/, 85];
3184
+ _23.label = 84;
3185
+ case 84:
3186
+ _23.trys.push([84, 88, , 89]);
3187
+ if (!assistantMessageId) return [3 /*break*/, 86];
3119
3188
  return [4 /*yield*/, updateAssistantMessageWithFallback(assistantMessageId, {
3120
3189
  content: fallbackContent,
3121
3190
  metadata: failureMetadata,
3122
3191
  updatedAt: failedAt
3123
3192
  })];
3124
- case 84:
3125
- _22.sent();
3126
- _22.label = 85;
3127
- case 85: return [4 /*yield*/, touchConversation(conversation._id, failedAt, assistantMessageId ? String(assistantMessageId) : undefined)];
3128
- case 86:
3129
- _22.sent();
3130
- return [3 /*break*/, 88];
3193
+ case 85:
3194
+ _23.sent();
3195
+ _23.label = 86;
3196
+ case 86: return [4 /*yield*/, touchConversation(conversation._id, failedAt, assistantMessageId ? String(assistantMessageId) : undefined)];
3131
3197
  case 87:
3132
- persistError_1 = _22.sent();
3133
- console.error(new Date(), 'AI assistant finalize fallback update failed', persistError_1);
3134
- return [3 /*break*/, 88];
3198
+ _23.sent();
3199
+ return [3 /*break*/, 89];
3135
3200
  case 88:
3136
- if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 92];
3137
- _22.label = 89;
3201
+ persistError_1 = _23.sent();
3202
+ console.error(new Date(), 'AI assistant finalize fallback update failed', persistError_1);
3203
+ return [3 /*break*/, 89];
3138
3204
  case 89:
3139
- _22.trys.push([89, 91, , 92]);
3140
- return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
3205
+ if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 93];
3206
+ _23.label = 90;
3141
3207
  case 90:
3142
- _22.sent();
3143
- return [3 /*break*/, 92];
3208
+ _23.trys.push([90, 92, , 93]);
3209
+ return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
3144
3210
  case 91:
3145
- _l = _22.sent();
3146
- return [3 /*break*/, 92];
3211
+ _23.sent();
3212
+ return [3 /*break*/, 93];
3147
3213
  case 92:
3214
+ _l = _23.sent();
3215
+ return [3 /*break*/, 93];
3216
+ case 93:
3148
3217
  console.error(new Date(), 'AI assistant run finalize failed:', finalizeError_1);
3149
3218
  return [2 /*return*/, __assign(__assign({}, assistantDoc), { _id: assistantMessageId, content: fallbackContent, metadata: failureMetadata, updatedAt: failedAt })];
3150
- case 93: return [2 /*return*/];
3219
+ case 94: return [2 /*return*/];
3151
3220
  }
3152
3221
  });
3153
3222
  }); });
@@ -23034,6 +23103,68 @@ function estimateUsage(messages, responseText, model) {
23034
23103
  totalTokens: inputTokens + outputTokens
23035
23104
  };
23036
23105
  }
23106
+ function buildAssistantAIRunUsageLedgerEntry(input) {
23107
+ return {
23108
+ id_client: normalizeOptionalString(input.idClient),
23109
+ model: normalizeOptionalString(input.model) || 'unknown',
23110
+ input_tokens: Number(input.inputTokens || 0),
23111
+ output_tokens: Number(input.outputTokens || 0),
23112
+ total_tokens: Number(input.totalTokens || 0),
23113
+ category: input.category,
23114
+ id_request: normalizeOptionalString(input.requestId) || undefined,
23115
+ id_conversation: normalizeOptionalString(input.conversationId) || undefined,
23116
+ usage_source: 'ai_assistant',
23117
+ usage_surface: 'assistant',
23118
+ usage_phase: input.usagePhase,
23119
+ cost_basis: 'estimated_tokens',
23120
+ id_app: normalizeOptionalString(input.idApp),
23121
+ metadata: input.metadata
23122
+ };
23123
+ }
23124
+ function buildAssistantAIRunId(prefix, parts) {
23125
+ var normalizedParts = parts
23126
+ .map(function (part) { return normalizeOptionalString(part); })
23127
+ .filter(Boolean);
23128
+ if (normalizedParts.length) {
23129
+ return "ai-run:ai_assistant:".concat(prefix, ":").concat(normalizedParts.join(':'));
23130
+ }
23131
+ var digest = (0, crypto_1.createHash)('sha1').update("".concat(prefix, ":").concat(Date.now(), ":").concat(Math.random())).digest('hex').slice(0, 20);
23132
+ return "ai-run:ai_assistant:".concat(prefix, ":").concat(digest);
23133
+ }
23134
+ function recordAssistantAnswerAIRun(input) {
23135
+ return __awaiter(this, void 0, void 0, function () {
23136
+ var messages, run, error_14;
23137
+ return __generator(this, function (_a) {
23138
+ switch (_a.label) {
23139
+ case 0:
23140
+ _a.trys.push([0, 2, , 3]);
23141
+ messages = [
23142
+ input.userMessage,
23143
+ input.assistantMessage
23144
+ ].filter(function (message) { return !!message; });
23145
+ run = (0, ai_run_evidence_adapters_1.buildAssistantAIRunFromEvidence)({
23146
+ runId: input.runId,
23147
+ requestId: input.requestId,
23148
+ messageId: input.messageId,
23149
+ conversation: input.conversation || {},
23150
+ messages: messages,
23151
+ usageLedger: input.usageLedgerEntry ? [input.usageLedgerEntry] : [],
23152
+ correctnessChecks: input.correctnessChecks || [],
23153
+ now: input.now || new Date()
23154
+ });
23155
+ return [4 /*yield*/, ai_run_evidence_manager_1.AIRunEvidenceManager.upsertRuns([run])];
23156
+ case 1:
23157
+ _a.sent();
23158
+ return [3 /*break*/, 3];
23159
+ case 2:
23160
+ error_14 = _a.sent();
23161
+ console.error(new Date(), 'Failed to record AI assistant AIRun evidence', error_14);
23162
+ return [3 /*break*/, 3];
23163
+ case 3: return [2 /*return*/];
23164
+ }
23165
+ });
23166
+ });
23167
+ }
23037
23168
  function evaluateGuardrails(message) {
23038
23169
  var e_58, _a;
23039
23170
  var normalized = String(message || '').toLowerCase();