@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
@@ -88,6 +88,7 @@ import { ExpressRequest, ExpressResponse } from "../../Express";
88
88
  import MicrosoftTeamsServiceUrl from "./MicrosoftTeamsServiceUrl";
89
89
  // Teams action handlers and types
90
90
  import MicrosoftTeamsAuthAction, {
91
+ MicrosoftTeamsAccountNotLinkedException,
91
92
  MicrosoftTeamsRequest,
92
93
  } from "./Actions/Auth";
93
94
  import MicrosoftTeamsIncidentActions from "./Actions/Incident";
@@ -102,6 +103,10 @@ import MicrosoftTeamsIncidentEpisodeActions from "./Actions/IncidentEpisode";
102
103
  import MicrosoftTeamsMonitorActions from "./Actions/Monitor";
103
104
  import MicrosoftTeamsScheduledMaintenanceActions from "./Actions/ScheduledMaintenance";
104
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";
105
110
 
106
111
  /*
107
112
  * AI Ops - observability assistant imports. These power the natural-language
@@ -236,6 +241,13 @@ const MICROSOFT_TEAMS_ROSTER_ERROR_FRAGMENTS: Array<string> = [
236
241
  // Maximum number of pages to fetch when paginating teams
237
242
  const MICROSOFT_TEAMS_MAX_PAGES: number = 500;
238
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
+
239
251
  /*
240
252
  * Hosts that may receive a Teams incoming webhook. Legacy Connector webhooks
241
253
  * use Office domains. Teams Workflows use regional logic.azure.com hosts, and
@@ -3008,21 +3020,6 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
3008
3020
  });
3009
3021
  }
3010
3022
 
3011
- // If this is actually an Adaptive Card submit wrapped as a message, route to invoke handler
3012
- if (
3013
- (possibleActionValue["action"] as string) ||
3014
- (possibleActionValue["data"] as any)?.["action"]
3015
- ) {
3016
- logger.debug(
3017
- "Message activity contains action payload; routing to invoke handler",
3018
- );
3019
- await this.handleBotInvokeActivity({
3020
- activity: data.activity,
3021
- turnContext: data.turnContext,
3022
- });
3023
- return;
3024
- }
3025
-
3026
3023
  // Check if the bot was mentioned
3027
3024
  const recipientId: string = (data.activity["recipient"] as JSONObject)?.[
3028
3025
  "id"
@@ -3037,45 +3034,45 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
3037
3034
  );
3038
3035
  });
3039
3036
 
3040
- // Only respond if it's a direct message or the bot was mentioned
3041
- if (!isDirectMessage && !isMentioned) {
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) {
3042
3045
  logger.debug("Bot not mentioned in channel message, ignoring");
3043
3046
  return;
3044
3047
  }
3045
3048
 
3046
- // Extract tenant ID to get project ID
3047
- const tenantId: string = (channelData["tenant"] as JSONObject)?.[
3048
- "id"
3049
- ] as string;
3050
- if (!tenantId) {
3051
- logger.error("Tenant ID not found in channelData");
3052
- await data.turnContext.sendActivity(
3053
- "Sorry, I couldn't identify your organization. Please try again later.",
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
+ },
3054
3060
  );
3055
3061
  return;
3056
3062
  }
3057
3063
 
3058
- // Get project auth by tenant ID
3059
- const tenantResolution: MicrosoftTeamsTenantResolution =
3060
- await this.resolveProjectByTenantId({
3061
- tenantId: tenantId,
3062
- });
3063
-
3064
- if (
3065
- !tenantResolution.projectAuth ||
3066
- !tenantResolution.projectAuth.projectId
3067
- ) {
3068
- await data.turnContext.sendActivity(
3069
- 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",
3070
3068
  );
3069
+ await this.handleBotInvokeActivity({
3070
+ activity: data.activity,
3071
+ turnContext: data.turnContext,
3072
+ });
3071
3073
  return;
3072
3074
  }
3073
3075
 
3074
- const projectId: ObjectID = tenantResolution.projectAuth.projectId;
3075
- logger.debug(
3076
- `Found project ID: ${projectId.toString()} for tenant ID: ${tenantId}`,
3077
- );
3078
-
3079
3076
  // Clean the message text by removing bot mentions
3080
3077
  const cleanText: string = messageText
3081
3078
  .replace(/<at[^>]*>.*?<\/at>/g, "")
@@ -3091,81 +3088,131 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
3091
3088
  .replace(/<at[^>]*>.*?<\/at>/g, "")
3092
3089
  .trim();
3093
3090
 
3094
- let responseText: string = "";
3091
+ const isCreateIncidentCommand: boolean =
3092
+ cleanText === CREATE_INCIDENT_COMMAND ||
3093
+ cleanText.startsWith(CREATE_INCIDENT_COMMAND + " ");
3095
3094
 
3096
- try {
3097
- const isCreateIncidentCommand: boolean =
3098
- cleanText === "create incident" ||
3099
- cleanText.startsWith("create incident ");
3095
+ const isCreateMaintenanceCommand: boolean =
3096
+ cleanText === CREATE_MAINTENANCE_COMMAND ||
3097
+ cleanText.startsWith(CREATE_MAINTENANCE_COMMAND + " ");
3100
3098
 
3101
- const isCreateMaintenanceCommand: boolean =
3102
- cleanText === "create maintenance" ||
3103
- cleanText.startsWith("create maintenance ");
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 === "?";
3104
3106
 
3105
- /*
3106
- * Explicit commands are matched precisely so that natural-language
3107
- * questions (which may incidentally contain words like "help" or
3108
- * "alerts") fall through to the AI assistant instead of a canned command.
3109
- */
3110
- const isHelpCommand: boolean =
3111
- cleanText === "help" || cleanText === "" || cleanText === "?";
3107
+ const isShowActiveIncidentsCommand: boolean =
3108
+ cleanText === "show active incidents" || cleanText === "active incidents";
3112
3109
 
3113
- const isShowActiveIncidentsCommand: boolean =
3114
- cleanText === "show active incidents" ||
3115
- cleanText === "active incidents";
3110
+ const isShowScheduledMaintenanceCommand: boolean =
3111
+ cleanText === "show scheduled maintenance" ||
3112
+ cleanText === "scheduled maintenance";
3116
3113
 
3117
- const isShowScheduledMaintenanceCommand: boolean =
3118
- cleanText === "show scheduled maintenance" ||
3119
- cleanText === "scheduled maintenance";
3114
+ const isShowOngoingMaintenanceCommand: boolean =
3115
+ cleanText === "show ongoing maintenance" ||
3116
+ cleanText === "ongoing maintenance";
3120
3117
 
3121
- const isShowOngoingMaintenanceCommand: boolean =
3122
- cleanText === "show ongoing maintenance" ||
3123
- cleanText === "ongoing maintenance";
3118
+ const isShowActiveAlertsCommand: boolean =
3119
+ cleanText === "show active alerts" || cleanText === "active alerts";
3124
3120
 
3125
- const isShowActiveAlertsCommand: boolean =
3126
- cleanText === "show active alerts" || cleanText === "active alerts";
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 ");
3127
3128
 
3128
- /*
3129
- * "ask <question>" is an explicit prefix that always routes to the AI
3130
- * assistant. When present, strip the prefix and use the remainder as the
3131
- * question.
3132
- */
3133
- const isAskCommand: boolean =
3134
- cleanText === "ask" || cleanText.startsWith("ask ");
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
+ );
3135
3188
 
3136
3189
  if (isHelpCommand) {
3137
3190
  responseText = this.getHelpMessage();
3138
3191
  } else if (isCreateIncidentCommand) {
3139
- // Handle create incident command (legacy slash command supported)
3192
+ // "create incident <title>" opens the form with the title filled in.
3140
3193
  logger.debug("Processing create incident command");
3141
- const card: JSONObject =
3142
- await MicrosoftTeamsIncidentActions.buildNewIncidentCard(projectId);
3143
- await data.turnContext.sendActivity({
3144
- attachments: [
3145
- {
3146
- contentType: "application/vnd.microsoft.card.adaptive",
3147
- content: card,
3148
- },
3149
- ],
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(),
3150
3201
  });
3151
- logger.debug("New incident card sent successfully");
3152
3202
  return;
3153
3203
  } else if (isCreateMaintenanceCommand) {
3154
- // Handle create maintenance command (legacy slash command supported)
3204
+ // "create maintenance <title>" opens the form with the title filled in.
3155
3205
  logger.debug("Processing create maintenance command");
3156
- const card: JSONObject =
3157
- await MicrosoftTeamsScheduledMaintenanceActions.buildNewScheduledMaintenanceCard(
3158
- projectId,
3159
- );
3160
- await data.turnContext.sendActivity({
3161
- attachments: [
3162
- {
3163
- contentType: "application/vnd.microsoft.card.adaptive",
3164
- content: card,
3165
- },
3166
- ],
3167
- });
3168
- 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
+ );
3169
3216
  return;
3170
3217
  } else if (isShowActiveIncidentsCommand) {
3171
3218
  responseText = await this.getActiveIncidentsMessage(projectId);
@@ -3201,19 +3248,98 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
3201
3248
  return;
3202
3249
  }
3203
3250
 
3204
- // Send response directly using TurnContext - this is the recommended Bot Framework pattern
3205
- await data.turnContext.sendActivity(responseText);
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
+ );
3206
3259
  logger.debug("Bot message sent successfully using TurnContext", {
3207
3260
  projectId: projectId.toString(),
3208
3261
  });
3209
3262
  } catch (error) {
3210
- logger.error("Error sending bot message via TurnContext: " + error, {
3211
- projectId: projectId.toString(),
3212
- });
3213
- await data.turnContext.sendActivity(
3214
- "Sorry, I encountered an error processing your request. Please try again later.",
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
+ },
3215
3283
  );
3216
- throw error;
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
+ });
3217
3343
  }
3218
3344
  }
3219
3345
 
@@ -3236,14 +3362,35 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
3236
3362
  * channel/chat message bodies are typically HTML (body.contentType "html").
3237
3363
  */
3238
3364
  private static toPlainTextFromTeamsMessageBody(rawContent: string): string {
3239
- return rawContent
3240
- .replace(/<at[^>]*>.*?<\/at>/g, "")
3241
- .replace(/<[^>]*>/g, "")
3365
+ return this.stripHtmlTags(rawContent.replace(/<at[^>]*>.*?<\/at>/g, ""))
3242
3366
  .replace(/&nbsp;/g, " ")
3243
3367
  .replace(/\s+/g, " ")
3244
3368
  .trim();
3245
3369
  }
3246
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 "&lt;", 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
+
3247
3394
  /*
3248
3395
  * AI Ops: gather the prior turns of the current Teams conversation/thread and
3249
3396
  * map them to the assistant's history shape ({ role, content }, oldest-first,
@@ -3507,6 +3654,11 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
3507
3654
  projectId: projectId,
3508
3655
  });
3509
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
+
3510
3662
  logger.debug(
3511
3663
  "No OneUptime user linked to Teams user; prompting to connect account",
3512
3664
  {
@@ -3514,9 +3666,11 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
3514
3666
  workspaceUserId: teamsUserId,
3515
3667
  },
3516
3668
  );
3517
- logger.debug(error);
3518
3669
  await turnContext.sendActivity(
3519
- "I couldn't find your OneUptime account. Please connect your Microsoft Teams account in OneUptime User Settings before asking me questions.",
3670
+ await MicrosoftTeamsReplies.getAccountNotLinkedMessage({
3671
+ projectId: projectId,
3672
+ purpose: "ask OneUptime questions from Microsoft Teams",
3673
+ }),
3520
3674
  );
3521
3675
  return;
3522
3676
  }
@@ -3646,6 +3800,31 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
3646
3800
  }
3647
3801
  }
3648
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
+
3649
3828
  // Helper methods for bot commands
3650
3829
  private static getHelpMessage(): string {
3651
3830
  return `Hello! I'm the OneUptime bot. I can help you with the following commands:
@@ -3653,8 +3832,8 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
3653
3832
  **Available Commands:**
3654
3833
  - **help** - Show this help message
3655
3834
  - **ask <question>** - Ask OneUptime AI about your logs, traces, metrics, incidents and monitors
3656
- - **create incident** - Create a new incident
3657
- - **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
3658
3837
  - **show active incidents** - Display all currently active incidents
3659
3838
  - **show scheduled maintenance** - Show upcoming scheduled maintenance events
3660
3839
  - **show ongoing maintenance** - Display currently ongoing maintenance events
@@ -3759,11 +3938,9 @@ If you need to report an incident or check historical incidents, please visit th
3759
3938
  `;
3760
3939
 
3761
3940
  if (incident.monitors && incident.monitors.length > 0) {
3762
- message += `• **Affected Services:** ${incident.monitors
3763
- .map((m: Monitor) => {
3764
- return m.name;
3765
- })
3766
- .join(", ")}\n`;
3941
+ message += `• **Affected Services:** ${this.formatAffectedMonitorNames(
3942
+ incident.monitors,
3943
+ )}\n`;
3767
3944
  }
3768
3945
 
3769
3946
  if (incident.description) {
@@ -3866,11 +4043,9 @@ Check back later for upcoming maintenance windows.`;
3866
4043
  `;
3867
4044
 
3868
4045
  if (event.monitors && event.monitors.length > 0) {
3869
- message += `• **Affected Services:** ${event.monitors
3870
- .map((m: Monitor) => {
3871
- return m.name;
3872
- })
3873
- .join(", ")}\n`;
4046
+ message += `• **Affected Services:** ${this.formatAffectedMonitorNames(
4047
+ event.monitors,
4048
+ )}\n`;
3874
4049
  }
3875
4050
 
3876
4051
  if (event.description) {
@@ -3972,11 +4147,9 @@ All systems are currently operating normally.`;
3972
4147
  `;
3973
4148
 
3974
4149
  if (event.monitors && event.monitors.length > 0) {
3975
- message += `• **Affected Services:** ${event.monitors
3976
- .map((m: Monitor) => {
3977
- return m.name;
3978
- })
3979
- .join(", ")}\n`;
4150
+ message += `• **Affected Services:** ${this.formatAffectedMonitorNames(
4151
+ event.monitors,
4152
+ )}\n`;
3980
4153
  }
3981
4154
 
3982
4155
  if (event.description) {
@@ -4118,6 +4291,8 @@ All monitoring checks are passing normally.`;
4118
4291
  logger.debug(`Bot invoke activity - Action type: ${actionType}`);
4119
4292
  logger.debug(`Bot invoke value: ${JSON.stringify(value)}`);
4120
4293
 
4294
+ let projectId: ObjectID | undefined = undefined;
4295
+
4121
4296
  try {
4122
4297
  // Resolve project and user context from activity
4123
4298
  const channelData: JSONObject =
@@ -4148,7 +4323,7 @@ All monitoring checks are passing normally.`;
4148
4323
  return;
4149
4324
  }
4150
4325
 
4151
- const projectId: ObjectID = tenantResolution.projectAuth.projectId;
4326
+ projectId = tenantResolution.projectAuth.projectId;
4152
4327
  const fromObj: JSONObject = ((data.activity["from"] as JSONObject) ||
4153
4328
  {}) as JSONObject;
4154
4329
  const teamsUserId: string | undefined =
@@ -4303,21 +4478,62 @@ All monitoring checks are passing normally.`;
4303
4478
  return;
4304
4479
  }
4305
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
+
4306
4508
  // Tell the user why they were refused; the message is written for them.
4307
4509
  if (error instanceof NotAuthorizedException) {
4308
4510
  logger.debug("Bot invoke activity refused: " + error.message, {
4309
4511
  actionType: actionType,
4310
4512
  });
4311
- await data.turnContext.sendActivity(error.message);
4513
+ await MicrosoftTeamsReplies.sendBestEffort(
4514
+ data.turnContext,
4515
+ error.message,
4516
+ );
4312
4517
  return;
4313
4518
  }
4314
4519
 
4315
- logger.error("Error handling bot invoke activity:", {
4316
- actionType: actionType,
4317
- });
4318
- logger.error(error);
4319
- await data.turnContext.sendActivity(
4320
- "Sorry, that action failed. Please try again later.",
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.",
4321
4537
  );
4322
4538
  }
4323
4539
  }
@@ -6132,8 +6348,16 @@ All monitoring checks are passing normally.`;
6132
6348
  }),
6133
6349
  );
6134
6350
 
6135
- // Run the activity through our activity handler
6136
- await activityHandler.run(context);
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
+ }
6137
6361
  });
6138
6362
 
6139
6363
  logger.debug("Bot Framework activity processed successfully");
@@ -6655,9 +6879,8 @@ All monitoring checks are passing normally.`;
6655
6879
  const body: JSONObject = msg["body"] as JSONObject;
6656
6880
  let text: string = (body?.["content"] as string) || "";
6657
6881
 
6658
- // Remove HTML tags if present (Teams uses HTML)
6659
- text = text.replace(/<[^>]*>/g, "");
6660
- text = text.trim();
6882
+ // Teams message bodies are HTML.
6883
+ text = this.stripHtmlTags(text).trim();
6661
6884
 
6662
6885
  // Skip empty messages
6663
6886
  if (!text) {