@oneuptime/common 11.3.26 → 11.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/AIRun.ts +50 -0
- package/Models/DatabaseModels/IncidentEpisodeRoleMember.ts +1 -1
- package/Models/DatabaseModels/IncidentMember.ts +1 -1
- package/Models/DatabaseModels/IncomingCallPolicy.ts +13 -0
- package/Models/DatabaseModels/Index.ts +3 -0
- package/Models/DatabaseModels/MigrationFailure.ts +170 -0
- package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +51 -2
- package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +44 -0
- package/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.ts +6 -0
- package/Models/DatabaseModels/OnCallDutyPolicyScheduleLayerUser.ts +6 -0
- package/Models/DatabaseModels/OnCallDutyPolicyTimeLog.ts +1 -1
- package/Models/DatabaseModels/OnCallDutyPolicyUserOverride.ts +2 -2
- package/Models/DatabaseModels/Project.ts +60 -0
- package/Server/API/AIInvestigationAPI.ts +148 -0
- package/Server/API/AlertAPI.ts +1 -1
- package/Server/API/IncidentAPI.ts +2 -2
- package/Server/API/IncidentEpisodeAPI.ts +1 -1
- package/Server/API/LlmProviderAPI.ts +1 -0
- package/Server/API/ScheduledMaintenanceAPI.ts +1 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783470000000-AddIncomingCallPolicyRoutingPhoneNumberUnique.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783510935686-FixNotNullForeignKeysOnDelete.ts +81 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783515836148-MigrationName.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783523076215-AddMigrationFailureTable.ts +35 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783598145111-AddEnableAutomaticIncidentInvestigationToProject.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783615884106-AddInvestigationSubjectToAIRun.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783632447975-AddEnableAutomaticAlertInvestigationToProject.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +14 -0
- package/Server/Infrastructure/PostgresDatabase.ts +11 -0
- package/Server/Services/AIService.ts +74 -2
- package/Server/Services/AlertService.ts +25 -0
- package/Server/Services/AnalyticsDatabaseService.ts +10 -1
- package/Server/Services/DatabaseService.ts +10 -1
- package/Server/Services/IncidentService.ts +26 -1
- package/Server/Services/IncidentStateTimelineService.ts +19 -0
- package/Server/Services/IncomingCallPolicyEscalationRuleService.ts +75 -2
- package/Server/Services/IncomingCallPolicyService.ts +42 -1
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/MigrationFailureService.ts +9 -0
- package/Server/Services/MonitorProbeService.ts +33 -7
- package/Server/Services/MonitorService.ts +19 -7
- package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +65 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +185 -41
- package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +23 -15
- package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +39 -0
- package/Server/Services/OnCallDutyPolicyScheduleLayerService.ts +148 -0
- package/Server/Services/OnCallDutyPolicyScheduleLayerUserService.ts +11 -2
- package/Server/Services/OnCallDutyPolicyScheduleService.ts +502 -26
- package/Server/Services/OnCallDutyPolicyTimeLogService.ts +49 -7
- package/Server/Services/OnCallDutyPolicyUserOverrideService.ts +218 -4
- package/Server/Services/ProjectCallSMSConfigService.ts +82 -1
- package/Server/Services/TeamMemberService.ts +6 -0
- package/Server/Services/UserNotificationRuleService.ts +13 -42
- package/Server/Services/UserOnCallLogService.ts +90 -0
- package/Server/Services/UserOnCallLogTimelineService.ts +43 -1
- package/Server/Types/Database/QueryUtil.ts +57 -0
- package/Server/Utils/AI/AlertAIContextBuilder.ts +6 -1
- package/Server/Utils/AI/Chat/ChatAgentRunner.ts +14 -2
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +119 -11
- package/Server/Utils/AI/IncidentAIContextBuilder.ts +18 -3
- package/Server/Utils/AI/IncidentEpisodeAIContextBuilder.ts +6 -1
- package/Server/Utils/AI/ScheduledMaintenanceAIContextBuilder.ts +12 -2
- package/Server/Utils/AI/Sentinel/AlertInvestigationRunner.ts +141 -0
- package/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.ts +178 -0
- package/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.ts +105 -0
- package/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.ts +405 -0
- package/Server/Utils/AI/Sentinel/SentinelMemory.ts +167 -0
- package/Server/Utils/AI/Toolbox/IncidentTools.ts +183 -1
- package/Server/Utils/AI/Toolbox/Index.ts +15 -1
- package/Server/Utils/AI/Toolbox/RecentChangesTools.ts +208 -0
- package/Server/Utils/AI/Toolbox/SentinelActionTools.ts +577 -0
- package/Server/Utils/AI/Toolbox/Serializer.ts +42 -0
- package/Server/Utils/Database/MigrationFailureLog.ts +240 -0
- package/Server/Utils/IncomingCallPhoneNumber.ts +41 -0
- package/Server/Utils/LLM/LLMService.ts +110 -11
- package/Server/Utils/Telemetry/IoTSnapshotScan.ts +12 -9
- package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +12 -9
- package/Tests/Server/API/BaseAPI.test.ts +1 -0
- package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +0 -8
- package/Tests/Server/Services/OnCallDutyPolicyScheduleLayerUserReorder.test.ts +233 -0
- package/Tests/Server/Services/OnCallDutyPolicyTimeLogServiceScoping.test.ts +242 -0
- package/Tests/Server/Services/OnCallDutyPolicyUserOverrideEdit.test.ts +198 -0
- package/Tests/Server/Services/UserOnCallLogClaimNotificationRule.test.ts +495 -0
- package/Tests/Server/Types/Database/QueryUtil.test.ts +74 -0
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +78 -0
- package/Tests/Server/Utils/AI/ToolResultSerializer.test.ts +68 -0
- package/Tests/Types/DateExhaustiveTimezone.test.ts +700 -0
- package/Tests/Types/DateTimezoneWallClock.test.ts +99 -0
- package/Tests/Types/Events/Recurring.test.ts +22 -9
- package/Tests/Types/OnCallDutyPolicy/LayerUtilAuditFixes.test.ts +291 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilAuditFixesRound2.test.ts +398 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilDSTWeekendGap.test.ts +114 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilDSTWeeklyDayShift.test.ts +76 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilDailyMutation.test.ts +128 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilDailyProbe.test.ts +203 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilDiffFuzz.test.ts +322 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilEdgeCases.test.ts +280 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveCurrentUser.test.ts +863 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveDaily.test.ts +900 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveMultiLayer.test.ts +1104 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveRotation.test.ts +957 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveWeekly.test.ts +1095 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilInvariants.test.ts +232 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeAudit.test.ts +227 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilMonthYearAudit.test.ts +255 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilMultiLayerAudit.test.ts +388 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilMultiLayerEdge.test.ts +300 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilOvernightDSTAudit.test.ts +158 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilRestrictedGapFix.test.ts +253 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilRestrictedGapRepro.test.ts +157 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilRotationFixes.test.ts +414 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilTimezone.test.ts +243 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilWeekendGapRepro.test.ts +112 -0
- package/Tests/Types/OnCallDutyPolicy/OverrideLensAudit.test.ts +117 -0
- package/Tests/Types/OnCallDutyPolicy/RestrictionTimes.test.ts +8 -6
- package/Tests/Types/OnCallDutyPolicy/RestrictionTimesDefaultDayAudit.test.ts +112 -0
- package/Tests/Types/OnCallDutyPolicy/RestrictionTimesExhaustive.test.ts +821 -0
- package/Tests/Types/OnCallDutyPolicy/RestrictionTimesMutationInvariant.test.ts +886 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleShiftUtil.test.ts +260 -0
- package/Tests/Types/OnCallDutyPolicy/UserOverrideUtil.test.ts +255 -0
- package/Tests/Types/OnCallDutyPolicy/UserOverrideUtilExhaustive.test.ts +1126 -0
- package/Types/Date.ts +246 -15
- package/Types/OnCallDutyPolicy/Layer.ts +790 -260
- package/Types/OnCallDutyPolicy/RestrictionTimes.ts +39 -13
- package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +257 -0
- package/Types/OnCallDutyPolicy/UserOverrideUtil.ts +21 -5
- package/UI/Components/Calendar/Calendar.tsx +8 -2
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +5 -5
- package/UI/Components/Events/RecurringFieldElement.tsx +16 -0
- package/UI/Components/ModelFormModal/ModelFormModal.tsx +8 -0
- package/UI/Components/RadioButtons/BasicRadioButtons.tsx +1 -1
- package/build/dist/Models/DatabaseModels/AIRun.js +52 -0
- package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeRoleMember.js +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeRoleMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentMember.js +1 -1
- package/build/dist/Models/DatabaseModels/IncidentMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js +10 -0
- package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MigrationFailure.js +196 -0
- package/build/dist/Models/DatabaseModels/MigrationFailure.js.map +1 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +52 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +45 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.js +6 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayerUser.js +6 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayerUser.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyUserOverride.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyUserOverride.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +62 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +107 -0
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -0
- package/build/dist/Server/API/AlertAPI.js +1 -1
- package/build/dist/Server/API/IncidentAPI.js +2 -2
- package/build/dist/Server/API/IncidentEpisodeAPI.js +1 -1
- package/build/dist/Server/API/LlmProviderAPI.js +1 -0
- package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783470000000-AddIncomingCallPolicyRoutingPhoneNumberUnique.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783470000000-AddIncomingCallPolicyRoutingPhoneNumberUnique.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783510935686-FixNotNullForeignKeysOnDelete.js +38 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783510935686-FixNotNullForeignKeysOnDelete.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783515836148-MigrationName.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783515836148-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783523076215-AddMigrationFailureTable.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783523076215-AddMigrationFailureTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783598145111-AddEnableAutomaticIncidentInvestigationToProject.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783598145111-AddEnableAutomaticIncidentInvestigationToProject.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783615884106-AddInvestigationSubjectToAIRun.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783615884106-AddInvestigationSubjectToAIRun.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783632447975-AddEnableAutomaticAlertInvestigationToProject.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783632447975-AddEnableAutomaticAlertInvestigationToProject.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/PostgresDatabase.js +9 -0
- package/build/dist/Server/Infrastructure/PostgresDatabase.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +53 -2
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +24 -0
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +10 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +10 -1
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +25 -1
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +19 -0
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyEscalationRuleService.js +55 -2
- package/build/dist/Server/Services/IncomingCallPolicyEscalationRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyService.js +40 -0
- package/build/dist/Server/Services/IncomingCallPolicyService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MigrationFailureService.js +9 -0
- package/build/dist/Server/Services/MigrationFailureService.js.map +1 -0
- package/build/dist/Server/Services/MonitorProbeService.js +33 -7
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +12 -5
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +81 -22
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +134 -31
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +21 -13
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +36 -0
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js +121 -0
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js +11 -2
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +409 -36
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyTimeLogService.js +52 -8
- package/build/dist/Server/Services/OnCallDutyPolicyTimeLogService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js +170 -3
- package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js.map +1 -1
- package/build/dist/Server/Services/ProjectCallSMSConfigService.js +72 -0
- package/build/dist/Server/Services/ProjectCallSMSConfigService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +6 -0
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +12 -30
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserOnCallLogService.js +75 -0
- package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
- package/build/dist/Server/Services/UserOnCallLogTimelineService.js +31 -1
- package/build/dist/Server/Services/UserOnCallLogTimelineService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryUtil.js +45 -0
- package/build/dist/Server/Types/Database/QueryUtil.js.map +1 -1
- package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js +6 -1
- package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +13 -2
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +59 -11
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js +18 -3
- package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js.map +1 -1
- package/build/dist/Server/Utils/AI/IncidentEpisodeAIContextBuilder.js +6 -1
- package/build/dist/Server/Utils/AI/IncidentEpisodeAIContextBuilder.js.map +1 -1
- package/build/dist/Server/Utils/AI/ScheduledMaintenanceAIContextBuilder.js +12 -2
- package/build/dist/Server/Utils/AI/ScheduledMaintenanceAIContextBuilder.js.map +1 -1
- package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js +119 -0
- package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js +147 -0
- package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.js +93 -0
- package/build/dist/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js +311 -0
- package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js.map +1 -0
- package/build/dist/Server/Utils/AI/Sentinel/SentinelMemory.js +143 -0
- package/build/dist/Server/Utils/AI/Sentinel/SentinelMemory.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +152 -1
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/Index.js +10 -1
- package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/RecentChangesTools.js +165 -0
- package/build/dist/Server/Utils/AI/Toolbox/RecentChangesTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/SentinelActionTools.js +451 -0
- package/build/dist/Server/Utils/AI/Toolbox/SentinelActionTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/Serializer.js +40 -0
- package/build/dist/Server/Utils/AI/Toolbox/Serializer.js.map +1 -1
- package/build/dist/Server/Utils/Database/MigrationFailureLog.js +174 -0
- package/build/dist/Server/Utils/Database/MigrationFailureLog.js.map +1 -0
- package/build/dist/Server/Utils/IncomingCallPhoneNumber.js +30 -0
- package/build/dist/Server/Utils/IncomingCallPhoneNumber.js.map +1 -0
- package/build/dist/Server/Utils/LLM/LLMService.js +81 -5
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/IoTSnapshotScan.js +11 -8
- package/build/dist/Server/Utils/Telemetry/IoTSnapshotScan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +11 -8
- package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -1
- package/build/dist/Types/Date.js +185 -15
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/Layer.js +602 -171
- package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/RestrictionTimes.js +27 -13
- package/build/dist/Types/OnCallDutyPolicy/RestrictionTimes.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +159 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js +20 -5
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js.map +1 -1
- package/build/dist/UI/Components/Calendar/Calendar.js +2 -2
- package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +2 -2
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Events/RecurringFieldElement.js +13 -0
- package/build/dist/UI/Components/Events/RecurringFieldElement.js.map +1 -1
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +1 -1
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
- package/package.json +1 -1
|
@@ -15,6 +15,8 @@ import UserNotificationExecutionStatus from "../../Types/UserNotification/UserNo
|
|
|
15
15
|
import User from "../../Models/DatabaseModels/User";
|
|
16
16
|
import Model from "../../Models/DatabaseModels/UserOnCallLogTimeline";
|
|
17
17
|
import AlertService from "./AlertService";
|
|
18
|
+
import AlertEpisodeService from "./AlertEpisodeService";
|
|
19
|
+
import IncidentEpisodeService from "./IncidentEpisodeService";
|
|
18
20
|
|
|
19
21
|
export class Service extends DatabaseService<Model> {
|
|
20
22
|
public constructor() {
|
|
@@ -40,6 +42,8 @@ export class Service extends DatabaseService<Model> {
|
|
|
40
42
|
onCallDutyPolicyExecutionLogId: true,
|
|
41
43
|
triggeredByIncidentId: true,
|
|
42
44
|
triggeredByAlertId: true,
|
|
45
|
+
triggeredByAlertEpisodeId: true,
|
|
46
|
+
triggeredByIncidentEpisodeId: true,
|
|
43
47
|
onCallDutyPolicyExecutionLogTimelineId: true,
|
|
44
48
|
},
|
|
45
49
|
skip: 0,
|
|
@@ -52,6 +56,19 @@ export class Service extends DatabaseService<Model> {
|
|
|
52
56
|
for (const item of items) {
|
|
53
57
|
const isIncident: boolean = Boolean(item.triggeredByIncidentId);
|
|
54
58
|
const isAlert: boolean = Boolean(item.triggeredByAlertId);
|
|
59
|
+
/*
|
|
60
|
+
* Alert-episode and incident-episode pages were never handled here, so
|
|
61
|
+
* acknowledging one via call/SMS/email/push marked only this user's log
|
|
62
|
+
* done but never acknowledged the EPISODE. ExecutePendingExecutions gates
|
|
63
|
+
* every co-notified user's continuation solely on isEpisodeAcknowledged,
|
|
64
|
+
* so the other responders kept escalating and the episode stayed
|
|
65
|
+
* unacknowledged in its own state (audit F15). Handle both episode kinds
|
|
66
|
+
* the same way incident/alert are handled below.
|
|
67
|
+
*/
|
|
68
|
+
const isAlertEpisode: boolean = Boolean(item.triggeredByAlertEpisodeId);
|
|
69
|
+
const isIncidentEpisode: boolean = Boolean(
|
|
70
|
+
item.triggeredByIncidentEpisodeId,
|
|
71
|
+
);
|
|
55
72
|
|
|
56
73
|
// this incident is acknowledged.
|
|
57
74
|
|
|
@@ -73,7 +90,16 @@ export class Service extends DatabaseService<Model> {
|
|
|
73
90
|
throw new BadDataException("User not found.");
|
|
74
91
|
}
|
|
75
92
|
|
|
76
|
-
const
|
|
93
|
+
const entityLabel: string =
|
|
94
|
+
isIncident || isIncidentEpisode
|
|
95
|
+
? isIncidentEpisode
|
|
96
|
+
? "Incident Episode"
|
|
97
|
+
: "Incident"
|
|
98
|
+
: isAlertEpisode
|
|
99
|
+
? "Alert Episode"
|
|
100
|
+
: "Alert";
|
|
101
|
+
|
|
102
|
+
const statusMessage: string = `${entityLabel} acknowledged by ${user.name} (${user.email})`;
|
|
77
103
|
|
|
78
104
|
await UserOnCallLogService.updateOneById({
|
|
79
105
|
id: item.userNotificationLogId!,
|
|
@@ -133,6 +159,22 @@ export class Service extends DatabaseService<Model> {
|
|
|
133
159
|
item.userId!,
|
|
134
160
|
);
|
|
135
161
|
}
|
|
162
|
+
|
|
163
|
+
if (isAlertEpisode) {
|
|
164
|
+
// alert episode — stops co-notified responders from escalating.
|
|
165
|
+
await AlertEpisodeService.acknowledgeEpisode(
|
|
166
|
+
item.triggeredByAlertEpisodeId!,
|
|
167
|
+
item.userId!,
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (isIncidentEpisode) {
|
|
172
|
+
// incident episode — stops co-notified responders from escalating.
|
|
173
|
+
await IncidentEpisodeService.acknowledgeEpisode(
|
|
174
|
+
item.triggeredByIncidentEpisodeId!,
|
|
175
|
+
item.userId!,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
136
178
|
}
|
|
137
179
|
}
|
|
138
180
|
|
|
@@ -549,6 +549,63 @@ export default class QueryUtil {
|
|
|
549
549
|
_id: QueryHelper.any(query[key] as Array<string>),
|
|
550
550
|
};
|
|
551
551
|
}
|
|
552
|
+
|
|
553
|
+
/*
|
|
554
|
+
* Text-search operator nested under a single-Entity relation, e.g.
|
|
555
|
+
* { user: { name: new Search("foo") } }. serializeQuery otherwise only
|
|
556
|
+
* visits top-level keys, so the nested operator reaches TypeORM as a raw
|
|
557
|
+
* class instance and silently degrades to an exact equality
|
|
558
|
+
* (`user.name = 'foo'` instead of `user.name ILIKE '%foo%'`) — which is
|
|
559
|
+
* why the Owner / user picker "search" appeared to do nothing once a
|
|
560
|
+
* project had more than a page of members.
|
|
561
|
+
*
|
|
562
|
+
* We deliberately touch ONLY the ILIKE-family leaf operators here and
|
|
563
|
+
* leave every other nested value (arrays, ids, plain equality, other
|
|
564
|
+
* operators) exactly as it was, so existing nested relation filters (the
|
|
565
|
+
* access-control label filters built by @CanAccessIfCanReadOn, etc.)
|
|
566
|
+
* serialize unchanged.
|
|
567
|
+
*/
|
|
568
|
+
if (
|
|
569
|
+
tableColumnMetadata &&
|
|
570
|
+
tableColumnMetadata.modelType &&
|
|
571
|
+
tableColumnMetadata.type === TableColumnType.Entity &&
|
|
572
|
+
query[key] &&
|
|
573
|
+
typeof query[key] === Typeof.Object &&
|
|
574
|
+
!Array.isArray(query[key]) &&
|
|
575
|
+
(Object.getPrototypeOf(query[key]) === Object.prototype ||
|
|
576
|
+
Object.getPrototypeOf(query[key]) === null)
|
|
577
|
+
) {
|
|
578
|
+
const relationModel: BaseModel = new tableColumnMetadata.modelType();
|
|
579
|
+
const relationQuery: Record<string, any> = query[key] as Record<
|
|
580
|
+
string,
|
|
581
|
+
any
|
|
582
|
+
>;
|
|
583
|
+
for (const relationKey in relationQuery) {
|
|
584
|
+
const relationColumnMetadata: TableColumnMetadata =
|
|
585
|
+
relationModel.getTableColumnMetadata(relationKey);
|
|
586
|
+
if (!relationColumnMetadata) {
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
const nestedValue: any = relationQuery[relationKey];
|
|
590
|
+
if (nestedValue instanceof Search) {
|
|
591
|
+
relationQuery[relationKey] = QueryHelper.search(
|
|
592
|
+
(nestedValue as Search<string>).toString(),
|
|
593
|
+
) as any;
|
|
594
|
+
} else if (nestedValue instanceof StartsWith) {
|
|
595
|
+
relationQuery[relationKey] = QueryHelper.startsWith(
|
|
596
|
+
(nestedValue as StartsWith<string>).toString(),
|
|
597
|
+
) as any;
|
|
598
|
+
} else if (nestedValue instanceof EndsWith) {
|
|
599
|
+
relationQuery[relationKey] = QueryHelper.endsWith(
|
|
600
|
+
(nestedValue as EndsWith<string>).toString(),
|
|
601
|
+
) as any;
|
|
602
|
+
} else if (nestedValue instanceof NotContains) {
|
|
603
|
+
relationQuery[relationKey] = QueryHelper.notContains(
|
|
604
|
+
(nestedValue as NotContains<string>).toString(),
|
|
605
|
+
) as any;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
552
609
|
}
|
|
553
610
|
|
|
554
611
|
return query;
|
|
@@ -235,7 +235,12 @@ The note should:
|
|
|
235
235
|
4. Be detailed enough to help team members understand the situation
|
|
236
236
|
5. Use technical language appropriate for the engineering team
|
|
237
237
|
|
|
238
|
-
Write in markdown format for better readability. Be thorough and technical
|
|
238
|
+
Write in markdown format for better readability. Be thorough and technical.
|
|
239
|
+
|
|
240
|
+
Grounding rules (important):
|
|
241
|
+
- Use ONLY facts that appear in the provided alert data. Do NOT invent causes, metrics, impact, or actions the data does not support.
|
|
242
|
+
- If something a section needs is not in the data, write "Not available in the alert record" instead of guessing.
|
|
243
|
+
- Never fabricate numbers or state confidence levels.`;
|
|
239
244
|
}
|
|
240
245
|
|
|
241
246
|
// Build user message
|
|
@@ -908,9 +908,21 @@ export default class ChatAgentRunner {
|
|
|
908
908
|
continue;
|
|
909
909
|
}
|
|
910
910
|
|
|
911
|
+
const isUserMessage: boolean = message.role === AIChatMessageRole.User;
|
|
912
|
+
|
|
911
913
|
messages.push({
|
|
912
|
-
role:
|
|
913
|
-
|
|
914
|
+
role: isUserMessage ? "user" : "assistant",
|
|
915
|
+
/*
|
|
916
|
+
* A prior assistant answer carries [C#] citation markers that pointed
|
|
917
|
+
* at that turn's tool results — citations that no longer exist in this
|
|
918
|
+
* turn. Left in the replayed history the model echoes and renumbers
|
|
919
|
+
* them, and this turn's stripFabricatedCitationMarkers then deletes the
|
|
920
|
+
* unmatched ones, leaving claims that look uncited. Strip the markers
|
|
921
|
+
* from replayed answers so only freshly minted citations ever appear.
|
|
922
|
+
*/
|
|
923
|
+
content: isUserMessage
|
|
924
|
+
? message.contentInMarkdown
|
|
925
|
+
: message.contentInMarkdown.replace(/\s?\[C\d+\]/g, ""),
|
|
914
926
|
});
|
|
915
927
|
}
|
|
916
928
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import DatabaseCommonInteractionProps from "../../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
2
2
|
import OneUptimeDate from "../../../../Types/Date";
|
|
3
3
|
import ObjectID from "../../../../Types/ObjectID";
|
|
4
|
+
import { JSONObject } from "../../../../Types/JSON";
|
|
4
5
|
import { AIChatCitation } from "../../../../Types/AI/AIChatTypes";
|
|
5
6
|
import AIService, { AILogResponse } from "../../../Services/AIService";
|
|
6
7
|
import logger from "../../Logger";
|
|
@@ -32,6 +33,29 @@ export interface ObservabilityAssistantPriorTurn {
|
|
|
32
33
|
content: string;
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
/*
|
|
37
|
+
* A single "thinking step" emitted live as the agent loop runs, so callers can
|
|
38
|
+
* narrate the investigation in real time ("Reading trace ✓ 0.4s"). This is the
|
|
39
|
+
* step-level narration the OneUptime UI renders by polling AIRunEvent rows.
|
|
40
|
+
*/
|
|
41
|
+
export type ObservabilityAssistantStepType =
|
|
42
|
+
| "llm_started"
|
|
43
|
+
| "llm_completed"
|
|
44
|
+
| "tool_started"
|
|
45
|
+
| "tool_completed"
|
|
46
|
+
| "tool_failed";
|
|
47
|
+
|
|
48
|
+
export interface ObservabilityAssistantStep {
|
|
49
|
+
type: ObservabilityAssistantStepType;
|
|
50
|
+
toolName?: string | undefined;
|
|
51
|
+
toolArguments?: JSONObject | undefined;
|
|
52
|
+
rowCount?: number | undefined;
|
|
53
|
+
durationMs?: number | undefined;
|
|
54
|
+
citationId?: string | undefined;
|
|
55
|
+
totalTokens?: number | undefined;
|
|
56
|
+
errorMessage?: string | undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
35
59
|
export interface ObservabilityAssistantRequest {
|
|
36
60
|
projectId: ObjectID;
|
|
37
61
|
userId?: ObjectID | undefined;
|
|
@@ -44,6 +68,29 @@ export interface ObservabilityAssistantRequest {
|
|
|
44
68
|
llmProviderId?: ObjectID | undefined;
|
|
45
69
|
// Label recorded on LlmLog, e.g. "Slack ChatOps".
|
|
46
70
|
feature: string;
|
|
71
|
+
/*
|
|
72
|
+
* Extra instructions appended to the base observability system prompt — used
|
|
73
|
+
* to give an autonomous run (e.g. Sentinel incident investigation) a distinct
|
|
74
|
+
* persona and task framing while keeping the same hard rules (citations, no
|
|
75
|
+
* fabrication, read-only). The base prompt's grounding rules always win.
|
|
76
|
+
*/
|
|
77
|
+
systemInstructions?: string | undefined;
|
|
78
|
+
/*
|
|
79
|
+
* Optional budget overrides. Autonomous investigations get more room than an
|
|
80
|
+
* interactive chat-ops answer, which must return in a single quick message.
|
|
81
|
+
* Omitted values fall back to the interactive defaults.
|
|
82
|
+
*/
|
|
83
|
+
maxLlmCalls?: number | undefined;
|
|
84
|
+
maxToolCalls?: number | undefined;
|
|
85
|
+
maxWallClockMs?: number | undefined;
|
|
86
|
+
maxOutputTokens?: number | undefined;
|
|
87
|
+
/*
|
|
88
|
+
* Optional live-narration hook, fired for each LLM/tool step as the loop runs.
|
|
89
|
+
* Used by autonomous runs to persist a per-step AIRunEvent trail so the UI can
|
|
90
|
+
* "watch it think". Best-effort — implementations must not throw; a slow or
|
|
91
|
+
* failing handler should not break the run.
|
|
92
|
+
*/
|
|
93
|
+
onStep?: ((step: ObservabilityAssistantStep) => Promise<void>) | undefined;
|
|
47
94
|
}
|
|
48
95
|
|
|
49
96
|
export interface ObservabilityAssistantResult {
|
|
@@ -70,19 +117,50 @@ export default class ObservabilityAssistant {
|
|
|
70
117
|
): Promise<ObservabilityAssistantResult> {
|
|
71
118
|
const startedAtMs: number = Date.now();
|
|
72
119
|
|
|
120
|
+
const maxLlmCalls: number = request.maxLlmCalls ?? MAX_LLM_CALLS;
|
|
121
|
+
const maxToolCalls: number = request.maxToolCalls ?? MAX_TOOL_CALLS;
|
|
122
|
+
const maxWallClockMs: number = request.maxWallClockMs ?? MAX_WALL_CLOCK_MS;
|
|
123
|
+
const maxOutputTokens: number =
|
|
124
|
+
request.maxOutputTokens ?? MAX_OUTPUT_TOKENS;
|
|
125
|
+
|
|
126
|
+
// Best-effort live-narration emitter — never throws into the loop.
|
|
127
|
+
const emitStep: (
|
|
128
|
+
step: ObservabilityAssistantStep,
|
|
129
|
+
) => Promise<void> = async (
|
|
130
|
+
step: ObservabilityAssistantStep,
|
|
131
|
+
): Promise<void> => {
|
|
132
|
+
if (!request.onStep) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
await request.onStep(step);
|
|
137
|
+
} catch (err) {
|
|
138
|
+
logger.error(`ObservabilityAssistant onStep failed: ${err}`);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
73
142
|
const toolContext: ToolContext = {
|
|
74
143
|
projectId: request.projectId,
|
|
75
144
|
props: request.props,
|
|
76
145
|
};
|
|
77
146
|
|
|
147
|
+
let systemPromptContent: string = buildObservabilityChatSystemPrompt({
|
|
148
|
+
currentTime: OneUptimeDate.getCurrentDate(),
|
|
149
|
+
/*
|
|
150
|
+
* Slack/Teams and autonomous investigations have no approval UI, so this
|
|
151
|
+
* surface stays strictly read-only.
|
|
152
|
+
*/
|
|
153
|
+
permissionMode: AIChatPermissionMode.ReadOnly,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (request.systemInstructions) {
|
|
157
|
+
systemPromptContent += `\n\n${request.systemInstructions}`;
|
|
158
|
+
}
|
|
159
|
+
|
|
78
160
|
const messages: Array<LLMMessage> = [
|
|
79
161
|
{
|
|
80
162
|
role: "system",
|
|
81
|
-
content:
|
|
82
|
-
currentTime: OneUptimeDate.getCurrentDate(),
|
|
83
|
-
// Slack/Teams have no approval UI, so this surface stays read-only.
|
|
84
|
-
permissionMode: AIChatPermissionMode.ReadOnly,
|
|
85
|
-
}),
|
|
163
|
+
content: systemPromptContent,
|
|
86
164
|
},
|
|
87
165
|
];
|
|
88
166
|
|
|
@@ -104,9 +182,9 @@ export default class ObservabilityAssistant {
|
|
|
104
182
|
|
|
105
183
|
while (true) {
|
|
106
184
|
const budgetExhausted: boolean =
|
|
107
|
-
llmCallCount >=
|
|
108
|
-
toolCallCount >=
|
|
109
|
-
Date.now() - startedAtMs >=
|
|
185
|
+
llmCallCount >= maxLlmCalls - 1 ||
|
|
186
|
+
toolCallCount >= maxToolCalls ||
|
|
187
|
+
Date.now() - startedAtMs >= maxWallClockMs;
|
|
110
188
|
|
|
111
189
|
if (budgetExhausted) {
|
|
112
190
|
messages.push({
|
|
@@ -116,6 +194,8 @@ export default class ObservabilityAssistant {
|
|
|
116
194
|
});
|
|
117
195
|
}
|
|
118
196
|
|
|
197
|
+
await emitStep({ type: "llm_started" });
|
|
198
|
+
|
|
119
199
|
const response: AILogResponse = await AIService.executeWithLogging({
|
|
120
200
|
projectId: request.projectId,
|
|
121
201
|
userId: request.userId,
|
|
@@ -125,7 +205,7 @@ export default class ObservabilityAssistant {
|
|
|
125
205
|
tools: budgetExhausted
|
|
126
206
|
? undefined
|
|
127
207
|
: AIToolbox.getLlmToolDefinitions(AIChatPermissionMode.ReadOnly),
|
|
128
|
-
maxTokens:
|
|
208
|
+
maxTokens: maxOutputTokens,
|
|
129
209
|
temperature: TEMPERATURE,
|
|
130
210
|
// Chat-ops content is per-user — do not persist previews to LlmLog.
|
|
131
211
|
storeContentPreviews: false,
|
|
@@ -134,6 +214,11 @@ export default class ObservabilityAssistant {
|
|
|
134
214
|
llmCallCount++;
|
|
135
215
|
totalTokens += response.llmLog.totalTokens || 0;
|
|
136
216
|
|
|
217
|
+
await emitStep({
|
|
218
|
+
type: "llm_completed",
|
|
219
|
+
totalTokens: response.llmLog.totalTokens || 0,
|
|
220
|
+
});
|
|
221
|
+
|
|
137
222
|
if (!providerName) {
|
|
138
223
|
providerName = response.llmLog.llmProviderName;
|
|
139
224
|
modelName = response.llmLog.modelName;
|
|
@@ -152,8 +237,8 @@ export default class ObservabilityAssistant {
|
|
|
152
237
|
|
|
153
238
|
for (const toolCall of response.toolCalls) {
|
|
154
239
|
const overBudget: boolean =
|
|
155
|
-
toolCallCount >=
|
|
156
|
-
Date.now() - startedAtMs >=
|
|
240
|
+
toolCallCount >= maxToolCalls ||
|
|
241
|
+
Date.now() - startedAtMs >= maxWallClockMs;
|
|
157
242
|
|
|
158
243
|
if (overBudget) {
|
|
159
244
|
messages.push({
|
|
@@ -176,6 +261,14 @@ export default class ObservabilityAssistant {
|
|
|
176
261
|
continue;
|
|
177
262
|
}
|
|
178
263
|
|
|
264
|
+
const toolStartedAtMs: number = Date.now();
|
|
265
|
+
|
|
266
|
+
await emitStep({
|
|
267
|
+
type: "tool_started",
|
|
268
|
+
toolName: toolCall.name,
|
|
269
|
+
toolArguments: toolCall.arguments,
|
|
270
|
+
});
|
|
271
|
+
|
|
179
272
|
const outcome: ToolCallOutcome = await AIToolbox.executeTool({
|
|
180
273
|
name: toolCall.name,
|
|
181
274
|
args: toolCall.arguments,
|
|
@@ -183,6 +276,13 @@ export default class ObservabilityAssistant {
|
|
|
183
276
|
});
|
|
184
277
|
|
|
185
278
|
if (!outcome.success || !outcome.result) {
|
|
279
|
+
await emitStep({
|
|
280
|
+
type: "tool_failed",
|
|
281
|
+
toolName: toolCall.name,
|
|
282
|
+
durationMs: Date.now() - toolStartedAtMs,
|
|
283
|
+
errorMessage: outcome.errorMessage || outcome.textForLlm,
|
|
284
|
+
});
|
|
285
|
+
|
|
186
286
|
messages.push({
|
|
187
287
|
role: "tool",
|
|
188
288
|
toolCallId: toolCall.id,
|
|
@@ -202,6 +302,14 @@ export default class ObservabilityAssistant {
|
|
|
202
302
|
target: outcome.result.citationTarget,
|
|
203
303
|
});
|
|
204
304
|
|
|
305
|
+
await emitStep({
|
|
306
|
+
type: "tool_completed",
|
|
307
|
+
toolName: toolCall.name,
|
|
308
|
+
durationMs: Date.now() - toolStartedAtMs,
|
|
309
|
+
rowCount: outcome.result.rowCount,
|
|
310
|
+
citationId: citationId,
|
|
311
|
+
});
|
|
312
|
+
|
|
205
313
|
const escapedText: string = escapeToolResultContent(
|
|
206
314
|
outcome.textForLlm,
|
|
207
315
|
);
|
|
@@ -365,7 +365,12 @@ The postmortem should:
|
|
|
365
365
|
|
|
366
366
|
Use a standard incident postmortem format with sections for: Executive Summary, Timeline, Root Cause Analysis, Impact, Action Items, and Lessons Learned.
|
|
367
367
|
|
|
368
|
-
Write in a professional, clear, and concise manner. Use markdown formatting for better readability
|
|
368
|
+
Write in a professional, clear, and concise manner. Use markdown formatting for better readability.
|
|
369
|
+
|
|
370
|
+
Grounding rules (important):
|
|
371
|
+
- Use ONLY facts that appear in the provided incident data. Do NOT invent root causes, timelines, metrics, customer impact, or actions the data does not support.
|
|
372
|
+
- If a section needs information the data does not contain, write "Not available in the incident record" instead of guessing.
|
|
373
|
+
- Never fabricate numbers or state confidence levels.`;
|
|
369
374
|
}
|
|
370
375
|
|
|
371
376
|
// Build user message based on whether template is provided
|
|
@@ -549,7 +554,12 @@ DO NOT include:
|
|
|
549
554
|
- Confidential information
|
|
550
555
|
- Excessive jargon
|
|
551
556
|
|
|
552
|
-
Write in markdown format for better readability
|
|
557
|
+
Write in markdown format for better readability.
|
|
558
|
+
|
|
559
|
+
Grounding rules (important):
|
|
560
|
+
- Use ONLY facts that appear in the provided incident data; never invent impact, causes, timing, or status.
|
|
561
|
+
- If something is not known from the data, say it is still being investigated rather than guessing.
|
|
562
|
+
- Never fabricate numbers or specific timings the data does not support.`;
|
|
553
563
|
}
|
|
554
564
|
} else if (template) {
|
|
555
565
|
// Internal note with template
|
|
@@ -577,7 +587,12 @@ The note should:
|
|
|
577
587
|
4. Be detailed enough to help team members understand the situation
|
|
578
588
|
5. Use technical language appropriate for the engineering team
|
|
579
589
|
|
|
580
|
-
Write in markdown format for better readability. Be thorough and technical
|
|
590
|
+
Write in markdown format for better readability. Be thorough and technical.
|
|
591
|
+
|
|
592
|
+
Grounding rules (important):
|
|
593
|
+
- Use ONLY facts that appear in the provided incident data. Do NOT invent root causes, metrics, impact, or actions the data does not support.
|
|
594
|
+
- If something a section needs is not in the data, write "Not available in the incident record" instead of guessing.
|
|
595
|
+
- Never fabricate numbers or state confidence levels.`;
|
|
581
596
|
}
|
|
582
597
|
|
|
583
598
|
// Build user message
|
|
@@ -389,7 +389,12 @@ The postmortem should:
|
|
|
389
389
|
|
|
390
390
|
Use a standard incident postmortem format with sections for: Executive Summary, Timeline, Root Cause Analysis, Impact, Action Items, and Lessons Learned.
|
|
391
391
|
|
|
392
|
-
Write in a professional, clear, and concise manner. Use markdown formatting for better readability
|
|
392
|
+
Write in a professional, clear, and concise manner. Use markdown formatting for better readability.
|
|
393
|
+
|
|
394
|
+
Grounding rules (important):
|
|
395
|
+
- Use ONLY facts that appear in the provided episode data. Do NOT invent root causes, timelines, metrics, impact, or actions the data does not support.
|
|
396
|
+
- If a section needs information the data does not contain, write "Not available in the incident record" instead of guessing.
|
|
397
|
+
- Never fabricate numbers or state confidence levels.`;
|
|
393
398
|
}
|
|
394
399
|
|
|
395
400
|
// Build user message based on whether template is provided
|
|
@@ -288,7 +288,12 @@ DO NOT include:
|
|
|
288
288
|
- Confidential information
|
|
289
289
|
- Excessive jargon
|
|
290
290
|
|
|
291
|
-
Write in markdown format for better readability
|
|
291
|
+
Write in markdown format for better readability.
|
|
292
|
+
|
|
293
|
+
Grounding rules (important):
|
|
294
|
+
- Use ONLY facts that appear in the provided maintenance data; never invent scope, impact, timing, or status.
|
|
295
|
+
- If something is not known from the data, say it will be confirmed rather than guessing.
|
|
296
|
+
- Never fabricate numbers or specific timings the data does not support.`;
|
|
292
297
|
}
|
|
293
298
|
} else if (template) {
|
|
294
299
|
// Internal note with template
|
|
@@ -316,7 +321,12 @@ The note should:
|
|
|
316
321
|
4. Be detailed enough to help team members understand the current status
|
|
317
322
|
5. Use technical language appropriate for the engineering team
|
|
318
323
|
|
|
319
|
-
Write in markdown format for better readability. Be thorough and technical
|
|
324
|
+
Write in markdown format for better readability. Be thorough and technical.
|
|
325
|
+
|
|
326
|
+
Grounding rules (important):
|
|
327
|
+
- Use ONLY facts that appear in the provided maintenance data. Do NOT invent scope, metrics, impact, or actions the data does not support.
|
|
328
|
+
- If something a section needs is not in the data, write "Not available in the maintenance record" instead of guessing.
|
|
329
|
+
- Never fabricate numbers or state confidence levels.`;
|
|
320
330
|
}
|
|
321
331
|
|
|
322
332
|
// Build user message
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import ObjectID from "../../../../Types/ObjectID";
|
|
2
|
+
import OneUptimeDate from "../../../../Types/Date";
|
|
3
|
+
import { Blue500 } from "../../../../Types/BrandColors";
|
|
4
|
+
import { AlertFeedEventType } from "../../../../Models/DatabaseModels/AlertFeed";
|
|
5
|
+
import AlertFeedService from "../../../Services/AlertFeedService";
|
|
6
|
+
import AlertAIContextBuilder, {
|
|
7
|
+
AlertContextData,
|
|
8
|
+
} from "../AlertAIContextBuilder";
|
|
9
|
+
import SentinelInvestigationEngine from "./SentinelInvestigationEngine";
|
|
10
|
+
import { ObservabilityAssistantResult } from "../Chat/ObservabilityAssistant";
|
|
11
|
+
import logger from "../../Logger";
|
|
12
|
+
import CaptureSpan from "../../Telemetry/CaptureSpan";
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* Sentinel — alert investigation.
|
|
16
|
+
*
|
|
17
|
+
* Alerts are the earlier, "left of boom" signal. When a new alert is declared,
|
|
18
|
+
* Sentinel investigates it (read-only) and posts a cited root-cause analysis to
|
|
19
|
+
* the alert timeline + Slack/Teams. Symmetric to incident investigation and
|
|
20
|
+
* built on the same shared SentinelInvestigationEngine.
|
|
21
|
+
*
|
|
22
|
+
* Gated by the same per-project opt-in as incidents. Alert volume can be higher
|
|
23
|
+
* than incidents, so severity / rate gating is a deliberate follow-up.
|
|
24
|
+
*/
|
|
25
|
+
export default class SentinelAlertInvestigationRunner {
|
|
26
|
+
/*
|
|
27
|
+
* Entry point called (fire-and-forget) from AlertService.onCreateSuccess.
|
|
28
|
+
* Never throws — all failures are logged and recorded on the AIRun.
|
|
29
|
+
*/
|
|
30
|
+
@CaptureSpan()
|
|
31
|
+
public static async investigateNewAlert(data: {
|
|
32
|
+
alertId: ObjectID;
|
|
33
|
+
projectId: ObjectID;
|
|
34
|
+
}): Promise<void> {
|
|
35
|
+
const { alertId, projectId } = data;
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
if (
|
|
39
|
+
!(await SentinelInvestigationEngine.isEnabledForProject(
|
|
40
|
+
projectId,
|
|
41
|
+
"Alert",
|
|
42
|
+
))
|
|
43
|
+
) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const contextData: AlertContextData =
|
|
48
|
+
await AlertAIContextBuilder.buildAlertContext({
|
|
49
|
+
alertId,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
await SentinelInvestigationEngine.investigate({
|
|
53
|
+
projectId,
|
|
54
|
+
feature: "Sentinel Alert Investigation",
|
|
55
|
+
subjectAlertId: alertId,
|
|
56
|
+
contextSummary: this.buildAlertSummary(contextData),
|
|
57
|
+
postAnalysis: async (postData: {
|
|
58
|
+
analysisMarkdown: string;
|
|
59
|
+
isConfident: boolean;
|
|
60
|
+
result: ObservabilityAssistantResult;
|
|
61
|
+
}): Promise<void> => {
|
|
62
|
+
await AlertFeedService.createAlertFeedItem({
|
|
63
|
+
alertId,
|
|
64
|
+
projectId,
|
|
65
|
+
alertFeedEventType: AlertFeedEventType.RootCause,
|
|
66
|
+
displayColor: Blue500,
|
|
67
|
+
feedInfoInMarkdown: postData.analysisMarkdown,
|
|
68
|
+
/*
|
|
69
|
+
* Quiet mode: an inconclusive investigation posts to the timeline
|
|
70
|
+
* but does NOT loudly ping the workspace / on-call.
|
|
71
|
+
*/
|
|
72
|
+
workspaceNotification: {
|
|
73
|
+
sendWorkspaceNotification: postData.isConfident,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
} catch (error) {
|
|
79
|
+
logger.error(
|
|
80
|
+
`Sentinel: unexpected error investigating alert ${alertId.toString()}: ${error}`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Build a compact alert record to seed the investigation.
|
|
86
|
+
private static buildAlertSummary(contextData: AlertContextData): string {
|
|
87
|
+
const { alert, internalNotes } = contextData;
|
|
88
|
+
|
|
89
|
+
const lines: Array<string> = [];
|
|
90
|
+
lines.push("# Alert");
|
|
91
|
+
lines.push(`Title: ${alert.title || "N/A"}`);
|
|
92
|
+
|
|
93
|
+
if (alert.description) {
|
|
94
|
+
lines.push(`Description: ${alert.description}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
lines.push(`Severity: ${alert.alertSeverity?.name || "N/A"}`);
|
|
98
|
+
lines.push(`Current state: ${alert.currentAlertState?.name || "N/A"}`);
|
|
99
|
+
lines.push(
|
|
100
|
+
`Declared at: ${
|
|
101
|
+
alert.createdAt
|
|
102
|
+
? OneUptimeDate.getDateAsFormattedString(alert.createdAt)
|
|
103
|
+
: "N/A"
|
|
104
|
+
}`,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
if (alert.monitor?.name) {
|
|
108
|
+
lines.push(`Affected monitor: ${alert.monitor.name}`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (alert.labels && alert.labels.length > 0) {
|
|
112
|
+
lines.push(
|
|
113
|
+
`Labels: ${alert.labels
|
|
114
|
+
.map((l: { name?: string }) => {
|
|
115
|
+
return l.name;
|
|
116
|
+
})
|
|
117
|
+
.filter(Boolean)
|
|
118
|
+
.join(", ")}`,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (alert.rootCause) {
|
|
123
|
+
lines.push(`Root cause (as recorded so far): ${alert.rootCause}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const recentNotes: Array<string> = (internalNotes || [])
|
|
127
|
+
.slice(-5)
|
|
128
|
+
.map((note: { note?: string }) => {
|
|
129
|
+
return note.note ? `- ${note.note}` : "";
|
|
130
|
+
})
|
|
131
|
+
.filter(Boolean);
|
|
132
|
+
|
|
133
|
+
if (recentNotes.length > 0) {
|
|
134
|
+
lines.push("");
|
|
135
|
+
lines.push("Recent internal notes:");
|
|
136
|
+
lines.push(...recentNotes);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return lines.join("\n");
|
|
140
|
+
}
|
|
141
|
+
}
|