@oneuptime/common 14.0.9 → 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.
Files changed (383) hide show
  1. package/Models/DatabaseModels/AutoRemediationSuggestion.ts +60 -0
  2. package/Models/DatabaseModels/CephCluster.ts +213 -0
  3. package/Models/DatabaseModels/DatabaseServer.ts +213 -0
  4. package/Models/DatabaseModels/DockerHost.ts +213 -0
  5. package/Models/DatabaseModels/DockerSwarmCluster.ts +213 -0
  6. package/Models/DatabaseModels/GlobalConfig.ts +1 -1
  7. package/Models/DatabaseModels/Host.ts +213 -0
  8. package/Models/DatabaseModels/Index.ts +2 -0
  9. package/Models/DatabaseModels/PodmanHost.ts +213 -0
  10. package/Models/DatabaseModels/ProxmoxCluster.ts +213 -0
  11. package/Models/DatabaseModels/ResourceAiAgent.ts +419 -0
  12. package/Models/DatabaseModels/RunnerJob.ts +144 -0
  13. package/Models/DatabaseModels/VMwareVCenter.ts +213 -0
  14. package/Server/API/AutoRemediationAPI.ts +392 -1
  15. package/Server/API/ResourceAiAccessAPI.ts +1669 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.ts +423 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  18. package/Server/Infrastructure/Semaphore.ts +22 -0
  19. package/Server/Middleware/TelemetryIngest.ts +15 -5
  20. package/Server/Services/AnalyticsDatabaseService.ts +45 -1
  21. package/Server/Services/AutoRemediationRuleEngineService.ts +940 -112
  22. package/Server/Services/CephClusterService.ts +109 -1
  23. package/Server/Services/DatabaseServerService.ts +116 -1
  24. package/Server/Services/DockerHostService.ts +109 -1
  25. package/Server/Services/DockerSwarmClusterService.ts +113 -1
  26. package/Server/Services/HostService.ts +126 -4
  27. package/Server/Services/MetricRecordingRuleService.ts +47 -0
  28. package/Server/Services/PodmanHostService.ts +109 -1
  29. package/Server/Services/ProxmoxClusterService.ts +110 -1
  30. package/Server/Services/ResourceAiAccessService.ts +1439 -0
  31. package/Server/Services/ResourceAiAgentJobService.ts +202 -0
  32. package/Server/Services/ResourceAiAgentService.ts +2432 -0
  33. package/Server/Services/RunnerJobService.ts +611 -4
  34. package/Server/Services/TelemetryUsageBillingService.ts +28 -0
  35. package/Server/Services/TraceRecordingRuleService.ts +33 -0
  36. package/Server/Services/VMwareVCenterService.ts +110 -1
  37. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +1434 -32
  38. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +935 -21
  39. package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +25 -1
  40. package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +577 -0
  41. package/Server/Utils/AI/ResourceAccess/ResourceAccessContext.ts +271 -0
  42. package/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.ts +45 -0
  43. package/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.ts +964 -0
  44. package/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.ts +333 -0
  45. package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +873 -0
  46. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +72 -2
  47. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +72 -5
  48. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +72 -5
  49. package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +396 -13
  50. package/Server/Utils/AutoRemediation/RemediationVerifier.ts +35 -2
  51. package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +9 -1
  52. package/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.ts +920 -0
  53. package/Server/Utils/SessionReplay/SessionReplayUsage.ts +84 -6
  54. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +35 -15
  55. package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +33 -15
  56. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +21 -1
  57. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +298 -224
  58. package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +35 -15
  59. package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +389 -175
  60. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +366 -143
  61. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.ts +163 -0
  62. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.ts +396 -0
  63. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.ts +418 -0
  64. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.ts +152 -0
  65. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.ts +251 -0
  66. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.ts +214 -0
  67. package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +93 -0
  68. package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +18 -6
  69. package/Tests/App/Dashboard/InvestigationInfrastructureTools.test.tsx +506 -0
  70. package/Tests/App/Dashboard/RemediationSuggestionCardDescription.test.tsx +209 -0
  71. package/Tests/App/Dashboard/RemediationSuggestionCardResource.test.tsx +317 -0
  72. package/Tests/App/Dashboard/ResourceAiAccessSettingsUtil.test.ts +921 -0
  73. package/Tests/App/Dashboard/ResourceAiAgentInstall.test.ts +860 -0
  74. package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +1721 -0
  75. package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +1002 -0
  76. package/Tests/App/Dashboard/ResourceAiInsightsPage.test.tsx +931 -0
  77. package/Tests/App/Dashboard/ResourceAiNavigation.test.tsx +575 -0
  78. package/Tests/App/Dashboard/RunbookStepTypeMaps.test.ts +38 -7
  79. package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +33 -1
  80. package/Tests/Models/DatabaseModels/ResourceAiAccessColumns.test.ts +738 -0
  81. package/Tests/Models/DatabaseModels/ResourceAiAgentModel.test.ts +842 -0
  82. package/Tests/Server/API/AutoRemediationApproveResourceRound.test.ts +835 -0
  83. package/Tests/Server/API/ResourceAiAccessAPI.test.ts +2730 -0
  84. package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +60 -0
  85. package/Tests/Server/Infrastructure/Postgres/AddResourceAiAgentsMigration.test.ts +659 -0
  86. package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +31 -0
  87. package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +63 -5
  88. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +103 -5
  89. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +19 -1
  90. package/Tests/Server/Services/AutoRemediationResourceRuleEngine.test.ts +1279 -0
  91. package/Tests/Server/Services/DatabaseServerService.test.ts +55 -0
  92. package/Tests/Server/Services/GroupTelemetryUsageExcludeNames.test.ts +299 -0
  93. package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +44 -0
  94. package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +45 -6
  95. package/Tests/Server/Services/RecordingRuleReservedMetricName.test.ts +171 -0
  96. package/Tests/Server/Services/ResourceAiAccessChangeAuthorization.test.ts +256 -0
  97. package/Tests/Server/Services/ResourceAiAccessService.test.ts +1373 -0
  98. package/Tests/Server/Services/ResourceAiAgentJobService.test.ts +375 -0
  99. package/Tests/Server/Services/ResourceAiAgentServiceHelpers.test.ts +1114 -0
  100. package/Tests/Server/Services/ResourceAiAgentServiceLifecycle.test.ts +1050 -0
  101. package/Tests/Server/Services/ResourceAiAgentServiceRegister.test.ts +2251 -0
  102. package/Tests/Server/Services/ResourceAiSettingsCreate.test.ts +373 -0
  103. package/Tests/Server/Services/ResourceAiSettingsPermission.test.ts +1042 -0
  104. package/Tests/Server/Services/ResourceServiceDeleteCleansUpAi.test.ts +319 -0
  105. package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +105 -0
  106. package/Tests/Server/Services/RunnerJobEnqueueResourceCommand.test.ts +986 -0
  107. package/Tests/Server/Services/RunnerJobResourceCommandLane.test.ts +211 -0
  108. package/Tests/Server/Services/RunnerJobResourceCommandTimeoutAndRedaction.test.ts +352 -0
  109. package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +218 -0
  110. package/Tests/Server/TestingUtils/Services/FakeRunnerJobCount.ts +145 -0
  111. package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +453 -0
  112. package/Tests/Server/Utils/AI/InvestigationInfrastructureReport.test.ts +721 -0
  113. package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +94 -1
  114. package/Tests/Server/Utils/AI/RemediationCommandToolsResource.test.ts +1530 -0
  115. package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +1249 -0
  116. package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +117 -0
  117. package/Tests/Server/Utils/AI/RemediationResourceCopyParity.test.ts +463 -0
  118. package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +722 -0
  119. package/Tests/Server/Utils/AI/ResourceAccess/ResourceAccessContext.test.ts +266 -0
  120. package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.test.ts +1220 -0
  121. package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.test.ts +569 -0
  122. package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +830 -0
  123. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorResource.test.ts +717 -0
  124. package/Tests/Server/Utils/AutoRemediation/RemediationVerifierResourceFollowUp.test.ts +338 -0
  125. package/Tests/Server/Utils/Monitor/Criteria/SessionReplayBudgetTemplateCriteria.test.ts +422 -0
  126. package/Tests/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.test.ts +1647 -0
  127. package/Tests/Server/Utils/SessionReplay/SessionReplayUsage.test.ts +143 -1
  128. package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +33 -3
  129. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsAccountNotLinked.test.ts +1093 -0
  130. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.test.ts +1049 -0
  131. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.test.ts +1676 -0
  132. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCards.test.ts +2884 -0
  133. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.test.ts +2490 -0
  134. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmit.test.ts +2293 -0
  135. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmitServerTimezone.test.ts +386 -0
  136. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.test.ts +1477 -0
  137. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.test.ts +1967 -0
  138. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsStripHtmlTags.test.ts +92 -0
  139. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsSubmittedFormRemoval.test.ts +1819 -0
  140. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.test.ts +1033 -0
  141. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezoneServerZone.test.ts +610 -0
  142. package/Tests/Server/Utils/Workspace/MicrosoftTeamsBotMessageHandling.test.ts +2610 -0
  143. package/Tests/Server/Utils/Workspace/MicrosoftTeamsCreateCommandsEndToEnd.test.ts +4672 -0
  144. package/Tests/Server/Utils/Workspace/WorkspaceCreateProjectReferences.test.ts +190 -65
  145. package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +10 -4
  146. package/Tests/Types/AutoRemediation/AiRemediationCommandPlanResourceCommand.test.ts +305 -0
  147. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +277 -13
  148. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +113 -0
  149. package/Tests/Types/Monitor/RumAlertTemplates.test.ts +773 -2
  150. package/Tests/Types/ResourceAiAgent/AiResourceType.test.ts +419 -0
  151. package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +517 -0
  152. package/Tests/Types/Runbook/RunbookStepType.test.ts +147 -8
  153. package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +769 -1
  154. package/Tests/Utils/AiRemediation/Resource/CephCommandPolicy.test.ts +1653 -0
  155. package/Tests/Utils/AiRemediation/Resource/CephOutputRedaction.test.ts +204 -0
  156. package/Tests/Utils/AiRemediation/Resource/DatabaseCommandPolicy.test.ts +1077 -0
  157. package/Tests/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.test.ts +558 -0
  158. package/Tests/Utils/AiRemediation/Resource/DatabaseQueryRedactor.test.ts +834 -0
  159. package/Tests/Utils/AiRemediation/Resource/DockerCliGrammar.test.ts +747 -0
  160. package/Tests/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.test.ts +1259 -0
  161. package/Tests/Utils/AiRemediation/Resource/DockerOutputRedaction.test.ts +386 -0
  162. package/Tests/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.test.ts +782 -0
  163. package/Tests/Utils/AiRemediation/Resource/GovcCommandPolicy.test.ts +2259 -0
  164. package/Tests/Utils/AiRemediation/Resource/HostCommandPolicy.test.ts +2019 -0
  165. package/Tests/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.test.ts +2497 -0
  166. package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicy.test.ts +1305 -0
  167. package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.test.ts +585 -0
  168. package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactor.test.ts +334 -0
  169. package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactorCopyParity.test.ts +98 -0
  170. package/Tests/Utils/AiRemediation/Resource/ResourcePolicyImportClosure.test.ts +391 -0
  171. package/Tests/Utils/AiRemediation/ResourceAiAgentPolicyCopyParity.test.ts +497 -0
  172. package/Tests/Utils/SessionReplay/SessionReplayBudgetMetricType.test.ts +383 -0
  173. package/Types/AI/ResourceAiAccessApi.ts +140 -0
  174. package/Types/AI/ResourceAiAccessPermissions.ts +126 -0
  175. package/Types/AutoRemediation/AiRemediationCommandPlan.ts +183 -2
  176. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +55 -22
  177. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +35 -3
  178. package/Types/Monitor/RumAlertTemplates.ts +351 -4
  179. package/Types/ResourceAiAgent/AiResourceType.ts +310 -0
  180. package/Types/ResourceAiAgent/ResourceAiAccess.ts +574 -0
  181. package/Types/Rum/SessionReplayBudgetMetricType.ts +47 -0
  182. package/Types/Runbook/RunbookStepType.ts +29 -0
  183. package/Types/Telemetry/TelemetryIngestSurface.ts +14 -2
  184. package/Utils/AI/InvestigationReport.ts +121 -15
  185. package/Utils/AiRemediation/Resource/CephCommandPolicy.ts +1936 -0
  186. package/Utils/AiRemediation/Resource/DatabaseCommandPolicy.ts +166 -0
  187. package/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.ts +1532 -0
  188. package/Utils/AiRemediation/Resource/DatabaseQueryRedactor.ts +1394 -0
  189. package/Utils/AiRemediation/Resource/DockerCliGrammar.ts +1839 -0
  190. package/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.ts +490 -0
  191. package/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.ts +687 -0
  192. package/Utils/AiRemediation/Resource/GovcCommandPolicy.ts +2096 -0
  193. package/Utils/AiRemediation/Resource/HostCommandPolicy.ts +2982 -0
  194. package/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.ts +1679 -0
  195. package/Utils/AiRemediation/Resource/ResourceCommandPolicy.ts +851 -0
  196. package/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.ts +593 -0
  197. package/Utils/AiRemediation/Resource/ResourceOutputRedactor.ts +2812 -0
  198. package/Utils/SessionReplay/SessionReplayBudgetMetricType.ts +184 -0
  199. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +62 -0
  200. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -1
  201. package/build/dist/Models/DatabaseModels/CephCluster.js +219 -0
  202. package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
  203. package/build/dist/Models/DatabaseModels/DatabaseServer.js +219 -0
  204. package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
  205. package/build/dist/Models/DatabaseModels/DockerHost.js +219 -0
  206. package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
  207. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +219 -0
  208. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
  209. package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
  210. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  211. package/build/dist/Models/DatabaseModels/Host.js +219 -0
  212. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  213. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  214. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  215. package/build/dist/Models/DatabaseModels/PodmanHost.js +219 -0
  216. package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
  217. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +219 -0
  218. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
  219. package/build/dist/Models/DatabaseModels/ResourceAiAgent.js +439 -0
  220. package/build/dist/Models/DatabaseModels/ResourceAiAgent.js.map +1 -0
  221. package/build/dist/Models/DatabaseModels/RunnerJob.js +145 -0
  222. package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
  223. package/build/dist/Models/DatabaseModels/VMwareVCenter.js +219 -0
  224. package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
  225. package/build/dist/Server/API/AutoRemediationAPI.js +231 -1
  226. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
  227. package/build/dist/Server/API/ResourceAiAccessAPI.js +1119 -0
  228. package/build/dist/Server/API/ResourceAiAccessAPI.js.map +1 -0
  229. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js +168 -0
  230. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js.map +1 -0
  231. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  232. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  233. package/build/dist/Server/Infrastructure/Semaphore.js +6 -0
  234. package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
  235. package/build/dist/Server/Middleware/TelemetryIngest.js +12 -5
  236. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  237. package/build/dist/Server/Services/AnalyticsDatabaseService.js +26 -1
  238. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  239. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +601 -3
  240. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
  241. package/build/dist/Server/Services/CephClusterService.js +104 -0
  242. package/build/dist/Server/Services/CephClusterService.js.map +1 -1
  243. package/build/dist/Server/Services/DatabaseServerService.js +99 -0
  244. package/build/dist/Server/Services/DatabaseServerService.js.map +1 -1
  245. package/build/dist/Server/Services/DockerHostService.js +104 -0
  246. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  247. package/build/dist/Server/Services/DockerSwarmClusterService.js +104 -0
  248. package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
  249. package/build/dist/Server/Services/HostService.js +114 -2
  250. package/build/dist/Server/Services/HostService.js.map +1 -1
  251. package/build/dist/Server/Services/MetricRecordingRuleService.js +46 -0
  252. package/build/dist/Server/Services/MetricRecordingRuleService.js.map +1 -1
  253. package/build/dist/Server/Services/PodmanHostService.js +104 -0
  254. package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
  255. package/build/dist/Server/Services/ProxmoxClusterService.js +104 -0
  256. package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
  257. package/build/dist/Server/Services/ResourceAiAccessService.js +1028 -0
  258. package/build/dist/Server/Services/ResourceAiAccessService.js.map +1 -0
  259. package/build/dist/Server/Services/ResourceAiAgentJobService.js +173 -0
  260. package/build/dist/Server/Services/ResourceAiAgentJobService.js.map +1 -0
  261. package/build/dist/Server/Services/ResourceAiAgentService.js +1687 -0
  262. package/build/dist/Server/Services/ResourceAiAgentService.js.map +1 -0
  263. package/build/dist/Server/Services/RunnerJobService.js +344 -5
  264. package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
  265. package/build/dist/Server/Services/TelemetryUsageBillingService.js +26 -0
  266. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  267. package/build/dist/Server/Services/TraceRecordingRuleService.js +37 -0
  268. package/build/dist/Server/Services/TraceRecordingRuleService.js.map +1 -1
  269. package/build/dist/Server/Services/VMwareVCenterService.js +104 -0
  270. package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -1
  271. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +1029 -30
  272. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
  273. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +633 -28
  274. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  275. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +21 -1
  276. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
  277. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +330 -0
  278. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -0
  279. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js +160 -0
  280. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js.map +1 -0
  281. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js +33 -0
  282. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js.map +1 -0
  283. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js +640 -0
  284. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js.map +1 -0
  285. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js +226 -0
  286. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js.map +1 -0
  287. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +600 -0
  288. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -0
  289. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +50 -4
  290. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  291. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +55 -4
  292. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  293. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +55 -4
  294. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  295. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +290 -13
  296. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
  297. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +29 -1
  298. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -1
  299. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +9 -1
  300. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
  301. package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js +627 -0
  302. package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js.map +1 -0
  303. package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js +60 -5
  304. package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js.map +1 -1
  305. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +19 -15
  306. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
  307. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +19 -15
  308. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
  309. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +17 -1
  310. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
  311. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +183 -209
  312. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
  313. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +19 -15
  314. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
  315. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +233 -167
  316. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -1
  317. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +263 -110
  318. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  319. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js +129 -0
  320. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js.map +1 -0
  321. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js +266 -0
  322. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js.map +1 -0
  323. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js +258 -0
  324. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js.map +1 -0
  325. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js +104 -0
  326. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js.map +1 -0
  327. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js +183 -0
  328. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js.map +1 -0
  329. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js +123 -0
  330. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js.map +1 -0
  331. package/build/dist/Types/AI/ResourceAiAccessApi.js +30 -0
  332. package/build/dist/Types/AI/ResourceAiAccessApi.js.map +1 -0
  333. package/build/dist/Types/AI/ResourceAiAccessPermissions.js +98 -0
  334. package/build/dist/Types/AI/ResourceAiAccessPermissions.js.map +1 -0
  335. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +116 -29
  336. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
  337. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +47 -21
  338. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  339. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +5 -0
  340. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  341. package/build/dist/Types/Monitor/RumAlertTemplates.js +199 -3
  342. package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
  343. package/build/dist/Types/ResourceAiAgent/AiResourceType.js +242 -0
  344. package/build/dist/Types/ResourceAiAgent/AiResourceType.js.map +1 -0
  345. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +275 -0
  346. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -0
  347. package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js +45 -0
  348. package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js.map +1 -0
  349. package/build/dist/Types/Runbook/RunbookStepType.js +27 -0
  350. package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
  351. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +13 -2
  352. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
  353. package/build/dist/Utils/AI/InvestigationReport.js +71 -11
  354. package/build/dist/Utils/AI/InvestigationReport.js.map +1 -1
  355. package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js +1462 -0
  356. package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js.map +1 -0
  357. package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js +122 -0
  358. package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js.map +1 -0
  359. package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js +1139 -0
  360. package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js.map +1 -0
  361. package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js +1060 -0
  362. package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js.map +1 -0
  363. package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js +1301 -0
  364. package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js.map +1 -0
  365. package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js +370 -0
  366. package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js.map +1 -0
  367. package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js +498 -0
  368. package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js.map +1 -0
  369. package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js +1565 -0
  370. package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js.map +1 -0
  371. package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js +2206 -0
  372. package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js.map +1 -0
  373. package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js +1129 -0
  374. package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js.map +1 -0
  375. package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js +565 -0
  376. package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js.map +1 -0
  377. package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js +408 -0
  378. package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js.map +1 -0
  379. package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js +1910 -0
  380. package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js.map +1 -0
  381. package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js +160 -0
  382. package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js.map +1 -0
  383. package/package.json +1 -1
@@ -0,0 +1,251 @@
1
+ import { Activity, TurnContext } from "botbuilder";
2
+ import URL from "../../../../Types/API/URL";
3
+ import BadDataException from "../../../../Types/Exception/BadDataException";
4
+ import NotAuthorizedException from "../../../../Types/Exception/NotAuthorizedException";
5
+ import { JSONObject } from "../../../../Types/JSON";
6
+ import ObjectID from "../../../../Types/ObjectID";
7
+ import DatabaseConfig from "../../../DatabaseConfig";
8
+ import { ProjectScopedReferenceException } from "../../Database/ProjectScopedReferenceValidator";
9
+ import logger, { LogAttributes } from "../../Logger";
10
+ import MicrosoftTeamsMessageSize, {
11
+ MICROSOFT_TEAMS_CARD_SIZE_BUDGETS_IN_BYTES,
12
+ } from "./MicrosoftTeamsMessageSize";
13
+
14
+ /*
15
+ * Replies the Microsoft Teams bot sends, and the rule they follow: an inbound
16
+ * message gets one answer, and an answer that cannot be sent never turns into
17
+ * a second one.
18
+ *
19
+ * Issue #4111: a failed command replied "Sorry, I encountered an error..."
20
+ * and then rethrew, the adapter answered Teams with HTTP 500, and Teams
21
+ * delivered the message again, so every error showed up twice. Replies that
22
+ * are not the point of the turn (an error text, removing a submitted form) are
23
+ * therefore sent best-effort: a failure is logged, never thrown.
24
+ */
25
+
26
+ export const MICROSOFT_TEAMS_ADAPTIVE_CARD_CONTENT_TYPE: string =
27
+ "application/vnd.microsoft.card.adaptive";
28
+
29
+ /*
30
+ * The reply for a submit that references a record the project does not have
31
+ * (deleted since the form was sent, or another project's id in a tampered
32
+ * submit). Fixed text: the validator's own message names the other project's
33
+ * record, which is not for this chat.
34
+ */
35
+ export const MICROSOFT_TEAMS_UNAVAILABLE_REFERENCE_MESSAGE: string =
36
+ "One of the values you picked (a monitor, label, on-call policy, severity or status) is not available in this project any more. Please pick it again.";
37
+
38
+ export default class MicrosoftTeamsReplies {
39
+ // Sends a reply; logs instead of throwing. Returns whether Teams took it.
40
+ public static async sendBestEffort(
41
+ turnContext: TurnContext,
42
+ reply: string | Partial<Activity>,
43
+ ): Promise<boolean> {
44
+ try {
45
+ await turnContext.sendActivity(reply);
46
+ return true;
47
+ } catch (error) {
48
+ logger.error(
49
+ `Could not send a Microsoft Teams reply: ${this.describeError(error)}`,
50
+ );
51
+ return false;
52
+ }
53
+ }
54
+
55
+ /*
56
+ * Removes a message the bot posted, such as the form a user just submitted;
57
+ * logs instead of throwing. It runs after the record the form created
58
+ * exists, so a failure here must never be reported as a failed create.
59
+ */
60
+ public static async deleteBestEffort(
61
+ turnContext: TurnContext,
62
+ activityId: string | undefined,
63
+ ): Promise<void> {
64
+ if (!activityId) {
65
+ return;
66
+ }
67
+
68
+ try {
69
+ await turnContext.deleteActivity(activityId);
70
+ } catch (error) {
71
+ logger.debug(
72
+ `Could not remove a submitted Microsoft Teams card: ${this.describeError(error)}`,
73
+ );
74
+ }
75
+ }
76
+
77
+ /*
78
+ * Sends an adaptive card built for each size budget in turn, until Teams
79
+ * accepts one. Only a "too large" refusal moves on to the next, smaller
80
+ * budget; any other error is thrown at once, and so is the last "too
81
+ * large". A budget whose card is no different from the one just refused
82
+ * is skipped.
83
+ */
84
+ public static async sendCardWithinSizeLimit(data: {
85
+ turnContext: TurnContext;
86
+ buildCard: (budgetInBytes: number) => JSONObject;
87
+ budgetsInBytes?: ReadonlyArray<number> | undefined;
88
+ }): Promise<void> {
89
+ const budgetsInBytes: ReadonlyArray<number> =
90
+ data.budgetsInBytes || MICROSOFT_TEAMS_CARD_SIZE_BUDGETS_IN_BYTES;
91
+
92
+ let lastError: unknown = undefined;
93
+ let lastRefusedCard: string | null = null;
94
+
95
+ for (const budgetInBytes of budgetsInBytes) {
96
+ const card: JSONObject = data.buildCard(budgetInBytes);
97
+ const serializedCard: string = JSON.stringify(card);
98
+
99
+ if (serializedCard === lastRefusedCard) {
100
+ continue;
101
+ }
102
+
103
+ try {
104
+ await data.turnContext.sendActivity({
105
+ attachments: [
106
+ {
107
+ contentType: MICROSOFT_TEAMS_ADAPTIVE_CARD_CONTENT_TYPE,
108
+ content: card,
109
+ },
110
+ ],
111
+ });
112
+ return;
113
+ } catch (error) {
114
+ if (!MicrosoftTeamsMessageSize.isMessageTooLargeError(error)) {
115
+ throw error;
116
+ }
117
+
118
+ logger.warn(
119
+ `Microsoft Teams refused a ${MicrosoftTeamsMessageSize.getSizeInBytes(
120
+ serializedCard,
121
+ )} byte card as too large (budget ${budgetInBytes} bytes); trying a smaller one.`,
122
+ );
123
+
124
+ lastError = error;
125
+ lastRefusedCard = serializedCard;
126
+ }
127
+ }
128
+
129
+ throw lastError;
130
+ }
131
+
132
+ /*
133
+ * One line that says what went wrong, for the log. Bot Framework errors
134
+ * carry the HTTP status and Teams' error code, e.g.
135
+ * "RestError 413 MessageSizeTooBig: Message size too large.".
136
+ */
137
+ public static describeError(error: unknown): string {
138
+ if (!error || typeof error !== "object") {
139
+ return String(error);
140
+ }
141
+
142
+ /*
143
+ * OneUptime's exceptions keep Error's name, so the class they were thrown
144
+ * as comes from the constructor instead.
145
+ */
146
+ const errorName: string =
147
+ ((error as { name?: unknown }).name as string | undefined) || "";
148
+ const constructorName: string =
149
+ ((error as { constructor?: { name?: unknown } }).constructor?.name as
150
+ | string
151
+ | undefined) || "";
152
+ const name: string =
153
+ errorName && errorName !== "Error"
154
+ ? errorName
155
+ : constructorName && constructorName !== "Object"
156
+ ? constructorName
157
+ : errorName || "Error";
158
+ const message: string = String(
159
+ (error as { message?: unknown }).message ?? "",
160
+ );
161
+ const statusCode: number | undefined =
162
+ MicrosoftTeamsMessageSize.getErrorStatusCode(error);
163
+ const code: string | undefined =
164
+ MicrosoftTeamsMessageSize.getErrorCode(error);
165
+
166
+ return [name, statusCode, code]
167
+ .filter((part: string | number | undefined) => {
168
+ return part !== undefined && part !== "";
169
+ })
170
+ .join(" ")
171
+ .concat(`: ${message}`);
172
+ }
173
+
174
+ /*
175
+ * Logs a failure: one line that says what failed and why, then the error
176
+ * itself, which keeps its stack and lets the log tell a refusal from a
177
+ * fault. A Bot Framework HTTP error is left at the one line: its status and
178
+ * code say it all, and the object carries the whole request and response.
179
+ */
180
+ public static logFailure(
181
+ summary: string,
182
+ error: unknown,
183
+ attributes?: LogAttributes | undefined,
184
+ ): void {
185
+ logger.error(`${summary}: ${this.describeError(error)}`, attributes);
186
+
187
+ if (MicrosoftTeamsMessageSize.getErrorStatusCode(error) === undefined) {
188
+ logger.error(error, attributes);
189
+ }
190
+ }
191
+
192
+ /*
193
+ * The message of an error OneUptime writes for the person who caused it: a
194
+ * validation or a permission refusal. Null for anything else, whose text is
195
+ * meant for operators.
196
+ */
197
+ public static getUserFacingErrorMessage(error: unknown): string | null {
198
+ if (error instanceof ProjectScopedReferenceException) {
199
+ return MICROSOFT_TEAMS_UNAVAILABLE_REFERENCE_MESSAGE;
200
+ }
201
+
202
+ if (
203
+ (error instanceof BadDataException ||
204
+ error instanceof NotAuthorizedException) &&
205
+ error.message
206
+ ) {
207
+ return error.message;
208
+ }
209
+
210
+ return null;
211
+ }
212
+
213
+ // A link into the project in the OneUptime dashboard, or null if unknown.
214
+ public static async getDashboardLink(data: {
215
+ projectId: ObjectID;
216
+ route: string; // below the project, e.g. "/incidents/create"
217
+ }): Promise<string | null> {
218
+ try {
219
+ const dashboardUrl: URL = await DatabaseConfig.getDashboardUrl();
220
+
221
+ return URL.fromString(dashboardUrl.toString())
222
+ .addRoute(`/${data.projectId.toString()}${data.route}`)
223
+ .toString();
224
+ } catch (error) {
225
+ logger.debug("Could not build a OneUptime dashboard link");
226
+ logger.debug(error);
227
+ return null;
228
+ }
229
+ }
230
+
231
+ /*
232
+ * What to tell a Teams user who has not connected their Microsoft Teams
233
+ * account to OneUptime yet: where to do it. `purpose` completes "To ...",
234
+ * e.g. "create incidents from Microsoft Teams".
235
+ */
236
+ public static async getAccountNotLinkedMessage(data: {
237
+ projectId: ObjectID;
238
+ purpose: string;
239
+ }): Promise<string> {
240
+ const settingsLink: string | null = await this.getDashboardLink({
241
+ projectId: data.projectId,
242
+ route: "/user-settings/microsoft-teams-integration",
243
+ });
244
+
245
+ const where: string = settingsLink
246
+ ? `in [OneUptime → User Settings → Microsoft Teams](${settingsLink})`
247
+ : "in OneUptime under User Settings → Microsoft Teams";
248
+
249
+ return `To ${data.purpose}, first connect your Microsoft Teams account to OneUptime ${where}, then try again.`;
250
+ }
251
+ }
@@ -0,0 +1,214 @@
1
+ import moment from "moment-timezone";
2
+ import { JSONObject } from "../../../../Types/JSON";
3
+
4
+ /*
5
+ * The time zone a Microsoft Teams user typed a date and a time in.
6
+ *
7
+ * Input.Date and Input.Time submit a bare "2026-10-01" and "14:00", with no
8
+ * zone. Those used to be read in the server's time zone (UTC in the
9
+ * containers), so 14:00 typed in New York became 10:00 in New York. Teams
10
+ * tells the bot the sender's zone on the activity (localTimezone, an IANA
11
+ * name, and the clientInfo entity), though not from every client: iOS has
12
+ * been seen to leave localTimezone out.
13
+ *
14
+ * The form names the zone of whoever asked for it and carries that zone in
15
+ * its submit data, and the submitted times are read in it: in a channel the
16
+ * person who fills the form in may be somewhere else, and they typed the times
17
+ * the form asked for. A form that named no zone is read in the submitter's own
18
+ * zone, then at the UTC offset of their activity's local timestamp, then in
19
+ * UTC. Whichever zone is used is named back to the user.
20
+ */
21
+
22
+ export interface MicrosoftTeamsUserTimezone {
23
+ // IANA name, when known.
24
+ timezone?: string | undefined;
25
+ // Offset from UTC in minutes, when only an offset is known.
26
+ utcOffsetInMinutes?: number | undefined;
27
+ // How the zone is named to the user, e.g. "America/New_York" or "UTC+05:30".
28
+ label: string;
29
+ }
30
+
31
+ const DATE_TIME_FORMATS: Array<string> = [
32
+ "YYYY-MM-DD HH:mm",
33
+ "YYYY-MM-DD HH:mm:ss",
34
+ ];
35
+
36
+ const UTC_OFFSET_SUFFIX: RegExp = /(?:[+-]\d{2}:?\d{2}|Z)$/i;
37
+
38
+ export default class MicrosoftTeamsTimezone {
39
+ public static readonly UTC: MicrosoftTeamsUserTimezone = {
40
+ timezone: "UTC",
41
+ label: "UTC",
42
+ };
43
+
44
+ // The name, when it is an IANA time zone moment-timezone knows.
45
+ public static getKnownTimezone(value: unknown): string | undefined {
46
+ if (typeof value !== "string") {
47
+ return undefined;
48
+ }
49
+
50
+ const name: string = value.trim();
51
+
52
+ if (!name || !moment.tz.zone(name)) {
53
+ return undefined;
54
+ }
55
+
56
+ return name;
57
+ }
58
+
59
+ // The IANA zone an activity says its sender is in.
60
+ public static getTimezoneFromActivity(
61
+ activity: JSONObject,
62
+ ): string | undefined {
63
+ const fromLocalTimezone: string | undefined = this.getKnownTimezone(
64
+ activity["localTimezone"],
65
+ );
66
+
67
+ if (fromLocalTimezone) {
68
+ return fromLocalTimezone;
69
+ }
70
+
71
+ const entities: Array<JSONObject> =
72
+ (activity["entities"] as Array<JSONObject> | undefined) || [];
73
+
74
+ for (const entity of entities) {
75
+ if (entity && entity["type"] === "clientInfo") {
76
+ const fromClientInfo: string | undefined = this.getKnownTimezone(
77
+ entity["timezone"],
78
+ );
79
+
80
+ if (fromClientInfo) {
81
+ return fromClientInfo;
82
+ }
83
+ }
84
+ }
85
+
86
+ return undefined;
87
+ }
88
+
89
+ /*
90
+ * The UTC offset of the activity's local timestamp, in minutes. botbuilder
91
+ * turns localTimestamp into a Date, which drops the offset, and keeps the
92
+ * original string as rawLocalTimestamp.
93
+ */
94
+ public static getUtcOffsetFromActivity(
95
+ activity: JSONObject,
96
+ ): number | undefined {
97
+ for (const field of ["rawLocalTimestamp", "localTimestamp"]) {
98
+ const value: unknown = activity[field];
99
+
100
+ if (typeof value !== "string" || !UTC_OFFSET_SUFFIX.test(value.trim())) {
101
+ continue;
102
+ }
103
+
104
+ const parsed: moment.Moment = moment.parseZone(
105
+ value.trim(),
106
+ moment.ISO_8601,
107
+ true,
108
+ );
109
+
110
+ if (parsed.isValid()) {
111
+ return parsed.utcOffset();
112
+ }
113
+ }
114
+
115
+ return undefined;
116
+ }
117
+
118
+ /*
119
+ * The zone to read a submitted date and time in: the zone the form named,
120
+ * which is what its reader was told, then the submitting activity's own
121
+ * zone, then its UTC offset, then UTC.
122
+ */
123
+ public static resolve(data: {
124
+ activity: JSONObject;
125
+ timezoneFromCard?: unknown;
126
+ }): MicrosoftTeamsUserTimezone {
127
+ const timezone: string | undefined =
128
+ this.getKnownTimezone(data.timezoneFromCard) ||
129
+ this.getTimezoneFromActivity(data.activity);
130
+
131
+ if (timezone) {
132
+ return { timezone: timezone, label: timezone };
133
+ }
134
+
135
+ const utcOffsetInMinutes: number | undefined =
136
+ this.getUtcOffsetFromActivity(data.activity);
137
+
138
+ if (utcOffsetInMinutes !== undefined) {
139
+ return {
140
+ utcOffsetInMinutes: utcOffsetInMinutes,
141
+ label: this.formatUtcOffset(utcOffsetInMinutes),
142
+ };
143
+ }
144
+
145
+ return this.UTC;
146
+ }
147
+
148
+ /*
149
+ * Whether only a UTC offset is known. The offset is today's, so a date past
150
+ * a daylight saving change can be an hour out, and the reply says so.
151
+ */
152
+ public static isUtcOffsetOnly(timezone: MicrosoftTeamsUserTimezone): boolean {
153
+ return !timezone.timezone && timezone.utcOffsetInMinutes !== undefined;
154
+ }
155
+
156
+ // "UTC", "UTC+05:30", "UTC-04:00".
157
+ public static formatUtcOffset(utcOffsetInMinutes: number): string {
158
+ if (utcOffsetInMinutes === 0) {
159
+ return "UTC";
160
+ }
161
+
162
+ const sign: string = utcOffsetInMinutes > 0 ? "+" : "-";
163
+ const absolute: number = Math.abs(utcOffsetInMinutes);
164
+ const hours: string = String(Math.floor(absolute / 60)).padStart(2, "0");
165
+ const minutes: string = String(absolute % 60).padStart(2, "0");
166
+
167
+ return `UTC${sign}${hours}:${minutes}`;
168
+ }
169
+
170
+ /*
171
+ * The instant a date ("YYYY-MM-DD") and a time ("HH:mm") mean in the zone,
172
+ * or null when either is not in that form.
173
+ */
174
+ public static toDate(data: {
175
+ date: string;
176
+ time: string;
177
+ timezone: MicrosoftTeamsUserTimezone;
178
+ }): Date | null {
179
+ const text: string = `${data.date.trim()} ${data.time.trim()}`;
180
+
181
+ if (data.timezone.timezone) {
182
+ const zoned: moment.Moment = moment.tz(
183
+ text,
184
+ DATE_TIME_FORMATS,
185
+ true,
186
+ data.timezone.timezone,
187
+ );
188
+
189
+ return zoned.isValid() ? zoned.toDate() : null;
190
+ }
191
+
192
+ const wallClock: moment.Moment = moment.utc(text, DATE_TIME_FORMATS, true);
193
+
194
+ if (!wallClock.isValid()) {
195
+ return null;
196
+ }
197
+
198
+ return wallClock
199
+ .subtract(data.timezone.utcOffsetInMinutes || 0, "minutes")
200
+ .toDate();
201
+ }
202
+
203
+ // A date as the user reads it back, e.g. "Oct 1, 2026, 14:00 (America/New_York)".
204
+ public static format(
205
+ date: Date,
206
+ timezone: MicrosoftTeamsUserTimezone,
207
+ ): string {
208
+ const zoned: moment.Moment = timezone.timezone
209
+ ? moment(date).tz(timezone.timezone)
210
+ : moment(date).utcOffset(timezone.utcOffsetInMinutes || 0);
211
+
212
+ return `${zoned.format("MMM D, YYYY, HH:mm")} (${timezone.label})`;
213
+ }
214
+ }
@@ -11,6 +11,7 @@ import ClusterAccessNotice, {
11
11
  FinishedRunKubectlUsage,
12
12
  getClusterAccessSignature,
13
13
  getClusterAiAgentPageRoute,
14
+ NO_KUBECTL_RUN_TEXT,
14
15
  parseClusterAccess,
15
16
  } from "../../../../App/FeatureSet/Dashboard/src/Components/AI/ClusterAccessNotice";
16
17
  import { KubectlActivitySummary } from "../../../../App/FeatureSet/Dashboard/src/Components/AIChat/ChatActivityFeed";
@@ -251,6 +252,75 @@ describe("describeFinishedRunKubectlUsage", () => {
251
252
  "OneUptime AI tried 2 read-only kubectl commands, but none ran on the cluster — the cluster's AI agent or Runner did not pick them up, or they were refused. This investigation used OneUptime data only; see Investigation activity for why.",
252
253
  );
253
254
  });
255
+
256
+ /*
257
+ * Regression: an incident linked to a cluster and to a Docker host whose
258
+ * investigation ran docker commands through the host's AI agent, and no
259
+ * kubectl, was reported as having "used OneUptime data only".
260
+ */
261
+ describe("a run that ran commands on other infrastructure", () => {
262
+ function withInfrastructure(
263
+ overrides: Partial<KubectlActivitySummary> = {},
264
+ executed: number = 3,
265
+ ): KubectlActivitySummary {
266
+ return activity({
267
+ ...overrides,
268
+ infrastructure: {
269
+ executed,
270
+ succeeded: executed,
271
+ notRun: 0,
272
+ unknown: 0,
273
+ },
274
+ });
275
+ }
276
+
277
+ test("says only that no kubectl ran, never that the run used OneUptime data only", () => {
278
+ expect(describeFinishedRunKubectlUsage(withInfrastructure())).toEqual({
279
+ text: NO_KUBECTL_RUN_TEXT,
280
+ tone: "none",
281
+ });
282
+ });
283
+
284
+ test("ends a tried-kubectl sentence without the data-only claim", () => {
285
+ expect(usageText(withInfrastructure({ notRun: 2 }))).toBe(
286
+ "OneUptime AI tried 2 read-only kubectl commands, but none ran on the cluster — the cluster's AI agent or Runner did not pick them up, or they were refused. See Investigation activity for why.",
287
+ );
288
+ expect(usageText(withInfrastructure({ unknown: 1 }))).toBe(
289
+ "OneUptime AI tried 1 read-only kubectl command, but no result came back from the cluster — the cluster's AI agent or Runner took it but never reported back, so whether it ran is unknown. See Investigation activity for why.",
290
+ );
291
+ });
292
+
293
+ test("keeps the kubectl wording when no infrastructure command ran", () => {
294
+ const noneRan: KubectlActivitySummary = activity({
295
+ infrastructure: { executed: 0, succeeded: 0, notRun: 2, unknown: 1 },
296
+ });
297
+
298
+ expect(usageText(noneRan)).toBe(DATA_ONLY_RUN_TEXT);
299
+ expect(
300
+ usageText({
301
+ ...noneRan,
302
+ notRun: 2,
303
+ }),
304
+ ).toContain(
305
+ "This investigation used OneUptime data only; see Investigation activity for why.",
306
+ );
307
+ expect(usageText(withInfrastructure({}, 0))).toBe(DATA_ONLY_RUN_TEXT);
308
+ });
309
+
310
+ test("leaves the wording of runs whose kubectl ran unchanged", () => {
311
+ expect(
312
+ usageText(
313
+ withInfrastructure({
314
+ executed: 2,
315
+ succeeded: 2,
316
+ clusterToolCalls: 2,
317
+ }),
318
+ ),
319
+ ).toBe(
320
+ "OneUptime AI ran 2 read-only kubectl commands during this investigation.",
321
+ );
322
+ });
323
+ });
254
324
  });
255
325
 
256
326
  /*
@@ -731,6 +801,29 @@ describe("ClusterAccessNotice", () => {
731
801
  expect(usage.className).toContain("gray");
732
802
  expect(usage).toHaveTextContent(DATA_ONLY_RUN_TEXT);
733
803
  });
804
+
805
+ test("never calls a run that ran commands on other infrastructure data-only", () => {
806
+ render(
807
+ <ClusterAccessNotice
808
+ clusterAccess={[makeStatus()]}
809
+ isRunFinished={true}
810
+ kubectlActivity={activity({
811
+ clusterToolCalls: 3,
812
+ infrastructure: {
813
+ executed: 3,
814
+ succeeded: 3,
815
+ notRun: 0,
816
+ unknown: 0,
817
+ },
818
+ })}
819
+ />,
820
+ );
821
+
822
+ const usage: HTMLElement = screen.getByTestId("cluster-access-run-usage");
823
+ expect(usage).toHaveAttribute("data-tone", "none");
824
+ expect(usage).toHaveTextContent(NO_KUBECTL_RUN_TEXT);
825
+ expect(noticeText()).not.toContain("OneUptime data only");
826
+ });
734
827
  });
735
828
 
736
829
  test("only gaps that block investigation explain an unreachable cluster", () => {
@@ -96,14 +96,26 @@ function readAgentFile(...segments: Array<string>): string {
96
96
  return fs.readFileSync(path.join(AGENT_DIR, ...segments), "utf8");
97
97
  }
98
98
 
99
- /* Environment variable names the compose file passes to the collector. */
99
+ /*
100
+ * Environment variable names the compose file passes to the collector: its
101
+ * oneuptime-database-agent service only (the OneUptime AI agent beside it
102
+ * reads the same .env and is documented on its own).
103
+ */
100
104
  function composeVariables(): Set<string> {
105
+ const compose: string = readAgentFile("docker-compose.yml");
106
+ const start: number = compose.indexOf("\n oneuptime-database-agent:\n");
107
+ const next: number = compose.slice(start + 1).search(/\n {2}[a-z0-9-]+:\n/);
108
+ const collector: string =
109
+ next < 0 ? compose.slice(start) : compose.slice(start, start + 1 + next);
110
+
111
+ expect(start).toBeGreaterThanOrEqual(0);
112
+
101
113
  return new Set<string>(
102
- Array.from(
103
- readAgentFile("docker-compose.yml").matchAll(/^\s*-\s*([A-Z_]+)=\$\{/gm),
104
- ).map((match: RegExpMatchArray): string => {
105
- return match[1]!;
106
- }),
114
+ Array.from(collector.matchAll(/^\s*-\s*([A-Z_]+)=\$\{/gm)).map(
115
+ (match: RegExpMatchArray): string => {
116
+ return match[1]!;
117
+ },
118
+ ),
107
119
  );
108
120
  }
109
121