@oneuptime/common 14.0.8 → 14.0.9

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 (639) hide show
  1. package/Models/DatabaseModels/Index.ts +2 -0
  2. package/Models/DatabaseModels/KubernetesAiAgent.ts +364 -0
  3. package/Models/DatabaseModels/KubernetesCluster.ts +3 -3
  4. package/Models/DatabaseModels/Project.ts +55 -5
  5. package/Models/DatabaseModels/ProxmoxResource.ts +49 -1
  6. package/Models/DatabaseModels/RunnerJob.ts +75 -0
  7. package/Models/DatabaseModels/TeamComplianceSetting.ts +143 -2
  8. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +17 -0
  9. package/Server/API/AIChatAPI.ts +6 -3
  10. package/Server/API/AIInvestigationAPI.ts +17 -10
  11. package/Server/API/AutoRemediationAPI.ts +207 -25
  12. package/Server/API/KubernetesClusterAiAccessAPI.ts +623 -21
  13. package/Server/API/MicrosoftTeamsAPI.ts +93 -14
  14. package/Server/API/ProxmoxResourceAPI.ts +244 -14
  15. package/Server/Infrastructure/GlobalCache.ts +32 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.ts +99 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.ts +137 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.ts +42 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  20. package/Server/Middleware/TelemetryIngest.ts +41 -18
  21. package/Server/Services/AIService.ts +70 -1
  22. package/Server/Services/AlertService.ts +352 -11
  23. package/Server/Services/AlertSeverityService.ts +65 -15
  24. package/Server/Services/AutoRemediationRuleService.ts +1 -1
  25. package/Server/Services/IncidentService.ts +280 -104
  26. package/Server/Services/IncidentSeverityService.ts +66 -15
  27. package/Server/Services/KubernetesAiAgentJobService.ts +185 -0
  28. package/Server/Services/KubernetesAiAgentService.ts +1634 -0
  29. package/Server/Services/KubernetesClusterAiAccessService.ts +1118 -451
  30. package/Server/Services/KubernetesClusterService.ts +129 -21
  31. package/Server/Services/ProjectService.ts +32 -0
  32. package/Server/Services/ProxmoxResourceService.ts +322 -5
  33. package/Server/Services/RunnerJobService.ts +241 -104
  34. package/Server/Services/RunnerService.ts +1 -1
  35. package/Server/Services/ScheduledMaintenanceService.ts +737 -1
  36. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +414 -56
  37. package/Server/Services/TeamComplianceSettingService.ts +1125 -9
  38. package/Server/Utils/AI/ClusterAccess/ClusterAccessContext.ts +67 -9
  39. package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +39 -10
  40. package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +14 -3
  41. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +37 -15
  42. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +67 -24
  43. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +48 -5
  44. package/Server/Utils/AI/SRE/IncidentPostmortemRunner.ts +40 -8
  45. package/Server/Utils/AI/SRE/InvestigationEligibility.ts +13 -2
  46. package/Server/Utils/AI/SRE/InvestigationGrader.ts +1 -1
  47. package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +6 -1
  48. package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +133 -7
  49. package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +58 -4
  50. package/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.ts +447 -0
  51. package/Server/Utils/Telemetry/ProxmoxNativePush.ts +903 -0
  52. package/Server/Utils/Telemetry/TelemetryEntity.ts +87 -27
  53. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +684 -47
  54. package/Tests/App/AdminDashboard/RowActionPlacementOverrides.test.tsx +278 -0
  55. package/Tests/App/Dashboard/AIChatChartWidgetZoom.test.tsx +738 -0
  56. package/Tests/App/Dashboard/AIFeaturesSettingsPointers.test.tsx +147 -0
  57. package/Tests/App/Dashboard/AIInsightsKubernetesClusterPage.test.tsx +1523 -0
  58. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +463 -3
  59. package/Tests/App/Dashboard/AffectedResourcesPickerDropdownPlacement.test.tsx +958 -0
  60. package/Tests/App/Dashboard/AffectedResourcesPickerFocusLeave.test.tsx +595 -0
  61. package/Tests/App/Dashboard/AskAiAvailability.test.ts +20 -3
  62. package/Tests/App/Dashboard/AskAiDisabled.test.tsx +8 -3
  63. package/Tests/App/Dashboard/CephRateChartReload.test.tsx +1456 -0
  64. package/Tests/App/Dashboard/CephTimeRangeZoom.test.tsx +1229 -0
  65. package/Tests/App/Dashboard/ChartCardTimeRangeZoom.test.tsx +151 -0
  66. package/Tests/App/Dashboard/ChartCardZoomAffordances.test.tsx +257 -0
  67. package/Tests/App/Dashboard/ChartRefetchFrame.test.tsx +141 -0
  68. package/Tests/App/Dashboard/ChartZoomHarness.tsx +249 -0
  69. package/Tests/App/Dashboard/ChartZoomStandIn.tsx +131 -0
  70. package/Tests/App/Dashboard/CloudServerlessSlowLoads.test.tsx +628 -0
  71. package/Tests/App/Dashboard/CloudServerlessTimeRangeZoom.test.tsx +607 -0
  72. package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +91 -19
  73. package/Tests/App/Dashboard/CompanionMetricsTabZoom.test.tsx +632 -0
  74. package/Tests/App/Dashboard/ContainerChartZoomStandIn.tsx +195 -0
  75. package/Tests/App/Dashboard/ContainerHostOverviewSlowLoads.test.tsx +542 -0
  76. package/Tests/App/Dashboard/ContainerHostOverviewTimeRangeZoom.test.tsx +848 -0
  77. package/Tests/App/Dashboard/ContainerMetricsTimeRangeZoom.test.tsx +561 -0
  78. package/Tests/App/Dashboard/DashboardBoardWideZoomShell.test.tsx +1147 -0
  79. package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +3 -2
  80. package/Tests/App/Dashboard/DashboardHistogramWidgetDragCursor.test.tsx +399 -0
  81. package/Tests/App/Dashboard/DashboardHistogramWidgetZoom.test.tsx +985 -0
  82. package/Tests/App/Dashboard/DashboardHistogramWidgetZoomHint.test.tsx +803 -0
  83. package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +1 -0
  84. package/Tests/App/Dashboard/DashboardSettingsPreviewZoom.test.tsx +679 -0
  85. package/Tests/App/Dashboard/DashboardSloAndDataSourceChartZoom.test.tsx +881 -0
  86. package/Tests/App/Dashboard/DashboardTraceStatusWidgets.test.tsx +878 -0
  87. package/Tests/App/Dashboard/DatabaseMetricChartModalTimeRangeZoom.test.tsx +442 -0
  88. package/Tests/App/Dashboard/DatabaseOverviewTimeRangeZoom.test.tsx +831 -0
  89. package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +43 -0
  90. package/Tests/App/Dashboard/DockerSwarmInsightsTimeRangeZoom.test.tsx +524 -0
  91. package/Tests/App/Dashboard/DockerSwarmRateChartRefresh.test.tsx +259 -0
  92. package/Tests/App/Dashboard/EdgeDetailPanelHistory.test.tsx +763 -0
  93. package/Tests/App/Dashboard/EdgeDetailPanelTimeRangeZoom.test.tsx +547 -0
  94. package/Tests/App/Dashboard/EdgeHistoryBucketsCases.tsx +565 -0
  95. package/Tests/App/Dashboard/EdgeHistoryBucketsKathmandu.test.tsx +73 -0
  96. package/Tests/App/Dashboard/EdgeHistoryBucketsKolkata.test.tsx +74 -0
  97. package/Tests/App/Dashboard/EdgeHistoryBucketsNewYork.test.tsx +72 -0
  98. package/Tests/App/Dashboard/EdgeHistoryBucketsUtc.test.tsx +72 -0
  99. package/Tests/App/Dashboard/EmbeddedMetricCardRefresh.test.tsx +310 -0
  100. package/Tests/App/Dashboard/EmbeddedMetricCardTimeRangeZoom.test.tsx +536 -0
  101. package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +3 -1
  102. package/Tests/App/Dashboard/EscalationRuleRowActions.test.tsx +660 -0
  103. package/Tests/App/Dashboard/EventNotes.test.tsx +2 -2
  104. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +587 -13
  105. package/Tests/App/Dashboard/EventOverviewSnapshotExplorerZoom.test.tsx +1139 -0
  106. package/Tests/App/Dashboard/EventOverviewSnapshotZoomAcrossTabs.test.tsx +1057 -0
  107. package/Tests/App/Dashboard/EventOverviewTelemetrySnapshotZoom.test.tsx +757 -0
  108. package/Tests/App/Dashboard/ExceptionOccurrenceTrendZoom.test.tsx +675 -0
  109. package/Tests/App/Dashboard/ExceptionOccurrencesZoomSurvivesViewSwitch.test.tsx +405 -0
  110. package/Tests/App/Dashboard/ExceptionSignalPages.test.tsx +67 -3
  111. package/Tests/App/Dashboard/ExceptionTablesSpanStatus.test.tsx +515 -0
  112. package/Tests/App/Dashboard/ExplorerOwnZoomRegression.test.tsx +739 -0
  113. package/Tests/App/Dashboard/FlowBandwidthAxisCases.tsx +461 -0
  114. package/Tests/App/Dashboard/FlowBandwidthAxisKathmandu.test.tsx +25 -0
  115. package/Tests/App/Dashboard/FlowBandwidthAxisKolkata.test.tsx +25 -0
  116. package/Tests/App/Dashboard/FlowBandwidthAxisNewYork.test.tsx +25 -0
  117. package/Tests/App/Dashboard/FlowBandwidthAxisUtc.test.tsx +24 -0
  118. package/Tests/App/Dashboard/FlowTopTalkersZoomRefetch.test.tsx +722 -0
  119. package/Tests/App/Dashboard/FlowViewportGuard.test.tsx +2526 -0
  120. package/Tests/App/Dashboard/HostPagesSlowLoads.test.tsx +872 -0
  121. package/Tests/App/Dashboard/HostPagesTimeRangeZoom.test.tsx +1208 -0
  122. package/Tests/App/Dashboard/IncidentRootCauseTimeRangeZoom.test.tsx +358 -0
  123. package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +100 -9
  124. package/Tests/App/Dashboard/InfrastructureMetricsTabTimeRangeZoom.test.tsx +485 -0
  125. package/Tests/App/Dashboard/InvestigationDrawerCompanionZoom.test.tsx +655 -0
  126. package/Tests/App/Dashboard/InvestigationDrawerZoom.test.tsx +830 -0
  127. package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +338 -2
  128. package/Tests/App/Dashboard/InvoicesPayInvoice.test.tsx +454 -16
  129. package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +799 -819
  130. package/Tests/App/Dashboard/KubernetesClusterAiAgentOverviewCard.test.tsx +367 -0
  131. package/Tests/App/Dashboard/KubernetesClusterAiAgentStatus.test.ts +1202 -0
  132. package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +106 -0
  133. package/Tests/App/Dashboard/KubernetesClusterAiNavigation.test.tsx +354 -0
  134. package/Tests/App/Dashboard/KubernetesClusterAiPage.test.tsx +1884 -2054
  135. package/Tests/App/Dashboard/KubernetesClusterAiPageServerParity.test.ts +478 -179
  136. package/Tests/App/Dashboard/KubernetesClusterMetricTooltips.test.ts +50 -0
  137. package/Tests/App/Dashboard/KubernetesClusterOverviewTooltips.test.tsx +2 -1
  138. package/Tests/App/Dashboard/KubernetesClusterOverviewZoom.test.tsx +1217 -0
  139. package/Tests/App/Dashboard/KubernetesClusterPagesZoom.test.tsx +731 -0
  140. package/Tests/App/Dashboard/KubernetesCostsLoadRecovery.test.tsx +869 -0
  141. package/Tests/App/Dashboard/KubernetesCostsZoom.test.tsx +1214 -0
  142. package/Tests/App/Dashboard/KubernetesCostsZoomExactHours.test.tsx +692 -0
  143. package/Tests/App/Dashboard/KubernetesNetworkThroughputReload.test.tsx +902 -0
  144. package/Tests/App/Dashboard/KubernetesNetworkZoomBucketEdges.test.tsx +571 -0
  145. package/Tests/App/Dashboard/KubernetesOverviewZoomBucketEdges.test.tsx +697 -0
  146. package/Tests/App/Dashboard/KubernetesResourceMetricsTabZoom.test.tsx +633 -0
  147. package/Tests/App/Dashboard/LogsExplorerTimeRangeZoom.test.tsx +470 -0
  148. package/Tests/App/Dashboard/LogsInsightsTimeRangeZoom.test.tsx +948 -0
  149. package/Tests/App/Dashboard/LogsViewerPinnedWindowZoom.test.tsx +486 -0
  150. package/Tests/App/Dashboard/MetricChartsBucketInspectorDoubleClick.test.tsx +1001 -0
  151. package/Tests/App/Dashboard/MetricExplorerInvestigationAutoRefresh.test.tsx +514 -0
  152. package/Tests/App/Dashboard/MetricExplorerSavedViewZoomRoundTrip.test.tsx +581 -0
  153. package/Tests/App/Dashboard/MetricExplorerTimeRangeZoom.test.tsx +1162 -0
  154. package/Tests/App/Dashboard/MetricMonitorPreviewZoomLabel.test.ts +72 -0
  155. package/Tests/App/Dashboard/MetricRowSparklineTimeRangeZoom.test.tsx +204 -0
  156. package/Tests/App/Dashboard/MetricViewFirstResultLands.test.tsx +408 -0
  157. package/Tests/App/Dashboard/MetricViewOwnZoomResetPlacement.test.tsx +952 -0
  158. package/Tests/App/Dashboard/MetricViewTimeRange.test.ts +139 -0
  159. package/Tests/App/Dashboard/MetricViewTimeRangeZoom.test.tsx +556 -0
  160. package/Tests/App/Dashboard/MonitorMetricsChartWrappersZoom.test.tsx +552 -0
  161. package/Tests/App/Dashboard/MonitorMetricsTabsTimeRangeZoom.test.tsx +740 -0
  162. package/Tests/App/Dashboard/MonitorOverviewChartsTimeRangeZoom.test.tsx +735 -0
  163. package/Tests/App/Dashboard/MonitorStepPreviewsTimeRangeZoom.test.tsx +835 -0
  164. package/Tests/App/Dashboard/NetworkDeviceTimeRangeZoom.test.tsx +1115 -0
  165. package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +186 -17
  166. package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +155 -46
  167. package/Tests/App/Dashboard/PasskeySettings.test.tsx +87 -2
  168. package/Tests/App/Dashboard/ProjectAISettingsPages.test.tsx +884 -0
  169. package/Tests/App/Dashboard/ProxmoxNodeRemove.test.tsx +621 -0
  170. package/Tests/App/Dashboard/ProxmoxOverviewSlowLoads.test.tsx +584 -0
  171. package/Tests/App/Dashboard/ProxmoxPagesTimeRangeZoom.test.tsx +823 -0
  172. package/Tests/App/Dashboard/ProxmoxRateChartReload.test.tsx +1253 -0
  173. package/Tests/App/Dashboard/PublicDashboardBoardWideZoom.test.tsx +605 -0
  174. package/Tests/App/Dashboard/RealRowsLineChart.tsx +250 -0
  175. package/Tests/App/Dashboard/RechartsHostsPlotCursor.test.tsx +513 -0
  176. package/Tests/App/Dashboard/RowActionPlacementOverrides.test.tsx +865 -0
  177. package/Tests/App/Dashboard/RumOverviewTimeRangeZoom.test.tsx +877 -0
  178. package/Tests/App/Dashboard/RunnerKubernetesAgentForm.test.tsx +20 -4
  179. package/Tests/App/Dashboard/RunnerSupersededByAiAgentNote.test.tsx +296 -0
  180. package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +146 -36
  181. package/Tests/App/Dashboard/ServiceDatabaseSlowLoads.test.tsx +1166 -0
  182. package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +1243 -104
  183. package/Tests/App/Dashboard/ServiceOverviewTimeRangeZoom.test.tsx +792 -0
  184. package/Tests/App/Dashboard/SloBudgetBurnDownZoom.test.tsx +771 -0
  185. package/Tests/App/Dashboard/SloBudgetBurnDownZoomAffordances.test.tsx +380 -0
  186. package/Tests/App/Dashboard/SloEventMetricsBarChartZoom.test.tsx +369 -0
  187. package/Tests/App/Dashboard/SloHistoryChartsTimeRangeZoom.test.tsx +694 -0
  188. package/Tests/App/Dashboard/SloHistoryChartsZoomAffordances.test.tsx +497 -0
  189. package/Tests/App/Dashboard/SloMetricsTimeRangeZoom.test.tsx +541 -0
  190. package/Tests/App/Dashboard/SlowLoadHarness.ts +123 -0
  191. package/Tests/App/Dashboard/SnapshotExplorerPrimaryZoom.test.tsx +1194 -0
  192. package/Tests/App/Dashboard/SnapshotViewerPinnedWindow.test.tsx +620 -0
  193. package/Tests/App/Dashboard/TelemetrySnapshotPanelTimeRangeZoom.test.tsx +765 -0
  194. package/Tests/App/Dashboard/TelemetrySnapshotZoom.test.tsx +516 -0
  195. package/Tests/App/Dashboard/TelemetrySnapshotZoomAcrossTabs.test.tsx +827 -0
  196. package/Tests/App/Dashboard/TimeRangeZoomPageHarness.tsx +463 -0
  197. package/Tests/App/Dashboard/TraceChartEditorStatusSplit.test.tsx +543 -0
  198. package/Tests/App/Dashboard/TraceStatusPresentation.test.tsx +967 -0
  199. package/Tests/App/Dashboard/TraceTimelineMinimapZoom.test.tsx +315 -0
  200. package/Tests/App/Dashboard/TracesAnalyticsStatusSplit.test.tsx +778 -0
  201. package/Tests/App/Dashboard/TracesAnalyticsViewZoom.test.tsx +349 -0
  202. package/Tests/App/Dashboard/TracesExplorerTimeRangeZoom.test.tsx +551 -0
  203. package/Tests/App/Dashboard/TracesStatusChartAndFacet.test.tsx +687 -0
  204. package/Tests/App/Dashboard/TracesViewerStaleResponses.test.tsx +458 -0
  205. package/Tests/App/Dashboard/UptimeStripsExcludedFromZoom.test.tsx +406 -0
  206. package/Tests/App/Dashboard/VMwareOverviewSlowLoads.test.tsx +535 -0
  207. package/Tests/App/Dashboard/VMwarePagesTimeRangeZoom.test.tsx +606 -0
  208. package/Tests/App/Dashboard/ValueWidgetSparklineStaleHover.test.tsx +1292 -0
  209. package/Tests/App/Dashboard/ValueWidgetSparklineZoom.test.tsx +765 -0
  210. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +98 -0
  211. package/Tests/Models/DatabaseModels/KubernetesAiAgentModel.test.ts +295 -0
  212. package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +347 -0
  213. package/Tests/Server/API/AIChatRouteAuthorization.test.ts +58 -0
  214. package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +1 -1
  215. package/Tests/Server/API/AIInvestigationAPI.test.ts +123 -45
  216. package/Tests/Server/API/AutoRemediationApproveClusterRound.test.ts +1329 -0
  217. package/Tests/Server/API/AutoRemediationApproveKubectlRecheck.test.ts +25 -2
  218. package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -0
  219. package/Tests/Server/API/KubernetesClusterAiAccessAPIAgent.test.ts +903 -0
  220. package/Tests/Server/API/MicrosoftTeamsChatsRefreshRoute.test.ts +667 -0
  221. package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +294 -6
  222. package/Tests/Server/API/ProxmoxResourceAPIRemoveNode.test.ts +1932 -0
  223. package/Tests/Server/Infrastructure/GlobalCache.test.ts +195 -0
  224. package/Tests/Server/Infrastructure/Postgres/AddKubernetesAiAgentAndAiDefaultsMigration.test.ts +623 -0
  225. package/Tests/Server/Infrastructure/Postgres/AddKubernetesClusterAiAccessMigration.test.ts +87 -10
  226. package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleScopeMigration.test.ts +622 -0
  227. package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +61 -4
  228. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +98 -2
  229. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +105 -2
  230. package/Tests/Server/Services/AIServiceBalanceBlocker.test.ts +282 -0
  231. package/Tests/Server/Services/AlertMonitorClearWritesNull.test.ts +409 -0
  232. package/Tests/Server/Services/AlertMonitorEditFeed.test.ts +474 -0
  233. package/Tests/Server/Services/AlertMonitorEditGuard.test.ts +610 -0
  234. package/Tests/Server/Services/AutoRemediationClusterRuleEngine.test.ts +2 -0
  235. package/Tests/Server/Services/AutoRemediationRuleCommandRunners.test.ts +2 -1
  236. package/Tests/Server/Services/IncidentAffectedMonitorsEdit.test.ts +1360 -0
  237. package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +3 -1
  238. package/Tests/Server/Services/IncidentSeverityDeletePausesComplianceRules.test.ts +488 -0
  239. package/Tests/Server/Services/KubernetesAiAgentJobService.test.ts +329 -0
  240. package/Tests/Server/Services/KubernetesAiAgentServiceHelpers.test.ts +618 -0
  241. package/Tests/Server/Services/KubernetesAiAgentServiceLifecycle.test.ts +1444 -0
  242. package/Tests/Server/Services/KubernetesAiAgentServiceRegister.test.ts +1666 -0
  243. package/Tests/Server/Services/KubernetesClusterAiAccessDeletedRunnerRemedy.test.ts +140 -111
  244. package/Tests/Server/Services/KubernetesClusterAiAccessGapNextSteps.test.ts +267 -105
  245. package/Tests/Server/Services/KubernetesClusterAiAccessLegacySuperseded.test.ts +440 -0
  246. package/Tests/Server/Services/KubernetesClusterAiAccessService.test.ts +567 -411
  247. package/Tests/Server/Services/KubernetesClusterAiAccessTarget.test.ts +1168 -0
  248. package/Tests/Server/Services/KubernetesClusterAiSettingsPermission.test.ts +410 -12
  249. package/Tests/Server/Services/KubernetesClusterServiceAiAccessFeed.test.ts +55 -0
  250. package/Tests/Server/Services/ProjectServiceNewProjectAiDefaults.test.ts +288 -0
  251. package/Tests/Server/Services/ProxmoxResourcePostgres.test.ts +5633 -0
  252. package/Tests/Server/Services/ProxmoxResourceService.test.ts +6458 -5
  253. package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +48 -15
  254. package/Tests/Server/Services/RunnerJobEnqueueKubectlAiAgent.test.ts +620 -0
  255. package/Tests/Server/Services/RunnerJobKubectlWriteScope.test.ts +170 -3
  256. package/Tests/Server/Services/RunnerJobTimeoutReason.test.ts +72 -0
  257. package/Tests/Server/Services/RunnerServiceAgentName.test.ts +6 -4
  258. package/Tests/Server/Services/ScheduledMaintenanceAttachmentEdit.test.ts +2113 -0
  259. package/Tests/Server/Services/ScheduledMaintenanceMonitorRelease.test.ts +972 -0
  260. package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +2237 -0
  261. package/Tests/Server/Services/TeamComplianceSettingService.test.ts +3988 -138
  262. package/Tests/Server/Utils/AI/ClusterAccessContext.test.ts +107 -1
  263. package/Tests/Server/Utils/AI/IncidentPostmortemRunner.test.ts +351 -0
  264. package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +2 -0
  265. package/Tests/Server/Utils/AI/InvestigationEligibility.test.ts +310 -0
  266. package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +70 -0
  267. package/Tests/Server/Utils/AI/KubectlJobRunnerFinishedJob.test.ts +58 -0
  268. package/Tests/Server/Utils/AI/RemediationCommandToolsKubectl.test.ts +2 -0
  269. package/Tests/Server/Utils/AI/RemediationCommandToolsKubectlOutcome.test.ts +2 -0
  270. package/Tests/Server/Utils/AI/RemediationCommandToolsLiveCluster.test.ts +2 -0
  271. package/Tests/Server/Utils/AI/RemediationCommandToolsRunnerScope.test.ts +125 -1
  272. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +252 -3
  273. package/Tests/Server/Utils/AI/RemediationExecutionRunnerClusterMode.test.ts +2 -0
  274. package/Tests/Server/Utils/AI/RemediationExecutionRunnerProjectGates.test.ts +240 -0
  275. package/Tests/Server/Utils/AI/RemediationKubectlCopyParity.test.ts +2 -0
  276. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutor.test.ts +2 -0
  277. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorUnknownRun.test.ts +2 -0
  278. package/Tests/Server/Utils/AutoRemediation/CommandPlanVerification.test.ts +2 -0
  279. package/Tests/Server/Utils/Telemetry/HostAssetAttributesFromOtlp.test.ts +68 -0
  280. package/Tests/Server/Utils/Telemetry/InventoryMirrorPostgres.test.ts +370 -0
  281. package/Tests/Server/Utils/Telemetry/NetworkDeviceInventoryAttributes.test.ts +522 -0
  282. package/Tests/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.test.ts +155 -0
  283. package/Tests/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.test.ts +8631 -0
  284. package/Tests/Server/Utils/Telemetry/ProxmoxNativePush.test.ts +2852 -0
  285. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +367 -1
  286. package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +45 -3
  287. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +25 -0
  288. package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNames.test.ts +3119 -0
  289. package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNamesPostgres.test.ts +1721 -0
  290. package/Tests/Types/Kubernetes/KubernetesAgentChartAiAccess.test.ts +581 -113
  291. package/Tests/Types/Kubernetes/KubernetesAiAgentAccessContract.test.ts +510 -0
  292. package/Tests/Types/Team/ComplianceRule.test.ts +1029 -0
  293. package/Tests/Types/Team/TeamComplianceStatus.test.ts +176 -0
  294. package/Tests/UI/Components/ActionButton/RowActions.test.tsx +641 -0
  295. package/Tests/UI/Components/ActionButton/RowActionsAccessibility.test.tsx +414 -0
  296. package/Tests/UI/Components/ActionButton/SplitActionButtons.test.ts +565 -0
  297. package/Tests/UI/Components/Charts/BarChartDragToSelect.test.tsx +386 -0
  298. package/Tests/UI/Components/Charts/ChartDoubleClickResetWithoutDblclick.test.tsx +1025 -0
  299. package/Tests/UI/Components/Charts/ChartGroupPageZoomHint.test.tsx +196 -0
  300. package/Tests/UI/Components/Charts/ChartPlaceholdersTakeDoubleClick.test.tsx +1861 -0
  301. package/Tests/UI/Components/Charts/ChartPlotClicksWhileResetArmed.test.tsx +382 -0
  302. package/Tests/UI/Components/Charts/ChartRangeSelection.test.tsx +704 -0
  303. package/Tests/UI/Components/Charts/ChartRangeSelectionDoubleClickReset.test.tsx +1481 -0
  304. package/Tests/UI/Components/Charts/ChartRangeSelectionRealRecharts.test.tsx +918 -0
  305. package/Tests/UI/Components/Charts/ChartRowBucketStart.test.ts +350 -0
  306. package/Tests/UI/Components/Charts/DoubleClickReset.test.tsx +996 -0
  307. package/Tests/UI/Components/Charts/HistogramDoubleClickResetRealRecharts.test.tsx +965 -0
  308. package/Tests/UI/Components/Charts/HistogramDriftThenRefetch.test.tsx +277 -0
  309. package/Tests/UI/Components/Charts/HistogramRangeSelectionDataChange.test.tsx +1757 -0
  310. package/Tests/UI/Components/Charts/HistogramRangeSelectionRealRecharts.test.tsx +560 -0
  311. package/Tests/UI/Components/Charts/TimeRangeZoom/ChartPageTimeRangeZoom.test.tsx +513 -0
  312. package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.test.tsx +845 -0
  313. package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.test.tsx +119 -0
  314. package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHintTailwind.test.tsx +274 -0
  315. package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.test.ts +433 -0
  316. package/Tests/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.test.tsx +863 -0
  317. package/Tests/UI/Components/Charts/TimeRangeZoom/ZoomDocsPromises.test.tsx +1147 -0
  318. package/Tests/UI/Components/DisabledButtonTooltip.test.tsx +14 -3
  319. package/Tests/UI/Components/EntityDropdownEscape.test.tsx +454 -0
  320. package/Tests/UI/Components/EntityDropdownFocusLeave.test.tsx +420 -0
  321. package/Tests/UI/Components/Forms/FormFieldDropdownDisabled.test.tsx +233 -0
  322. package/Tests/UI/Components/Input.test.tsx +80 -1
  323. package/Tests/UI/Components/LogsAnalyticsViewZoom.test.tsx +947 -0
  324. package/Tests/UI/Components/LogsHistogramDragTooltip.test.tsx +17 -5
  325. package/Tests/UI/Components/LogsViewerAnalyticsZoom.test.tsx +501 -0
  326. package/Tests/UI/Components/LogsViewerHistogramZoom.test.tsx +1 -1
  327. package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +6 -4
  328. package/Tests/UI/Components/ModelTable/BaseModelTablePermissionGating.test.tsx +60 -8
  329. package/Tests/UI/Components/ModelTable/BaseModelTableRowActions.test.tsx +476 -0
  330. package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +7 -5
  331. package/Tests/UI/Components/MoreMenuPortal.test.tsx +623 -0
  332. package/Tests/UI/Components/StatusPage/ResourceGridActions.test.tsx +538 -0
  333. package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +14 -4
  334. package/Tests/UI/Components/TableCellWrapping.test.tsx +3 -3
  335. package/Tests/UI/Components/TableRowActions.test.tsx +472 -0
  336. package/Tests/UI/Components/TelemetryHistogramDragTooltip.test.tsx +1 -1
  337. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerHistogramClickZoom.test.tsx +1 -1
  338. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerZoomScope.test.tsx +470 -0
  339. package/Tests/UI/Components/TelemetryViewer/UseViewerTimeRangeZoom.test.tsx +571 -0
  340. package/Tests/UI/Components/TelemetryViewer/ViewerDoubleClickResetUnderDataChange.test.tsx +928 -0
  341. package/Tests/UI/Components/TelemetryViewer/ViewerFollowsEnclosingZoom.test.tsx +1569 -0
  342. package/Tests/UI/Components/Toggle.test.tsx +66 -0
  343. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardRefreshNames.test.tsx +1023 -0
  344. package/Tests/UI/Rum/ChunkLoader.test.ts +201 -0
  345. package/Tests/UI/Rum/FidelityNotices.test.ts +54 -0
  346. package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +72 -0
  347. package/Tests/UI/Rum/ReplayFrameCapture.test.ts +1009 -9
  348. package/Tests/UI/Rum/ReplayRecordedAssets.test.ts +1069 -0
  349. package/Tests/UI/Rum/ReplayStage.test.tsx +913 -2
  350. package/Tests/UI/Rum/SessionReplayTable.test.tsx +443 -8
  351. package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +439 -9
  352. package/Tests/UI/Rum/UserFlowTablesRowActions.test.tsx +501 -0
  353. package/Tests/Utils/AiRemediation/KubectlPolicyChartRbacParity.test.ts +47 -19
  354. package/Tests/Utils/AiRemediation/KubectlWriteScopeCallerParity.test.ts +2 -0
  355. package/Tests/Utils/AiRemediation/KubernetesAiAgentPolicyCopyParity.test.ts +396 -0
  356. package/Tests/Utils/Dashboard/DashboardTimeRangeZoom.test.ts +104 -1
  357. package/Types/AI/AIRunType.ts +9 -4
  358. package/Types/AI/InvestigationNotStartedReason.ts +6 -0
  359. package/Types/AutoRemediation/AiRemediationCommandPlan.ts +14 -16
  360. package/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.ts +28 -0
  361. package/Types/Dashboard/DashboardComponents/DashboardTraceChartComponent.ts +4 -2
  362. package/Types/Kubernetes/KubernetesClusterAiAccess.ts +263 -32
  363. package/Types/Kubernetes/KubernetesClusterAiAccessPermissions.ts +20 -16
  364. package/Types/Kubernetes/KubernetesClusterAiInsights.ts +81 -0
  365. package/Types/Monitor/ProxmoxAlertTemplates.ts +4 -4
  366. package/Types/Team/ComplianceNotificationChannel.ts +22 -0
  367. package/Types/Team/ComplianceRule.ts +434 -0
  368. package/Types/Team/ComplianceRuleType.ts +21 -0
  369. package/Types/Team/TeamComplianceStatus.ts +81 -0
  370. package/Types/Telemetry/TelemetryIngestSurface.ts +28 -0
  371. package/UI/Components/ActionButton/ActionButtonSchema.ts +21 -0
  372. package/UI/Components/ActionButton/RowActions.tsx +238 -0
  373. package/UI/Components/ActionButton/SplitActionButtons.ts +173 -0
  374. package/UI/Components/Charts/Area/AreaChart.tsx +32 -2
  375. package/UI/Components/Charts/Bar/BarChart.tsx +40 -3
  376. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +37 -11
  377. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +80 -243
  378. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +122 -31
  379. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +95 -244
  380. package/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.ts +214 -0
  381. package/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.ts +32 -0
  382. package/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.ts +599 -0
  383. package/UI/Components/Charts/Line/LineChart.tsx +32 -2
  384. package/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.tsx +70 -0
  385. package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.tsx +226 -0
  386. package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.tsx +73 -0
  387. package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.ts +163 -0
  388. package/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.ts +215 -0
  389. package/UI/Components/Charts/Utils/DataPoint.ts +20 -8
  390. package/UI/Components/Charts/Utils/XAxis.ts +75 -0
  391. package/UI/Components/Charts/Utils/useHistogramRangeSelection.ts +493 -59
  392. package/UI/Components/EntityDropdown/EntityDropdown.tsx +107 -11
  393. package/UI/Components/Forms/Fields/FormField.tsx +10 -0
  394. package/UI/Components/Input/Input.tsx +90 -57
  395. package/UI/Components/List/ListRow.tsx +8 -74
  396. package/UI/Components/LogsViewer/LogsViewer.tsx +40 -11
  397. package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +22 -6
  398. package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +209 -6
  399. package/UI/Components/LogsViewer/components/LogsHistogram.tsx +127 -84
  400. package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +3 -0
  401. package/UI/Components/ModelTable/BaseModelTable.tsx +12 -1
  402. package/UI/Components/MoreMenu/MoreMenu.tsx +365 -30
  403. package/UI/Components/MoreMenu/MoreMenuItem.tsx +70 -17
  404. package/UI/Components/OrderedStatesList/Item.tsx +7 -72
  405. package/UI/Components/StatusPage/ResourceGrid.tsx +126 -77
  406. package/UI/Components/Table/TableBody.tsx +8 -2
  407. package/UI/Components/Table/TableRow.tsx +20 -140
  408. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +41 -10
  409. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +47 -9
  410. package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +25 -6
  411. package/UI/Components/TelemetryViewer/types.ts +2 -0
  412. package/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.ts +448 -0
  413. package/UI/Components/Toggle/Toggle.tsx +26 -0
  414. package/UI/Components/Tooltip/Tooltip.tsx +8 -1
  415. package/UI/Styles/Theme.css +14 -2
  416. package/Utils/AiRemediation/CommandPolicy.ts +1 -1
  417. package/Utils/AiRemediation/KubectlPolicy.ts +1 -1
  418. package/Utils/Dashboard/DashboardTimeRangeZoom.ts +46 -2
  419. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  420. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  421. package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js +385 -0
  422. package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js.map +1 -0
  423. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +3 -3
  424. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  425. package/build/dist/Models/DatabaseModels/Project.js +56 -5
  426. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  427. package/build/dist/Models/DatabaseModels/ProxmoxResource.js +51 -1
  428. package/build/dist/Models/DatabaseModels/ProxmoxResource.js.map +1 -1
  429. package/build/dist/Models/DatabaseModels/RunnerJob.js +74 -0
  430. package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
  431. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +134 -3
  432. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
  433. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  434. package/build/dist/Server/API/AIChatAPI.js +6 -1
  435. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  436. package/build/dist/Server/API/AIInvestigationAPI.js +17 -10
  437. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  438. package/build/dist/Server/API/AutoRemediationAPI.js +144 -24
  439. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
  440. package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js +436 -22
  441. package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js.map +1 -1
  442. package/build/dist/Server/API/MicrosoftTeamsAPI.js +69 -13
  443. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  444. package/build/dist/Server/API/ProxmoxResourceAPI.js +187 -14
  445. package/build/dist/Server/API/ProxmoxResourceAPI.js.map +1 -1
  446. package/build/dist/Server/Infrastructure/GlobalCache.js +27 -0
  447. package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
  448. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js +50 -0
  449. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js.map +1 -0
  450. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js +84 -0
  451. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js.map +1 -0
  452. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js +31 -0
  453. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js.map +1 -0
  454. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  455. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  456. package/build/dist/Server/Middleware/TelemetryIngest.js +34 -19
  457. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  458. package/build/dist/Server/Services/AIService.js +59 -1
  459. package/build/dist/Server/Services/AIService.js.map +1 -1
  460. package/build/dist/Server/Services/AlertService.js +248 -13
  461. package/build/dist/Server/Services/AlertService.js.map +1 -1
  462. package/build/dist/Server/Services/AlertSeverityService.js +51 -15
  463. package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
  464. package/build/dist/Server/Services/AutoRemediationRuleService.js +1 -1
  465. package/build/dist/Server/Services/AutoRemediationRuleService.js.map +1 -1
  466. package/build/dist/Server/Services/IncidentService.js +199 -72
  467. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  468. package/build/dist/Server/Services/IncidentSeverityService.js +51 -15
  469. package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
  470. package/build/dist/Server/Services/KubernetesAiAgentJobService.js +158 -0
  471. package/build/dist/Server/Services/KubernetesAiAgentJobService.js.map +1 -0
  472. package/build/dist/Server/Services/KubernetesAiAgentService.js +1145 -0
  473. package/build/dist/Server/Services/KubernetesAiAgentService.js.map +1 -0
  474. package/build/dist/Server/Services/KubernetesClusterAiAccessService.js +842 -371
  475. package/build/dist/Server/Services/KubernetesClusterAiAccessService.js.map +1 -1
  476. package/build/dist/Server/Services/KubernetesClusterService.js +86 -17
  477. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  478. package/build/dist/Server/Services/ProjectService.js +22 -0
  479. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  480. package/build/dist/Server/Services/ProxmoxResourceService.js +258 -3
  481. package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -1
  482. package/build/dist/Server/Services/RunnerJobService.js +178 -92
  483. package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
  484. package/build/dist/Server/Services/RunnerService.js +1 -1
  485. package/build/dist/Server/Services/RunnerService.js.map +1 -1
  486. package/build/dist/Server/Services/ScheduledMaintenanceService.js +535 -3
  487. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  488. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +316 -46
  489. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  490. package/build/dist/Server/Services/TeamComplianceSettingService.js +833 -7
  491. package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
  492. package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js +52 -9
  493. package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js.map +1 -1
  494. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +13 -9
  495. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
  496. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +7 -3
  497. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
  498. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +29 -15
  499. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
  500. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +56 -20
  501. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  502. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +39 -5
  503. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  504. package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js +30 -3
  505. package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js.map +1 -1
  506. package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js +13 -2
  507. package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js.map +1 -1
  508. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +1 -1
  509. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +4 -2
  510. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
  511. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +111 -6
  512. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -1
  513. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +40 -4
  514. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -1
  515. package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js +296 -0
  516. package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js.map +1 -0
  517. package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js +699 -0
  518. package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js.map +1 -0
  519. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +77 -19
  520. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  521. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +505 -42
  522. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  523. package/build/dist/Types/AI/AIRunType.js +9 -4
  524. package/build/dist/Types/AI/AIRunType.js.map +1 -1
  525. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +10 -16
  526. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
  527. package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js +28 -0
  528. package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js.map +1 -0
  529. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +72 -16
  530. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
  531. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js +20 -16
  532. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js.map +1 -1
  533. package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js +17 -0
  534. package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js.map +1 -0
  535. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +4 -4
  536. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -1
  537. package/build/dist/Types/Team/ComplianceNotificationChannel.js +23 -0
  538. package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -0
  539. package/build/dist/Types/Team/ComplianceRule.js +304 -0
  540. package/build/dist/Types/Team/ComplianceRule.js.map +1 -0
  541. package/build/dist/Types/Team/ComplianceRuleType.js +21 -0
  542. package/build/dist/Types/Team/ComplianceRuleType.js.map +1 -1
  543. package/build/dist/Types/Team/TeamComplianceStatus.js +2 -0
  544. package/build/dist/Types/Team/TeamComplianceStatus.js.map +1 -0
  545. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +25 -0
  546. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
  547. package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js +20 -1
  548. package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js.map +1 -1
  549. package/build/dist/UI/Components/ActionButton/RowActions.js +113 -0
  550. package/build/dist/UI/Components/ActionButton/RowActions.js.map +1 -0
  551. package/build/dist/UI/Components/ActionButton/SplitActionButtons.js +71 -0
  552. package/build/dist/UI/Components/ActionButton/SplitActionButtons.js.map +1 -0
  553. package/build/dist/UI/Components/Charts/Area/AreaChart.js +16 -1
  554. package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
  555. package/build/dist/UI/Components/Charts/Bar/BarChart.js +16 -1
  556. package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
  557. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +27 -5
  558. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  559. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +61 -194
  560. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  561. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +84 -26
  562. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  563. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +75 -196
  564. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  565. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js +133 -0
  566. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js.map +1 -1
  567. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js +26 -0
  568. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js.map +1 -0
  569. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js +371 -0
  570. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js.map +1 -0
  571. package/build/dist/UI/Components/Charts/Line/LineChart.js +16 -1
  572. package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
  573. package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js +35 -0
  574. package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js.map +1 -0
  575. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js +107 -0
  576. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js.map +1 -0
  577. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js +41 -0
  578. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js.map +1 -0
  579. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js +117 -0
  580. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js.map +1 -0
  581. package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js +121 -0
  582. package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js.map +1 -0
  583. package/build/dist/UI/Components/Charts/Utils/DataPoint.js +15 -7
  584. package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
  585. package/build/dist/UI/Components/Charts/Utils/XAxis.js +70 -0
  586. package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
  587. package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js +305 -38
  588. package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js.map +1 -1
  589. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +89 -14
  590. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  591. package/build/dist/UI/Components/Forms/Fields/FormField.js +11 -2
  592. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  593. package/build/dist/UI/Components/Input/Input.js +69 -54
  594. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  595. package/build/dist/UI/Components/List/ListRow.js +4 -39
  596. package/build/dist/UI/Components/List/ListRow.js.map +1 -1
  597. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +31 -8
  598. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  599. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +10 -1
  600. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
  601. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +139 -21
  602. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
  603. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +30 -8
  604. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
  605. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +1 -1
  606. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
  607. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +10 -0
  608. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  609. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +253 -14
  610. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  611. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +43 -13
  612. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
  613. package/build/dist/UI/Components/OrderedStatesList/Item.js +2 -38
  614. package/build/dist/UI/Components/OrderedStatesList/Item.js.map +1 -1
  615. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +53 -15
  616. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
  617. package/build/dist/UI/Components/Table/TableBody.js +6 -2
  618. package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
  619. package/build/dist/UI/Components/Table/TableRow.js +12 -75
  620. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  621. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +32 -7
  622. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  623. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +27 -9
  624. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  625. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +11 -1
  626. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
  627. package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js +272 -0
  628. package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js.map +1 -0
  629. package/build/dist/UI/Components/Toggle/Toggle.js +14 -1
  630. package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
  631. package/build/dist/UI/Components/Tooltip/Tooltip.js +1 -1
  632. package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
  633. package/build/dist/Utils/AiRemediation/CommandPolicy.js +1 -1
  634. package/build/dist/Utils/AiRemediation/CommandPolicy.js.map +1 -1
  635. package/build/dist/Utils/AiRemediation/KubectlPolicy.js +1 -1
  636. package/build/dist/Utils/AiRemediation/KubectlPolicy.js.map +1 -1
  637. package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js +27 -1
  638. package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js.map +1 -1
  639. package/package.json +1 -1
@@ -2,6 +2,7 @@ import {
2
2
  KubernetesAiAccessGap,
3
3
  KubernetesAiRemediationMode,
4
4
  KubernetesClusterAiAccessStatus,
5
+ getKubernetesAiAccessTargetKind,
5
6
  } from "../../../../Types/Kubernetes/KubernetesClusterAiAccess";
6
7
  import { KUBECTL_ALWAYS_ASKS_SUMMARY } from "../../../../Types/AutoRemediation/AiRemediationCommandPlan";
7
8
 
@@ -20,6 +21,46 @@ function capitalizeFirst(text: string): string {
20
21
  return text.charAt(0).toUpperCase() + text.slice(1);
21
22
  }
22
23
 
24
+ /*
25
+ * Who runs kubectl for a cluster, by name, for copy the model and humans
26
+ * read: "the Kubernetes AI agent", or `Runner "<name>"`. Told apart by
27
+ * runner.kind only — accessMethod is "in_cluster" for both the agent and
28
+ * the chart's previous in-cluster Runner.
29
+ */
30
+ export function describeClusterAccessTarget(
31
+ status: Pick<KubernetesClusterAiAccessStatus, "runner">,
32
+ ): string {
33
+ if (getKubernetesAiAccessTargetKind(status.runner) === "ai_agent") {
34
+ return "the Kubernetes AI agent";
35
+ }
36
+
37
+ return `Runner "${status.runner?.name || "Runner"}"`;
38
+ }
39
+
40
+ /*
41
+ * The same with "its" ("its Kubernetes AI agent", "its Runner"), for copy
42
+ * that has already named the cluster.
43
+ */
44
+ export function describeClusterAccessTargetOfCluster(
45
+ status: Pick<KubernetesClusterAiAccessStatus, "runner">,
46
+ ): string {
47
+ return getKubernetesAiAccessTargetKind(status.runner) === "ai_agent"
48
+ ? "its Kubernetes AI agent"
49
+ : "its Runner";
50
+ }
51
+
52
+ /*
53
+ * The same as a role, for copy about the cluster in general: "the
54
+ * cluster's Kubernetes AI agent" or "the cluster's Runner".
55
+ */
56
+ export function describeClusterAccessTargetRole(
57
+ status: Pick<KubernetesClusterAiAccessStatus, "runner">,
58
+ ): string {
59
+ return getKubernetesAiAccessTargetKind(status.runner) === "ai_agent"
60
+ ? "the cluster's Kubernetes AI agent"
61
+ : "the cluster's Runner";
62
+ }
63
+
23
64
  /*
24
65
  * The prompt-side view of cluster access.
25
66
  *
@@ -55,7 +96,7 @@ export default class ClusterAccessContext {
55
96
  })
56
97
  .join(
57
98
  ", ",
58
- )}. Use run_kubectl for READ-ONLY inspection — kubectl get/describe/events/logs/top/rollout status — the way an on-call engineer would open a terminal: describe the failing pod, read its recent events, check node capacity and pending-pod reasons, tail the crashing container's logs. Prefer direct cluster inspection over guessing from metrics when the two disagree. Every kubectl command that ran is cited like any other tool result; a command that could not run comes back as an error, is not evidence, and must never be described as inspected. The Runner that runs kubectl lives in the cluster and can itself be down: if run_kubectl says a cluster's Runner did not pick up a command, that cluster is unreachable for the rest of this investigation — do not call run_kubectl on it again, continue with OneUptime telemetry, and say so in your report. Reading Secrets is refused and credential-looking values (Secret data, passwords, tokens, keys) are redacted from every output before you see it — never ask for them and never treat a redaction marker as a finding.`,
99
+ )}. Use run_kubectl for READ-ONLY inspection — kubectl get/describe/events/logs/top/rollout status — the way an on-call engineer would open a terminal: describe the failing pod, read its recent events, check node capacity and pending-pod reasons, tail the crashing container's logs. Prefer direct cluster inspection over guessing from metrics when the two disagree. Every kubectl command that ran is cited like any other tool result; a command that could not run comes back as an error, is not evidence, and must never be described as inspected. The agent (or Runner) that runs kubectl lives in the cluster and can itself be down: if run_kubectl says a cluster's agent or Runner did not pick up a command, that cluster is unreachable for the rest of this investigation — do not call run_kubectl on it again, continue with OneUptime telemetry, and say so in your report. Reading Secrets is refused and credential-looking values (Secret data, passwords, tokens, keys) are redacted from every output before you see it — never ask for them and never treat a redaction marker as a finding.`,
59
100
  );
60
101
  }
61
102
 
@@ -78,7 +119,7 @@ export default class ClusterAccessContext {
78
119
  }
79
120
 
80
121
  lines.push(
81
- `Add a section **${ClusterAccessContext.REPORT_SECTION_HEADING}** before Suggested next steps: one or two sentences on what you inspected directly on the cluster (or that you could not — access not set up, or the cluster's Runner not responding — and that the human should check the cluster's AI page).`,
122
+ `Add a section **${ClusterAccessContext.REPORT_SECTION_HEADING}** before Suggested next steps: one or two sentences on what you inspected directly on the cluster (or that you could not — access not set up, or the cluster's AI agent or Runner not responding — and that the human should check the cluster's AI agent page (AI → Agent)).`,
82
123
  );
83
124
 
84
125
  return lines.join("\n");
@@ -97,13 +138,9 @@ export default class ClusterAccessContext {
97
138
  for (const status of statuses) {
98
139
  if (status.isInvestigationReady) {
99
140
  lines.push(
100
- `- Cluster "${status.clusterName}" (clusterId: ${status.clusterId}): kubectl READ access available via run_kubectl${
101
- status.accessMethod === "in_cluster"
102
- ? " (in-cluster Runner)"
103
- : status.credentialName
104
- ? ` (Runner "${status.runner?.name}" with credential "${status.credentialName}")`
105
- : ""
106
- }. Remediation: ${ClusterAccessContext.describeRemediationMode(status)}.`,
141
+ `- Cluster "${status.clusterName}" (clusterId: ${status.clusterId}): kubectl READ access available via run_kubectl${ClusterAccessContext.describeAccessPath(
142
+ status,
143
+ )}. Remediation: ${ClusterAccessContext.describeRemediationMode(status)}.`,
107
144
  );
108
145
  continue;
109
146
  }
@@ -126,6 +163,27 @@ export default class ClusterAccessContext {
126
163
  return lines.join("\n");
127
164
  }
128
165
 
166
+ /*
167
+ * How kubectl reaches a ready cluster, as a parenthetical: the Kubernetes
168
+ * AI agent, the chart's previous in-cluster Runner, or a Runner with a
169
+ * credential.
170
+ */
171
+ private static describeAccessPath(
172
+ status: KubernetesClusterAiAccessStatus,
173
+ ): string {
174
+ if (getKubernetesAiAccessTargetKind(status.runner) === "ai_agent") {
175
+ return " (via the in-cluster Kubernetes AI agent)";
176
+ }
177
+
178
+ if (status.accessMethod === "in_cluster") {
179
+ return " (in-cluster Runner)";
180
+ }
181
+
182
+ return status.credentialName
183
+ ? ` (Runner "${status.runner?.name}" with credential "${status.credentialName}")`
184
+ : "";
185
+ }
186
+
129
187
  /*
130
188
  * The sentence the investigation panel shows humans when AI investigated
131
189
  * with OneUptime data only. Deterministic so it reads the same on every
@@ -7,6 +7,7 @@ import {
7
7
  KubernetesClusterAiAccessStatus,
8
8
  MAX_KUBECTL_COMMANDS_PER_INVESTIGATION,
9
9
  MAX_KUBECTL_TIMEOUT_MS,
10
+ getKubernetesAiAccessTargetKind,
10
11
  } from "../../../../Types/Kubernetes/KubernetesClusterAiAccess";
11
12
  import KubectlPolicy, {
12
13
  KubectlPolicyResult,
@@ -30,6 +31,11 @@ import {
30
31
  LIST_CLUSTER_ACCESS_TOOL_NAME,
31
32
  RUN_KUBECTL_TOOL_NAME,
32
33
  } from "../../../../Types/Kubernetes/KubernetesClusterAiAccessToolNames";
34
+ import {
35
+ describeClusterAccessTarget,
36
+ describeClusterAccessTargetOfCluster,
37
+ describeClusterAccessTargetRole,
38
+ } from "./ClusterAccessContext";
33
39
 
34
40
  /*
35
41
  * The run-scoped, READ-ONLY kubectl toolkit for an investigation.
@@ -227,8 +233,13 @@ export default class KubectlInvestigationToolkit {
227
233
  : ""
228
234
  } — ${
229
235
  this.isClusterUnreachable(cluster.clusterId)
230
- ? `UNREACHABLE for the rest of this investigation: its Runner "${cluster.runner?.name}" did not pick up an earlier command. Do not call run_kubectl on it again.`
231
- : `read-only kubectl via Runner "${cluster.runner?.name}"`
236
+ ? `UNREACHABLE for the rest of this investigation: its ${describeClusterAccessTarget(
237
+ cluster,
238
+ ).replace(
239
+ /^the /,
240
+ "",
241
+ )} did not pick up an earlier command. Do not call run_kubectl on it again.`
242
+ : `read-only kubectl via ${describeClusterAccessTarget(cluster)}`
232
243
  }`;
233
244
  })
234
245
  .join("\n");
@@ -345,15 +356,20 @@ export default class KubectlInvestigationToolkit {
345
356
  );
346
357
 
347
358
  if (tripped !== undefined) {
359
+ const target: string = describeClusterAccessTarget(cluster);
360
+ const role: string = describeClusterAccessTargetRole(cluster);
361
+
348
362
  return this.failure(
349
- `Runner "${cluster.runner.name}", which serves cluster "${cluster.clusterName}", did not pick up an earlier command${
363
+ `${target.charAt(0).toUpperCase()}${target.slice(1)}, which serves cluster "${cluster.clusterName}", did not pick up an earlier command${
350
364
  tripped.clusterName !== cluster.clusterName
351
365
  ? ` (for cluster "${tripped.clusterName}")`
352
366
  : ""
353
367
  } within ${KubectlInvestigationToolkit.describeSeconds(
354
368
  tripped.claimWindowMs,
355
- )}, so the cluster is treated as unreachable for the rest of this investigation. Nothing was run. Do not call run_kubectl on this cluster again: continue with OneUptime telemetry and say in **Cluster access** that the cluster's Runner did not respond.`,
356
- `kubectl was not run on cluster "${cluster.clusterName}": its Runner did not pick up an earlier command, so the cluster was unreachable for the rest of this investigation.`,
369
+ )}, so the cluster is treated as unreachable for the rest of this investigation. Nothing was run. Do not call run_kubectl on this cluster again: continue with OneUptime telemetry and say in **Cluster access** that ${role} did not respond.`,
370
+ `kubectl was not run on cluster "${cluster.clusterName}": ${describeClusterAccessTargetOfCluster(
371
+ cluster,
372
+ )} did not pick up an earlier command, so the cluster was unreachable for the rest of this investigation.`,
357
373
  );
358
374
  }
359
375
 
@@ -427,8 +443,12 @@ export default class KubectlInvestigationToolkit {
427
443
  const alsoUnreachable: Array<KubernetesClusterAiAccessStatus> =
428
444
  this.getOtherClustersOnRunner(cluster);
429
445
 
446
+ const role: string = describeClusterAccessTargetRole(cluster);
447
+
430
448
  return this.failure(
431
- `kubectl was NOT run on cluster "${cluster.clusterName}": its Runner did not pick up "${outcome.displayCommand}" within ${KubectlInvestigationToolkit.describeSeconds(
449
+ `kubectl was NOT run on cluster "${cluster.clusterName}": ${describeClusterAccessTargetOfCluster(
450
+ cluster,
451
+ )} did not pick up "${outcome.displayCommand}" within ${KubectlInvestigationToolkit.describeSeconds(
432
452
  budget.plan.claimTimeoutInMs,
433
453
  )} (it may be offline, restarting or busy). The cluster is treated as unreachable for the rest of this investigation — do not call run_kubectl on it again.${
434
454
  alsoUnreachable.length > 0
@@ -440,8 +460,10 @@ export default class KubectlInvestigationToolkit {
440
460
  ", ",
441
461
  )}, so ${alsoUnreachable.length === 1 ? "that cluster is" : "those clusters are"} unreachable too.`
442
462
  : ""
443
- } Continue with OneUptime telemetry and say in **Cluster access** that the cluster's Runner did not respond.`,
444
- `kubectl was not run on cluster "${cluster.clusterName}": its Runner did not pick up the command in time.`,
463
+ } Continue with OneUptime telemetry and say in **Cluster access** that ${role} did not respond.`,
464
+ `kubectl was not run on cluster "${cluster.clusterName}": ${describeClusterAccessTargetOfCluster(
465
+ cluster,
466
+ )} did not pick up the command in time.`,
445
467
  );
446
468
  }
447
469
 
@@ -460,9 +482,16 @@ export default class KubectlInvestigationToolkit {
460
482
  ? redactedReason
461
483
  : `${redactedReason}.`;
462
484
 
485
+ const isAgent: boolean =
486
+ getKubernetesAiAccessTargetKind(cluster.runner) === "ai_agent";
487
+
463
488
  return this.failure(
464
- `No kubectl result came back from cluster "${cluster.clusterName}" for "${outcome.displayCommand}": ${reason} Nothing from this command is evidence. Continue with OneUptime telemetry and mention in **Cluster access** that the cluster's Runner stopped responding.`,
465
- `${KUBECTL_RESULT_UNKNOWN_EVENT_PREFIX} the Runner of cluster "${cluster.clusterName}" took the command, but no result came back, so whether it ran is unknown.`,
489
+ `No kubectl result came back from cluster "${cluster.clusterName}" for "${outcome.displayCommand}": ${reason} Nothing from this command is evidence. Continue with OneUptime telemetry and mention in **Cluster access** that ${describeClusterAccessTargetRole(
490
+ cluster,
491
+ )} stopped responding.`,
492
+ `${KUBECTL_RESULT_UNKNOWN_EVENT_PREFIX} the ${
493
+ isAgent ? "Kubernetes AI agent" : "Runner"
494
+ } of cluster "${cluster.clusterName}" took the command, but no result came back, so whether it ran is unknown.`,
466
495
  );
467
496
  }
468
497
 
@@ -392,6 +392,9 @@ export default class KubectlJobRunner {
392
392
  wasClaimed: claimState.wasClaimed,
393
393
  claimTimeoutInMs: data.claimTimeoutInMs,
394
394
  executionTimeoutInMs: data.executionTimeoutInMs,
395
+ isForKubernetesAiAgent: Boolean(
396
+ job.targetKubernetesAiAgentId,
397
+ ),
395
398
  })
396
399
  : terminalJob.errorMessage ||
397
400
  `Command ended with status ${terminalJob.status}.`,
@@ -612,18 +615,26 @@ export default class KubectlJobRunner {
612
615
  wasClaimed: boolean | undefined;
613
616
  claimTimeoutInMs: number;
614
617
  executionTimeoutInMs: number;
618
+ // The job was for the cluster's Kubernetes AI agent, not a Runner.
619
+ isForKubernetesAiAgent?: boolean | undefined;
615
620
  }): string {
621
+ const executor: string = data.isForKubernetesAiAgent
622
+ ? "Kubernetes AI agent"
623
+ : "Runner";
624
+
616
625
  if (data.wasClaimed === false) {
617
- return `The cluster's Runner did not pick up this kubectl command within ${KubectlJobRunner.describeSeconds(
626
+ return `The cluster's ${executor} did not pick up this kubectl command within ${KubectlJobRunner.describeSeconds(
618
627
  data.claimTimeoutInMs,
619
628
  )} — it may be offline, restarting or busy with other work. Nothing was run on the cluster.`;
620
629
  }
621
630
 
622
631
  if (data.wasClaimed === undefined) {
623
- return "No result came back for this kubectl command in time, and whether a Runner picked it up could not be read. What the command did is unknown.";
632
+ return `No result came back for this kubectl command in time, and whether ${
633
+ data.isForKubernetesAiAgent ? "the Kubernetes AI agent" : "a Runner"
634
+ } picked it up could not be read. What the command did is unknown.`;
624
635
  }
625
636
 
626
- return `The Runner took this kubectl command but did not report a result in time — it stopped responding, or kubectl outlived its ${KubectlJobRunner.describeSeconds(
637
+ return `The ${executor} took this kubectl command but did not report a result in time — it stopped responding, or kubectl outlived its ${KubectlJobRunner.describeSeconds(
627
638
  data.executionTimeoutInMs,
628
639
  )} timeout. Whether it ran, and what it did, is unknown.`;
629
640
  }
@@ -38,6 +38,7 @@ import {
38
38
  KubernetesRunnerPosture,
39
39
  isKubernetesAgentRunnerName,
40
40
  isKubernetesAgentRunnerPosture,
41
+ getKubernetesAiAccessTargetKind,
41
42
  isUnattendedRemediationMode,
42
43
  parseKubernetesRunnerPosture,
43
44
  } from "../../../../Types/Kubernetes/KubernetesClusterAiAccess";
@@ -82,7 +83,10 @@ import KubectlJobRunner, {
82
83
  RedactedKubectlOutput,
83
84
  } from "../ClusterAccess/KubectlJobRunner";
84
85
  import KubectlOutputRedactor from "../../../../Utils/AiRemediation/KubectlOutputRedactor";
85
- import { UNATTENDED_ROUND_BECOMES_PROPOSAL_SUMMARY } from "../ClusterAccess/ClusterAccessContext";
86
+ import {
87
+ UNATTENDED_ROUND_BECOMES_PROPOSAL_SUMMARY,
88
+ describeClusterAccessTarget,
89
+ } from "../ClusterAccess/ClusterAccessContext";
86
90
  import logger from "../../Logger";
87
91
 
88
92
  /*
@@ -404,7 +408,7 @@ export default class RemediationCommandToolkit {
404
408
  definition: {
405
409
  name: "list_command_targets",
406
410
  description:
407
- "List where this remediation may run commands: Runners (Bash runs on the Runner's host; SSH runs on an assigned credential's host) and Kubernetes clusters (Kubectl runs through the cluster's Runner). Call this before composing any command.",
411
+ "List where this remediation may run commands: Runners (Bash runs on the Runner's host; SSH runs on an assigned credential's host) and Kubernetes clusters (Kubectl runs through the cluster's Kubernetes AI agent or Runner). Call this before composing any command.",
408
412
  inputSchema: {
409
413
  type: "object",
410
414
  properties: {},
@@ -497,7 +501,7 @@ export default class RemediationCommandToolkit {
497
501
  kubernetesClusterId: cluster.clusterId,
498
502
  name: cluster.clusterName,
499
503
  stepTypes: "Kubectl",
500
- via: `Runner "${cluster.runner?.name}"${
504
+ via: `${describeClusterAccessTarget(cluster)}${
501
505
  cluster.accessMethod === "in_cluster" ? " (in-cluster)" : ""
502
506
  }`,
503
507
  /*
@@ -785,7 +789,10 @@ export default class RemediationCommandToolkit {
785
789
  return refusal
786
790
  ? RemediationCommandToolkit.describeRunnerScopeRefusal({
787
791
  refusal,
788
- runnerLabel: `the Runner of cluster "${data.cluster.clusterName}"`,
792
+ runnerLabel:
793
+ getKubernetesAiAccessTargetKind(data.cluster.runner) === "ai_agent"
794
+ ? `the Kubernetes AI agent of cluster "${data.cluster.clusterName}"`
795
+ : `the Runner of cluster "${data.cluster.clusterName}"`,
789
796
  settings: RemediationCommandToolkit.getRunnerScopeSettings(
790
797
  data.cluster,
791
798
  ),
@@ -794,14 +801,29 @@ export default class RemediationCommandToolkit {
794
801
  }
795
802
 
796
803
  /*
797
- * Where the bound Runner's write scope is set, for a refusal to name: the
798
- * Kubernetes agent chart's values for the agent's in-cluster Runner (by
799
- * its server-owned name, or its posture), the Runner's own environment
800
- * for any other — a credential Runner, which no chart configures.
804
+ * Where the target's write scope is set, for a refusal to name — three
805
+ * ways, by who runs kubectl for the cluster:
806
+ *
807
+ * - the Kubernetes AI agent (runner.kind "ai_agent"): the chart's
808
+ * aiAgent.remediation.* values;
809
+ * - the chart's previous in-cluster Runner (by its server-owned name, or
810
+ * its posture): its values are aiAccess.remediation.*, and changing
811
+ * them now means upgrading the chart to the AI agent, which replaces it;
812
+ * - any other Runner — a credential Runner, which no chart configures:
813
+ * its own environment.
801
814
  */
802
- private static getRunnerScopeSettings(
803
- cluster: KubernetesClusterAiAccessStatus,
815
+ public static getRunnerScopeSettings(
816
+ cluster: Pick<KubernetesClusterAiAccessStatus, "runner">,
804
817
  ): { namespaces: string; nodeOperations: string } {
818
+ if (getKubernetesAiAccessTargetKind(cluster.runner) === "ai_agent") {
819
+ return {
820
+ namespaces:
821
+ "aiAgent.remediation.namespaces on the Kubernetes agent chart",
822
+ nodeOperations:
823
+ "aiAgent.remediation.nodeOperations=false on the Kubernetes agent chart",
824
+ };
825
+ }
826
+
805
827
  const isAgentRunner: boolean =
806
828
  isKubernetesAgentRunnerName(cluster.runner?.name) ||
807
829
  isKubernetesAgentRunnerPosture(cluster.runner?.posture);
@@ -809,9 +831,9 @@ export default class RemediationCommandToolkit {
809
831
  if (isAgentRunner) {
810
832
  return {
811
833
  namespaces:
812
- "aiAccess.remediation.namespaces on the Kubernetes agent chart",
834
+ "aiAccess.remediation.namespaces on the Kubernetes agent chart; after upgrading to the Kubernetes AI agent, aiAgent.remediation.namespaces",
813
835
  nodeOperations:
814
- "aiAccess.remediation.nodeOperations=false on the Kubernetes agent chart",
836
+ "aiAccess.remediation.nodeOperations=false on the Kubernetes agent chart; after upgrading to the Kubernetes AI agent, aiAgent.remediation.nodeOperations",
815
837
  };
816
838
  }
817
839
 
@@ -1783,7 +1805,7 @@ export default class RemediationCommandToolkit {
1783
1805
  return {
1784
1806
  text: `Cluster "${status.clusterName}" no longer allows AI remediation${
1785
1807
  gap ? ` (${gap.title})` : ""
1786
- } — its AI page changed during this run. ${stopText}`,
1808
+ } — its AI agent page changed during this run. ${stopText}`,
1787
1809
  };
1788
1810
  }
1789
1811
 
@@ -1794,7 +1816,7 @@ export default class RemediationCommandToolkit {
1794
1816
  ) {
1795
1817
  this.revokeCluster(clusterId);
1796
1818
  return {
1797
- text: `Cluster "${status.clusterName}" was re-bound to a different Runner or credential during this run. ${stopText}`,
1819
+ text: `Cluster "${status.clusterName}" was re-bound to a different Runner or credential during this run (or its Kubernetes AI agent took over from its Runner). ${stopText}`,
1798
1820
  };
1799
1821
  }
1800
1822
 
@@ -2001,7 +2023,7 @@ export default class RemediationCommandToolkit {
2001
2023
  return {
2002
2024
  definition: {
2003
2025
  name: "propose_remediation_commands",
2004
- description: `Propose an ordered plan of at most ${MAX_PLAN_COMMANDS} remediation commands for one-click human approval. Nothing executes until a human approves the whole plan. Call this at most once with your final plan (a later call replaces the earlier one). Provide a rollbackCommand for every state-changing command that has an undo (for Kubectl, e.g. kubectl rollout undo deployment/<name> -n <namespace>). Kubectl commands run through the cluster's Runner, and a write outside its writeScope (list_command_targets) is refused; ${KUBECTL_NEVER_RUNS_SUMMARY}.`,
2026
+ description: `Propose an ordered plan of at most ${MAX_PLAN_COMMANDS} remediation commands for one-click human approval. Nothing executes until a human approves the whole plan. Call this at most once with your final plan (a later call replaces the earlier one). Provide a rollbackCommand for every state-changing command that has an undo (for Kubectl, e.g. kubectl rollout undo deployment/<name> -n <namespace>). Kubectl commands run through the cluster's Kubernetes AI agent or Runner, and a write outside its writeScope (list_command_targets) is refused; ${KUBECTL_NEVER_RUNS_SUMMARY}.`,
2005
2027
  inputSchema: {
2006
2028
  type: "object",
2007
2029
  properties: {
@@ -107,6 +107,26 @@ import CaptureSpan from "../../Telemetry/CaptureSpan";
107
107
  * suggestion settles what happened instead of re-executing anything.
108
108
  */
109
109
 
110
+ /*
111
+ * A cluster round: remediation a cluster's AI agent page asked for (its
112
+ * Fixes mode), not an auto-remediation rule — it names a cluster and no
113
+ * rule. The project's "Enable AI command execution" opt-in gates rule
114
+ * rounds only; a cluster round's consent lives on the cluster (see
115
+ * RemediationExecutionRunner.checkProjectGates). Keyed on the suggestion
116
+ * row, never on the plan's step types: a rule can compose an all-kubectl
117
+ * plan, and it was composed under the opt-in, so it stays under it. Shared
118
+ * with the approve route so execution and approval can never disagree about
119
+ * which rounds need the opt-in.
120
+ */
121
+ export function isClusterRemediationRound(suggestion: {
122
+ kubernetesClusterId?: ObjectID | undefined;
123
+ autoRemediationRuleId?: ObjectID | undefined;
124
+ }): boolean {
125
+ return (
126
+ Boolean(suggestion.kubernetesClusterId) && !suggestion.autoRemediationRuleId
127
+ );
128
+ }
129
+
110
130
  const MAX_SIGNAL_TITLE_CHARS: number = 500;
111
131
  const MAX_SIGNAL_DESCRIPTION_CHARS: number = 4000;
112
132
  const MAX_POSTED_ANALYSIS_CHARS: number = 6000;
@@ -507,25 +527,16 @@ export default class RemediationExecutionRunner {
507
527
  return;
508
528
  }
509
529
 
510
- // Gates that must still hold at execution time, not just at rule match.
511
- const gateFailure: string | null =
512
- await this.checkProjectGates(projectId);
513
- if (gateFailure) {
514
- await this.settleNoneApplicable({
515
- suggestion,
516
- rationaleMarkdown: gateFailure,
517
- });
518
- await this.completeRunQuietly(aiRunId);
519
- return;
520
- }
521
-
522
530
  /*
523
531
  * A cluster-level round whose cluster was deleted while it waited in
524
532
  * the queue: the delete nulled kubernetesClusterId (ON DELETE SET
525
533
  * NULL), and a cluster round never had a rule — so without this it
526
534
  * would fall into the rule lane below and be closed as "the rule
527
535
  * behind this suggestion was deleted", naming a rule that never
528
- * existed. Its server-written name is what is left to tell.
536
+ * existed. Its server-written name is what is left to tell. Checked
537
+ * before the project gates: nothing is left to run, and with no
538
+ * cluster on the row it no longer reads as a cluster round, so the
539
+ * gates would otherwise blame an opt-in it never needed.
529
540
  */
530
541
  const deletedClusterRound: { clusterName: string } | null =
531
542
  !suggestion.kubernetesClusterId && !suggestion.autoRemediationRuleId
@@ -541,6 +552,20 @@ export default class RemediationExecutionRunner {
541
552
  return;
542
553
  }
543
554
 
555
+ // Gates that must still hold at execution time, not just at rule match.
556
+ const gateFailure: string | null = await this.checkProjectGates({
557
+ projectId,
558
+ isClusterRound: isClusterRemediationRound(suggestion),
559
+ });
560
+ if (gateFailure) {
561
+ await this.settleNoneApplicable({
562
+ suggestion,
563
+ rationaleMarkdown: gateFailure,
564
+ });
565
+ await this.completeRunQuietly(aiRunId);
566
+ return;
567
+ }
568
+
544
569
  if (suggestion.kubernetesClusterId) {
545
570
  /*
546
571
  * Cluster-level remediation: the cluster's AI page plays the rule's
@@ -565,7 +590,7 @@ export default class RemediationExecutionRunner {
565
590
  suggestion,
566
591
  rationaleMarkdown: `OneUptime AI can no longer remediate cluster "${
567
592
  clusterTarget?.clusterName || "(deleted)"
568
- }"${firstGap ? `: ${firstGap}` : ""}. Nothing was run or proposed. Review the cluster's AI page.`,
593
+ }"${firstGap ? `: ${firstGap}` : ""}. Nothing was run or proposed. Review the cluster's AI agent page (AI → Agent).`,
569
594
  });
570
595
  await this.completeRunQuietly(aiRunId);
571
596
  return;
@@ -1119,7 +1144,7 @@ export default class RemediationExecutionRunner {
1119
1144
  if (live.withdrawnReason) {
1120
1145
  await this.settleNoneApplicable({
1121
1146
  suggestion,
1122
- rationaleMarkdown: `${live.withdrawnReason} Review the cluster's AI page.\n\n${data.rationaleMarkdown}`,
1147
+ rationaleMarkdown: `${live.withdrawnReason} Review the cluster's AI agent page (AI → Agent).\n\n${data.rationaleMarkdown}`,
1123
1148
  });
1124
1149
  return;
1125
1150
  }
@@ -1386,12 +1411,26 @@ export default class RemediationExecutionRunner {
1386
1411
  });
1387
1412
  }
1388
1413
 
1389
- // Null when all gates pass; otherwise the rationale for settling quietly.
1390
- private static async checkProjectGates(
1391
- projectId: ObjectID,
1392
- ): Promise<string | null> {
1414
+ /*
1415
+ * The project switches a round must still pass when it runs. Null when
1416
+ * they do; otherwise the rationale for settling quietly.
1417
+ *
1418
+ * Enable AI and Enable auto-remediation are kill switches for every
1419
+ * round. The "Enable AI command execution" opt-in gates rule rounds
1420
+ * (Bash/SSH on Runners, and kubectl a rule composes) but not a cluster
1421
+ * round (isClusterRemediationRound): its consent is the cluster's own
1422
+ * Fixes mode plus, for the in-cluster Kubernetes AI agent, the chart's
1423
+ * write RBAC. A cluster reached through an advanced Runner with a
1424
+ * Kubernetes credential has no chart RBAC behind it, so its status keeps
1425
+ * the project_ai_command_execution_disabled gap while the opt-in is off —
1426
+ * and the cluster round stops at isRemediationReady instead.
1427
+ */
1428
+ public static async checkProjectGates(data: {
1429
+ projectId: ObjectID;
1430
+ isClusterRound: boolean;
1431
+ }): Promise<string | null> {
1393
1432
  const project: Project | null = await ProjectService.findOneById({
1394
- id: projectId,
1433
+ id: data.projectId,
1395
1434
  select: {
1396
1435
  enableAi: true,
1397
1436
  enableAutoRemediation: true,
@@ -1405,15 +1444,19 @@ export default class RemediationExecutionRunner {
1405
1444
  project.enableAi === false ||
1406
1445
  project.enableAutoRemediation === false
1407
1446
  ) {
1408
- return "AI or auto-remediation was disabled for this project before the run started — nothing was run or proposed.";
1447
+ return "AI or auto-remediation was disabled for this project before the run started (Project Settings → AI Features) — nothing was run or proposed.";
1448
+ }
1449
+
1450
+ if (data.isClusterRound) {
1451
+ return null;
1409
1452
  }
1410
1453
 
1411
1454
  /*
1412
- * Opt-in semantics (=== true): AI command execution never runs in a
1413
- * project that has not explicitly turned it on.
1455
+ * Opt-in semantics (=== true): a rule's AI command execution never runs
1456
+ * in a project that has not explicitly turned it on.
1414
1457
  */
1415
1458
  if (project.enableAiCommandExecution !== true) {
1416
- return "AI command execution is not enabled for this project (Project Settings → AI) — nothing was run or proposed.";
1459
+ return "AI command execution is not enabled for this project (Project Settings → AI Features) — nothing was run or proposed.";
1417
1460
  }
1418
1461
 
1419
1462
  return null;
@@ -18,6 +18,7 @@ import Project from "../../../../Models/DatabaseModels/Project";
18
18
  import LlmProvider from "../../../../Models/DatabaseModels/LlmProvider";
19
19
  import AIRunService from "../../../Services/AIRunService";
20
20
  import AIRunEventService from "../../../Services/AIRunEventService";
21
+ import AIService from "../../../Services/AIService";
21
22
  import ProjectService from "../../../Services/ProjectService";
22
23
  import LlmProviderService from "../../../Services/LlmProviderService";
23
24
  import AIInvestigationQueue from "./InvestigationQueue";
@@ -205,10 +206,10 @@ export interface InvestigationRequest {
205
206
 
206
207
  export default class AIInvestigationEngine {
207
208
  /*
208
- * Shared gate: AI enabled, the subject's auto-investigation opt-in on, and an
209
- * LLM provider configured. Incidents and alerts each have their own opt-in so
210
- * they can be enabled independently. Runs before any (subject-specific)
211
- * context assembly.
209
+ * Shared gate: AI enabled, the subject's auto-investigation opt-in on, an
210
+ * LLM provider configured, and AI credits to pay for it. Incidents and
211
+ * alerts each have their own opt-in so they can be enabled independently.
212
+ * Runs before any (subject-specific) context assembly.
212
213
  */
213
214
  @CaptureSpan()
214
215
  public static async isEnabledForProject(
@@ -249,16 +250,58 @@ export default class AIInvestigationEngine {
249
250
  return "automatic_investigation_disabled";
250
251
  }
251
252
 
253
+ return this.getProviderOrBalanceReason(projectId);
254
+ }
255
+
256
+ /*
257
+ * The half of the gate that is not a switch: a model to call, and AI
258
+ * credits to pay for it. Shared with the other autonomous AI work that
259
+ * has its own switch (the postmortem draft on resolve), so the two can
260
+ * never disagree about whether AI can run at all.
261
+ *
262
+ * The balance check is the same predicate as the Kubernetes cluster's
263
+ * ai_balance_insufficient gap (AIService.getAiBalanceBlocker): on
264
+ * OneUptime's own billed provider, with no credits left and auto-recharge
265
+ * off, every model call would be refused with "Insufficient AI balance" —
266
+ * so a run started now would only fail, be retried, and fail again, and
267
+ * nobody would see why. It fails OPEN: a balance that cannot be read
268
+ * never blocks, because the model call itself still enforces the balance.
269
+ */
270
+ public static async getProviderOrBalanceReason(
271
+ projectId: ObjectID,
272
+ ): Promise<"provider_missing" | "insufficient_ai_balance" | null> {
252
273
  const llmProvider: LlmProvider | null =
253
274
  await LlmProviderService.getLLMProviderForProject(projectId);
254
275
 
255
276
  if (!llmProvider) {
256
277
  logger.debug(
257
- `AI: skipping investigation for project ${projectId.toString()} — no LLM provider configured.`,
278
+ `AI: skipping autonomous AI work for project ${projectId.toString()} — no LLM provider configured.`,
258
279
  );
259
280
  return "provider_missing";
260
281
  }
261
282
 
283
+ let balanceBlocker: string | null = null;
284
+
285
+ try {
286
+ balanceBlocker = await AIService.getAiBalanceBlocker({
287
+ projectId,
288
+ // Already resolved above — spares the predicate a second lookup.
289
+ llmProvider,
290
+ });
291
+ } catch (error) {
292
+ logger.error(
293
+ `AI: could not check the AI balance for project ${projectId.toString()}; not blocking on it: ${error}`,
294
+ );
295
+ balanceBlocker = null;
296
+ }
297
+
298
+ if (balanceBlocker) {
299
+ logger.debug(
300
+ `AI: skipping autonomous AI work for project ${projectId.toString()} — ${balanceBlocker}`,
301
+ );
302
+ return "insufficient_ai_balance";
303
+ }
304
+
262
305
  return null;
263
306
  }
264
307