@oneuptime/common 9.4.12 → 9.4.13

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 (256) hide show
  1. package/Models/DatabaseModels/Incident.ts +77 -0
  2. package/Models/DatabaseModels/IncidentEpisode.ts +1223 -0
  3. package/Models/DatabaseModels/IncidentEpisodeFeed.ts +533 -0
  4. package/Models/DatabaseModels/IncidentEpisodeInternalNote.ts +456 -0
  5. package/Models/DatabaseModels/IncidentEpisodeMember.ts +587 -0
  6. package/Models/DatabaseModels/IncidentEpisodeOwnerTeam.ts +421 -0
  7. package/Models/DatabaseModels/IncidentEpisodeOwnerUser.ts +419 -0
  8. package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +524 -0
  9. package/Models/DatabaseModels/IncidentGroupingRule.ts +1430 -0
  10. package/Models/DatabaseModels/Index.ts +18 -0
  11. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +70 -0
  12. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.ts +59 -0
  13. package/Models/DatabaseModels/UserOnCallLog.ts +48 -0
  14. package/Models/DatabaseModels/UserOnCallLogTimeline.ts +49 -0
  15. package/Models/DatabaseModels/WorkspaceNotificationLog.ts +57 -0
  16. package/Server/API/IncidentEpisodeAPI.ts +150 -0
  17. package/Server/API/SlackAPI.ts +23 -0
  18. package/Server/API/UserOnCallLogTimelineAPI.ts +24 -4
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1769626069479-MigrationName.ts +729 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/1769629928240-MigrationName.ts +261 -0
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/1769676117342-RenameEvaluateOverTimeInCriteriaFilter.ts +28 -0
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  23. package/Server/Services/BillingService.ts +1 -3
  24. package/Server/Services/CallService.ts +1 -0
  25. package/Server/Services/IncidentEpisodeFeedService.ts +94 -0
  26. package/Server/Services/IncidentEpisodeInternalNoteService.ts +71 -0
  27. package/Server/Services/IncidentEpisodeMemberService.ts +321 -0
  28. package/Server/Services/IncidentEpisodeOwnerTeamService.ts +10 -0
  29. package/Server/Services/IncidentEpisodeOwnerUserService.ts +10 -0
  30. package/Server/Services/IncidentEpisodeService.ts +1045 -0
  31. package/Server/Services/IncidentEpisodeStateTimelineService.ts +566 -0
  32. package/Server/Services/IncidentGroupingEngineService.ts +1047 -0
  33. package/Server/Services/IncidentGroupingRuleService.ts +14 -0
  34. package/Server/Services/IncidentService.ts +11 -0
  35. package/Server/Services/Index.ts +18 -0
  36. package/Server/Services/MailService.ts +1 -0
  37. package/Server/Services/MonitorService.ts +9 -0
  38. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +18 -0
  39. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +64 -2
  40. package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +26 -1
  41. package/Server/Services/OnCallDutyPolicyService.ts +15 -0
  42. package/Server/Services/SmsService.ts +1 -0
  43. package/Server/Services/UserNotificationRuleService.ts +48 -2
  44. package/Server/Services/UserNotificationSettingService.ts +23 -0
  45. package/Server/Services/UserOnCallLogService.ts +41 -4
  46. package/Server/Services/WhatsAppService.ts +1 -0
  47. package/Server/Services/WorkspaceNotificationLogService.ts +16 -0
  48. package/Server/Services/WorkspaceNotificationRuleService.ts +116 -0
  49. package/Server/Utils/AI/IncidentEpisodeAIContextBuilder.ts +490 -0
  50. package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +1 -1
  51. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +1 -1
  52. package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +1 -1
  53. package/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.ts +1 -1
  54. package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +2 -2
  55. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +182 -0
  56. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +13 -0
  57. package/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.ts +1 -1
  58. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +37 -0
  59. package/Server/Utils/PushNotificationUtil.ts +31 -0
  60. package/Server/Utils/WhatsAppTemplateUtil.ts +14 -0
  61. package/Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes.ts +18 -0
  62. package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +702 -0
  63. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +20 -0
  64. package/Server/Utils/Workspace/Slack/Actions/ActionTypes.ts +11 -0
  65. package/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.ts +918 -0
  66. package/Server/Utils/Workspace/Slack/Messages/IncidentEpisode.ts +120 -0
  67. package/Server/Utils/Workspace/WorkspaceMessages/IncidentEpisode.ts +74 -0
  68. package/Types/Email/EmailTemplateType.ts +6 -0
  69. package/Types/Monitor/CriteriaFilter.ts +24 -4
  70. package/Types/Monitor/MonitorCriteriaInstance.ts +67 -0
  71. package/Types/Monitor/MonitorStep.ts +37 -0
  72. package/Types/Monitor/MonitorStepSnmpMonitor.ts +102 -0
  73. package/Types/Monitor/MonitorType.ts +15 -2
  74. package/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.ts +8 -0
  75. package/Types/Monitor/SnmpMonitor/SnmpDataType.ts +21 -0
  76. package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +16 -0
  77. package/Types/Monitor/SnmpMonitor/SnmpOid.ts +60 -0
  78. package/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.ts +7 -0
  79. package/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.ts +7 -0
  80. package/Types/Monitor/SnmpMonitor/SnmpV3Auth.ts +12 -0
  81. package/Types/Monitor/SnmpMonitor/SnmpVersion.ts +7 -0
  82. package/Types/NotificationSetting/NotificationSettingEventType.ts +7 -0
  83. package/Types/Permission.ts +311 -0
  84. package/Types/Probe/ProbeMonitorResponse.ts +2 -0
  85. package/Types/UserNotification/UserNotificationEventType.ts +1 -0
  86. package/Types/WhatsApp/WhatsAppTemplates.ts +24 -0
  87. package/Types/Workspace/NotificationRules/EventType.ts +1 -0
  88. package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +38 -1
  89. package/Utils/Monitor/MonitorMetricType.ts +2 -1
  90. package/build/dist/Models/DatabaseModels/Incident.js +78 -0
  91. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  92. package/build/dist/Models/DatabaseModels/IncidentEpisode.js +1250 -0
  93. package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -0
  94. package/build/dist/Models/DatabaseModels/IncidentEpisodeFeed.js +555 -0
  95. package/build/dist/Models/DatabaseModels/IncidentEpisodeFeed.js.map +1 -0
  96. package/build/dist/Models/DatabaseModels/IncidentEpisodeInternalNote.js +467 -0
  97. package/build/dist/Models/DatabaseModels/IncidentEpisodeInternalNote.js.map +1 -0
  98. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js +607 -0
  99. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js.map +1 -0
  100. package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerTeam.js +437 -0
  101. package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerTeam.js.map +1 -0
  102. package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerUser.js +436 -0
  103. package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerUser.js.map +1 -0
  104. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +546 -0
  105. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -0
  106. package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js +1437 -0
  107. package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js.map +1 -0
  108. package/build/dist/Models/DatabaseModels/Index.js +16 -0
  109. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  110. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +69 -0
  111. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
  112. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js +58 -0
  113. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js.map +1 -1
  114. package/build/dist/Models/DatabaseModels/UserOnCallLog.js +47 -0
  115. package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
  116. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +48 -0
  117. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
  118. package/build/dist/Models/DatabaseModels/WorkspaceNotificationLog.js +58 -0
  119. package/build/dist/Models/DatabaseModels/WorkspaceNotificationLog.js.map +1 -1
  120. package/build/dist/Server/API/IncidentEpisodeAPI.js +97 -0
  121. package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -0
  122. package/build/dist/Server/API/SlackAPI.js +18 -0
  123. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  124. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +30 -10
  125. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
  126. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1769626069479-MigrationName.js +256 -0
  127. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1769626069479-MigrationName.js.map +1 -0
  128. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1769629928240-MigrationName.js +96 -0
  129. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1769629928240-MigrationName.js.map +1 -0
  130. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1769676117342-RenameEvaluateOverTimeInCriteriaFilter.js +25 -0
  131. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1769676117342-RenameEvaluateOverTimeInCriteriaFilter.js.map +1 -0
  132. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  133. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  134. package/build/dist/Server/Services/BillingService.js +1 -2
  135. package/build/dist/Server/Services/BillingService.js.map +1 -1
  136. package/build/dist/Server/Services/CallService.js.map +1 -1
  137. package/build/dist/Server/Services/IncidentEpisodeFeedService.js +83 -0
  138. package/build/dist/Server/Services/IncidentEpisodeFeedService.js.map +1 -0
  139. package/build/dist/Server/Services/IncidentEpisodeInternalNoteService.js +70 -0
  140. package/build/dist/Server/Services/IncidentEpisodeInternalNoteService.js.map +1 -0
  141. package/build/dist/Server/Services/IncidentEpisodeMemberService.js +298 -0
  142. package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -0
  143. package/build/dist/Server/Services/IncidentEpisodeOwnerTeamService.js +9 -0
  144. package/build/dist/Server/Services/IncidentEpisodeOwnerTeamService.js.map +1 -0
  145. package/build/dist/Server/Services/IncidentEpisodeOwnerUserService.js +9 -0
  146. package/build/dist/Server/Services/IncidentEpisodeOwnerUserService.js.map +1 -0
  147. package/build/dist/Server/Services/IncidentEpisodeService.js +933 -0
  148. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -0
  149. package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +498 -0
  150. package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -0
  151. package/build/dist/Server/Services/IncidentGroupingEngineService.js +799 -0
  152. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -0
  153. package/build/dist/Server/Services/IncidentGroupingRuleService.js +13 -0
  154. package/build/dist/Server/Services/IncidentGroupingRuleService.js.map +1 -0
  155. package/build/dist/Server/Services/IncidentService.js +10 -0
  156. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  157. package/build/dist/Server/Services/Index.js +16 -0
  158. package/build/dist/Server/Services/Index.js.map +1 -1
  159. package/build/dist/Server/Services/MailService.js.map +1 -1
  160. package/build/dist/Server/Services/MonitorService.js +9 -1
  161. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  162. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +10 -0
  163. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  164. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +48 -2
  165. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  166. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +20 -1
  167. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
  168. package/build/dist/Server/Services/OnCallDutyPolicyService.js +8 -0
  169. package/build/dist/Server/Services/OnCallDutyPolicyService.js.map +1 -1
  170. package/build/dist/Server/Services/SmsService.js.map +1 -1
  171. package/build/dist/Server/Services/UserNotificationRuleService.js +39 -2
  172. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  173. package/build/dist/Server/Services/UserNotificationSettingService.js +9 -0
  174. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  175. package/build/dist/Server/Services/UserOnCallLogService.js +35 -3
  176. package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
  177. package/build/dist/Server/Services/WhatsAppService.js.map +1 -1
  178. package/build/dist/Server/Services/WorkspaceNotificationLogService.js +12 -0
  179. package/build/dist/Server/Services/WorkspaceNotificationLogService.js.map +1 -1
  180. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +95 -1
  181. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  182. package/build/dist/Server/Utils/AI/IncidentEpisodeAIContextBuilder.js +402 -0
  183. package/build/dist/Server/Utils/AI/IncidentEpisodeAIContextBuilder.js.map +1 -0
  184. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +1 -1
  185. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +1 -1
  186. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +1 -1
  187. package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js +1 -1
  188. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +2 -2
  189. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +135 -0
  190. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -0
  191. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +10 -0
  192. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  193. package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js +1 -1
  194. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +26 -0
  195. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  196. package/build/dist/Server/Utils/PushNotificationUtil.js +20 -0
  197. package/build/dist/Server/Utils/PushNotificationUtil.js.map +1 -1
  198. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +8 -0
  199. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
  200. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes.js +17 -0
  201. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes.js.map +1 -1
  202. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +547 -0
  203. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -0
  204. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +15 -0
  205. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  206. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js +10 -0
  207. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js.map +1 -1
  208. package/build/dist/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.js +651 -0
  209. package/build/dist/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.js.map +1 -0
  210. package/build/dist/Server/Utils/Workspace/Slack/Messages/IncidentEpisode.js +100 -0
  211. package/build/dist/Server/Utils/Workspace/Slack/Messages/IncidentEpisode.js.map +1 -0
  212. package/build/dist/Server/Utils/Workspace/WorkspaceMessages/IncidentEpisode.js +70 -0
  213. package/build/dist/Server/Utils/Workspace/WorkspaceMessages/IncidentEpisode.js.map +1 -0
  214. package/build/dist/Types/Email/EmailTemplateType.js +5 -0
  215. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  216. package/build/dist/Types/Monitor/CriteriaFilter.js +16 -3
  217. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  218. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +62 -0
  219. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  220. package/build/dist/Types/Monitor/MonitorStep.js +26 -0
  221. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  222. package/build/dist/Types/Monitor/MonitorStepSnmpMonitor.js +77 -0
  223. package/build/dist/Types/Monitor/MonitorStepSnmpMonitor.js.map +1 -0
  224. package/build/dist/Types/Monitor/MonitorType.js +13 -2
  225. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  226. package/build/dist/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.js +9 -0
  227. package/build/dist/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.js.map +1 -0
  228. package/build/dist/Types/Monitor/SnmpMonitor/SnmpDataType.js +22 -0
  229. package/build/dist/Types/Monitor/SnmpMonitor/SnmpDataType.js.map +1 -0
  230. package/build/dist/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.js +2 -0
  231. package/build/dist/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.js.map +1 -0
  232. package/build/dist/Types/Monitor/SnmpMonitor/SnmpOid.js +55 -0
  233. package/build/dist/Types/Monitor/SnmpMonitor/SnmpOid.js.map +1 -0
  234. package/build/dist/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.js +8 -0
  235. package/build/dist/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.js.map +1 -0
  236. package/build/dist/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.js +8 -0
  237. package/build/dist/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.js.map +1 -0
  238. package/build/dist/Types/Monitor/SnmpMonitor/SnmpV3Auth.js +2 -0
  239. package/build/dist/Types/Monitor/SnmpMonitor/SnmpV3Auth.js.map +1 -0
  240. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVersion.js +8 -0
  241. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVersion.js.map +1 -0
  242. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +5 -0
  243. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  244. package/build/dist/Types/Permission.js +264 -0
  245. package/build/dist/Types/Permission.js.map +1 -1
  246. package/build/dist/Types/UserNotification/UserNotificationEventType.js +1 -0
  247. package/build/dist/Types/UserNotification/UserNotificationEventType.js.map +1 -1
  248. package/build/dist/Types/WhatsApp/WhatsAppTemplates.js +15 -0
  249. package/build/dist/Types/WhatsApp/WhatsAppTemplates.js.map +1 -1
  250. package/build/dist/Types/Workspace/NotificationRules/EventType.js +1 -0
  251. package/build/dist/Types/Workspace/NotificationRules/EventType.js.map +1 -1
  252. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +33 -1
  253. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -1
  254. package/build/dist/Utils/Monitor/MonitorMetricType.js +2 -1
  255. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  256. package/package.json +1 -1
@@ -0,0 +1,799 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import ObjectID from "../../Types/ObjectID";
11
+ import IncidentGroupingRule from "../../Models/DatabaseModels/IncidentGroupingRule";
12
+ import Incident from "../../Models/DatabaseModels/Incident";
13
+ import IncidentEpisode from "../../Models/DatabaseModels/IncidentEpisode";
14
+ import IncidentEpisodeMember, { IncidentEpisodeMemberAddedBy, } from "../../Models/DatabaseModels/IncidentEpisodeMember";
15
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
16
+ import logger from "../Utils/Logger";
17
+ import SortOrder from "../../Types/BaseDatabase/SortOrder";
18
+ import OneUptimeDate from "../../Types/Date";
19
+ import QueryHelper from "../Types/Database/QueryHelper";
20
+ import IncidentGroupingRuleService from "./IncidentGroupingRuleService";
21
+ import IncidentEpisodeService from "./IncidentEpisodeService";
22
+ import IncidentEpisodeMemberService from "./IncidentEpisodeMemberService";
23
+ import MonitorService from "./MonitorService";
24
+ import ServiceMonitorService from "./ServiceMonitorService";
25
+ import Semaphore from "../Infrastructure/Semaphore";
26
+ import IncidentEpisodeFeedService from "./IncidentEpisodeFeedService";
27
+ import { IncidentEpisodeFeedEventType } from "../../Models/DatabaseModels/IncidentEpisodeFeed";
28
+ import { Green500 } from "../../Types/BrandColors";
29
+ class IncidentGroupingEngineServiceClass {
30
+ async processIncident(incident) {
31
+ logger.debug(`Processing incident ${incident.id} for grouping`);
32
+ try {
33
+ if (!incident.id || !incident.projectId) {
34
+ logger.warn("Incident missing id or projectId, skipping grouping");
35
+ return { grouped: false };
36
+ }
37
+ // If incident already has an episode, don't reprocess
38
+ if (incident.incidentEpisodeId) {
39
+ return { grouped: true, episodeId: incident.incidentEpisodeId };
40
+ }
41
+ // Get enabled rules sorted by priority
42
+ const rules = await IncidentGroupingRuleService.findBy({
43
+ query: {
44
+ projectId: incident.projectId,
45
+ isEnabled: true,
46
+ },
47
+ sort: {
48
+ priority: SortOrder.Ascending,
49
+ },
50
+ props: {
51
+ isRoot: true,
52
+ },
53
+ select: {
54
+ _id: true,
55
+ name: true,
56
+ priority: true,
57
+ // Match criteria fields
58
+ monitors: {
59
+ _id: true,
60
+ },
61
+ incidentSeverities: {
62
+ _id: true,
63
+ },
64
+ incidentLabels: {
65
+ _id: true,
66
+ },
67
+ monitorLabels: {
68
+ _id: true,
69
+ },
70
+ incidentTitlePattern: true,
71
+ incidentDescriptionPattern: true,
72
+ monitorNamePattern: true,
73
+ monitorDescriptionPattern: true,
74
+ // Group by fields
75
+ groupByMonitor: true,
76
+ groupBySeverity: true,
77
+ groupByIncidentTitle: true,
78
+ groupByService: true,
79
+ // Time settings
80
+ enableTimeWindow: true,
81
+ timeWindowMinutes: true,
82
+ episodeTitleTemplate: true,
83
+ episodeDescriptionTemplate: true,
84
+ enableResolveDelay: true,
85
+ resolveDelayMinutes: true,
86
+ enableReopenWindow: true,
87
+ reopenWindowMinutes: true,
88
+ enableInactivityTimeout: true,
89
+ inactivityTimeoutMinutes: true,
90
+ defaultAssignToUserId: true,
91
+ defaultAssignToTeamId: true,
92
+ onCallDutyPolicies: {
93
+ _id: true,
94
+ },
95
+ },
96
+ limit: 100,
97
+ skip: 0,
98
+ });
99
+ if (rules.length === 0) {
100
+ logger.debug(`No enabled grouping rules found for project ${incident.projectId}`);
101
+ return { grouped: false };
102
+ }
103
+ logger.debug(`Found ${rules.length} enabled grouping rules for project ${incident.projectId}`);
104
+ // Find first matching rule
105
+ for (const rule of rules) {
106
+ const matches = await this.doesIncidentMatchRule(incident, rule);
107
+ if (matches) {
108
+ logger.debug(`Incident ${incident.id} matches rule ${rule.name || rule.id}`);
109
+ // Try to find existing episode or create new one
110
+ const result = await this.groupIncidentWithRule(incident, rule);
111
+ return result;
112
+ }
113
+ }
114
+ logger.debug(`Incident ${incident.id} did not match any grouping rules`);
115
+ return { grouped: false };
116
+ }
117
+ catch (error) {
118
+ logger.error(`Error processing incident for grouping: ${error}`);
119
+ return { grouped: false };
120
+ }
121
+ }
122
+ async doesIncidentMatchRule(incident, rule) {
123
+ logger.debug(`Checking if incident ${incident.id} matches rule ${rule.name || rule.id}`);
124
+ // Check monitor IDs - if monitors are specified, incident must be from one of them
125
+ if (rule.monitors && rule.monitors.length > 0) {
126
+ if (!incident.monitors || incident.monitors.length === 0) {
127
+ return false;
128
+ }
129
+ const ruleMonitorIds = rule.monitors.map((m) => {
130
+ var _a;
131
+ return ((_a = m.id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
132
+ });
133
+ const incidentMonitorIds = incident.monitors.map((m) => {
134
+ var _a;
135
+ return ((_a = m.id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
136
+ });
137
+ const hasMatchingMonitor = ruleMonitorIds.some((monitorId) => {
138
+ return incidentMonitorIds.includes(monitorId);
139
+ });
140
+ if (!hasMatchingMonitor) {
141
+ return false;
142
+ }
143
+ }
144
+ // Check incident severity IDs - if severities are specified, incident must have one of them
145
+ if (rule.incidentSeverities && rule.incidentSeverities.length > 0) {
146
+ if (!incident.incidentSeverityId) {
147
+ return false;
148
+ }
149
+ const severityIds = rule.incidentSeverities.map((s) => {
150
+ var _a;
151
+ return ((_a = s.id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
152
+ });
153
+ const incidentSeverityIdStr = incident.incidentSeverityId.toString();
154
+ if (!severityIds.includes(incidentSeverityIdStr)) {
155
+ return false;
156
+ }
157
+ }
158
+ // Check incident label IDs - if incident labels are specified, incident must have at least one of them
159
+ if (rule.incidentLabels && rule.incidentLabels.length > 0) {
160
+ if (!incident.labels || incident.labels.length === 0) {
161
+ return false;
162
+ }
163
+ const ruleLabelIds = rule.incidentLabels.map((l) => {
164
+ var _a;
165
+ return ((_a = l.id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
166
+ });
167
+ const incidentLabelIds = incident.labels.map((l) => {
168
+ var _a;
169
+ return ((_a = l.id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
170
+ });
171
+ const hasMatchingLabel = ruleLabelIds.some((labelId) => {
172
+ return incidentLabelIds.includes(labelId);
173
+ });
174
+ if (!hasMatchingLabel) {
175
+ return false;
176
+ }
177
+ }
178
+ // Check monitor-related criteria (labels, name pattern, description pattern)
179
+ const hasMonitorCriteria = Boolean((rule.monitorLabels && rule.monitorLabels.length > 0) ||
180
+ rule.monitorNamePattern ||
181
+ rule.monitorDescriptionPattern);
182
+ if (hasMonitorCriteria) {
183
+ if (!incident.monitors || incident.monitors.length === 0) {
184
+ return false;
185
+ }
186
+ // Check at least one monitor matches all criteria
187
+ let anyMonitorMatches = false;
188
+ for (const incidentMonitor of incident.monitors) {
189
+ if (!incidentMonitor.id) {
190
+ continue;
191
+ }
192
+ // Load monitor with all needed fields
193
+ const monitor = await MonitorService.findOneById({
194
+ id: incidentMonitor.id,
195
+ select: {
196
+ name: true,
197
+ description: true,
198
+ labels: {
199
+ _id: true,
200
+ },
201
+ },
202
+ props: {
203
+ isRoot: true,
204
+ },
205
+ });
206
+ if (!monitor) {
207
+ continue;
208
+ }
209
+ let monitorMatches = true;
210
+ // Check monitor labels
211
+ if (rule.monitorLabels && rule.monitorLabels.length > 0) {
212
+ if (!monitor.labels || monitor.labels.length === 0) {
213
+ monitorMatches = false;
214
+ }
215
+ else {
216
+ const ruleMonitorLabelIds = rule.monitorLabels.map((l) => {
217
+ var _a;
218
+ return ((_a = l.id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
219
+ });
220
+ const monitorLabelIds = monitor.labels.map((l) => {
221
+ var _a;
222
+ return ((_a = l.id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
223
+ });
224
+ const hasMatchingMonitorLabel = ruleMonitorLabelIds.some((labelId) => {
225
+ return monitorLabelIds.includes(labelId);
226
+ });
227
+ if (!hasMatchingMonitorLabel) {
228
+ monitorMatches = false;
229
+ }
230
+ }
231
+ }
232
+ // Check monitor name pattern (regex)
233
+ if (monitorMatches && rule.monitorNamePattern) {
234
+ if (!monitor.name) {
235
+ monitorMatches = false;
236
+ }
237
+ else {
238
+ try {
239
+ const regex = new RegExp(rule.monitorNamePattern, "i");
240
+ if (!regex.test(monitor.name)) {
241
+ monitorMatches = false;
242
+ }
243
+ }
244
+ catch (_a) {
245
+ logger.warn(`Invalid regex pattern in rule ${rule.id}: ${rule.monitorNamePattern}`);
246
+ monitorMatches = false;
247
+ }
248
+ }
249
+ }
250
+ // Check monitor description pattern (regex)
251
+ if (monitorMatches && rule.monitorDescriptionPattern) {
252
+ if (!monitor.description) {
253
+ monitorMatches = false;
254
+ }
255
+ else {
256
+ try {
257
+ const regex = new RegExp(rule.monitorDescriptionPattern, "i");
258
+ if (!regex.test(monitor.description)) {
259
+ monitorMatches = false;
260
+ }
261
+ }
262
+ catch (_b) {
263
+ logger.warn(`Invalid regex pattern in rule ${rule.id}: ${rule.monitorDescriptionPattern}`);
264
+ monitorMatches = false;
265
+ }
266
+ }
267
+ }
268
+ if (monitorMatches) {
269
+ anyMonitorMatches = true;
270
+ break;
271
+ }
272
+ }
273
+ if (!anyMonitorMatches) {
274
+ return false;
275
+ }
276
+ }
277
+ // Check incident title pattern (regex)
278
+ if (rule.incidentTitlePattern) {
279
+ if (!incident.title) {
280
+ return false;
281
+ }
282
+ try {
283
+ const regex = new RegExp(rule.incidentTitlePattern, "i");
284
+ if (!regex.test(incident.title)) {
285
+ return false;
286
+ }
287
+ }
288
+ catch (_c) {
289
+ logger.warn(`Invalid regex pattern in rule ${rule.id}: ${rule.incidentTitlePattern}`);
290
+ return false;
291
+ }
292
+ }
293
+ // Check incident description pattern (regex)
294
+ if (rule.incidentDescriptionPattern) {
295
+ if (!incident.description) {
296
+ return false;
297
+ }
298
+ try {
299
+ const regex = new RegExp(rule.incidentDescriptionPattern, "i");
300
+ if (!regex.test(incident.description)) {
301
+ return false;
302
+ }
303
+ }
304
+ catch (_d) {
305
+ logger.warn(`Invalid regex pattern in rule ${rule.id}: ${rule.incidentDescriptionPattern}`);
306
+ return false;
307
+ }
308
+ }
309
+ // If no criteria specified (all fields empty), rule matches all incidents
310
+ logger.debug(`Rule ${rule.name || rule.id} matched incident ${incident.id} (all criteria passed)`);
311
+ return true;
312
+ }
313
+ async groupIncidentWithRule(incident, rule) {
314
+ var _a, _b;
315
+ // Build the grouping key based on groupBy fields
316
+ const groupingKey = await this.buildGroupingKey(incident, rule);
317
+ // Create mutex key to prevent race conditions when creating episodes
318
+ const mutexKey = `${(_a = incident.projectId) === null || _a === void 0 ? void 0 : _a.toString()}-${(_b = rule.id) === null || _b === void 0 ? void 0 : _b.toString()}-${groupingKey}`;
319
+ let mutex = null;
320
+ try {
321
+ /*
322
+ * Acquire mutex to prevent concurrent episode creation for the same grouping key
323
+ * This is critical - we must have the lock before proceeding to prevent race conditions
324
+ */
325
+ logger.debug(`Acquiring mutex for grouping key: ${mutexKey} for incident ${incident.id}`);
326
+ mutex = await Semaphore.lock({
327
+ key: mutexKey,
328
+ namespace: "IncidentGroupingEngine.groupIncidentWithRule",
329
+ lockTimeout: 30000, // 30 seconds - enough time to complete episode creation
330
+ acquireTimeout: 60000, // Wait up to 60 seconds to acquire the lock
331
+ });
332
+ logger.debug(`Acquired mutex for grouping key: ${mutexKey} for incident ${incident.id}`);
333
+ // Calculate time window cutoff (only if time window is enabled)
334
+ let timeWindowCutoff = null;
335
+ if (rule.enableTimeWindow) {
336
+ const timeWindowMinutes = rule.timeWindowMinutes || 60;
337
+ timeWindowCutoff = OneUptimeDate.getSomeMinutesAgo(timeWindowMinutes);
338
+ }
339
+ // Find existing active episode that matches
340
+ const existingEpisode = await this.findMatchingActiveEpisode(incident.projectId, rule.id, groupingKey, timeWindowCutoff);
341
+ if (existingEpisode && existingEpisode.id) {
342
+ // Add incident to existing episode
343
+ await this.addIncidentToEpisode(incident, existingEpisode.id, IncidentEpisodeMemberAddedBy.Rule, rule.id);
344
+ // Update episode severity if incident has higher severity
345
+ if (incident.incidentSeverityId) {
346
+ await IncidentEpisodeService.updateEpisodeSeverity(existingEpisode.id, incident.incidentSeverityId, true);
347
+ }
348
+ return {
349
+ grouped: true,
350
+ episodeId: existingEpisode.id,
351
+ isNewEpisode: false,
352
+ };
353
+ }
354
+ // Check if we can reopen a recently resolved episode (only if enabled)
355
+ if (rule.enableReopenWindow) {
356
+ const reopenWindowMinutes = rule.reopenWindowMinutes || 0;
357
+ if (reopenWindowMinutes > 0) {
358
+ const reopenCutoff = OneUptimeDate.getSomeMinutesAgo(reopenWindowMinutes);
359
+ const recentlyResolvedEpisode = await this.findRecentlyResolvedEpisode(incident.projectId, rule.id, groupingKey, reopenCutoff);
360
+ if (recentlyResolvedEpisode && recentlyResolvedEpisode.id) {
361
+ // Reopen the episode
362
+ await IncidentEpisodeService.reopenEpisode(recentlyResolvedEpisode.id);
363
+ // Add incident to reopened episode
364
+ await this.addIncidentToEpisode(incident, recentlyResolvedEpisode.id, IncidentEpisodeMemberAddedBy.Rule, rule.id);
365
+ // Update episode severity if incident has higher severity
366
+ if (incident.incidentSeverityId) {
367
+ await IncidentEpisodeService.updateEpisodeSeverity(recentlyResolvedEpisode.id, incident.incidentSeverityId, true);
368
+ }
369
+ return {
370
+ grouped: true,
371
+ episodeId: recentlyResolvedEpisode.id,
372
+ isNewEpisode: false,
373
+ wasReopened: true,
374
+ };
375
+ }
376
+ }
377
+ }
378
+ // Create new episode
379
+ const newEpisode = await this.createNewEpisode(incident, rule, groupingKey);
380
+ if (newEpisode && newEpisode.id) {
381
+ // Add incident to new episode
382
+ await this.addIncidentToEpisode(incident, newEpisode.id, IncidentEpisodeMemberAddedBy.Rule, rule.id);
383
+ return { grouped: true, episodeId: newEpisode.id, isNewEpisode: true };
384
+ }
385
+ return { grouped: false };
386
+ }
387
+ finally {
388
+ // Release mutex
389
+ if (mutex) {
390
+ try {
391
+ logger.debug(`Releasing mutex for grouping key: ${mutexKey} for incident ${incident.id}`);
392
+ await Semaphore.release(mutex);
393
+ logger.debug(`Released mutex for grouping key: ${mutexKey} for incident ${incident.id}`);
394
+ }
395
+ catch (err) {
396
+ logger.error(`Error releasing mutex for grouping key: ${mutexKey}: ${err}`);
397
+ }
398
+ }
399
+ }
400
+ }
401
+ async buildGroupingKey(incident, rule) {
402
+ const parts = [];
403
+ /*
404
+ * Group by service - only if explicitly enabled
405
+ * Must be checked before monitor since service contains multiple monitors
406
+ */
407
+ if (rule.groupByService &&
408
+ incident.monitors &&
409
+ incident.monitors.length > 0) {
410
+ // Use the first monitor's service for grouping
411
+ const firstMonitor = incident.monitors[0];
412
+ if (firstMonitor && firstMonitor.id) {
413
+ const serviceMonitor = await ServiceMonitorService.findOneBy({
414
+ query: {
415
+ monitorId: firstMonitor.id,
416
+ },
417
+ select: {
418
+ serviceId: true,
419
+ },
420
+ props: {
421
+ isRoot: true,
422
+ },
423
+ });
424
+ if (serviceMonitor === null || serviceMonitor === void 0 ? void 0 : serviceMonitor.serviceId) {
425
+ parts.push(`service:${serviceMonitor.serviceId.toString()}`);
426
+ }
427
+ }
428
+ }
429
+ // Group by monitor - only if explicitly enabled
430
+ if (rule.groupByMonitor &&
431
+ incident.monitors &&
432
+ incident.monitors.length > 0) {
433
+ // Use the first monitor for grouping key
434
+ const firstMonitor = incident.monitors[0];
435
+ if (firstMonitor && firstMonitor.id) {
436
+ parts.push(`monitor:${firstMonitor.id.toString()}`);
437
+ }
438
+ }
439
+ // Group by severity - only if explicitly enabled
440
+ if (rule.groupBySeverity && incident.incidentSeverityId) {
441
+ parts.push(`severity:${incident.incidentSeverityId.toString()}`);
442
+ }
443
+ // Group by incident title - only if explicitly enabled
444
+ if (rule.groupByIncidentTitle && incident.title) {
445
+ // Normalize title for grouping (remove numbers, etc.)
446
+ const normalizedTitle = incident.title
447
+ .toLowerCase()
448
+ .replace(/\d+/g, "X");
449
+ parts.push(`title:${normalizedTitle}`);
450
+ }
451
+ // If no group by options are enabled, all matching incidents go into a single episode
452
+ return parts.join("|") || "default";
453
+ }
454
+ async findMatchingActiveEpisode(projectId, ruleId, groupingKey, timeWindowCutoff) {
455
+ const query = {
456
+ projectId: projectId,
457
+ incidentGroupingRuleId: ruleId,
458
+ groupingKey: groupingKey,
459
+ resolvedAt: null, // Only find active (non-resolved) episodes
460
+ };
461
+ // Only add time window filter if enabled
462
+ if (timeWindowCutoff) {
463
+ query.lastIncidentAddedAt =
464
+ QueryHelper.greaterThanEqualTo(timeWindowCutoff);
465
+ }
466
+ const episode = await IncidentEpisodeService.findOneBy({
467
+ query: query,
468
+ sort: {
469
+ lastIncidentAddedAt: SortOrder.Descending,
470
+ },
471
+ select: {
472
+ _id: true,
473
+ lastIncidentAddedAt: true,
474
+ },
475
+ props: {
476
+ isRoot: true,
477
+ },
478
+ });
479
+ return episode;
480
+ }
481
+ async findRecentlyResolvedEpisode(projectId, ruleId, groupingKey, reopenCutoff) {
482
+ // Find recently resolved episode with matching rule and grouping key
483
+ const episode = await IncidentEpisodeService.findOneBy({
484
+ query: {
485
+ projectId: projectId,
486
+ incidentGroupingRuleId: ruleId,
487
+ groupingKey: groupingKey,
488
+ resolvedAt: QueryHelper.greaterThanEqualTo(reopenCutoff),
489
+ },
490
+ sort: {
491
+ resolvedAt: SortOrder.Descending,
492
+ },
493
+ select: {
494
+ _id: true,
495
+ resolvedAt: true,
496
+ },
497
+ props: {
498
+ isRoot: true,
499
+ },
500
+ });
501
+ return episode;
502
+ }
503
+ async createNewEpisode(incident, rule, groupingKey) {
504
+ // Generate episode title from template (with initial incidentCount of 1)
505
+ const title = this.generateEpisodeTitle(incident, rule.episodeTitleTemplate, 1);
506
+ // Generate episode description from template (with initial incidentCount of 1)
507
+ const description = this.generateEpisodeDescription(incident, rule.episodeDescriptionTemplate, 1);
508
+ const newEpisode = new IncidentEpisode();
509
+ newEpisode.projectId = incident.projectId;
510
+ newEpisode.title = title;
511
+ if (description) {
512
+ newEpisode.description = description;
513
+ }
514
+ /*
515
+ * Store preprocessed templates for dynamic variable updates
516
+ * Static variables are replaced, dynamic ones (like {{incidentCount}}) remain as placeholders
517
+ */
518
+ if (rule.episodeTitleTemplate) {
519
+ newEpisode.titleTemplate = this.preprocessTemplate(incident, rule.episodeTitleTemplate);
520
+ }
521
+ if (rule.episodeDescriptionTemplate) {
522
+ newEpisode.descriptionTemplate = this.preprocessTemplate(incident, rule.episodeDescriptionTemplate);
523
+ }
524
+ newEpisode.incidentGroupingRuleId = rule.id;
525
+ newEpisode.groupingKey = groupingKey;
526
+ newEpisode.isManuallyCreated = false;
527
+ // Set severity from incident
528
+ if (incident.incidentSeverityId) {
529
+ newEpisode.incidentSeverityId = incident.incidentSeverityId;
530
+ }
531
+ // Set default ownership from rule
532
+ if (rule.defaultAssignToUserId) {
533
+ newEpisode.assignedToUserId = rule.defaultAssignToUserId;
534
+ }
535
+ if (rule.defaultAssignToTeamId) {
536
+ newEpisode.assignedToTeamId = rule.defaultAssignToTeamId;
537
+ }
538
+ // Copy on-call policies from rule
539
+ if (rule.onCallDutyPolicies && rule.onCallDutyPolicies.length > 0) {
540
+ newEpisode.onCallDutyPolicies = rule.onCallDutyPolicies;
541
+ }
542
+ try {
543
+ const createdEpisode = await IncidentEpisodeService.create({
544
+ data: newEpisode,
545
+ props: {
546
+ isRoot: true,
547
+ },
548
+ });
549
+ // Add episode feed entry for episode creation
550
+ if (createdEpisode.id) {
551
+ const groupByParts = [];
552
+ if (rule.groupByMonitor) {
553
+ groupByParts.push("Monitor");
554
+ }
555
+ if (rule.groupBySeverity) {
556
+ groupByParts.push("Severity");
557
+ }
558
+ if (rule.groupByIncidentTitle) {
559
+ groupByParts.push("Incident Title");
560
+ }
561
+ if (rule.groupByService) {
562
+ groupByParts.push("Service");
563
+ }
564
+ const groupByDescription = groupByParts.length > 0
565
+ ? `Grouping by: ${groupByParts.join(", ")}`
566
+ : "Grouping all matching incidents together";
567
+ let moreInfo = `**Rule:** ${rule.name || "Unnamed Rule"}\n\n`;
568
+ moreInfo += `**Grouping Key:** \`${groupingKey}\`\n\n`;
569
+ moreInfo += `**${groupByDescription}**`;
570
+ if (rule.enableTimeWindow && rule.timeWindowMinutes) {
571
+ moreInfo += `\n\n**Time Window:** ${rule.timeWindowMinutes} minutes`;
572
+ }
573
+ try {
574
+ await IncidentEpisodeFeedService.createIncidentEpisodeFeedItem({
575
+ incidentEpisodeId: createdEpisode.id,
576
+ projectId: incident.projectId,
577
+ incidentEpisodeFeedEventType: IncidentEpisodeFeedEventType.EpisodeCreated,
578
+ displayColor: Green500,
579
+ feedInfoInMarkdown: `**Episode Created** by grouping rule **${rule.name || "Unnamed Rule"}**`,
580
+ moreInformationInMarkdown: moreInfo,
581
+ });
582
+ }
583
+ catch (feedError) {
584
+ logger.error(`Error creating episode feed for episode creation: ${feedError}`);
585
+ }
586
+ }
587
+ return createdEpisode;
588
+ }
589
+ catch (error) {
590
+ logger.error(`Error creating new episode: ${error}`);
591
+ return null;
592
+ }
593
+ }
594
+ generateEpisodeTitle(incident, template, incidentCount = 1) {
595
+ var _a;
596
+ if (!template) {
597
+ // Default title based on incident
598
+ if (incident.monitors &&
599
+ incident.monitors.length > 0 &&
600
+ ((_a = incident.monitors[0]) === null || _a === void 0 ? void 0 : _a.name)) {
601
+ return `Incident Episode: ${incident.monitors[0].name}`;
602
+ }
603
+ if (incident.title) {
604
+ return `Incident Episode: ${incident.title.substring(0, 50)}`;
605
+ }
606
+ return "Incident Episode";
607
+ }
608
+ return (this.replaceTemplatePlaceholders(incident, template, incidentCount) ||
609
+ "Incident Episode");
610
+ }
611
+ generateEpisodeDescription(incident, template, incidentCount = 1) {
612
+ if (!template) {
613
+ return undefined;
614
+ }
615
+ return (this.replaceTemplatePlaceholders(incident, template, incidentCount) ||
616
+ undefined);
617
+ }
618
+ replaceTemplatePlaceholders(incident, template, incidentCount = 1) {
619
+ var _a, _b;
620
+ let result = template;
621
+ /*
622
+ * Static variables (from first incident)
623
+ * {{incidentTitle}}
624
+ */
625
+ if (incident.title) {
626
+ result = result.replace(/\{\{incidentTitle\}\}/g, incident.title);
627
+ }
628
+ // {{incidentDescription}}
629
+ if (incident.description) {
630
+ result = result.replace(/\{\{incidentDescription\}\}/g, incident.description);
631
+ }
632
+ // {{monitorName}} - use first monitor's name
633
+ if (incident.monitors &&
634
+ incident.monitors.length > 0 &&
635
+ ((_a = incident.monitors[0]) === null || _a === void 0 ? void 0 : _a.name)) {
636
+ result = result.replace(/\{\{monitorName\}\}/g, incident.monitors[0].name);
637
+ }
638
+ // {{incidentSeverity}}
639
+ if ((_b = incident.incidentSeverity) === null || _b === void 0 ? void 0 : _b.name) {
640
+ result = result.replace(/\{\{incidentSeverity\}\}/g, incident.incidentSeverity.name);
641
+ }
642
+ /*
643
+ * Dynamic variables (updated when incidents are added/removed)
644
+ * {{incidentCount}}
645
+ */
646
+ result = result.replace(/\{\{incidentCount\}\}/g, incidentCount.toString());
647
+ // Clean up any remaining unknown placeholders
648
+ result = result.replace(/\{\{[^}]+\}\}/g, "");
649
+ return result;
650
+ }
651
+ /*
652
+ * Preprocess template: replace static variables but keep dynamic ones as placeholders
653
+ * This is stored on the episode so we can re-render with updated dynamic values later
654
+ */
655
+ preprocessTemplate(incident, template) {
656
+ var _a, _b;
657
+ let result = template;
658
+ /*
659
+ * Replace static variables (from first incident)
660
+ * {{incidentTitle}}
661
+ */
662
+ if (incident.title) {
663
+ result = result.replace(/\{\{incidentTitle\}\}/g, incident.title);
664
+ }
665
+ // {{incidentDescription}}
666
+ if (incident.description) {
667
+ result = result.replace(/\{\{incidentDescription\}\}/g, incident.description);
668
+ }
669
+ // {{monitorName}} - use first monitor's name
670
+ if (incident.monitors &&
671
+ incident.monitors.length > 0 &&
672
+ ((_a = incident.monitors[0]) === null || _a === void 0 ? void 0 : _a.name)) {
673
+ result = result.replace(/\{\{monitorName\}\}/g, incident.monitors[0].name);
674
+ }
675
+ // {{incidentSeverity}}
676
+ if ((_b = incident.incidentSeverity) === null || _b === void 0 ? void 0 : _b.name) {
677
+ result = result.replace(/\{\{incidentSeverity\}\}/g, incident.incidentSeverity.name);
678
+ }
679
+ /*
680
+ * Keep dynamic variables as placeholders (e.g., {{incidentCount}})
681
+ * They will be replaced when title/description is re-rendered
682
+ */
683
+ return result;
684
+ }
685
+ async addIncidentToEpisode(incident, episodeId, addedBy, ruleId) {
686
+ const member = new IncidentEpisodeMember();
687
+ member.projectId = incident.projectId;
688
+ member.incidentEpisodeId = episodeId;
689
+ member.incidentId = incident.id;
690
+ member.addedBy = addedBy;
691
+ if (ruleId) {
692
+ member.matchedRuleId = ruleId;
693
+ }
694
+ try {
695
+ await IncidentEpisodeMemberService.create({
696
+ data: member,
697
+ props: {
698
+ isRoot: true,
699
+ },
700
+ });
701
+ // Feed entries are created by IncidentEpisodeMemberService.onCreateSuccess
702
+ }
703
+ catch (error) {
704
+ // Check if it's a duplicate error (incident already in episode)
705
+ if (error instanceof Error &&
706
+ error.message.includes("already a member")) {
707
+ logger.debug(`Incident ${incident.id} is already in episode ${episodeId}`);
708
+ return;
709
+ }
710
+ throw error;
711
+ }
712
+ }
713
+ async addIncidentToEpisodeManually(incident, episodeId, addedByUserId) {
714
+ const member = new IncidentEpisodeMember();
715
+ member.projectId = incident.projectId;
716
+ member.incidentEpisodeId = episodeId;
717
+ member.incidentId = incident.id;
718
+ member.addedBy = IncidentEpisodeMemberAddedBy.Manual;
719
+ if (addedByUserId) {
720
+ member.addedByUserId = addedByUserId;
721
+ }
722
+ await IncidentEpisodeMemberService.create({
723
+ data: member,
724
+ props: {
725
+ isRoot: true,
726
+ },
727
+ });
728
+ // Feed entries are created by IncidentEpisodeMemberService.onCreateSuccess
729
+ // Update episode severity if needed
730
+ if (incident.incidentSeverityId) {
731
+ await IncidentEpisodeService.updateEpisodeSeverity(episodeId, incident.incidentSeverityId, true);
732
+ }
733
+ }
734
+ }
735
+ __decorate([
736
+ CaptureSpan(),
737
+ __metadata("design:type", Function),
738
+ __metadata("design:paramtypes", [Incident]),
739
+ __metadata("design:returntype", Promise)
740
+ ], IncidentGroupingEngineServiceClass.prototype, "processIncident", null);
741
+ __decorate([
742
+ CaptureSpan(),
743
+ __metadata("design:type", Function),
744
+ __metadata("design:paramtypes", [Incident,
745
+ IncidentGroupingRule]),
746
+ __metadata("design:returntype", Promise)
747
+ ], IncidentGroupingEngineServiceClass.prototype, "doesIncidentMatchRule", null);
748
+ __decorate([
749
+ CaptureSpan(),
750
+ __metadata("design:type", Function),
751
+ __metadata("design:paramtypes", [Incident,
752
+ IncidentGroupingRule]),
753
+ __metadata("design:returntype", Promise)
754
+ ], IncidentGroupingEngineServiceClass.prototype, "groupIncidentWithRule", null);
755
+ __decorate([
756
+ CaptureSpan(),
757
+ __metadata("design:type", Function),
758
+ __metadata("design:paramtypes", [Incident,
759
+ IncidentGroupingRule]),
760
+ __metadata("design:returntype", Promise)
761
+ ], IncidentGroupingEngineServiceClass.prototype, "buildGroupingKey", null);
762
+ __decorate([
763
+ CaptureSpan(),
764
+ __metadata("design:type", Function),
765
+ __metadata("design:paramtypes", [ObjectID,
766
+ ObjectID, String, Object]),
767
+ __metadata("design:returntype", Promise)
768
+ ], IncidentGroupingEngineServiceClass.prototype, "findMatchingActiveEpisode", null);
769
+ __decorate([
770
+ CaptureSpan(),
771
+ __metadata("design:type", Function),
772
+ __metadata("design:paramtypes", [ObjectID,
773
+ ObjectID, String, Date]),
774
+ __metadata("design:returntype", Promise)
775
+ ], IncidentGroupingEngineServiceClass.prototype, "findRecentlyResolvedEpisode", null);
776
+ __decorate([
777
+ CaptureSpan(),
778
+ __metadata("design:type", Function),
779
+ __metadata("design:paramtypes", [Incident,
780
+ IncidentGroupingRule, String]),
781
+ __metadata("design:returntype", Promise)
782
+ ], IncidentGroupingEngineServiceClass.prototype, "createNewEpisode", null);
783
+ __decorate([
784
+ CaptureSpan(),
785
+ __metadata("design:type", Function),
786
+ __metadata("design:paramtypes", [Incident,
787
+ ObjectID, String, ObjectID]),
788
+ __metadata("design:returntype", Promise)
789
+ ], IncidentGroupingEngineServiceClass.prototype, "addIncidentToEpisode", null);
790
+ __decorate([
791
+ CaptureSpan(),
792
+ __metadata("design:type", Function),
793
+ __metadata("design:paramtypes", [Incident,
794
+ ObjectID,
795
+ ObjectID]),
796
+ __metadata("design:returntype", Promise)
797
+ ], IncidentGroupingEngineServiceClass.prototype, "addIncidentToEpisodeManually", null);
798
+ export default new IncidentGroupingEngineServiceClass();
799
+ //# sourceMappingURL=IncidentGroupingEngineService.js.map