@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
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import DatabaseCommonInteractionProps from "../../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
2
|
+
import BadDataException from "../../../../Types/Exception/BadDataException";
|
|
3
|
+
import { JSONObject } from "../../../../Types/JSON";
|
|
4
|
+
import ObjectID from "../../../../Types/ObjectID";
|
|
5
|
+
import OneUptimeDate from "../../../../Types/Date";
|
|
6
|
+
import Permission from "../../../../Types/Permission";
|
|
7
|
+
import {
|
|
8
|
+
AIChatCitationTarget,
|
|
9
|
+
AIChatWidget,
|
|
10
|
+
} from "../../../../Types/AI/AIChatTypes";
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* The execution context for a tool call. projectId is ALWAYS the tenant from
|
|
14
|
+
* the authenticated request props — it is never a tool argument, so the model
|
|
15
|
+
* cannot point a tool at another project.
|
|
16
|
+
*/
|
|
17
|
+
export interface ToolContext {
|
|
18
|
+
projectId: ObjectID;
|
|
19
|
+
props: DatabaseCommonInteractionProps;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ToolExecutionResult {
|
|
23
|
+
// Serialized, truncated and redacted data that goes into the LLM prompt.
|
|
24
|
+
dataForLlm: string;
|
|
25
|
+
rowCount: number;
|
|
26
|
+
citationLabel: string;
|
|
27
|
+
citationTarget?: AIChatCitationTarget | undefined;
|
|
28
|
+
redactionCount: number;
|
|
29
|
+
isTruncated: boolean;
|
|
30
|
+
/*
|
|
31
|
+
* Optional structured widget (chart, table, trace waterfall, resource card)
|
|
32
|
+
* rendered inline in the chat. Built from the RAW rows the tool fetched — not
|
|
33
|
+
* the redacted LLM payload — because it is rendered back to the same user who
|
|
34
|
+
* already has RBAC access to this data.
|
|
35
|
+
*/
|
|
36
|
+
widget?: AIChatWidget | undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface ObservabilityTool {
|
|
40
|
+
name: string;
|
|
41
|
+
description: string;
|
|
42
|
+
// JSON Schema for the tool arguments, handed to the LLM.
|
|
43
|
+
inputSchema: JSONObject;
|
|
44
|
+
/*
|
|
45
|
+
* The user must hold at least one of these permissions for the tool to
|
|
46
|
+
* execute. For tools that call permission-checked services this is
|
|
47
|
+
* defense-in-depth; for tools that call raw-SQL aggregation services it is
|
|
48
|
+
* the authorization.
|
|
49
|
+
*/
|
|
50
|
+
requiredPermissions: Array<Permission>;
|
|
51
|
+
/*
|
|
52
|
+
* True for tools that MUTATE project data (create/acknowledge/resolve, etc).
|
|
53
|
+
* These are gated by the conversation's permission mode: paused for approval
|
|
54
|
+
* in AskForApproval mode, run immediately in AutoRun, and not offered to the
|
|
55
|
+
* model at all in ReadOnly. Undefined/false = a read-only tool that always
|
|
56
|
+
* runs.
|
|
57
|
+
*/
|
|
58
|
+
isMutation?: boolean | undefined;
|
|
59
|
+
/*
|
|
60
|
+
* Optional human-readable label for the approval card, derived from the
|
|
61
|
+
* (already validated) tool arguments — e.g. "Create incident: Checkout down".
|
|
62
|
+
* Falls back to the tool name when omitted.
|
|
63
|
+
*/
|
|
64
|
+
buildActionTitle?: ((args: JSONObject) => string) | undefined;
|
|
65
|
+
execute(args: JSONObject, ctx: ToolContext): Promise<ToolExecutionResult>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/*
|
|
69
|
+
* Defensive argument readers. Tool arguments come from the LLM and are
|
|
70
|
+
* untrusted: everything is type-checked, defaulted and clamped.
|
|
71
|
+
*/
|
|
72
|
+
export class ToolArgs {
|
|
73
|
+
public static getString(args: JSONObject, key: string): string | undefined {
|
|
74
|
+
const value: unknown = args[key];
|
|
75
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
76
|
+
return value.trim();
|
|
77
|
+
}
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public static getStringArray(
|
|
82
|
+
args: JSONObject,
|
|
83
|
+
key: string,
|
|
84
|
+
): Array<string> | undefined {
|
|
85
|
+
const value: unknown = args[key];
|
|
86
|
+
if (Array.isArray(value)) {
|
|
87
|
+
const strings: Array<string> = value.filter((item: unknown) => {
|
|
88
|
+
return typeof item === "string" && item.trim().length > 0;
|
|
89
|
+
}) as Array<string>;
|
|
90
|
+
if (strings.length > 0) {
|
|
91
|
+
return strings;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public static getNumber(
|
|
98
|
+
args: JSONObject,
|
|
99
|
+
key: string,
|
|
100
|
+
options: { defaultValue: number; min: number; max: number },
|
|
101
|
+
): number {
|
|
102
|
+
const value: unknown = args[key];
|
|
103
|
+
let parsed: number = options.defaultValue;
|
|
104
|
+
|
|
105
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
106
|
+
parsed = value;
|
|
107
|
+
} else if (typeof value === "string" && value.trim().length > 0) {
|
|
108
|
+
const fromString: number = Number(value);
|
|
109
|
+
if (Number.isFinite(fromString)) {
|
|
110
|
+
parsed = fromString;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return Math.min(options.max, Math.max(options.min, Math.floor(parsed)));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public static getBoolean(args: JSONObject, key: string): boolean | undefined {
|
|
118
|
+
const value: unknown = args[key];
|
|
119
|
+
if (typeof value === "boolean") {
|
|
120
|
+
return value;
|
|
121
|
+
}
|
|
122
|
+
if (value === "true") {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
if (value === "false") {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
public static getObjectID(
|
|
132
|
+
args: JSONObject,
|
|
133
|
+
key: string,
|
|
134
|
+
): ObjectID | undefined {
|
|
135
|
+
const value: string | undefined = this.getString(args, key);
|
|
136
|
+
if (!value) {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
return new ObjectID(value);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
* Combines the caller's optional serviceId filter with the user's owned-scope
|
|
144
|
+
* access (from ModelPermission.getAccessibleServiceIdsForAnalyticsModel) into
|
|
145
|
+
* the `serviceIds` filter to hand an aggregation service.
|
|
146
|
+
*
|
|
147
|
+
* `allowed === null` means the user has project-wide access: pass only the
|
|
148
|
+
* caller's own filter (or undefined for no filter). Otherwise the user is
|
|
149
|
+
* label/owned-restricted: intersect with any requested service and NEVER
|
|
150
|
+
* return undefined or an empty array — an empty result is forced to a
|
|
151
|
+
* no-match sentinel, because the aggregation services treat a missing/empty
|
|
152
|
+
* serviceIds as "no filter" (which would leak the whole project).
|
|
153
|
+
*/
|
|
154
|
+
public static scopeServiceIds(
|
|
155
|
+
allowed: Array<ObjectID> | null,
|
|
156
|
+
requested: ObjectID | undefined,
|
|
157
|
+
): Array<ObjectID> | undefined {
|
|
158
|
+
if (allowed === null) {
|
|
159
|
+
return requested ? [requested] : undefined;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
let effective: Array<ObjectID> = allowed;
|
|
163
|
+
if (requested) {
|
|
164
|
+
effective = allowed.filter((id: ObjectID) => {
|
|
165
|
+
return id.toString() === requested.toString();
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (effective.length === 0) {
|
|
170
|
+
return [ObjectID.getZeroObjectID()];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return effective;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/*
|
|
177
|
+
* Time range for a tool call: explicit ISO startTime/endTime arguments,
|
|
178
|
+
* clamped to a maximum window, defaulting to the last hour.
|
|
179
|
+
*/
|
|
180
|
+
public static getTimeRange(
|
|
181
|
+
args: JSONObject,
|
|
182
|
+
options?: { defaultHours?: number; maxDays?: number },
|
|
183
|
+
): { startTime: Date; endTime: Date } {
|
|
184
|
+
const defaultHours: number = options?.defaultHours ?? 1;
|
|
185
|
+
const maxDays: number = options?.maxDays ?? 30;
|
|
186
|
+
|
|
187
|
+
const endTimeString: string | undefined = this.getString(args, "endTime");
|
|
188
|
+
const startTimeString: string | undefined = this.getString(
|
|
189
|
+
args,
|
|
190
|
+
"startTime",
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
/*
|
|
194
|
+
* Reject unparseable timestamps instead of silently falling back to the
|
|
195
|
+
* default window — a silent fallback answers a different question than the
|
|
196
|
+
* one asked. Throwing lets the model see the error and retry with a valid
|
|
197
|
+
* ISO 8601 value.
|
|
198
|
+
*/
|
|
199
|
+
let endTime: Date = OneUptimeDate.getCurrentDate();
|
|
200
|
+
if (endTimeString) {
|
|
201
|
+
const parsed: Date = new Date(endTimeString);
|
|
202
|
+
if (isNaN(parsed.getTime())) {
|
|
203
|
+
throw new BadDataException(
|
|
204
|
+
`endTime "${endTimeString}" is not a valid ISO 8601 timestamp (e.g. 2024-01-31T14:00:00Z).`,
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
endTime = parsed;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
let startTime: Date = OneUptimeDate.addRemoveHours(
|
|
211
|
+
endTime,
|
|
212
|
+
-1 * defaultHours,
|
|
213
|
+
);
|
|
214
|
+
if (startTimeString) {
|
|
215
|
+
const parsed: Date = new Date(startTimeString);
|
|
216
|
+
if (isNaN(parsed.getTime())) {
|
|
217
|
+
throw new BadDataException(
|
|
218
|
+
`startTime "${startTimeString}" is not a valid ISO 8601 timestamp (e.g. 2024-01-31T13:00:00Z).`,
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
startTime = parsed;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (startTime.getTime() >= endTime.getTime()) {
|
|
225
|
+
throw new BadDataException("startTime must be before endTime.");
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const maxWindowMs: number = maxDays * 24 * 60 * 60 * 1000;
|
|
229
|
+
if (endTime.getTime() - startTime.getTime() > maxWindowMs) {
|
|
230
|
+
startTime = new Date(endTime.getTime() - maxWindowMs);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return { startTime, endTime };
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Shared JSON-Schema fragments for tool input schemas.
|
|
238
|
+
export const TimeRangeSchemaProperties: JSONObject = {
|
|
239
|
+
startTime: {
|
|
240
|
+
type: "string",
|
|
241
|
+
description:
|
|
242
|
+
"Start of the time range as an ISO 8601 timestamp. Defaults to one hour before endTime.",
|
|
243
|
+
},
|
|
244
|
+
endTime: {
|
|
245
|
+
type: "string",
|
|
246
|
+
description:
|
|
247
|
+
"End of the time range as an ISO 8601 timestamp. Defaults to now.",
|
|
248
|
+
},
|
|
249
|
+
};
|
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import Span from "../../../../Models/AnalyticsModels/Span";
|
|
2
|
+
import DatabaseRequestType from "../../../Types/BaseDatabase/DatabaseRequestType";
|
|
3
|
+
import ModelPermission from "../../../Types/AnalyticsDatabase/ModelPermission";
|
|
4
|
+
import SortOrder from "../../../../Types/BaseDatabase/SortOrder";
|
|
5
|
+
import BadDataException from "../../../../Types/Exception/BadDataException";
|
|
6
|
+
import { JSONObject } from "../../../../Types/JSON";
|
|
7
|
+
import ObjectID from "../../../../Types/ObjectID";
|
|
8
|
+
import Permission from "../../../../Types/Permission";
|
|
9
|
+
import {
|
|
10
|
+
AIChatCitationTargetType,
|
|
11
|
+
AIChatWidgetSpan,
|
|
12
|
+
} from "../../../../Types/AI/AIChatTypes";
|
|
13
|
+
import SpanService from "../../../Services/SpanService";
|
|
14
|
+
import TraceAggregationService, {
|
|
15
|
+
TraceAnalyticsTableRow,
|
|
16
|
+
} from "../../../Services/TraceAggregationService";
|
|
17
|
+
import ToolResultSerializer, { SerializedResult } from "./Serializer";
|
|
18
|
+
import WidgetBuilder from "./WidgetBuilder";
|
|
19
|
+
import {
|
|
20
|
+
ObservabilityTool,
|
|
21
|
+
TimeRangeSchemaProperties,
|
|
22
|
+
ToolArgs,
|
|
23
|
+
ToolContext,
|
|
24
|
+
ToolExecutionResult,
|
|
25
|
+
} from "./ToolTypes";
|
|
26
|
+
|
|
27
|
+
const TRACE_READ_PERMISSIONS: Array<Permission> = [
|
|
28
|
+
Permission.ProjectOwner,
|
|
29
|
+
Permission.ProjectAdmin,
|
|
30
|
+
Permission.ProjectMember,
|
|
31
|
+
Permission.Viewer,
|
|
32
|
+
Permission.TelemetryAdmin,
|
|
33
|
+
Permission.TelemetryMember,
|
|
34
|
+
Permission.TelemetryViewer,
|
|
35
|
+
Permission.ReadTelemetryServiceTraces,
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const VALID_METRICS: Array<string> = [
|
|
39
|
+
"count",
|
|
40
|
+
"errorCount",
|
|
41
|
+
"avgDuration",
|
|
42
|
+
"minDuration",
|
|
43
|
+
"maxDuration",
|
|
44
|
+
"p50Duration",
|
|
45
|
+
"p90Duration",
|
|
46
|
+
"p95Duration",
|
|
47
|
+
"p99Duration",
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const VALID_GROUP_BY: Array<string> = [
|
|
51
|
+
"name",
|
|
52
|
+
"primaryEntityId",
|
|
53
|
+
"kind",
|
|
54
|
+
"statusCode",
|
|
55
|
+
"isRootSpan",
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
/*
|
|
59
|
+
* Upper bound on spans fetched for a single trace waterfall. High enough for
|
|
60
|
+
* almost every real trace; when a trace exceeds it we say so explicitly rather
|
|
61
|
+
* than silently dropping spans (which also orphans their children into fake
|
|
62
|
+
* roots).
|
|
63
|
+
*/
|
|
64
|
+
const MAX_TRACE_SPANS: number = 500;
|
|
65
|
+
|
|
66
|
+
export const QueryTracesTool: ObservabilityTool = {
|
|
67
|
+
name: "query_traces",
|
|
68
|
+
description:
|
|
69
|
+
"Analyze spans/traces: latency profile (count, errorCount, avg and p50/p90/p95/p99 durations in ms) grouped by one dimension such as span name or service. Use this to answer 'why is X slow', 'error rate by operation' or 'slowest endpoints'. Then drill into a single trace with get_trace.",
|
|
70
|
+
inputSchema: {
|
|
71
|
+
type: "object",
|
|
72
|
+
properties: {
|
|
73
|
+
...TimeRangeSchemaProperties,
|
|
74
|
+
groupBy: {
|
|
75
|
+
type: "string",
|
|
76
|
+
enum: ["name", "primaryEntityId", "kind", "statusCode", "isRootSpan"],
|
|
77
|
+
description:
|
|
78
|
+
"Dimension to group by (default name = span/operation name; primaryEntityId = service).",
|
|
79
|
+
},
|
|
80
|
+
metric: {
|
|
81
|
+
type: "string",
|
|
82
|
+
enum: [
|
|
83
|
+
"count",
|
|
84
|
+
"errorCount",
|
|
85
|
+
"avgDuration",
|
|
86
|
+
"minDuration",
|
|
87
|
+
"maxDuration",
|
|
88
|
+
"p50Duration",
|
|
89
|
+
"p90Duration",
|
|
90
|
+
"p95Duration",
|
|
91
|
+
"p99Duration",
|
|
92
|
+
],
|
|
93
|
+
description:
|
|
94
|
+
"Metric used to rank the groups (default p95Duration). The full latency profile is always returned per group.",
|
|
95
|
+
},
|
|
96
|
+
nameSearchText: {
|
|
97
|
+
type: "string",
|
|
98
|
+
description: "Only spans whose name contains this text.",
|
|
99
|
+
},
|
|
100
|
+
serviceId: {
|
|
101
|
+
type: "string",
|
|
102
|
+
description: "Only spans from this telemetry service.",
|
|
103
|
+
},
|
|
104
|
+
hasException: {
|
|
105
|
+
type: "boolean",
|
|
106
|
+
description: "Only spans that recorded an exception.",
|
|
107
|
+
},
|
|
108
|
+
rootOnly: {
|
|
109
|
+
type: "boolean",
|
|
110
|
+
description: "Only root spans (whole-request latency).",
|
|
111
|
+
},
|
|
112
|
+
limit: {
|
|
113
|
+
type: "number",
|
|
114
|
+
description: "Maximum groups to return (default 10, max 25).",
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
requiredPermissions: TRACE_READ_PERMISSIONS,
|
|
119
|
+
execute: async (
|
|
120
|
+
args: JSONObject,
|
|
121
|
+
ctx: ToolContext,
|
|
122
|
+
): Promise<ToolExecutionResult> => {
|
|
123
|
+
const { startTime, endTime } = ToolArgs.getTimeRange(args, {
|
|
124
|
+
defaultHours: 24,
|
|
125
|
+
maxDays: 30,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const metric: string = ToolArgs.getString(args, "metric") || "p95Duration";
|
|
129
|
+
if (!VALID_METRICS.includes(metric)) {
|
|
130
|
+
throw new BadDataException(`Invalid metric: ${metric}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const groupBy: string = ToolArgs.getString(args, "groupBy") || "name";
|
|
134
|
+
if (!VALID_GROUP_BY.includes(groupBy)) {
|
|
135
|
+
throw new BadDataException(`Invalid groupBy: ${groupBy}`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const limit: number = ToolArgs.getNumber(args, "limit", {
|
|
139
|
+
defaultValue: 10,
|
|
140
|
+
min: 1,
|
|
141
|
+
max: 25,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const serviceId: ObjectID | undefined = ToolArgs.getObjectID(
|
|
145
|
+
args,
|
|
146
|
+
"serviceId",
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
const windowMinutes: number =
|
|
150
|
+
(endTime.getTime() - startTime.getTime()) / (60 * 1000);
|
|
151
|
+
|
|
152
|
+
/*
|
|
153
|
+
* getAnalyticsTable builds raw aggregation SQL and skips the model layer's
|
|
154
|
+
* owned-scope filter, so a label-restricted user would otherwise see
|
|
155
|
+
* project-wide trace analytics. Constrain to the services this user may
|
|
156
|
+
* read (spans are owned through Service, same as logs).
|
|
157
|
+
*/
|
|
158
|
+
const accessibleServiceIds: Array<ObjectID> | null =
|
|
159
|
+
await ModelPermission.getAccessibleServiceIdsForAnalyticsModel(
|
|
160
|
+
Span,
|
|
161
|
+
ctx.props,
|
|
162
|
+
DatabaseRequestType.Read,
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const tableRows: Array<TraceAnalyticsTableRow> =
|
|
166
|
+
await TraceAggregationService.getAnalyticsTable({
|
|
167
|
+
projectId: ctx.projectId,
|
|
168
|
+
startTime: startTime,
|
|
169
|
+
endTime: endTime,
|
|
170
|
+
bucketSizeInMinutes: Math.max(1, Math.round(windowMinutes / 60)),
|
|
171
|
+
chartType: "table",
|
|
172
|
+
metric: metric as never,
|
|
173
|
+
groupBy: [groupBy],
|
|
174
|
+
limit: limit,
|
|
175
|
+
nameSearchText: ToolArgs.getString(args, "nameSearchText"),
|
|
176
|
+
serviceIds: ToolArgs.scopeServiceIds(accessibleServiceIds, serviceId),
|
|
177
|
+
hasException: ToolArgs.getBoolean(args, "hasException"),
|
|
178
|
+
rootOnly: ToolArgs.getBoolean(args, "rootOnly"),
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const rows: Array<JSONObject> = tableRows.map(
|
|
182
|
+
(row: TraceAnalyticsTableRow) => {
|
|
183
|
+
return {
|
|
184
|
+
[groupBy]: Object.values(row.groupValues).join(" / "),
|
|
185
|
+
count: row.count,
|
|
186
|
+
errorCount: row.errorCount,
|
|
187
|
+
avgMs: Math.round(row.avgDurationMs * 100) / 100,
|
|
188
|
+
p50Ms: Math.round(row.p50DurationMs * 100) / 100,
|
|
189
|
+
p90Ms: Math.round(row.p90DurationMs * 100) / 100,
|
|
190
|
+
p95Ms: Math.round(row.p95DurationMs * 100) / 100,
|
|
191
|
+
p99Ms: Math.round(row.p99DurationMs * 100) / 100,
|
|
192
|
+
};
|
|
193
|
+
},
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
const serialized: SerializedResult =
|
|
197
|
+
ToolResultSerializer.serializeRows(rows);
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
dataForLlm: serialized.text,
|
|
201
|
+
rowCount: serialized.rowCount,
|
|
202
|
+
citationLabel: `Trace analytics by ${groupBy} (${metric}), ${startTime.toISOString()} – ${endTime.toISOString()}`,
|
|
203
|
+
citationTarget: {
|
|
204
|
+
type: AIChatCitationTargetType.Traces,
|
|
205
|
+
},
|
|
206
|
+
redactionCount: serialized.redactionCount,
|
|
207
|
+
isTruncated: serialized.isTruncated,
|
|
208
|
+
widget:
|
|
209
|
+
rows.length > 0
|
|
210
|
+
? WidgetBuilder.table({
|
|
211
|
+
title: `Trace analytics by ${groupBy}`,
|
|
212
|
+
description: `Ranked by ${metric} · ${startTime.toISOString()} – ${endTime.toISOString()}`,
|
|
213
|
+
columns: [
|
|
214
|
+
{ key: groupBy, title: groupBy, type: "text" },
|
|
215
|
+
{ key: "count", title: "Count", type: "number" },
|
|
216
|
+
{ key: "errorCount", title: "Errors", type: "number" },
|
|
217
|
+
{ key: "avgMs", title: "Avg (ms)", type: "number" },
|
|
218
|
+
{ key: "p90Ms", title: "p90 (ms)", type: "number" },
|
|
219
|
+
{ key: "p95Ms", title: "p95 (ms)", type: "number" },
|
|
220
|
+
{ key: "p99Ms", title: "p99 (ms)", type: "number" },
|
|
221
|
+
],
|
|
222
|
+
rows: rows,
|
|
223
|
+
link: { type: AIChatCitationTargetType.Traces },
|
|
224
|
+
})
|
|
225
|
+
: undefined,
|
|
226
|
+
};
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
interface SpanTreeNode {
|
|
231
|
+
span: Span;
|
|
232
|
+
children: Array<SpanTreeNode>;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export const GetTraceTool: ObservabilityTool = {
|
|
236
|
+
name: "get_trace",
|
|
237
|
+
description:
|
|
238
|
+
"Get the span tree (waterfall) of one trace by traceId: every span with its duration, status and whether it recorded an exception. Use after query_traces or search_logs surfaces an interesting traceId.",
|
|
239
|
+
inputSchema: {
|
|
240
|
+
type: "object",
|
|
241
|
+
properties: {
|
|
242
|
+
traceId: {
|
|
243
|
+
type: "string",
|
|
244
|
+
description: "The trace ID (required).",
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
required: ["traceId"],
|
|
248
|
+
},
|
|
249
|
+
requiredPermissions: TRACE_READ_PERMISSIONS,
|
|
250
|
+
execute: async (
|
|
251
|
+
args: JSONObject,
|
|
252
|
+
ctx: ToolContext,
|
|
253
|
+
): Promise<ToolExecutionResult> => {
|
|
254
|
+
const traceId: string | undefined = ToolArgs.getString(args, "traceId");
|
|
255
|
+
|
|
256
|
+
if (!traceId) {
|
|
257
|
+
throw new BadDataException("traceId is required.");
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const spans: Array<Span> = await SpanService.findBy({
|
|
261
|
+
query: {
|
|
262
|
+
traceId: traceId,
|
|
263
|
+
} as never,
|
|
264
|
+
select: {
|
|
265
|
+
spanId: true,
|
|
266
|
+
parentSpanId: true,
|
|
267
|
+
name: true,
|
|
268
|
+
startTimeUnixNano: true,
|
|
269
|
+
durationUnixNano: true,
|
|
270
|
+
statusCode: true,
|
|
271
|
+
kind: true,
|
|
272
|
+
} as never,
|
|
273
|
+
sort: {
|
|
274
|
+
startTimeUnixNano: SortOrder.Ascending,
|
|
275
|
+
} as never,
|
|
276
|
+
limit: MAX_TRACE_SPANS,
|
|
277
|
+
skip: 0,
|
|
278
|
+
props: ctx.props,
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
const isSpanLimitHit: boolean = spans.length >= MAX_TRACE_SPANS;
|
|
282
|
+
|
|
283
|
+
// Build the tree.
|
|
284
|
+
const nodesBySpanId: Map<string, SpanTreeNode> = new Map();
|
|
285
|
+
const roots: Array<SpanTreeNode> = [];
|
|
286
|
+
|
|
287
|
+
for (const span of spans) {
|
|
288
|
+
nodesBySpanId.set(span.spanId?.toString() || "", {
|
|
289
|
+
span,
|
|
290
|
+
children: [],
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
for (const node of nodesBySpanId.values()) {
|
|
295
|
+
const parentId: string = node.span.parentSpanId?.toString() || "";
|
|
296
|
+
const parent: SpanTreeNode | undefined = nodesBySpanId.get(parentId);
|
|
297
|
+
if (parent && parent !== node) {
|
|
298
|
+
parent.children.push(node);
|
|
299
|
+
} else {
|
|
300
|
+
roots.push(node);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const lines: Array<string> = [];
|
|
305
|
+
|
|
306
|
+
const renderNode: (node: SpanTreeNode, depth: number) => void = (
|
|
307
|
+
node: SpanTreeNode,
|
|
308
|
+
depth: number,
|
|
309
|
+
): void => {
|
|
310
|
+
const durationMs: number =
|
|
311
|
+
Math.round((Number(node.span.durationUnixNano) / 1_000_000) * 100) /
|
|
312
|
+
100;
|
|
313
|
+
const status: string =
|
|
314
|
+
Number(node.span.statusCode) === 2 ? " [ERROR]" : "";
|
|
315
|
+
lines.push(
|
|
316
|
+
`${" ".repeat(depth)}- ${node.span.name} (${durationMs}ms)${status}`,
|
|
317
|
+
);
|
|
318
|
+
for (const child of node.children) {
|
|
319
|
+
renderNode(child, depth + 1);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
for (const root of roots) {
|
|
324
|
+
renderNode(root, 0);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (isSpanLimitHit) {
|
|
328
|
+
lines.push(
|
|
329
|
+
`… trace truncated at ${MAX_TRACE_SPANS} spans; deeper spans are omitted and some shown here may appear as roots because their parent was cut off.`,
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const serialized: SerializedResult = ToolResultSerializer.serializeText(
|
|
334
|
+
lines.join("\n"),
|
|
335
|
+
spans.length,
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
/*
|
|
339
|
+
* Build the waterfall widget: each span's start is expressed as an offset in
|
|
340
|
+
* ms from the earliest span start (the trace start), so the renderer can lay
|
|
341
|
+
* out proportional bars without any wall-clock math.
|
|
342
|
+
*/
|
|
343
|
+
let traceStartNano: number | undefined = undefined;
|
|
344
|
+
let traceEndNano: number = 0;
|
|
345
|
+
for (const span of spans) {
|
|
346
|
+
const start: number = Number(span.startTimeUnixNano);
|
|
347
|
+
const end: number = start + Number(span.durationUnixNano);
|
|
348
|
+
if (traceStartNano === undefined || start < traceStartNano) {
|
|
349
|
+
traceStartNano = start;
|
|
350
|
+
}
|
|
351
|
+
if (end > traceEndNano) {
|
|
352
|
+
traceEndNano = end;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const nanoToMs: (nano: number) => number = (nano: number): number => {
|
|
357
|
+
return Math.round((nano / 1_000_000) * 100) / 100;
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
const widgetSpans: Array<AIChatWidgetSpan> = spans.map((span: Span) => {
|
|
361
|
+
const start: number = Number(span.startTimeUnixNano);
|
|
362
|
+
return {
|
|
363
|
+
spanId: span.spanId?.toString() || "",
|
|
364
|
+
parentSpanId: span.parentSpanId?.toString() || undefined,
|
|
365
|
+
name: span.name || "(unnamed span)",
|
|
366
|
+
startOffsetMs: nanoToMs(start - (traceStartNano ?? start)),
|
|
367
|
+
durationMs: nanoToMs(Number(span.durationUnixNano)),
|
|
368
|
+
isError: Number(span.statusCode) === 2,
|
|
369
|
+
};
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
const totalDurationMs: number =
|
|
373
|
+
traceStartNano !== undefined
|
|
374
|
+
? nanoToMs(traceEndNano - traceStartNano)
|
|
375
|
+
: 0;
|
|
376
|
+
|
|
377
|
+
return {
|
|
378
|
+
dataForLlm: serialized.text,
|
|
379
|
+
rowCount: serialized.rowCount,
|
|
380
|
+
citationLabel: `Trace ${traceId} (${spans.length}${isSpanLimitHit ? "+" : ""} spans)`,
|
|
381
|
+
citationTarget: {
|
|
382
|
+
type: AIChatCitationTargetType.TraceView,
|
|
383
|
+
params: { traceId: traceId },
|
|
384
|
+
},
|
|
385
|
+
redactionCount: serialized.redactionCount,
|
|
386
|
+
isTruncated: serialized.isTruncated || isSpanLimitHit,
|
|
387
|
+
widget:
|
|
388
|
+
widgetSpans.length > 0
|
|
389
|
+
? WidgetBuilder.traceWaterfall({
|
|
390
|
+
title: `Trace waterfall (${spans.length}${isSpanLimitHit ? "+" : ""} spans)`,
|
|
391
|
+
description: `${totalDurationMs} ms total`,
|
|
392
|
+
spans: widgetSpans,
|
|
393
|
+
totalDurationMs: totalDurationMs,
|
|
394
|
+
link: {
|
|
395
|
+
type: AIChatCitationTargetType.TraceView,
|
|
396
|
+
params: { traceId: traceId },
|
|
397
|
+
},
|
|
398
|
+
})
|
|
399
|
+
: undefined,
|
|
400
|
+
};
|
|
401
|
+
},
|
|
402
|
+
};
|