@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
@@ -9,6 +9,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  };
10
10
  import HTTPErrorResponse from "../../../Types/API/HTTPErrorResponse";
11
11
  import URL from "../../../Types/API/URL";
12
+ import JSONFunctions from "../../../Types/JSONFunctions";
12
13
  import API from "../../../Utils/API";
13
14
  import LlmType from "../../../Types/LLM/LlmType";
14
15
  import BadDataException from "../../../Types/Exception/BadDataException";
@@ -21,6 +22,7 @@ class LLMService {
21
22
  case LlmType.OpenAI:
22
23
  case LlmType.Groq:
23
24
  case LlmType.Mistral:
25
+ case LlmType.OpenAICompatible:
24
26
  return await this.getOpenAICompatibleCompletion(config, request);
25
27
  case LlmType.AzureOpenAI:
26
28
  return await this.getAzureOpenAICompletion(config, request);
@@ -32,11 +34,227 @@ class LLMService {
32
34
  throw new BadDataException(`Unsupported LLM type: ${config.llmType}`);
33
35
  }
34
36
  }
35
- static async getOpenAICompatibleCompletion(config, request) {
37
+ /*
38
+ * OpenAI-compatible wire format (OpenAI, Groq, Mistral, Azure OpenAI).
39
+ */
40
+ static toOpenAIMessages(messages) {
41
+ return messages.map((msg) => {
42
+ if (msg.role === "assistant" && msg.toolCalls && msg.toolCalls.length) {
43
+ return {
44
+ role: "assistant",
45
+ content: msg.content || null,
46
+ tool_calls: msg.toolCalls.map((toolCall) => {
47
+ return {
48
+ id: toolCall.id,
49
+ type: "function",
50
+ function: {
51
+ name: toolCall.name,
52
+ arguments: JSON.stringify(toolCall.arguments),
53
+ },
54
+ };
55
+ }),
56
+ };
57
+ }
58
+ if (msg.role === "tool") {
59
+ return {
60
+ role: "tool",
61
+ tool_call_id: msg.toolCallId || "",
62
+ content: msg.content,
63
+ };
64
+ }
65
+ return {
66
+ role: msg.role,
67
+ content: msg.content,
68
+ };
69
+ });
70
+ }
71
+ static toOpenAITools(tools) {
72
+ return tools.map((tool) => {
73
+ return {
74
+ type: "function",
75
+ function: {
76
+ name: tool.name,
77
+ description: tool.description,
78
+ parameters: tool.inputSchema,
79
+ },
80
+ };
81
+ });
82
+ }
83
+ static parseOpenAIToolCalls(message) {
84
+ const rawToolCalls = message["tool_calls"];
85
+ if (!rawToolCalls || rawToolCalls.length === 0) {
86
+ return undefined;
87
+ }
88
+ return rawToolCalls.map((rawToolCall, index) => {
89
+ const fn = rawToolCall["function"] || {};
90
+ const parsed = this.parseToolCallArguments(fn["arguments"] || "{}");
91
+ return {
92
+ id: rawToolCall["id"] || `tool_call_${index}`,
93
+ name: fn["name"] || "",
94
+ arguments: parsed.arguments,
95
+ argumentsParseError: parsed.error,
96
+ };
97
+ });
98
+ }
99
+ /*
100
+ * Models sometimes emit slightly malformed argument JSON (trailing commas,
101
+ * single quotes). Try strict JSON first, then tolerant JSON5, and report a
102
+ * parse error instead of silently executing with empty arguments.
103
+ */
104
+ static parseToolCallArguments(rawArguments) {
105
+ try {
106
+ return { arguments: JSON.parse(rawArguments) };
107
+ }
108
+ catch (_a) {
109
+ // fall through to tolerant parsing
110
+ }
111
+ try {
112
+ const parsed = JSONFunctions.parse(rawArguments);
113
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
114
+ return { arguments: parsed };
115
+ }
116
+ return {
117
+ arguments: {},
118
+ error: "Tool arguments were not a JSON object.",
119
+ };
120
+ }
121
+ catch (_b) {
122
+ return {
123
+ arguments: {},
124
+ error: "Tool arguments were malformed JSON and could not be parsed.",
125
+ };
126
+ }
127
+ }
128
+ static buildOpenAIRequestBody(modelName, request) {
36
129
  var _a;
37
- if (!config.apiKey) {
130
+ const data = {
131
+ model: modelName,
132
+ messages: this.toOpenAIMessages(request.messages),
133
+ temperature: (_a = request.temperature) !== null && _a !== void 0 ? _a : 0.7,
134
+ };
135
+ if (request.maxTokens) {
136
+ data["max_tokens"] = request.maxTokens;
137
+ }
138
+ if (request.tools && request.tools.length > 0) {
139
+ data["tools"] = this.toOpenAITools(request.tools);
140
+ }
141
+ return data;
142
+ }
143
+ static parseOpenAIResponse(jsonData, providerName) {
144
+ var _a;
145
+ const choices = jsonData["choices"];
146
+ if (!choices || choices.length === 0) {
147
+ throw new BadDataException(`No response from ${providerName}`);
148
+ }
149
+ const message = choices[0]["message"];
150
+ const usage = jsonData["usage"];
151
+ const toolCalls = this.parseOpenAIToolCalls(message);
152
+ /*
153
+ * OpenAI (and Azure OpenAI) automatically cache a stable prompt prefix
154
+ * once it is long enough and report the cache hit under
155
+ * prompt_tokens_details.cached_tokens — surface it for cost visibility.
156
+ */
157
+ const cachedTokens = usage
158
+ ? (_a = usage["prompt_tokens_details"]) === null || _a === void 0 ? void 0 : _a["cached_tokens"]
159
+ : undefined;
160
+ return {
161
+ content: message["content"] || "",
162
+ toolCalls: toolCalls,
163
+ stopReason: toolCalls && toolCalls.length > 0 ? "tool_use" : "stop",
164
+ usage: usage
165
+ ? {
166
+ promptTokens: usage["prompt_tokens"],
167
+ completionTokens: usage["completion_tokens"],
168
+ totalTokens: usage["total_tokens"],
169
+ cachedInputTokens: cachedTokens || undefined,
170
+ }
171
+ : undefined,
172
+ };
173
+ }
174
+ /*
175
+ * Build the chat completions URL for an OpenAI-compatible server from the
176
+ * configured base URL. Users enter the base URL in a few different ways, and
177
+ * we normalize all of them onto the right endpoint instead of 404-ing:
178
+ *
179
+ * - Already a full endpoint (".../chat/completions") -> used as-is.
180
+ * - Includes a path (".../v1", ".../openai/v1") -> append "/chat/completions".
181
+ * - Bare server root ("http://host:8000") -> append "/v1/chat/completions",
182
+ * since vLLM, LocalAI and similar servers expose the OpenAI-compatible API
183
+ * under /v1 by default. This is the most common self-hosted setup and the
184
+ * easiest one for users to get wrong (omitting /v1 returns FastAPI's
185
+ * {"detail":"Not Found"}).
186
+ *
187
+ * The endpoint segment is only ever appended to the PATH portion: any
188
+ * ?query or #fragment on the base URL is split off first and re-attached
189
+ * afterwards (otherwise "/chat/completions" would land inside the query or
190
+ * fragment). Trailing slashes are stripped so we never emit
191
+ * ".../v1//chat/completions", and the URL scheme is lower-cased because URL
192
+ * schemes are case-insensitive but downstream URL parsing only recognizes
193
+ * lowercase http/https.
194
+ */
195
+ static buildOpenAICompatibleChatCompletionsUrl(baseUrl) {
196
+ const raw = baseUrl.trim();
197
+ // Split off #fragment, then ?query, so we can operate on the path alone.
198
+ const fragmentIndex = raw.indexOf("#");
199
+ const fragment = fragmentIndex >= 0 ? raw.substring(fragmentIndex) : "";
200
+ const withoutFragment = fragmentIndex >= 0 ? raw.substring(0, fragmentIndex) : raw;
201
+ const queryIndex = withoutFragment.indexOf("?");
202
+ const query = queryIndex >= 0 ? withoutFragment.substring(queryIndex) : "";
203
+ let base = queryIndex >= 0
204
+ ? withoutFragment.substring(0, queryIndex)
205
+ : withoutFragment;
206
+ /*
207
+ * Lower-case the scheme (e.g. "HTTP://" -> "http://") and strip trailing
208
+ * slashes.
209
+ */
210
+ const schemeRegex = /^[a-z][a-z0-9+.-]*:\/\//i;
211
+ base = base
212
+ .replace(schemeRegex, (scheme) => {
213
+ return scheme.toLowerCase();
214
+ })
215
+ .replace(/\/+$/, "");
216
+ let path;
217
+ const fullEndpointRegex = /\/chat\/completions$/i;
218
+ const hasPathAfterHostRegex = /^[a-z][a-z0-9+.-]*:\/\/[^/]+\/.+/i;
219
+ if (fullEndpointRegex.test(base)) {
220
+ // The user already pointed us at the full endpoint.
221
+ path = base;
222
+ }
223
+ else if (hasPathAfterHostRegex.test(base)) {
224
+ /*
225
+ * The base URL carries a path after the host[:port] (e.g.
226
+ * "http://host:8000/v1" or ".../openai/v1") — trust it and only append
227
+ * the endpoint.
228
+ */
229
+ path = `${base}/chat/completions`;
230
+ }
231
+ else {
232
+ /*
233
+ * Bare server root ("http://host:8000") — add the conventional /v1
234
+ * prefix that OpenAI-compatible servers (vLLM, LocalAI, ...) use.
235
+ */
236
+ path = `${base}/v1/chat/completions`;
237
+ }
238
+ return `${path}${query}${fragment}`;
239
+ }
240
+ static async getOpenAICompatibleCompletion(config, request) {
241
+ /*
242
+ * Generic OpenAI-compatible servers (vLLM, LocalAI, etc.) are usually
243
+ * self-hosted, frequently keyless, and have no canonical endpoint or
244
+ * default model — so the API key is optional but the base URL and model
245
+ * name must be provided. The hosted providers (OpenAI, Groq, Mistral)
246
+ * keep requiring a key and fall back to sensible defaults.
247
+ */
248
+ const isGenericOpenAICompatible = config.llmType === LlmType.OpenAICompatible;
249
+ if (!isGenericOpenAICompatible && !config.apiKey) {
38
250
  throw new BadDataException(`${config.llmType} API key is required`);
39
251
  }
252
+ if (isGenericOpenAICompatible && !config.baseUrl) {
253
+ throw new BadDataException("Base URL is required for OpenAI-compatible providers (e.g. http://your-vllm-server:8000/v1)");
254
+ }
255
+ if (isGenericOpenAICompatible && !config.modelName) {
256
+ throw new BadDataException("Model Name is required for OpenAI-compatible providers. It must match a model your server exposes.");
257
+ }
40
258
  const defaultBaseUrls = {
41
259
  [LlmType.OpenAI]: "https://api.openai.com/v1",
42
260
  [LlmType.Groq]: "https://api.groq.com/openai/v1",
@@ -52,21 +270,11 @@ class LLMService {
52
270
  "https://api.openai.com/v1";
53
271
  const modelName = config.modelName || defaultModels[config.llmType] || "gpt-4o";
54
272
  const response = await API.post({
55
- url: URL.fromString(`${baseUrl}/chat/completions`),
56
- data: {
57
- model: modelName,
58
- messages: request.messages.map((msg) => {
59
- return {
60
- role: msg.role,
61
- content: msg.content,
62
- };
63
- }),
64
- temperature: (_a = request.temperature) !== null && _a !== void 0 ? _a : 0.7,
65
- },
66
- headers: {
67
- Authorization: `Bearer ${config.apiKey}`,
68
- "Content-Type": "application/json",
69
- },
273
+ url: URL.fromString(this.buildOpenAICompatibleChatCompletionsUrl(baseUrl)),
274
+ data: this.buildOpenAIRequestBody(modelName, request),
275
+ headers: Object.assign({ "Content-Type": "application/json" }, (config.apiKey
276
+ ? { Authorization: `Bearer ${config.apiKey}` }
277
+ : {})),
70
278
  options: {
71
279
  retries: 2,
72
280
  exponentialBackoff: true,
@@ -82,23 +290,7 @@ class LLMService {
82
290
  logger.error(response, logAttributes);
83
291
  throw new BadDataException(`${config.llmType} API error: ${JSON.stringify(response.jsonData)}`);
84
292
  }
85
- const jsonData = response.jsonData;
86
- const choices = jsonData["choices"];
87
- if (!choices || choices.length === 0) {
88
- throw new BadDataException(`No response from ${config.llmType}`);
89
- }
90
- const message = choices[0]["message"];
91
- const usage = jsonData["usage"];
92
- return {
93
- content: message["content"],
94
- usage: usage
95
- ? {
96
- promptTokens: usage["prompt_tokens"],
97
- completionTokens: usage["completion_tokens"],
98
- totalTokens: usage["total_tokens"],
99
- }
100
- : undefined,
101
- };
293
+ return this.parseOpenAIResponse(response.jsonData, config.llmType);
102
294
  }
103
295
  static buildAzureOpenAIChatCompletionsUrl(baseUrl) {
104
296
  const trimmed = baseUrl.replace(/\/+$/, "");
@@ -112,7 +304,6 @@ class LLMService {
112
304
  return `${pathPart}/chat/completions?${params.toString()}`;
113
305
  }
114
306
  static async getAzureOpenAICompletion(config, request) {
115
- var _a;
116
307
  if (!config.apiKey) {
117
308
  throw new BadDataException("Azure OpenAI API key is required");
118
309
  }
@@ -123,16 +314,7 @@ class LLMService {
123
314
  const requestUrl = LLMService.buildAzureOpenAIChatCompletionsUrl(config.baseUrl);
124
315
  const response = await API.post({
125
316
  url: URL.fromString(requestUrl),
126
- data: {
127
- model: modelName,
128
- messages: request.messages.map((msg) => {
129
- return {
130
- role: msg.role,
131
- content: msg.content,
132
- };
133
- }),
134
- temperature: (_a = request.temperature) !== null && _a !== void 0 ? _a : 0.7,
135
- },
317
+ data: this.buildOpenAIRequestBody(modelName, request),
136
318
  headers: {
137
319
  "api-key": config.apiKey,
138
320
  "Content-Type": "application/json",
@@ -152,23 +334,83 @@ class LLMService {
152
334
  logger.error(response, logAttributes);
153
335
  throw new BadDataException(`Azure OpenAI API error: ${JSON.stringify(response.jsonData)}`);
154
336
  }
155
- const jsonData = response.jsonData;
156
- const choices = jsonData["choices"];
157
- if (!choices || choices.length === 0) {
158
- throw new BadDataException("No response from Azure OpenAI");
159
- }
160
- const message = choices[0]["message"];
161
- const usage = jsonData["usage"];
162
- return {
163
- content: message["content"],
164
- usage: usage
165
- ? {
166
- promptTokens: usage["prompt_tokens"],
167
- completionTokens: usage["completion_tokens"],
168
- totalTokens: usage["total_tokens"],
337
+ return this.parseOpenAIResponse(response.jsonData, "Azure OpenAI");
338
+ }
339
+ static toAnthropicMessages(messages) {
340
+ const anthropicMessages = [];
341
+ for (const msg of messages) {
342
+ if (msg.role === "system") {
343
+ continue; // hoisted separately
344
+ }
345
+ if (msg.role === "assistant" && msg.toolCalls && msg.toolCalls.length) {
346
+ const contentBlocks = [];
347
+ if (msg.content) {
348
+ contentBlocks.push({ type: "text", text: msg.content });
169
349
  }
170
- : undefined,
171
- };
350
+ for (const toolCall of msg.toolCalls) {
351
+ contentBlocks.push({
352
+ type: "tool_use",
353
+ id: toolCall.id,
354
+ name: toolCall.name,
355
+ input: toolCall.arguments,
356
+ });
357
+ }
358
+ anthropicMessages.push({ role: "assistant", content: contentBlocks });
359
+ continue;
360
+ }
361
+ if (msg.role === "tool") {
362
+ const toolResultBlock = {
363
+ type: "tool_result",
364
+ tool_use_id: msg.toolCallId || "",
365
+ content: msg.content,
366
+ };
367
+ /*
368
+ * Tool results must be user messages. Merge consecutive tool
369
+ * results into one user message so roles keep alternating.
370
+ */
371
+ const lastMessage = anthropicMessages[anthropicMessages.length - 1];
372
+ if (lastMessage &&
373
+ lastMessage["role"] === "user" &&
374
+ Array.isArray(lastMessage["content"])) {
375
+ lastMessage["content"].push(toolResultBlock);
376
+ }
377
+ else {
378
+ anthropicMessages.push({
379
+ role: "user",
380
+ content: [toolResultBlock],
381
+ });
382
+ }
383
+ continue;
384
+ }
385
+ /*
386
+ * Anthropic requires strictly alternating user/assistant turns and
387
+ * returns a 400 on two consecutive same-role messages. The agent loop
388
+ * can legitimately emit back-to-back user turns (e.g. a tool_result
389
+ * user message immediately followed by the "budget exhausted, answer
390
+ * now" nudge), so coalesce a run of same-role messages into one instead
391
+ * of failing the whole request.
392
+ */
393
+ const previousMessage = anthropicMessages[anthropicMessages.length - 1];
394
+ if (previousMessage && previousMessage["role"] === msg.role) {
395
+ if (typeof previousMessage["content"] === "string") {
396
+ previousMessage["content"] =
397
+ `${previousMessage["content"]}\n\n${msg.content}`;
398
+ continue;
399
+ }
400
+ if (Array.isArray(previousMessage["content"])) {
401
+ previousMessage["content"].push({
402
+ type: "text",
403
+ text: msg.content,
404
+ });
405
+ continue;
406
+ }
407
+ }
408
+ anthropicMessages.push({
409
+ role: msg.role,
410
+ content: msg.content,
411
+ });
412
+ }
413
+ return anthropicMessages;
172
414
  }
173
415
  static async getAnthropicCompletion(config, request) {
174
416
  var _a;
@@ -177,27 +419,50 @@ class LLMService {
177
419
  }
178
420
  const baseUrl = config.baseUrl || "https://api.anthropic.com/v1";
179
421
  const modelName = config.modelName || "claude-sonnet-4-20250514";
180
- // Anthropic requires system message to be separate
181
422
  let systemMessage = "";
182
- const userMessages = [];
183
423
  for (const msg of request.messages) {
184
424
  if (msg.role === "system") {
185
425
  systemMessage = msg.content;
186
426
  }
187
- else {
188
- userMessages.push({
189
- role: msg.role,
190
- content: msg.content,
191
- });
192
- }
193
427
  }
194
428
  const requestData = {
195
429
  model: modelName,
196
- messages: userMessages,
430
+ messages: this.toAnthropicMessages(request.messages),
197
431
  temperature: (_a = request.temperature) !== null && _a !== void 0 ? _a : 0.7,
432
+ // Anthropic requires max_tokens on every request.
433
+ max_tokens: request.maxTokens || LLMService.ANTHROPIC_DEFAULT_MAX_TOKENS,
198
434
  };
435
+ /*
436
+ * Prompt caching. The system prompt and tool definitions are the large,
437
+ * stable prefix re-sent on every turn of the agent loop, so caching them is
438
+ * the biggest single cost + latency lever (cached input is billed at ~10%).
439
+ * An ephemeral cache_control breakpoint on the system block and on the LAST
440
+ * tool caches the whole system + tools prefix. cache_control is GA under
441
+ * anthropic-version 2023-06-01, so no beta header is required.
442
+ */
199
443
  if (systemMessage) {
200
- requestData["system"] = systemMessage;
444
+ requestData["system"] = [
445
+ {
446
+ type: "text",
447
+ text: systemMessage,
448
+ cache_control: { type: "ephemeral" },
449
+ },
450
+ ];
451
+ }
452
+ if (request.tools && request.tools.length > 0) {
453
+ const anthropicTools = request.tools.map((tool) => {
454
+ return {
455
+ name: tool.name,
456
+ description: tool.description,
457
+ input_schema: tool.inputSchema,
458
+ };
459
+ });
460
+ // A breakpoint on the last tool caches the entire tools block before it.
461
+ const lastTool = anthropicTools[anthropicTools.length - 1];
462
+ if (lastTool) {
463
+ lastTool["cache_control"] = { type: "ephemeral" };
464
+ }
465
+ requestData["tools"] = anthropicTools;
201
466
  }
202
467
  const response = await API.post({
203
468
  url: URL.fromString(`${baseUrl}/messages`),
@@ -227,46 +492,94 @@ class LLMService {
227
492
  if (!content || content.length === 0) {
228
493
  throw new BadDataException("No response from Anthropic");
229
494
  }
230
- const textContent = content.find((c) => {
231
- return c["type"] === "text";
495
+ const textContent = content
496
+ .filter((block) => {
497
+ return block["type"] === "text";
498
+ })
499
+ .map((block) => {
500
+ return block["text"];
501
+ })
502
+ .join("");
503
+ const toolCalls = content
504
+ .filter((block) => {
505
+ return block["type"] === "tool_use";
506
+ })
507
+ .map((block) => {
508
+ return {
509
+ id: block["id"] || "",
510
+ name: block["name"] || "",
511
+ arguments: block["input"] || {},
512
+ };
232
513
  });
233
- if (!textContent) {
514
+ if (!textContent && toolCalls.length === 0) {
234
515
  throw new BadDataException("No text content in Anthropic response");
235
516
  }
236
517
  const usage = jsonData["usage"];
237
518
  return {
238
- content: textContent["text"],
519
+ content: textContent,
520
+ toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
521
+ stopReason: jsonData["stop_reason"] === "tool_use" ? "tool_use" : "stop",
239
522
  usage: usage
240
523
  ? {
241
- promptTokens: usage["input_tokens"],
242
- completionTokens: usage["output_tokens"],
524
+ promptTokens: usage["input_tokens"] || 0,
525
+ completionTokens: usage["output_tokens"] || 0,
526
+ /*
527
+ * Anthropic reports cache-read and cache-creation input tokens
528
+ * separately from input_tokens. Surface them and fold them into
529
+ * totalTokens so the logged total reflects the full billable input.
530
+ */
531
+ cachedInputTokens: usage["cache_read_input_tokens"] || undefined,
532
+ cacheCreationTokens: usage["cache_creation_input_tokens"] || undefined,
243
533
  totalTokens: (usage["input_tokens"] || 0) +
534
+ (usage["cache_read_input_tokens"] || 0) +
535
+ (usage["cache_creation_input_tokens"] || 0) +
244
536
  (usage["output_tokens"] || 0),
245
537
  }
246
538
  : undefined,
247
539
  };
248
540
  }
541
+ /*
542
+ * Ollama native /api/chat. Deliberately NOT routed through the
543
+ * OpenAI-compatible branch: Ollama deployments are keyless by design and
544
+ * the OpenAI branch requires an API key.
545
+ */
249
546
  static async getOllamaCompletion(config, request) {
250
547
  var _a;
251
548
  if (!config.baseUrl) {
252
549
  throw new BadDataException("Ollama base URL is required");
253
550
  }
254
551
  const modelName = config.modelName || "llama2";
255
- const response = await API.post({
256
- url: URL.fromString(`${config.baseUrl}/api/chat`),
257
- data: {
258
- model: modelName,
259
- messages: request.messages.map((msg) => {
552
+ const requestData = {
553
+ model: modelName,
554
+ messages: request.messages.map((msg) => {
555
+ if (msg.role === "assistant" && msg.toolCalls && msg.toolCalls.length) {
260
556
  return {
261
- role: msg.role,
262
- content: msg.content,
557
+ role: "assistant",
558
+ content: msg.content || "",
559
+ tool_calls: msg.toolCalls.map((toolCall) => {
560
+ return {
561
+ function: {
562
+ name: toolCall.name,
563
+ arguments: toolCall.arguments,
564
+ },
565
+ };
566
+ }),
263
567
  };
264
- }),
265
- stream: false,
266
- options: {
267
- temperature: (_a = request.temperature) !== null && _a !== void 0 ? _a : 0.7,
268
- },
269
- },
568
+ }
569
+ return {
570
+ role: msg.role,
571
+ content: msg.content,
572
+ };
573
+ }),
574
+ stream: false,
575
+ options: Object.assign({ temperature: (_a = request.temperature) !== null && _a !== void 0 ? _a : 0.7 }, (request.maxTokens ? { num_predict: request.maxTokens } : {})),
576
+ };
577
+ if (request.tools && request.tools.length > 0) {
578
+ requestData["tools"] = this.toOpenAITools(request.tools);
579
+ }
580
+ const response = await API.post({
581
+ url: URL.fromString(`${config.baseUrl}/api/chat`),
582
+ data: requestData,
270
583
  headers: {
271
584
  "Content-Type": "application/json",
272
585
  },
@@ -290,9 +603,50 @@ class LLMService {
290
603
  if (!message) {
291
604
  throw new BadDataException("No response from Ollama");
292
605
  }
606
+ const rawToolCalls = message["tool_calls"];
607
+ let toolCalls = undefined;
608
+ if (rawToolCalls && rawToolCalls.length > 0) {
609
+ toolCalls = rawToolCalls.map((rawToolCall, index) => {
610
+ const fn = rawToolCall["function"] || {};
611
+ let parsedArguments = {};
612
+ let parseError = undefined;
613
+ const rawArguments = fn["arguments"];
614
+ if (typeof rawArguments === "string") {
615
+ const parsed = this.parseToolCallArguments(rawArguments);
616
+ parsedArguments = parsed.arguments;
617
+ parseError = parsed.error;
618
+ }
619
+ else if (rawArguments && typeof rawArguments === "object") {
620
+ parsedArguments = rawArguments;
621
+ }
622
+ // Ollama does not return tool-call ids; synthesize stable ones.
623
+ return {
624
+ id: `tool_call_${index}`,
625
+ name: fn["name"] || "",
626
+ arguments: parsedArguments,
627
+ argumentsParseError: parseError,
628
+ };
629
+ });
630
+ }
631
+ /*
632
+ * Ollama reports token counts on the final /api/chat response as
633
+ * prompt_eval_count (input) and eval_count (output). Populate usage from
634
+ * them so LlmLog, the AI dashboards and (costed self-hosted Ollama)
635
+ * billing are not silently blind to token spend.
636
+ */
637
+ const ollamaPromptTokens = jsonData["prompt_eval_count"] || 0;
638
+ const ollamaCompletionTokens = jsonData["eval_count"] || 0;
293
639
  return {
294
- content: message["content"],
295
- usage: undefined, // Ollama doesn't provide token usage in the same way
640
+ content: message["content"] || "",
641
+ toolCalls: toolCalls,
642
+ stopReason: toolCalls && toolCalls.length > 0 ? "tool_use" : "stop",
643
+ usage: ollamaPromptTokens || ollamaCompletionTokens
644
+ ? {
645
+ promptTokens: ollamaPromptTokens,
646
+ completionTokens: ollamaCompletionTokens,
647
+ totalTokens: ollamaPromptTokens + ollamaCompletionTokens,
648
+ }
649
+ : undefined,
296
650
  };
297
651
  }
298
652
  }
@@ -301,6 +655,12 @@ class LLMService {
301
655
  * ?api-version=... in their configured base URL.
302
656
  */
303
657
  LLMService.AZURE_OPENAI_DEFAULT_API_VERSION = "2024-10-21";
658
+ /*
659
+ * Anthropic wire format. System message is hoisted, tool results ride in
660
+ * user messages as tool_result blocks, and max_tokens is required by the
661
+ * API.
662
+ */
663
+ LLMService.ANTHROPIC_DEFAULT_MAX_TOKENS = 4096;
304
664
  export default LLMService;
305
665
  __decorate([
306
666
  CaptureSpan(),