@oneuptime/common 11.5.4 → 11.5.5
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.
- package/Models/DatabaseModels/AIAgentTaskPullRequest.ts +56 -45
- package/Models/DatabaseModels/AIInsight.ts +748 -0
- package/Models/DatabaseModels/AIRun.ts +262 -0
- package/Models/DatabaseModels/CodeRepository.ts +42 -0
- package/Models/DatabaseModels/GlobalConfig.ts +105 -0
- package/Models/DatabaseModels/Index.ts +4 -8
- package/Models/DatabaseModels/InstanceHealthLog.ts +277 -0
- package/Models/DatabaseModels/LlmLog.ts +33 -0
- package/Models/DatabaseModels/Project.ts +123 -6
- package/Models/DatabaseModels/Runbook.ts +1 -1
- package/Server/API/AIAgentDataAPI.ts +802 -140
- package/Server/API/AIAgentTaskAPI.ts +132 -69
- package/Server/API/AIAgentTaskLogAPI.ts +65 -41
- package/Server/API/AIAgentTaskPullRequestAPI.ts +41 -0
- package/Server/API/AIInsightAPI.ts +220 -0
- package/Server/API/AIInvestigationAPI.ts +363 -1
- package/Server/API/CodeFixRunAPI.ts +251 -0
- package/Server/API/GitHubAPI.ts +246 -3
- package/Server/API/TelemetryExceptionAPI.ts +193 -48
- package/Server/EnvironmentConfig.ts +1 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783943300000-DropServiceCodeRepository.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783947444597-CodeFixRunsOnAIRun.ts +73 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783950962813-AddCodeFixTaskType.ts +29 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783954040984-AddInstrumentationFixTasksFlag.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783957160597-MigrationName.ts +51 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783958542237-AddTaskContextToAIRun.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783965945957-AddInvestigationVerdictAndGrade.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783970619301-AddFixGuardrailColumns.ts +53 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783970619302-DropLegacyAIAgentTaskTables.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783977781677-AddCiStatusToFixPullRequests.ts +37 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783990000000-AddCompletionTokensToLlmLog.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784010274993-AddSentinelInsight.ts +75 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784010274994-AddSentinelInsightFlags.ts +37 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784030612266-RenameSentinelToAI.ts +203 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784033837629-MigrationName.ts +163 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +30 -0
- package/Server/Infrastructure/Queue.ts +82 -4
- package/Server/Infrastructure/Semaphore.ts +62 -1
- package/Server/Services/AIAgentService.ts +32 -0
- package/Server/Services/AIAgentTaskPullRequestService.ts +117 -0
- package/Server/Services/AIInsightService.ts +174 -0
- package/Server/Services/AIRunEventService.ts +63 -0
- package/Server/Services/AIRunService.ts +259 -1
- package/Server/Services/AIService.ts +249 -7
- package/Server/Services/AlertService.ts +4 -4
- package/Server/Services/CodeRepositoryService.ts +209 -0
- package/Server/Services/GlobalConfigService.ts +148 -0
- package/Server/Services/IncidentService.ts +183 -38
- package/Server/Services/IncidentStateTimelineService.ts +24 -4
- package/Server/Services/Index.ts +4 -4
- package/Server/Services/{AIAgentTaskLogService.ts → InstanceHealthLogService.ts} +1 -1
- package/Server/Services/LlmLogService.ts +27 -0
- package/Server/Services/LlmProviderService.ts +108 -0
- package/Server/Services/MetricBaselineService.ts +123 -0
- package/Server/Services/MonitorService.ts +15 -0
- package/Server/Services/TelemetryExceptionService.ts +323 -116
- package/Server/Services/TraceAggregationService.ts +176 -0
- package/Server/Types/Workflow/ComponentCode.ts +6 -0
- package/Server/Types/Workflow/Components/AI/GenerateText.ts +326 -0
- package/Server/Types/Workflow/Components/Index.ts +2 -0
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +1 -1
- package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +71 -0
- package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +243 -0
- package/Server/Utils/AI/CodeFix/CodeFixRunQueue.ts +131 -0
- package/Server/Utils/AI/CodeFix/FixRunBudget.ts +148 -0
- package/Server/Utils/AI/CodeFix/OpenPullRequestCap.ts +117 -0
- package/Server/Utils/AI/Eval/EvalCorpus.ts +369 -0
- package/Server/Utils/AI/Eval/EvalScores.ts +172 -0
- package/Server/Utils/AI/Eval/ReplayInvestigation.ts +87 -0
- package/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.ts +676 -0
- package/Server/Utils/AI/{Sentinel/SentinelInvestigationEngine.ts → SRE/AIInvestigationEngine.ts} +58 -37
- package/Server/Utils/AI/{Sentinel/SentinelMemory.ts → SRE/AIMemory.ts} +3 -3
- package/Server/Utils/AI/{Sentinel → SRE}/AlertInvestigationRunner.ts +50 -20
- package/Server/Utils/AI/SRE/ConfidenceSignal.ts +293 -0
- package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +115 -0
- package/Server/Utils/AI/SRE/FixPerformanceTaskTrigger.ts +223 -0
- package/Server/Utils/AI/{Sentinel → SRE}/IncidentInvestigationRunner.ts +71 -21
- package/Server/Utils/AI/{Sentinel → SRE}/IncidentPostmortemRunner.ts +8 -8
- package/Server/Utils/AI/SRE/Insights/Detectors/ErrorLogSpikeDetector.ts +364 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +317 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/Index.ts +27 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/MetricDriftDetector.ts +221 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +238 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/TraceLatencyRegressionDetector.ts +521 -0
- package/Server/Utils/AI/SRE/Insights/FixRouting.ts +242 -0
- package/Server/Utils/AI/SRE/Insights/InsightScanner.ts +290 -0
- package/Server/Utils/AI/SRE/Insights/InsightStore.ts +283 -0
- package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +242 -0
- package/Server/Utils/AI/SRE/Insights/Triage.ts +162 -0
- package/Server/Utils/AI/SRE/Insights/Types.ts +49 -0
- package/Server/Utils/AI/SRE/InstrumentationTaskTrigger.ts +212 -0
- package/Server/Utils/AI/SRE/InvestigationGrader.ts +282 -0
- package/Server/Utils/AI/{Sentinel → SRE}/InvestigationQueue.ts +114 -19
- package/Server/Utils/AI/{Sentinel → SRE}/README.md +4 -4
- package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +172 -0
- package/Server/Utils/AI/Toolbox/{SentinelActionTools.ts → AIActionTools.ts} +22 -1
- package/Server/Utils/AI/Toolbox/Index.ts +2 -2
- package/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.ts +526 -0
- package/Server/Utils/CodeRepository/GitHub/GitHub.ts +319 -1
- package/Server/Utils/CodeRepository/ServiceRepoLinkSuggester.ts +221 -0
- package/Server/Utils/CodeRepository/StackTraceRepoResolver.ts +571 -0
- package/Server/Utils/Execute.ts +2 -1
- package/Server/Utils/LLM/LLMService.ts +160 -30
- package/Server/Utils/Monitor/Criteria/SqlMonitorCriteria.ts +152 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +29 -0
- package/Tests/Server/Infrastructure/Queue.test.ts +227 -0
- package/Tests/Server/Infrastructure/SemaphorePermit.test.ts +159 -0
- package/Tests/Server/Services/AIAgentTaskPullRequestOutcomeStats.test.ts +154 -0
- package/Tests/Server/Services/AIInsightService.test.ts +324 -0
- package/Tests/Server/Services/AIRunCodeFixClaim.test.ts +401 -0
- package/Tests/Server/Services/AIRunHumanVerdict.test.ts +161 -0
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +95 -5
- package/Tests/Server/Services/AIServiceProjectAccess.test.ts +259 -0
- package/Tests/Server/Services/FixFromIncidentTaskTrigger.test.ts +249 -0
- package/Tests/Server/Services/FixPerformanceTaskTrigger.test.ts +274 -0
- package/Tests/Server/Services/GlobalConfigService.test.ts +80 -0
- package/Tests/Server/Services/IncidentInternalNoteAnnouncement.test.ts +1 -1
- package/Tests/Server/Services/InstrumentationTaskTrigger.test.ts +313 -0
- package/Tests/Server/Services/LlmProviderProjectOwned.test.ts +132 -0
- package/Tests/Server/Services/TelemetryExceptionAIFixReadiness.test.ts +405 -0
- package/Tests/Server/Services/TelemetryExceptionCodeFixRun.test.ts +322 -0
- package/Tests/Server/Services/TraceServiceLatencyProfile.test.ts +278 -0
- package/Tests/Server/Types/Workflow/Components/AIGenerateText.test.ts +722 -0
- package/Tests/Server/Utils/AI/{SentinelAlertGating.test.ts → AIAlertGating.test.ts} +19 -19
- package/Tests/Server/Utils/AI/AIConfidenceSignal.test.ts +362 -0
- package/Tests/Server/Utils/AI/{SentinelInvestigationQueue.test.ts → AIInvestigationQueue.test.ts} +19 -19
- package/Tests/Server/Utils/AI/CodeAgentWorkspaceGuard.test.ts +138 -0
- package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +335 -0
- package/Tests/Server/Utils/AI/CodeFixRunQueue.test.ts +134 -0
- package/Tests/Server/Utils/AI/EvalCorpus.test.ts +209 -0
- package/Tests/Server/Utils/AI/EvalScores.test.ts +343 -0
- package/Tests/Server/Utils/AI/FixRunBudget.test.ts +218 -0
- package/Tests/Server/Utils/AI/Insights/ErrorLogSpikeDetector.test.ts +437 -0
- package/Tests/Server/Utils/AI/Insights/ExceptionSpikeDetector.test.ts +287 -0
- package/Tests/Server/Utils/AI/Insights/InsightDetectorsIndex.test.ts +34 -0
- package/Tests/Server/Utils/AI/Insights/InsightFixRouting.test.ts +572 -0
- package/Tests/Server/Utils/AI/Insights/InsightNeverThrowsHardening.test.ts +344 -0
- package/Tests/Server/Utils/AI/Insights/InsightScanner.test.ts +720 -0
- package/Tests/Server/Utils/AI/Insights/InsightStore.test.ts +467 -0
- package/Tests/Server/Utils/AI/Insights/InsightStoreHardening.test.ts +370 -0
- package/Tests/Server/Utils/AI/Insights/InsightTriage.test.ts +210 -0
- package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +221 -0
- package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +328 -0
- package/Tests/Server/Utils/AI/Insights/MetricBaselineDrift.test.ts +182 -0
- package/Tests/Server/Utils/AI/Insights/MetricDriftDetector.test.ts +280 -0
- package/Tests/Server/Utils/AI/Insights/NewExceptionDetector.test.ts +259 -0
- package/Tests/Server/Utils/AI/Insights/TraceLatencyRegressionDetector.test.ts +770 -0
- package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +343 -0
- package/Tests/Server/Utils/AI/LLMServiceRequestPolicy.test.ts +307 -0
- package/Tests/Server/Utils/AI/OpenPullRequestCap.test.ts +170 -0
- package/Tests/Server/Utils/AI/SpanTreeAnalyzer.test.ts +559 -0
- package/Tests/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.test.ts +158 -0
- package/Tests/Server/Utils/GitHubCheckRunsConclusion.test.ts +100 -0
- package/Tests/Server/Utils/GitHubPullRequestStateMapping.test.ts +50 -0
- package/Tests/Server/Utils/Monitor/Criteria/SqlMonitorCriteria.test.ts +266 -0
- package/Tests/Server/Utils/ServiceRepoLinkSuggester.test.ts +167 -0
- package/Tests/Server/Utils/StackTraceRepoResolver.test.ts +527 -0
- package/Tests/Types/AI/AIChatPermissionMode.test.ts +112 -0
- package/Tests/Types/AI/CodeFixTaskType.test.ts +152 -0
- package/Tests/Types/AI/FixPullRequestCiStatus.test.ts +181 -0
- package/Tests/Types/Monitor/MonitorStepSqlMonitor.test.ts +110 -0
- package/Tests/Types/Monitor/SqlDatabaseType.test.ts +55 -0
- package/Tests/Types/Workflow/AIGenerateTextMetadata.test.ts +180 -0
- package/Tests/UI/Components/TableBulkCsvExport.test.tsx +168 -0
- package/Tests/UI/Utils/TableColumnsToCsv.test.ts +523 -0
- package/Types/AI/AIChatTypes.ts +8 -0
- package/Types/AI/AIInsightEvidence.ts +77 -0
- package/Types/AI/AIInsightHumanVerdict.ts +15 -0
- package/Types/AI/AIInsightSeverity.ts +13 -0
- package/Types/AI/AIInsightStatus.ts +38 -0
- package/Types/AI/AIInsightType.ts +41 -0
- package/Types/AI/AIRunAutoGrade.ts +18 -0
- package/Types/AI/AIRunEventType.ts +5 -0
- package/Types/AI/AIRunHumanVerdict.ts +17 -0
- package/Types/AI/AIRunType.ts +6 -0
- package/Types/AI/CodeFixTaskContext.ts +88 -0
- package/Types/AI/CodeFixTaskType.ts +132 -0
- package/Types/AI/FixPullRequestCiStatus.ts +132 -0
- package/Types/BaseDatabase/AggregationIntervalUtil.ts +67 -0
- package/Types/Incident/IncidentMetricType.ts +7 -0
- package/Types/Monitor/CriteriaFilter.ts +8 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +67 -0
- package/Types/Monitor/MonitorStep.ts +38 -0
- package/Types/Monitor/MonitorStepSqlMonitor.ts +141 -0
- package/Types/Monitor/MonitorType.ts +17 -0
- package/Types/Monitor/SqlDatabaseType.ts +49 -0
- package/Types/Monitor/SqlMonitor/SqlMonitorResponse.ts +28 -0
- package/Types/Permission.ts +11 -95
- package/Types/Probe/ProbeMonitorResponse.ts +2 -0
- package/Types/Runbook/RunbookStep.ts +26 -2
- package/Types/Runbook/RunbookStepType.ts +1 -0
- package/Types/Workflow/Component.ts +13 -0
- package/Types/Workflow/ComponentID.ts +1 -0
- package/Types/Workflow/Components/AI.ts +148 -0
- package/Types/Workflow/Components.ts +8 -0
- package/UI/Components/AI/GenerateFromAIModal.tsx +1 -1
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +11 -0
- package/UI/Components/MoreMenu/MoreMenu.tsx +1 -1
- package/UI/Components/Table/Table.tsx +38 -2
- package/UI/Utils/TableColumnsToCsv.ts +385 -0
- package/Utils/Monitor/MonitorMetricType.ts +1 -0
- package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js +59 -45
- package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AIInsight.js +795 -0
- package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AIRun.js +274 -0
- package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CodeRepository.js +43 -0
- package/build/dist/Models/DatabaseModels/CodeRepository.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +110 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +4 -8
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/InstanceHealthLog.js +304 -0
- package/build/dist/Models/DatabaseModels/InstanceHealthLog.js.map +1 -0
- package/build/dist/Models/DatabaseModels/LlmLog.js +35 -0
- package/build/dist/Models/DatabaseModels/LlmLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +127 -6
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Runbook.js +1 -1
- package/build/dist/Models/DatabaseModels/Runbook.js.map +1 -1
- package/build/dist/Server/API/AIAgentDataAPI.js +568 -85
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
- package/build/dist/Server/API/AIAgentTaskAPI.js +100 -44
- package/build/dist/Server/API/AIAgentTaskAPI.js.map +1 -1
- package/build/dist/Server/API/AIAgentTaskLogAPI.js +49 -25
- package/build/dist/Server/API/AIAgentTaskLogAPI.js.map +1 -1
- package/build/dist/Server/API/AIAgentTaskPullRequestAPI.js +27 -0
- package/build/dist/Server/API/AIAgentTaskPullRequestAPI.js.map +1 -1
- package/build/dist/Server/API/AIInsightAPI.js +140 -0
- package/build/dist/Server/API/AIInsightAPI.js.map +1 -0
- package/build/dist/Server/API/AIInvestigationAPI.js +257 -1
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/CodeFixRunAPI.js +181 -0
- package/build/dist/Server/API/CodeFixRunAPI.js.map +1 -0
- package/build/dist/Server/API/GitHubAPI.js +164 -2
- package/build/dist/Server/API/GitHubAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryExceptionAPI.js +148 -43
- package/build/dist/Server/API/TelemetryExceptionAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +1 -1
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783943300000-DropServiceCodeRepository.js +23 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783943300000-DropServiceCodeRepository.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783947444597-CodeFixRunsOnAIRun.js +32 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783947444597-CodeFixRunsOnAIRun.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783950962813-AddCodeFixTaskType.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783950962813-AddCodeFixTaskType.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783954040984-AddInstrumentationFixTasksFlag.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783954040984-AddInstrumentationFixTasksFlag.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783957160597-MigrationName.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783957160597-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783958542237-AddTaskContextToAIRun.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783958542237-AddTaskContextToAIRun.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783965945957-AddInvestigationVerdictAndGrade.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783965945957-AddInvestigationVerdictAndGrade.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783970619301-AddFixGuardrailColumns.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783970619301-AddFixGuardrailColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783970619302-DropLegacyAIAgentTaskTables.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783970619302-DropLegacyAIAgentTaskTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783977781677-AddCiStatusToFixPullRequests.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783977781677-AddCiStatusToFixPullRequests.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783990000000-AddCompletionTokensToLlmLog.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783990000000-AddCompletionTokensToLlmLog.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784010274993-AddSentinelInsight.js +32 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784010274993-AddSentinelInsight.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784010274994-AddSentinelInsightFlags.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784010274994-AddSentinelInsightFlags.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784030612266-RenameSentinelToAI.js +125 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784030612266-RenameSentinelToAI.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784033837629-MigrationName.js +62 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784033837629-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Queue.js +73 -3
- package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +44 -1
- package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
- package/build/dist/Server/Services/AIAgentService.js +29 -0
- package/build/dist/Server/Services/AIAgentService.js.map +1 -1
- package/build/dist/Server/Services/AIAgentTaskPullRequestService.js +78 -0
- package/build/dist/Server/Services/AIAgentTaskPullRequestService.js.map +1 -1
- package/build/dist/Server/Services/AIInsightService.js +164 -0
- package/build/dist/Server/Services/AIInsightService.js.map +1 -0
- package/build/dist/Server/Services/AIRunEventService.js +49 -0
- package/build/dist/Server/Services/AIRunEventService.js.map +1 -1
- package/build/dist/Server/Services/AIRunService.js +221 -0
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +198 -11
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +4 -4
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/CodeRepositoryService.js +180 -0
- package/build/dist/Server/Services/CodeRepositoryService.js.map +1 -1
- package/build/dist/Server/Services/GlobalConfigService.js +84 -0
- package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +149 -37
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +24 -4
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +4 -4
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/{AIAgentTaskLogService.js → InstanceHealthLogService.js} +2 -2
- package/build/dist/Server/Services/InstanceHealthLogService.js.map +1 -0
- package/build/dist/Server/Services/LlmLogService.js +23 -0
- package/build/dist/Server/Services/LlmLogService.js.map +1 -1
- package/build/dist/Server/Services/LlmProviderService.js +96 -0
- package/build/dist/Server/Services/LlmProviderService.js.map +1 -1
- package/build/dist/Server/Services/MetricBaselineService.js +65 -0
- package/build/dist/Server/Services/MetricBaselineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +9 -1
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryExceptionService.js +243 -82
- package/build/dist/Server/Services/TelemetryExceptionService.js.map +1 -1
- package/build/dist/Server/Services/TraceAggregationService.js +124 -0
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/ComponentCode.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/AI/GenerateText.js +240 -0
- package/build/dist/Server/Types/Workflow/Components/AI/GenerateText.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/Index.js +2 -0
- package/build/dist/Server/Types/Workflow/Components/Index.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +48 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js.map +1 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +174 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixRunQueue.js +126 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixRunQueue.js.map +1 -0
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +131 -0
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -0
- package/build/dist/Server/Utils/AI/CodeFix/OpenPullRequestCap.js +99 -0
- package/build/dist/Server/Utils/AI/CodeFix/OpenPullRequestCap.js.map +1 -0
- package/build/dist/Server/Utils/AI/Eval/EvalCorpus.js +245 -0
- package/build/dist/Server/Utils/AI/Eval/EvalCorpus.js.map +1 -0
- package/build/dist/Server/Utils/AI/Eval/EvalScores.js +83 -0
- package/build/dist/Server/Utils/AI/Eval/EvalScores.js.map +1 -0
- package/build/dist/Server/Utils/AI/Eval/ReplayInvestigation.js +12 -0
- package/build/dist/Server/Utils/AI/Eval/ReplayInvestigation.js.map +1 -0
- package/build/dist/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.js +439 -0
- package/build/dist/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.js.map +1 -0
- package/build/dist/Server/Utils/AI/{Sentinel/SentinelInvestigationEngine.js → SRE/AIInvestigationEngine.js} +47 -31
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -0
- package/build/dist/Server/Utils/AI/{Sentinel/SentinelMemory.js → SRE/AIMemory.js} +5 -5
- package/build/dist/Server/Utils/AI/SRE/AIMemory.js.map +1 -0
- package/build/dist/Server/Utils/AI/{Sentinel → SRE}/AlertInvestigationRunner.js +42 -19
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js +226 -0
- package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js +100 -0
- package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/FixPerformanceTaskTrigger.js +174 -0
- package/build/dist/Server/Utils/AI/SRE/FixPerformanceTaskTrigger.js.map +1 -0
- package/build/dist/Server/Utils/AI/{Sentinel → SRE}/IncidentInvestigationRunner.js +60 -22
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/{Sentinel → SRE}/IncidentPostmortemRunner.js +9 -9
- package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ErrorLogSpikeDetector.js +268 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ErrorLogSpikeDetector.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +226 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/Index.js +26 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/Index.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/MetricDriftDetector.js +159 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/MetricDriftDetector.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +177 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/TraceLatencyRegressionDetector.js +384 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/TraceLatencyRegressionDetector.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js +180 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightScanner.js +269 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightScanner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js +231 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +206 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Triage.js +121 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Triage.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Types.js +2 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Types.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js +148 -0
- package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +231 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -0
- package/build/dist/Server/Utils/AI/{Sentinel → SRE}/InvestigationQueue.js +102 -23
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +167 -0
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/{SentinelActionTools.js → AIActionTools.js} +18 -2
- package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js +2 -2
- package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.js +301 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +240 -2
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/ServiceRepoLinkSuggester.js +127 -0
- package/build/dist/Server/Utils/CodeRepository/ServiceRepoLinkSuggester.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/StackTraceRepoResolver.js +336 -0
- package/build/dist/Server/Utils/CodeRepository/StackTraceRepoResolver.js.map +1 -0
- package/build/dist/Server/Utils/Execute.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +125 -25
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SqlMonitorCriteria.js +120 -0
- package/build/dist/Server/Utils/Monitor/Criteria/SqlMonitorCriteria.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +21 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Types/AI/AIInsightEvidence.js +2 -0
- package/build/dist/Types/AI/AIInsightEvidence.js.map +1 -0
- package/build/dist/Types/AI/AIInsightHumanVerdict.js +16 -0
- package/build/dist/Types/AI/AIInsightHumanVerdict.js.map +1 -0
- package/build/dist/Types/AI/AIInsightSeverity.js +14 -0
- package/build/dist/Types/AI/AIInsightSeverity.js.map +1 -0
- package/build/dist/Types/AI/AIInsightStatus.js +36 -0
- package/build/dist/Types/AI/AIInsightStatus.js.map +1 -0
- package/build/dist/Types/AI/AIInsightType.js +42 -0
- package/build/dist/Types/AI/AIInsightType.js.map +1 -0
- package/build/dist/Types/AI/AIRunAutoGrade.js +19 -0
- package/build/dist/Types/AI/AIRunAutoGrade.js.map +1 -0
- package/build/dist/Types/AI/AIRunEventType.js +5 -0
- package/build/dist/Types/AI/AIRunEventType.js.map +1 -1
- package/build/dist/Types/AI/AIRunHumanVerdict.js +18 -0
- package/build/dist/Types/AI/AIRunHumanVerdict.js.map +1 -0
- package/build/dist/Types/AI/AIRunType.js +6 -0
- package/build/dist/Types/AI/AIRunType.js.map +1 -1
- package/build/dist/Types/AI/CodeFixTaskContext.js +29 -0
- package/build/dist/Types/AI/CodeFixTaskContext.js.map +1 -0
- package/build/dist/Types/AI/CodeFixTaskType.js +122 -0
- package/build/dist/Types/AI/CodeFixTaskType.js.map +1 -0
- package/build/dist/Types/AI/FixPullRequestCiStatus.js +102 -0
- package/build/dist/Types/AI/FixPullRequestCiStatus.js.map +1 -0
- package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js +55 -0
- package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js.map +1 -1
- package/build/dist/Types/Incident/IncidentMetricType.js +7 -0
- package/build/dist/Types/Incident/IncidentMetricType.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +7 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +62 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +28 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js +93 -0
- package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorType.js +15 -0
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/SqlDatabaseType.js +47 -0
- package/build/dist/Types/Monitor/SqlDatabaseType.js.map +1 -0
- package/build/dist/Types/Monitor/SqlMonitor/SqlMonitorResponse.js +2 -0
- package/build/dist/Types/Monitor/SqlMonitor/SqlMonitorResponse.js.map +1 -0
- package/build/dist/Types/Permission.js +10 -84
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Runbook/RunbookStepType.js +1 -0
- package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
- package/build/dist/Types/Workflow/ComponentID.js +1 -0
- package/build/dist/Types/Workflow/ComponentID.js.map +1 -1
- package/build/dist/Types/Workflow/Components/AI.js +135 -0
- package/build/dist/Types/Workflow/Components/AI.js.map +1 -0
- package/build/dist/Types/Workflow/Components.js +7 -0
- package/build/dist/Types/Workflow/Components.js.map +1 -1
- package/build/dist/UI/Components/AI/GenerateFromAIModal.js +1 -1
- package/build/dist/UI/Components/AI/GenerateFromAIModal.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +9 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +1 -1
- package/build/dist/UI/Components/Table/Table.js +28 -2
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Utils/TableColumnsToCsv.js +291 -0
- package/build/dist/UI/Utils/TableColumnsToCsv.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorMetricType.js +1 -0
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/package.json +1 -1
- package/Models/DatabaseModels/AIAgentTask.ts +0 -660
- package/Models/DatabaseModels/AIAgentTaskLog.ts +0 -426
- package/Models/DatabaseModels/AIAgentTaskTelemetryException.ts +0 -399
- package/Models/DatabaseModels/ServiceCodeRepository.ts +0 -647
- package/Server/Services/AIAgentTaskService.ts +0 -240
- package/Server/Services/AIAgentTaskTelemetryExceptionService.ts +0 -39
- package/Server/Services/ServiceCodeRepositoryService.ts +0 -55
- package/Tests/Server/Services/AIAgentTaskServiceClaim.test.ts +0 -146
- package/Types/AI/AIAgentTaskMetadata.ts +0 -25
- package/Types/AI/AIAgentTaskType.ts +0 -40
- package/build/dist/Models/DatabaseModels/AIAgentTask.js +0 -691
- package/build/dist/Models/DatabaseModels/AIAgentTask.js.map +0 -1
- package/build/dist/Models/DatabaseModels/AIAgentTaskLog.js +0 -447
- package/build/dist/Models/DatabaseModels/AIAgentTaskLog.js.map +0 -1
- package/build/dist/Models/DatabaseModels/AIAgentTaskTelemetryException.js +0 -415
- package/build/dist/Models/DatabaseModels/AIAgentTaskTelemetryException.js.map +0 -1
- package/build/dist/Models/DatabaseModels/ServiceCodeRepository.js +0 -665
- package/build/dist/Models/DatabaseModels/ServiceCodeRepository.js.map +0 -1
- package/build/dist/Server/Services/AIAgentTaskLogService.js.map +0 -1
- package/build/dist/Server/Services/AIAgentTaskService.js +0 -217
- package/build/dist/Server/Services/AIAgentTaskService.js.map +0 -1
- package/build/dist/Server/Services/AIAgentTaskTelemetryExceptionService.js +0 -36
- package/build/dist/Server/Services/AIAgentTaskTelemetryExceptionService.js.map +0 -1
- package/build/dist/Server/Services/ServiceCodeRepositoryService.js +0 -54
- package/build/dist/Server/Services/ServiceCodeRepositoryService.js.map +0 -1
- package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js.map +0 -1
- package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js.map +0 -1
- package/build/dist/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.js.map +0 -1
- package/build/dist/Server/Utils/AI/Sentinel/InvestigationQueue.js.map +0 -1
- package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js.map +0 -1
- package/build/dist/Server/Utils/AI/Sentinel/SentinelMemory.js.map +0 -1
- package/build/dist/Server/Utils/AI/Toolbox/SentinelActionTools.js.map +0 -1
- package/build/dist/Types/AI/AIAgentTaskMetadata.js +0 -6
- package/build/dist/Types/AI/AIAgentTaskMetadata.js.map +0 -1
- package/build/dist/Types/AI/AIAgentTaskType.js +0 -29
- package/build/dist/Types/AI/AIAgentTaskType.js.map +0 -1
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import ObjectID from "../../../../../Types/ObjectID";
|
|
2
|
+
import OneUptimeDate from "../../../../../Types/Date";
|
|
3
|
+
import ColumnLength from "../../../../../Types/Database/ColumnLength";
|
|
4
|
+
import SortOrder from "../../../../../Types/BaseDatabase/SortOrder";
|
|
5
|
+
import AIInsight from "../../../../../Models/DatabaseModels/AIInsight";
|
|
6
|
+
import AIInsightStatus, {
|
|
7
|
+
AIInsightStatusHelper,
|
|
8
|
+
} from "../../../../../Types/AI/AIInsightStatus";
|
|
9
|
+
import AIInsightService from "../../../../Services/AIInsightService";
|
|
10
|
+
import { InsightCandidate } from "./Types";
|
|
11
|
+
import logger from "../../../Logger";
|
|
12
|
+
import CaptureSpan from "../../../Telemetry/CaptureSpan";
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* AI Insights — the dedupe/upsert store between detectors and the
|
|
16
|
+
* AIInsight table. Detectors re-emit the same finding on every scan
|
|
17
|
+
* tick while the underlying signal persists; the store's job is to keep the
|
|
18
|
+
* inbox quiet: one row per live finding (refreshed in place), a cooldown on
|
|
19
|
+
* findings a human already dismissed, and a hard cap on how many NEW rows a
|
|
20
|
+
* single scan may create.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* G4/G11 volume guardrail: a single scan tick may create at most this many
|
|
25
|
+
* NEW insights per project. A telemetry storm (deploy gone wrong, detector
|
|
26
|
+
* mis-tuning) would otherwise flood the inbox — and every new insight fans
|
|
27
|
+
* out into budgeted triage/fix work. Recurring findings still refresh their
|
|
28
|
+
* existing rows beyond the cap; drops are logged, never silent.
|
|
29
|
+
*/
|
|
30
|
+
export const MAX_NEW_INSIGHTS_PER_PROJECT_PER_SCAN: number = 10;
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* G11 noise posture: a human dismissal is the strongest precision signal we
|
|
34
|
+
* have, so a finding with the same fingerprint stays suppressed for this
|
|
35
|
+
* many days after the dismissal instead of reappearing on the next tick.
|
|
36
|
+
* After the cooldown (or after a Resolved insight's signal returns) a fresh
|
|
37
|
+
* insight is warranted — a resolved issue that reappears is a regression.
|
|
38
|
+
*/
|
|
39
|
+
export const DISMISSED_COOLDOWN_DAYS: number = 7;
|
|
40
|
+
|
|
41
|
+
/*
|
|
42
|
+
* Column-safety clamps: DatabaseService validates string columns against the
|
|
43
|
+
* model's declared lengths and THROWS on overflow, and detectors embed raw
|
|
44
|
+
* telemetry strings (a span name can be an entire SQL statement, exception
|
|
45
|
+
* types and service names are unbounded). Clamping here — the single choke
|
|
46
|
+
* point where candidates become rows — protects every current and future
|
|
47
|
+
* detector. The fingerprint clamp is applied to the dedupe LOOKUP as well as
|
|
48
|
+
* the insert, so a clamped fingerprint keeps refreshing the same row instead
|
|
49
|
+
* of failing (or duplicating) on every tick. Values mirror the
|
|
50
|
+
* AIInsight column definitions (LongText/ShortText).
|
|
51
|
+
*/
|
|
52
|
+
export const INSIGHT_FINGERPRINT_MAX_LENGTH: number = ColumnLength.LongText;
|
|
53
|
+
export const INSIGHT_TITLE_MAX_LENGTH: number = ColumnLength.LongText;
|
|
54
|
+
export const INSIGHT_SERVICE_NAME_MAX_LENGTH: number = ColumnLength.LongText;
|
|
55
|
+
export const INSIGHT_METRIC_NAME_MAX_LENGTH: number = ColumnLength.LongText;
|
|
56
|
+
export const INSIGHT_TRACE_ID_MAX_LENGTH: number = ColumnLength.ShortText;
|
|
57
|
+
|
|
58
|
+
export interface UpsertCandidatesResult {
|
|
59
|
+
// Newly created insights (status Detected) — the scanner routes these.
|
|
60
|
+
created: Array<AIInsight>;
|
|
61
|
+
// Existing non-terminal insights refreshed in place.
|
|
62
|
+
refreshed: number;
|
|
63
|
+
// Candidates suppressed by the dismissed-fingerprint cooldown.
|
|
64
|
+
suppressed: number;
|
|
65
|
+
// Candidates dropped by MAX_NEW_INSIGHTS_PER_PROJECT_PER_SCAN.
|
|
66
|
+
droppedByCap: number;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export default class InsightStore {
|
|
70
|
+
/*
|
|
71
|
+
* Upsert one scan tick's candidates for one project. For each candidate,
|
|
72
|
+
* the most recent insight with the same (projectId, fingerprint) decides
|
|
73
|
+
* the outcome:
|
|
74
|
+
* - none → CREATE (subject to the per-scan cap)
|
|
75
|
+
* - non-terminal → REFRESH (never touches status)
|
|
76
|
+
* - Dismissed within the cooldown → suppress
|
|
77
|
+
* - Dismissed past the cooldown,
|
|
78
|
+
* or Resolved → CREATE (regression / recurrence)
|
|
79
|
+
* All access is root-props: the scanner is a system actor with explicit
|
|
80
|
+
* projectId scoping, not a per-user ACL consumer.
|
|
81
|
+
*/
|
|
82
|
+
@CaptureSpan()
|
|
83
|
+
public static async upsertCandidates(data: {
|
|
84
|
+
projectId: ObjectID;
|
|
85
|
+
candidates: Array<InsightCandidate>;
|
|
86
|
+
now: Date;
|
|
87
|
+
}): Promise<UpsertCandidatesResult> {
|
|
88
|
+
const result: UpsertCandidatesResult = {
|
|
89
|
+
created: [],
|
|
90
|
+
refreshed: 0,
|
|
91
|
+
suppressed: 0,
|
|
92
|
+
droppedByCap: 0,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// No silent caps: dropped fingerprints are logged after the loop.
|
|
96
|
+
const droppedFingerprints: Array<string> = [];
|
|
97
|
+
|
|
98
|
+
for (const candidate of data.candidates) {
|
|
99
|
+
/*
|
|
100
|
+
* Per-candidate isolation: one failing candidate (transient DB error,
|
|
101
|
+
* unexpected data) must not abort the batch — insights created earlier
|
|
102
|
+
* in this tick are returned for routing either way, and the remaining
|
|
103
|
+
* candidates still get their chance. Without this, a mid-batch failure
|
|
104
|
+
* would strand already-created rows in Detected forever (refreshes
|
|
105
|
+
* never touch status, so they would never be routed).
|
|
106
|
+
*/
|
|
107
|
+
try {
|
|
108
|
+
/*
|
|
109
|
+
* The clamped fingerprint is the row's identity everywhere — lookup
|
|
110
|
+
* and insert — so dedupe survives the clamp (see the constants).
|
|
111
|
+
*/
|
|
112
|
+
const fingerprint: string = this.clampToColumn(
|
|
113
|
+
candidate.fingerprint,
|
|
114
|
+
INSIGHT_FINGERPRINT_MAX_LENGTH,
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
/*
|
|
118
|
+
* Most recent row wins: (projectId, fingerprint) is deliberately NOT
|
|
119
|
+
* unique — terminal rows accumulate as history — so sort by createdAt
|
|
120
|
+
* to judge against the latest lifecycle state of this finding.
|
|
121
|
+
*/
|
|
122
|
+
const existing: AIInsight | null = await AIInsightService.findOneBy({
|
|
123
|
+
query: {
|
|
124
|
+
projectId: data.projectId,
|
|
125
|
+
fingerprint: fingerprint,
|
|
126
|
+
},
|
|
127
|
+
select: {
|
|
128
|
+
_id: true,
|
|
129
|
+
status: true,
|
|
130
|
+
occurrenceCount: true,
|
|
131
|
+
humanVerdictAt: true,
|
|
132
|
+
},
|
|
133
|
+
sort: { createdAt: SortOrder.Descending },
|
|
134
|
+
props: { isRoot: true },
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (
|
|
138
|
+
existing &&
|
|
139
|
+
existing.status &&
|
|
140
|
+
!AIInsightStatusHelper.isTerminalStatus(existing.status)
|
|
141
|
+
) {
|
|
142
|
+
/*
|
|
143
|
+
* REFRESH: the finding is still live and already has a row. The
|
|
144
|
+
* evidence/severity are replaced with this tick's numbers (the
|
|
145
|
+
* newest picture of the signal), but status is NEVER touched here —
|
|
146
|
+
* routing (ActionRequired/FixOpened) happened when the row was
|
|
147
|
+
* created and humans/fix flows own it from there.
|
|
148
|
+
*/
|
|
149
|
+
await AIInsightService.updateOneById({
|
|
150
|
+
id: existing.id!,
|
|
151
|
+
data: {
|
|
152
|
+
lastSeenAt: data.now,
|
|
153
|
+
occurrenceCount: (existing.occurrenceCount || 1) + 1,
|
|
154
|
+
severity: candidate.severity,
|
|
155
|
+
detailMarkdown: candidate.detailMarkdown,
|
|
156
|
+
evidence: candidate.evidence,
|
|
157
|
+
},
|
|
158
|
+
props: { isRoot: true },
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
result.refreshed++;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (existing && existing.status === AIInsightStatus.Dismissed) {
|
|
166
|
+
/*
|
|
167
|
+
* Cooldown is measured from the human's dismissal, inclusive at the
|
|
168
|
+
* boundary (exactly DISMISSED_COOLDOWN_DAYS old still suppresses).
|
|
169
|
+
* A Dismissed row without a verdict timestamp cannot prove the
|
|
170
|
+
* cooldown elapsed, so it suppresses too — when in doubt, stay
|
|
171
|
+
* quiet (G11 noise posture).
|
|
172
|
+
*/
|
|
173
|
+
const cooldownMs: number = OneUptimeDate.getMillisecondsInDays(
|
|
174
|
+
DISMISSED_COOLDOWN_DAYS,
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
const withinCooldown: boolean = existing.humanVerdictAt
|
|
178
|
+
? data.now.getTime() -
|
|
179
|
+
OneUptimeDate.fromString(existing.humanVerdictAt).getTime() <=
|
|
180
|
+
cooldownMs
|
|
181
|
+
: true;
|
|
182
|
+
|
|
183
|
+
if (withinCooldown) {
|
|
184
|
+
logger.debug(
|
|
185
|
+
`AI Insights: suppressing candidate ${fingerprint} for project ${data.projectId.toString()} — dismissed by a human within the last ${DISMISSED_COOLDOWN_DAYS} days.`,
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
result.suppressed++;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/*
|
|
194
|
+
* CREATE: no live row for this fingerprint (never seen, Resolved, or
|
|
195
|
+
* Dismissed long enough ago). Subject to the per-scan cap.
|
|
196
|
+
*/
|
|
197
|
+
if (result.created.length >= MAX_NEW_INSIGHTS_PER_PROJECT_PER_SCAN) {
|
|
198
|
+
droppedFingerprints.push(fingerprint);
|
|
199
|
+
result.droppedByCap++;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const insight: AIInsight = new AIInsight();
|
|
204
|
+
insight.projectId = data.projectId;
|
|
205
|
+
insight.insightType = candidate.insightType;
|
|
206
|
+
// Defensive initial state — the scanner routes it in the same tick.
|
|
207
|
+
insight.status = AIInsightStatus.Detected;
|
|
208
|
+
insight.severity = candidate.severity;
|
|
209
|
+
insight.fingerprint = fingerprint;
|
|
210
|
+
insight.title = this.clampToColumn(
|
|
211
|
+
candidate.title,
|
|
212
|
+
INSIGHT_TITLE_MAX_LENGTH,
|
|
213
|
+
);
|
|
214
|
+
insight.detailMarkdown = candidate.detailMarkdown;
|
|
215
|
+
insight.evidence = candidate.evidence;
|
|
216
|
+
insight.firstSeenAt = data.now;
|
|
217
|
+
insight.lastSeenAt = data.now;
|
|
218
|
+
insight.occurrenceCount = 1;
|
|
219
|
+
|
|
220
|
+
if (candidate.serviceName) {
|
|
221
|
+
insight.serviceName = this.clampToColumn(
|
|
222
|
+
candidate.serviceName,
|
|
223
|
+
INSIGHT_SERVICE_NAME_MAX_LENGTH,
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
if (candidate.telemetryServiceId) {
|
|
227
|
+
insight.telemetryServiceId = candidate.telemetryServiceId;
|
|
228
|
+
}
|
|
229
|
+
if (candidate.telemetryExceptionId) {
|
|
230
|
+
insight.telemetryExceptionId = candidate.telemetryExceptionId;
|
|
231
|
+
}
|
|
232
|
+
if (candidate.traceId) {
|
|
233
|
+
insight.traceId = this.clampToColumn(
|
|
234
|
+
candidate.traceId,
|
|
235
|
+
INSIGHT_TRACE_ID_MAX_LENGTH,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
if (candidate.metricName) {
|
|
239
|
+
insight.metricName = this.clampToColumn(
|
|
240
|
+
candidate.metricName,
|
|
241
|
+
INSIGHT_METRIC_NAME_MAX_LENGTH,
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const created: AIInsight = await AIInsightService.create({
|
|
246
|
+
data: insight,
|
|
247
|
+
props: { isRoot: true },
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
result.created.push(created);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
logger.error(
|
|
253
|
+
`AI Insights: upsert failed for candidate ${candidate.fingerprint} (project ${data.projectId.toString()}) — continuing with the remaining candidates: ${error}`,
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (result.droppedByCap > 0) {
|
|
259
|
+
logger.debug(
|
|
260
|
+
`AI Insights: candidate fingerprints dropped by the per-scan cap for project ${data.projectId.toString()}: ${droppedFingerprints.join(", ")}`,
|
|
261
|
+
);
|
|
262
|
+
logger.info(
|
|
263
|
+
`AI Insights: per-scan new-insight cap (${MAX_NEW_INSIGHTS_PER_PROJECT_PER_SCAN}) reached for project ${data.projectId.toString()} — dropped ${result.droppedByCap} candidate(s) this tick. Recurring findings will re-surface on later ticks if their signal persists.`,
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return result;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/*
|
|
271
|
+
* Hard code-unit slice to the column's declared length — the same measure
|
|
272
|
+
* DatabaseService validates against, so a clamped value can never trip the
|
|
273
|
+
* length check. No cosmetic ellipsis: detectors own presentation; this is
|
|
274
|
+
* purely a data-safety guard, and it must be deterministic so a clamped
|
|
275
|
+
* fingerprint stays stable across ticks.
|
|
276
|
+
*/
|
|
277
|
+
private static clampToColumn(value: string, maxLength: number): string {
|
|
278
|
+
if (value.length <= maxLength) {
|
|
279
|
+
return value;
|
|
280
|
+
}
|
|
281
|
+
return value.slice(0, maxLength);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import ObjectID from "../../../../../Types/ObjectID";
|
|
2
|
+
import OneUptimeDate from "../../../../../Types/Date";
|
|
3
|
+
import AIInsight from "../../../../../Models/DatabaseModels/AIInsight";
|
|
4
|
+
import AIInsightEvidence from "../../../../../Types/AI/AIInsightEvidence";
|
|
5
|
+
import AIInsightService from "../../../../Services/AIInsightService";
|
|
6
|
+
import { AI_INSIGHT_TRIAGE_FEATURE } from "../../../../Services/AIService";
|
|
7
|
+
import AIInvestigationEngine from "../AIInvestigationEngine";
|
|
8
|
+
import AIInvestigationQueue from "../InvestigationQueue";
|
|
9
|
+
import { ConfidenceSignal } from "../ConfidenceSignal";
|
|
10
|
+
import { ObservabilityAssistantResult } from "../../Chat/ObservabilityAssistant";
|
|
11
|
+
import logger from "../../../Logger";
|
|
12
|
+
import CaptureSpan from "../../../Telemetry/CaptureSpan";
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* AI SRE — per-insight preventive triage.
|
|
16
|
+
*
|
|
17
|
+
* A deterministic detector filed a AIInsight; this runner executes the
|
|
18
|
+
* budgeted, read-only Investigation AIRun that triages it: most likely root
|
|
19
|
+
* cause, estimated blast radius, ONE recommended next action — every claim
|
|
20
|
+
* cited. Structurally a sibling of IncidentInvestigationRunner: the queue
|
|
21
|
+
* claims the run and dispatches here; the shared engine owns the run
|
|
22
|
+
* lifecycle, the agent loop and the confidence signal.
|
|
23
|
+
*
|
|
24
|
+
* The difference is the OUTPUT SINK. Insights never page and never open
|
|
25
|
+
* incidents (the roadmap's Preventive-lane rule), so postAnalysis writes the
|
|
26
|
+
* summary onto the insight row and NOTHING else — the quiet inbox.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/*
|
|
30
|
+
* Cap on the rendered evidence JSON embedded in the triage prompt. Latency
|
|
31
|
+
* evidence carries span-tree findings that can be large; the numbers matter,
|
|
32
|
+
* an exhaustive span listing does not.
|
|
33
|
+
*/
|
|
34
|
+
const MAX_RENDERED_EVIDENCE_CHARS: number = 4000;
|
|
35
|
+
|
|
36
|
+
/*
|
|
37
|
+
* The preventive-triage framing, prepended to the subject description. The
|
|
38
|
+
* engine's persona is written for a just-declared incident/alert, so the
|
|
39
|
+
* request context must recast the situation before the insight is described
|
|
40
|
+
* (the engine embeds contextSummary into the investigation question — the
|
|
41
|
+
* same mechanism the incident runner uses to convey its subject).
|
|
42
|
+
*/
|
|
43
|
+
const PREVENTIVE_TRIAGE_FRAMING: string = `IMPORTANT — this is PREVENTIVE TRIAGE, not an incident investigation: NO incident or alert exists and nobody has been paged. A deterministic statistical sensor (no AI involved) watched this project's telemetry and filed the finding described below, with the evidence it computed. Your job:
|
|
44
|
+
- Establish the most likely root cause of the finding.
|
|
45
|
+
- Estimate the blast radius: which services/users/operations are affected, and how badly.
|
|
46
|
+
- Recommend exactly ONE next action (the single most useful thing an engineer should do first).
|
|
47
|
+
Cite the evidence for every factual claim. If the telemetry cannot support a conclusion, say so plainly. Do not refer to "the incident" — there is none.`;
|
|
48
|
+
|
|
49
|
+
export default class InsightTriageRunner {
|
|
50
|
+
/*
|
|
51
|
+
* Execute a claimed triage run: load the insight, build its description
|
|
52
|
+
* and hand it to the shared engine. Called by AIInvestigationQueue
|
|
53
|
+
* after a successful claim. Never throws — failures are handed to the
|
|
54
|
+
* queue's retry policy so a claimed run is always finalized or requeued.
|
|
55
|
+
*/
|
|
56
|
+
@CaptureSpan()
|
|
57
|
+
public static async executeTriage(data: {
|
|
58
|
+
aiRunId: ObjectID;
|
|
59
|
+
projectId: ObjectID;
|
|
60
|
+
sentinelInsightId: ObjectID;
|
|
61
|
+
attemptCount: number;
|
|
62
|
+
}): Promise<void> {
|
|
63
|
+
const { aiRunId, projectId, sentinelInsightId, attemptCount } = data;
|
|
64
|
+
|
|
65
|
+
let contextSummary: string;
|
|
66
|
+
try {
|
|
67
|
+
const insight: AIInsight | null = await AIInsightService.findOneById({
|
|
68
|
+
id: sentinelInsightId,
|
|
69
|
+
select: {
|
|
70
|
+
_id: true,
|
|
71
|
+
insightType: true,
|
|
72
|
+
severity: true,
|
|
73
|
+
title: true,
|
|
74
|
+
detailMarkdown: true,
|
|
75
|
+
evidence: true,
|
|
76
|
+
serviceName: true,
|
|
77
|
+
traceId: true,
|
|
78
|
+
metricName: true,
|
|
79
|
+
firstSeenAt: true,
|
|
80
|
+
lastSeenAt: true,
|
|
81
|
+
occurrenceCount: true,
|
|
82
|
+
},
|
|
83
|
+
props: { isRoot: true },
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (!insight) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
"AI insight not found — it may have been deleted after the triage run was enqueued.",
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
contextSummary = this.buildInsightSummary(insight);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
/*
|
|
95
|
+
* Context assembly failed — the run is claimed, so hand it to the
|
|
96
|
+
* retry policy rather than leaving it Running until the sweeper.
|
|
97
|
+
*/
|
|
98
|
+
await AIInvestigationQueue.failOrRequeue({
|
|
99
|
+
aiRunId,
|
|
100
|
+
attemptCount,
|
|
101
|
+
errorMessage: `Failed to build insight context: ${
|
|
102
|
+
error instanceof Error ? error.message : String(error)
|
|
103
|
+
}`,
|
|
104
|
+
isPermanent: false,
|
|
105
|
+
});
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
await AIInvestigationEngine.executeRun({
|
|
110
|
+
aiRunId,
|
|
111
|
+
projectId,
|
|
112
|
+
attemptCount,
|
|
113
|
+
request: {
|
|
114
|
+
feature: AI_INSIGHT_TRIAGE_FEATURE,
|
|
115
|
+
contextSummary,
|
|
116
|
+
postAnalysis: async (postData: {
|
|
117
|
+
analysisMarkdown: string;
|
|
118
|
+
confidence: ConfidenceSignal;
|
|
119
|
+
result: ObservabilityAssistantResult;
|
|
120
|
+
}): Promise<void> => {
|
|
121
|
+
/*
|
|
122
|
+
* The quiet inbox — deliberately the ONLY write: no feed items,
|
|
123
|
+
* no workspace notification, no owner/on-call ping, no metrics,
|
|
124
|
+
* and no instrumentation-task trigger. Insights never page and
|
|
125
|
+
* never enter the notification pipeline (Preventive-lane rule);
|
|
126
|
+
* the summary waits on the Insights page until a human looks.
|
|
127
|
+
*/
|
|
128
|
+
await AIInsightService.updateOneById({
|
|
129
|
+
id: sentinelInsightId,
|
|
130
|
+
data: {
|
|
131
|
+
triageSummaryMarkdown: postData.analysisMarkdown,
|
|
132
|
+
triageCompletedAt: OneUptimeDate.getCurrentDate(),
|
|
133
|
+
},
|
|
134
|
+
props: { isRoot: true },
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
logger.debug(
|
|
138
|
+
`AI insights: triage summary posted for insight ${sentinelInsightId.toString()} (run ${aiRunId.toString()}, confident=${postData.confidence.confident} via ${postData.confidence.source}).`,
|
|
139
|
+
);
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Build the compact insight record that seeds the triage.
|
|
146
|
+
private static buildInsightSummary(insight: AIInsight): string {
|
|
147
|
+
const lines: Array<string> = [];
|
|
148
|
+
|
|
149
|
+
lines.push(PREVENTIVE_TRIAGE_FRAMING);
|
|
150
|
+
lines.push("");
|
|
151
|
+
lines.push("# Insight finding");
|
|
152
|
+
lines.push(`Finding type: ${insight.insightType || "N/A"}`);
|
|
153
|
+
lines.push(`Title: ${insight.title || "N/A"}`);
|
|
154
|
+
lines.push(`Severity: ${insight.severity || "N/A"}`);
|
|
155
|
+
|
|
156
|
+
if (insight.serviceName) {
|
|
157
|
+
lines.push(`Attributed service: ${insight.serviceName}`);
|
|
158
|
+
}
|
|
159
|
+
if (insight.metricName) {
|
|
160
|
+
lines.push(`Metric: ${insight.metricName}`);
|
|
161
|
+
}
|
|
162
|
+
if (insight.traceId) {
|
|
163
|
+
lines.push(`Representative trace id: ${insight.traceId}`);
|
|
164
|
+
}
|
|
165
|
+
if (insight.firstSeenAt) {
|
|
166
|
+
lines.push(
|
|
167
|
+
`First seen: ${OneUptimeDate.getDateAsFormattedString(insight.firstSeenAt)}`,
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
if (insight.lastSeenAt) {
|
|
171
|
+
lines.push(
|
|
172
|
+
`Last seen: ${OneUptimeDate.getDateAsFormattedString(insight.lastSeenAt)}`,
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
if (insight.occurrenceCount) {
|
|
176
|
+
lines.push(`Times detected: ${insight.occurrenceCount}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (insight.detailMarkdown) {
|
|
180
|
+
lines.push("");
|
|
181
|
+
lines.push(
|
|
182
|
+
"## Detector's evidence (deterministic, computed at detect time)",
|
|
183
|
+
);
|
|
184
|
+
lines.push(insight.detailMarkdown);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const renderedEvidence: string = this.renderEvidence(insight.evidence);
|
|
188
|
+
if (renderedEvidence) {
|
|
189
|
+
lines.push("");
|
|
190
|
+
lines.push("## Raw evidence values");
|
|
191
|
+
lines.push(renderedEvidence);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return lines.join("\n");
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/*
|
|
198
|
+
* Render the stored evidence JSON compactly: one line per populated
|
|
199
|
+
* section, values verbatim (the numbers ARE the evidence), capped so a
|
|
200
|
+
* large span-tree finding cannot flood the prompt.
|
|
201
|
+
*/
|
|
202
|
+
private static renderEvidence(
|
|
203
|
+
evidence: AIInsightEvidence | undefined,
|
|
204
|
+
): string {
|
|
205
|
+
if (!evidence) {
|
|
206
|
+
return "";
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const lines: Array<string> = [];
|
|
210
|
+
|
|
211
|
+
const sections: Array<keyof AIInsightEvidence> = [
|
|
212
|
+
"exception",
|
|
213
|
+
"logSpike",
|
|
214
|
+
"latency",
|
|
215
|
+
"metricDrift",
|
|
216
|
+
];
|
|
217
|
+
|
|
218
|
+
for (const section of sections) {
|
|
219
|
+
const value: AIInsightEvidence[keyof AIInsightEvidence] =
|
|
220
|
+
evidence[section];
|
|
221
|
+
|
|
222
|
+
if (!value) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
let rendered: string;
|
|
227
|
+
try {
|
|
228
|
+
rendered = JSON.stringify(value);
|
|
229
|
+
} catch {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (rendered.length > MAX_RENDERED_EVIDENCE_CHARS) {
|
|
234
|
+
rendered = `${rendered.substring(0, MAX_RENDERED_EVIDENCE_CHARS)}… (truncated)`;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
lines.push(`- ${section}: ${rendered}`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return lines.join("\n");
|
|
241
|
+
}
|
|
242
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import ObjectID from "../../../../../Types/ObjectID";
|
|
2
|
+
import AIRunType from "../../../../../Types/AI/AIRunType";
|
|
3
|
+
import AIRunStatus from "../../../../../Types/AI/AIRunStatus";
|
|
4
|
+
import AIInsight from "../../../../../Models/DatabaseModels/AIInsight";
|
|
5
|
+
import Project from "../../../../../Models/DatabaseModels/Project";
|
|
6
|
+
import LlmProvider from "../../../../../Models/DatabaseModels/LlmProvider";
|
|
7
|
+
import ProjectService from "../../../../Services/ProjectService";
|
|
8
|
+
import LlmProviderService from "../../../../Services/LlmProviderService";
|
|
9
|
+
import AIRunService from "../../../../Services/AIRunService";
|
|
10
|
+
import AIInsightService from "../../../../Services/AIInsightService";
|
|
11
|
+
import AIInvestigationQueue from "../InvestigationQueue";
|
|
12
|
+
import QueryHelper from "../../../../Types/Database/QueryHelper";
|
|
13
|
+
import logger from "../../../Logger";
|
|
14
|
+
import CaptureSpan from "../../../Telemetry/CaptureSpan";
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
* Per-insight LLM triage enqueue: a budgeted, read-only Investigation AIRun
|
|
18
|
+
* (triggeredByAiInsightId set) that posts a cited root-cause/blast-
|
|
19
|
+
* radius/suggested-action summary back onto the insight. Quiet-skips when
|
|
20
|
+
* no LLM provider is configured or the budget has no headroom, and dedupes
|
|
21
|
+
* to one non-terminal triage run per insight.
|
|
22
|
+
*
|
|
23
|
+
* The durable queue does the heavy lifting (claim CAS, concurrency cap,
|
|
24
|
+
* daily token budget, retries, TTL expiry, stale sweeping) — this module
|
|
25
|
+
* only owns the insight-specific gates, mirroring the posture of
|
|
26
|
+
* AIInvestigationEngine.isEnabledForProject: enableAi not disabled,
|
|
27
|
+
* the subject's own strict opt-in (Project.enableAiInsights, default
|
|
28
|
+
* FALSE), and a configured LLM provider.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
export interface InsightTriageResult {
|
|
32
|
+
// Set when a triage run was enqueued for the insight.
|
|
33
|
+
triageAiRunId?: ObjectID | undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default class InsightTriage {
|
|
37
|
+
/*
|
|
38
|
+
* NEVER throws — this runs inside the scanner's per-insight routing and a
|
|
39
|
+
* failed triage enqueue must not fail the scan itself. Every failure is
|
|
40
|
+
* logged and swallowed; an empty result means "no triage enqueued".
|
|
41
|
+
*/
|
|
42
|
+
@CaptureSpan()
|
|
43
|
+
public static async enqueueInsightTriage(data: {
|
|
44
|
+
insight: AIInsight;
|
|
45
|
+
}): Promise<InsightTriageResult> {
|
|
46
|
+
const { insight } = data;
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
if (!insight.id || !insight.projectId) {
|
|
50
|
+
return {};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const projectId: ObjectID = insight.projectId;
|
|
54
|
+
|
|
55
|
+
const project: Project | null = await ProjectService.findOneById({
|
|
56
|
+
id: projectId,
|
|
57
|
+
select: {
|
|
58
|
+
enableAi: true,
|
|
59
|
+
enableAiInsights: true,
|
|
60
|
+
},
|
|
61
|
+
props: { isRoot: true },
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (!project) {
|
|
65
|
+
logger.debug(
|
|
66
|
+
`AI insights: not enqueueing triage for insight ${insight.id.toString()} — project not found.`,
|
|
67
|
+
);
|
|
68
|
+
return {};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (project.enableAi === false) {
|
|
72
|
+
logger.debug(
|
|
73
|
+
`AI insights: not enqueueing triage for insight ${insight.id.toString()} — AI is disabled for the project.`,
|
|
74
|
+
);
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/*
|
|
79
|
+
* Strict opt-in — the column defaults to false. A triage run only
|
|
80
|
+
* exists because insights exist, so it shares the insights flag; the
|
|
81
|
+
* fix-tasks flag is a separate, stricter opt-in.
|
|
82
|
+
*/
|
|
83
|
+
if (project.enableAiInsights !== true) {
|
|
84
|
+
logger.debug(
|
|
85
|
+
`AI insights: not enqueueing triage for insight ${insight.id.toString()} — project has not opted in to AI insights.`,
|
|
86
|
+
);
|
|
87
|
+
return {};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const llmProvider: LlmProvider | null =
|
|
91
|
+
await LlmProviderService.getLLMProviderForProject(projectId);
|
|
92
|
+
|
|
93
|
+
if (!llmProvider) {
|
|
94
|
+
logger.debug(
|
|
95
|
+
`AI insights: not enqueueing triage for insight ${insight.id.toString()} — no LLM provider configured.`,
|
|
96
|
+
);
|
|
97
|
+
return {};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/*
|
|
101
|
+
* Dedupe: at most one non-terminal triage run per insight — the
|
|
102
|
+
* scanner refreshes recurring insights every tick, and a refresh must
|
|
103
|
+
* not fan out into duplicate triage runs.
|
|
104
|
+
*/
|
|
105
|
+
const nonTerminalTriageRunCount: number = (
|
|
106
|
+
await AIRunService.countBy({
|
|
107
|
+
query: {
|
|
108
|
+
runType: AIRunType.Investigation,
|
|
109
|
+
triggeredByAiInsightId: insight.id,
|
|
110
|
+
status: QueryHelper.notIn([
|
|
111
|
+
AIRunStatus.Completed,
|
|
112
|
+
AIRunStatus.Error,
|
|
113
|
+
AIRunStatus.Cancelled,
|
|
114
|
+
AIRunStatus.Stale,
|
|
115
|
+
]),
|
|
116
|
+
},
|
|
117
|
+
props: { isRoot: true },
|
|
118
|
+
})
|
|
119
|
+
).toNumber();
|
|
120
|
+
|
|
121
|
+
if (nonTerminalTriageRunCount > 0) {
|
|
122
|
+
logger.debug(
|
|
123
|
+
`AI insights: not enqueueing triage for insight ${insight.id.toString()} — a non-terminal triage run already exists.`,
|
|
124
|
+
);
|
|
125
|
+
return {};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/*
|
|
129
|
+
* Record the durable intent. The queue's own budget quiet-skip
|
|
130
|
+
* applies here too — a null result means no run was created (budget
|
|
131
|
+
* exhausted or the create failed) and the insight simply gets no
|
|
132
|
+
* triage this tick.
|
|
133
|
+
*/
|
|
134
|
+
const triageAiRunId: ObjectID | null = await AIInvestigationQueue.enqueue(
|
|
135
|
+
{
|
|
136
|
+
projectId,
|
|
137
|
+
subjectAIInsightId: insight.id,
|
|
138
|
+
},
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
if (!triageAiRunId) {
|
|
142
|
+
return {};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Link the insight to its triage run for the dashboard's live panel.
|
|
146
|
+
await AIInsightService.updateOneById({
|
|
147
|
+
id: insight.id,
|
|
148
|
+
data: {
|
|
149
|
+
triageAiRunId,
|
|
150
|
+
},
|
|
151
|
+
props: { isRoot: true },
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
return { triageAiRunId };
|
|
155
|
+
} catch (error) {
|
|
156
|
+
logger.error(
|
|
157
|
+
`AI insights: failed to enqueue triage for insight ${insight.id?.toString()}: ${error}`,
|
|
158
|
+
);
|
|
159
|
+
return {};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|