@oneuptime/common 11.3.25 → 11.3.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (397) hide show
  1. package/Models/DatabaseModels/AIConversation.ts +322 -0
  2. package/Models/DatabaseModels/AIConversationMessage.ts +495 -0
  3. package/Models/DatabaseModels/AIRun.ts +584 -0
  4. package/Models/DatabaseModels/AIRunEvent.ts +443 -0
  5. package/Models/DatabaseModels/IncidentEpisodeRoleMember.ts +1 -1
  6. package/Models/DatabaseModels/IncidentMember.ts +1 -1
  7. package/Models/DatabaseModels/IncomingCallPolicy.ts +13 -0
  8. package/Models/DatabaseModels/Index.ts +11 -0
  9. package/Models/DatabaseModels/LlmLog.ts +26 -0
  10. package/Models/DatabaseModels/LlmProvider.ts +2 -2
  11. package/Models/DatabaseModels/MigrationFailure.ts +170 -0
  12. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +51 -2
  13. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +44 -0
  14. package/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.ts +6 -0
  15. package/Models/DatabaseModels/OnCallDutyPolicyScheduleLayerUser.ts +6 -0
  16. package/Models/DatabaseModels/OnCallDutyPolicyTimeLog.ts +1 -1
  17. package/Models/DatabaseModels/OnCallDutyPolicyUserOverride.ts +2 -2
  18. package/Server/API/AIChatAPI.ts +693 -0
  19. package/Server/API/AlertAPI.ts +1 -1
  20. package/Server/API/IncidentAPI.ts +2 -2
  21. package/Server/API/IncidentEpisodeAPI.ts +1 -1
  22. package/Server/API/LlmProviderAPI.ts +170 -0
  23. package/Server/API/MicrosoftTeamsAPI.ts +5 -0
  24. package/Server/API/ScheduledMaintenanceAPI.ts +1 -1
  25. package/Server/API/SlackAPI.ts +663 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1783363279075-AddAIChatModels.ts +245 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1783443471795-AddLlmProviderToAIConversation.ts +36 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1783453297388-AddAIChatWriteActionsAndWidgets.ts +46 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1783461767405-MigrationName.ts +119 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1783470000000-AddIncomingCallPolicyRoutingPhoneNumberUnique.ts +25 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/1783510935686-FixNotNullForeignKeysOnDelete.ts +81 -0
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/1783515836148-MigrationName.ts +25 -0
  33. package/Server/Infrastructure/Postgres/SchemaMigrations/1783523076215-AddMigrationFailureTable.ts +35 -0
  34. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +16 -0
  35. package/Server/Infrastructure/PostgresDatabase.ts +11 -0
  36. package/Server/Services/AIConversationMessageService.ts +39 -0
  37. package/Server/Services/AIConversationService.ts +63 -0
  38. package/Server/Services/AIRunEventService.ts +39 -0
  39. package/Server/Services/AIRunService.ts +39 -0
  40. package/Server/Services/AIService.ts +127 -33
  41. package/Server/Services/AnalyticsDatabaseService.ts +10 -1
  42. package/Server/Services/DatabaseService.ts +29 -1
  43. package/Server/Services/IncidentService.ts +1 -1
  44. package/Server/Services/IncomingCallPolicyEscalationRuleService.ts +75 -2
  45. package/Server/Services/IncomingCallPolicyService.ts +42 -1
  46. package/Server/Services/Index.ts +2 -0
  47. package/Server/Services/LlmProviderService.ts +110 -0
  48. package/Server/Services/MigrationFailureService.ts +9 -0
  49. package/Server/Services/MonitorProbeService.ts +33 -7
  50. package/Server/Services/MonitorService.ts +19 -7
  51. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +65 -0
  52. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +185 -41
  53. package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +23 -15
  54. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +39 -0
  55. package/Server/Services/OnCallDutyPolicyScheduleLayerService.ts +148 -0
  56. package/Server/Services/OnCallDutyPolicyScheduleLayerUserService.ts +11 -2
  57. package/Server/Services/OnCallDutyPolicyScheduleService.ts +502 -26
  58. package/Server/Services/OnCallDutyPolicyTimeLogService.ts +49 -7
  59. package/Server/Services/OnCallDutyPolicyUserOverrideService.ts +218 -4
  60. package/Server/Services/ProjectCallSMSConfigService.ts +82 -1
  61. package/Server/Services/ProjectService.ts +24 -0
  62. package/Server/Services/TeamMemberService.ts +6 -0
  63. package/Server/Services/UserNotificationRuleService.ts +13 -42
  64. package/Server/Services/UserOnCallLogService.ts +90 -0
  65. package/Server/Services/UserOnCallLogTimelineService.ts +43 -1
  66. package/Server/Types/AnalyticsDatabase/ModelPermission.ts +74 -9
  67. package/Server/Types/Database/QueryUtil.ts +57 -0
  68. package/Server/Utils/AI/AIChatPrivacyFilter.ts +28 -0
  69. package/Server/Utils/AI/AlertAIContextBuilder.ts +6 -1
  70. package/Server/Utils/AI/Chat/ChatAgentRunner.ts +1066 -0
  71. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +239 -0
  72. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +51 -0
  73. package/Server/Utils/AI/IncidentAIContextBuilder.ts +18 -3
  74. package/Server/Utils/AI/IncidentEpisodeAIContextBuilder.ts +6 -1
  75. package/Server/Utils/AI/ScheduledMaintenanceAIContextBuilder.ts +12 -2
  76. package/Server/Utils/AI/Toolbox/AlertTools.ts +201 -0
  77. package/Server/Utils/AI/Toolbox/AlertWriteTools.ts +174 -0
  78. package/Server/Utils/AI/Toolbox/ContextTools.ts +189 -0
  79. package/Server/Utils/AI/Toolbox/ExceptionTools.ts +149 -0
  80. package/Server/Utils/AI/Toolbox/IncidentTools.ts +386 -0
  81. package/Server/Utils/AI/Toolbox/IncidentWriteTools.ts +350 -0
  82. package/Server/Utils/AI/Toolbox/Index.ts +231 -0
  83. package/Server/Utils/AI/Toolbox/LogTools.ts +339 -0
  84. package/Server/Utils/AI/Toolbox/MetricTools.ts +179 -0
  85. package/Server/Utils/AI/Toolbox/MonitorTools.ts +193 -0
  86. package/Server/Utils/AI/Toolbox/RecentChangesTools.ts +208 -0
  87. package/Server/Utils/AI/Toolbox/Serializer.ts +299 -0
  88. package/Server/Utils/AI/Toolbox/ToolTypes.ts +249 -0
  89. package/Server/Utils/AI/Toolbox/TraceTools.ts +402 -0
  90. package/Server/Utils/AI/Toolbox/WidgetBuilder.ts +189 -0
  91. package/Server/Utils/Database/MigrationFailureLog.ts +240 -0
  92. package/Server/Utils/IncomingCallPhoneNumber.ts +41 -0
  93. package/Server/Utils/LLM/LLMService.ts +605 -96
  94. package/Server/Utils/Telemetry/IoTSnapshotScan.ts +12 -9
  95. package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +12 -9
  96. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +512 -19
  97. package/Server/Utils/Workspace/Slack/Slack.ts +80 -0
  98. package/Server/Utils/Workspace/Slack/app-manifest.json +16 -1
  99. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +0 -8
  100. package/Tests/Server/Services/OnCallDutyPolicyScheduleLayerUserReorder.test.ts +233 -0
  101. package/Tests/Server/Services/OnCallDutyPolicyTimeLogServiceScoping.test.ts +242 -0
  102. package/Tests/Server/Services/OnCallDutyPolicyUserOverrideEdit.test.ts +198 -0
  103. package/Tests/Server/Services/UserOnCallLogClaimNotificationRule.test.ts +495 -0
  104. package/Tests/Server/Types/Database/QueryUtil.test.ts +74 -0
  105. package/Tests/Server/Utils/AI/AIChatModelACL.test.ts +42 -0
  106. package/Tests/Server/Utils/AI/ChatAgentHelpers.test.ts +89 -0
  107. package/Tests/Server/Utils/AI/LLMServiceBaseUrl.test.ts +139 -0
  108. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +386 -0
  109. package/Tests/Server/Utils/AI/ToolArgsGetTimeRange.test.ts +62 -0
  110. package/Tests/Server/Utils/AI/ToolArgsScopeServiceIds.test.ts +79 -0
  111. package/Tests/Server/Utils/AI/ToolResultSerializer.test.ts +223 -0
  112. package/Tests/Types/Billing/SubscriptionStatus.test.ts +127 -0
  113. package/Tests/Types/DateExhaustiveTimezone.test.ts +700 -0
  114. package/Tests/Types/DateTimezoneWallClock.test.ts +99 -0
  115. package/Tests/Types/Events/Recurring.test.ts +22 -9
  116. package/Tests/Types/Metrics/RecordingRuleDefinition.test.ts +213 -0
  117. package/Tests/Types/OnCallDutyPolicy/LayerUtilAuditFixes.test.ts +291 -0
  118. package/Tests/Types/OnCallDutyPolicy/LayerUtilAuditFixesRound2.test.ts +398 -0
  119. package/Tests/Types/OnCallDutyPolicy/LayerUtilDSTWeekendGap.test.ts +114 -0
  120. package/Tests/Types/OnCallDutyPolicy/LayerUtilDSTWeeklyDayShift.test.ts +76 -0
  121. package/Tests/Types/OnCallDutyPolicy/LayerUtilDailyMutation.test.ts +128 -0
  122. package/Tests/Types/OnCallDutyPolicy/LayerUtilDailyProbe.test.ts +203 -0
  123. package/Tests/Types/OnCallDutyPolicy/LayerUtilDiffFuzz.test.ts +322 -0
  124. package/Tests/Types/OnCallDutyPolicy/LayerUtilEdgeCases.test.ts +280 -0
  125. package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveCurrentUser.test.ts +863 -0
  126. package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveDaily.test.ts +900 -0
  127. package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveMultiLayer.test.ts +1104 -0
  128. package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveRotation.test.ts +957 -0
  129. package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveWeekly.test.ts +1095 -0
  130. package/Tests/Types/OnCallDutyPolicy/LayerUtilInvariants.test.ts +232 -0
  131. package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeAudit.test.ts +227 -0
  132. package/Tests/Types/OnCallDutyPolicy/LayerUtilMonthYearAudit.test.ts +255 -0
  133. package/Tests/Types/OnCallDutyPolicy/LayerUtilMultiLayerAudit.test.ts +388 -0
  134. package/Tests/Types/OnCallDutyPolicy/LayerUtilMultiLayerEdge.test.ts +300 -0
  135. package/Tests/Types/OnCallDutyPolicy/LayerUtilOvernightDSTAudit.test.ts +158 -0
  136. package/Tests/Types/OnCallDutyPolicy/LayerUtilRestrictedGapFix.test.ts +253 -0
  137. package/Tests/Types/OnCallDutyPolicy/LayerUtilRestrictedGapRepro.test.ts +157 -0
  138. package/Tests/Types/OnCallDutyPolicy/LayerUtilRotationFixes.test.ts +414 -0
  139. package/Tests/Types/OnCallDutyPolicy/LayerUtilTimezone.test.ts +243 -0
  140. package/Tests/Types/OnCallDutyPolicy/LayerUtilWeekendGapRepro.test.ts +112 -0
  141. package/Tests/Types/OnCallDutyPolicy/OverrideLensAudit.test.ts +117 -0
  142. package/Tests/Types/OnCallDutyPolicy/RestrictionTimes.test.ts +8 -6
  143. package/Tests/Types/OnCallDutyPolicy/RestrictionTimesDefaultDayAudit.test.ts +112 -0
  144. package/Tests/Types/OnCallDutyPolicy/RestrictionTimesExhaustive.test.ts +821 -0
  145. package/Tests/Types/OnCallDutyPolicy/RestrictionTimesMutationInvariant.test.ts +886 -0
  146. package/Tests/Types/OnCallDutyPolicy/UserOverrideUtil.test.ts +255 -0
  147. package/Tests/Types/OnCallDutyPolicy/UserOverrideUtilExhaustive.test.ts +1126 -0
  148. package/Types/AI/AIChatMessageRole.ts +6 -0
  149. package/Types/AI/AIChatMessageStatus.ts +32 -0
  150. package/Types/AI/AIChatPermissionMode.ts +69 -0
  151. package/Types/AI/AIChatTypes.ts +231 -0
  152. package/Types/AI/AIRunEventType.ts +17 -0
  153. package/Types/AI/AIRunStatus.ts +28 -0
  154. package/Types/AI/AIRunType.ts +6 -0
  155. package/Types/Date.ts +200 -15
  156. package/Types/LLM/LlmType.ts +6 -0
  157. package/Types/OnCallDutyPolicy/Layer.ts +790 -260
  158. package/Types/OnCallDutyPolicy/RestrictionTimes.ts +39 -13
  159. package/Types/OnCallDutyPolicy/UserOverrideUtil.ts +21 -5
  160. package/UI/Components/Events/RecurringFieldElement.tsx +16 -0
  161. package/UI/Components/Header/HeaderIconDropdownButton.tsx +22 -12
  162. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +35 -3
  163. package/UI/Components/ModelFormModal/ModelFormModal.tsx +8 -0
  164. package/UI/Components/Page/Page.tsx +14 -0
  165. package/UI/Components/RadioButtons/BasicRadioButtons.tsx +1 -1
  166. package/UI/Utils/LlmTypeDropdownOptions.ts +40 -0
  167. package/UI/Utils/TestLLMProvider.ts +59 -0
  168. package/build/dist/Models/DatabaseModels/AIConversation.js +345 -0
  169. package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -0
  170. package/build/dist/Models/DatabaseModels/AIConversationMessage.js +521 -0
  171. package/build/dist/Models/DatabaseModels/AIConversationMessage.js.map +1 -0
  172. package/build/dist/Models/DatabaseModels/AIRun.js +619 -0
  173. package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -0
  174. package/build/dist/Models/DatabaseModels/AIRunEvent.js +469 -0
  175. package/build/dist/Models/DatabaseModels/AIRunEvent.js.map +1 -0
  176. package/build/dist/Models/DatabaseModels/IncidentEpisodeRoleMember.js +1 -1
  177. package/build/dist/Models/DatabaseModels/IncidentEpisodeRoleMember.js.map +1 -1
  178. package/build/dist/Models/DatabaseModels/IncidentMember.js +1 -1
  179. package/build/dist/Models/DatabaseModels/IncidentMember.js.map +1 -1
  180. package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js +10 -0
  181. package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js.map +1 -1
  182. package/build/dist/Models/DatabaseModels/Index.js +10 -0
  183. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  184. package/build/dist/Models/DatabaseModels/LlmLog.js +28 -0
  185. package/build/dist/Models/DatabaseModels/LlmLog.js.map +1 -1
  186. package/build/dist/Models/DatabaseModels/LlmProvider.js +2 -2
  187. package/build/dist/Models/DatabaseModels/LlmProvider.js.map +1 -1
  188. package/build/dist/Models/DatabaseModels/MigrationFailure.js +196 -0
  189. package/build/dist/Models/DatabaseModels/MigrationFailure.js.map +1 -0
  190. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +52 -2
  191. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
  192. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +45 -0
  193. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  194. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.js +6 -0
  195. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.js.map +1 -1
  196. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayerUser.js +6 -0
  197. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayerUser.js.map +1 -1
  198. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js +1 -1
  199. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js.map +1 -1
  200. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyUserOverride.js +2 -2
  201. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyUserOverride.js.map +1 -1
  202. package/build/dist/Server/API/AIChatAPI.js +498 -0
  203. package/build/dist/Server/API/AIChatAPI.js.map +1 -0
  204. package/build/dist/Server/API/AlertAPI.js +1 -1
  205. package/build/dist/Server/API/IncidentAPI.js +2 -2
  206. package/build/dist/Server/API/IncidentEpisodeAPI.js +1 -1
  207. package/build/dist/Server/API/LlmProviderAPI.js +108 -1
  208. package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
  209. package/build/dist/Server/API/MicrosoftTeamsAPI.js +4 -0
  210. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  211. package/build/dist/Server/API/ScheduledMaintenanceAPI.js +1 -1
  212. package/build/dist/Server/API/SlackAPI.js +442 -0
  213. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  214. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783363279075-AddAIChatModels.js +96 -0
  215. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783363279075-AddAIChatModels.js.map +1 -0
  216. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783443471795-AddLlmProviderToAIConversation.js +25 -0
  217. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783443471795-AddLlmProviderToAIConversation.js.map +1 -0
  218. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783453297388-AddAIChatWriteActionsAndWidgets.js +31 -0
  219. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783453297388-AddAIChatWriteActionsAndWidgets.js.map +1 -0
  220. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783461767405-MigrationName.js +46 -0
  221. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783461767405-MigrationName.js.map +1 -0
  222. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783470000000-AddIncomingCallPolicyRoutingPhoneNumberUnique.js +18 -0
  223. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783470000000-AddIncomingCallPolicyRoutingPhoneNumberUnique.js.map +1 -0
  224. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783510935686-FixNotNullForeignKeysOnDelete.js +38 -0
  225. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783510935686-FixNotNullForeignKeysOnDelete.js.map +1 -0
  226. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783515836148-MigrationName.js +16 -0
  227. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783515836148-MigrationName.js.map +1 -0
  228. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783523076215-AddMigrationFailureTable.js +18 -0
  229. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783523076215-AddMigrationFailureTable.js.map +1 -0
  230. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +16 -0
  231. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  232. package/build/dist/Server/Infrastructure/PostgresDatabase.js +9 -0
  233. package/build/dist/Server/Infrastructure/PostgresDatabase.js.map +1 -1
  234. package/build/dist/Server/Services/AIConversationMessageService.js +34 -0
  235. package/build/dist/Server/Services/AIConversationMessageService.js.map +1 -0
  236. package/build/dist/Server/Services/AIConversationService.js +42 -0
  237. package/build/dist/Server/Services/AIConversationService.js.map +1 -0
  238. package/build/dist/Server/Services/AIRunEventService.js +34 -0
  239. package/build/dist/Server/Services/AIRunEventService.js.map +1 -0
  240. package/build/dist/Server/Services/AIRunService.js +34 -0
  241. package/build/dist/Server/Services/AIRunService.js.map +1 -0
  242. package/build/dist/Server/Services/AIService.js +84 -25
  243. package/build/dist/Server/Services/AIService.js.map +1 -1
  244. package/build/dist/Server/Services/AnalyticsDatabaseService.js +10 -1
  245. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  246. package/build/dist/Server/Services/DatabaseService.js +20 -1
  247. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  248. package/build/dist/Server/Services/IncidentService.js +1 -1
  249. package/build/dist/Server/Services/IncomingCallPolicyEscalationRuleService.js +55 -2
  250. package/build/dist/Server/Services/IncomingCallPolicyEscalationRuleService.js.map +1 -1
  251. package/build/dist/Server/Services/IncomingCallPolicyService.js +40 -0
  252. package/build/dist/Server/Services/IncomingCallPolicyService.js.map +1 -1
  253. package/build/dist/Server/Services/Index.js +2 -0
  254. package/build/dist/Server/Services/Index.js.map +1 -1
  255. package/build/dist/Server/Services/LlmProviderService.js +108 -0
  256. package/build/dist/Server/Services/LlmProviderService.js.map +1 -1
  257. package/build/dist/Server/Services/MigrationFailureService.js +9 -0
  258. package/build/dist/Server/Services/MigrationFailureService.js.map +1 -0
  259. package/build/dist/Server/Services/MonitorProbeService.js +33 -7
  260. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  261. package/build/dist/Server/Services/MonitorService.js +12 -5
  262. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  263. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +81 -22
  264. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  265. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +134 -31
  266. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  267. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +21 -13
  268. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
  269. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +36 -0
  270. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  271. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js +121 -0
  272. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js.map +1 -1
  273. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js +11 -2
  274. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js.map +1 -1
  275. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +409 -36
  276. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  277. package/build/dist/Server/Services/OnCallDutyPolicyTimeLogService.js +52 -8
  278. package/build/dist/Server/Services/OnCallDutyPolicyTimeLogService.js.map +1 -1
  279. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js +170 -3
  280. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js.map +1 -1
  281. package/build/dist/Server/Services/ProjectCallSMSConfigService.js +72 -0
  282. package/build/dist/Server/Services/ProjectCallSMSConfigService.js.map +1 -1
  283. package/build/dist/Server/Services/ProjectService.js +25 -0
  284. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  285. package/build/dist/Server/Services/TeamMemberService.js +6 -0
  286. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  287. package/build/dist/Server/Services/UserNotificationRuleService.js +12 -30
  288. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  289. package/build/dist/Server/Services/UserOnCallLogService.js +75 -0
  290. package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
  291. package/build/dist/Server/Services/UserOnCallLogTimelineService.js +31 -1
  292. package/build/dist/Server/Services/UserOnCallLogTimelineService.js.map +1 -1
  293. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +50 -7
  294. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
  295. package/build/dist/Server/Types/Database/QueryUtil.js +45 -0
  296. package/build/dist/Server/Types/Database/QueryUtil.js.map +1 -1
  297. package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js +18 -0
  298. package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js.map +1 -0
  299. package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js +6 -1
  300. package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js.map +1 -1
  301. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +756 -0
  302. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -0
  303. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +165 -0
  304. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -0
  305. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +44 -0
  306. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -0
  307. package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js +18 -3
  308. package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js.map +1 -1
  309. package/build/dist/Server/Utils/AI/IncidentEpisodeAIContextBuilder.js +6 -1
  310. package/build/dist/Server/Utils/AI/IncidentEpisodeAIContextBuilder.js.map +1 -1
  311. package/build/dist/Server/Utils/AI/ScheduledMaintenanceAIContextBuilder.js +12 -2
  312. package/build/dist/Server/Utils/AI/ScheduledMaintenanceAIContextBuilder.js.map +1 -1
  313. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +167 -0
  314. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -0
  315. package/build/dist/Server/Utils/AI/Toolbox/AlertWriteTools.js +136 -0
  316. package/build/dist/Server/Utils/AI/Toolbox/AlertWriteTools.js.map +1 -0
  317. package/build/dist/Server/Utils/AI/Toolbox/ContextTools.js +141 -0
  318. package/build/dist/Server/Utils/AI/Toolbox/ContextTools.js.map +1 -0
  319. package/build/dist/Server/Utils/AI/Toolbox/ExceptionTools.js +117 -0
  320. package/build/dist/Server/Utils/AI/Toolbox/ExceptionTools.js.map +1 -0
  321. package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +318 -0
  322. package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -0
  323. package/build/dist/Server/Utils/AI/Toolbox/IncidentWriteTools.js +280 -0
  324. package/build/dist/Server/Utils/AI/Toolbox/IncidentWriteTools.js.map +1 -0
  325. package/build/dist/Server/Utils/AI/Toolbox/Index.js +153 -0
  326. package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -0
  327. package/build/dist/Server/Utils/AI/Toolbox/LogTools.js +246 -0
  328. package/build/dist/Server/Utils/AI/Toolbox/LogTools.js.map +1 -0
  329. package/build/dist/Server/Utils/AI/Toolbox/MetricTools.js +120 -0
  330. package/build/dist/Server/Utils/AI/Toolbox/MetricTools.js.map +1 -0
  331. package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js +158 -0
  332. package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js.map +1 -0
  333. package/build/dist/Server/Utils/AI/Toolbox/RecentChangesTools.js +165 -0
  334. package/build/dist/Server/Utils/AI/Toolbox/RecentChangesTools.js.map +1 -0
  335. package/build/dist/Server/Utils/AI/Toolbox/Serializer.js +228 -0
  336. package/build/dist/Server/Utils/AI/Toolbox/Serializer.js.map +1 -0
  337. package/build/dist/Server/Utils/AI/Toolbox/ToolTypes.js +142 -0
  338. package/build/dist/Server/Utils/AI/Toolbox/ToolTypes.js.map +1 -0
  339. package/build/dist/Server/Utils/AI/Toolbox/TraceTools.js +309 -0
  340. package/build/dist/Server/Utils/AI/Toolbox/TraceTools.js.map +1 -0
  341. package/build/dist/Server/Utils/AI/Toolbox/WidgetBuilder.js +120 -0
  342. package/build/dist/Server/Utils/AI/Toolbox/WidgetBuilder.js.map +1 -0
  343. package/build/dist/Server/Utils/Database/MigrationFailureLog.js +174 -0
  344. package/build/dist/Server/Utils/Database/MigrationFailureLog.js.map +1 -0
  345. package/build/dist/Server/Utils/IncomingCallPhoneNumber.js +30 -0
  346. package/build/dist/Server/Utils/IncomingCallPhoneNumber.js.map +1 -0
  347. package/build/dist/Server/Utils/LLM/LLMService.js +452 -92
  348. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  349. package/build/dist/Server/Utils/Telemetry/IoTSnapshotScan.js +11 -8
  350. package/build/dist/Server/Utils/Telemetry/IoTSnapshotScan.js.map +1 -1
  351. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +11 -8
  352. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -1
  353. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +378 -15
  354. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  355. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +59 -0
  356. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  357. package/build/dist/Server/Utils/Workspace/Slack/app-manifest.json +16 -1
  358. package/build/dist/Types/AI/AIChatMessageRole.js +7 -0
  359. package/build/dist/Types/AI/AIChatMessageRole.js.map +1 -0
  360. package/build/dist/Types/AI/AIChatMessageStatus.js +27 -0
  361. package/build/dist/Types/AI/AIChatMessageStatus.js.map +1 -0
  362. package/build/dist/Types/AI/AIChatPermissionMode.js +53 -0
  363. package/build/dist/Types/AI/AIChatPermissionMode.js.map +1 -0
  364. package/build/dist/Types/AI/AIChatTypes.js +74 -0
  365. package/build/dist/Types/AI/AIChatTypes.js.map +1 -0
  366. package/build/dist/Types/AI/AIRunEventType.js +18 -0
  367. package/build/dist/Types/AI/AIRunEventType.js.map +1 -0
  368. package/build/dist/Types/AI/AIRunStatus.js +26 -0
  369. package/build/dist/Types/AI/AIRunStatus.js.map +1 -0
  370. package/build/dist/Types/AI/AIRunType.js +7 -0
  371. package/build/dist/Types/AI/AIRunType.js.map +1 -0
  372. package/build/dist/Types/Date.js +153 -15
  373. package/build/dist/Types/Date.js.map +1 -1
  374. package/build/dist/Types/LLM/LlmType.js +6 -0
  375. package/build/dist/Types/LLM/LlmType.js.map +1 -1
  376. package/build/dist/Types/OnCallDutyPolicy/Layer.js +602 -171
  377. package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
  378. package/build/dist/Types/OnCallDutyPolicy/RestrictionTimes.js +27 -13
  379. package/build/dist/Types/OnCallDutyPolicy/RestrictionTimes.js.map +1 -1
  380. package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js +20 -5
  381. package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js.map +1 -1
  382. package/build/dist/UI/Components/Events/RecurringFieldElement.js +13 -0
  383. package/build/dist/UI/Components/Events/RecurringFieldElement.js.map +1 -1
  384. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +10 -5
  385. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
  386. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +18 -4
  387. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  388. package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
  389. package/build/dist/UI/Components/Page/Page.js +3 -1
  390. package/build/dist/UI/Components/Page/Page.js.map +1 -1
  391. package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +1 -1
  392. package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
  393. package/build/dist/UI/Utils/LlmTypeDropdownOptions.js +38 -0
  394. package/build/dist/UI/Utils/LlmTypeDropdownOptions.js.map +1 -0
  395. package/build/dist/UI/Utils/TestLLMProvider.js +37 -0
  396. package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -0
  397. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  import logger from "../Utils/Logger";
2
2
  import DatabaseDataSourceOptions from "./Postgres/DataSourceOptions";
3
+ import { recordSchemaMigrationFailureBestEffort } from "../Utils/Database/MigrationFailureLog";
3
4
  import Sleep from "../../Types/Sleep";
4
5
  import { DataSource, DataSourceOptions, QueryRunner } from "typeorm";
5
6
  import { createDatabase, dropDatabase } from "typeorm-extension";
@@ -95,6 +96,16 @@ export default class Database {
95
96
  } catch (err) {
96
97
  logger.error("Postgres Database Connection Failed");
97
98
  logger.error(err);
99
+
100
+ /*
101
+ * When this process runs schema migrations on boot (migrationsRun=true),
102
+ * connect() also fails if a migration threw. Record which migration
103
+ * failed and why — on a throwaway connection, since the DataSource above
104
+ * is unusable — so the admin health page can explain the pending schema.
105
+ * Best-effort and self-contained: it never throws and never masks `err`.
106
+ */
107
+ await recordSchemaMigrationFailureBestEffort(dataSourceOptions, err);
108
+
98
109
  throw err;
99
110
  }
100
111
  }
@@ -0,0 +1,39 @@
1
+ import PositiveNumber from "../../Types/PositiveNumber";
2
+ import CountBy from "../Types/Database/CountBy";
3
+ import FindBy from "../Types/Database/FindBy";
4
+ import { OnFind } from "../Types/Database/Hooks";
5
+ import DatabaseService from "./DatabaseService";
6
+ import Model from "../../Models/DatabaseModels/AIConversationMessage";
7
+ import { pinQueryToRequestingUser } from "../Utils/AI/AIChatPrivacyFilter";
8
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
9
+
10
+ export class Service extends DatabaseService<Model> {
11
+ public constructor() {
12
+ super(Model);
13
+ }
14
+
15
+ protected override async onBeforeFind(
16
+ findBy: FindBy<Model>,
17
+ ): Promise<OnFind<Model>> {
18
+ findBy.query = pinQueryToRequestingUser(
19
+ findBy.query,
20
+ findBy.props,
21
+ "userId",
22
+ );
23
+ return { findBy, carryForward: null };
24
+ }
25
+
26
+ @CaptureSpan()
27
+ public override async countBy(
28
+ countBy: CountBy<Model>,
29
+ ): Promise<PositiveNumber> {
30
+ countBy.query = pinQueryToRequestingUser(
31
+ countBy.query,
32
+ countBy.props,
33
+ "userId",
34
+ );
35
+ return super.countBy(countBy);
36
+ }
37
+ }
38
+
39
+ export default new Service();
@@ -0,0 +1,63 @@
1
+ import PositiveNumber from "../../Types/PositiveNumber";
2
+ import CountBy from "../Types/Database/CountBy";
3
+ import DeleteBy from "../Types/Database/DeleteBy";
4
+ import FindBy from "../Types/Database/FindBy";
5
+ import UpdateBy from "../Types/Database/UpdateBy";
6
+ import { OnDelete, OnFind, OnUpdate } from "../Types/Database/Hooks";
7
+ import DatabaseService from "./DatabaseService";
8
+ import Model from "../../Models/DatabaseModels/AIConversation";
9
+ import { pinQueryToRequestingUser } from "../Utils/AI/AIChatPrivacyFilter";
10
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
11
+
12
+ export class Service extends DatabaseService<Model> {
13
+ public constructor() {
14
+ super(Model);
15
+ }
16
+
17
+ protected override async onBeforeFind(
18
+ findBy: FindBy<Model>,
19
+ ): Promise<OnFind<Model>> {
20
+ findBy.query = pinQueryToRequestingUser(
21
+ findBy.query,
22
+ findBy.props,
23
+ "createdByUserId",
24
+ );
25
+ return { findBy, carryForward: null };
26
+ }
27
+
28
+ @CaptureSpan()
29
+ public override async countBy(
30
+ countBy: CountBy<Model>,
31
+ ): Promise<PositiveNumber> {
32
+ countBy.query = pinQueryToRequestingUser(
33
+ countBy.query,
34
+ countBy.props,
35
+ "createdByUserId",
36
+ );
37
+ return super.countBy(countBy);
38
+ }
39
+
40
+ protected override async onBeforeUpdate(
41
+ updateBy: UpdateBy<Model>,
42
+ ): Promise<OnUpdate<Model>> {
43
+ updateBy.query = pinQueryToRequestingUser(
44
+ updateBy.query,
45
+ updateBy.props,
46
+ "createdByUserId",
47
+ );
48
+ return { updateBy, carryForward: null };
49
+ }
50
+
51
+ protected override async onBeforeDelete(
52
+ deleteBy: DeleteBy<Model>,
53
+ ): Promise<OnDelete<Model>> {
54
+ deleteBy.query = pinQueryToRequestingUser(
55
+ deleteBy.query,
56
+ deleteBy.props,
57
+ "createdByUserId",
58
+ );
59
+ return { deleteBy, carryForward: null };
60
+ }
61
+ }
62
+
63
+ export default new Service();
@@ -0,0 +1,39 @@
1
+ import PositiveNumber from "../../Types/PositiveNumber";
2
+ import CountBy from "../Types/Database/CountBy";
3
+ import FindBy from "../Types/Database/FindBy";
4
+ import { OnFind } from "../Types/Database/Hooks";
5
+ import DatabaseService from "./DatabaseService";
6
+ import Model from "../../Models/DatabaseModels/AIRunEvent";
7
+ import { pinQueryToRequestingUser } from "../Utils/AI/AIChatPrivacyFilter";
8
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
9
+
10
+ export class Service extends DatabaseService<Model> {
11
+ public constructor() {
12
+ super(Model);
13
+ }
14
+
15
+ protected override async onBeforeFind(
16
+ findBy: FindBy<Model>,
17
+ ): Promise<OnFind<Model>> {
18
+ findBy.query = pinQueryToRequestingUser(
19
+ findBy.query,
20
+ findBy.props,
21
+ "userId",
22
+ );
23
+ return { findBy, carryForward: null };
24
+ }
25
+
26
+ @CaptureSpan()
27
+ public override async countBy(
28
+ countBy: CountBy<Model>,
29
+ ): Promise<PositiveNumber> {
30
+ countBy.query = pinQueryToRequestingUser(
31
+ countBy.query,
32
+ countBy.props,
33
+ "userId",
34
+ );
35
+ return super.countBy(countBy);
36
+ }
37
+ }
38
+
39
+ export default new Service();
@@ -0,0 +1,39 @@
1
+ import PositiveNumber from "../../Types/PositiveNumber";
2
+ import CountBy from "../Types/Database/CountBy";
3
+ import FindBy from "../Types/Database/FindBy";
4
+ import { OnFind } from "../Types/Database/Hooks";
5
+ import DatabaseService from "./DatabaseService";
6
+ import Model from "../../Models/DatabaseModels/AIRun";
7
+ import { pinQueryToRequestingUser } from "../Utils/AI/AIChatPrivacyFilter";
8
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
9
+
10
+ export class Service extends DatabaseService<Model> {
11
+ public constructor() {
12
+ super(Model);
13
+ }
14
+
15
+ protected override async onBeforeFind(
16
+ findBy: FindBy<Model>,
17
+ ): Promise<OnFind<Model>> {
18
+ findBy.query = pinQueryToRequestingUser(
19
+ findBy.query,
20
+ findBy.props,
21
+ "userId",
22
+ );
23
+ return { findBy, carryForward: null };
24
+ }
25
+
26
+ @CaptureSpan()
27
+ public override async countBy(
28
+ countBy: CountBy<Model>,
29
+ ): Promise<PositiveNumber> {
30
+ countBy.query = pinQueryToRequestingUser(
31
+ countBy.query,
32
+ countBy.props,
33
+ "userId",
34
+ );
35
+ return super.countBy(countBy);
36
+ }
37
+ }
38
+
39
+ export default new Service();
@@ -9,7 +9,12 @@ import LLMService, {
9
9
  LLMProviderConfig,
10
10
  LLMCompletionResponse,
11
11
  LLMMessage,
12
+ LLMToolCall,
13
+ LLMToolDefinition,
14
+ LLMUsage,
12
15
  } from "../Utils/LLM/LLMService";
16
+ import LlmType from "../../Types/LLM/LlmType";
17
+ import { Span, trace } from "@opentelemetry/api";
13
18
  import LlmProvider from "../../Models/DatabaseModels/LlmProvider";
14
19
  import LlmLog from "../../Models/DatabaseModels/LlmLog";
15
20
  import LlmLogStatus from "../../Types/LlmLogStatus";
@@ -20,18 +25,32 @@ import logger, { LogAttributes } from "../Utils/Logger";
20
25
 
21
26
  export interface AILogRequest {
22
27
  projectId: ObjectID;
23
- userId?: ObjectID;
28
+ userId?: ObjectID | undefined;
24
29
  feature: string; // e.g., "IncidentPostmortem", "IncidentNote"
25
30
  incidentId?: ObjectID;
26
31
  alertId?: ObjectID;
27
32
  scheduledMaintenanceId?: ObjectID;
33
+ aiRunId?: ObjectID;
34
+ /*
35
+ * When set, use this specific provider (validated against the project) rather
36
+ * than the project default. Powers the in-chat provider/model switcher.
37
+ */
38
+ llmProviderId?: ObjectID | undefined;
28
39
  messages: Array<LLMMessage>;
29
- maxTokens?: number;
30
- temperature?: number;
40
+ tools?: Array<LLMToolDefinition> | undefined;
41
+ maxTokens?: number | undefined;
42
+ temperature?: number | undefined;
43
+ /*
44
+ * When false, prompt/response previews are NOT persisted to LlmLog.
45
+ * Use for features whose content is private to a single user (e.g. AI
46
+ * chat) — LlmLog is readable by all project members.
47
+ */
48
+ storeContentPreviews?: boolean | undefined;
31
49
  }
32
50
 
33
51
  export interface AILogResponse {
34
52
  content: string;
53
+ toolCalls?: Array<LLMToolCall> | undefined;
35
54
  llmLog: LlmLog;
36
55
  }
37
56
 
@@ -46,9 +65,12 @@ export class Service extends BaseService {
46
65
  ): Promise<AILogResponse> {
47
66
  const startTime: Date = new Date();
48
67
 
49
- // Get LLM provider for the project
68
+ // Get LLM provider for the project (honoring an explicit per-chat choice).
50
69
  const llmProvider: LlmProvider | null =
51
- await LlmProviderService.getLLMProviderForProject(request.projectId);
70
+ await LlmProviderService.getProviderForChat({
71
+ projectId: request.projectId,
72
+ llmProviderId: request.llmProviderId,
73
+ });
52
74
 
53
75
  if (!llmProvider) {
54
76
  throw new BadDataException(
@@ -67,12 +89,18 @@ export class Service extends BaseService {
67
89
  logEntry.projectId = request.projectId;
68
90
  logEntry.isGlobalProvider = llmProvider.isGlobalLlm || false;
69
91
  logEntry.feature = request.feature;
70
- logEntry.requestPrompt = request.messages
71
- .map((m: LLMMessage) => {
72
- return m.content;
73
- })
74
- .join("\n")
75
- .substring(0, 5000); // Store first 5000 chars
92
+
93
+ const storeContentPreviews: boolean =
94
+ request.storeContentPreviews !== false;
95
+
96
+ logEntry.requestPrompt = storeContentPreviews
97
+ ? request.messages
98
+ .map((m: LLMMessage) => {
99
+ return m.content;
100
+ })
101
+ .join("\n")
102
+ .substring(0, 5000) // Store first 5000 chars
103
+ : "[Redacted — this content is private to the requesting user]";
76
104
  logEntry.requestStartedAt = startTime;
77
105
 
78
106
  // Set optional fields only if they have values
@@ -100,10 +128,21 @@ export class Service extends BaseService {
100
128
  if (request.scheduledMaintenanceId) {
101
129
  logEntry.scheduledMaintenanceId = request.scheduledMaintenanceId;
102
130
  }
131
+ if (request.aiRunId) {
132
+ logEntry.aiRunId = request.aiRunId;
133
+ }
103
134
 
104
- // Check if billing should apply
135
+ /*
136
+ * Check if billing should apply. Only bill for the global (OneUptime-hosted)
137
+ * provider, and only when it actually has a per-token cost. A free global
138
+ * provider (costPerMillionTokensInUSDCents = 0, the default) consumes no
139
+ * balance, so it must not require or block on one either — otherwise a $0
140
+ * provider would still fail with "Insufficient AI balance".
141
+ */
105
142
  const shouldBill: boolean =
106
- IsBillingEnabled && (llmProvider.isGlobalLlm || false);
143
+ IsBillingEnabled &&
144
+ (llmProvider.isGlobalLlm || false) &&
145
+ (llmProvider.costPerMillionTokensInUSDCents || 0) > 0;
107
146
 
108
147
  // Check balance if billing enabled and using global provider
109
148
  if (shouldBill) {
@@ -153,6 +192,8 @@ export class Service extends BaseService {
153
192
  llmProviderConfig: llmConfig,
154
193
  messages: request.messages,
155
194
  temperature: request.temperature ?? 0.7,
195
+ maxTokens: request.maxTokens,
196
+ tools: request.tools,
156
197
  });
157
198
 
158
199
  const endTime: Date = new Date();
@@ -160,7 +201,9 @@ export class Service extends BaseService {
160
201
  // Update log with success info
161
202
  logEntry.status = LlmLogStatus.Success;
162
203
  logEntry.totalTokens = response.usage?.totalTokens || 0;
163
- logEntry.responsePreview = response.content.substring(0, 2000); // Store first 2000 chars
204
+ logEntry.responsePreview = storeContentPreviews
205
+ ? response.content.substring(0, 2000) // Store first 2000 chars
206
+ : "[Redacted — this content is private to the requesting user]";
164
207
  logEntry.requestCompletedAt = endTime;
165
208
  logEntry.durationMs = endTime.getTime() - startTime.getTime();
166
209
 
@@ -176,27 +219,16 @@ export class Service extends BaseService {
176
219
 
177
220
  // Deduct from project balance
178
221
  if (totalCost > 0) {
179
- const project: Project | null = await ProjectService.findOneById({
180
- id: request.projectId,
181
- select: { aiCurrentBalanceInUSDCents: true },
182
- props: { isRoot: true },
222
+ /*
223
+ * Atomic decrement — concurrent LLM calls within and across chat
224
+ * turns must not lose each other's deductions (a read-modify-write
225
+ * here silently forgave overlapping spend).
226
+ */
227
+ await ProjectService.deductAiBalanceInUSDCents({
228
+ projectId: request.projectId,
229
+ amountInUSDCents: totalCost,
183
230
  });
184
231
 
185
- if (project) {
186
- const newBalance: number = Math.max(
187
- 0,
188
- (project.aiCurrentBalanceInUSDCents || 0) - totalCost,
189
- );
190
-
191
- await ProjectService.updateOneById({
192
- id: request.projectId,
193
- data: {
194
- aiCurrentBalanceInUSDCents: newBalance,
195
- },
196
- props: { isRoot: true },
197
- });
198
- }
199
-
200
232
  // Check if auto-recharge is needed (do this async, don't wait)
201
233
  AIBillingService.rechargeIfBalanceIsLow(request.projectId).catch(
202
234
  (err: Error) => {
@@ -213,6 +245,18 @@ export class Service extends BaseService {
213
245
  }
214
246
  }
215
247
 
248
+ /*
249
+ * Emit gen_ai.* semantic-convention attributes on the active span so
250
+ * OneUptime's own AI usage is a first-class LLM span in OneUptime's own
251
+ * telemetry (dogfooding — LlmSpanUtil detects these). Never fails the call.
252
+ */
253
+ this.setGenAiSpanAttributes({
254
+ llmType: llmProvider.llmType,
255
+ modelName: llmConfig.modelName,
256
+ usage: response.usage,
257
+ costInUSDCents: logEntry.costInUSDCents,
258
+ });
259
+
216
260
  // Save log entry
217
261
  const savedLog: LlmLog = await LlmLogService.create({
218
262
  data: logEntry,
@@ -221,6 +265,7 @@ export class Service extends BaseService {
221
265
 
222
266
  return {
223
267
  content: response.content,
268
+ toolCalls: response.toolCalls,
224
269
  llmLog: savedLog,
225
270
  };
226
271
  } catch (error) {
@@ -239,6 +284,55 @@ export class Service extends BaseService {
239
284
  throw error;
240
285
  }
241
286
  }
287
+
288
+ /*
289
+ * Set gen_ai.* attributes (OpenTelemetry GenAI semantic conventions) on the
290
+ * currently-active span. The @CaptureSpan()-wrapped caller owns that span, so
291
+ * LlmSpanUtil recognizes these calls as first-class LLM spans.
292
+ */
293
+ private setGenAiSpanAttributes(data: {
294
+ llmType: LlmType;
295
+ modelName?: string | undefined;
296
+ usage?: LLMUsage | undefined;
297
+ costInUSDCents?: number | undefined;
298
+ }): void {
299
+ try {
300
+ const span: Span | undefined = trace.getActiveSpan();
301
+ if (!span) {
302
+ return;
303
+ }
304
+
305
+ span.setAttribute("gen_ai.system", data.llmType.toString());
306
+ span.setAttribute("gen_ai.provider.name", data.llmType.toString());
307
+ span.setAttribute("gen_ai.operation.name", "chat");
308
+
309
+ if (data.modelName) {
310
+ span.setAttribute("gen_ai.request.model", data.modelName);
311
+ span.setAttribute("gen_ai.response.model", data.modelName);
312
+ }
313
+
314
+ if (data.usage) {
315
+ span.setAttribute(
316
+ "gen_ai.usage.input_tokens",
317
+ data.usage.promptTokens || 0,
318
+ );
319
+ span.setAttribute(
320
+ "gen_ai.usage.output_tokens",
321
+ data.usage.completionTokens || 0,
322
+ );
323
+ span.setAttribute(
324
+ "gen_ai.usage.total_tokens",
325
+ data.usage.totalTokens || 0,
326
+ );
327
+ }
328
+
329
+ if (data.costInUSDCents) {
330
+ span.setAttribute("gen_ai.usage.cost_usd", data.costInUSDCents / 100);
331
+ }
332
+ } catch {
333
+ // Telemetry must never fail the LLM call.
334
+ }
335
+ }
242
336
  }
243
337
 
244
338
  export default new Service();
@@ -1899,7 +1899,16 @@ export default class AnalyticsDatabaseService<
1899
1899
  return data;
1900
1900
  }
1901
1901
 
1902
- protected async getException(error: Exception): Promise<void> {
1902
+ /*
1903
+ * Rethrow hook for the catch blocks below. MUST stay synchronous and
1904
+ * `never`-returning: the call sites use `throw this.getException(error)`,
1905
+ * so if this were `async` it would return a Promise that `throw` then
1906
+ * throws verbatim (never awaited) — the real exception is lost, callers up
1907
+ * the stack catch a bare Promise (surfacing as "[object Promise]"), and the
1908
+ * un-awaited rejection becomes an unhandled rejection. Throwing directly
1909
+ * propagates the original exception on the synchronous throw path.
1910
+ */
1911
+ protected getException(error: Exception): never {
1903
1912
  throw error;
1904
1913
  }
1905
1914
 
@@ -443,7 +443,16 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
443
443
  return Promise.resolve(error);
444
444
  }
445
445
 
446
- protected async getException(error: Exception): Promise<void> {
446
+ /*
447
+ * Rethrow hook for the catch blocks below. MUST stay synchronous and
448
+ * `never`-returning: the call sites use `throw this.getException(error)`,
449
+ * so if this were `async` it would return a Promise that `throw` then
450
+ * throws verbatim (never awaited) — the real exception is lost, callers up
451
+ * the stack catch a bare Promise (surfacing as "[object Promise]"), and the
452
+ * un-awaited rejection becomes an unhandled rejection. Throwing directly
453
+ * propagates the original exception on the synchronous throw path.
454
+ */
455
+ protected getException(error: Exception): never {
447
456
  throw error;
448
457
  }
449
458
 
@@ -2106,6 +2115,25 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
2106
2115
  );
2107
2116
  }
2108
2117
 
2118
+ /*
2119
+ * Atomically subtract `value` from a numeric column in a single UPDATE
2120
+ * (SET col = col - value) so concurrent callers never lose each other's
2121
+ * writes the way a read-modify-write would. The column can go negative;
2122
+ * callers that gate on a non-negative balance simply reject the next
2123
+ * request rather than silently forgiving the overage.
2124
+ */
2125
+ protected async atomicDecrementColumnValueBy(data: {
2126
+ id: ObjectID;
2127
+ columnName: keyof TBaseModel;
2128
+ value: number;
2129
+ }): Promise<void> {
2130
+ await this.getRepository().decrement(
2131
+ { _id: data.id.toString() } as any,
2132
+ data.columnName as string,
2133
+ data.value,
2134
+ );
2135
+ }
2136
+
2109
2137
  @CaptureSpan()
2110
2138
  public async searchBy({
2111
2139
  skip,
@@ -3479,7 +3479,7 @@ ${incidentSeverity.name}
3479
3479
  const response: LLMCompletionResponse = await LLMService.getCompletion({
3480
3480
  llmProviderConfig: llmConfig,
3481
3481
  messages: aiContext.messages,
3482
- temperature: 0.7,
3482
+ temperature: 0.2,
3483
3483
  });
3484
3484
 
3485
3485
  return response.content;
@@ -135,6 +135,79 @@ export class Service extends DatabaseService<IncomingCallPolicyEscalationRule> {
135
135
  protected override async onBeforeUpdate(
136
136
  updateBy: UpdateBy<IncomingCallPolicyEscalationRule>,
137
137
  ): Promise<OnUpdate<IncomingCallPolicyEscalationRule>> {
138
+ /*
139
+ * Enforce user/schedule mutual exclusivity on update (parity with onBeforeCreate).
140
+ * Only runs when the update actually touches one of the routing-target fields, so
141
+ * internal updates (status/order via isRoot) are unaffected.
142
+ */
143
+ const data: UpdateBy<IncomingCallPolicyEscalationRule>["data"] =
144
+ updateBy.data;
145
+ const isTouchingTarget: boolean =
146
+ data.userId !== undefined ||
147
+ data.onCallDutyPolicyScheduleId !== undefined;
148
+
149
+ if (isTouchingTarget && updateBy.query._id) {
150
+ const settingUser: boolean = Boolean(data.userId);
151
+ const settingSchedule: boolean = Boolean(data.onCallDutyPolicyScheduleId);
152
+
153
+ if (settingUser && settingSchedule) {
154
+ throw new BadDataException(
155
+ "Only one of User or On-Call Schedule can be specified, not both",
156
+ );
157
+ }
158
+
159
+ // Setting one target clears the other so a rule can never hold both.
160
+ const nullableData: {
161
+ userId?: ObjectID | null;
162
+ onCallDutyPolicyScheduleId?: ObjectID | null;
163
+ } = data as {
164
+ userId?: ObjectID | null;
165
+ onCallDutyPolicyScheduleId?: ObjectID | null;
166
+ };
167
+ if (settingUser) {
168
+ nullableData.onCallDutyPolicyScheduleId = null;
169
+ }
170
+ if (settingSchedule) {
171
+ nullableData.userId = null;
172
+ }
173
+
174
+ const existing: IncomingCallPolicyEscalationRule | null =
175
+ await this.findOneBy({
176
+ query: {
177
+ _id: updateBy.query._id!,
178
+ },
179
+ select: {
180
+ userId: true,
181
+ onCallDutyPolicyScheduleId: true,
182
+ },
183
+ props: {
184
+ isRoot: true,
185
+ },
186
+ });
187
+
188
+ /*
189
+ * Whether each target will be present AFTER this update, accounting for
190
+ * fields left untouched (keep existing) and the opposite-field clearing
191
+ * done above.
192
+ */
193
+ const willHaveUser: boolean = settingUser
194
+ ? true
195
+ : data.userId === undefined
196
+ ? Boolean(existing?.userId)
197
+ : false;
198
+ const willHaveSchedule: boolean = settingSchedule
199
+ ? true
200
+ : data.onCallDutyPolicyScheduleId === undefined
201
+ ? Boolean(existing?.onCallDutyPolicyScheduleId)
202
+ : false;
203
+
204
+ if (!willHaveUser && !willHaveSchedule) {
205
+ throw new BadDataException(
206
+ "Either a User or an On-Call Schedule must be specified for the escalation rule",
207
+ );
208
+ }
209
+ }
210
+
138
211
  if (updateBy.data.order && !updateBy.props.isRoot && updateBy.query._id) {
139
212
  const resource: IncomingCallPolicyEscalationRule | null =
140
213
  await this.findOneBy({
@@ -194,8 +267,8 @@ export class Service extends DatabaseService<IncomingCallPolicyEscalationRule> {
194
267
  if (newOrder > currentOrder) {
195
268
  // moving down.
196
269
  for (const resource of resources) {
197
- if (resource.order! <= newOrder) {
198
- // increment order.
270
+ if (resource.order! > currentOrder && resource.order! <= newOrder) {
271
+ // decrement order to fill the gap left by the moved rule.
199
272
  await this.updateOneBy({
200
273
  query: {
201
274
  _id: resource._id!,
@@ -2,7 +2,10 @@ import DatabaseService from "./DatabaseService";
2
2
  import IncomingCallPolicy from "../../Models/DatabaseModels/IncomingCallPolicy";
3
3
  import IncomingCallPolicyLabelRuleEngineService from "./IncomingCallPolicyLabelRuleEngineService";
4
4
  import IncomingCallPolicyOwnerRuleEngineService from "./IncomingCallPolicyOwnerRuleEngineService";
5
- import { OnCreate } from "../Types/Database/Hooks";
5
+ import { OnCreate, OnDelete } from "../Types/Database/Hooks";
6
+ import DeleteBy from "../Types/Database/DeleteBy";
7
+ import LIMIT_MAX from "../../Types/Database/LimitMax";
8
+ import releaseIncomingCallPhoneNumber from "../Utils/IncomingCallPhoneNumber";
6
9
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
7
10
  import logger, { LogAttributes } from "../Utils/Logger";
8
11
 
@@ -11,6 +14,44 @@ export class Service extends DatabaseService<IncomingCallPolicy> {
11
14
  super(IncomingCallPolicy);
12
15
  }
13
16
 
17
+ @CaptureSpan()
18
+ protected override async onBeforeDelete(
19
+ deleteBy: DeleteBy<IncomingCallPolicy>,
20
+ ): Promise<OnDelete<IncomingCallPolicy>> {
21
+ /*
22
+ * Release any provisioned numbers before the policy rows are removed so we
23
+ * don't leave paid, orphaned numbers on the provider that can never be
24
+ * released again (the policy — and its SID — would be gone).
25
+ */
26
+ const policies: Array<IncomingCallPolicy> = await this.findBy({
27
+ query: deleteBy.query,
28
+ select: {
29
+ _id: true,
30
+ callProviderPhoneNumberId: true,
31
+ projectCallSMSConfigId: true,
32
+ },
33
+ limit: LIMIT_MAX,
34
+ skip: 0,
35
+ props: {
36
+ isRoot: true,
37
+ },
38
+ });
39
+
40
+ for (const policy of policies) {
41
+ if (policy.callProviderPhoneNumberId && policy.projectCallSMSConfigId) {
42
+ await releaseIncomingCallPhoneNumber({
43
+ projectCallSMSConfigId: policy.projectCallSMSConfigId,
44
+ callProviderPhoneNumberId: policy.callProviderPhoneNumberId,
45
+ });
46
+ }
47
+ }
48
+
49
+ return {
50
+ deleteBy,
51
+ carryForward: null,
52
+ };
53
+ }
54
+
14
55
  @CaptureSpan()
15
56
  protected override async onCreateSuccess(
16
57
  _onCreate: OnCreate<IncomingCallPolicy>,