@oneuptime/common 14.0.8 → 14.0.10
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/AutoRemediationSuggestion.ts +60 -0
- package/Models/DatabaseModels/CephCluster.ts +213 -0
- package/Models/DatabaseModels/DatabaseServer.ts +213 -0
- package/Models/DatabaseModels/DockerHost.ts +213 -0
- package/Models/DatabaseModels/DockerSwarmCluster.ts +213 -0
- package/Models/DatabaseModels/GlobalConfig.ts +1 -1
- package/Models/DatabaseModels/Host.ts +213 -0
- package/Models/DatabaseModels/Index.ts +4 -0
- package/Models/DatabaseModels/KubernetesAiAgent.ts +364 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +3 -3
- package/Models/DatabaseModels/PodmanHost.ts +213 -0
- package/Models/DatabaseModels/Project.ts +55 -5
- package/Models/DatabaseModels/ProxmoxCluster.ts +213 -0
- package/Models/DatabaseModels/ProxmoxResource.ts +49 -1
- package/Models/DatabaseModels/ResourceAiAgent.ts +419 -0
- package/Models/DatabaseModels/RunnerJob.ts +219 -0
- package/Models/DatabaseModels/TeamComplianceSetting.ts +143 -2
- package/Models/DatabaseModels/VMwareVCenter.ts +213 -0
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +17 -0
- package/Server/API/AIChatAPI.ts +6 -3
- package/Server/API/AIInvestigationAPI.ts +17 -10
- package/Server/API/AutoRemediationAPI.ts +598 -25
- package/Server/API/KubernetesClusterAiAccessAPI.ts +623 -21
- package/Server/API/MicrosoftTeamsAPI.ts +93 -14
- package/Server/API/ProxmoxResourceAPI.ts +244 -14
- package/Server/API/ResourceAiAccessAPI.ts +1669 -0
- package/Server/Infrastructure/GlobalCache.ts +32 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.ts +99 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.ts +137 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.ts +42 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.ts +423 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
- package/Server/Infrastructure/Semaphore.ts +22 -0
- package/Server/Middleware/TelemetryIngest.ts +51 -18
- package/Server/Services/AIService.ts +70 -1
- package/Server/Services/AlertService.ts +352 -11
- package/Server/Services/AlertSeverityService.ts +65 -15
- package/Server/Services/AnalyticsDatabaseService.ts +45 -1
- package/Server/Services/AutoRemediationRuleEngineService.ts +940 -112
- package/Server/Services/AutoRemediationRuleService.ts +1 -1
- package/Server/Services/CephClusterService.ts +109 -1
- package/Server/Services/DatabaseServerService.ts +116 -1
- package/Server/Services/DockerHostService.ts +109 -1
- package/Server/Services/DockerSwarmClusterService.ts +113 -1
- package/Server/Services/HostService.ts +126 -4
- package/Server/Services/IncidentService.ts +280 -104
- package/Server/Services/IncidentSeverityService.ts +66 -15
- package/Server/Services/KubernetesAiAgentJobService.ts +185 -0
- package/Server/Services/KubernetesAiAgentService.ts +1634 -0
- package/Server/Services/KubernetesClusterAiAccessService.ts +1118 -451
- package/Server/Services/KubernetesClusterService.ts +129 -21
- package/Server/Services/MetricRecordingRuleService.ts +47 -0
- package/Server/Services/PodmanHostService.ts +109 -1
- package/Server/Services/ProjectService.ts +32 -0
- package/Server/Services/ProxmoxClusterService.ts +110 -1
- package/Server/Services/ProxmoxResourceService.ts +322 -5
- package/Server/Services/ResourceAiAccessService.ts +1439 -0
- package/Server/Services/ResourceAiAgentJobService.ts +202 -0
- package/Server/Services/ResourceAiAgentService.ts +2432 -0
- package/Server/Services/RunnerJobService.ts +852 -108
- package/Server/Services/RunnerService.ts +1 -1
- package/Server/Services/ScheduledMaintenanceService.ts +737 -1
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +414 -56
- package/Server/Services/TeamComplianceSettingService.ts +1125 -9
- package/Server/Services/TelemetryUsageBillingService.ts +28 -0
- package/Server/Services/TraceRecordingRuleService.ts +33 -0
- package/Server/Services/VMwareVCenterService.ts +110 -1
- package/Server/Utils/AI/ClusterAccess/ClusterAccessContext.ts +67 -9
- package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +39 -10
- package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +14 -3
- package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +1475 -51
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +1000 -43
- package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +25 -1
- package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +577 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAccessContext.ts +271 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.ts +45 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.ts +964 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.ts +333 -0
- package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +873 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +120 -7
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +72 -5
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +72 -5
- package/Server/Utils/AI/SRE/IncidentPostmortemRunner.ts +40 -8
- package/Server/Utils/AI/SRE/InvestigationEligibility.ts +13 -2
- package/Server/Utils/AI/SRE/InvestigationGrader.ts +1 -1
- package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +402 -14
- package/Server/Utils/AutoRemediation/RemediationVerifier.ts +35 -2
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +9 -1
- package/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.ts +920 -0
- package/Server/Utils/SessionReplay/SessionReplayUsage.ts +84 -6
- package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +133 -7
- package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +58 -4
- package/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.ts +447 -0
- package/Server/Utils/Telemetry/ProxmoxNativePush.ts +903 -0
- package/Server/Utils/Telemetry/TelemetryEntity.ts +87 -27
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +35 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +33 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +21 -1
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +298 -224
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +35 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +389 -175
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +1073 -213
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.ts +163 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.ts +396 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.ts +418 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.ts +152 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.ts +251 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.ts +214 -0
- package/Tests/App/AdminDashboard/RowActionPlacementOverrides.test.tsx +278 -0
- package/Tests/App/Dashboard/AIChatChartWidgetZoom.test.tsx +738 -0
- package/Tests/App/Dashboard/AIFeaturesSettingsPointers.test.tsx +147 -0
- package/Tests/App/Dashboard/AIInsightsKubernetesClusterPage.test.tsx +1523 -0
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +463 -3
- package/Tests/App/Dashboard/AffectedResourcesPickerDropdownPlacement.test.tsx +958 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerFocusLeave.test.tsx +595 -0
- package/Tests/App/Dashboard/AskAiAvailability.test.ts +20 -3
- package/Tests/App/Dashboard/AskAiDisabled.test.tsx +8 -3
- package/Tests/App/Dashboard/CephRateChartReload.test.tsx +1456 -0
- package/Tests/App/Dashboard/CephTimeRangeZoom.test.tsx +1229 -0
- package/Tests/App/Dashboard/ChartCardTimeRangeZoom.test.tsx +151 -0
- package/Tests/App/Dashboard/ChartCardZoomAffordances.test.tsx +257 -0
- package/Tests/App/Dashboard/ChartRefetchFrame.test.tsx +141 -0
- package/Tests/App/Dashboard/ChartZoomHarness.tsx +249 -0
- package/Tests/App/Dashboard/ChartZoomStandIn.tsx +131 -0
- package/Tests/App/Dashboard/CloudServerlessSlowLoads.test.tsx +628 -0
- package/Tests/App/Dashboard/CloudServerlessTimeRangeZoom.test.tsx +607 -0
- package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +184 -19
- package/Tests/App/Dashboard/CompanionMetricsTabZoom.test.tsx +632 -0
- package/Tests/App/Dashboard/ContainerChartZoomStandIn.tsx +195 -0
- package/Tests/App/Dashboard/ContainerHostOverviewSlowLoads.test.tsx +542 -0
- package/Tests/App/Dashboard/ContainerHostOverviewTimeRangeZoom.test.tsx +848 -0
- package/Tests/App/Dashboard/ContainerMetricsTimeRangeZoom.test.tsx +561 -0
- package/Tests/App/Dashboard/DashboardBoardWideZoomShell.test.tsx +1147 -0
- package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +3 -2
- package/Tests/App/Dashboard/DashboardHistogramWidgetDragCursor.test.tsx +399 -0
- package/Tests/App/Dashboard/DashboardHistogramWidgetZoom.test.tsx +985 -0
- package/Tests/App/Dashboard/DashboardHistogramWidgetZoomHint.test.tsx +803 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +1 -0
- package/Tests/App/Dashboard/DashboardSettingsPreviewZoom.test.tsx +679 -0
- package/Tests/App/Dashboard/DashboardSloAndDataSourceChartZoom.test.tsx +881 -0
- package/Tests/App/Dashboard/DashboardTraceStatusWidgets.test.tsx +878 -0
- package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +18 -6
- package/Tests/App/Dashboard/DatabaseMetricChartModalTimeRangeZoom.test.tsx +442 -0
- package/Tests/App/Dashboard/DatabaseOverviewTimeRangeZoom.test.tsx +831 -0
- package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +43 -0
- package/Tests/App/Dashboard/DockerSwarmInsightsTimeRangeZoom.test.tsx +524 -0
- package/Tests/App/Dashboard/DockerSwarmRateChartRefresh.test.tsx +259 -0
- package/Tests/App/Dashboard/EdgeDetailPanelHistory.test.tsx +763 -0
- package/Tests/App/Dashboard/EdgeDetailPanelTimeRangeZoom.test.tsx +547 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsCases.tsx +565 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsKathmandu.test.tsx +73 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsKolkata.test.tsx +74 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsNewYork.test.tsx +72 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsUtc.test.tsx +72 -0
- package/Tests/App/Dashboard/EmbeddedMetricCardRefresh.test.tsx +310 -0
- package/Tests/App/Dashboard/EmbeddedMetricCardTimeRangeZoom.test.tsx +536 -0
- package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +3 -1
- package/Tests/App/Dashboard/EscalationRuleRowActions.test.tsx +660 -0
- package/Tests/App/Dashboard/EventNotes.test.tsx +2 -2
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +587 -13
- package/Tests/App/Dashboard/EventOverviewSnapshotExplorerZoom.test.tsx +1139 -0
- package/Tests/App/Dashboard/EventOverviewSnapshotZoomAcrossTabs.test.tsx +1057 -0
- package/Tests/App/Dashboard/EventOverviewTelemetrySnapshotZoom.test.tsx +757 -0
- package/Tests/App/Dashboard/ExceptionOccurrenceTrendZoom.test.tsx +675 -0
- package/Tests/App/Dashboard/ExceptionOccurrencesZoomSurvivesViewSwitch.test.tsx +405 -0
- package/Tests/App/Dashboard/ExceptionSignalPages.test.tsx +67 -3
- package/Tests/App/Dashboard/ExceptionTablesSpanStatus.test.tsx +515 -0
- package/Tests/App/Dashboard/ExplorerOwnZoomRegression.test.tsx +739 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisCases.tsx +461 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisKathmandu.test.tsx +25 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisKolkata.test.tsx +25 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisNewYork.test.tsx +25 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisUtc.test.tsx +24 -0
- package/Tests/App/Dashboard/FlowTopTalkersZoomRefetch.test.tsx +722 -0
- package/Tests/App/Dashboard/FlowViewportGuard.test.tsx +2526 -0
- package/Tests/App/Dashboard/HostPagesSlowLoads.test.tsx +872 -0
- package/Tests/App/Dashboard/HostPagesTimeRangeZoom.test.tsx +1208 -0
- package/Tests/App/Dashboard/IncidentRootCauseTimeRangeZoom.test.tsx +358 -0
- package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +100 -9
- package/Tests/App/Dashboard/InfrastructureMetricsTabTimeRangeZoom.test.tsx +485 -0
- package/Tests/App/Dashboard/InvestigationDrawerCompanionZoom.test.tsx +655 -0
- package/Tests/App/Dashboard/InvestigationDrawerZoom.test.tsx +830 -0
- package/Tests/App/Dashboard/InvestigationInfrastructureTools.test.tsx +506 -0
- package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +338 -2
- package/Tests/App/Dashboard/InvoicesPayInvoice.test.tsx +454 -16
- package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +799 -819
- package/Tests/App/Dashboard/KubernetesClusterAiAgentOverviewCard.test.tsx +367 -0
- package/Tests/App/Dashboard/KubernetesClusterAiAgentStatus.test.ts +1202 -0
- package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +106 -0
- package/Tests/App/Dashboard/KubernetesClusterAiNavigation.test.tsx +354 -0
- package/Tests/App/Dashboard/KubernetesClusterAiPage.test.tsx +1884 -2054
- package/Tests/App/Dashboard/KubernetesClusterAiPageServerParity.test.ts +478 -179
- package/Tests/App/Dashboard/KubernetesClusterMetricTooltips.test.ts +50 -0
- package/Tests/App/Dashboard/KubernetesClusterOverviewTooltips.test.tsx +2 -1
- package/Tests/App/Dashboard/KubernetesClusterOverviewZoom.test.tsx +1217 -0
- package/Tests/App/Dashboard/KubernetesClusterPagesZoom.test.tsx +731 -0
- package/Tests/App/Dashboard/KubernetesCostsLoadRecovery.test.tsx +869 -0
- package/Tests/App/Dashboard/KubernetesCostsZoom.test.tsx +1214 -0
- package/Tests/App/Dashboard/KubernetesCostsZoomExactHours.test.tsx +692 -0
- package/Tests/App/Dashboard/KubernetesNetworkThroughputReload.test.tsx +902 -0
- package/Tests/App/Dashboard/KubernetesNetworkZoomBucketEdges.test.tsx +571 -0
- package/Tests/App/Dashboard/KubernetesOverviewZoomBucketEdges.test.tsx +697 -0
- package/Tests/App/Dashboard/KubernetesResourceMetricsTabZoom.test.tsx +633 -0
- package/Tests/App/Dashboard/LogsExplorerTimeRangeZoom.test.tsx +470 -0
- package/Tests/App/Dashboard/LogsInsightsTimeRangeZoom.test.tsx +948 -0
- package/Tests/App/Dashboard/LogsViewerPinnedWindowZoom.test.tsx +486 -0
- package/Tests/App/Dashboard/MetricChartsBucketInspectorDoubleClick.test.tsx +1001 -0
- package/Tests/App/Dashboard/MetricExplorerInvestigationAutoRefresh.test.tsx +514 -0
- package/Tests/App/Dashboard/MetricExplorerSavedViewZoomRoundTrip.test.tsx +581 -0
- package/Tests/App/Dashboard/MetricExplorerTimeRangeZoom.test.tsx +1162 -0
- package/Tests/App/Dashboard/MetricMonitorPreviewZoomLabel.test.ts +72 -0
- package/Tests/App/Dashboard/MetricRowSparklineTimeRangeZoom.test.tsx +204 -0
- package/Tests/App/Dashboard/MetricViewFirstResultLands.test.tsx +408 -0
- package/Tests/App/Dashboard/MetricViewOwnZoomResetPlacement.test.tsx +952 -0
- package/Tests/App/Dashboard/MetricViewTimeRange.test.ts +139 -0
- package/Tests/App/Dashboard/MetricViewTimeRangeZoom.test.tsx +556 -0
- package/Tests/App/Dashboard/MonitorMetricsChartWrappersZoom.test.tsx +552 -0
- package/Tests/App/Dashboard/MonitorMetricsTabsTimeRangeZoom.test.tsx +740 -0
- package/Tests/App/Dashboard/MonitorOverviewChartsTimeRangeZoom.test.tsx +735 -0
- package/Tests/App/Dashboard/MonitorStepPreviewsTimeRangeZoom.test.tsx +835 -0
- package/Tests/App/Dashboard/NetworkDeviceTimeRangeZoom.test.tsx +1115 -0
- package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +186 -17
- package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +155 -46
- package/Tests/App/Dashboard/PasskeySettings.test.tsx +87 -2
- package/Tests/App/Dashboard/ProjectAISettingsPages.test.tsx +884 -0
- package/Tests/App/Dashboard/ProxmoxNodeRemove.test.tsx +621 -0
- package/Tests/App/Dashboard/ProxmoxOverviewSlowLoads.test.tsx +584 -0
- package/Tests/App/Dashboard/ProxmoxPagesTimeRangeZoom.test.tsx +823 -0
- package/Tests/App/Dashboard/ProxmoxRateChartReload.test.tsx +1253 -0
- package/Tests/App/Dashboard/PublicDashboardBoardWideZoom.test.tsx +605 -0
- package/Tests/App/Dashboard/RealRowsLineChart.tsx +250 -0
- package/Tests/App/Dashboard/RechartsHostsPlotCursor.test.tsx +513 -0
- package/Tests/App/Dashboard/RemediationSuggestionCardDescription.test.tsx +209 -0
- package/Tests/App/Dashboard/RemediationSuggestionCardResource.test.tsx +317 -0
- package/Tests/App/Dashboard/ResourceAiAccessSettingsUtil.test.ts +921 -0
- package/Tests/App/Dashboard/ResourceAiAgentInstall.test.ts +860 -0
- package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +1721 -0
- package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +1002 -0
- package/Tests/App/Dashboard/ResourceAiInsightsPage.test.tsx +931 -0
- package/Tests/App/Dashboard/ResourceAiNavigation.test.tsx +575 -0
- package/Tests/App/Dashboard/RowActionPlacementOverrides.test.tsx +865 -0
- package/Tests/App/Dashboard/RumOverviewTimeRangeZoom.test.tsx +877 -0
- package/Tests/App/Dashboard/RunbookStepTypeMaps.test.ts +38 -7
- package/Tests/App/Dashboard/RunnerKubernetesAgentForm.test.tsx +20 -4
- package/Tests/App/Dashboard/RunnerSupersededByAiAgentNote.test.tsx +296 -0
- package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +146 -36
- package/Tests/App/Dashboard/ServiceDatabaseSlowLoads.test.tsx +1166 -0
- package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +1243 -104
- package/Tests/App/Dashboard/ServiceOverviewTimeRangeZoom.test.tsx +792 -0
- package/Tests/App/Dashboard/SloBudgetBurnDownZoom.test.tsx +771 -0
- package/Tests/App/Dashboard/SloBudgetBurnDownZoomAffordances.test.tsx +380 -0
- package/Tests/App/Dashboard/SloEventMetricsBarChartZoom.test.tsx +369 -0
- package/Tests/App/Dashboard/SloHistoryChartsTimeRangeZoom.test.tsx +694 -0
- package/Tests/App/Dashboard/SloHistoryChartsZoomAffordances.test.tsx +497 -0
- package/Tests/App/Dashboard/SloMetricsTimeRangeZoom.test.tsx +541 -0
- package/Tests/App/Dashboard/SlowLoadHarness.ts +123 -0
- package/Tests/App/Dashboard/SnapshotExplorerPrimaryZoom.test.tsx +1194 -0
- package/Tests/App/Dashboard/SnapshotViewerPinnedWindow.test.tsx +620 -0
- package/Tests/App/Dashboard/TelemetrySnapshotPanelTimeRangeZoom.test.tsx +765 -0
- package/Tests/App/Dashboard/TelemetrySnapshotZoom.test.tsx +516 -0
- package/Tests/App/Dashboard/TelemetrySnapshotZoomAcrossTabs.test.tsx +827 -0
- package/Tests/App/Dashboard/TimeRangeZoomPageHarness.tsx +463 -0
- package/Tests/App/Dashboard/TraceChartEditorStatusSplit.test.tsx +543 -0
- package/Tests/App/Dashboard/TraceStatusPresentation.test.tsx +967 -0
- package/Tests/App/Dashboard/TraceTimelineMinimapZoom.test.tsx +315 -0
- package/Tests/App/Dashboard/TracesAnalyticsStatusSplit.test.tsx +778 -0
- package/Tests/App/Dashboard/TracesAnalyticsViewZoom.test.tsx +349 -0
- package/Tests/App/Dashboard/TracesExplorerTimeRangeZoom.test.tsx +551 -0
- package/Tests/App/Dashboard/TracesStatusChartAndFacet.test.tsx +687 -0
- package/Tests/App/Dashboard/TracesViewerStaleResponses.test.tsx +458 -0
- package/Tests/App/Dashboard/UptimeStripsExcludedFromZoom.test.tsx +406 -0
- package/Tests/App/Dashboard/VMwareOverviewSlowLoads.test.tsx +535 -0
- package/Tests/App/Dashboard/VMwarePagesTimeRangeZoom.test.tsx +606 -0
- package/Tests/App/Dashboard/ValueWidgetSparklineStaleHover.test.tsx +1292 -0
- package/Tests/App/Dashboard/ValueWidgetSparklineZoom.test.tsx +765 -0
- package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +98 -0
- package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +33 -1
- package/Tests/Models/DatabaseModels/KubernetesAiAgentModel.test.ts +295 -0
- package/Tests/Models/DatabaseModels/ResourceAiAccessColumns.test.ts +738 -0
- package/Tests/Models/DatabaseModels/ResourceAiAgentModel.test.ts +842 -0
- package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +347 -0
- package/Tests/Server/API/AIChatRouteAuthorization.test.ts +58 -0
- package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +1 -1
- package/Tests/Server/API/AIInvestigationAPI.test.ts +123 -45
- package/Tests/Server/API/AutoRemediationApproveClusterRound.test.ts +1329 -0
- package/Tests/Server/API/AutoRemediationApproveKubectlRecheck.test.ts +25 -2
- package/Tests/Server/API/AutoRemediationApproveResourceRound.test.ts +835 -0
- package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -0
- package/Tests/Server/API/KubernetesClusterAiAccessAPIAgent.test.ts +903 -0
- package/Tests/Server/API/MicrosoftTeamsChatsRefreshRoute.test.ts +667 -0
- package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +294 -6
- package/Tests/Server/API/ProxmoxResourceAPIRemoveNode.test.ts +1932 -0
- package/Tests/Server/API/ResourceAiAccessAPI.test.ts +2730 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +195 -0
- package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +60 -0
- package/Tests/Server/Infrastructure/Postgres/AddKubernetesAiAgentAndAiDefaultsMigration.test.ts +623 -0
- package/Tests/Server/Infrastructure/Postgres/AddKubernetesClusterAiAccessMigration.test.ts +87 -10
- package/Tests/Server/Infrastructure/Postgres/AddResourceAiAgentsMigration.test.ts +659 -0
- package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleScopeMigration.test.ts +622 -0
- package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +31 -0
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +119 -4
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +196 -2
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +123 -2
- package/Tests/Server/Services/AIServiceBalanceBlocker.test.ts +282 -0
- package/Tests/Server/Services/AlertMonitorClearWritesNull.test.ts +409 -0
- package/Tests/Server/Services/AlertMonitorEditFeed.test.ts +474 -0
- package/Tests/Server/Services/AlertMonitorEditGuard.test.ts +610 -0
- package/Tests/Server/Services/AutoRemediationClusterRuleEngine.test.ts +2 -0
- package/Tests/Server/Services/AutoRemediationResourceRuleEngine.test.ts +1279 -0
- package/Tests/Server/Services/AutoRemediationRuleCommandRunners.test.ts +2 -1
- package/Tests/Server/Services/DatabaseServerService.test.ts +55 -0
- package/Tests/Server/Services/GroupTelemetryUsageExcludeNames.test.ts +299 -0
- package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +44 -0
- package/Tests/Server/Services/IncidentAffectedMonitorsEdit.test.ts +1360 -0
- package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +3 -1
- package/Tests/Server/Services/IncidentSeverityDeletePausesComplianceRules.test.ts +488 -0
- package/Tests/Server/Services/KubernetesAiAgentJobService.test.ts +329 -0
- package/Tests/Server/Services/KubernetesAiAgentServiceHelpers.test.ts +618 -0
- package/Tests/Server/Services/KubernetesAiAgentServiceLifecycle.test.ts +1444 -0
- package/Tests/Server/Services/KubernetesAiAgentServiceRegister.test.ts +1666 -0
- package/Tests/Server/Services/KubernetesClusterAiAccessDeletedRunnerRemedy.test.ts +140 -111
- package/Tests/Server/Services/KubernetesClusterAiAccessGapNextSteps.test.ts +267 -105
- package/Tests/Server/Services/KubernetesClusterAiAccessLegacySuperseded.test.ts +440 -0
- package/Tests/Server/Services/KubernetesClusterAiAccessService.test.ts +567 -411
- package/Tests/Server/Services/KubernetesClusterAiAccessTarget.test.ts +1168 -0
- package/Tests/Server/Services/KubernetesClusterAiSettingsPermission.test.ts +410 -12
- package/Tests/Server/Services/KubernetesClusterServiceAiAccessFeed.test.ts +55 -0
- package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +45 -6
- package/Tests/Server/Services/ProjectServiceNewProjectAiDefaults.test.ts +288 -0
- package/Tests/Server/Services/ProxmoxResourcePostgres.test.ts +5633 -0
- package/Tests/Server/Services/ProxmoxResourceService.test.ts +6458 -5
- package/Tests/Server/Services/RecordingRuleReservedMetricName.test.ts +171 -0
- package/Tests/Server/Services/ResourceAiAccessChangeAuthorization.test.ts +256 -0
- package/Tests/Server/Services/ResourceAiAccessService.test.ts +1373 -0
- package/Tests/Server/Services/ResourceAiAgentJobService.test.ts +375 -0
- package/Tests/Server/Services/ResourceAiAgentServiceHelpers.test.ts +1114 -0
- package/Tests/Server/Services/ResourceAiAgentServiceLifecycle.test.ts +1050 -0
- package/Tests/Server/Services/ResourceAiAgentServiceRegister.test.ts +2251 -0
- package/Tests/Server/Services/ResourceAiSettingsCreate.test.ts +373 -0
- package/Tests/Server/Services/ResourceAiSettingsPermission.test.ts +1042 -0
- package/Tests/Server/Services/ResourceServiceDeleteCleansUpAi.test.ts +319 -0
- package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +153 -15
- package/Tests/Server/Services/RunnerJobEnqueueKubectlAiAgent.test.ts +620 -0
- package/Tests/Server/Services/RunnerJobEnqueueResourceCommand.test.ts +986 -0
- package/Tests/Server/Services/RunnerJobKubectlWriteScope.test.ts +170 -3
- package/Tests/Server/Services/RunnerJobResourceCommandLane.test.ts +211 -0
- package/Tests/Server/Services/RunnerJobResourceCommandTimeoutAndRedaction.test.ts +352 -0
- package/Tests/Server/Services/RunnerJobTimeoutReason.test.ts +72 -0
- package/Tests/Server/Services/RunnerServiceAgentName.test.ts +6 -4
- package/Tests/Server/Services/ScheduledMaintenanceAttachmentEdit.test.ts +2113 -0
- package/Tests/Server/Services/ScheduledMaintenanceMonitorRelease.test.ts +972 -0
- package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +2237 -0
- package/Tests/Server/Services/TeamComplianceSettingService.test.ts +3988 -138
- package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +218 -0
- package/Tests/Server/TestingUtils/Services/FakeRunnerJobCount.ts +145 -0
- package/Tests/Server/Utils/AI/ClusterAccessContext.test.ts +107 -1
- package/Tests/Server/Utils/AI/IncidentPostmortemRunner.test.ts +351 -0
- package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +2 -0
- package/Tests/Server/Utils/AI/InvestigationEligibility.test.ts +310 -0
- package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +453 -0
- package/Tests/Server/Utils/AI/InvestigationInfrastructureReport.test.ts +721 -0
- package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +70 -0
- package/Tests/Server/Utils/AI/KubectlJobRunnerFinishedJob.test.ts +58 -0
- package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +94 -1
- package/Tests/Server/Utils/AI/RemediationCommandToolsKubectl.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsKubectlOutcome.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsLiveCluster.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsResource.test.ts +1530 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsRunnerScope.test.ts +125 -1
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +252 -3
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerClusterMode.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerProjectGates.test.ts +240 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +1249 -0
- package/Tests/Server/Utils/AI/RemediationKubectlCopyParity.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +117 -0
- package/Tests/Server/Utils/AI/RemediationResourceCopyParity.test.ts +463 -0
- package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +722 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAccessContext.test.ts +266 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.test.ts +1220 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.test.ts +569 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +830 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutor.test.ts +2 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorResource.test.ts +717 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorUnknownRun.test.ts +2 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanVerification.test.ts +2 -0
- package/Tests/Server/Utils/AutoRemediation/RemediationVerifierResourceFollowUp.test.ts +338 -0
- package/Tests/Server/Utils/Monitor/Criteria/SessionReplayBudgetTemplateCriteria.test.ts +422 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.test.ts +1647 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayUsage.test.ts +143 -1
- package/Tests/Server/Utils/Telemetry/HostAssetAttributesFromOtlp.test.ts +68 -0
- package/Tests/Server/Utils/Telemetry/InventoryMirrorPostgres.test.ts +370 -0
- package/Tests/Server/Utils/Telemetry/NetworkDeviceInventoryAttributes.test.ts +522 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.test.ts +155 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.test.ts +8631 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxNativePush.test.ts +2852 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +367 -1
- package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +75 -3
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsAccountNotLinked.test.ts +1093 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.test.ts +1049 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.test.ts +1676 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCards.test.ts +2884 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.test.ts +2490 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmit.test.ts +2293 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmitServerTimezone.test.ts +386 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.test.ts +1477 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.test.ts +1967 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsStripHtmlTags.test.ts +92 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsSubmittedFormRemoval.test.ts +1819 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.test.ts +1033 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezoneServerZone.test.ts +610 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsBotMessageHandling.test.ts +2610 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +25 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsCreateCommandsEndToEnd.test.ts +4672 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNames.test.ts +3119 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNamesPostgres.test.ts +1721 -0
- package/Tests/Server/Utils/Workspace/WorkspaceCreateProjectReferences.test.ts +190 -65
- package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +10 -4
- package/Tests/Types/AutoRemediation/AiRemediationCommandPlanResourceCommand.test.ts +305 -0
- package/Tests/Types/Kubernetes/KubernetesAgentChartAiAccess.test.ts +581 -113
- package/Tests/Types/Kubernetes/KubernetesAiAgentAccessContract.test.ts +510 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +277 -13
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +113 -0
- package/Tests/Types/Monitor/RumAlertTemplates.test.ts +773 -2
- package/Tests/Types/ResourceAiAgent/AiResourceType.test.ts +419 -0
- package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +517 -0
- package/Tests/Types/Runbook/RunbookStepType.test.ts +147 -8
- package/Tests/Types/Team/ComplianceRule.test.ts +1029 -0
- package/Tests/Types/Team/TeamComplianceStatus.test.ts +176 -0
- package/Tests/UI/Components/ActionButton/RowActions.test.tsx +641 -0
- package/Tests/UI/Components/ActionButton/RowActionsAccessibility.test.tsx +414 -0
- package/Tests/UI/Components/ActionButton/SplitActionButtons.test.ts +565 -0
- package/Tests/UI/Components/Charts/BarChartDragToSelect.test.tsx +386 -0
- package/Tests/UI/Components/Charts/ChartDoubleClickResetWithoutDblclick.test.tsx +1025 -0
- package/Tests/UI/Components/Charts/ChartGroupPageZoomHint.test.tsx +196 -0
- package/Tests/UI/Components/Charts/ChartPlaceholdersTakeDoubleClick.test.tsx +1861 -0
- package/Tests/UI/Components/Charts/ChartPlotClicksWhileResetArmed.test.tsx +382 -0
- package/Tests/UI/Components/Charts/ChartRangeSelection.test.tsx +704 -0
- package/Tests/UI/Components/Charts/ChartRangeSelectionDoubleClickReset.test.tsx +1481 -0
- package/Tests/UI/Components/Charts/ChartRangeSelectionRealRecharts.test.tsx +918 -0
- package/Tests/UI/Components/Charts/ChartRowBucketStart.test.ts +350 -0
- package/Tests/UI/Components/Charts/DoubleClickReset.test.tsx +996 -0
- package/Tests/UI/Components/Charts/HistogramDoubleClickResetRealRecharts.test.tsx +965 -0
- package/Tests/UI/Components/Charts/HistogramDriftThenRefetch.test.tsx +277 -0
- package/Tests/UI/Components/Charts/HistogramRangeSelectionDataChange.test.tsx +1757 -0
- package/Tests/UI/Components/Charts/HistogramRangeSelectionRealRecharts.test.tsx +560 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/ChartPageTimeRangeZoom.test.tsx +513 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.test.tsx +845 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.test.tsx +119 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHintTailwind.test.tsx +274 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.test.ts +433 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.test.tsx +863 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/ZoomDocsPromises.test.tsx +1147 -0
- package/Tests/UI/Components/DisabledButtonTooltip.test.tsx +14 -3
- package/Tests/UI/Components/EntityDropdownEscape.test.tsx +454 -0
- package/Tests/UI/Components/EntityDropdownFocusLeave.test.tsx +420 -0
- package/Tests/UI/Components/Forms/FormFieldDropdownDisabled.test.tsx +233 -0
- package/Tests/UI/Components/Input.test.tsx +80 -1
- package/Tests/UI/Components/LogsAnalyticsViewZoom.test.tsx +947 -0
- package/Tests/UI/Components/LogsHistogramDragTooltip.test.tsx +17 -5
- package/Tests/UI/Components/LogsViewerAnalyticsZoom.test.tsx +501 -0
- package/Tests/UI/Components/LogsViewerHistogramZoom.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +6 -4
- package/Tests/UI/Components/ModelTable/BaseModelTablePermissionGating.test.tsx +60 -8
- package/Tests/UI/Components/ModelTable/BaseModelTableRowActions.test.tsx +476 -0
- package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +7 -5
- package/Tests/UI/Components/MoreMenuPortal.test.tsx +623 -0
- package/Tests/UI/Components/StatusPage/ResourceGridActions.test.tsx +538 -0
- package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +14 -4
- package/Tests/UI/Components/TableCellWrapping.test.tsx +3 -3
- package/Tests/UI/Components/TableRowActions.test.tsx +472 -0
- package/Tests/UI/Components/TelemetryHistogramDragTooltip.test.tsx +1 -1
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerHistogramClickZoom.test.tsx +1 -1
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerZoomScope.test.tsx +470 -0
- package/Tests/UI/Components/TelemetryViewer/UseViewerTimeRangeZoom.test.tsx +571 -0
- package/Tests/UI/Components/TelemetryViewer/ViewerDoubleClickResetUnderDataChange.test.tsx +928 -0
- package/Tests/UI/Components/TelemetryViewer/ViewerFollowsEnclosingZoom.test.tsx +1569 -0
- package/Tests/UI/Components/Toggle.test.tsx +66 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardRefreshNames.test.tsx +1023 -0
- package/Tests/UI/Rum/ChunkLoader.test.ts +201 -0
- package/Tests/UI/Rum/FidelityNotices.test.ts +54 -0
- package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +769 -1
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +72 -0
- package/Tests/UI/Rum/ReplayFrameCapture.test.ts +1009 -9
- package/Tests/UI/Rum/ReplayRecordedAssets.test.ts +1069 -0
- package/Tests/UI/Rum/ReplayStage.test.tsx +913 -2
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +443 -8
- package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +439 -9
- package/Tests/UI/Rum/UserFlowTablesRowActions.test.tsx +501 -0
- package/Tests/Utils/AiRemediation/KubectlPolicyChartRbacParity.test.ts +47 -19
- package/Tests/Utils/AiRemediation/KubectlWriteScopeCallerParity.test.ts +2 -0
- package/Tests/Utils/AiRemediation/KubernetesAiAgentPolicyCopyParity.test.ts +396 -0
- package/Tests/Utils/AiRemediation/Resource/CephCommandPolicy.test.ts +1653 -0
- package/Tests/Utils/AiRemediation/Resource/CephOutputRedaction.test.ts +204 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseCommandPolicy.test.ts +1077 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.test.ts +558 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseQueryRedactor.test.ts +834 -0
- package/Tests/Utils/AiRemediation/Resource/DockerCliGrammar.test.ts +747 -0
- package/Tests/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.test.ts +1259 -0
- package/Tests/Utils/AiRemediation/Resource/DockerOutputRedaction.test.ts +386 -0
- package/Tests/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.test.ts +782 -0
- package/Tests/Utils/AiRemediation/Resource/GovcCommandPolicy.test.ts +2259 -0
- package/Tests/Utils/AiRemediation/Resource/HostCommandPolicy.test.ts +2019 -0
- package/Tests/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.test.ts +2497 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicy.test.ts +1305 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.test.ts +585 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactor.test.ts +334 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactorCopyParity.test.ts +98 -0
- package/Tests/Utils/AiRemediation/Resource/ResourcePolicyImportClosure.test.ts +391 -0
- package/Tests/Utils/AiRemediation/ResourceAiAgentPolicyCopyParity.test.ts +497 -0
- package/Tests/Utils/Dashboard/DashboardTimeRangeZoom.test.ts +104 -1
- package/Tests/Utils/SessionReplay/SessionReplayBudgetMetricType.test.ts +383 -0
- package/Types/AI/AIRunType.ts +9 -4
- package/Types/AI/InvestigationNotStartedReason.ts +6 -0
- package/Types/AI/ResourceAiAccessApi.ts +140 -0
- package/Types/AI/ResourceAiAccessPermissions.ts +126 -0
- package/Types/AutoRemediation/AiRemediationCommandPlan.ts +197 -18
- package/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.ts +28 -0
- package/Types/Dashboard/DashboardComponents/DashboardTraceChartComponent.ts +4 -2
- package/Types/Kubernetes/KubernetesClusterAiAccess.ts +263 -32
- package/Types/Kubernetes/KubernetesClusterAiAccessPermissions.ts +20 -16
- package/Types/Kubernetes/KubernetesClusterAiInsights.ts +81 -0
- package/Types/Monitor/ProxmoxAlertTemplates.ts +4 -4
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +55 -22
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +35 -3
- package/Types/Monitor/RumAlertTemplates.ts +351 -4
- package/Types/ResourceAiAgent/AiResourceType.ts +310 -0
- package/Types/ResourceAiAgent/ResourceAiAccess.ts +574 -0
- package/Types/Rum/SessionReplayBudgetMetricType.ts +47 -0
- package/Types/Runbook/RunbookStepType.ts +29 -0
- package/Types/Team/ComplianceNotificationChannel.ts +22 -0
- package/Types/Team/ComplianceRule.ts +434 -0
- package/Types/Team/ComplianceRuleType.ts +21 -0
- package/Types/Team/TeamComplianceStatus.ts +81 -0
- package/Types/Telemetry/TelemetryIngestSurface.ts +40 -0
- package/UI/Components/ActionButton/ActionButtonSchema.ts +21 -0
- package/UI/Components/ActionButton/RowActions.tsx +238 -0
- package/UI/Components/ActionButton/SplitActionButtons.ts +173 -0
- package/UI/Components/Charts/Area/AreaChart.tsx +32 -2
- package/UI/Components/Charts/Bar/BarChart.tsx +40 -3
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +37 -11
- package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +80 -243
- package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +122 -31
- package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +95 -244
- package/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.ts +214 -0
- package/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.ts +32 -0
- package/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.ts +599 -0
- package/UI/Components/Charts/Line/LineChart.tsx +32 -2
- package/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.tsx +70 -0
- package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.tsx +226 -0
- package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.tsx +73 -0
- package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.ts +163 -0
- package/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.ts +215 -0
- package/UI/Components/Charts/Utils/DataPoint.ts +20 -8
- package/UI/Components/Charts/Utils/XAxis.ts +75 -0
- package/UI/Components/Charts/Utils/useHistogramRangeSelection.ts +493 -59
- package/UI/Components/EntityDropdown/EntityDropdown.tsx +107 -11
- package/UI/Components/Forms/Fields/FormField.tsx +10 -0
- package/UI/Components/Input/Input.tsx +90 -57
- package/UI/Components/List/ListRow.tsx +8 -74
- package/UI/Components/LogsViewer/LogsViewer.tsx +40 -11
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +22 -6
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +209 -6
- package/UI/Components/LogsViewer/components/LogsHistogram.tsx +127 -84
- package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +3 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +12 -1
- package/UI/Components/MoreMenu/MoreMenu.tsx +365 -30
- package/UI/Components/MoreMenu/MoreMenuItem.tsx +70 -17
- package/UI/Components/OrderedStatesList/Item.tsx +7 -72
- package/UI/Components/StatusPage/ResourceGrid.tsx +126 -77
- package/UI/Components/Table/TableBody.tsx +8 -2
- package/UI/Components/Table/TableRow.tsx +20 -140
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +41 -10
- package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +47 -9
- package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +25 -6
- package/UI/Components/TelemetryViewer/types.ts +2 -0
- package/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.ts +448 -0
- package/UI/Components/Toggle/Toggle.tsx +26 -0
- package/UI/Components/Tooltip/Tooltip.tsx +8 -1
- package/UI/Styles/Theme.css +14 -2
- package/Utils/AI/InvestigationReport.ts +121 -15
- package/Utils/AiRemediation/CommandPolicy.ts +1 -1
- package/Utils/AiRemediation/KubectlPolicy.ts +1 -1
- package/Utils/AiRemediation/Resource/CephCommandPolicy.ts +1936 -0
- package/Utils/AiRemediation/Resource/DatabaseCommandPolicy.ts +166 -0
- package/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.ts +1532 -0
- package/Utils/AiRemediation/Resource/DatabaseQueryRedactor.ts +1394 -0
- package/Utils/AiRemediation/Resource/DockerCliGrammar.ts +1839 -0
- package/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.ts +490 -0
- package/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.ts +687 -0
- package/Utils/AiRemediation/Resource/GovcCommandPolicy.ts +2096 -0
- package/Utils/AiRemediation/Resource/HostCommandPolicy.ts +2982 -0
- package/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.ts +1679 -0
- package/Utils/AiRemediation/Resource/ResourceCommandPolicy.ts +851 -0
- package/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.ts +593 -0
- package/Utils/AiRemediation/Resource/ResourceOutputRedactor.ts +2812 -0
- package/Utils/Dashboard/DashboardTimeRangeZoom.ts +46 -2
- package/Utils/SessionReplay/SessionReplayBudgetMetricType.ts +184 -0
- package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +62 -0
- package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js +219 -0
- package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseServer.js +219 -0
- package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js +219 -0
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +219 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Host.js +219 -0
- package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +4 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js +385 -0
- package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js.map +1 -0
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +3 -3
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanHost.js +219 -0
- package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +56 -5
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +219 -0
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxResource.js +51 -1
- package/build/dist/Models/DatabaseModels/ProxmoxResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ResourceAiAgent.js +439 -0
- package/build/dist/Models/DatabaseModels/ResourceAiAgent.js.map +1 -0
- package/build/dist/Models/DatabaseModels/RunnerJob.js +219 -0
- package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +134 -3
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js +219 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +6 -1
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +17 -10
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/AutoRemediationAPI.js +374 -24
- package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
- package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js +436 -22
- package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +69 -13
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/ProxmoxResourceAPI.js +187 -14
- package/build/dist/Server/API/ProxmoxResourceAPI.js.map +1 -1
- package/build/dist/Server/API/ResourceAiAccessAPI.js +1119 -0
- package/build/dist/Server/API/ResourceAiAccessAPI.js.map +1 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js +27 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js +50 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js +84 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js +31 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js +168 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +6 -0
- package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +41 -19
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +59 -1
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +248 -13
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AlertSeverityService.js +51 -15
- package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +26 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +601 -3
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleService.js +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +104 -0
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseServerService.js +99 -0
- package/build/dist/Server/Services/DatabaseServerService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +104 -0
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +104 -0
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +114 -2
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +199 -72
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentSeverityService.js +51 -15
- package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesAiAgentJobService.js +158 -0
- package/build/dist/Server/Services/KubernetesAiAgentJobService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesAiAgentService.js +1145 -0
- package/build/dist/Server/Services/KubernetesAiAgentService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesClusterAiAccessService.js +842 -371
- package/build/dist/Server/Services/KubernetesClusterAiAccessService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +86 -17
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/MetricRecordingRuleService.js +46 -0
- package/build/dist/Server/Services/MetricRecordingRuleService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +104 -0
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +22 -0
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +104 -0
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxResourceService.js +258 -3
- package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -1
- package/build/dist/Server/Services/ResourceAiAccessService.js +1028 -0
- package/build/dist/Server/Services/ResourceAiAccessService.js.map +1 -0
- package/build/dist/Server/Services/ResourceAiAgentJobService.js +173 -0
- package/build/dist/Server/Services/ResourceAiAgentJobService.js.map +1 -0
- package/build/dist/Server/Services/ResourceAiAgentService.js +1687 -0
- package/build/dist/Server/Services/ResourceAiAgentService.js.map +1 -0
- package/build/dist/Server/Services/RunnerJobService.js +522 -97
- package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
- package/build/dist/Server/Services/RunnerService.js +1 -1
- package/build/dist/Server/Services/RunnerService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +535 -3
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +316 -46
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/TeamComplianceSettingService.js +833 -7
- package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +26 -0
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/TraceRecordingRuleService.js +37 -0
- package/build/dist/Server/Services/TraceRecordingRuleService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterService.js +104 -0
- package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js +52 -9
- package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +13 -9
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +7 -3
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +1056 -43
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +683 -42
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +21 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +330 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js +160 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js +33 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js +640 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js +226 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +600 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +89 -9
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +55 -4
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +55 -4
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js +30 -3
- package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js +13 -2
- package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +1 -1
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +294 -15
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
- package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +29 -1
- package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +9 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js +627 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js +60 -5
- package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +111 -6
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +40 -4
- package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js +296 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js +699 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +77 -19
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +17 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +183 -209
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +233 -167
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +768 -152
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js +129 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js +266 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js +258 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js +104 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js +183 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js +123 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js.map +1 -0
- package/build/dist/Types/AI/AIRunType.js +9 -4
- package/build/dist/Types/AI/AIRunType.js.map +1 -1
- package/build/dist/Types/AI/ResourceAiAccessApi.js +30 -0
- package/build/dist/Types/AI/ResourceAiAccessApi.js.map +1 -0
- package/build/dist/Types/AI/ResourceAiAccessPermissions.js +98 -0
- package/build/dist/Types/AI/ResourceAiAccessPermissions.js.map +1 -0
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +126 -45
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js +28 -0
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js.map +1 -0
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +72 -16
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js +20 -16
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js +17 -0
- package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js.map +1 -0
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +4 -4
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +47 -21
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +5 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/RumAlertTemplates.js +199 -3
- package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
- package/build/dist/Types/ResourceAiAgent/AiResourceType.js +242 -0
- package/build/dist/Types/ResourceAiAgent/AiResourceType.js.map +1 -0
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +275 -0
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js +45 -0
- package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js.map +1 -0
- package/build/dist/Types/Runbook/RunbookStepType.js +27 -0
- package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
- package/build/dist/Types/Team/ComplianceNotificationChannel.js +23 -0
- package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -0
- package/build/dist/Types/Team/ComplianceRule.js +304 -0
- package/build/dist/Types/Team/ComplianceRule.js.map +1 -0
- package/build/dist/Types/Team/ComplianceRuleType.js +21 -0
- package/build/dist/Types/Team/ComplianceRuleType.js.map +1 -1
- package/build/dist/Types/Team/TeamComplianceStatus.js +2 -0
- package/build/dist/Types/Team/TeamComplianceStatus.js.map +1 -0
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +36 -0
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
- package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js +20 -1
- package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js.map +1 -1
- package/build/dist/UI/Components/ActionButton/RowActions.js +113 -0
- package/build/dist/UI/Components/ActionButton/RowActions.js.map +1 -0
- package/build/dist/UI/Components/ActionButton/SplitActionButtons.js +71 -0
- package/build/dist/UI/Components/ActionButton/SplitActionButtons.js.map +1 -0
- package/build/dist/UI/Components/Charts/Area/AreaChart.js +16 -1
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +16 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +27 -5
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +61 -194
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +84 -26
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +75 -196
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js +133 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js +26 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js.map +1 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js +371 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js.map +1 -0
- package/build/dist/UI/Components/Charts/Line/LineChart.js +16 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js +35 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js +107 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js +41 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js +117 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js +121 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js.map +1 -0
- package/build/dist/UI/Components/Charts/Utils/DataPoint.js +15 -7
- package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/XAxis.js +70 -0
- package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js +305 -38
- package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js.map +1 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +89 -14
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +11 -2
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +69 -54
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/List/ListRow.js +4 -39
- package/build/dist/UI/Components/List/ListRow.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +31 -8
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +10 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +139 -21
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +30 -8
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +10 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +253 -14
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +43 -13
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
- package/build/dist/UI/Components/OrderedStatesList/Item.js +2 -38
- package/build/dist/UI/Components/OrderedStatesList/Item.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js +53 -15
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
- package/build/dist/UI/Components/Table/TableBody.js +6 -2
- package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +12 -75
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +32 -7
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +27 -9
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +11 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js +272 -0
- package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js.map +1 -0
- package/build/dist/UI/Components/Toggle/Toggle.js +14 -1
- package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
- package/build/dist/Utils/AI/InvestigationReport.js +71 -11
- package/build/dist/Utils/AI/InvestigationReport.js.map +1 -1
- package/build/dist/Utils/AiRemediation/CommandPolicy.js +1 -1
- package/build/dist/Utils/AiRemediation/CommandPolicy.js.map +1 -1
- package/build/dist/Utils/AiRemediation/KubectlPolicy.js +1 -1
- package/build/dist/Utils/AiRemediation/KubectlPolicy.js.map +1 -1
- package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js +1462 -0
- package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js +122 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js +1139 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js +1060 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js +1301 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js +370 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js +498 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js +1565 -0
- package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js +2206 -0
- package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js +1129 -0
- package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js +565 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js +408 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js +1910 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js.map +1 -0
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js +27 -1
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js.map +1 -1
- package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js +160 -0
- package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js.map +1 -0
- package/package.json +1 -1
|
@@ -65,6 +65,7 @@ import UserService from "../../../Services/UserService";
|
|
|
65
65
|
import QueryHelper from "../../../Types/Database/QueryHelper";
|
|
66
66
|
import SortOrder from "../../../../Types/BaseDatabase/SortOrder";
|
|
67
67
|
import LIMIT_MAX from "../../../../Types/Database/LimitMax";
|
|
68
|
+
import { truncateToLength } from "../../Database/TruncateColumnValue";
|
|
68
69
|
|
|
69
70
|
// Bot Framework SDK imports
|
|
70
71
|
import {
|
|
@@ -87,6 +88,7 @@ import { ExpressRequest, ExpressResponse } from "../../Express";
|
|
|
87
88
|
import MicrosoftTeamsServiceUrl from "./MicrosoftTeamsServiceUrl";
|
|
88
89
|
// Teams action handlers and types
|
|
89
90
|
import MicrosoftTeamsAuthAction, {
|
|
91
|
+
MicrosoftTeamsAccountNotLinkedException,
|
|
90
92
|
MicrosoftTeamsRequest,
|
|
91
93
|
} from "./Actions/Auth";
|
|
92
94
|
import MicrosoftTeamsIncidentActions from "./Actions/Incident";
|
|
@@ -101,6 +103,10 @@ import MicrosoftTeamsIncidentEpisodeActions from "./Actions/IncidentEpisode";
|
|
|
101
103
|
import MicrosoftTeamsMonitorActions from "./Actions/Monitor";
|
|
102
104
|
import MicrosoftTeamsScheduledMaintenanceActions from "./Actions/ScheduledMaintenance";
|
|
103
105
|
import MicrosoftTeamsOnCallDutyActions from "./Actions/OnCallDutyPolicy";
|
|
106
|
+
import MicrosoftTeamsActivityDeduplicator from "./MicrosoftTeamsActivityDeduplicator";
|
|
107
|
+
import MicrosoftTeamsCreateCommands from "./MicrosoftTeamsCreateCommands";
|
|
108
|
+
import MicrosoftTeamsMessageSize from "./MicrosoftTeamsMessageSize";
|
|
109
|
+
import MicrosoftTeamsReplies from "./MicrosoftTeamsReplies";
|
|
104
110
|
|
|
105
111
|
/*
|
|
106
112
|
* AI Ops - observability assistant imports. These power the natural-language
|
|
@@ -164,6 +170,64 @@ export enum MicrosoftTeamsAppInstallState {
|
|
|
164
170
|
export const MICROSOFT_TEAMS_INSTALL_READ_PERMISSION: string =
|
|
165
171
|
"TeamsAppInstallation.ReadForTeam.All";
|
|
166
172
|
|
|
173
|
+
/*
|
|
174
|
+
* The resource-specific (per chat) permission that lets OneUptime read a group
|
|
175
|
+
* chat's name (its Graph "topic") with the app-only token. Bot Framework
|
|
176
|
+
* activities from group chats do not reliably carry the name, so without this
|
|
177
|
+
* a group chat can only be named after its members. It is granted per chat
|
|
178
|
+
* when the app is installed or updated there with a manifest that requests it.
|
|
179
|
+
* (The tenant-wide Chat.ReadBasic.WhereInstalled application permission works
|
|
180
|
+
* with the same call, for admins who would rather grant it once.)
|
|
181
|
+
*/
|
|
182
|
+
export const MICROSOFT_TEAMS_CHAT_TOPIC_READ_PERMISSION: string =
|
|
183
|
+
"ChatSettings.Read.Chat";
|
|
184
|
+
|
|
185
|
+
export enum MicrosoftTeamsChatTopicLookupStatus {
|
|
186
|
+
Found = "Found", // the chat has a name in Teams.
|
|
187
|
+
NoTopic = "NoTopic", // the chat exists but nobody has named it.
|
|
188
|
+
PermissionDenied = "PermissionDenied",
|
|
189
|
+
Unknown = "Unknown",
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export interface MicrosoftTeamsChatTopicLookup {
|
|
193
|
+
status: MicrosoftTeamsChatTopicLookupStatus;
|
|
194
|
+
topic?: string | undefined; // set only when status is Found.
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export interface MicrosoftTeamsChatNameRefreshResult {
|
|
198
|
+
// The project's chats as stored once the refresh has been written.
|
|
199
|
+
chats: Record<string, MicrosoftTeamsChat>;
|
|
200
|
+
// Group chats whose name Microsoft refused to share (permission missing).
|
|
201
|
+
permissionDeniedChatIds: Array<string>;
|
|
202
|
+
// Group chats whose name could not be read for any other reason.
|
|
203
|
+
failedChatIds: Array<string>;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// A chat's name and the Teams name it was built from, as Refresh Chats writes them.
|
|
207
|
+
export interface MicrosoftTeamsChatNameUpdate {
|
|
208
|
+
name: string;
|
|
209
|
+
topic?: string | undefined; // absent: the chat has no name in Teams.
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// How many Graph chat lookups Refresh Chats runs at once.
|
|
213
|
+
const MICROSOFT_TEAMS_CHAT_TOPIC_LOOKUP_CONCURRENCY: number = 5;
|
|
214
|
+
|
|
215
|
+
/*
|
|
216
|
+
* Per-lookup ceiling. Concurrent refreshes of a project share one run, so a
|
|
217
|
+
* lookup that never answers would otherwise hold every later Refresh Chats
|
|
218
|
+
* for that project.
|
|
219
|
+
*/
|
|
220
|
+
const MICROSOFT_TEAMS_CHAT_TOPIC_LOOKUP_TIMEOUT_IN_MS: number = 15000;
|
|
221
|
+
|
|
222
|
+
/*
|
|
223
|
+
* Chat names are kept well under the 100-character ShortText columns that
|
|
224
|
+
* store them in notification logs — Teams chat names can be much longer.
|
|
225
|
+
*/
|
|
226
|
+
const MICROSOFT_TEAMS_CHAT_NAME_MAX_LENGTH: number = 80;
|
|
227
|
+
|
|
228
|
+
// How many member names a group chat named after its members shows.
|
|
229
|
+
const MICROSOFT_TEAMS_CHAT_NAME_MEMBERS_SHOWN: number = 3;
|
|
230
|
+
|
|
167
231
|
/*
|
|
168
232
|
* Microsoft's wording when the Bot Framework refuses a proactive post because
|
|
169
233
|
* the app is not a member of the target conversation. Matched case-insensitively
|
|
@@ -177,6 +241,13 @@ const MICROSOFT_TEAMS_ROSTER_ERROR_FRAGMENTS: Array<string> = [
|
|
|
177
241
|
// Maximum number of pages to fetch when paginating teams
|
|
178
242
|
const MICROSOFT_TEAMS_MAX_PAGES: number = 500;
|
|
179
243
|
|
|
244
|
+
// Bot commands that open a form; text after them becomes the form's title.
|
|
245
|
+
const CREATE_INCIDENT_COMMAND: string = "create incident";
|
|
246
|
+
const CREATE_MAINTENANCE_COMMAND: string = "create maintenance";
|
|
247
|
+
|
|
248
|
+
// How many affected monitors a "show ..." reply names for one item.
|
|
249
|
+
const MICROSOFT_TEAMS_MAX_AFFECTED_MONITOR_NAMES: number = 10;
|
|
250
|
+
|
|
180
251
|
/*
|
|
181
252
|
* Hosts that may receive a Teams incoming webhook. Legacy Connector webhooks
|
|
182
253
|
* use Office domains. Teams Workflows use regional logic.azure.com hosts, and
|
|
@@ -2949,21 +3020,6 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
|
|
|
2949
3020
|
});
|
|
2950
3021
|
}
|
|
2951
3022
|
|
|
2952
|
-
// If this is actually an Adaptive Card submit wrapped as a message, route to invoke handler
|
|
2953
|
-
if (
|
|
2954
|
-
(possibleActionValue["action"] as string) ||
|
|
2955
|
-
(possibleActionValue["data"] as any)?.["action"]
|
|
2956
|
-
) {
|
|
2957
|
-
logger.debug(
|
|
2958
|
-
"Message activity contains action payload; routing to invoke handler",
|
|
2959
|
-
);
|
|
2960
|
-
await this.handleBotInvokeActivity({
|
|
2961
|
-
activity: data.activity,
|
|
2962
|
-
turnContext: data.turnContext,
|
|
2963
|
-
});
|
|
2964
|
-
return;
|
|
2965
|
-
}
|
|
2966
|
-
|
|
2967
3023
|
// Check if the bot was mentioned
|
|
2968
3024
|
const recipientId: string = (data.activity["recipient"] as JSONObject)?.[
|
|
2969
3025
|
"id"
|
|
@@ -2978,45 +3034,45 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
|
|
|
2978
3034
|
);
|
|
2979
3035
|
});
|
|
2980
3036
|
|
|
2981
|
-
//
|
|
2982
|
-
|
|
3037
|
+
// An Adaptive Card submit arrives as a message whose value names the action.
|
|
3038
|
+
const isCardSubmit: boolean = Boolean(
|
|
3039
|
+
(possibleActionValue["action"] as string) ||
|
|
3040
|
+
(possibleActionValue["data"] as any)?.["action"],
|
|
3041
|
+
);
|
|
3042
|
+
|
|
3043
|
+
// Only respond to card submits, direct messages and @mentions.
|
|
3044
|
+
if (!isCardSubmit && !isDirectMessage && !isMentioned) {
|
|
2983
3045
|
logger.debug("Bot not mentioned in channel message, ignoring");
|
|
2984
3046
|
return;
|
|
2985
3047
|
}
|
|
2986
3048
|
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
"
|
|
3049
|
+
/*
|
|
3050
|
+
* Teams delivers an activity again when the first delivery was slow or
|
|
3051
|
+
* failed. Handling it twice sends every reply twice and creates a
|
|
3052
|
+
* submitted incident twice, so only the first delivery is handled.
|
|
3053
|
+
*/
|
|
3054
|
+
if (!(await MicrosoftTeamsActivityDeduplicator.claim(data.activity))) {
|
|
3055
|
+
logger.debug(
|
|
3056
|
+
"Microsoft Teams delivered this activity before; ignoring the repeat",
|
|
3057
|
+
{
|
|
3058
|
+
activityId: (data.activity["id"] as string) || "",
|
|
3059
|
+
},
|
|
2995
3060
|
);
|
|
2996
3061
|
return;
|
|
2997
3062
|
}
|
|
2998
3063
|
|
|
2999
|
-
//
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
});
|
|
3004
|
-
|
|
3005
|
-
if (
|
|
3006
|
-
!tenantResolution.projectAuth ||
|
|
3007
|
-
!tenantResolution.projectAuth.projectId
|
|
3008
|
-
) {
|
|
3009
|
-
await data.turnContext.sendActivity(
|
|
3010
|
-
this.getTenantResolutionFailureMessage(tenantResolution),
|
|
3064
|
+
// If this is actually an Adaptive Card submit wrapped as a message, route to invoke handler
|
|
3065
|
+
if (isCardSubmit) {
|
|
3066
|
+
logger.debug(
|
|
3067
|
+
"Message activity contains action payload; routing to invoke handler",
|
|
3011
3068
|
);
|
|
3069
|
+
await this.handleBotInvokeActivity({
|
|
3070
|
+
activity: data.activity,
|
|
3071
|
+
turnContext: data.turnContext,
|
|
3072
|
+
});
|
|
3012
3073
|
return;
|
|
3013
3074
|
}
|
|
3014
3075
|
|
|
3015
|
-
const projectId: ObjectID = tenantResolution.projectAuth.projectId;
|
|
3016
|
-
logger.debug(
|
|
3017
|
-
`Found project ID: ${projectId.toString()} for tenant ID: ${tenantId}`,
|
|
3018
|
-
);
|
|
3019
|
-
|
|
3020
3076
|
// Clean the message text by removing bot mentions
|
|
3021
3077
|
const cleanText: string = messageText
|
|
3022
3078
|
.replace(/<at[^>]*>.*?<\/at>/g, "")
|
|
@@ -3032,81 +3088,131 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
|
|
|
3032
3088
|
.replace(/<at[^>]*>.*?<\/at>/g, "")
|
|
3033
3089
|
.trim();
|
|
3034
3090
|
|
|
3035
|
-
|
|
3091
|
+
const isCreateIncidentCommand: boolean =
|
|
3092
|
+
cleanText === CREATE_INCIDENT_COMMAND ||
|
|
3093
|
+
cleanText.startsWith(CREATE_INCIDENT_COMMAND + " ");
|
|
3036
3094
|
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
cleanText.startsWith("create incident ");
|
|
3095
|
+
const isCreateMaintenanceCommand: boolean =
|
|
3096
|
+
cleanText === CREATE_MAINTENANCE_COMMAND ||
|
|
3097
|
+
cleanText.startsWith(CREATE_MAINTENANCE_COMMAND + " ");
|
|
3041
3098
|
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3099
|
+
/*
|
|
3100
|
+
* Explicit commands are matched precisely so that natural-language
|
|
3101
|
+
* questions (which may incidentally contain words like "help" or
|
|
3102
|
+
* "alerts") fall through to the AI assistant instead of a canned command.
|
|
3103
|
+
*/
|
|
3104
|
+
const isHelpCommand: boolean =
|
|
3105
|
+
cleanText === "help" || cleanText === "" || cleanText === "?";
|
|
3045
3106
|
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
* questions (which may incidentally contain words like "help" or
|
|
3049
|
-
* "alerts") fall through to the AI assistant instead of a canned command.
|
|
3050
|
-
*/
|
|
3051
|
-
const isHelpCommand: boolean =
|
|
3052
|
-
cleanText === "help" || cleanText === "" || cleanText === "?";
|
|
3107
|
+
const isShowActiveIncidentsCommand: boolean =
|
|
3108
|
+
cleanText === "show active incidents" || cleanText === "active incidents";
|
|
3053
3109
|
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3110
|
+
const isShowScheduledMaintenanceCommand: boolean =
|
|
3111
|
+
cleanText === "show scheduled maintenance" ||
|
|
3112
|
+
cleanText === "scheduled maintenance";
|
|
3057
3113
|
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3114
|
+
const isShowOngoingMaintenanceCommand: boolean =
|
|
3115
|
+
cleanText === "show ongoing maintenance" ||
|
|
3116
|
+
cleanText === "ongoing maintenance";
|
|
3061
3117
|
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
cleanText === "ongoing maintenance";
|
|
3118
|
+
const isShowActiveAlertsCommand: boolean =
|
|
3119
|
+
cleanText === "show active alerts" || cleanText === "active alerts";
|
|
3065
3120
|
|
|
3066
|
-
|
|
3067
|
-
|
|
3121
|
+
/*
|
|
3122
|
+
* "ask <question>" is an explicit prefix that always routes to the AI
|
|
3123
|
+
* assistant. When present, strip the prefix and use the remainder as the
|
|
3124
|
+
* question.
|
|
3125
|
+
*/
|
|
3126
|
+
const isAskCommand: boolean =
|
|
3127
|
+
cleanText === "ask" || cleanText.startsWith("ask ");
|
|
3068
3128
|
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3129
|
+
/*
|
|
3130
|
+
* The command, named for log lines that must not quote the message: a
|
|
3131
|
+
* free-form question can carry things that do not belong in a log.
|
|
3132
|
+
*/
|
|
3133
|
+
const commandName: string | undefined = [
|
|
3134
|
+
{ matches: isHelpCommand, name: "help" },
|
|
3135
|
+
{ matches: isCreateIncidentCommand, name: CREATE_INCIDENT_COMMAND },
|
|
3136
|
+
{ matches: isCreateMaintenanceCommand, name: CREATE_MAINTENANCE_COMMAND },
|
|
3137
|
+
{ matches: isShowActiveIncidentsCommand, name: "show active incidents" },
|
|
3138
|
+
{
|
|
3139
|
+
matches: isShowScheduledMaintenanceCommand,
|
|
3140
|
+
name: "show scheduled maintenance",
|
|
3141
|
+
},
|
|
3142
|
+
{
|
|
3143
|
+
matches: isShowOngoingMaintenanceCommand,
|
|
3144
|
+
name: "show ongoing maintenance",
|
|
3145
|
+
},
|
|
3146
|
+
{ matches: isShowActiveAlertsCommand, name: "show active alerts" },
|
|
3147
|
+
{ matches: isAskCommand, name: "ask" },
|
|
3148
|
+
].find((command: { matches: boolean; name: string }) => {
|
|
3149
|
+
return command.matches;
|
|
3150
|
+
})?.name;
|
|
3151
|
+
|
|
3152
|
+
let projectId: ObjectID | undefined = undefined;
|
|
3153
|
+
let responseText: string = "";
|
|
3154
|
+
|
|
3155
|
+
try {
|
|
3156
|
+
// Extract tenant ID to get project ID
|
|
3157
|
+
const tenantId: string = (channelData["tenant"] as JSONObject)?.[
|
|
3158
|
+
"id"
|
|
3159
|
+
] as string;
|
|
3160
|
+
if (!tenantId) {
|
|
3161
|
+
logger.error("Tenant ID not found in channelData");
|
|
3162
|
+
await data.turnContext.sendActivity(
|
|
3163
|
+
"Sorry, I couldn't identify your organization. Please try again later.",
|
|
3164
|
+
);
|
|
3165
|
+
return;
|
|
3166
|
+
}
|
|
3167
|
+
|
|
3168
|
+
// Get project auth by tenant ID
|
|
3169
|
+
const tenantResolution: MicrosoftTeamsTenantResolution =
|
|
3170
|
+
await this.resolveProjectByTenantId({
|
|
3171
|
+
tenantId: tenantId,
|
|
3172
|
+
});
|
|
3173
|
+
|
|
3174
|
+
if (
|
|
3175
|
+
!tenantResolution.projectAuth ||
|
|
3176
|
+
!tenantResolution.projectAuth.projectId
|
|
3177
|
+
) {
|
|
3178
|
+
await data.turnContext.sendActivity(
|
|
3179
|
+
this.getTenantResolutionFailureMessage(tenantResolution),
|
|
3180
|
+
);
|
|
3181
|
+
return;
|
|
3182
|
+
}
|
|
3183
|
+
|
|
3184
|
+
projectId = tenantResolution.projectAuth.projectId;
|
|
3185
|
+
logger.debug(
|
|
3186
|
+
`Found project ID: ${projectId.toString()} for tenant ID: ${tenantId}`,
|
|
3187
|
+
);
|
|
3076
3188
|
|
|
3077
3189
|
if (isHelpCommand) {
|
|
3078
3190
|
responseText = this.getHelpMessage();
|
|
3079
3191
|
} else if (isCreateIncidentCommand) {
|
|
3080
|
-
//
|
|
3192
|
+
// "create incident <title>" opens the form with the title filled in.
|
|
3081
3193
|
logger.debug("Processing create incident command");
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
},
|
|
3090
|
-
],
|
|
3194
|
+
await MicrosoftTeamsCreateCommands.handleCreateIncidentCommand({
|
|
3195
|
+
turnContext: data.turnContext,
|
|
3196
|
+
activity: data.activity,
|
|
3197
|
+
projectId: projectId,
|
|
3198
|
+
initialTitle: originalQuestionText
|
|
3199
|
+
.substring(CREATE_INCIDENT_COMMAND.length)
|
|
3200
|
+
.trim(),
|
|
3091
3201
|
});
|
|
3092
|
-
logger.debug("New incident card sent successfully");
|
|
3093
3202
|
return;
|
|
3094
3203
|
} else if (isCreateMaintenanceCommand) {
|
|
3095
|
-
//
|
|
3204
|
+
// "create maintenance <title>" opens the form with the title filled in.
|
|
3096
3205
|
logger.debug("Processing create maintenance command");
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
],
|
|
3108
|
-
});
|
|
3109
|
-
logger.debug("New scheduled maintenance card sent successfully");
|
|
3206
|
+
await MicrosoftTeamsCreateCommands.handleCreateScheduledMaintenanceCommand(
|
|
3207
|
+
{
|
|
3208
|
+
turnContext: data.turnContext,
|
|
3209
|
+
activity: data.activity,
|
|
3210
|
+
projectId: projectId,
|
|
3211
|
+
initialTitle: originalQuestionText
|
|
3212
|
+
.substring(CREATE_MAINTENANCE_COMMAND.length)
|
|
3213
|
+
.trim(),
|
|
3214
|
+
},
|
|
3215
|
+
);
|
|
3110
3216
|
return;
|
|
3111
3217
|
} else if (isShowActiveIncidentsCommand) {
|
|
3112
3218
|
responseText = await this.getActiveIncidentsMessage(projectId);
|
|
@@ -3142,19 +3248,98 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
|
|
|
3142
3248
|
return;
|
|
3143
3249
|
}
|
|
3144
3250
|
|
|
3145
|
-
|
|
3146
|
-
|
|
3251
|
+
/*
|
|
3252
|
+
* Send response directly using TurnContext - this is the recommended Bot
|
|
3253
|
+
* Framework pattern. Lists grow with the project, so the text is kept
|
|
3254
|
+
* within what Teams accepts.
|
|
3255
|
+
*/
|
|
3256
|
+
await data.turnContext.sendActivity(
|
|
3257
|
+
MicrosoftTeamsMessageSize.fitTextToBudget({ text: responseText }),
|
|
3258
|
+
);
|
|
3147
3259
|
logger.debug("Bot message sent successfully using TurnContext", {
|
|
3148
3260
|
projectId: projectId.toString(),
|
|
3149
3261
|
});
|
|
3150
3262
|
} catch (error) {
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3263
|
+
/*
|
|
3264
|
+
* One reply, and no rethrow. This used to reply and then rethrow: the
|
|
3265
|
+
* adapter answered Teams with HTTP 500, Teams delivered the message
|
|
3266
|
+
* again, and every failure showed up twice (issue #4111).
|
|
3267
|
+
*/
|
|
3268
|
+
/*
|
|
3269
|
+
* The command is named, not quoted: a free-form question can carry
|
|
3270
|
+
* things that do not belong in an error log. The text is in the debug
|
|
3271
|
+
* log above.
|
|
3272
|
+
*/
|
|
3273
|
+
MicrosoftTeamsReplies.logFailure(
|
|
3274
|
+
`Microsoft Teams message ${(data.activity["id"] as string) || ""} (${
|
|
3275
|
+
commandName
|
|
3276
|
+
? `"${commandName}"`
|
|
3277
|
+
: `a ${cleanText.length}-character question`
|
|
3278
|
+
}) failed`,
|
|
3279
|
+
error,
|
|
3280
|
+
{
|
|
3281
|
+
projectId: projectId?.toString(),
|
|
3282
|
+
},
|
|
3156
3283
|
);
|
|
3157
|
-
|
|
3284
|
+
await MicrosoftTeamsReplies.sendBestEffort(
|
|
3285
|
+
data.turnContext,
|
|
3286
|
+
this.getUnexpectedErrorMessage(data.activity),
|
|
3287
|
+
);
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
|
|
3291
|
+
/*
|
|
3292
|
+
* The reply to a message whose handling failed in a way nobody planned for.
|
|
3293
|
+
* It names the activity id, which the server log line carries too, so an
|
|
3294
|
+
* administrator can find what went wrong.
|
|
3295
|
+
*/
|
|
3296
|
+
public static getUnexpectedErrorMessage(activity: JSONObject): string {
|
|
3297
|
+
const reference: string = (activity["id"] as string | undefined) || "";
|
|
3298
|
+
|
|
3299
|
+
return `Sorry, something went wrong in OneUptime while handling that message. Please try again in a minute.${
|
|
3300
|
+
reference
|
|
3301
|
+
? ` If it keeps happening, ask your OneUptime administrator to look for reference ${reference} in the server logs.`
|
|
3302
|
+
: ""
|
|
3303
|
+
}`;
|
|
3304
|
+
}
|
|
3305
|
+
|
|
3306
|
+
/*
|
|
3307
|
+
* The last line of defence for an inbound activity whose handler threw.
|
|
3308
|
+
*
|
|
3309
|
+
* The error is logged and the turn ends normally, so CloudAdapter answers
|
|
3310
|
+
* Teams with 200. Letting the error through made CloudAdapter answer HTTP
|
|
3311
|
+
* 500, Teams delivered the activity again, and every reply the turn had
|
|
3312
|
+
* posted appeared twice (issue #4111). A message that got no reply yet gets
|
|
3313
|
+
* one; an invoke gets the response it needs, or CloudAdapter answers 501.
|
|
3314
|
+
*
|
|
3315
|
+
* This is deliberately not adapter.onTurnError: the same adapter sends
|
|
3316
|
+
* proactive notifications, and their callers need their errors thrown.
|
|
3317
|
+
*/
|
|
3318
|
+
public static async recoverFromFailedTurn(data: {
|
|
3319
|
+
turnContext: TurnContext;
|
|
3320
|
+
error: unknown;
|
|
3321
|
+
}): Promise<void> {
|
|
3322
|
+
const { turnContext, error } = data;
|
|
3323
|
+
const activity: Partial<Activity> = turnContext.activity || {};
|
|
3324
|
+
|
|
3325
|
+
MicrosoftTeamsReplies.logFailure(
|
|
3326
|
+
`Microsoft Teams ${activity.type || "unknown"} activity ${activity.id || ""} failed`,
|
|
3327
|
+
error,
|
|
3328
|
+
);
|
|
3329
|
+
|
|
3330
|
+
if (activity.type === "message" && !turnContext.responded) {
|
|
3331
|
+
await MicrosoftTeamsReplies.sendBestEffort(
|
|
3332
|
+
turnContext,
|
|
3333
|
+
this.getUnexpectedErrorMessage(activity as unknown as JSONObject),
|
|
3334
|
+
);
|
|
3335
|
+
return;
|
|
3336
|
+
}
|
|
3337
|
+
|
|
3338
|
+
if (activity.type === "invoke") {
|
|
3339
|
+
await MicrosoftTeamsReplies.sendBestEffort(turnContext, {
|
|
3340
|
+
type: "invokeResponse",
|
|
3341
|
+
value: { status: 200 },
|
|
3342
|
+
});
|
|
3158
3343
|
}
|
|
3159
3344
|
}
|
|
3160
3345
|
|
|
@@ -3177,14 +3362,35 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
|
|
|
3177
3362
|
* channel/chat message bodies are typically HTML (body.contentType "html").
|
|
3178
3363
|
*/
|
|
3179
3364
|
private static toPlainTextFromTeamsMessageBody(rawContent: string): string {
|
|
3180
|
-
return rawContent
|
|
3181
|
-
.replace(/<at[^>]*>.*?<\/at>/g, "")
|
|
3182
|
-
.replace(/<[^>]*>/g, "")
|
|
3365
|
+
return this.stripHtmlTags(rawContent.replace(/<at[^>]*>.*?<\/at>/g, ""))
|
|
3183
3366
|
.replace(/ /g, " ")
|
|
3184
3367
|
.replace(/\s+/g, " ")
|
|
3185
3368
|
.trim();
|
|
3186
3369
|
}
|
|
3187
3370
|
|
|
3371
|
+
/*
|
|
3372
|
+
* Plain text out of a Teams message body, which Graph and the Bot Framework
|
|
3373
|
+
* hand over as HTML. Removing complete tags is not enough on its own: an
|
|
3374
|
+
* unclosed one ("<script" with no ">" after it) matches no tag pattern, so
|
|
3375
|
+
* once no tag is left, any "<" still standing goes too, and the text holds
|
|
3376
|
+
* no markup at all. The tag pass repeats until nothing changes - the shape
|
|
3377
|
+
* code scanning recognises as complete, where a single pass is reported as
|
|
3378
|
+
* incomplete multi-character sanitization. Teams sends a literal "<" in a
|
|
3379
|
+
* message as "<", which is left encoded: decoding it here would hand
|
|
3380
|
+
* back what this removed.
|
|
3381
|
+
*/
|
|
3382
|
+
public static stripHtmlTags(html: string): string {
|
|
3383
|
+
let text: string = html;
|
|
3384
|
+
let previous: string;
|
|
3385
|
+
|
|
3386
|
+
do {
|
|
3387
|
+
previous = text;
|
|
3388
|
+
text = text.replace(/<[^>]*>/g, "");
|
|
3389
|
+
} while (text !== previous);
|
|
3390
|
+
|
|
3391
|
+
return text.replace(/</g, "");
|
|
3392
|
+
}
|
|
3393
|
+
|
|
3188
3394
|
/*
|
|
3189
3395
|
* AI Ops: gather the prior turns of the current Teams conversation/thread and
|
|
3190
3396
|
* map them to the assistant's history shape ({ role, content }, oldest-first,
|
|
@@ -3448,6 +3654,11 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
|
|
|
3448
3654
|
projectId: projectId,
|
|
3449
3655
|
});
|
|
3450
3656
|
} catch (error) {
|
|
3657
|
+
// A failed lookup is not a missing account; the caller answers it.
|
|
3658
|
+
if (!(error instanceof MicrosoftTeamsAccountNotLinkedException)) {
|
|
3659
|
+
throw error;
|
|
3660
|
+
}
|
|
3661
|
+
|
|
3451
3662
|
logger.debug(
|
|
3452
3663
|
"No OneUptime user linked to Teams user; prompting to connect account",
|
|
3453
3664
|
{
|
|
@@ -3455,9 +3666,11 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
|
|
|
3455
3666
|
workspaceUserId: teamsUserId,
|
|
3456
3667
|
},
|
|
3457
3668
|
);
|
|
3458
|
-
logger.debug(error);
|
|
3459
3669
|
await turnContext.sendActivity(
|
|
3460
|
-
|
|
3670
|
+
await MicrosoftTeamsReplies.getAccountNotLinkedMessage({
|
|
3671
|
+
projectId: projectId,
|
|
3672
|
+
purpose: "ask OneUptime questions from Microsoft Teams",
|
|
3673
|
+
}),
|
|
3461
3674
|
);
|
|
3462
3675
|
return;
|
|
3463
3676
|
}
|
|
@@ -3587,6 +3800,31 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
|
|
|
3587
3800
|
}
|
|
3588
3801
|
}
|
|
3589
3802
|
|
|
3803
|
+
/*
|
|
3804
|
+
* The monitors an incident or maintenance event affects, as one line: the
|
|
3805
|
+
* first few names, then how many more. An event can cover hundreds of
|
|
3806
|
+
* monitors, and listing them all made the reply too large for Teams.
|
|
3807
|
+
*/
|
|
3808
|
+
public static formatAffectedMonitorNames(monitors: Array<Monitor>): string {
|
|
3809
|
+
const names: Array<string> = monitors
|
|
3810
|
+
.map((monitor: Monitor) => {
|
|
3811
|
+
return monitor.name || "";
|
|
3812
|
+
})
|
|
3813
|
+
.filter((name: string) => {
|
|
3814
|
+
return Boolean(name);
|
|
3815
|
+
});
|
|
3816
|
+
|
|
3817
|
+
const shownNames: Array<string> = names.slice(
|
|
3818
|
+
0,
|
|
3819
|
+
MICROSOFT_TEAMS_MAX_AFFECTED_MONITOR_NAMES,
|
|
3820
|
+
);
|
|
3821
|
+
const notShownCount: number = names.length - shownNames.length;
|
|
3822
|
+
|
|
3823
|
+
return notShownCount > 0
|
|
3824
|
+
? `${shownNames.join(", ")} and ${notShownCount} more`
|
|
3825
|
+
: shownNames.join(", ");
|
|
3826
|
+
}
|
|
3827
|
+
|
|
3590
3828
|
// Helper methods for bot commands
|
|
3591
3829
|
private static getHelpMessage(): string {
|
|
3592
3830
|
return `Hello! I'm the OneUptime bot. I can help you with the following commands:
|
|
@@ -3594,8 +3832,8 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
|
|
|
3594
3832
|
**Available Commands:**
|
|
3595
3833
|
- **help** - Show this help message
|
|
3596
3834
|
- **ask <question>** - Ask OneUptime AI about your logs, traces, metrics, incidents and monitors
|
|
3597
|
-
- **create incident** - Create a new incident
|
|
3598
|
-
- **create maintenance** - Create a new scheduled maintenance event
|
|
3835
|
+
- **create incident [title]** - Create a new incident
|
|
3836
|
+
- **create maintenance [title]** - Create a new scheduled maintenance event
|
|
3599
3837
|
- **show active incidents** - Display all currently active incidents
|
|
3600
3838
|
- **show scheduled maintenance** - Show upcoming scheduled maintenance events
|
|
3601
3839
|
- **show ongoing maintenance** - Display currently ongoing maintenance events
|
|
@@ -3700,11 +3938,9 @@ If you need to report an incident or check historical incidents, please visit th
|
|
|
3700
3938
|
`;
|
|
3701
3939
|
|
|
3702
3940
|
if (incident.monitors && incident.monitors.length > 0) {
|
|
3703
|
-
message += `• **Affected Services:** ${
|
|
3704
|
-
.
|
|
3705
|
-
|
|
3706
|
-
})
|
|
3707
|
-
.join(", ")}\n`;
|
|
3941
|
+
message += `• **Affected Services:** ${this.formatAffectedMonitorNames(
|
|
3942
|
+
incident.monitors,
|
|
3943
|
+
)}\n`;
|
|
3708
3944
|
}
|
|
3709
3945
|
|
|
3710
3946
|
if (incident.description) {
|
|
@@ -3807,11 +4043,9 @@ Check back later for upcoming maintenance windows.`;
|
|
|
3807
4043
|
`;
|
|
3808
4044
|
|
|
3809
4045
|
if (event.monitors && event.monitors.length > 0) {
|
|
3810
|
-
message += `• **Affected Services:** ${
|
|
3811
|
-
.
|
|
3812
|
-
|
|
3813
|
-
})
|
|
3814
|
-
.join(", ")}\n`;
|
|
4046
|
+
message += `• **Affected Services:** ${this.formatAffectedMonitorNames(
|
|
4047
|
+
event.monitors,
|
|
4048
|
+
)}\n`;
|
|
3815
4049
|
}
|
|
3816
4050
|
|
|
3817
4051
|
if (event.description) {
|
|
@@ -3913,11 +4147,9 @@ All systems are currently operating normally.`;
|
|
|
3913
4147
|
`;
|
|
3914
4148
|
|
|
3915
4149
|
if (event.monitors && event.monitors.length > 0) {
|
|
3916
|
-
message += `• **Affected Services:** ${
|
|
3917
|
-
.
|
|
3918
|
-
|
|
3919
|
-
})
|
|
3920
|
-
.join(", ")}\n`;
|
|
4150
|
+
message += `• **Affected Services:** ${this.formatAffectedMonitorNames(
|
|
4151
|
+
event.monitors,
|
|
4152
|
+
)}\n`;
|
|
3921
4153
|
}
|
|
3922
4154
|
|
|
3923
4155
|
if (event.description) {
|
|
@@ -4059,6 +4291,8 @@ All monitoring checks are passing normally.`;
|
|
|
4059
4291
|
logger.debug(`Bot invoke activity - Action type: ${actionType}`);
|
|
4060
4292
|
logger.debug(`Bot invoke value: ${JSON.stringify(value)}`);
|
|
4061
4293
|
|
|
4294
|
+
let projectId: ObjectID | undefined = undefined;
|
|
4295
|
+
|
|
4062
4296
|
try {
|
|
4063
4297
|
// Resolve project and user context from activity
|
|
4064
4298
|
const channelData: JSONObject =
|
|
@@ -4089,7 +4323,7 @@ All monitoring checks are passing normally.`;
|
|
|
4089
4323
|
return;
|
|
4090
4324
|
}
|
|
4091
4325
|
|
|
4092
|
-
|
|
4326
|
+
projectId = tenantResolution.projectAuth.projectId;
|
|
4093
4327
|
const fromObj: JSONObject = ((data.activity["from"] as JSONObject) ||
|
|
4094
4328
|
{}) as JSONObject;
|
|
4095
4329
|
const teamsUserId: string | undefined =
|
|
@@ -4244,21 +4478,62 @@ All monitoring checks are passing normally.`;
|
|
|
4244
4478
|
return;
|
|
4245
4479
|
}
|
|
4246
4480
|
} catch (error) {
|
|
4481
|
+
/*
|
|
4482
|
+
* Every reply below is sent best-effort: a reply that fails here must
|
|
4483
|
+
* not escape, or the adapter answers Teams with HTTP 500 and Teams
|
|
4484
|
+
* delivers the action again (issue #4111).
|
|
4485
|
+
*/
|
|
4486
|
+
|
|
4487
|
+
// The account is not connected: say where to connect it.
|
|
4488
|
+
if (
|
|
4489
|
+
error instanceof MicrosoftTeamsAccountNotLinkedException &&
|
|
4490
|
+
projectId
|
|
4491
|
+
) {
|
|
4492
|
+
logger.debug(
|
|
4493
|
+
"Bot invoke activity from a Teams user with no linked account",
|
|
4494
|
+
{
|
|
4495
|
+
actionType: actionType,
|
|
4496
|
+
},
|
|
4497
|
+
);
|
|
4498
|
+
await MicrosoftTeamsReplies.sendBestEffort(
|
|
4499
|
+
data.turnContext,
|
|
4500
|
+
await MicrosoftTeamsReplies.getAccountNotLinkedMessage({
|
|
4501
|
+
projectId: projectId,
|
|
4502
|
+
purpose: "use OneUptime actions in Microsoft Teams",
|
|
4503
|
+
}),
|
|
4504
|
+
);
|
|
4505
|
+
return;
|
|
4506
|
+
}
|
|
4507
|
+
|
|
4247
4508
|
// Tell the user why they were refused; the message is written for them.
|
|
4248
4509
|
if (error instanceof NotAuthorizedException) {
|
|
4249
4510
|
logger.debug("Bot invoke activity refused: " + error.message, {
|
|
4250
4511
|
actionType: actionType,
|
|
4251
4512
|
});
|
|
4252
|
-
await
|
|
4513
|
+
await MicrosoftTeamsReplies.sendBestEffort(
|
|
4514
|
+
data.turnContext,
|
|
4515
|
+
error.message,
|
|
4516
|
+
);
|
|
4253
4517
|
return;
|
|
4254
4518
|
}
|
|
4255
4519
|
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4520
|
+
MicrosoftTeamsReplies.logFailure(
|
|
4521
|
+
"Error handling bot invoke activity",
|
|
4522
|
+
error,
|
|
4523
|
+
{
|
|
4524
|
+
actionType: actionType,
|
|
4525
|
+
projectId: projectId?.toString(),
|
|
4526
|
+
},
|
|
4527
|
+
);
|
|
4528
|
+
|
|
4529
|
+
const reason: string | null =
|
|
4530
|
+
MicrosoftTeamsReplies.getUserFacingErrorMessage(error);
|
|
4531
|
+
|
|
4532
|
+
await MicrosoftTeamsReplies.sendBestEffort(
|
|
4533
|
+
data.turnContext,
|
|
4534
|
+
reason
|
|
4535
|
+
? `Sorry, that action failed: ${reason}`
|
|
4536
|
+
: "Sorry, that action failed. Please try again later.",
|
|
4262
4537
|
);
|
|
4263
4538
|
}
|
|
4264
4539
|
}
|
|
@@ -4507,28 +4782,30 @@ All monitoring checks are passing normally.`;
|
|
|
4507
4782
|
chatType: MicrosoftTeamsChatType;
|
|
4508
4783
|
topic?: string | undefined;
|
|
4509
4784
|
memberNames: Array<string>;
|
|
4510
|
-
}): string {
|
|
4511
4785
|
/*
|
|
4512
|
-
*
|
|
4513
|
-
*
|
|
4786
|
+
* How many members have a name, when memberNames holds only the first
|
|
4787
|
+
* few of them (as stored chats do). Defaults to memberNames' own count.
|
|
4514
4788
|
*/
|
|
4515
|
-
|
|
4516
|
-
|
|
4789
|
+
memberCount?: number | undefined;
|
|
4790
|
+
}): string {
|
|
4517
4791
|
const truncate: (name: string) => string = (name: string): string => {
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4792
|
+
if (name.length <= MICROSOFT_TEAMS_CHAT_NAME_MAX_LENGTH) {
|
|
4793
|
+
return name;
|
|
4794
|
+
}
|
|
4795
|
+
|
|
4796
|
+
/*
|
|
4797
|
+
* Cut by UTF-16 code units, but never between the two halves of an
|
|
4798
|
+
* emoji: a lone surrogate makes Postgres refuse the whole jsonb write
|
|
4799
|
+
* that carries the name.
|
|
4800
|
+
*/
|
|
4801
|
+
return `${truncateToLength(name, MICROSOFT_TEAMS_CHAT_NAME_MAX_LENGTH - 1)}…`;
|
|
4521
4802
|
};
|
|
4522
4803
|
|
|
4523
4804
|
if (data.topic && data.topic.trim()) {
|
|
4524
4805
|
return truncate(data.topic.trim());
|
|
4525
4806
|
}
|
|
4526
4807
|
|
|
4527
|
-
const memberNames: Array<string> = data.memberNames
|
|
4528
|
-
(name: string) => {
|
|
4529
|
-
return Boolean(name && name.trim());
|
|
4530
|
-
},
|
|
4531
|
-
);
|
|
4808
|
+
const memberNames: Array<string> = this.getNonBlankNames(data.memberNames);
|
|
4532
4809
|
|
|
4533
4810
|
if (data.chatType === "personal") {
|
|
4534
4811
|
return memberNames[0] ? truncate(`${memberNames[0]}`) : "Personal chat";
|
|
@@ -4538,9 +4815,15 @@ All monitoring checks are passing normally.`;
|
|
|
4538
4815
|
return "Group chat";
|
|
4539
4816
|
}
|
|
4540
4817
|
|
|
4541
|
-
const
|
|
4542
|
-
|
|
4543
|
-
|
|
4818
|
+
const shownNames: Array<string> = memberNames.slice(
|
|
4819
|
+
0,
|
|
4820
|
+
MICROSOFT_TEAMS_CHAT_NAME_MEMBERS_SHOWN,
|
|
4821
|
+
);
|
|
4822
|
+
const memberCount: number = Math.max(
|
|
4823
|
+
data.memberCount || 0,
|
|
4824
|
+
memberNames.length,
|
|
4825
|
+
);
|
|
4826
|
+
const remainingCount: number = memberCount - shownNames.length;
|
|
4544
4827
|
|
|
4545
4828
|
if (remainingCount > 0) {
|
|
4546
4829
|
return truncate(`${shownNames.join(", ")} + ${remainingCount} more`);
|
|
@@ -4549,34 +4832,147 @@ All monitoring checks are passing normally.`;
|
|
|
4549
4832
|
return truncate(shownNames.join(", "));
|
|
4550
4833
|
}
|
|
4551
4834
|
|
|
4835
|
+
private static getNonBlankNames(names: Array<string>): Array<string> {
|
|
4836
|
+
return names.filter((name: string) => {
|
|
4837
|
+
return Boolean(name && name.trim());
|
|
4838
|
+
});
|
|
4839
|
+
}
|
|
4840
|
+
|
|
4552
4841
|
/*
|
|
4553
|
-
*
|
|
4554
|
-
*
|
|
4555
|
-
*
|
|
4842
|
+
* Builds the record to store for a chat that was just heard from, on top of
|
|
4843
|
+
* what is already stored. Whatever could not be read this time — the name
|
|
4844
|
+
* (Graph refused, failed, or was not asked) or the roster (the Bot Framework
|
|
4845
|
+
* call failed) — is taken from the stored record instead of being dropped:
|
|
4846
|
+
* a failed lookup must never turn a chat's real name back into member
|
|
4847
|
+
* names, or member names into a bare "Group chat".
|
|
4556
4848
|
*/
|
|
4557
|
-
|
|
4558
|
-
tenantId: string;
|
|
4849
|
+
public static buildCapturedChat(data: {
|
|
4559
4850
|
chatId: string;
|
|
4851
|
+
chatType: MicrosoftTeamsChatType;
|
|
4560
4852
|
serviceUrl?: string | undefined;
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4853
|
+
// conversation.name from the activity, when Teams sent one.
|
|
4854
|
+
activityTopic?: string | undefined;
|
|
4855
|
+
// The Graph answer; undefined when Graph was not asked.
|
|
4856
|
+
topicLookup?: MicrosoftTeamsChatTopicLookup | undefined;
|
|
4857
|
+
// The chat's human members; null when the roster could not be read.
|
|
4858
|
+
roster: {
|
|
4859
|
+
memberNames: Array<string>;
|
|
4860
|
+
memberAadObjectIds: Array<string>;
|
|
4861
|
+
} | null;
|
|
4862
|
+
storedChat?: MicrosoftTeamsChat | undefined;
|
|
4863
|
+
now: string;
|
|
4864
|
+
}): MicrosoftTeamsChat {
|
|
4865
|
+
const storedChat: MicrosoftTeamsChat | undefined = data.storedChat;
|
|
4866
|
+
const activityTopic: string = (data.activityTopic || "").trim();
|
|
4867
|
+
const lookupStatus: MicrosoftTeamsChatTopicLookupStatus | undefined =
|
|
4868
|
+
data.topicLookup?.status;
|
|
4869
|
+
const topicCleared: boolean =
|
|
4870
|
+
!activityTopic &&
|
|
4871
|
+
lookupStatus === MicrosoftTeamsChatTopicLookupStatus.NoTopic;
|
|
4872
|
+
|
|
4873
|
+
let topic: string | undefined = undefined;
|
|
4874
|
+
|
|
4875
|
+
if (activityTopic) {
|
|
4876
|
+
topic = activityTopic;
|
|
4877
|
+
} else if (lookupStatus === MicrosoftTeamsChatTopicLookupStatus.Found) {
|
|
4878
|
+
topic = data.topicLookup?.topic;
|
|
4879
|
+
} else if (!topicCleared) {
|
|
4880
|
+
topic = storedChat?.topic; // not read this time: keep the last known name.
|
|
4881
|
+
}
|
|
4882
|
+
|
|
4883
|
+
let memberNames: Array<string> | undefined = storedChat?.memberNames?.slice(
|
|
4884
|
+
0,
|
|
4885
|
+
MICROSOFT_TEAMS_CHAT_NAME_MEMBERS_SHOWN,
|
|
4886
|
+
);
|
|
4887
|
+
let memberCount: number | undefined = storedChat?.memberCount;
|
|
4888
|
+
let memberAadObjectIds: Array<string> =
|
|
4889
|
+
storedChat?.memberAadObjectIds || [];
|
|
4578
4890
|
|
|
4579
|
-
if (
|
|
4891
|
+
if (data.roster) {
|
|
4892
|
+
const names: Array<string> = this.getNonBlankNames(
|
|
4893
|
+
data.roster.memberNames,
|
|
4894
|
+
);
|
|
4895
|
+
memberNames = names.slice(0, MICROSOFT_TEAMS_CHAT_NAME_MEMBERS_SHOWN);
|
|
4896
|
+
memberCount = names.length;
|
|
4897
|
+
memberAadObjectIds = data.roster.memberAadObjectIds;
|
|
4898
|
+
}
|
|
4899
|
+
|
|
4900
|
+
let name: string;
|
|
4901
|
+
|
|
4902
|
+
if (topic || (memberNames && memberNames.length > 0)) {
|
|
4903
|
+
name = this.getChatDisplayName({
|
|
4904
|
+
chatType: data.chatType,
|
|
4905
|
+
topic: topic,
|
|
4906
|
+
memberNames: memberNames || [],
|
|
4907
|
+
memberCount: memberCount,
|
|
4908
|
+
});
|
|
4909
|
+
} else if (storedChat?.name && !(topicCleared && storedChat.topic)) {
|
|
4910
|
+
/*
|
|
4911
|
+
* Nothing to build a name from this time. The stored name is still the
|
|
4912
|
+
* best there is — unless it was the Teams name, and Teams just said the
|
|
4913
|
+
* chat no longer has one.
|
|
4914
|
+
*/
|
|
4915
|
+
name = storedChat.name;
|
|
4916
|
+
} else {
|
|
4917
|
+
name = this.getChatDisplayName({
|
|
4918
|
+
chatType: data.chatType,
|
|
4919
|
+
memberNames: [],
|
|
4920
|
+
});
|
|
4921
|
+
}
|
|
4922
|
+
|
|
4923
|
+
const chat: MicrosoftTeamsChat = {
|
|
4924
|
+
id: data.chatId,
|
|
4925
|
+
name: name,
|
|
4926
|
+
chatType: data.chatType,
|
|
4927
|
+
serviceUrl: data.serviceUrl,
|
|
4928
|
+
// When the chat was first connected; hearing from it again is not that.
|
|
4929
|
+
addedAt: storedChat?.addedAt || data.now,
|
|
4930
|
+
memberAadObjectIds: memberAadObjectIds,
|
|
4931
|
+
};
|
|
4932
|
+
|
|
4933
|
+
if (topic) {
|
|
4934
|
+
chat.topic = topic;
|
|
4935
|
+
}
|
|
4936
|
+
|
|
4937
|
+
if (memberNames !== undefined) {
|
|
4938
|
+
chat.memberNames = memberNames;
|
|
4939
|
+
}
|
|
4940
|
+
|
|
4941
|
+
if (memberCount !== undefined) {
|
|
4942
|
+
chat.memberCount = memberCount;
|
|
4943
|
+
}
|
|
4944
|
+
|
|
4945
|
+
return chat;
|
|
4946
|
+
}
|
|
4947
|
+
|
|
4948
|
+
/*
|
|
4949
|
+
* Returns true when every connected project of this tenant already has
|
|
4950
|
+
* this chat stored with the same service URL — i.e. there is nothing to
|
|
4951
|
+
* capture or refresh.
|
|
4952
|
+
*/
|
|
4953
|
+
private static async isChatCapturedForTenant(data: {
|
|
4954
|
+
tenantId: string;
|
|
4955
|
+
chatId: string;
|
|
4956
|
+
serviceUrl?: string | undefined;
|
|
4957
|
+
}): Promise<boolean> {
|
|
4958
|
+
const projectAuths: Array<WorkspaceProjectAuthToken> =
|
|
4959
|
+
await WorkspaceProjectAuthTokenService.findBy({
|
|
4960
|
+
query: {
|
|
4961
|
+
workspaceType: WorkspaceType.MicrosoftTeams,
|
|
4962
|
+
workspaceProjectId: data.tenantId,
|
|
4963
|
+
},
|
|
4964
|
+
select: {
|
|
4965
|
+
_id: true,
|
|
4966
|
+
miscData: true,
|
|
4967
|
+
},
|
|
4968
|
+
limit: LIMIT_MAX,
|
|
4969
|
+
skip: 0,
|
|
4970
|
+
props: {
|
|
4971
|
+
isRoot: true,
|
|
4972
|
+
},
|
|
4973
|
+
});
|
|
4974
|
+
|
|
4975
|
+
if (projectAuths.length === 0) {
|
|
4580
4976
|
return true; // no connected projects — nothing to capture into.
|
|
4581
4977
|
}
|
|
4582
4978
|
|
|
@@ -4604,6 +5000,21 @@ All monitoring checks are passing normally.`;
|
|
|
4604
5000
|
) {
|
|
4605
5001
|
return false;
|
|
4606
5002
|
}
|
|
5003
|
+
|
|
5004
|
+
/*
|
|
5005
|
+
* Group chats captured before member counts were stored were also
|
|
5006
|
+
* captured before OneUptime asked Graph for their name. Re-capture
|
|
5007
|
+
* them once: that stores the roster (so the name can fall back to the
|
|
5008
|
+
* members if the chat's name is ever removed), and reads the name if
|
|
5009
|
+
* the chat already lets OneUptime read it. Chats the app was added to
|
|
5010
|
+
* with an older manifest only allow that once the app is updated in the
|
|
5011
|
+
* chat, which sends no activity — Refresh Chats picks the name up then.
|
|
5012
|
+
* A roster that could not be read leaves the count unset, so the next
|
|
5013
|
+
* message tries again.
|
|
5014
|
+
*/
|
|
5015
|
+
if (chat.chatType === "groupChat" && chat.memberCount === undefined) {
|
|
5016
|
+
return false;
|
|
5017
|
+
}
|
|
4607
5018
|
}
|
|
4608
5019
|
|
|
4609
5020
|
return true;
|
|
@@ -4667,12 +5078,16 @@ All monitoring checks are passing normally.`;
|
|
|
4667
5078
|
}
|
|
4668
5079
|
|
|
4669
5080
|
// Resolve a human friendly name for the chat.
|
|
4670
|
-
const
|
|
4671
|
-
|
|
4672
|
-
|
|
5081
|
+
const activityTopic: string =
|
|
5082
|
+
typeof conversation["name"] === "string"
|
|
5083
|
+
? (conversation["name"] as string).trim()
|
|
5084
|
+
: "";
|
|
4673
5085
|
|
|
4674
|
-
|
|
4675
|
-
let
|
|
5086
|
+
// null when the roster could not be read.
|
|
5087
|
+
let roster: {
|
|
5088
|
+
memberNames: Array<string>;
|
|
5089
|
+
memberAadObjectIds: Array<string>;
|
|
5090
|
+
} | null = null;
|
|
4676
5091
|
|
|
4677
5092
|
try {
|
|
4678
5093
|
const botId: string | undefined =
|
|
@@ -4700,39 +5115,60 @@ All monitoring checks are passing normally.`;
|
|
|
4700
5115
|
},
|
|
4701
5116
|
);
|
|
4702
5117
|
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
5118
|
+
roster = {
|
|
5119
|
+
memberNames: humanMembers.map((member: TeamsChannelAccount) => {
|
|
5120
|
+
return member.name || "";
|
|
5121
|
+
}),
|
|
5122
|
+
/*
|
|
5123
|
+
* The Entra object id is what maps a chat member back to the
|
|
5124
|
+
* OneUptime user who connected that Teams account, so personal
|
|
5125
|
+
* chats can serve as direct-message delivery targets.
|
|
5126
|
+
*/
|
|
5127
|
+
memberAadObjectIds: humanMembers
|
|
5128
|
+
.map((member: TeamsChannelAccount) => {
|
|
5129
|
+
return member.aadObjectId || "";
|
|
5130
|
+
})
|
|
5131
|
+
.filter((aadObjectId: string) => {
|
|
5132
|
+
return Boolean(aadObjectId);
|
|
5133
|
+
}),
|
|
5134
|
+
};
|
|
4719
5135
|
} catch (err) {
|
|
4720
5136
|
logger.debug("Could not fetch chat members for chat name resolution");
|
|
4721
5137
|
logger.debug(err);
|
|
4722
5138
|
}
|
|
4723
5139
|
|
|
4724
|
-
const
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
5140
|
+
const tenantChat: {
|
|
5141
|
+
projectId: ObjectID | null;
|
|
5142
|
+
storedChat: MicrosoftTeamsChat | undefined;
|
|
5143
|
+
} = await this.getTenantChatContext({
|
|
5144
|
+
tenantId: tenantId,
|
|
5145
|
+
chatId: chatId,
|
|
5146
|
+
});
|
|
5147
|
+
|
|
5148
|
+
/*
|
|
5149
|
+
* Teams does not reliably put a group chat's name on its activities, so
|
|
5150
|
+
* a named group chat would otherwise be listed by its members. Graph has
|
|
5151
|
+
* the name; ask it. Personal chats have no name to find.
|
|
5152
|
+
*/
|
|
5153
|
+
let topicLookup: MicrosoftTeamsChatTopicLookup | undefined = undefined;
|
|
5154
|
+
|
|
5155
|
+
if (chatType === "groupChat" && !activityTopic && tenantChat.projectId) {
|
|
5156
|
+
topicLookup = await this.getGroupChatTopicFromGraph({
|
|
5157
|
+
projectId: tenantChat.projectId,
|
|
5158
|
+
chatId: chatId,
|
|
5159
|
+
});
|
|
5160
|
+
}
|
|
5161
|
+
|
|
5162
|
+
const chat: MicrosoftTeamsChat = this.buildCapturedChat({
|
|
5163
|
+
chatId: chatId,
|
|
4731
5164
|
chatType: chatType,
|
|
4732
5165
|
serviceUrl: activityServiceUrl,
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
5166
|
+
activityTopic: activityTopic,
|
|
5167
|
+
topicLookup: topicLookup,
|
|
5168
|
+
roster: roster,
|
|
5169
|
+
storedChat: tenantChat.storedChat,
|
|
5170
|
+
now: OneUptimeDate.getCurrentDate().toISOString(),
|
|
5171
|
+
});
|
|
4736
5172
|
|
|
4737
5173
|
await this.saveChatToProjectAuthTokens({
|
|
4738
5174
|
tenantId: tenantId,
|
|
@@ -4887,6 +5323,423 @@ All monitoring checks are passing normally.`;
|
|
|
4887
5323
|
}
|
|
4888
5324
|
}
|
|
4889
5325
|
|
|
5326
|
+
/*
|
|
5327
|
+
* What a bot activity needs to know about its tenant before storing a chat:
|
|
5328
|
+
* any project connected to the tenant (bot activities identify the tenant,
|
|
5329
|
+
* not the project, and every project of a tenant yields the same Graph app
|
|
5330
|
+
* token), and the chat as it is stored now, so a re-capture builds on it.
|
|
5331
|
+
*
|
|
5332
|
+
* A failed read throws: capturing without knowing what is stored would
|
|
5333
|
+
* overwrite a chat's real name with whatever this activity could supply.
|
|
5334
|
+
*/
|
|
5335
|
+
private static async getTenantChatContext(data: {
|
|
5336
|
+
tenantId: string;
|
|
5337
|
+
chatId: string;
|
|
5338
|
+
}): Promise<{
|
|
5339
|
+
projectId: ObjectID | null;
|
|
5340
|
+
storedChat: MicrosoftTeamsChat | undefined;
|
|
5341
|
+
}> {
|
|
5342
|
+
let projectId: ObjectID | null = null;
|
|
5343
|
+
let storedChat: MicrosoftTeamsChat | undefined = undefined;
|
|
5344
|
+
|
|
5345
|
+
const projectAuths: Array<WorkspaceProjectAuthToken> =
|
|
5346
|
+
await WorkspaceProjectAuthTokenService.findBy({
|
|
5347
|
+
query: {
|
|
5348
|
+
workspaceType: WorkspaceType.MicrosoftTeams,
|
|
5349
|
+
workspaceProjectId: data.tenantId,
|
|
5350
|
+
},
|
|
5351
|
+
select: {
|
|
5352
|
+
_id: true,
|
|
5353
|
+
projectId: true,
|
|
5354
|
+
miscData: true,
|
|
5355
|
+
},
|
|
5356
|
+
limit: LIMIT_MAX,
|
|
5357
|
+
skip: 0,
|
|
5358
|
+
props: {
|
|
5359
|
+
isRoot: true,
|
|
5360
|
+
},
|
|
5361
|
+
});
|
|
5362
|
+
|
|
5363
|
+
for (const projectAuth of projectAuths) {
|
|
5364
|
+
if (!projectId && projectAuth.projectId) {
|
|
5365
|
+
projectId = projectAuth.projectId;
|
|
5366
|
+
}
|
|
5367
|
+
|
|
5368
|
+
if (!storedChat) {
|
|
5369
|
+
storedChat = (projectAuth.miscData as MicrosoftTeamsMiscData)
|
|
5370
|
+
?.availableChats?.[data.chatId];
|
|
5371
|
+
}
|
|
5372
|
+
}
|
|
5373
|
+
|
|
5374
|
+
return { projectId: projectId, storedChat: storedChat };
|
|
5375
|
+
}
|
|
5376
|
+
|
|
5377
|
+
/*
|
|
5378
|
+
* Reads a group chat's name from Graph (GET /chats/{id}). Only group chats
|
|
5379
|
+
* are looked up: their Bot Framework conversation id is also their Graph
|
|
5380
|
+
* chat id, and they are the only chats that can be named.
|
|
5381
|
+
*
|
|
5382
|
+
* Never throws. A refusal comes back as PermissionDenied — the app-only
|
|
5383
|
+
* token needs ChatSettings.Read.Chat (granted per chat, and chats the app
|
|
5384
|
+
* was added to before the manifest requested it do not have it) or the
|
|
5385
|
+
* tenant-wide Chat.ReadBasic.WhereInstalled. Pass accessToken when looking
|
|
5386
|
+
* up many chats, so the token is fetched once rather than once per chat.
|
|
5387
|
+
*/
|
|
5388
|
+
@CaptureSpan()
|
|
5389
|
+
public static async getGroupChatTopicFromGraph(data: {
|
|
5390
|
+
projectId: ObjectID;
|
|
5391
|
+
chatId: string;
|
|
5392
|
+
accessToken?: string | undefined;
|
|
5393
|
+
}): Promise<MicrosoftTeamsChatTopicLookup> {
|
|
5394
|
+
if (!data.chatId) {
|
|
5395
|
+
return { status: MicrosoftTeamsChatTopicLookupStatus.Unknown };
|
|
5396
|
+
}
|
|
5397
|
+
|
|
5398
|
+
try {
|
|
5399
|
+
const accessToken: string =
|
|
5400
|
+
data.accessToken ||
|
|
5401
|
+
(await this.getValidAccessToken({
|
|
5402
|
+
authToken: "",
|
|
5403
|
+
projectId: data.projectId,
|
|
5404
|
+
}));
|
|
5405
|
+
|
|
5406
|
+
const response: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
5407
|
+
await API.get<JSONObject>({
|
|
5408
|
+
url: URL.fromString(
|
|
5409
|
+
`https://graph.microsoft.com/v1.0/chats/${encodeURIComponent(
|
|
5410
|
+
data.chatId,
|
|
5411
|
+
)}`,
|
|
5412
|
+
),
|
|
5413
|
+
headers: {
|
|
5414
|
+
Authorization: `Bearer ${accessToken}`,
|
|
5415
|
+
"Content-Type": "application/json",
|
|
5416
|
+
},
|
|
5417
|
+
options: {
|
|
5418
|
+
timeout: MICROSOFT_TEAMS_CHAT_TOPIC_LOOKUP_TIMEOUT_IN_MS,
|
|
5419
|
+
},
|
|
5420
|
+
});
|
|
5421
|
+
|
|
5422
|
+
if (response instanceof HTTPErrorResponse) {
|
|
5423
|
+
if (this.isGraphPermissionDeniedResponse(response)) {
|
|
5424
|
+
logger.debug(
|
|
5425
|
+
`Cannot read the name of Microsoft Teams chat ${data.chatId}: Microsoft Graph denied the request. The OneUptime app in that chat needs the ${MICROSOFT_TEAMS_CHAT_TOPIC_READ_PERMISSION} permission — update the app in the chat so Teams grants it.`,
|
|
5426
|
+
);
|
|
5427
|
+
return {
|
|
5428
|
+
status: MicrosoftTeamsChatTopicLookupStatus.PermissionDenied,
|
|
5429
|
+
};
|
|
5430
|
+
}
|
|
5431
|
+
|
|
5432
|
+
/*
|
|
5433
|
+
* A 404 for a chat the bot is in would mean the Bot Framework
|
|
5434
|
+
* conversation id is not the Graph chat id — worth seeing in
|
|
5435
|
+
* production logs, unlike a passing throttle or outage.
|
|
5436
|
+
*/
|
|
5437
|
+
if (response.statusCode === 404) {
|
|
5438
|
+
logger.warn(
|
|
5439
|
+
`Microsoft Graph has no chat with the id of Microsoft Teams chat ${data.chatId}, so its name cannot be read.`,
|
|
5440
|
+
);
|
|
5441
|
+
} else {
|
|
5442
|
+
logger.debug(`Could not read Microsoft Teams chat ${data.chatId}:`);
|
|
5443
|
+
logger.debug(response);
|
|
5444
|
+
}
|
|
5445
|
+
|
|
5446
|
+
return { status: MicrosoftTeamsChatTopicLookupStatus.Unknown };
|
|
5447
|
+
}
|
|
5448
|
+
|
|
5449
|
+
const topic: unknown = response.data?.["topic"];
|
|
5450
|
+
|
|
5451
|
+
if (typeof topic === "string" && topic.trim()) {
|
|
5452
|
+
return {
|
|
5453
|
+
status: MicrosoftTeamsChatTopicLookupStatus.Found,
|
|
5454
|
+
topic: topic.trim(),
|
|
5455
|
+
};
|
|
5456
|
+
}
|
|
5457
|
+
|
|
5458
|
+
return { status: MicrosoftTeamsChatTopicLookupStatus.NoTopic };
|
|
5459
|
+
} catch (err) {
|
|
5460
|
+
logger.debug(`Error reading Microsoft Teams chat ${data.chatId}:`);
|
|
5461
|
+
logger.debug(err);
|
|
5462
|
+
return { status: MicrosoftTeamsChatTopicLookupStatus.Unknown };
|
|
5463
|
+
}
|
|
5464
|
+
}
|
|
5465
|
+
|
|
5466
|
+
// Refreshes in progress, by project: a second click joins the first.
|
|
5467
|
+
private static chatNameRefreshesInFlight: Map<
|
|
5468
|
+
string,
|
|
5469
|
+
Promise<MicrosoftTeamsChatNameRefreshResult>
|
|
5470
|
+
> = new Map();
|
|
5471
|
+
|
|
5472
|
+
/*
|
|
5473
|
+
* What "Refresh Chats" does. Microsoft does not let an app list chats, but
|
|
5474
|
+
* it does let it read one it is in — so every stored group chat is re-read,
|
|
5475
|
+
* which fixes chats captured under their member names and picks up renames.
|
|
5476
|
+
*
|
|
5477
|
+
* A chat whose name was removed in Teams goes back to its member names when
|
|
5478
|
+
* they were stored with it; otherwise it keeps its current name, unless
|
|
5479
|
+
* that was the removed Teams name. A chat whose name could not be read is
|
|
5480
|
+
* left as it is and reported, so the page can say why.
|
|
5481
|
+
*
|
|
5482
|
+
* Concurrent refreshes of one project (within this App process) share a
|
|
5483
|
+
* single run, so a held-down button costs one pass over the chats, not one
|
|
5484
|
+
* per click.
|
|
5485
|
+
*/
|
|
5486
|
+
public static async refreshChatNamesForProject(data: {
|
|
5487
|
+
projectId: ObjectID;
|
|
5488
|
+
}): Promise<MicrosoftTeamsChatNameRefreshResult> {
|
|
5489
|
+
const key: string = data.projectId.toString();
|
|
5490
|
+
|
|
5491
|
+
const inFlight: Promise<MicrosoftTeamsChatNameRefreshResult> | undefined =
|
|
5492
|
+
this.chatNameRefreshesInFlight.get(key);
|
|
5493
|
+
|
|
5494
|
+
if (inFlight) {
|
|
5495
|
+
return inFlight;
|
|
5496
|
+
}
|
|
5497
|
+
|
|
5498
|
+
const refresh: Promise<MicrosoftTeamsChatNameRefreshResult> =
|
|
5499
|
+
this.runChatNameRefresh(data).finally(() => {
|
|
5500
|
+
this.chatNameRefreshesInFlight.delete(key);
|
|
5501
|
+
});
|
|
5502
|
+
|
|
5503
|
+
this.chatNameRefreshesInFlight.set(key, refresh);
|
|
5504
|
+
|
|
5505
|
+
return refresh;
|
|
5506
|
+
}
|
|
5507
|
+
|
|
5508
|
+
@CaptureSpan()
|
|
5509
|
+
private static async runChatNameRefresh(data: {
|
|
5510
|
+
projectId: ObjectID;
|
|
5511
|
+
}): Promise<MicrosoftTeamsChatNameRefreshResult> {
|
|
5512
|
+
const projectAuth: WorkspaceProjectAuthToken | null =
|
|
5513
|
+
await WorkspaceProjectAuthTokenService.getProjectAuth({
|
|
5514
|
+
projectId: data.projectId,
|
|
5515
|
+
workspaceType: WorkspaceType.MicrosoftTeams,
|
|
5516
|
+
});
|
|
5517
|
+
|
|
5518
|
+
const storedChats: Record<string, MicrosoftTeamsChat> =
|
|
5519
|
+
(projectAuth?.miscData as MicrosoftTeamsMiscData | undefined)
|
|
5520
|
+
?.availableChats || {};
|
|
5521
|
+
|
|
5522
|
+
const result: MicrosoftTeamsChatNameRefreshResult = {
|
|
5523
|
+
chats: { ...storedChats },
|
|
5524
|
+
permissionDeniedChatIds: [],
|
|
5525
|
+
failedChatIds: [],
|
|
5526
|
+
};
|
|
5527
|
+
|
|
5528
|
+
const tenantId: string | undefined = projectAuth?.workspaceProjectId;
|
|
5529
|
+
|
|
5530
|
+
const groupChats: Array<MicrosoftTeamsChat> = Object.values(
|
|
5531
|
+
storedChats,
|
|
5532
|
+
).filter((chat: MicrosoftTeamsChat) => {
|
|
5533
|
+
return Boolean(chat && chat.id && chat.chatType === "groupChat");
|
|
5534
|
+
});
|
|
5535
|
+
|
|
5536
|
+
if (!tenantId || groupChats.length === 0) {
|
|
5537
|
+
return result;
|
|
5538
|
+
}
|
|
5539
|
+
|
|
5540
|
+
/*
|
|
5541
|
+
* One token for every lookup. Without one nothing can be read, and that
|
|
5542
|
+
* is a failure the caller must see — not a refresh that silently changed
|
|
5543
|
+
* nothing.
|
|
5544
|
+
*/
|
|
5545
|
+
const accessToken: string = await this.getValidAccessToken({
|
|
5546
|
+
authToken: "",
|
|
5547
|
+
projectId: data.projectId,
|
|
5548
|
+
});
|
|
5549
|
+
|
|
5550
|
+
const updates: Record<string, MicrosoftTeamsChatNameUpdate> = {};
|
|
5551
|
+
|
|
5552
|
+
for (
|
|
5553
|
+
let index: number = 0;
|
|
5554
|
+
index < groupChats.length;
|
|
5555
|
+
index += MICROSOFT_TEAMS_CHAT_TOPIC_LOOKUP_CONCURRENCY
|
|
5556
|
+
) {
|
|
5557
|
+
const batch: Array<MicrosoftTeamsChat> = groupChats.slice(
|
|
5558
|
+
index,
|
|
5559
|
+
index + MICROSOFT_TEAMS_CHAT_TOPIC_LOOKUP_CONCURRENCY,
|
|
5560
|
+
);
|
|
5561
|
+
|
|
5562
|
+
const lookups: Array<MicrosoftTeamsChatTopicLookup> = await Promise.all(
|
|
5563
|
+
batch.map((chat: MicrosoftTeamsChat) => {
|
|
5564
|
+
return this.getGroupChatTopicFromGraph({
|
|
5565
|
+
projectId: data.projectId,
|
|
5566
|
+
chatId: chat.id,
|
|
5567
|
+
accessToken: accessToken,
|
|
5568
|
+
});
|
|
5569
|
+
}),
|
|
5570
|
+
);
|
|
5571
|
+
|
|
5572
|
+
batch.forEach((chat: MicrosoftTeamsChat, batchIndex: number) => {
|
|
5573
|
+
const lookup: MicrosoftTeamsChatTopicLookup = lookups[batchIndex]!;
|
|
5574
|
+
|
|
5575
|
+
if (
|
|
5576
|
+
lookup.status === MicrosoftTeamsChatTopicLookupStatus.PermissionDenied
|
|
5577
|
+
) {
|
|
5578
|
+
result.permissionDeniedChatIds.push(chat.id);
|
|
5579
|
+
return;
|
|
5580
|
+
}
|
|
5581
|
+
|
|
5582
|
+
if (lookup.status === MicrosoftTeamsChatTopicLookupStatus.Unknown) {
|
|
5583
|
+
result.failedChatIds.push(chat.id);
|
|
5584
|
+
return;
|
|
5585
|
+
}
|
|
5586
|
+
|
|
5587
|
+
const update: MicrosoftTeamsChatNameUpdate = this.getChatNameUpdate({
|
|
5588
|
+
chat: chat,
|
|
5589
|
+
lookup: lookup,
|
|
5590
|
+
});
|
|
5591
|
+
|
|
5592
|
+
if (update.name !== chat.name || update.topic !== chat.topic) {
|
|
5593
|
+
updates[chat.id] = update;
|
|
5594
|
+
}
|
|
5595
|
+
});
|
|
5596
|
+
}
|
|
5597
|
+
|
|
5598
|
+
if (Object.keys(updates).length > 0) {
|
|
5599
|
+
await this.renameChatsInProjectAuthTokens({
|
|
5600
|
+
tenantId: tenantId,
|
|
5601
|
+
chatNames: updates,
|
|
5602
|
+
});
|
|
5603
|
+
}
|
|
5604
|
+
|
|
5605
|
+
/*
|
|
5606
|
+
* What is stored now, whether or not anything was renamed: a chat
|
|
5607
|
+
* removed while names were being read is gone, and is not reported.
|
|
5608
|
+
*/
|
|
5609
|
+
result.chats = await this.getChatsForProject({
|
|
5610
|
+
projectId: data.projectId,
|
|
5611
|
+
});
|
|
5612
|
+
|
|
5613
|
+
return result;
|
|
5614
|
+
}
|
|
5615
|
+
|
|
5616
|
+
// The name a stored group chat gets from a lookup that Graph answered.
|
|
5617
|
+
private static getChatNameUpdate(data: {
|
|
5618
|
+
chat: MicrosoftTeamsChat;
|
|
5619
|
+
lookup: MicrosoftTeamsChatTopicLookup;
|
|
5620
|
+
}): MicrosoftTeamsChatNameUpdate {
|
|
5621
|
+
const chat: MicrosoftTeamsChat = data.chat;
|
|
5622
|
+
|
|
5623
|
+
if (
|
|
5624
|
+
data.lookup.status === MicrosoftTeamsChatTopicLookupStatus.Found &&
|
|
5625
|
+
data.lookup.topic
|
|
5626
|
+
) {
|
|
5627
|
+
return {
|
|
5628
|
+
name: this.getChatDisplayName({
|
|
5629
|
+
chatType: chat.chatType,
|
|
5630
|
+
topic: data.lookup.topic,
|
|
5631
|
+
memberNames: [],
|
|
5632
|
+
}),
|
|
5633
|
+
topic: data.lookup.topic,
|
|
5634
|
+
};
|
|
5635
|
+
}
|
|
5636
|
+
|
|
5637
|
+
// The chat has no name in Teams.
|
|
5638
|
+
if (chat.memberNames && chat.memberNames.length > 0) {
|
|
5639
|
+
return {
|
|
5640
|
+
name: this.getChatDisplayName({
|
|
5641
|
+
chatType: chat.chatType,
|
|
5642
|
+
memberNames: chat.memberNames,
|
|
5643
|
+
memberCount: chat.memberCount,
|
|
5644
|
+
}),
|
|
5645
|
+
};
|
|
5646
|
+
}
|
|
5647
|
+
|
|
5648
|
+
/*
|
|
5649
|
+
* No members to name it after. Keep the current name — unless it was the
|
|
5650
|
+
* Teams name that has just been removed.
|
|
5651
|
+
*/
|
|
5652
|
+
return {
|
|
5653
|
+
name: chat.topic
|
|
5654
|
+
? this.getChatDisplayName({ chatType: chat.chatType, memberNames: [] })
|
|
5655
|
+
: chat.name,
|
|
5656
|
+
};
|
|
5657
|
+
}
|
|
5658
|
+
|
|
5659
|
+
/*
|
|
5660
|
+
* Sets the name (and the Teams name it came from) of chats already stored
|
|
5661
|
+
* for a tenant, on every connected project. Only those fields are written,
|
|
5662
|
+
* onto each record as it is now — a chat removed or re-captured while names
|
|
5663
|
+
* were being looked up is neither resurrected nor rolled back.
|
|
5664
|
+
*/
|
|
5665
|
+
@CaptureSpan()
|
|
5666
|
+
public static async renameChatsInProjectAuthTokens(data: {
|
|
5667
|
+
tenantId: string;
|
|
5668
|
+
chatNames: Record<string, MicrosoftTeamsChatNameUpdate>;
|
|
5669
|
+
}): Promise<void> {
|
|
5670
|
+
const projectAuths: Array<WorkspaceProjectAuthToken> =
|
|
5671
|
+
await WorkspaceProjectAuthTokenService.findBy({
|
|
5672
|
+
query: {
|
|
5673
|
+
workspaceType: WorkspaceType.MicrosoftTeams,
|
|
5674
|
+
workspaceProjectId: data.tenantId,
|
|
5675
|
+
},
|
|
5676
|
+
select: {
|
|
5677
|
+
_id: true,
|
|
5678
|
+
miscData: true,
|
|
5679
|
+
},
|
|
5680
|
+
limit: LIMIT_MAX,
|
|
5681
|
+
skip: 0,
|
|
5682
|
+
props: {
|
|
5683
|
+
isRoot: true,
|
|
5684
|
+
},
|
|
5685
|
+
});
|
|
5686
|
+
|
|
5687
|
+
for (const projectAuth of projectAuths) {
|
|
5688
|
+
const miscData: MicrosoftTeamsMiscData = {
|
|
5689
|
+
...((projectAuth.miscData as MicrosoftTeamsMiscData) || {}),
|
|
5690
|
+
} as MicrosoftTeamsMiscData;
|
|
5691
|
+
|
|
5692
|
+
const availableChats: Record<string, MicrosoftTeamsChat> = {
|
|
5693
|
+
...(miscData.availableChats || {}),
|
|
5694
|
+
};
|
|
5695
|
+
|
|
5696
|
+
let changed: boolean = false;
|
|
5697
|
+
|
|
5698
|
+
for (const [chatId, update] of Object.entries(data.chatNames)) {
|
|
5699
|
+
const existingChat: MicrosoftTeamsChat | undefined =
|
|
5700
|
+
availableChats[chatId];
|
|
5701
|
+
|
|
5702
|
+
if (
|
|
5703
|
+
!existingChat ||
|
|
5704
|
+
(existingChat.name === update.name &&
|
|
5705
|
+
existingChat.topic === update.topic)
|
|
5706
|
+
) {
|
|
5707
|
+
continue;
|
|
5708
|
+
}
|
|
5709
|
+
|
|
5710
|
+
const renamedChat: MicrosoftTeamsChat = {
|
|
5711
|
+
...existingChat,
|
|
5712
|
+
name: update.name,
|
|
5713
|
+
};
|
|
5714
|
+
|
|
5715
|
+
if (update.topic) {
|
|
5716
|
+
renamedChat.topic = update.topic;
|
|
5717
|
+
} else {
|
|
5718
|
+
delete renamedChat.topic;
|
|
5719
|
+
}
|
|
5720
|
+
|
|
5721
|
+
availableChats[chatId] = renamedChat;
|
|
5722
|
+
changed = true;
|
|
5723
|
+
}
|
|
5724
|
+
|
|
5725
|
+
if (!changed) {
|
|
5726
|
+
continue;
|
|
5727
|
+
}
|
|
5728
|
+
|
|
5729
|
+
miscData.availableChats = availableChats;
|
|
5730
|
+
|
|
5731
|
+
await WorkspaceProjectAuthTokenService.updateOneById({
|
|
5732
|
+
id: projectAuth.id!,
|
|
5733
|
+
data: {
|
|
5734
|
+
miscData: miscData,
|
|
5735
|
+
},
|
|
5736
|
+
props: {
|
|
5737
|
+
isRoot: true,
|
|
5738
|
+
},
|
|
5739
|
+
});
|
|
5740
|
+
}
|
|
5741
|
+
}
|
|
5742
|
+
|
|
4890
5743
|
@CaptureSpan()
|
|
4891
5744
|
public static async getChatsForProject(data: {
|
|
4892
5745
|
projectId: ObjectID;
|
|
@@ -5495,8 +6348,16 @@ All monitoring checks are passing normally.`;
|
|
|
5495
6348
|
}),
|
|
5496
6349
|
);
|
|
5497
6350
|
|
|
5498
|
-
|
|
5499
|
-
|
|
6351
|
+
try {
|
|
6352
|
+
// Run the activity through our activity handler
|
|
6353
|
+
await activityHandler.run(context);
|
|
6354
|
+
} catch (error) {
|
|
6355
|
+
// Never answer Teams with a 500; see recoverFromFailedTurn.
|
|
6356
|
+
await MicrosoftTeamsUtil.recoverFromFailedTurn({
|
|
6357
|
+
turnContext: context,
|
|
6358
|
+
error: error,
|
|
6359
|
+
});
|
|
6360
|
+
}
|
|
5500
6361
|
});
|
|
5501
6362
|
|
|
5502
6363
|
logger.debug("Bot Framework activity processed successfully");
|
|
@@ -6018,9 +6879,8 @@ All monitoring checks are passing normally.`;
|
|
|
6018
6879
|
const body: JSONObject = msg["body"] as JSONObject;
|
|
6019
6880
|
let text: string = (body?.["content"] as string) || "";
|
|
6020
6881
|
|
|
6021
|
-
//
|
|
6022
|
-
text = text.
|
|
6023
|
-
text = text.trim();
|
|
6882
|
+
// Teams message bodies are HTML.
|
|
6883
|
+
text = this.stripHtmlTags(text).trim();
|
|
6024
6884
|
|
|
6025
6885
|
// Skip empty messages
|
|
6026
6886
|
if (!text) {
|