@oneuptime/common 12.0.23 → 12.0.24

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 (294) hide show
  1. package/Models/DatabaseModels/DetectionRule.ts +55 -0
  2. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +27 -7
  3. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +67 -0
  4. package/Models/DatabaseModels/Project.ts +68 -0
  5. package/Models/DatabaseModels/User.ts +68 -0
  6. package/Server/API/TelemetryAPI.ts +29 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.ts +28 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.ts +49 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.ts +33 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  11. package/Server/Middleware/GzipRequestBody.ts +311 -0
  12. package/Server/Middleware/MultipartFormData.ts +87 -3
  13. package/Server/Services/DetectionRuleService.ts +73 -6
  14. package/Server/Services/Index.ts +205 -0
  15. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +59 -0
  16. package/Server/Services/NetworkDeviceService.ts +148 -0
  17. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +65 -0
  18. package/Server/Services/OnCallDutyPolicyFeedService.ts +1 -1
  19. package/Server/Services/ProjectService.ts +29 -19
  20. package/Server/Services/SecurityEventService.ts +90 -13
  21. package/Server/Services/StatusPageResourceService.ts +223 -0
  22. package/Server/Services/TelemetryAttributeService.ts +17 -0
  23. package/Server/Services/UserService.ts +4 -6
  24. package/Server/Types/Markdown.ts +161 -67
  25. package/Server/Utils/AI/Toolbox/OnCallTools.ts +12 -4
  26. package/Server/Utils/AnalyticsDatabase/Statement.ts +13 -1
  27. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +297 -6
  28. package/Server/Utils/Attribution.ts +4 -0
  29. package/Server/Utils/Marketing/MarketingEventUtil.ts +45 -7
  30. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +55 -3
  31. package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +21 -0
  32. package/Server/Utils/StartServer.ts +12 -32
  33. package/Server/Utils/Telemetry/LlmCostBudgetEvaluator.ts +101 -4
  34. package/Server/Utils/Telemetry/LlmMetricSpend.ts +130 -0
  35. package/Server/Views/Partials/AnalyticsConsent.ejs +159 -102
  36. package/Server/Views/Partials/Head.ejs +2 -1
  37. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +776 -38
  38. package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +359 -0
  39. package/Tests/App/Dashboard/CorrelateGraph.test.tsx +865 -0
  40. package/Tests/App/Dashboard/CorrelationGraph.test.ts +346 -0
  41. package/Tests/App/Dashboard/CriteriaFilterConditionDropdown.test.tsx +256 -0
  42. package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +738 -0
  43. package/Tests/App/Dashboard/CriteriaFilterMonitorTypeChange.test.ts +1122 -0
  44. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +283 -0
  45. package/Tests/App/Dashboard/ExternalStatusPageCriteriaFilter.test.ts +407 -0
  46. package/Tests/App/Dashboard/MetricSeriesInvestigateMenu.test.tsx +5 -14
  47. package/Tests/App/Dashboard/MonitorCriteriaActionToggles.test.tsx +426 -0
  48. package/Tests/App/Dashboard/MonitorStepsCriteriaAlignmentWiring.test.tsx +352 -0
  49. package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +278 -0
  50. package/Tests/App/Dashboard/OnCallLayerShiftPreviewOverrides.test.ts +237 -0
  51. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +2 -2
  52. package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +460 -0
  53. package/Tests/App/Dashboard/SecurityEventAttributeUtil.test.ts +171 -0
  54. package/Tests/App/Dashboard/SecurityEventCorrelation.test.ts +857 -0
  55. package/Tests/App/Dashboard/SecurityEventDetailObservables.test.tsx +194 -0
  56. package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +124 -0
  57. package/Tests/App/Dashboard/SecurityEventsMonitorStepForm.test.tsx +79 -19
  58. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +382 -0
  59. package/Tests/App/StatusPage/BulkAddStatusPageMonitors.test.ts +216 -0
  60. package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +590 -11
  61. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +757 -0
  62. package/Tests/Models/DiscoveryScanNameColumn.test.ts +293 -0
  63. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +564 -0
  64. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +120 -4
  65. package/Tests/Server/Middleware/GzipRequestBody.test.ts +725 -0
  66. package/Tests/Server/Middleware/MultipartFormData.test.ts +298 -0
  67. package/Tests/Server/Services/AddDetectionRuleDistinctCountColumnsMigration.test.ts +311 -0
  68. package/Tests/Server/Services/DetectionRuleService.test.ts +134 -2
  69. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +7 -1
  70. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +131 -0
  71. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +194 -0
  72. package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +800 -0
  73. package/Tests/Server/Services/OnCallScheduleAttachRosterRefresh.test.ts +244 -0
  74. package/Tests/Server/Services/SecurityEventService.test.ts +376 -0
  75. package/Tests/Server/Services/StatusPageResourceDuplicates.test.ts +703 -0
  76. package/Tests/Server/Services/TelemetryAttributeServiceSecurityEvent.test.ts +256 -0
  77. package/Tests/Server/Types/Workflow/Components/ComponentRegistryParity.test.ts +417 -0
  78. package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWhereOperators.test.ts +677 -0
  79. package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +43 -0
  80. package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +15 -11
  81. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +369 -8
  82. package/Tests/Server/Utils/SecurityEvent/SigmaClickhouseCompiler.test.ts +35 -0
  83. package/Tests/Server/Utils/Telemetry/LlmCostBudgetEvaluator.test.ts +368 -4
  84. package/Tests/Server/Utils/Telemetry/LlmMetricSpend.test.ts +245 -0
  85. package/Tests/Server/Views/AnalyticsConsentPartial.test.ts +48 -5
  86. package/Tests/Types/Code/YamlSyntax.test.ts +396 -0
  87. package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +957 -0
  88. package/Tests/Types/Monitor/MonitorCriteriaActionValidation.test.ts +598 -0
  89. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +49 -0
  90. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +6 -6
  91. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +4 -4
  92. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +4 -3
  93. package/Tests/Types/Telemetry/LlmMetricConventions.test.ts +193 -0
  94. package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +0 -12
  95. package/Tests/UI/Components/CardModelDetailEdit.test.tsx +1 -17
  96. package/Tests/UI/Components/CodeEditor.test.tsx +474 -10
  97. package/Tests/UI/Components/Detail/YamlField.test.tsx +105 -0
  98. package/Tests/UI/Components/EntityDropdownLabelsBulkAdd.test.tsx +319 -0
  99. package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +231 -0
  100. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +1 -0
  101. package/Tests/UI/Components/Forms/ValidationYAML.test.ts +234 -0
  102. package/Tests/UI/Components/ModelTable/AttributeColumns.test.tsx +573 -0
  103. package/Tests/UI/Components/ModelTable/BaseModelTableAttributeColumns.test.tsx +824 -0
  104. package/Tests/UI/Components/ModelTable/ColumnCustomizationModalAddableColumns.test.tsx +707 -0
  105. package/Tests/UI/Components/SideOver.test.tsx +1 -1
  106. package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +294 -0
  107. package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +436 -0
  108. package/Tests/UI/Components/TableBulkCsvExport.test.tsx +6 -2
  109. package/Tests/UI/Components/Toggle.test.tsx +25 -0
  110. package/Tests/UI/Components/YamlEditor.test.tsx +847 -0
  111. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +252 -0
  112. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +221 -0
  113. package/Tests/Utils/NetworkDiscovery/ScanNameUtil.test.ts +312 -0
  114. package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +468 -0
  115. package/Tests/Utils/Telemetry/LlmMetricQuery.test.ts +472 -0
  116. package/Types/Code/YamlSyntax.ts +396 -0
  117. package/Types/Exception/ExceptionCode.ts +1 -0
  118. package/Types/Exception/PayloadTooLargeException.ts +8 -0
  119. package/Types/Marketing/Attribution.ts +10 -0
  120. package/Types/Marketing/MarketingEvent.ts +4 -0
  121. package/Types/Monitor/MonitorCriteriaInstance.ts +116 -56
  122. package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +2 -1
  123. package/Types/SecurityEvent/DetectionFindingConstants.ts +11 -0
  124. package/Types/Telemetry/LlmMetricConventions.ts +124 -0
  125. package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +3 -0
  126. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +10 -1
  127. package/UI/Components/CodeEditor/CodeEditor.tsx +241 -79
  128. package/UI/Components/CodeEditor/YamlEditor.tsx +369 -0
  129. package/UI/Components/Detail/Detail.tsx +10 -0
  130. package/UI/Components/EntityDropdown/EntityDropdown.tsx +33 -0
  131. package/UI/Components/Forms/Fields/FormField.tsx +31 -0
  132. package/UI/Components/Forms/Types/Field.ts +8 -0
  133. package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
  134. package/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.ts +2 -0
  135. package/UI/Components/Forms/Validation.ts +46 -0
  136. package/UI/Components/Input/Input.tsx +3 -0
  137. package/UI/Components/ModelTable/AttributeColumns.tsx +321 -0
  138. package/UI/Components/ModelTable/BaseModelTable.tsx +263 -14
  139. package/UI/Components/ModelTable/Column.ts +8 -0
  140. package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +310 -0
  141. package/UI/Components/ModelTable/ColumnPreference.ts +13 -1
  142. package/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.tsx +2 -2
  143. package/UI/Components/SideOver/SideOver.tsx +5 -5
  144. package/UI/Components/StatusPage/ResourceGrid.tsx +82 -2
  145. package/UI/Components/StatusPage/ResourceList.tsx +197 -38
  146. package/UI/Components/Toggle/Toggle.tsx +9 -1
  147. package/UI/Components/Types/FieldType.ts +1 -0
  148. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +73 -1
  149. package/Utils/NetworkDiscovery/ScanNameUtil.ts +181 -0
  150. package/Utils/StatusPage/ResourceExplorer.ts +258 -0
  151. package/Utils/Telemetry/LlmMetricQuery.ts +204 -0
  152. package/build/dist/Models/DatabaseModels/DetectionRule.js +57 -0
  153. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  154. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +27 -7
  155. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
  156. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +69 -0
  157. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  158. package/build/dist/Models/DatabaseModels/Project.js +76 -0
  159. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  160. package/build/dist/Models/DatabaseModels/User.js +76 -0
  161. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  162. package/build/dist/Server/API/TelemetryAPI.js +17 -0
  163. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  164. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js +21 -0
  165. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js.map +1 -0
  166. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js +42 -0
  167. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js.map +1 -0
  168. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js +22 -0
  169. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js.map +1 -0
  170. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  171. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  172. package/build/dist/Server/Middleware/GzipRequestBody.js +224 -0
  173. package/build/dist/Server/Middleware/GzipRequestBody.js.map +1 -0
  174. package/build/dist/Server/Middleware/MultipartFormData.js +71 -2
  175. package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
  176. package/build/dist/Server/Services/DetectionRuleService.js +49 -4
  177. package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
  178. package/build/dist/Server/Services/Index.js +204 -0
  179. package/build/dist/Server/Services/Index.js.map +1 -1
  180. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +50 -0
  181. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  182. package/build/dist/Server/Services/NetworkDeviceService.js +124 -0
  183. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  184. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +68 -13
  185. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  186. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js +1 -1
  187. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js.map +1 -1
  188. package/build/dist/Server/Services/ProjectService.js +25 -45
  189. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  190. package/build/dist/Server/Services/SecurityEventService.js +57 -5
  191. package/build/dist/Server/Services/SecurityEventService.js.map +1 -1
  192. package/build/dist/Server/Services/StatusPageResourceService.js +140 -0
  193. package/build/dist/Server/Services/StatusPageResourceService.js.map +1 -1
  194. package/build/dist/Server/Services/TelemetryAttributeService.js +17 -0
  195. package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
  196. package/build/dist/Server/Services/UserService.js +2 -12
  197. package/build/dist/Server/Services/UserService.js.map +1 -1
  198. package/build/dist/Server/Types/Markdown.js +147 -61
  199. package/build/dist/Server/Types/Markdown.js.map +1 -1
  200. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +12 -4
  201. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -1
  202. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +12 -1
  203. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  204. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +246 -9
  205. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  206. package/build/dist/Server/Utils/Attribution.js.map +1 -1
  207. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +27 -7
  208. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
  209. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +42 -7
  210. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  211. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +18 -0
  212. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
  213. package/build/dist/Server/Utils/StartServer.js +12 -21
  214. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  215. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js +76 -5
  216. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js.map +1 -1
  217. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js +102 -0
  218. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js.map +1 -0
  219. package/build/dist/Types/Code/YamlSyntax.js +212 -0
  220. package/build/dist/Types/Code/YamlSyntax.js.map +1 -0
  221. package/build/dist/Types/Exception/ExceptionCode.js +1 -0
  222. package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
  223. package/build/dist/Types/Exception/PayloadTooLargeException.js +8 -0
  224. package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -0
  225. package/build/dist/Types/Marketing/Attribution.js +10 -0
  226. package/build/dist/Types/Marketing/Attribution.js.map +1 -1
  227. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +112 -51
  228. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  229. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +2 -1
  230. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
  231. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +9 -0
  232. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
  233. package/build/dist/Types/Telemetry/LlmMetricConventions.js +98 -0
  234. package/build/dist/Types/Telemetry/LlmMetricConventions.js.map +1 -0
  235. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +1 -1
  236. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
  237. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +5 -2
  238. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  239. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +206 -76
  240. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  241. package/build/dist/UI/Components/CodeEditor/YamlEditor.js +201 -0
  242. package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -0
  243. package/build/dist/UI/Components/Detail/Detail.js +9 -0
  244. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  245. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +16 -1
  246. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  247. package/build/dist/UI/Components/Forms/Fields/FormField.js +14 -1
  248. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  249. package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
  250. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
  251. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
  252. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js +2 -0
  253. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js.map +1 -1
  254. package/build/dist/UI/Components/Forms/Validation.js +27 -0
  255. package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
  256. package/build/dist/UI/Components/Input/Input.js +1 -1
  257. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  258. package/build/dist/UI/Components/ModelTable/AttributeColumns.js +159 -0
  259. package/build/dist/UI/Components/ModelTable/AttributeColumns.js.map +1 -0
  260. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +179 -17
  261. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  262. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +133 -2
  263. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -1
  264. package/build/dist/UI/Components/ModelTable/ColumnPreference.js +7 -1
  265. package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -1
  266. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js +2 -2
  267. package/build/dist/UI/Components/SideOver/SideOver.js +5 -5
  268. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +28 -2
  269. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
  270. package/build/dist/UI/Components/StatusPage/ResourceList.js +87 -20
  271. package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
  272. package/build/dist/UI/Components/Toggle/Toggle.js +9 -1
  273. package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
  274. package/build/dist/UI/Components/Types/FieldType.js +1 -0
  275. package/build/dist/UI/Components/Types/FieldType.js.map +1 -1
  276. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +37 -1
  277. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
  278. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js +120 -0
  279. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js.map +1 -0
  280. package/build/dist/Utils/StatusPage/ResourceExplorer.js +171 -0
  281. package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -1
  282. package/build/dist/Utils/Telemetry/LlmMetricQuery.js +119 -0
  283. package/build/dist/Utils/Telemetry/LlmMetricQuery.js.map +1 -0
  284. package/jest.config.json +2 -0
  285. package/package.json +1 -1
  286. package/tsconfig.json +2 -1
  287. package/Tests/UI/Components/Toast.test.tsx +0 -197
  288. package/Tests/UI/Components/ToastStacking.test.tsx +0 -198
  289. package/UI/Components/Toast/Toast.tsx +0 -189
  290. package/UI/Components/Toast/ToastInit.tsx +0 -110
  291. package/build/dist/UI/Components/Toast/Toast.js +0 -123
  292. package/build/dist/UI/Components/Toast/Toast.js.map +0 -1
  293. package/build/dist/UI/Components/Toast/ToastInit.js +0 -53
  294. package/build/dist/UI/Components/Toast/ToastInit.js.map +0 -1
@@ -0,0 +1,472 @@
1
+ import Metric from "../../../Models/AnalyticsModels/Metric";
2
+ import AggregatedModel from "../../../Types/BaseDatabase/AggregatedModel";
3
+ import InBetween from "../../../Types/BaseDatabase/InBetween";
4
+ import Includes from "../../../Types/BaseDatabase/Includes";
5
+ import Query from "../../../Types/BaseDatabase/Query";
6
+ import ObjectID from "../../../Types/ObjectID";
7
+ import {
8
+ LlmCostMetricNames,
9
+ LlmTokenUsageMetricNames,
10
+ } from "../../../Types/Telemetry/LlmMetricConventions";
11
+ import LlmMetricQuery, {
12
+ LlmMetricScope,
13
+ LlmMetricTokenTotals,
14
+ METRIC_MODEL_ATTRIBUTE_KEY,
15
+ METRIC_SYSTEM_ATTRIBUTE_KEY,
16
+ } from "../../../Utils/Telemetry/LlmMetricQuery";
17
+ import { describe, expect, test } from "@jest/globals";
18
+
19
+ const PROJECT_ID: ObjectID = ObjectID.generate();
20
+ const SERVICE_ID: ObjectID = ObjectID.generate();
21
+ const START: Date = new Date("2026-08-26T00:00:00.000Z");
22
+ const END: Date = new Date("2026-08-26T13:45:00.000Z");
23
+
24
+ function scope(overrides?: Partial<LlmMetricScope>): LlmMetricScope {
25
+ return {
26
+ projectId: PROJECT_ID,
27
+ startTime: START,
28
+ endTime: END,
29
+ ...overrides,
30
+ };
31
+ }
32
+
33
+ function row(value: unknown, attributes?: Record<string, unknown>): unknown {
34
+ return {
35
+ timestamp: START,
36
+ value: value,
37
+ ...(attributes ? { attributes: attributes } : {}),
38
+ };
39
+ }
40
+
41
+ describe("LlmMetricQuery", () => {
42
+ describe("buildBaseQuery", () => {
43
+ test("scopes to the project", () => {
44
+ const query: Record<string, unknown> = LlmMetricQuery.buildBaseQuery({
45
+ scope: scope(),
46
+ metricNames: ["a"],
47
+ }) as unknown as Record<string, unknown>;
48
+
49
+ expect(query["projectId"]).toBe(PROJECT_ID);
50
+ });
51
+
52
+ test("matches any of the supplied metric names", () => {
53
+ const query: Record<string, unknown> = LlmMetricQuery.buildBaseQuery({
54
+ scope: scope(),
55
+ metricNames: ["a", "b", "c"],
56
+ }) as unknown as Record<string, unknown>;
57
+
58
+ expect(query["name"]).toBeInstanceOf(Includes);
59
+ expect((query["name"] as Includes).values).toEqual(["a", "b", "c"]);
60
+ });
61
+
62
+ /*
63
+ * The regression this guards: AggregateBy's startTimestamp/endTimestamp
64
+ * only choose the bucket grid. Without a `time` predicate in the query the
65
+ * aggregate scans the metric's whole retention and silently returns spend
66
+ * from outside the window.
67
+ */
68
+ test("bounds rows with an explicit time predicate", () => {
69
+ const query: Record<string, unknown> = LlmMetricQuery.buildBaseQuery({
70
+ scope: scope(),
71
+ metricNames: ["a"],
72
+ }) as unknown as Record<string, unknown>;
73
+
74
+ const time: InBetween<Date> = query["time"] as InBetween<Date>;
75
+
76
+ expect(time).toBeInstanceOf(InBetween);
77
+ expect(time.startValue).toBe(START);
78
+ expect(time.endValue).toBe(END);
79
+ });
80
+
81
+ test("omits service and attribute filters when unscoped", () => {
82
+ const query: Record<string, unknown> = LlmMetricQuery.buildBaseQuery({
83
+ scope: scope(),
84
+ metricNames: ["a"],
85
+ }) as unknown as Record<string, unknown>;
86
+
87
+ expect(query).not.toHaveProperty("primaryEntityId");
88
+ expect(query).not.toHaveProperty("attributes");
89
+ });
90
+
91
+ test("narrows by telemetry service via primaryEntityId", () => {
92
+ const query: Record<string, unknown> = LlmMetricQuery.buildBaseQuery({
93
+ scope: scope({ serviceId: SERVICE_ID }),
94
+ metricNames: ["a"],
95
+ }) as unknown as Record<string, unknown>;
96
+
97
+ expect(query["primaryEntityId"]).toBe(SERVICE_ID);
98
+ });
99
+
100
+ test("narrows by provider using the semconv attribute key", () => {
101
+ const query: Record<string, unknown> = LlmMetricQuery.buildBaseQuery({
102
+ scope: scope({ llmSystem: "openai" }),
103
+ metricNames: ["a"],
104
+ }) as unknown as Record<string, unknown>;
105
+
106
+ expect(query["attributes"]).toEqual({
107
+ [METRIC_SYSTEM_ATTRIBUTE_KEY]: "openai",
108
+ });
109
+ expect(METRIC_SYSTEM_ATTRIBUTE_KEY).toBe("gen_ai.system");
110
+ });
111
+
112
+ test("narrows by model using the semconv attribute key", () => {
113
+ const query: Record<string, unknown> = LlmMetricQuery.buildBaseQuery({
114
+ scope: scope({ llmModel: "gpt-4o" }),
115
+ metricNames: ["a"],
116
+ }) as unknown as Record<string, unknown>;
117
+
118
+ expect(query["attributes"]).toEqual({
119
+ [METRIC_MODEL_ATTRIBUTE_KEY]: "gpt-4o",
120
+ });
121
+ expect(METRIC_MODEL_ATTRIBUTE_KEY).toBe("gen_ai.request.model");
122
+ });
123
+
124
+ test("combines every scoping dimension at once", () => {
125
+ const query: Record<string, unknown> = LlmMetricQuery.buildBaseQuery({
126
+ scope: scope({
127
+ serviceId: SERVICE_ID,
128
+ llmSystem: "anthropic",
129
+ llmModel: "claude-sonnet-4",
130
+ }),
131
+ metricNames: ["a"],
132
+ }) as unknown as Record<string, unknown>;
133
+
134
+ expect(query["primaryEntityId"]).toBe(SERVICE_ID);
135
+ expect(query["attributes"]).toEqual({
136
+ [METRIC_SYSTEM_ATTRIBUTE_KEY]: "anthropic",
137
+ [METRIC_MODEL_ATTRIBUTE_KEY]: "claude-sonnet-4",
138
+ });
139
+ });
140
+
141
+ test("treats an empty-string scope value as unscoped", () => {
142
+ const query: Record<string, unknown> = LlmMetricQuery.buildBaseQuery({
143
+ scope: scope({ llmSystem: "", llmModel: "" }),
144
+ metricNames: ["a"],
145
+ }) as unknown as Record<string, unknown>;
146
+
147
+ expect(query).not.toHaveProperty("attributes");
148
+ });
149
+ });
150
+
151
+ describe("buildCostQuery / buildTokenQuery", () => {
152
+ test("cost query matches exactly the cost metric names", () => {
153
+ const query: Record<string, unknown> = LlmMetricQuery.buildCostQuery(
154
+ scope(),
155
+ ) as unknown as Record<string, unknown>;
156
+
157
+ expect((query["name"] as Includes).values).toEqual(LlmCostMetricNames);
158
+ });
159
+
160
+ test("token query matches exactly the token metric names", () => {
161
+ const query: Record<string, unknown> = LlmMetricQuery.buildTokenQuery(
162
+ scope(),
163
+ ) as unknown as Record<string, unknown>;
164
+
165
+ expect((query["name"] as Includes).values).toEqual(
166
+ LlmTokenUsageMetricNames,
167
+ );
168
+ });
169
+
170
+ test("the two queries never select the same metric names", () => {
171
+ const costNames: Array<string> = (
172
+ LlmMetricQuery.buildCostQuery(scope()) as unknown as Record<
173
+ string,
174
+ unknown
175
+ >
176
+ )["name"] as unknown as Array<string>;
177
+
178
+ const cost: Includes = (
179
+ LlmMetricQuery.buildCostQuery(scope()) as unknown as Record<
180
+ string,
181
+ unknown
182
+ >
183
+ )["name"] as Includes;
184
+
185
+ const token: Includes = (
186
+ LlmMetricQuery.buildTokenQuery(scope()) as unknown as Record<
187
+ string,
188
+ unknown
189
+ >
190
+ )["name"] as Includes;
191
+
192
+ expect(costNames).toBeDefined();
193
+
194
+ const overlap: Array<string> = (cost.values as Array<string>).filter(
195
+ (name: string) => {
196
+ return (token.values as Array<string>).includes(name);
197
+ },
198
+ );
199
+
200
+ expect(overlap).toEqual([]);
201
+ });
202
+
203
+ test("both carry the caller's scoping", () => {
204
+ const scoped: LlmMetricScope = scope({
205
+ serviceId: SERVICE_ID,
206
+ llmSystem: "openai",
207
+ });
208
+
209
+ for (const query of [
210
+ LlmMetricQuery.buildCostQuery(scoped),
211
+ LlmMetricQuery.buildTokenQuery(scoped),
212
+ ] as Array<Query<Metric>>) {
213
+ const record: Record<string, unknown> = query as unknown as Record<
214
+ string,
215
+ unknown
216
+ >;
217
+ expect(record["primaryEntityId"]).toBe(SERVICE_ID);
218
+ expect(record["attributes"]).toEqual({
219
+ [METRIC_SYSTEM_ATTRIBUTE_KEY]: "openai",
220
+ });
221
+ }
222
+ });
223
+ });
224
+
225
+ describe("sumAggregatedRows", () => {
226
+ test("sums the bucket values", () => {
227
+ expect(
228
+ LlmMetricQuery.sumAggregatedRows([
229
+ row(1.5),
230
+ row(2.25),
231
+ row(0.25),
232
+ ] as Array<AggregatedModel>),
233
+ ).toBeCloseTo(4);
234
+ });
235
+
236
+ test("returns 0 for an empty result", () => {
237
+ expect(LlmMetricQuery.sumAggregatedRows([])).toBe(0);
238
+ });
239
+
240
+ test("returns 0 for undefined and null", () => {
241
+ expect(LlmMetricQuery.sumAggregatedRows(undefined)).toBe(0);
242
+ expect(LlmMetricQuery.sumAggregatedRows(null)).toBe(0);
243
+ });
244
+
245
+ test("returns 0 for a non-array", () => {
246
+ expect(
247
+ LlmMetricQuery.sumAggregatedRows(
248
+ "nope" as unknown as Array<AggregatedModel>,
249
+ ),
250
+ ).toBe(0);
251
+ });
252
+
253
+ test("treats a missing value as zero", () => {
254
+ expect(
255
+ LlmMetricQuery.sumAggregatedRows([
256
+ { timestamp: START } as unknown as AggregatedModel,
257
+ row(3),
258
+ ] as Array<AggregatedModel>),
259
+ ).toBe(3);
260
+ });
261
+
262
+ test("coerces numeric strings", () => {
263
+ expect(
264
+ LlmMetricQuery.sumAggregatedRows([
265
+ row("2.5"),
266
+ row("1.5"),
267
+ ] as Array<AggregatedModel>),
268
+ ).toBeCloseTo(4);
269
+ });
270
+
271
+ /*
272
+ * These figures feed budget monitors. One malformed row must not turn a
273
+ * budget's spend into NaN, which would compare false against every
274
+ * threshold and silently disable the alert.
275
+ */
276
+ test("drops NaN rows instead of poisoning the total", () => {
277
+ expect(
278
+ LlmMetricQuery.sumAggregatedRows([
279
+ row(5),
280
+ row("not-a-number"),
281
+ row(5),
282
+ ] as Array<AggregatedModel>),
283
+ ).toBe(10);
284
+ });
285
+
286
+ test("drops Infinity rows instead of poisoning the total", () => {
287
+ expect(
288
+ LlmMetricQuery.sumAggregatedRows([
289
+ row(5),
290
+ row(Infinity),
291
+ row(-Infinity),
292
+ row(5),
293
+ ] as Array<AggregatedModel>),
294
+ ).toBe(10);
295
+ });
296
+
297
+ test("survives null entries inside the array", () => {
298
+ expect(
299
+ LlmMetricQuery.sumAggregatedRows([
300
+ row(2),
301
+ null as unknown as AggregatedModel,
302
+ row(3),
303
+ ] as Array<AggregatedModel>),
304
+ ).toBe(5);
305
+ });
306
+
307
+ test("preserves negative values, which a delta counter can legitimately emit", () => {
308
+ expect(
309
+ LlmMetricQuery.sumAggregatedRows([
310
+ row(10),
311
+ row(-4),
312
+ ] as Array<AggregatedModel>),
313
+ ).toBe(6);
314
+ });
315
+ });
316
+
317
+ describe("reduceTokenRows", () => {
318
+ test("splits rows by the semconv token type attribute", () => {
319
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
320
+ row(100, { "gen_ai.token.type": "input" }),
321
+ row(40, { "gen_ai.token.type": "output" }),
322
+ ] as Array<AggregatedModel>);
323
+
324
+ expect(totals).toEqual({ inputTokens: 100, outputTokens: 40 });
325
+ });
326
+
327
+ test("accumulates repeated rows of the same direction", () => {
328
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
329
+ row(10, { "gen_ai.token.type": "input" }),
330
+ row(15, { "gen_ai.token.type": "input" }),
331
+ row(1, { "gen_ai.token.type": "output" }),
332
+ ] as Array<AggregatedModel>);
333
+
334
+ expect(totals).toEqual({ inputTokens: 25, outputTokens: 1 });
335
+ });
336
+
337
+ test("accepts the pre-convention prompt/completion spellings", () => {
338
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
339
+ row(7, { "gen_ai.token.type": "prompt" }),
340
+ row(3, { "gen_ai.token.type": "completion" }),
341
+ ] as Array<AggregatedModel>);
342
+
343
+ expect(totals).toEqual({ inputTokens: 7, outputTokens: 3 });
344
+ });
345
+
346
+ test("accepts the alternate llm.token.type attribute key", () => {
347
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
348
+ row(9, { "llm.token.type": "input" }),
349
+ row(4, { "llm.token.type": "output" }),
350
+ ] as Array<AggregatedModel>);
351
+
352
+ expect(totals).toEqual({ inputTokens: 9, outputTokens: 4 });
353
+ });
354
+
355
+ test("is case and whitespace insensitive", () => {
356
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
357
+ row(5, { "gen_ai.token.type": " INPUT " }),
358
+ row(6, { "gen_ai.token.type": "Output" }),
359
+ ] as Array<AggregatedModel>);
360
+
361
+ expect(totals).toEqual({ inputTokens: 5, outputTokens: 6 });
362
+ });
363
+
364
+ /*
365
+ * The double-counting guard. A row carrying two recognized token-type keys
366
+ * is counted once, against the preferred (semconv) key.
367
+ */
368
+ test("counts a row once when it carries two recognized token type keys", () => {
369
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
370
+ row(50, {
371
+ "gen_ai.token.type": "input",
372
+ "llm.token.type": "input",
373
+ }),
374
+ ] as Array<AggregatedModel>);
375
+
376
+ expect(totals).toEqual({ inputTokens: 50, outputTokens: 0 });
377
+ });
378
+
379
+ test("prefers the semconv key when the two keys disagree", () => {
380
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
381
+ row(50, {
382
+ "gen_ai.token.type": "output",
383
+ "llm.token.type": "input",
384
+ }),
385
+ ] as Array<AggregatedModel>);
386
+
387
+ expect(totals).toEqual({ inputTokens: 0, outputTokens: 50 });
388
+ });
389
+
390
+ test("falls through to the alternate key when the semconv value is unrecognized", () => {
391
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
392
+ row(12, {
393
+ "gen_ai.token.type": "cache_read",
394
+ "llm.token.type": "input",
395
+ }),
396
+ ] as Array<AggregatedModel>);
397
+
398
+ expect(totals).toEqual({ inputTokens: 12, outputTokens: 0 });
399
+ });
400
+
401
+ /*
402
+ * Cache tokens are real counts but are neither input nor output in the
403
+ * sense the span columns use. Folding them in would inflate the
404
+ * metric-sourced totals against the span-sourced ones they stand in for.
405
+ */
406
+ test("drops cache token kinds", () => {
407
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
408
+ row(100, { "gen_ai.token.type": "input" }),
409
+ row(9999, { "gen_ai.token.type": "cache_read" }),
410
+ row(8888, { "gen_ai.token.type": "cache_creation" }),
411
+ ] as Array<AggregatedModel>);
412
+
413
+ expect(totals).toEqual({ inputTokens: 100, outputTokens: 0 });
414
+ });
415
+
416
+ test("drops rows with no token type attribute at all", () => {
417
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
418
+ row(100),
419
+ row(50, {}),
420
+ row(25, { "some.other.attribute": "input" }),
421
+ ] as Array<AggregatedModel>);
422
+
423
+ expect(totals).toEqual({ inputTokens: 0, outputTokens: 0 });
424
+ });
425
+
426
+ test("drops NaN and Infinity values", () => {
427
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
428
+ row(10, { "gen_ai.token.type": "input" }),
429
+ row("bad", { "gen_ai.token.type": "input" }),
430
+ row(Infinity, { "gen_ai.token.type": "output" }),
431
+ row(4, { "gen_ai.token.type": "output" }),
432
+ ] as Array<AggregatedModel>);
433
+
434
+ expect(totals).toEqual({ inputTokens: 10, outputTokens: 4 });
435
+ });
436
+
437
+ test("returns zeros for empty, undefined, null and non-array input", () => {
438
+ const zero: LlmMetricTokenTotals = { inputTokens: 0, outputTokens: 0 };
439
+
440
+ expect(LlmMetricQuery.reduceTokenRows([])).toEqual(zero);
441
+ expect(LlmMetricQuery.reduceTokenRows(undefined)).toEqual(zero);
442
+ expect(LlmMetricQuery.reduceTokenRows(null)).toEqual(zero);
443
+ expect(
444
+ LlmMetricQuery.reduceTokenRows(
445
+ "nope" as unknown as Array<AggregatedModel>,
446
+ ),
447
+ ).toEqual(zero);
448
+ });
449
+
450
+ test("survives null entries inside the array", () => {
451
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
452
+ row(3, { "gen_ai.token.type": "input" }),
453
+ null as unknown as AggregatedModel,
454
+ row(2, { "gen_ai.token.type": "output" }),
455
+ ] as Array<AggregatedModel>);
456
+
457
+ expect(totals).toEqual({ inputTokens: 3, outputTokens: 2 });
458
+ });
459
+
460
+ test("tolerates a non-object attributes field", () => {
461
+ const totals: LlmMetricTokenTotals = LlmMetricQuery.reduceTokenRows([
462
+ {
463
+ timestamp: START,
464
+ value: 5,
465
+ attributes: "not-an-object",
466
+ } as unknown as AggregatedModel,
467
+ ]);
468
+
469
+ expect(totals).toEqual({ inputTokens: 0, outputTokens: 0 });
470
+ });
471
+ });
472
+ });