@oneuptime/common 12.0.4 → 12.0.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/AIRun.ts +38 -1
- package/Models/DatabaseModels/AlertFeed.ts +30 -0
- package/Models/DatabaseModels/Dashboard.ts +28 -0
- package/Models/DatabaseModels/Incident.ts +2 -0
- package/Models/DatabaseModels/IncidentEpisode.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IncidentFeed.ts +30 -0
- package/Models/DatabaseModels/IncidentPublicNote.ts +1 -0
- package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
- package/Models/DatabaseModels/LogSavedView.ts +33 -0
- package/Models/DatabaseModels/Project.ts +231 -9
- package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.ts +4 -4
- package/Models/DatabaseModels/StatusPage.ts +28 -0
- package/Models/DatabaseModels/StatusPageAnnouncement.ts +1 -0
- package/Server/API/AIAgentDataAPI.ts +44 -55
- package/Server/API/AIInvestigationAPI.ts +175 -17
- package/Server/API/DashboardAPI.ts +10 -10
- package/Server/API/StatusPageAPI.ts +38 -19
- package/Server/EnvironmentConfig.ts +16 -0
- package/Server/Infrastructure/ClickhouseConfig.ts +15 -1
- package/Server/Infrastructure/ClickhouseDatabase.ts +1 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.ts +27 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.ts +89 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.ts +27 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.ts +40 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Services/AIRunService.ts +78 -10
- package/Server/Services/AIService.ts +94 -22
- package/Server/Services/AlertFeedService.ts +5 -0
- package/Server/Services/AnalyticsDatabaseService.ts +29 -0
- package/Server/Services/DatabaseService.ts +43 -2
- package/Server/Services/IncidentFeedService.ts +5 -0
- package/Server/Services/LlmLogService.ts +46 -2
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +6 -0
- package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +4 -0
- package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +8 -5
- package/Server/Utils/AI/CodeFix/FixRunBudget.ts +90 -16
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +2 -0
- package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +2 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +223 -22
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +25 -24
- package/Server/Utils/AI/SRE/ConfidenceSignal.ts +182 -71
- package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +252 -43
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +25 -24
- package/Server/Utils/AI/SRE/InstrumentationTaskTrigger.ts +47 -13
- package/Server/Utils/AI/SRE/InvestigationGrader.ts +9 -5
- package/Server/Utils/AI/SRE/InvestigationQueue.ts +141 -24
- package/Server/Utils/AI/SRE/InvestigationSubjectLock.ts +66 -0
- package/Server/Utils/AI/SRE/PostedRootCause.ts +94 -3
- package/Server/Utils/AI/SRE/README.md +1 -1
- package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +132 -10
- package/Server/Utils/AnalyticsDatabase/ClusterConfig.ts +24 -0
- package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +29 -0
- package/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts +56 -0
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +46 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +1 -0
- package/Server/Utils/PasswordHash.ts +28 -4
- package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +251 -0
- package/Tests/App/Dashboard/EventStatusPanel.test.tsx +747 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +480 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1184 -0
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +500 -0
- package/Tests/App/Dashboard/PortMonitorCriteriaFilter.test.ts +93 -0
- package/Tests/App/StatusPage/PublicStatusPageAPIErrorHandling.test.ts +117 -0
- package/Tests/App/StatusPage/StatusPageModelAPIPolymorphism.test.ts +223 -0
- package/Tests/Models/DatabaseModels/PermissionCatalogueCoverage.test.ts +243 -0
- package/Tests/Server/API/AIAgentDataFixFromIncidentContext.test.ts +266 -0
- package/Tests/Server/API/AIInvestigationAPI.test.ts +594 -0
- package/Tests/Server/API/AIInvestigationCreateFixTask.test.ts +80 -0
- package/Tests/Server/API/DashboardMasterPasswordAPI.test.ts +172 -1
- package/Tests/Server/API/StatusPageMasterPasswordAPI.test.ts +335 -0
- package/Tests/Server/Services/AIRunCodeFixClaim.test.ts +59 -5
- package/Tests/Server/Services/AIRunHumanVerdict.test.ts +127 -58
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +396 -20
- package/Tests/Server/Services/AddMasterPasswordSaltMigration.test.ts +283 -0
- package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +25 -1
- package/Tests/Server/Services/DatabaseServicePerUserPasswordSalt.test.ts +45 -35
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsWithoutHooks.test.ts +54 -0
- package/Tests/Server/Services/FeedAIRunAssociation.test.ts +125 -0
- package/Tests/Server/Services/FixFromIncidentTaskTrigger.test.ts +418 -57
- package/Tests/Server/Services/InstrumentationTaskTrigger.test.ts +173 -14
- package/Tests/Server/Services/MasterPasswordScrypt.test.ts +567 -0
- package/Tests/Server/Services/SeparateIncidentAlertAiSettingsMigration.test.ts +194 -0
- package/Tests/Server/Utils/AI/AIAlertGating.test.ts +37 -4
- package/Tests/Server/Utils/AI/AIConfidenceSignal.test.ts +330 -29
- package/Tests/Server/Utils/AI/AIIncidentGating.test.ts +25 -0
- package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +293 -5
- package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +59 -1
- package/Tests/Server/Utils/AI/FixFromIncidentAutoTrigger.test.ts +342 -19
- package/Tests/Server/Utils/AI/FixRunBudget.test.ts +214 -30
- package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +2 -0
- package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +65 -17
- package/Tests/Server/Utils/AI/InvestigationQueueRemediationExecution.test.ts +3 -0
- package/Tests/Server/Utils/AI/InvestigationSettlement.test.ts +313 -20
- package/Tests/Server/Utils/AI/PostedRootCause.test.ts +254 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +4 -0
- package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +2 -0
- package/Tests/Server/Utils/AI/SubjectCodeFixRunDedupe.test.ts +44 -0
- package/Tests/Server/Utils/AnalyticsDatabase/ClusterAwareSchema.test.ts +30 -0
- package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaPortTimings.test.ts +212 -0
- package/Tests/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.test.ts +401 -0
- package/Tests/Server/Utils/Monitor/MonitorMetricUtilPortTimings.test.ts +243 -0
- package/Tests/Server/Utils/PasswordHash.test.ts +30 -0
- package/Tests/Types/Dashboard/DashboardTemplates.test.ts +111 -0
- package/Tests/Types/Monitor/CephMetricCatalog.test.ts +104 -0
- package/Tests/Types/Monitor/CriteriaFilter.test.ts +4 -0
- package/Tests/Types/Monitor/DockerMetricCatalog.test.ts +109 -0
- package/Tests/Types/Monitor/DockerSwarmMetricCatalog.test.ts +118 -0
- package/Tests/Types/Monitor/HostMetricCatalog.test.ts +104 -0
- package/Tests/Types/Monitor/IotMetricCatalog.test.ts +104 -0
- package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +118 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +42 -0
- package/Tests/Types/Monitor/MonitorStep.test.ts +38 -0
- package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +75 -0
- package/Tests/Types/Monitor/PodmanMetricCatalog.test.ts +109 -0
- package/Tests/Types/Monitor/ProxmoxMetricCatalog.test.ts +107 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.test.ts +151 -0
- package/Tests/Types/Permission.test.ts +137 -0
- package/Tests/Types/Rum/SessionReplayMaskingMode.test.ts +101 -0
- package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +5 -5
- package/Tests/UI/Components/CardModelDetailEdit.test.tsx +3 -5
- package/Tests/UI/Components/ErrorBoundary.test.tsx +158 -0
- package/Tests/UI/Components/FeedItemSafeMode.test.tsx +74 -0
- package/Tests/UI/Components/MoreMenu.test.tsx +756 -0
- package/Tests/UI/Components/StatusPage/ResourceGroupSection.test.tsx +62 -0
- package/Tests/UI/Monitor/PortMonitorView.test.tsx +237 -0
- package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +91 -0
- package/Tests/UI/Utils/DownloadFile.test.ts +103 -0
- package/Tests/UI/Utils/ErrorSupportBundle.test.ts +582 -0
- package/Tests/UI/Utils/Project.test.ts +31 -0
- package/Tests/UI/Utils/StatusPageModelAPIInjection.test.ts +245 -0
- package/Tests/UI/Utils/UseDashboardGridDnd.test.tsx +820 -0
- package/Tests/Utils/Dashboard/DashboardViewConfig.test.ts +329 -0
- package/Tests/Utils/Dashboard/GridLayout.test.ts +951 -0
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +117 -0
- package/Tests/Utils/RecordingRuleExpression.test.ts +327 -0
- package/Tests/Utils/StatusPage/GroupNestingLayout.test.ts +186 -0
- package/Tests/Utils/StatusPage/GroupTree.test.ts +456 -0
- package/Tests/Utils/StatusPage/OverviewGroupHierarchyVisibility.test.ts +588 -0
- package/Tests/Utils/Telemetry/SavedViewTimeRange.test.ts +244 -0
- package/Tests/Utils/Telemetry/TelemetryQueryTimeRange.test.ts +825 -0
- package/Types/AI/AIRunCodeFixRecommendation.ts +17 -0
- package/Types/AI/CodeFixTaskContext.ts +63 -3
- package/Types/AI/CodeFixTaskType.ts +3 -3
- package/Types/HashedString.ts +4 -3
- package/Types/Monitor/CriteriaFilter.ts +4 -0
- package/Types/Monitor/DomainMonitor/DomainLookupMethod.ts +23 -0
- package/Types/Monitor/DomainMonitor/DomainMonitorResponse.ts +7 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +24 -7
- package/Types/Monitor/MonitorMetricType.ts +8 -0
- package/Types/Monitor/MonitorStep.ts +10 -1
- package/Types/Monitor/MonitorStepDomainMonitor.ts +21 -0
- package/Types/Monitor/PortMonitor/PortMonitorTimings.ts +10 -0
- package/Types/Permission.ts +23 -175
- package/Types/Probe/ProbeMonitorResponse.ts +6 -0
- package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +2 -3
- package/UI/Components/ErrorBoundary.tsx +138 -11
- package/UI/Components/Feed/FeedItem.tsx +9 -2
- package/UI/Components/ModelDetail/CardModelDetail.tsx +0 -12
- package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +12 -2
- package/UI/Components/MoreMenu/MoreMenu.tsx +285 -97
- package/UI/Components/MoreMenu/MoreMenuItem.tsx +8 -5
- package/UI/Utils/DownloadFile.ts +16 -8
- package/UI/Utils/ErrorSupportBundle.ts +805 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +19 -8
- package/UI/Utils/Project.ts +4 -0
- package/UI/Utils/StatusPage.ts +8 -2
- package/UI/Utils/UseDashboardGridDnd.ts +917 -0
- package/Utils/Dashboard/DashboardViewConfig.ts +80 -36
- package/Utils/Dashboard/GridLayout.ts +523 -0
- package/Utils/Metrics/RecordingRuleExpression.ts +19 -17
- package/Utils/Monitor/MonitorMetricType.ts +44 -2
- package/Utils/StatusPage/GroupNestingLayout.ts +69 -0
- package/Utils/StatusPage/GroupTree.ts +157 -66
- package/Utils/StatusPage/ResourceUptime.ts +37 -2
- package/Utils/Telemetry/SavedViewTimeRange.ts +114 -0
- package/Utils/Telemetry/TelemetryQueryTimeRange.ts +334 -0
- package/build/dist/Models/DatabaseModels/AIRun.js +39 -1
- package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertFeed.js +32 -0
- package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Dashboard.js +29 -0
- package/build/dist/Models/DatabaseModels/Dashboard.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +2 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentFeed.js +32 -0
- package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LogSavedView.js +33 -0
- package/build/dist/Models/DatabaseModels/LogSavedView.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +241 -11
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.js +4 -4
- package/build/dist/Models/DatabaseModels/StatusPage.js +29 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +1 -0
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
- package/build/dist/Server/API/AIAgentDataAPI.js +28 -46
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +111 -11
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +8 -5
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +29 -11
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +14 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js +12 -1
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseDatabase.js +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseDatabase.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AIRunService.js +58 -12
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +74 -21
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertFeedService.js +3 -0
- package/build/dist/Server/Services/AlertFeedService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +29 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +21 -2
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentFeedService.js +3 -0
- package/build/dist/Server/Services/IncidentFeedService.js.map +1 -1
- package/build/dist/Server/Services/LlmLogService.js +22 -1
- package/build/dist/Server/Services/LlmLogService.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +3 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +4 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +8 -5
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +63 -24
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +2 -0
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +2 -0
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +156 -28
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +21 -19
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js +128 -49
- package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js +170 -31
- package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +21 -19
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js +33 -9
- package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +9 -5
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +121 -41
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationSubjectLock.js +46 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationSubjectLock.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js +61 -14
- package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +79 -1
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/ClusterConfig.js +21 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/ClusterConfig.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +20 -3
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js +43 -0
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/PasswordHash.js +25 -4
- package/build/dist/Server/Utils/PasswordHash.js.map +1 -1
- package/build/dist/Types/AI/AIRunCodeFixRecommendation.js +18 -0
- package/build/dist/Types/AI/AIRunCodeFixRecommendation.js.map +1 -0
- package/build/dist/Types/AI/CodeFixTaskContext.js +23 -3
- package/build/dist/Types/AI/CodeFixTaskContext.js.map +1 -1
- package/build/dist/Types/AI/CodeFixTaskType.js +3 -3
- package/build/dist/Types/HashedString.js +4 -3
- package/build/dist/Types/HashedString.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +4 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/DomainMonitor/DomainLookupMethod.js +24 -0
- package/build/dist/Types/Monitor/DomainMonitor/DomainLookupMethod.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +24 -7
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorMetricType.js +7 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +6 -1
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js +15 -0
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/PortMonitor/PortMonitorTimings.js +2 -0
- package/build/dist/Types/Monitor/PortMonitor/PortMonitorTimings.js.map +1 -0
- package/build/dist/Types/Permission.js +23 -155
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +2 -5
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
- package/build/dist/UI/Components/ErrorBoundary.js +67 -8
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js +2 -2
- package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +0 -12
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +12 -2
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +193 -65
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
- package/build/dist/UI/Utils/DownloadFile.js +15 -8
- package/build/dist/UI/Utils/DownloadFile.js.map +1 -1
- package/build/dist/UI/Utils/ErrorSupportBundle.js +476 -0
- package/build/dist/UI/Utils/ErrorSupportBundle.js.map +1 -0
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -8
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/Project.js +3 -0
- package/build/dist/UI/Utils/Project.js.map +1 -1
- package/build/dist/UI/Utils/StatusPage.js +4 -4
- package/build/dist/UI/Utils/StatusPage.js.map +1 -1
- package/build/dist/UI/Utils/UseDashboardGridDnd.js +551 -0
- package/build/dist/UI/Utils/UseDashboardGridDnd.js.map +1 -0
- package/build/dist/Utils/Dashboard/DashboardViewConfig.js +42 -26
- package/build/dist/Utils/Dashboard/DashboardViewConfig.js.map +1 -1
- package/build/dist/Utils/Dashboard/GridLayout.js +338 -0
- package/build/dist/Utils/Dashboard/GridLayout.js.map +1 -0
- package/build/dist/Utils/Metrics/RecordingRuleExpression.js +19 -17
- package/build/dist/Utils/Metrics/RecordingRuleExpression.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +38 -6
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js +46 -0
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js.map +1 -1
- package/build/dist/Utils/StatusPage/GroupTree.js +79 -34
- package/build/dist/Utils/StatusPage/GroupTree.js.map +1 -1
- package/build/dist/Utils/StatusPage/ResourceUptime.js +22 -1
- package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
- package/build/dist/Utils/Telemetry/SavedViewTimeRange.js +79 -0
- package/build/dist/Utils/Telemetry/SavedViewTimeRange.js.map +1 -0
- package/build/dist/Utils/Telemetry/TelemetryQueryTimeRange.js +236 -0
- package/build/dist/Utils/Telemetry/TelemetryQueryTimeRange.js.map +1 -0
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ import FixRunBudget, {
|
|
|
4
4
|
} from "../../../../Server/Utils/AI/CodeFix/FixRunBudget";
|
|
5
5
|
import ProjectService from "../../../../Server/Services/ProjectService";
|
|
6
6
|
import AIRunService from "../../../../Server/Services/AIRunService";
|
|
7
|
+
import QueryHelper from "../../../../Server/Types/Database/QueryHelper";
|
|
7
8
|
import Project from "../../../../Models/DatabaseModels/Project";
|
|
8
9
|
import AIRunType from "../../../../Types/AI/AIRunType";
|
|
9
10
|
import BadDataException from "../../../../Types/Exception/BadDataException";
|
|
@@ -12,11 +13,11 @@ import PositiveNumber from "../../../../Types/PositiveNumber";
|
|
|
12
13
|
import { describe, expect, test, afterEach } from "@jest/globals";
|
|
13
14
|
|
|
14
15
|
/*
|
|
15
|
-
* The per-project daily fix-run budget (G11 guardrail):
|
|
16
|
-
*
|
|
17
|
-
* token budget, an UNSET limit is NOT unlimited — fix runs open pull
|
|
16
|
+
* The per-project daily fix-run budget (G11 guardrail): incident, alert and
|
|
17
|
+
* subjectless CodeFix AIRuns each count only against their own lane. Unlike
|
|
18
|
+
* the token budget, an UNSET limit is NOT unlimited — fix runs open pull
|
|
18
19
|
* requests on customer repositories, so the default cap applies. 0 pauses
|
|
19
|
-
*
|
|
20
|
+
* that lane entirely (the same kill-switch semantics as the token budget).
|
|
20
21
|
*/
|
|
21
22
|
|
|
22
23
|
const projectId: ObjectID = ObjectID.generate();
|
|
@@ -92,24 +93,37 @@ describe("FixRunBudget.evaluate (pure decision)", () => {
|
|
|
92
93
|
});
|
|
93
94
|
|
|
94
95
|
describe("FixRunBudget.describeRejection", () => {
|
|
95
|
-
test("paused rejection names the setting and
|
|
96
|
+
test("paused incident rejection names the incident setting and destination", () => {
|
|
96
97
|
const message: string = FixRunBudget.describeRejection(
|
|
97
98
|
FixRunBudget.evaluate({ configuredLimit: 0, runsToday: 0 }),
|
|
99
|
+
{ incidentId: ObjectID.generate() },
|
|
98
100
|
);
|
|
99
101
|
|
|
100
|
-
expect(message).toMatch(/Daily AI Fix Task Limit/);
|
|
102
|
+
expect(message).toMatch(/Daily Incident AI Fix Task Limit/);
|
|
103
|
+
expect(message).toMatch(/Incidents > Settings > AI/);
|
|
101
104
|
expect(message).toMatch(/0/);
|
|
102
105
|
});
|
|
103
106
|
|
|
104
|
-
test("over-budget rejection names the
|
|
107
|
+
test("over-budget alert rejection names the alert setting and destination", () => {
|
|
105
108
|
const message: string = FixRunBudget.describeRejection(
|
|
106
109
|
FixRunBudget.evaluate({ configuredLimit: 10, runsToday: 10 }),
|
|
110
|
+
{ alertId: ObjectID.generate() },
|
|
107
111
|
);
|
|
108
112
|
|
|
109
113
|
expect(message).toMatch(/10 of 10/);
|
|
110
|
-
expect(message).toMatch(/Daily AI Fix Task Limit/);
|
|
114
|
+
expect(message).toMatch(/Daily Alert AI Fix Task Limit/);
|
|
115
|
+
expect(message).toMatch(/Alerts > Settings > AI/);
|
|
111
116
|
expect(message).toMatch(new RegExp(String(DEFAULT_DAILY_FIX_RUN_LIMIT)));
|
|
112
117
|
});
|
|
118
|
+
|
|
119
|
+
test("subjectless rejection points to the always-visible AI Guardrails page", () => {
|
|
120
|
+
const message: string = FixRunBudget.describeRejection(
|
|
121
|
+
FixRunBudget.evaluate({ configuredLimit: 0, runsToday: 0 }),
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
expect(message).toMatch(/Daily Other AI Fix Task Limit/);
|
|
125
|
+
expect(message).toMatch(/Project Settings > AI > AI Guardrails/);
|
|
126
|
+
});
|
|
113
127
|
});
|
|
114
128
|
|
|
115
129
|
describe("FixRunBudget.getBudgetStatus (IO wiring)", () => {
|
|
@@ -117,12 +131,46 @@ describe("FixRunBudget.getBudgetStatus (IO wiring)", () => {
|
|
|
117
131
|
jest.restoreAllMocks();
|
|
118
132
|
});
|
|
119
133
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
134
|
+
function mockSubjectOperators(): {
|
|
135
|
+
isNull: Record<string, string>;
|
|
136
|
+
notNull: Record<string, string>;
|
|
137
|
+
} {
|
|
138
|
+
const isNull: Record<string, string> = { operator: "is-null" };
|
|
139
|
+
const notNull: Record<string, string> = { operator: "not-null" };
|
|
140
|
+
|
|
141
|
+
jest.spyOn(QueryHelper, "isNull").mockReturnValue(isNull);
|
|
142
|
+
jest.spyOn(QueryHelper, "notNull").mockReturnValue(notNull);
|
|
125
143
|
|
|
144
|
+
return { isNull, notNull };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
test("rejects a run carrying both subject types before reading project settings", async () => {
|
|
148
|
+
const findProject: jest.SpyInstance = jest.spyOn(
|
|
149
|
+
ProjectService,
|
|
150
|
+
"findOneById",
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
await expect(
|
|
154
|
+
FixRunBudget.getBudgetStatus(projectId, {
|
|
155
|
+
incidentId: ObjectID.generate(),
|
|
156
|
+
alertId: ObjectID.generate(),
|
|
157
|
+
}),
|
|
158
|
+
).rejects.toThrow(/both an incident and an alert/);
|
|
159
|
+
|
|
160
|
+
expect(findProject).not.toHaveBeenCalled();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test("subjectless callers retain the fallback limit and count only subjectless CodeFix runs", async () => {
|
|
164
|
+
const operators: ReturnType<typeof mockSubjectOperators> =
|
|
165
|
+
mockSubjectOperators();
|
|
166
|
+
const findProject: jest.SpyInstance = jest
|
|
167
|
+
.spyOn(ProjectService, "findOneById")
|
|
168
|
+
.mockResolvedValue({
|
|
169
|
+
id: projectId,
|
|
170
|
+
aiDailyFixTaskLimit: 10,
|
|
171
|
+
incidentAiDailyFixTaskLimit: 1,
|
|
172
|
+
alertAiDailyFixTaskLimit: 2,
|
|
173
|
+
} as unknown as Project);
|
|
126
174
|
const countBy: jest.SpyInstance = jest
|
|
127
175
|
.spyOn(AIRunService, "countBy")
|
|
128
176
|
.mockResolvedValue(new PositiveNumber(4));
|
|
@@ -136,44 +184,180 @@ describe("FixRunBudget.getBudgetStatus (IO wiring)", () => {
|
|
|
136
184
|
paused: false,
|
|
137
185
|
runsToday: 4,
|
|
138
186
|
});
|
|
187
|
+
expect(findProject).toHaveBeenCalledWith(
|
|
188
|
+
expect.objectContaining({ select: { aiDailyFixTaskLimit: true } }),
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const query: Record<string, unknown> = (
|
|
192
|
+
countBy.mock.calls[0]![0] as { query: Record<string, unknown> }
|
|
193
|
+
).query;
|
|
194
|
+
expect(query["projectId"]).toBe(projectId);
|
|
195
|
+
expect(query["runType"]).toBe(AIRunType.CodeFix);
|
|
196
|
+
expect(query["triggeredByIncidentId"]).toBe(operators.isNull);
|
|
197
|
+
expect(query["triggeredByAlertId"]).toBe(operators.isNull);
|
|
198
|
+
// createdAt >= UTC midnight rides in a QueryHelper find operator.
|
|
199
|
+
expect(query["createdAt"]).toBeDefined();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test("an explicitly empty subject from SubjectCodeFixRun also stays in the subjectless lane", async () => {
|
|
203
|
+
const operators: ReturnType<typeof mockSubjectOperators> =
|
|
204
|
+
mockSubjectOperators();
|
|
205
|
+
const findProject: jest.SpyInstance = jest
|
|
206
|
+
.spyOn(ProjectService, "findOneById")
|
|
207
|
+
.mockResolvedValue({
|
|
208
|
+
id: projectId,
|
|
209
|
+
aiDailyFixTaskLimit: 3,
|
|
210
|
+
incidentAiDailyFixTaskLimit: 0,
|
|
211
|
+
alertAiDailyFixTaskLimit: 0,
|
|
212
|
+
} as unknown as Project);
|
|
213
|
+
const countBy: jest.SpyInstance = jest
|
|
214
|
+
.spyOn(AIRunService, "countBy")
|
|
215
|
+
.mockResolvedValue(new PositiveNumber(2));
|
|
216
|
+
|
|
217
|
+
const decision: FixRunBudgetDecision = await FixRunBudget.getBudgetStatus(
|
|
218
|
+
projectId,
|
|
219
|
+
{ incidentId: undefined, alertId: undefined },
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
expect(decision.limit).toBe(3);
|
|
223
|
+
expect(decision.allowed).toBe(true);
|
|
224
|
+
expect(findProject).toHaveBeenCalledWith(
|
|
225
|
+
expect.objectContaining({ select: { aiDailyFixTaskLimit: true } }),
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const query: Record<string, unknown> = (
|
|
229
|
+
countBy.mock.calls[0]![0] as { query: Record<string, unknown> }
|
|
230
|
+
).query;
|
|
231
|
+
expect(query["triggeredByIncidentId"]).toBe(operators.isNull);
|
|
232
|
+
expect(query["triggeredByAlertId"]).toBe(operators.isNull);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test("incident callers select the incident limit and count only incident CodeFix runs", async () => {
|
|
236
|
+
const operators: ReturnType<typeof mockSubjectOperators> =
|
|
237
|
+
mockSubjectOperators();
|
|
238
|
+
const findProject: jest.SpyInstance = jest
|
|
239
|
+
.spyOn(ProjectService, "findOneById")
|
|
240
|
+
.mockResolvedValue({
|
|
241
|
+
id: projectId,
|
|
242
|
+
aiDailyFixTaskLimit: 99,
|
|
243
|
+
incidentAiDailyFixTaskLimit: 5,
|
|
244
|
+
alertAiDailyFixTaskLimit: 1,
|
|
245
|
+
} as unknown as Project);
|
|
246
|
+
const countBy: jest.SpyInstance = jest
|
|
247
|
+
.spyOn(AIRunService, "countBy")
|
|
248
|
+
.mockResolvedValue(new PositiveNumber(4));
|
|
249
|
+
|
|
250
|
+
const decision: FixRunBudgetDecision = await FixRunBudget.getBudgetStatus(
|
|
251
|
+
projectId,
|
|
252
|
+
{ incidentId: ObjectID.generate() },
|
|
253
|
+
);
|
|
139
254
|
|
|
140
|
-
expect(
|
|
255
|
+
expect(decision).toEqual({
|
|
256
|
+
allowed: true,
|
|
257
|
+
limit: 5,
|
|
258
|
+
paused: false,
|
|
259
|
+
runsToday: 4,
|
|
260
|
+
});
|
|
261
|
+
expect(findProject).toHaveBeenCalledWith(
|
|
141
262
|
expect.objectContaining({
|
|
142
|
-
|
|
143
|
-
projectId,
|
|
144
|
-
runType: AIRunType.CodeFix,
|
|
145
|
-
// createdAt >= UTC midnight rides in a QueryHelper find operator.
|
|
146
|
-
createdAt: expect.anything(),
|
|
147
|
-
}),
|
|
148
|
-
props: expect.objectContaining({ isRoot: true }),
|
|
263
|
+
select: { incidentAiDailyFixTaskLimit: true },
|
|
149
264
|
}),
|
|
150
265
|
);
|
|
266
|
+
|
|
267
|
+
const query: Record<string, unknown> = (
|
|
268
|
+
countBy.mock.calls[0]![0] as { query: Record<string, unknown> }
|
|
269
|
+
).query;
|
|
270
|
+
expect(query["runType"]).toBe(AIRunType.CodeFix);
|
|
271
|
+
expect(query["triggeredByIncidentId"]).toBe(operators.notNull);
|
|
272
|
+
expect(query["triggeredByAlertId"]).toBe(operators.isNull);
|
|
151
273
|
});
|
|
152
274
|
|
|
153
|
-
test("
|
|
275
|
+
test("alert callers select the alert limit and count only alert CodeFix runs", async () => {
|
|
276
|
+
const operators: ReturnType<typeof mockSubjectOperators> =
|
|
277
|
+
mockSubjectOperators();
|
|
278
|
+
const findProject: jest.SpyInstance = jest
|
|
279
|
+
.spyOn(ProjectService, "findOneById")
|
|
280
|
+
.mockResolvedValue({
|
|
281
|
+
id: projectId,
|
|
282
|
+
aiDailyFixTaskLimit: 99,
|
|
283
|
+
incidentAiDailyFixTaskLimit: 1,
|
|
284
|
+
alertAiDailyFixTaskLimit: 7,
|
|
285
|
+
} as unknown as Project);
|
|
286
|
+
const countBy: jest.SpyInstance = jest
|
|
287
|
+
.spyOn(AIRunService, "countBy")
|
|
288
|
+
.mockResolvedValue(new PositiveNumber(6));
|
|
289
|
+
|
|
290
|
+
const decision: FixRunBudgetDecision = await FixRunBudget.getBudgetStatus(
|
|
291
|
+
projectId,
|
|
292
|
+
{ alertId: ObjectID.generate() },
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
expect(decision).toEqual({
|
|
296
|
+
allowed: true,
|
|
297
|
+
limit: 7,
|
|
298
|
+
paused: false,
|
|
299
|
+
runsToday: 6,
|
|
300
|
+
});
|
|
301
|
+
expect(findProject).toHaveBeenCalledWith(
|
|
302
|
+
expect.objectContaining({ select: { alertAiDailyFixTaskLimit: true } }),
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
const query: Record<string, unknown> = (
|
|
306
|
+
countBy.mock.calls[0]![0] as { query: Record<string, unknown> }
|
|
307
|
+
).query;
|
|
308
|
+
expect(query["runType"]).toBe(AIRunType.CodeFix);
|
|
309
|
+
expect(query["triggeredByIncidentId"]).toBe(operators.isNull);
|
|
310
|
+
expect(query["triggeredByAlertId"]).toBe(operators.notNull);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
test("pausing the incident lane short-circuits without counting another lane", async () => {
|
|
154
314
|
jest.spyOn(ProjectService, "findOneById").mockResolvedValue({
|
|
155
315
|
id: projectId,
|
|
156
|
-
aiDailyFixTaskLimit:
|
|
316
|
+
aiDailyFixTaskLimit: 50,
|
|
317
|
+
incidentAiDailyFixTaskLimit: 0,
|
|
318
|
+
alertAiDailyFixTaskLimit: 50,
|
|
157
319
|
} as unknown as Project);
|
|
320
|
+
const countBy: jest.SpyInstance = jest.spyOn(AIRunService, "countBy");
|
|
321
|
+
|
|
322
|
+
const decision: FixRunBudgetDecision = await FixRunBudget.getBudgetStatus(
|
|
323
|
+
projectId,
|
|
324
|
+
{ incidentId: ObjectID.generate() },
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
expect(decision.allowed).toBe(false);
|
|
328
|
+
expect(decision.paused).toBe(true);
|
|
329
|
+
expect(countBy).not.toHaveBeenCalled();
|
|
330
|
+
});
|
|
158
331
|
|
|
332
|
+
test("pausing the alert lane short-circuits without counting another lane", async () => {
|
|
333
|
+
jest.spyOn(ProjectService, "findOneById").mockResolvedValue({
|
|
334
|
+
id: projectId,
|
|
335
|
+
aiDailyFixTaskLimit: 50,
|
|
336
|
+
incidentAiDailyFixTaskLimit: 50,
|
|
337
|
+
alertAiDailyFixTaskLimit: 0,
|
|
338
|
+
} as unknown as Project);
|
|
159
339
|
const countBy: jest.SpyInstance = jest.spyOn(AIRunService, "countBy");
|
|
160
340
|
|
|
161
|
-
const decision: FixRunBudgetDecision =
|
|
162
|
-
|
|
341
|
+
const decision: FixRunBudgetDecision = await FixRunBudget.getBudgetStatus(
|
|
342
|
+
projectId,
|
|
343
|
+
{ alertId: ObjectID.generate() },
|
|
344
|
+
);
|
|
163
345
|
|
|
164
346
|
expect(decision.allowed).toBe(false);
|
|
165
347
|
expect(decision.paused).toBe(true);
|
|
166
348
|
expect(countBy).not.toHaveBeenCalled();
|
|
167
349
|
});
|
|
168
350
|
|
|
169
|
-
test("a missing project row
|
|
351
|
+
test("a missing project row uses the default cap in the requested lane (fail-safe, not fail-open)", async () => {
|
|
170
352
|
jest.spyOn(ProjectService, "findOneById").mockResolvedValue(null);
|
|
171
353
|
jest
|
|
172
354
|
.spyOn(AIRunService, "countBy")
|
|
173
355
|
.mockResolvedValue(new PositiveNumber(DEFAULT_DAILY_FIX_RUN_LIMIT));
|
|
174
356
|
|
|
175
|
-
const decision: FixRunBudgetDecision =
|
|
176
|
-
|
|
357
|
+
const decision: FixRunBudgetDecision = await FixRunBudget.getBudgetStatus(
|
|
358
|
+
projectId,
|
|
359
|
+
{ alertId: ObjectID.generate() },
|
|
360
|
+
);
|
|
177
361
|
|
|
178
362
|
expect(decision.limit).toBe(DEFAULT_DAILY_FIX_RUN_LIMIT);
|
|
179
363
|
expect(decision.allowed).toBe(false);
|
|
@@ -199,7 +383,7 @@ describe("FixRunBudget.assertWithinBudget", () => {
|
|
|
199
383
|
).resolves.toBeUndefined();
|
|
200
384
|
});
|
|
201
385
|
|
|
202
|
-
test("over budget throws a BadDataException naming the setting", async () => {
|
|
386
|
+
test("over budget throws a BadDataException naming the subjectless setting", async () => {
|
|
203
387
|
jest.spyOn(ProjectService, "findOneById").mockResolvedValue({
|
|
204
388
|
id: projectId,
|
|
205
389
|
aiDailyFixTaskLimit: 5,
|
|
@@ -212,7 +396,7 @@ describe("FixRunBudget.assertWithinBudget", () => {
|
|
|
212
396
|
BadDataException,
|
|
213
397
|
);
|
|
214
398
|
await expect(FixRunBudget.assertWithinBudget(projectId)).rejects.toThrow(
|
|
215
|
-
/Daily AI Fix Task Limit/,
|
|
399
|
+
/Daily Other AI Fix Task Limit/,
|
|
216
400
|
);
|
|
217
401
|
});
|
|
218
402
|
});
|
|
@@ -8,6 +8,7 @@ import AIService from "../../../../../Server/Services/AIService";
|
|
|
8
8
|
import ProjectService from "../../../../../Server/Services/ProjectService";
|
|
9
9
|
import Project from "../../../../../Models/DatabaseModels/Project";
|
|
10
10
|
import AIRun from "../../../../../Models/DatabaseModels/AIRun";
|
|
11
|
+
import AIRunCodeFixRecommendation from "../../../../../Types/AI/AIRunCodeFixRecommendation";
|
|
11
12
|
import AIRunStatus from "../../../../../Types/AI/AIRunStatus";
|
|
12
13
|
import AIRunType from "../../../../../Types/AI/AIRunType";
|
|
13
14
|
import ObjectID from "../../../../../Types/ObjectID";
|
|
@@ -76,6 +77,7 @@ describe("AIInvestigationQueue — insight subject", () => {
|
|
|
76
77
|
data: expect.objectContaining({
|
|
77
78
|
status: AIRunStatus.Queued,
|
|
78
79
|
triggeredByAiInsightId: insightId,
|
|
80
|
+
codeFixRecommendation: AIRunCodeFixRecommendation.NotRecommended,
|
|
79
81
|
}),
|
|
80
82
|
props: expect.objectContaining({ isRoot: true }),
|
|
81
83
|
}),
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import InvestigationGrader from "../../../../Server/Utils/AI/SRE/InvestigationGrader";
|
|
2
|
+
import PostedRootCause from "../../../../Server/Utils/AI/SRE/PostedRootCause";
|
|
2
3
|
import AIRunService from "../../../../Server/Services/AIRunService";
|
|
3
4
|
import IncidentService from "../../../../Server/Services/IncidentService";
|
|
4
|
-
import IncidentFeedService from "../../../../Server/Services/IncidentFeedService";
|
|
5
5
|
import AIService, {
|
|
6
6
|
AILogResponse,
|
|
7
7
|
} from "../../../../Server/Services/AIService";
|
|
8
8
|
import AIRun from "../../../../Models/DatabaseModels/AIRun";
|
|
9
9
|
import Incident from "../../../../Models/DatabaseModels/Incident";
|
|
10
|
-
import IncidentFeed from "../../../../Models/DatabaseModels/IncidentFeed";
|
|
11
10
|
import AIRunAutoGrade from "../../../../Types/AI/AIRunAutoGrade";
|
|
12
11
|
import ObjectID from "../../../../Types/ObjectID";
|
|
13
12
|
import { describe, expect, test, afterEach } from "@jest/globals";
|
|
@@ -24,19 +23,20 @@ import { describe, expect, test, afterEach } from "@jest/globals";
|
|
|
24
23
|
|
|
25
24
|
const incidentId: ObjectID = ObjectID.generate();
|
|
26
25
|
const projectId: ObjectID = ObjectID.generate();
|
|
26
|
+
const runCompletedAt: Date = new Date("2026-08-07T12:00:00.000Z");
|
|
27
27
|
|
|
28
28
|
function fakeRun(autoGrade?: AIRunAutoGrade): AIRun {
|
|
29
|
-
return {
|
|
29
|
+
return {
|
|
30
|
+
id: ObjectID.generate(),
|
|
31
|
+
autoGrade,
|
|
32
|
+
completedAt: runCompletedAt,
|
|
33
|
+
} as unknown as AIRun;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
function fakeIncident(rootCause?: string | undefined): Incident {
|
|
33
37
|
return { id: incidentId, rootCause } as unknown as Incident;
|
|
34
38
|
}
|
|
35
39
|
|
|
36
|
-
function fakeFeedItem(markdown: string): IncidentFeed {
|
|
37
|
-
return { feedInfoInMarkdown: markdown } as unknown as IncidentFeed;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
40
|
function fakeLlmResponse(content: string): AILogResponse {
|
|
41
41
|
return { content } as unknown as AILogResponse;
|
|
42
42
|
}
|
|
@@ -221,11 +221,14 @@ describe("InvestigationGrader.gradeInvestigationOnResolve", () => {
|
|
|
221
221
|
});
|
|
222
222
|
|
|
223
223
|
test("no posted analysis (no RootCause feed item) → no LLM call", async () => {
|
|
224
|
-
|
|
224
|
+
const run: AIRun = fakeRun();
|
|
225
|
+
jest.spyOn(AIRunService, "findOneBy").mockResolvedValue(run);
|
|
225
226
|
jest
|
|
226
227
|
.spyOn(IncidentService, "findOneById")
|
|
227
228
|
.mockResolvedValue(fakeIncident("db down"));
|
|
228
|
-
jest.
|
|
229
|
+
const getForInvestigation: jest.SpyInstance = jest
|
|
230
|
+
.spyOn(PostedRootCause, "getForInvestigation")
|
|
231
|
+
.mockResolvedValue(null);
|
|
229
232
|
const executeWithLogging: jest.SpyInstance = jest.spyOn(
|
|
230
233
|
AIService,
|
|
231
234
|
"executeWithLogging",
|
|
@@ -236,9 +239,56 @@ describe("InvestigationGrader.gradeInvestigationOnResolve", () => {
|
|
|
236
239
|
projectId,
|
|
237
240
|
});
|
|
238
241
|
|
|
242
|
+
expect(getForInvestigation).toHaveBeenCalledWith({
|
|
243
|
+
incidentId,
|
|
244
|
+
aiRunId: run.id,
|
|
245
|
+
runCompletedAt,
|
|
246
|
+
});
|
|
239
247
|
expect(executeWithLogging).not.toHaveBeenCalled();
|
|
240
248
|
});
|
|
241
249
|
|
|
250
|
+
test("reads the report associated with the selected completed run exactly", async () => {
|
|
251
|
+
const run: AIRun = fakeRun();
|
|
252
|
+
const selectedAnalysis: string =
|
|
253
|
+
"## Selected investigation\nThe selected run found pool exhaustion.";
|
|
254
|
+
jest.spyOn(AIRunService, "findOneBy").mockResolvedValue(run);
|
|
255
|
+
jest
|
|
256
|
+
.spyOn(IncidentService, "findOneById")
|
|
257
|
+
.mockResolvedValue(fakeIncident("The connection pool was exhausted."));
|
|
258
|
+
const getForInvestigation: jest.SpyInstance = jest
|
|
259
|
+
.spyOn(PostedRootCause, "getForInvestigation")
|
|
260
|
+
.mockResolvedValue(selectedAnalysis);
|
|
261
|
+
const executeWithLogging: jest.SpyInstance = jest
|
|
262
|
+
.spyOn(AIService, "executeWithLogging")
|
|
263
|
+
.mockResolvedValue(fakeLlmResponse("MATCH"));
|
|
264
|
+
jest
|
|
265
|
+
.spyOn(AIRunService, "updateOneById")
|
|
266
|
+
.mockResolvedValue(undefined as never);
|
|
267
|
+
|
|
268
|
+
await InvestigationGrader.gradeInvestigationOnResolve({
|
|
269
|
+
incidentId,
|
|
270
|
+
projectId,
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
expect(getForInvestigation).toHaveBeenCalledTimes(1);
|
|
274
|
+
expect(getForInvestigation).toHaveBeenCalledWith({
|
|
275
|
+
incidentId,
|
|
276
|
+
aiRunId: run.id,
|
|
277
|
+
runCompletedAt,
|
|
278
|
+
});
|
|
279
|
+
expect(executeWithLogging).toHaveBeenCalledWith(
|
|
280
|
+
expect.objectContaining({
|
|
281
|
+
aiRunId: run.id,
|
|
282
|
+
messages: expect.arrayContaining([
|
|
283
|
+
expect.objectContaining({
|
|
284
|
+
role: "user",
|
|
285
|
+
content: expect.stringContaining(selectedAnalysis),
|
|
286
|
+
}),
|
|
287
|
+
]),
|
|
288
|
+
}),
|
|
289
|
+
);
|
|
290
|
+
});
|
|
291
|
+
|
|
242
292
|
test("happy path: one budgeted, preview-less LLM call; grade + timestamp stored on the run", async () => {
|
|
243
293
|
const run: AIRun = fakeRun();
|
|
244
294
|
jest.spyOn(AIRunService, "findOneBy").mockResolvedValue(run);
|
|
@@ -246,10 +296,8 @@ describe("InvestigationGrader.gradeInvestigationOnResolve", () => {
|
|
|
246
296
|
.spyOn(IncidentService, "findOneById")
|
|
247
297
|
.mockResolvedValue(fakeIncident("The connection pool was exhausted."));
|
|
248
298
|
jest
|
|
249
|
-
.spyOn(
|
|
250
|
-
.mockResolvedValue(
|
|
251
|
-
fakeFeedItem("## Analysis\nThe db connection pool ran dry."),
|
|
252
|
-
);
|
|
299
|
+
.spyOn(PostedRootCause, "getForInvestigation")
|
|
300
|
+
.mockResolvedValue("## Analysis\nThe db connection pool ran dry.");
|
|
253
301
|
const executeWithLogging: jest.SpyInstance = jest
|
|
254
302
|
.spyOn(AIService, "executeWithLogging")
|
|
255
303
|
.mockResolvedValue(fakeLlmResponse("MATCH"));
|
|
@@ -297,8 +345,8 @@ describe("InvestigationGrader.gradeInvestigationOnResolve", () => {
|
|
|
297
345
|
.spyOn(IncidentService, "findOneById")
|
|
298
346
|
.mockResolvedValue(fakeIncident("db down"));
|
|
299
347
|
jest
|
|
300
|
-
.spyOn(
|
|
301
|
-
.mockResolvedValue(
|
|
348
|
+
.spyOn(PostedRootCause, "getForInvestigation")
|
|
349
|
+
.mockResolvedValue("Analysis text.");
|
|
302
350
|
jest
|
|
303
351
|
.spyOn(AIService, "executeWithLogging")
|
|
304
352
|
.mockResolvedValue(fakeLlmResponse("Either MATCH or MISMATCH."));
|
|
@@ -321,8 +369,8 @@ describe("InvestigationGrader.gradeInvestigationOnResolve", () => {
|
|
|
321
369
|
.spyOn(IncidentService, "findOneById")
|
|
322
370
|
.mockResolvedValue(fakeIncident("db down"));
|
|
323
371
|
jest
|
|
324
|
-
.spyOn(
|
|
325
|
-
.mockResolvedValue(
|
|
372
|
+
.spyOn(PostedRootCause, "getForInvestigation")
|
|
373
|
+
.mockResolvedValue("Analysis text.");
|
|
326
374
|
jest
|
|
327
375
|
.spyOn(AIService, "executeWithLogging")
|
|
328
376
|
.mockRejectedValue(new Error("provider down"));
|
|
@@ -5,6 +5,7 @@ import AIService from "../../../../Server/Services/AIService";
|
|
|
5
5
|
import ProjectService from "../../../../Server/Services/ProjectService";
|
|
6
6
|
import AIRun from "../../../../Models/DatabaseModels/AIRun";
|
|
7
7
|
import Project from "../../../../Models/DatabaseModels/Project";
|
|
8
|
+
import AIRunCodeFixRecommendation from "../../../../Types/AI/AIRunCodeFixRecommendation";
|
|
8
9
|
import AIRunStatus from "../../../../Types/AI/AIRunStatus";
|
|
9
10
|
import AIRunType from "../../../../Types/AI/AIRunType";
|
|
10
11
|
import ObjectID from "../../../../Types/ObjectID";
|
|
@@ -96,6 +97,7 @@ describe("AIInvestigationQueue — RemediationExecution runs", () => {
|
|
|
96
97
|
status: AIRunStatus.Queued,
|
|
97
98
|
runType: AIRunType.RemediationExecution,
|
|
98
99
|
triggeredByAutoRemediationSuggestionId: SUGGESTION_ID,
|
|
100
|
+
codeFixRecommendation: AIRunCodeFixRecommendation.NotRecommended,
|
|
99
101
|
// Incident linkage stays set for the dashboard.
|
|
100
102
|
triggeredByIncidentId: INCIDENT_ID,
|
|
101
103
|
}),
|
|
@@ -131,6 +133,7 @@ describe("AIInvestigationQueue — RemediationExecution runs", () => {
|
|
|
131
133
|
data: expect.objectContaining({
|
|
132
134
|
runType: AIRunType.RemediationPlan,
|
|
133
135
|
triggeredByAutoRemediationSuggestionId: SUGGESTION_ID,
|
|
136
|
+
codeFixRecommendation: AIRunCodeFixRecommendation.NotRecommended,
|
|
134
137
|
}),
|
|
135
138
|
}),
|
|
136
139
|
);
|