@oneuptime/common 11.3.25 → 11.3.28
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/AIConversation.ts +322 -0
- package/Models/DatabaseModels/AIConversationMessage.ts +495 -0
- package/Models/DatabaseModels/AIRun.ts +584 -0
- package/Models/DatabaseModels/AIRunEvent.ts +443 -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 +11 -0
- package/Models/DatabaseModels/LlmLog.ts +26 -0
- package/Models/DatabaseModels/LlmProvider.ts +2 -2
- 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/Server/API/AIChatAPI.ts +693 -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 +170 -0
- package/Server/API/MicrosoftTeamsAPI.ts +5 -0
- package/Server/API/ScheduledMaintenanceAPI.ts +1 -1
- package/Server/API/SlackAPI.ts +663 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783363279075-AddAIChatModels.ts +245 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783443471795-AddLlmProviderToAIConversation.ts +36 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783453297388-AddAIChatWriteActionsAndWidgets.ts +46 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783461767405-MigrationName.ts +119 -0
- 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/Index.ts +16 -0
- package/Server/Infrastructure/PostgresDatabase.ts +11 -0
- package/Server/Services/AIConversationMessageService.ts +39 -0
- package/Server/Services/AIConversationService.ts +63 -0
- package/Server/Services/AIRunEventService.ts +39 -0
- package/Server/Services/AIRunService.ts +39 -0
- package/Server/Services/AIService.ts +127 -33
- package/Server/Services/AnalyticsDatabaseService.ts +10 -1
- package/Server/Services/DatabaseService.ts +29 -1
- package/Server/Services/IncidentService.ts +1 -1
- package/Server/Services/IncomingCallPolicyEscalationRuleService.ts +75 -2
- package/Server/Services/IncomingCallPolicyService.ts +42 -1
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/LlmProviderService.ts +110 -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/ProjectService.ts +24 -0
- 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/AnalyticsDatabase/ModelPermission.ts +74 -9
- package/Server/Types/Database/QueryUtil.ts +57 -0
- package/Server/Utils/AI/AIChatPrivacyFilter.ts +28 -0
- package/Server/Utils/AI/AlertAIContextBuilder.ts +6 -1
- package/Server/Utils/AI/Chat/ChatAgentRunner.ts +1066 -0
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +239 -0
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +51 -0
- 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/Toolbox/AlertTools.ts +201 -0
- package/Server/Utils/AI/Toolbox/AlertWriteTools.ts +174 -0
- package/Server/Utils/AI/Toolbox/ContextTools.ts +189 -0
- package/Server/Utils/AI/Toolbox/ExceptionTools.ts +149 -0
- package/Server/Utils/AI/Toolbox/IncidentTools.ts +386 -0
- package/Server/Utils/AI/Toolbox/IncidentWriteTools.ts +350 -0
- package/Server/Utils/AI/Toolbox/Index.ts +231 -0
- package/Server/Utils/AI/Toolbox/LogTools.ts +339 -0
- package/Server/Utils/AI/Toolbox/MetricTools.ts +179 -0
- package/Server/Utils/AI/Toolbox/MonitorTools.ts +193 -0
- package/Server/Utils/AI/Toolbox/RecentChangesTools.ts +208 -0
- package/Server/Utils/AI/Toolbox/Serializer.ts +299 -0
- package/Server/Utils/AI/Toolbox/ToolTypes.ts +249 -0
- package/Server/Utils/AI/Toolbox/TraceTools.ts +402 -0
- package/Server/Utils/AI/Toolbox/WidgetBuilder.ts +189 -0
- package/Server/Utils/Database/MigrationFailureLog.ts +240 -0
- package/Server/Utils/IncomingCallPhoneNumber.ts +41 -0
- package/Server/Utils/LLM/LLMService.ts +605 -96
- package/Server/Utils/Telemetry/IoTSnapshotScan.ts +12 -9
- package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +12 -9
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +512 -19
- package/Server/Utils/Workspace/Slack/Slack.ts +80 -0
- package/Server/Utils/Workspace/Slack/app-manifest.json +16 -1
- 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/AIChatModelACL.test.ts +42 -0
- package/Tests/Server/Utils/AI/ChatAgentHelpers.test.ts +89 -0
- package/Tests/Server/Utils/AI/LLMServiceBaseUrl.test.ts +139 -0
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +386 -0
- package/Tests/Server/Utils/AI/ToolArgsGetTimeRange.test.ts +62 -0
- package/Tests/Server/Utils/AI/ToolArgsScopeServiceIds.test.ts +79 -0
- package/Tests/Server/Utils/AI/ToolResultSerializer.test.ts +223 -0
- package/Tests/Types/Billing/SubscriptionStatus.test.ts +127 -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/Metrics/RecordingRuleDefinition.test.ts +213 -0
- 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/UserOverrideUtil.test.ts +255 -0
- package/Tests/Types/OnCallDutyPolicy/UserOverrideUtilExhaustive.test.ts +1126 -0
- package/Types/AI/AIChatMessageRole.ts +6 -0
- package/Types/AI/AIChatMessageStatus.ts +32 -0
- package/Types/AI/AIChatPermissionMode.ts +69 -0
- package/Types/AI/AIChatTypes.ts +231 -0
- package/Types/AI/AIRunEventType.ts +17 -0
- package/Types/AI/AIRunStatus.ts +28 -0
- package/Types/AI/AIRunType.ts +6 -0
- package/Types/Date.ts +200 -15
- package/Types/LLM/LlmType.ts +6 -0
- package/Types/OnCallDutyPolicy/Layer.ts +790 -260
- package/Types/OnCallDutyPolicy/RestrictionTimes.ts +39 -13
- package/Types/OnCallDutyPolicy/UserOverrideUtil.ts +21 -5
- package/UI/Components/Events/RecurringFieldElement.tsx +16 -0
- package/UI/Components/Header/HeaderIconDropdownButton.tsx +22 -12
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +35 -3
- package/UI/Components/ModelFormModal/ModelFormModal.tsx +8 -0
- package/UI/Components/Page/Page.tsx +14 -0
- package/UI/Components/RadioButtons/BasicRadioButtons.tsx +1 -1
- package/UI/Utils/LlmTypeDropdownOptions.ts +40 -0
- package/UI/Utils/TestLLMProvider.ts +59 -0
- package/build/dist/Models/DatabaseModels/AIConversation.js +345 -0
- package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AIConversationMessage.js +521 -0
- package/build/dist/Models/DatabaseModels/AIConversationMessage.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AIRun.js +619 -0
- package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AIRunEvent.js +469 -0
- package/build/dist/Models/DatabaseModels/AIRunEvent.js.map +1 -0
- 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 +10 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LlmLog.js +28 -0
- package/build/dist/Models/DatabaseModels/LlmLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LlmProvider.js +2 -2
- package/build/dist/Models/DatabaseModels/LlmProvider.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/Server/API/AIChatAPI.js +498 -0
- package/build/dist/Server/API/AIChatAPI.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 +108 -1
- package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +4 -0
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js +1 -1
- package/build/dist/Server/API/SlackAPI.js +442 -0
- package/build/dist/Server/API/SlackAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783363279075-AddAIChatModels.js +96 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783363279075-AddAIChatModels.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783443471795-AddLlmProviderToAIConversation.js +25 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783443471795-AddLlmProviderToAIConversation.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783453297388-AddAIChatWriteActionsAndWidgets.js +31 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783453297388-AddAIChatWriteActionsAndWidgets.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783461767405-MigrationName.js +46 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783461767405-MigrationName.js.map +1 -0
- 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/Index.js +16 -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/AIConversationMessageService.js +34 -0
- package/build/dist/Server/Services/AIConversationMessageService.js.map +1 -0
- package/build/dist/Server/Services/AIConversationService.js +42 -0
- package/build/dist/Server/Services/AIConversationService.js.map +1 -0
- package/build/dist/Server/Services/AIRunEventService.js +34 -0
- package/build/dist/Server/Services/AIRunEventService.js.map +1 -0
- package/build/dist/Server/Services/AIRunService.js +34 -0
- package/build/dist/Server/Services/AIRunService.js.map +1 -0
- package/build/dist/Server/Services/AIService.js +84 -25
- package/build/dist/Server/Services/AIService.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 +20 -1
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +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/LlmProviderService.js +108 -0
- package/build/dist/Server/Services/LlmProviderService.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/ProjectService.js +25 -0
- package/build/dist/Server/Services/ProjectService.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/AnalyticsDatabase/ModelPermission.js +50 -7
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.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/AIChatPrivacyFilter.js +18 -0
- package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js.map +1 -0
- 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 +756 -0
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +165 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +44 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -0
- 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/Toolbox/AlertTools.js +167 -0
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/AlertWriteTools.js +136 -0
- package/build/dist/Server/Utils/AI/Toolbox/AlertWriteTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/ContextTools.js +141 -0
- package/build/dist/Server/Utils/AI/Toolbox/ContextTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/ExceptionTools.js +117 -0
- package/build/dist/Server/Utils/AI/Toolbox/ExceptionTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +318 -0
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/IncidentWriteTools.js +280 -0
- package/build/dist/Server/Utils/AI/Toolbox/IncidentWriteTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js +153 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/LogTools.js +246 -0
- package/build/dist/Server/Utils/AI/Toolbox/LogTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/MetricTools.js +120 -0
- package/build/dist/Server/Utils/AI/Toolbox/MetricTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js +158 -0
- package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js.map +1 -0
- 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/Serializer.js +228 -0
- package/build/dist/Server/Utils/AI/Toolbox/Serializer.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/ToolTypes.js +142 -0
- package/build/dist/Server/Utils/AI/Toolbox/ToolTypes.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/TraceTools.js +309 -0
- package/build/dist/Server/Utils/AI/Toolbox/TraceTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/WidgetBuilder.js +120 -0
- package/build/dist/Server/Utils/AI/Toolbox/WidgetBuilder.js.map +1 -0
- 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 +452 -92
- 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/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +378 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +59 -0
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/app-manifest.json +16 -1
- package/build/dist/Types/AI/AIChatMessageRole.js +7 -0
- package/build/dist/Types/AI/AIChatMessageRole.js.map +1 -0
- package/build/dist/Types/AI/AIChatMessageStatus.js +27 -0
- package/build/dist/Types/AI/AIChatMessageStatus.js.map +1 -0
- package/build/dist/Types/AI/AIChatPermissionMode.js +53 -0
- package/build/dist/Types/AI/AIChatPermissionMode.js.map +1 -0
- package/build/dist/Types/AI/AIChatTypes.js +74 -0
- package/build/dist/Types/AI/AIChatTypes.js.map +1 -0
- package/build/dist/Types/AI/AIRunEventType.js +18 -0
- package/build/dist/Types/AI/AIRunEventType.js.map +1 -0
- package/build/dist/Types/AI/AIRunStatus.js +26 -0
- package/build/dist/Types/AI/AIRunStatus.js.map +1 -0
- package/build/dist/Types/AI/AIRunType.js +7 -0
- package/build/dist/Types/AI/AIRunType.js.map +1 -0
- package/build/dist/Types/Date.js +153 -15
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/LLM/LlmType.js +6 -0
- package/build/dist/Types/LLM/LlmType.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/UserOverrideUtil.js +20 -5
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.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/Header/HeaderIconDropdownButton.js +10 -5
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +18 -4
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/UI/Components/Page/Page.js +3 -1
- package/build/dist/UI/Components/Page/Page.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/build/dist/UI/Utils/LlmTypeDropdownOptions.js +38 -0
- package/build/dist/UI/Utils/LlmTypeDropdownOptions.js.map +1 -0
- package/build/dist/UI/Utils/TestLLMProvider.js +37 -0
- package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -0
- package/package.json +1 -1
package/Server/Services/Index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import BillingService from "./BillingService";
|
|
|
12
12
|
import CallLogService from "./CallLogService";
|
|
13
13
|
import CallService from "./CallService";
|
|
14
14
|
import DataMigrationService from "./DataMigrationService";
|
|
15
|
+
import MigrationFailureService from "./MigrationFailureService";
|
|
15
16
|
import DomainService from "./DomainService";
|
|
16
17
|
import EmailLogService from "./EmailLogService";
|
|
17
18
|
import EmailVerificationTokenService from "./EmailVerificationTokenService";
|
|
@@ -273,6 +274,7 @@ const services: Array<BaseService> = [
|
|
|
273
274
|
CallService,
|
|
274
275
|
|
|
275
276
|
DataMigrationService,
|
|
277
|
+
MigrationFailureService,
|
|
276
278
|
DomainService,
|
|
277
279
|
|
|
278
280
|
EmailLogService,
|
|
@@ -6,6 +6,7 @@ import ObjectID from "../../Types/ObjectID";
|
|
|
6
6
|
import UpdateBy from "../Types/Database/UpdateBy";
|
|
7
7
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
8
8
|
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
9
|
+
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
9
10
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
10
11
|
|
|
11
12
|
export class Service extends DatabaseService<Model> {
|
|
@@ -153,6 +154,115 @@ export class Service extends DatabaseService<Model> {
|
|
|
153
154
|
|
|
154
155
|
return null;
|
|
155
156
|
}
|
|
157
|
+
|
|
158
|
+
/*
|
|
159
|
+
* Resolve the provider to use for a chat turn. When the user has explicitly
|
|
160
|
+
* chosen a provider (llmProviderId), use it — but only if it is actually
|
|
161
|
+
* usable by this project: either a global provider, or one owned by the
|
|
162
|
+
* project. Otherwise fall back to the project default / global provider.
|
|
163
|
+
* A stale id (e.g. the chosen provider was deleted) also falls back, so a
|
|
164
|
+
* conversation never breaks because its provider went away.
|
|
165
|
+
*/
|
|
166
|
+
@CaptureSpan()
|
|
167
|
+
public async getProviderForChat(data: {
|
|
168
|
+
projectId: ObjectID;
|
|
169
|
+
llmProviderId?: ObjectID | undefined;
|
|
170
|
+
}): Promise<Model | null> {
|
|
171
|
+
if (data.llmProviderId) {
|
|
172
|
+
const provider: Model | null = await this.findOneBy({
|
|
173
|
+
query: {
|
|
174
|
+
_id: data.llmProviderId.toString(),
|
|
175
|
+
},
|
|
176
|
+
select: {
|
|
177
|
+
_id: true,
|
|
178
|
+
name: true,
|
|
179
|
+
llmType: true,
|
|
180
|
+
apiKey: true,
|
|
181
|
+
baseUrl: true,
|
|
182
|
+
modelName: true,
|
|
183
|
+
isGlobalLlm: true,
|
|
184
|
+
projectId: true,
|
|
185
|
+
costPerMillionTokensInUSDCents: true,
|
|
186
|
+
},
|
|
187
|
+
props: {
|
|
188
|
+
isRoot: true,
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
if (provider) {
|
|
193
|
+
const isGlobal: boolean = provider.isGlobalLlm === true;
|
|
194
|
+
const belongsToProject: boolean =
|
|
195
|
+
provider.projectId?.toString() === data.projectId.toString();
|
|
196
|
+
|
|
197
|
+
if (isGlobal || belongsToProject) {
|
|
198
|
+
return provider;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Fall through to default resolution when the id is invalid/inaccessible.
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return this.getLLMProviderForProject(data.projectId);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/*
|
|
208
|
+
* The providers a project member can pick from in the chat provider switcher:
|
|
209
|
+
* every provider configured for the project plus every global provider.
|
|
210
|
+
* Secrets (apiKey) are never selected here — this only feeds the picker UI.
|
|
211
|
+
*/
|
|
212
|
+
@CaptureSpan()
|
|
213
|
+
public async getSelectableProvidersForProject(
|
|
214
|
+
projectId: ObjectID,
|
|
215
|
+
): Promise<Array<Model>> {
|
|
216
|
+
const [projectProviders, globalProviders]: [Array<Model>, Array<Model>] =
|
|
217
|
+
await Promise.all([
|
|
218
|
+
this.findBy({
|
|
219
|
+
query: {
|
|
220
|
+
projectId: projectId,
|
|
221
|
+
},
|
|
222
|
+
select: {
|
|
223
|
+
_id: true,
|
|
224
|
+
name: true,
|
|
225
|
+
llmType: true,
|
|
226
|
+
modelName: true,
|
|
227
|
+
isDefault: true,
|
|
228
|
+
isGlobalLlm: true,
|
|
229
|
+
},
|
|
230
|
+
sort: {
|
|
231
|
+
isDefault: SortOrder.Descending,
|
|
232
|
+
name: SortOrder.Ascending,
|
|
233
|
+
},
|
|
234
|
+
skip: 0,
|
|
235
|
+
limit: LIMIT_MAX,
|
|
236
|
+
props: {
|
|
237
|
+
isRoot: true,
|
|
238
|
+
},
|
|
239
|
+
}),
|
|
240
|
+
this.findBy({
|
|
241
|
+
query: {
|
|
242
|
+
projectId: QueryHelper.isNull(),
|
|
243
|
+
isGlobalLlm: true,
|
|
244
|
+
},
|
|
245
|
+
select: {
|
|
246
|
+
_id: true,
|
|
247
|
+
name: true,
|
|
248
|
+
llmType: true,
|
|
249
|
+
modelName: true,
|
|
250
|
+
isDefault: true,
|
|
251
|
+
isGlobalLlm: true,
|
|
252
|
+
},
|
|
253
|
+
sort: {
|
|
254
|
+
name: SortOrder.Ascending,
|
|
255
|
+
},
|
|
256
|
+
skip: 0,
|
|
257
|
+
limit: LIMIT_MAX,
|
|
258
|
+
props: {
|
|
259
|
+
isRoot: true,
|
|
260
|
+
},
|
|
261
|
+
}),
|
|
262
|
+
]);
|
|
263
|
+
|
|
264
|
+
return [...projectProviders, ...globalProviders];
|
|
265
|
+
}
|
|
156
266
|
}
|
|
157
267
|
|
|
158
268
|
export default new Service();
|
|
@@ -310,8 +310,14 @@ export class Service extends DatabaseService<MonitorProbe> {
|
|
|
310
310
|
_onCreate: OnCreate<MonitorProbe>,
|
|
311
311
|
createdItem: MonitorProbe,
|
|
312
312
|
): Promise<MonitorProbe> {
|
|
313
|
-
|
|
314
|
-
|
|
313
|
+
/*
|
|
314
|
+
* Refresh only the monitor this probe was just added to. Do NOT call
|
|
315
|
+
* refreshProbeStatus(probeId) here: a global/shared probe can be attached
|
|
316
|
+
* to thousands of monitors, and refreshing every one of them on a single
|
|
317
|
+
* create storms the database and can 500 the request.
|
|
318
|
+
*/
|
|
319
|
+
if (createdItem.monitorId) {
|
|
320
|
+
await this.refreshMonitorStatusSafely(createdItem.monitorId);
|
|
315
321
|
}
|
|
316
322
|
|
|
317
323
|
return Promise.resolve(createdItem);
|
|
@@ -321,7 +327,7 @@ export class Service extends DatabaseService<MonitorProbe> {
|
|
|
321
327
|
onUpdate: OnUpdate<MonitorProbe>,
|
|
322
328
|
updatedItemIds: ObjectID[],
|
|
323
329
|
): Promise<OnUpdate<MonitorProbe>> {
|
|
324
|
-
// if isEnabled is updated, refresh the
|
|
330
|
+
// if isEnabled is updated, refresh the status of the affected monitors.
|
|
325
331
|
if (onUpdate.updateBy.data.isEnabled !== undefined) {
|
|
326
332
|
const monitorProbes: Array<MonitorProbe> = await this.findBy({
|
|
327
333
|
query: {
|
|
@@ -329,8 +335,6 @@ export class Service extends DatabaseService<MonitorProbe> {
|
|
|
329
335
|
},
|
|
330
336
|
select: {
|
|
331
337
|
monitorId: true,
|
|
332
|
-
probeId: true,
|
|
333
|
-
nextPingAt: true,
|
|
334
338
|
},
|
|
335
339
|
limit: LIMIT_PER_PROJECT,
|
|
336
340
|
skip: 0,
|
|
@@ -340,16 +344,38 @@ export class Service extends DatabaseService<MonitorProbe> {
|
|
|
340
344
|
});
|
|
341
345
|
|
|
342
346
|
for (const monitorProbe of monitorProbes) {
|
|
343
|
-
if (!monitorProbe.
|
|
347
|
+
if (!monitorProbe.monitorId) {
|
|
344
348
|
continue;
|
|
345
349
|
}
|
|
346
350
|
|
|
347
|
-
|
|
351
|
+
/*
|
|
352
|
+
* Refresh only the monitor whose probe row changed. Do NOT call
|
|
353
|
+
* refreshProbeStatus(probeId) here: a global/shared probe can be
|
|
354
|
+
* attached to thousands of monitors, and refreshing all of them on a
|
|
355
|
+
* single enable/disable toggle storms the database and 500s the
|
|
356
|
+
* request (the row itself is already saved by this point).
|
|
357
|
+
*/
|
|
358
|
+
await this.refreshMonitorStatusSafely(monitorProbe.monitorId);
|
|
348
359
|
}
|
|
349
360
|
}
|
|
350
361
|
|
|
351
362
|
return onUpdate;
|
|
352
363
|
}
|
|
364
|
+
|
|
365
|
+
/*
|
|
366
|
+
* Refresh a single monitor's aggregate probe status without letting a
|
|
367
|
+
* failure bubble up. These refreshes run in post-commit hooks
|
|
368
|
+
* (onCreateSuccess / onUpdateSuccess) after the MonitorProbe row is already
|
|
369
|
+
* persisted, so a status-refresh error must not turn a successful save into
|
|
370
|
+
* a 500 for the user — log it instead.
|
|
371
|
+
*/
|
|
372
|
+
private async refreshMonitorStatusSafely(monitorId: ObjectID): Promise<void> {
|
|
373
|
+
try {
|
|
374
|
+
await MonitorService.refreshMonitorProbeStatus(monitorId);
|
|
375
|
+
} catch (err) {
|
|
376
|
+
logger.error(err);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
353
379
|
}
|
|
354
380
|
|
|
355
381
|
export default new Service();
|
|
@@ -1620,14 +1620,26 @@ ${createdItem.description?.trim() || "No description provided."}
|
|
|
1620
1620
|
|
|
1621
1621
|
/*
|
|
1622
1622
|
* Each monitor appears at most once for a given probeId (composite
|
|
1623
|
-
* unique on MonitorProbe), so concurrent refreshes operate on
|
|
1624
|
-
*
|
|
1623
|
+
* unique on MonitorProbe), so concurrent refreshes operate on disjoint
|
|
1624
|
+
* rows and are safe to run in parallel. A global/shared probe can be
|
|
1625
|
+
* attached to thousands of monitors, though, so refresh in bounded
|
|
1626
|
+
* batches instead of firing every refresh at once — an unbounded
|
|
1627
|
+
* Promise.all here would exhaust the database connection pool.
|
|
1625
1628
|
*/
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1629
|
+
const refreshConcurrency: number = 50;
|
|
1630
|
+
|
|
1631
|
+
for (let i: number = 0; i < monitorProbes.length; i += refreshConcurrency) {
|
|
1632
|
+
const batch: Array<MonitorProbe> = monitorProbes.slice(
|
|
1633
|
+
i,
|
|
1634
|
+
i + refreshConcurrency,
|
|
1635
|
+
);
|
|
1636
|
+
|
|
1637
|
+
await Promise.all(
|
|
1638
|
+
batch.map((monitorProbe: MonitorProbe) => {
|
|
1639
|
+
return this.refreshMonitorProbeStatus(monitorProbe.monitorId!);
|
|
1640
|
+
}),
|
|
1641
|
+
);
|
|
1642
|
+
}
|
|
1631
1643
|
}
|
|
1632
1644
|
|
|
1633
1645
|
@CaptureSpan()
|
|
@@ -22,6 +22,9 @@ import PushNotificationMessage from "../../Types/PushNotification/PushNotificati
|
|
|
22
22
|
import PushNotificationUtil from "../Utils/PushNotificationUtil";
|
|
23
23
|
import { createWhatsAppMessageFromTemplate } from "../Utils/WhatsAppTemplateUtil";
|
|
24
24
|
import { WhatsAppMessagePayload } from "../../Types/WhatsApp/WhatsAppMessage";
|
|
25
|
+
import OnCallDutyPolicyTimeLogService from "./OnCallDutyPolicyTimeLogService";
|
|
26
|
+
import OneUptimeDate from "../../Types/Date";
|
|
27
|
+
import logger, { LogAttributes } from "../Utils/Logger";
|
|
25
28
|
|
|
26
29
|
export class Service extends DatabaseService<Model> {
|
|
27
30
|
public constructor() {
|
|
@@ -86,6 +89,39 @@ export class Service extends DatabaseService<Model> {
|
|
|
86
89
|
return createdItem;
|
|
87
90
|
}
|
|
88
91
|
|
|
92
|
+
/*
|
|
93
|
+
* Open the roster user's on-call time log for this schedule/rule/policy.
|
|
94
|
+
* Mirrors onDeleteSuccess's endTimeLogForUser (detaching a schedule closes
|
|
95
|
+
* the log, so attaching must open it). Without this, attaching a schedule
|
|
96
|
+
* whose roster user is ALREADY established never opened a log — the roster
|
|
97
|
+
* refresh only opens one when the current user CHANGES — so the whole stint
|
|
98
|
+
* went unrecorded in on-call reporting and the later detach's
|
|
99
|
+
* endTimeLogForUser was a no-op (audit M1). startTimeLogForUser is idempotent
|
|
100
|
+
* (open-log dedup), so a later natural handoff re-opening the same log is a
|
|
101
|
+
* no-op.
|
|
102
|
+
*/
|
|
103
|
+
if (
|
|
104
|
+
createdModel.onCallDutyPolicy?.id &&
|
|
105
|
+
createdModel.onCallDutyPolicyEscalationRule?.id &&
|
|
106
|
+
createdModel.projectId &&
|
|
107
|
+
createdModel.onCallDutyPolicyScheduleId
|
|
108
|
+
) {
|
|
109
|
+
OnCallDutyPolicyTimeLogService.startTimeLogForUser({
|
|
110
|
+
projectId: createdModel.projectId,
|
|
111
|
+
onCallDutyPolicyId: createdModel.onCallDutyPolicy.id,
|
|
112
|
+
onCallDutyPolicyEscalationRuleId:
|
|
113
|
+
createdModel.onCallDutyPolicyEscalationRule.id,
|
|
114
|
+
userId: userOnSchedule,
|
|
115
|
+
onCallDutyPolicyScheduleId: createdModel.onCallDutyPolicyScheduleId,
|
|
116
|
+
startsAt: OneUptimeDate.getCurrentDate(),
|
|
117
|
+
}).catch((error: Error) => {
|
|
118
|
+
logger.error(error, {
|
|
119
|
+
projectId: createdModel.projectId?.toString(),
|
|
120
|
+
userId: userOnSchedule?.toString(),
|
|
121
|
+
} as LogAttributes);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
89
125
|
const scheduleName: string =
|
|
90
126
|
createdModel.onCallDutyPolicySchedule?.name || "No name provided";
|
|
91
127
|
|
|
@@ -289,6 +325,35 @@ export class Service extends DatabaseService<Model> {
|
|
|
289
325
|
continue;
|
|
290
326
|
}
|
|
291
327
|
|
|
328
|
+
/*
|
|
329
|
+
* Close the roster user's open on-call time log for this schedule/rule/
|
|
330
|
+
* policy. Roster handoffs open a time log keyed by schedule + rule + policy
|
|
331
|
+
* (OnCallDutyPolicyScheduleService.startTimeLogForUser); the user-link and
|
|
332
|
+
* team-link delete handlers close theirs, but detaching a SCHEDULE from the
|
|
333
|
+
* rule left the log open forever, so the roster user kept showing as
|
|
334
|
+
* on-call in reporting (audit F18).
|
|
335
|
+
*/
|
|
336
|
+
if (
|
|
337
|
+
deletedItem.onCallDutyPolicy?.id &&
|
|
338
|
+
deletedItem.onCallDutyPolicyEscalationRule?.id &&
|
|
339
|
+
deletedItem.projectId
|
|
340
|
+
) {
|
|
341
|
+
OnCallDutyPolicyTimeLogService.endTimeLogForUser({
|
|
342
|
+
projectId: deletedItem.projectId,
|
|
343
|
+
onCallDutyPolicyId: deletedItem.onCallDutyPolicy.id,
|
|
344
|
+
onCallDutyPolicyEscalationRuleId:
|
|
345
|
+
deletedItem.onCallDutyPolicyEscalationRule.id,
|
|
346
|
+
userId: userOnSchedule,
|
|
347
|
+
onCallDutyPolicyScheduleId: deletedItem.onCallDutyPolicyScheduleId!,
|
|
348
|
+
endsAt: OneUptimeDate.getCurrentDate(),
|
|
349
|
+
}).catch((error: Error) => {
|
|
350
|
+
logger.error(error, {
|
|
351
|
+
projectId: deletedItem.projectId?.toString(),
|
|
352
|
+
userId: userOnSchedule?.toString(),
|
|
353
|
+
} as LogAttributes);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
292
357
|
const sendEmailToUserId: ObjectID | undefined | null = userOnSchedule;
|
|
293
358
|
|
|
294
359
|
if (!sendEmailToUserId) {
|
|
@@ -10,6 +10,7 @@ import OnCallDutyPolicyEscalationRuleScheduleService from "./OnCallDutyPolicyEsc
|
|
|
10
10
|
import OnCallDutyPolicyEscalationRuleTeamService from "./OnCallDutyPolicyEscalationRuleTeamService";
|
|
11
11
|
import OnCallDutyPolicyEscalationRuleUserService from "./OnCallDutyPolicyEscalationRuleUserService";
|
|
12
12
|
import OnCallDutyPolicyExecutionLogService from "./OnCallDutyPolicyExecutionLogService";
|
|
13
|
+
import OnCallDutyPolicyExecutionLog from "../../Models/DatabaseModels/OnCallDutyPolicyExecutionLog";
|
|
13
14
|
import OnCallDutyPolicyExecutionLogTimelineService from "./OnCallDutyPolicyExecutionLogTimelineService";
|
|
14
15
|
import OnCallDutyPolicyScheduleService from "./OnCallDutyPolicyScheduleService";
|
|
15
16
|
import TeamMemberService from "./TeamMemberService";
|
|
@@ -315,31 +316,66 @@ export class Service extends DatabaseService<Model> {
|
|
|
315
316
|
);
|
|
316
317
|
|
|
317
318
|
type StartUserNotificationRuleExecutionFunction = (
|
|
318
|
-
|
|
319
|
+
originalUserId: ObjectID,
|
|
320
|
+
alertSentToUserId: ObjectID,
|
|
319
321
|
teamId: ObjectID | null,
|
|
320
322
|
scheduleId: ObjectID | null,
|
|
321
323
|
) => Promise<void>;
|
|
322
324
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
325
|
+
/*
|
|
326
|
+
* Resolve the FINAL alert recipient for a target, applying a user override
|
|
327
|
+
* (getRouteAlertToUserId) exactly ONCE per paging decision.
|
|
328
|
+
*
|
|
329
|
+
* Schedule targets are already override-resolved: getCurrentUserIdInSchedule
|
|
330
|
+
* applies overrides via UserOverrideUtil. Applying getRouteAlertToUserId to
|
|
331
|
+
* them again re-substituted an already-substituted user (transitive), so the
|
|
332
|
+
* schedule paging path could page a different person than the roster,
|
|
333
|
+
* dashboard, handoff notification, and a rule that lists the same user
|
|
334
|
+
* directly — all of which apply overrides only once (audit F5). So team and
|
|
335
|
+
* direct-user targets (the RAW roster user) get the single override hop here;
|
|
336
|
+
* schedule targets do not.
|
|
337
|
+
*/
|
|
338
|
+
const resolveAlertRecipientUserId: (
|
|
339
|
+
userId: ObjectID,
|
|
340
|
+
isFromSchedule: boolean,
|
|
341
|
+
) => Promise<ObjectID> = async (
|
|
342
|
+
userId: ObjectID,
|
|
343
|
+
isFromSchedule: boolean,
|
|
344
|
+
): Promise<ObjectID> => {
|
|
345
|
+
if (isFromSchedule) {
|
|
346
|
+
return userId;
|
|
347
|
+
}
|
|
333
348
|
|
|
334
|
-
|
|
335
|
-
|
|
349
|
+
if (options.onCallPolicyId) {
|
|
350
|
+
const routeAlertToUserId: ObjectID | null =
|
|
351
|
+
await this.getRouteAlertToUserId({
|
|
336
352
|
userId,
|
|
337
353
|
onCallDutyPolicyId: options.onCallPolicyId,
|
|
338
354
|
projectId: options.projectId,
|
|
339
355
|
});
|
|
356
|
+
|
|
357
|
+
if (routeAlertToUserId) {
|
|
358
|
+
return routeAlertToUserId;
|
|
340
359
|
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return userId;
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
const startUserNotificationRuleExecution: StartUserNotificationRuleExecutionFunction =
|
|
366
|
+
async (
|
|
367
|
+
originalUserId: ObjectID,
|
|
368
|
+
alertSentToUserId: ObjectID,
|
|
369
|
+
teamId: ObjectID | null,
|
|
370
|
+
scheduleId: ObjectID | null,
|
|
371
|
+
): Promise<void> => {
|
|
372
|
+
/*
|
|
373
|
+
* This is where user is notified. alertSentToUserId is already resolved
|
|
374
|
+
* (override applied at most once by resolveAlertRecipientUserId).
|
|
375
|
+
*/
|
|
341
376
|
|
|
342
|
-
const
|
|
377
|
+
const wasOverridden: boolean =
|
|
378
|
+
alertSentToUserId.toString() !== originalUserId.toString();
|
|
343
379
|
|
|
344
380
|
logger.debug(
|
|
345
381
|
`Starting notification rule execution for userId: ${alertSentToUserId.toString()}`,
|
|
@@ -354,8 +390,8 @@ export class Service extends DatabaseService<Model> {
|
|
|
354
390
|
log.status = OnCallDutyExecutionLogTimelineStatus.Executing;
|
|
355
391
|
log.alertSentToUserId = alertSentToUserId;
|
|
356
392
|
|
|
357
|
-
if (
|
|
358
|
-
log.overridedByUserId =
|
|
393
|
+
if (wasOverridden) {
|
|
394
|
+
log.overridedByUserId = originalUserId;
|
|
359
395
|
}
|
|
360
396
|
|
|
361
397
|
if (teamId) {
|
|
@@ -390,12 +426,36 @@ export class Service extends DatabaseService<Model> {
|
|
|
390
426
|
onCallDutyPolicyExecutionLogTimelineId: log.id!,
|
|
391
427
|
projectId: options.projectId,
|
|
392
428
|
onCallScheduleId: scheduleId || undefined,
|
|
393
|
-
overridedByUserId:
|
|
429
|
+
overridedByUserId: wasOverridden ? originalUserId : undefined,
|
|
394
430
|
},
|
|
395
431
|
);
|
|
396
432
|
};
|
|
397
433
|
|
|
434
|
+
/*
|
|
435
|
+
* Dedup on the RESOLVED recipient (post-override), not the pre-route id.
|
|
436
|
+
* Keying on the pre-route id let two different targets that both reroute to
|
|
437
|
+
* the same backup each fire a full notification chain for the same person in
|
|
438
|
+
* one rule (audit F6).
|
|
439
|
+
*/
|
|
398
440
|
const uniqueUserIds: Array<ObjectID> = [];
|
|
441
|
+
const alreadyNotified: (recipientId: ObjectID) => boolean = (
|
|
442
|
+
recipientId: ObjectID,
|
|
443
|
+
): boolean => {
|
|
444
|
+
return Boolean(
|
|
445
|
+
uniqueUserIds.find((userId: ObjectID) => {
|
|
446
|
+
return recipientId.toString() === userId.toString();
|
|
447
|
+
}),
|
|
448
|
+
);
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
/*
|
|
452
|
+
* M-5: tracks whether any schedule target for this rule momentarily had no
|
|
453
|
+
* on-call user (a restriction gap / future start / empty layer). If a rule
|
|
454
|
+
* reaches NO ONE solely because of such a gap, we re-sample the same rule on
|
|
455
|
+
* the next cron ticks (bounded) instead of permanently skipping it, so a
|
|
456
|
+
* user coming on-call moments later still gets paged.
|
|
457
|
+
*/
|
|
458
|
+
let hadScheduleGap: boolean = false;
|
|
399
459
|
|
|
400
460
|
for (const teamInRule of teamsInRule) {
|
|
401
461
|
const usersInTeam: Array<User> = await TeamMemberService.getUsersInTeam(
|
|
@@ -403,14 +463,16 @@ export class Service extends DatabaseService<Model> {
|
|
|
403
463
|
);
|
|
404
464
|
|
|
405
465
|
for (const user of usersInTeam) {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
466
|
+
const recipientUserId: ObjectID = await resolveAlertRecipientUserId(
|
|
467
|
+
user.id!,
|
|
468
|
+
false,
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
if (!alreadyNotified(recipientUserId)) {
|
|
472
|
+
uniqueUserIds.push(recipientUserId);
|
|
412
473
|
await startUserNotificationRuleExecution(
|
|
413
474
|
user.id!,
|
|
475
|
+
recipientUserId,
|
|
414
476
|
teamInRule.teamId!,
|
|
415
477
|
null,
|
|
416
478
|
);
|
|
@@ -419,7 +481,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
419
481
|
log.statusMessage =
|
|
420
482
|
"Skipped because notification sent to this user already.";
|
|
421
483
|
log.status = OnCallDutyExecutionLogTimelineStatus.Skipped;
|
|
422
|
-
log.alertSentToUserId =
|
|
484
|
+
log.alertSentToUserId = recipientUserId;
|
|
423
485
|
log.userBelongsToTeamId = teamInRule.teamId!;
|
|
424
486
|
|
|
425
487
|
await OnCallDutyPolicyExecutionLogTimelineService.create({
|
|
@@ -433,19 +495,25 @@ export class Service extends DatabaseService<Model> {
|
|
|
433
495
|
}
|
|
434
496
|
|
|
435
497
|
for (const userRule of usersInRule) {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
498
|
+
const recipientUserId: ObjectID = await resolveAlertRecipientUserId(
|
|
499
|
+
userRule.userId!,
|
|
500
|
+
false,
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
if (!alreadyNotified(recipientUserId)) {
|
|
504
|
+
uniqueUserIds.push(recipientUserId);
|
|
505
|
+
await startUserNotificationRuleExecution(
|
|
506
|
+
userRule.userId!,
|
|
507
|
+
recipientUserId,
|
|
508
|
+
null,
|
|
509
|
+
null,
|
|
510
|
+
);
|
|
443
511
|
} else {
|
|
444
512
|
const log: OnCallDutyPolicyExecutionLogTimeline = getNewLog();
|
|
445
513
|
log.statusMessage =
|
|
446
514
|
"Skipped because notification sent to this user already.";
|
|
447
515
|
log.status = OnCallDutyExecutionLogTimelineStatus.Skipped;
|
|
448
|
-
log.alertSentToUserId =
|
|
516
|
+
log.alertSentToUserId = recipientUserId;
|
|
449
517
|
|
|
450
518
|
await OnCallDutyPolicyExecutionLogTimelineService.create({
|
|
451
519
|
data: log,
|
|
@@ -464,6 +532,8 @@ export class Service extends DatabaseService<Model> {
|
|
|
464
532
|
);
|
|
465
533
|
|
|
466
534
|
if (!userIdInSchedule) {
|
|
535
|
+
hadScheduleGap = true;
|
|
536
|
+
|
|
467
537
|
const log: OnCallDutyPolicyExecutionLogTimeline = getNewLog();
|
|
468
538
|
log.statusMessage =
|
|
469
539
|
"Skipped because no active users are found in this schedule.";
|
|
@@ -480,14 +550,17 @@ export class Service extends DatabaseService<Model> {
|
|
|
480
550
|
continue;
|
|
481
551
|
}
|
|
482
552
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
)
|
|
488
|
-
|
|
553
|
+
// Schedule users are already override-resolved; no second override hop (F5).
|
|
554
|
+
const recipientUserId: ObjectID = await resolveAlertRecipientUserId(
|
|
555
|
+
userIdInSchedule,
|
|
556
|
+
true,
|
|
557
|
+
);
|
|
558
|
+
|
|
559
|
+
if (!alreadyNotified(recipientUserId)) {
|
|
560
|
+
uniqueUserIds.push(recipientUserId);
|
|
489
561
|
await startUserNotificationRuleExecution(
|
|
490
562
|
userIdInSchedule,
|
|
563
|
+
recipientUserId,
|
|
491
564
|
null,
|
|
492
565
|
scheduleRule.onCallDutyPolicyScheduleId!,
|
|
493
566
|
);
|
|
@@ -496,7 +569,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
496
569
|
log.statusMessage =
|
|
497
570
|
"Skipped because notification sent to this user already.";
|
|
498
571
|
log.status = OnCallDutyExecutionLogTimelineStatus.Skipped;
|
|
499
|
-
log.alertSentToUserId =
|
|
572
|
+
log.alertSentToUserId = recipientUserId;
|
|
500
573
|
log.onCallDutyScheduleId = scheduleRule.onCallDutyPolicyScheduleId!;
|
|
501
574
|
|
|
502
575
|
await OnCallDutyPolicyExecutionLogTimelineService.create({
|
|
@@ -521,6 +594,77 @@ export class Service extends DatabaseService<Model> {
|
|
|
521
594
|
});
|
|
522
595
|
}
|
|
523
596
|
|
|
597
|
+
/*
|
|
598
|
+
* M-5: if this rule reached NO ONE and the only reason was a schedule gap
|
|
599
|
+
* (a schedule target with no on-call user right now), re-sample the SAME
|
|
600
|
+
* rule on the next cron ticks — bounded — instead of permanently skipping.
|
|
601
|
+
* ExecutePendingExecutions selects the rule with order =
|
|
602
|
+
* lastExecutedEscalationRuleOrder + 1, so rewinding the order by one makes
|
|
603
|
+
* it re-run this rule. No notifications were sent (uniqueUserIds is empty),
|
|
604
|
+
* so a re-sample cannot double-page anyone.
|
|
605
|
+
*/
|
|
606
|
+
const maxScheduleGapRetries: number = 5;
|
|
607
|
+
const scheduleGapRetryIntervalMinutes: number = 1;
|
|
608
|
+
const reachedNoOne: boolean = uniqueUserIds.length === 0;
|
|
609
|
+
|
|
610
|
+
if (reachedNoOne && hadScheduleGap && rule.order) {
|
|
611
|
+
const executionLog: OnCallDutyPolicyExecutionLog | null =
|
|
612
|
+
await OnCallDutyPolicyExecutionLogService.findOneById({
|
|
613
|
+
id: options.onCallPolicyExecutionLogId,
|
|
614
|
+
select: {
|
|
615
|
+
scheduleGapRetryCount: true,
|
|
616
|
+
},
|
|
617
|
+
props: {
|
|
618
|
+
isRoot: true,
|
|
619
|
+
},
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
const retryCount: number = executionLog?.scheduleGapRetryCount || 0;
|
|
623
|
+
|
|
624
|
+
if (retryCount < maxScheduleGapRetries) {
|
|
625
|
+
await OnCallDutyPolicyExecutionLogService.updateOneById({
|
|
626
|
+
id: options.onCallPolicyExecutionLogId,
|
|
627
|
+
data: {
|
|
628
|
+
lastExecutedEscalationRuleOrder: rule.order - 1,
|
|
629
|
+
executeNextEscalationRuleInMinutes: scheduleGapRetryIntervalMinutes,
|
|
630
|
+
scheduleGapRetryCount: retryCount + 1,
|
|
631
|
+
},
|
|
632
|
+
props: {
|
|
633
|
+
isRoot: true,
|
|
634
|
+
},
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
logger.debug(
|
|
638
|
+
`Rule ${ruleId.toString()} reached no one due to a schedule gap; re-sampling ${retryCount + 1}/${maxScheduleGapRetries}.`,
|
|
639
|
+
{
|
|
640
|
+
onCallDutyPolicyEscalationRuleId: ruleId.toString(),
|
|
641
|
+
} as LogAttributes,
|
|
642
|
+
);
|
|
643
|
+
} else {
|
|
644
|
+
// Retries exhausted — advance normally next tick and reset the counter.
|
|
645
|
+
await OnCallDutyPolicyExecutionLogService.updateOneById({
|
|
646
|
+
id: options.onCallPolicyExecutionLogId,
|
|
647
|
+
data: {
|
|
648
|
+
scheduleGapRetryCount: 0,
|
|
649
|
+
},
|
|
650
|
+
props: {
|
|
651
|
+
isRoot: true,
|
|
652
|
+
},
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
} else {
|
|
656
|
+
// Reached someone (or no schedule gap): clear retry state for the next rule.
|
|
657
|
+
await OnCallDutyPolicyExecutionLogService.updateOneById({
|
|
658
|
+
id: options.onCallPolicyExecutionLogId,
|
|
659
|
+
data: {
|
|
660
|
+
scheduleGapRetryCount: 0,
|
|
661
|
+
},
|
|
662
|
+
props: {
|
|
663
|
+
isRoot: true,
|
|
664
|
+
},
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
|
|
524
668
|
logger.debug(`Completed rule execution for ruleId: ${ruleId.toString()}`, {
|
|
525
669
|
projectId: options.projectId.toString(),
|
|
526
670
|
onCallDutyPolicyEscalationRuleId: ruleId.toString(),
|
|
@@ -912,8 +1056,8 @@ export class Service extends DatabaseService<Model> {
|
|
|
912
1056
|
// moving down.
|
|
913
1057
|
|
|
914
1058
|
for (const resource of resources) {
|
|
915
|
-
if (resource.order! <= newOrder) {
|
|
916
|
-
//
|
|
1059
|
+
if (resource.order! > currentOrder && resource.order! <= newOrder) {
|
|
1060
|
+
// decrement order to fill the gap left by the moved rule.
|
|
917
1061
|
await this.updateOneBy({
|
|
918
1062
|
query: {
|
|
919
1063
|
_id: resource._id!,
|