@datalayer/core 1.1.60 → 1.2.10

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 (496) hide show
  1. package/README.md +41 -18
  2. package/lib/api/DatalayerApi.d.ts +42 -1
  3. package/lib/api/DatalayerApi.js +90 -3
  4. package/lib/api/constants.d.ts +19 -1
  5. package/lib/api/constants.js +19 -1
  6. package/lib/api/contents/attachments.d.ts +9 -0
  7. package/lib/api/contents/attachments.js +39 -0
  8. package/lib/api/contents/bridges.d.ts +22 -0
  9. package/lib/api/contents/bridges.js +79 -0
  10. package/lib/api/contents/capabilities.d.ts +11 -0
  11. package/lib/api/contents/capabilities.js +21 -0
  12. package/lib/api/contents/cloudStorage.d.ts +31 -0
  13. package/lib/api/contents/cloudStorage.js +89 -0
  14. package/lib/api/contents/dataservers.d.ts +37 -0
  15. package/lib/api/contents/dataservers.js +121 -0
  16. package/lib/api/contents/datasets.d.ts +63 -0
  17. package/lib/api/contents/datasets.js +82 -0
  18. package/lib/api/contents/datasources.d.ts +70 -0
  19. package/lib/api/contents/datasources.js +149 -0
  20. package/lib/api/contents/generated.d.ts +1070 -0
  21. package/lib/api/contents/index.d.ts +16 -0
  22. package/lib/api/contents/index.js +20 -0
  23. package/lib/api/contents/mcp.d.ts +46 -0
  24. package/lib/api/contents/mcp.js +157 -0
  25. package/lib/api/contents/objects.d.ts +31 -0
  26. package/lib/api/contents/objects.js +88 -0
  27. package/lib/api/contents/operations.d.ts +3 -0
  28. package/lib/api/contents/operations.js +19 -0
  29. package/lib/api/contents/runtimeMounts.d.ts +40 -0
  30. package/lib/api/contents/runtimeMounts.js +59 -0
  31. package/lib/api/contents/sandboxUid.d.ts +21 -0
  32. package/lib/api/contents/sandboxUid.js +27 -0
  33. package/lib/api/contents/sources.d.ts +19 -0
  34. package/lib/api/contents/sources.js +119 -0
  35. package/lib/api/contents/sync.d.ts +18 -0
  36. package/lib/api/contents/sync.js +69 -0
  37. package/lib/api/contents/transfers.d.ts +38 -0
  38. package/lib/api/contents/transfers.js +123 -0
  39. package/lib/api/evals/client.d.ts +402 -0
  40. package/lib/api/evals/client.js +359 -0
  41. package/lib/api/evals/index.d.ts +10 -0
  42. package/lib/api/evals/index.js +18 -0
  43. package/lib/api/evals/request.d.ts +43 -0
  44. package/lib/api/evals/request.js +67 -0
  45. package/lib/api/evals/status.d.ts +27 -0
  46. package/lib/api/evals/status.js +122 -0
  47. package/lib/api/evals/types.d.ts +1335 -0
  48. package/lib/api/evals/types.js +5 -0
  49. package/lib/api/iam/connectedAgents.d.ts +68 -0
  50. package/lib/api/iam/connectedAgents.js +87 -0
  51. package/lib/api/iam/identityProviders.d.ts +76 -0
  52. package/lib/api/iam/identityProviders.js +187 -0
  53. package/lib/api/iam/index.d.ts +3 -1
  54. package/lib/api/iam/index.js +3 -1
  55. package/lib/api/iam/mcpAlertRules.d.ts +51 -0
  56. package/lib/api/iam/mcpAlertRules.js +198 -0
  57. package/lib/api/iam/mcpAuditSettings.d.ts +46 -0
  58. package/lib/api/iam/mcpAuditSettings.js +120 -0
  59. package/lib/api/iam/mcpPolicy.d.ts +181 -0
  60. package/lib/api/iam/mcpPolicy.js +168 -0
  61. package/lib/api/iam/organizationTeams.d.ts +13 -0
  62. package/lib/api/iam/organizationTeams.js +43 -0
  63. package/lib/api/iam/profile.d.ts +17 -1
  64. package/lib/api/iam/profile.js +27 -0
  65. package/lib/api/iam/scimTokens.d.ts +79 -0
  66. package/lib/api/iam/scimTokens.js +141 -0
  67. package/lib/api/iam/secrets.js +9 -21
  68. package/lib/api/iam/serviceAgents.d.ts +68 -0
  69. package/lib/api/iam/serviceAgents.js +119 -0
  70. package/lib/api/iam/trials.d.ts +38 -0
  71. package/lib/api/iam/trials.js +66 -0
  72. package/lib/api/index.d.ts +8 -1
  73. package/lib/api/index.js +7 -1
  74. package/lib/api/mcp/activity.d.ts +37 -0
  75. package/lib/api/mcp/activity.js +26 -0
  76. package/lib/api/mcp/alerts.d.ts +25 -0
  77. package/lib/api/mcp/alerts.js +51 -0
  78. package/lib/api/mcp/audit.d.ts +29 -0
  79. package/lib/api/mcp/audit.js +55 -0
  80. package/lib/api/mcp/bindings.d.ts +18 -0
  81. package/lib/api/mcp/bindings.js +42 -0
  82. package/lib/api/mcp/forwarding.d.ts +25 -0
  83. package/lib/api/mcp/forwarding.js +46 -0
  84. package/lib/api/mcp/gateway.d.ts +16 -0
  85. package/lib/api/mcp/gateway.js +70 -0
  86. package/lib/api/mcp/generated.d.ts +22 -0
  87. package/lib/api/mcp/generated.js +213 -0
  88. package/lib/api/mcp/index.d.ts +17 -0
  89. package/lib/api/mcp/index.js +25 -0
  90. package/lib/api/mcp/observability.d.ts +141 -0
  91. package/lib/api/mcp/observability.js +267 -0
  92. package/lib/api/mcp/operations.d.ts +83 -0
  93. package/lib/api/mcp/operations.js +50 -0
  94. package/lib/api/mcp/organizations.d.ts +102 -0
  95. package/lib/api/mcp/organizations.js +46 -0
  96. package/lib/api/mcp/policy.d.ts +9 -0
  97. package/lib/api/mcp/policy.js +23 -0
  98. package/lib/api/mcp/tasks.d.ts +49 -0
  99. package/lib/api/mcp/tasks.js +147 -0
  100. package/lib/api/orchestration/client.d.ts +53 -0
  101. package/lib/api/orchestration/client.js +105 -0
  102. package/lib/api/orchestration/events.d.ts +88 -0
  103. package/lib/api/orchestration/events.js +245 -0
  104. package/lib/api/orchestration/generated.d.ts +693 -0
  105. package/lib/api/orchestration/generated.js +687 -0
  106. package/lib/api/orchestration/index.d.ts +30 -0
  107. package/lib/api/orchestration/index.js +34 -0
  108. package/lib/api/orchestration/lifecycle.d.ts +39 -0
  109. package/lib/api/orchestration/lifecycle.js +57 -0
  110. package/lib/api/orchestration/measures.d.ts +55 -0
  111. package/lib/api/orchestration/measures.js +99 -0
  112. package/lib/api/otel/dashboards.d.ts +56 -0
  113. package/lib/api/otel/dashboards.js +50 -0
  114. package/lib/api/otel/index.d.ts +1 -0
  115. package/lib/api/otel/index.js +1 -0
  116. package/lib/api/otel/metrics.d.ts +16 -0
  117. package/lib/api/otel/metrics.js +15 -0
  118. package/lib/api/scheduler/client.d.ts +32 -0
  119. package/lib/api/scheduler/client.js +42 -0
  120. package/lib/api/scheduler/index.d.ts +8 -0
  121. package/lib/api/scheduler/index.js +16 -0
  122. package/lib/api/scheduler/request.d.ts +28 -0
  123. package/lib/api/scheduler/request.js +50 -0
  124. package/lib/api/scheduler/types.d.ts +88 -0
  125. package/lib/api/scheduler/types.js +5 -0
  126. package/lib/api/spacer/comments.d.ts +97 -0
  127. package/lib/api/spacer/comments.js +45 -0
  128. package/lib/api/spacer/index.d.ts +9 -0
  129. package/lib/api/spacer/index.js +17 -0
  130. package/lib/api/spacer/notebooks.d.ts +33 -0
  131. package/lib/api/spacer/notebooks.js +39 -0
  132. package/lib/api/spacer/request.d.ts +25 -0
  133. package/lib/api/spacer/request.js +46 -0
  134. package/lib/api/spacer/spaces.d.ts +68 -0
  135. package/lib/api/spacer/spaces.js +45 -0
  136. package/lib/api/utils/validation.d.ts +4 -4
  137. package/lib/api/utils/validation.js +10 -7
  138. package/lib/client/auth/index.js +0 -5
  139. package/lib/client/auth/storage.js +0 -5
  140. package/lib/client/auth/strategies.js +0 -5
  141. package/lib/client/base.d.ts +6 -0
  142. package/lib/client/base.js +8 -0
  143. package/lib/client/constants.d.ts +1 -0
  144. package/lib/client/constants.js +1 -0
  145. package/lib/client/index.d.ts +0 -10
  146. package/lib/client/index.js +2 -2
  147. package/lib/client/mixins/ContentsMixin.d.ts +71 -0
  148. package/lib/client/mixins/ContentsMixin.js +157 -0
  149. package/lib/client/mixins/IAMMixin.d.ts +0 -31
  150. package/lib/client/mixins/IAMMixin.js +0 -58
  151. package/lib/components/animation/AnimatedText.d.ts +2 -44
  152. package/lib/components/animation/AnimatedText.js +6 -126
  153. package/lib/components/anonymous/AnonymousKeyExpired.d.ts +56 -0
  154. package/lib/components/anonymous/AnonymousKeyExpired.js +96 -0
  155. package/lib/components/anonymous/AnonymousKeyTimer.d.ts +63 -0
  156. package/lib/components/anonymous/AnonymousKeyTimer.js +140 -0
  157. package/lib/components/anonymous/index.d.ts +7 -0
  158. package/lib/components/anonymous/index.js +15 -0
  159. package/lib/components/auth/SigInAPIKey.d.ts +1 -0
  160. package/lib/components/auth/SigInAPIKey.js +0 -6
  161. package/lib/components/auth/SignIn.d.ts +1 -0
  162. package/lib/components/auth/SignIn.js +0 -4
  163. package/lib/components/auth/SignIn.stories.d.ts +2 -2
  164. package/lib/components/avatars/BoringAvatar.d.ts +1 -1
  165. package/lib/components/avatars/BoringAvatar.stories.d.ts +1 -1
  166. package/lib/components/avatars/DLAvatar.d.ts +1 -1
  167. package/lib/components/avatars/DLAvatar.js +0 -4
  168. package/lib/components/avatars/UserAvatar.d.ts +16 -1
  169. package/lib/components/avatars/UserAvatar.js +15 -13
  170. package/lib/components/avatars/UserProfileAvatar.d.ts +1 -1
  171. package/lib/components/banners/NoAutomationBanner.d.ts +1 -1
  172. package/lib/components/billing/BillingEntitySelect.d.ts +16 -0
  173. package/lib/components/billing/BillingEntitySelect.js +49 -27
  174. package/lib/components/billing/eligibility.d.ts +22 -0
  175. package/lib/components/billing/eligibility.js +27 -0
  176. package/lib/components/billing/index.d.ts +1 -0
  177. package/lib/components/billing/index.js +1 -4
  178. package/lib/components/buttons/DownloadCSVButton.d.ts +1 -1
  179. package/lib/components/buttons/DownloadJsonButton.d.ts +1 -1
  180. package/lib/components/buttons/LongActionButton.d.ts +1 -0
  181. package/lib/components/buttons/LongActionButton.js +0 -4
  182. package/lib/components/buttons/UploadButton.d.ts +1 -0
  183. package/lib/components/buttons/UploadButton.js +0 -4
  184. package/lib/components/checkout/StripeCheckout.d.ts +1 -1
  185. package/lib/components/collaboration/LiveEditorCollaborators.d.ts +36 -0
  186. package/lib/components/collaboration/LiveEditorCollaborators.js +88 -53
  187. package/lib/components/collaboration/index.js +0 -4
  188. package/lib/components/confetti/ConfettiSuccess.d.ts +1 -1
  189. package/lib/components/contents/ContentSourceCard.d.ts +8 -0
  190. package/lib/components/contents/ContentSourceCard.js +23 -0
  191. package/lib/components/contents/HomeFolderObjectsBrowser.d.ts +10 -0
  192. package/lib/components/contents/HomeFolderObjectsBrowser.js +148 -0
  193. package/lib/components/contents/index.d.ts +2 -0
  194. package/lib/components/contents/index.js +6 -0
  195. package/lib/components/context/OrganizationSelect.d.ts +1 -1
  196. package/lib/components/display/AvatarSkeleton.d.ts +1 -1
  197. package/lib/components/display/BusyDots.d.ts +1 -1
  198. package/lib/components/display/CenteredSpinner.d.ts +1 -1
  199. package/lib/components/display/CodePreview.d.ts +1 -1
  200. package/lib/components/display/DatalayerBox.d.ts +7 -3
  201. package/lib/components/display/DatalayerBox.js +7 -7
  202. package/lib/components/display/HorizontalCenter.d.ts +1 -1
  203. package/lib/components/display/JupyterDialog.d.ts +1 -0
  204. package/lib/components/display/JupyterDialog.js +1 -7
  205. package/lib/components/display/Markdown.d.ts +1 -0
  206. package/lib/components/display/NavLink.js +3 -2
  207. package/lib/components/display/NotebookSkeleton.d.ts +1 -1
  208. package/lib/components/display/Placeholder.d.ts +1 -1
  209. package/lib/components/display/ToTopBranded.d.ts +1 -1
  210. package/lib/components/echarts/EChartsReact.d.ts +1 -1
  211. package/lib/components/flashes/FlashClosable.d.ts +1 -0
  212. package/lib/components/flashes/FlashClosable.js +0 -4
  213. package/lib/components/flashes/FlashGuest.d.ts +1 -1
  214. package/lib/components/flashes/FlashSurveys.d.ts +1 -1
  215. package/lib/components/flashes/FlashUnauthorized.d.ts +1 -0
  216. package/lib/components/flashes/FlashUnauthorized.js +0 -6
  217. package/lib/components/flashes/surveys/Survey2025_1.d.ts +1 -1
  218. package/lib/components/iam/ExternalTokenSilentLogin.d.ts +1 -1
  219. package/lib/components/index.d.ts +2 -0
  220. package/lib/components/index.js +2 -0
  221. package/lib/components/labels/StatusLabels.d.ts +2 -9
  222. package/lib/components/labels/StatusLabels.js +2 -26
  223. package/lib/components/labels/VisibilityLabel.d.ts +1 -1
  224. package/lib/components/landings/StepBlock.d.ts +1 -1
  225. package/lib/components/mcp/ClientBadge.d.ts +41 -0
  226. package/lib/components/mcp/ClientBadge.js +33 -0
  227. package/lib/components/mcp/McpErrorBlankslate.d.ts +21 -0
  228. package/lib/components/mcp/McpErrorBlankslate.js +17 -0
  229. package/lib/components/mcp/ScopeList.d.ts +28 -0
  230. package/lib/components/mcp/ScopeList.js +14 -0
  231. package/lib/components/mcp/index.d.ts +10 -0
  232. package/lib/components/mcp/index.js +18 -0
  233. package/lib/components/navbar/NavigationVisbilityObserver.d.ts +2 -1
  234. package/lib/components/navbar/SubdomainNavBar.d.ts +10 -5
  235. package/lib/components/navbar/SubdomainNavBar.js +2 -1
  236. package/lib/components/notebooks/JupyterNotebook.d.ts +1 -1
  237. package/lib/components/notebooks/JupyterNotebookToolbar.d.ts +1 -1
  238. package/lib/components/principal/PrincipalAppearance.d.ts +22 -42
  239. package/lib/components/principal/PrincipalAppearance.js +232 -182
  240. package/lib/components/principal/PrincipalAvatar.d.ts +9 -1
  241. package/lib/components/principal/PrincipalAvatar.js +18 -10
  242. package/lib/components/principal/PrincipalBadge.d.ts +1 -1
  243. package/lib/components/principal/PrincipalBanner.d.ts +1 -1
  244. package/lib/components/principal/PrincipalDetailsOverlay.d.ts +38 -1
  245. package/lib/components/principal/PrincipalDetailsOverlay.js +64 -33
  246. package/lib/components/principal/PrincipalHoverCard.d.ts +31 -0
  247. package/lib/components/principal/PrincipalHoverCard.js +52 -0
  248. package/lib/components/principal/PrincipalSwitcherMenu.d.ts +1 -0
  249. package/lib/components/principal/PrincipalSwitcherMenu.js +5 -14
  250. package/lib/components/principal/index.d.ts +2 -1
  251. package/lib/components/principal/index.js +2 -1
  252. package/lib/components/progress/ConsumptionBar.d.ts +1 -0
  253. package/lib/components/progress/ConsumptionBar.js +0 -4
  254. package/lib/components/progress/ProgressRing.d.ts +1 -0
  255. package/lib/components/progress/SpinnerBar.d.ts +1 -1
  256. package/lib/components/progress/Timer.d.ts +1 -0
  257. package/lib/components/progress/Timer.js +0 -4
  258. package/lib/components/screencapture/Screencapture.js +46 -3
  259. package/lib/components/screencapture/ScreencaptureButton.d.ts +1 -1
  260. package/lib/components/sharing/ShareAccessComponent.d.ts +58 -3
  261. package/lib/components/sharing/ShareAccessComponent.js +143 -98
  262. package/lib/components/sharing/SharingEditor.d.ts +21 -0
  263. package/lib/components/sharing/SharingEditor.js +9 -28
  264. package/lib/components/sharing/index.d.ts +1 -0
  265. package/lib/components/sharing/index.js +1 -0
  266. package/lib/components/sharing/sandboxSharing.d.ts +26 -0
  267. package/lib/components/sharing/sandboxSharing.js +41 -0
  268. package/lib/components/spaces/SpaceDetailsOverlay.d.ts +39 -0
  269. package/lib/components/spaces/SpaceDetailsOverlay.js +80 -0
  270. package/lib/components/spaces/SpaceDisplay.d.ts +38 -0
  271. package/lib/components/spaces/SpaceDisplay.js +92 -0
  272. package/lib/components/spaces/index.d.ts +4 -0
  273. package/lib/components/spaces/index.js +7 -0
  274. package/lib/components/spaces/spaceDisplayModel.d.ts +93 -0
  275. package/lib/components/spaces/spaceDisplayModel.js +170 -0
  276. package/lib/components/sparklines/Sparklines.js +3 -4
  277. package/lib/components/sparklines/index.js +0 -4
  278. package/lib/components/storage/ContentsBrowser.d.ts +25 -1
  279. package/lib/components/storage/ContentsBrowser.js +145 -52
  280. package/lib/components/storage/ContentsBrowserMock.d.ts +3 -0
  281. package/lib/components/storage/ContentsBrowserMock.js +75 -0
  282. package/lib/components/storage/ContentsItems.d.ts +2 -1
  283. package/lib/components/storage/ContentsItems.js +0 -4
  284. package/lib/components/storage/ContentsTable.d.ts +50 -0
  285. package/lib/components/storage/ContentsTable.js +134 -0
  286. package/lib/components/storage/HomeFolderDrive.d.ts +71 -0
  287. package/lib/components/storage/HomeFolderDrive.js +248 -0
  288. package/lib/components/storage/index.d.ts +2 -0
  289. package/lib/components/storage/index.js +2 -0
  290. package/lib/components/students/StudentItemStatus.d.ts +1 -1
  291. package/lib/components/students/StudentResultCircle.d.ts +1 -1
  292. package/lib/components/subnav/SubNav.d.ts +5 -5
  293. package/lib/components/subnav/SubNav.js +11 -9
  294. package/lib/components/tables/DataTable.d.ts +1 -1
  295. package/lib/components/text-reveal/TextRevealAnimation.d.ts +2 -2
  296. package/lib/components/text-reveal/useTextRevealAnimationLines.d.ts +1 -1
  297. package/lib/components/time/LiveRelativeTime.d.ts +1 -0
  298. package/lib/components/time/LiveRelativeTime.js +0 -8
  299. package/lib/components/time/index.js +0 -4
  300. package/lib/components/timeline/Timeline.d.ts +1 -1
  301. package/lib/components/timeline/index.js +0 -4
  302. package/lib/components/users/PeerIndicator.d.ts +1 -0
  303. package/lib/components/users/PeerIndicator.js +0 -4
  304. package/lib/config/Configuration.d.ts +15 -17
  305. package/lib/config/Configuration.js +7 -0
  306. package/lib/hooks/cacheConverters.d.ts +0 -7
  307. package/lib/hooks/cacheConverters.js +0 -25
  308. package/lib/hooks/index.d.ts +3 -0
  309. package/lib/hooks/index.js +3 -0
  310. package/lib/hooks/layouts/LayoutBackdrop.d.ts +1 -1
  311. package/lib/hooks/layouts/LayoutScreencapture.d.ts +1 -1
  312. package/lib/hooks/useBackdrop.d.ts +1 -1
  313. package/lib/hooks/useBackdropJupyterLab.d.ts +3 -2
  314. package/lib/hooks/useBackdropJupyterLab.js +0 -4
  315. package/lib/hooks/useBillingEntityStore.js +3 -0
  316. package/lib/hooks/useCache.d.ts +478 -130
  317. package/lib/hooks/useCache.js +1580 -676
  318. package/lib/hooks/useContainsFocus.d.ts +1 -1
  319. package/lib/hooks/useContents.d.ts +334 -0
  320. package/lib/hooks/useContents.js +1033 -0
  321. package/lib/hooks/useFocusTrap.d.ts +4 -4
  322. package/lib/hooks/useFocusTrap.js +1 -1
  323. package/lib/hooks/useMcp.d.ts +315 -0
  324. package/lib/hooks/useMcp.js +891 -0
  325. package/lib/hooks/useMobile.js +0 -5
  326. package/lib/hooks/useNavigate.d.ts +41 -3
  327. package/lib/hooks/useNavigate.js +106 -52
  328. package/lib/hooks/usePrincipalCacheStore.js +3 -0
  329. package/lib/hooks/usePrincipalStore.js +3 -0
  330. package/lib/hooks/useProjectStore.d.ts +3 -3
  331. package/lib/hooks/useProjectStore.js +4 -4
  332. package/lib/hooks/useRef.d.ts +1 -1
  333. package/lib/hooks/useRef.js +3 -0
  334. package/lib/hooks/useScreencapture.d.ts +2 -1
  335. package/lib/hooks/useScreencapture.js +0 -4
  336. package/lib/hooks/useSpaceCacheStore.d.ts +50 -0
  337. package/lib/hooks/useSpaceCacheStore.js +85 -0
  338. package/lib/hooks/useToast.js +0 -4
  339. package/lib/hooks/useVisibilityObserver.d.ts +1 -1
  340. package/lib/index.d.ts +4 -1
  341. package/lib/index.js +3 -1
  342. package/lib/mocks/components/FlashMock.d.ts +1 -1
  343. package/lib/mocks/views/ActionMenuMock.d.ts +1 -1
  344. package/lib/mocks/views/ChartMock.d.ts +1 -1
  345. package/lib/mocks/views/DashboardMock.d.ts +1 -1
  346. package/lib/mocks/views/FormMock.d.ts +1 -1
  347. package/lib/mocks/views/TableMock.d.ts +1 -1
  348. package/lib/mocks/views/WipMock.d.ts +1 -1
  349. package/lib/models/Credits.d.ts +16 -0
  350. package/lib/models/Credits.js +22 -0
  351. package/lib/models/CreditsDTO.d.ts +6 -5
  352. package/lib/models/CreditsDTO.js +7 -5
  353. package/lib/models/McpAuditEvent.d.ts +52 -0
  354. package/lib/models/McpAuditEvent.js +5 -0
  355. package/lib/models/McpBinding.d.ts +57 -0
  356. package/lib/models/McpBinding.js +5 -0
  357. package/lib/models/McpPolicy.d.ts +77 -0
  358. package/lib/models/McpPolicy.js +5 -0
  359. package/lib/models/McpTask.d.ts +94 -0
  360. package/lib/models/McpTask.js +7 -0
  361. package/lib/models/Organization.d.ts +69 -0
  362. package/lib/models/Organization.js +96 -0
  363. package/lib/models/Secret.d.ts +1 -2
  364. package/lib/models/Secret.js +2 -18
  365. package/lib/models/StartedBy.d.ts +91 -0
  366. package/lib/models/StartedBy.js +117 -0
  367. package/lib/models/Team.d.ts +2 -0
  368. package/lib/models/Team.js +2 -0
  369. package/lib/models/User.d.ts +4 -0
  370. package/lib/models/User.js +3 -0
  371. package/lib/models/UserDTO.js +4 -2
  372. package/lib/models/UserSettings.d.ts +13 -0
  373. package/lib/models/UserSettings.js +9 -0
  374. package/lib/models/contents/__fixtures__/solr-codec.json +57 -0
  375. package/lib/models/contents/__fixtures__/v1-contracts.json +194 -0
  376. package/lib/models/contents/fieldCase.d.ts +8 -0
  377. package/lib/models/contents/fieldCase.js +37 -0
  378. package/lib/models/contents/index.d.ts +2 -0
  379. package/lib/models/contents/index.js +6 -0
  380. package/lib/models/contents/permissions.d.ts +16 -0
  381. package/lib/models/contents/permissions.js +34 -0
  382. package/lib/models/index.d.ts +5 -1
  383. package/lib/models/index.js +5 -1
  384. package/lib/navigation/components.js +2 -3
  385. package/lib/routes/publicPaths.js +4 -0
  386. package/lib/state/index.d.ts +1 -0
  387. package/lib/state/index.js +1 -0
  388. package/lib/state/sessionEnd.d.ts +55 -0
  389. package/lib/state/sessionEnd.js +162 -0
  390. package/lib/state/substates/CoreState.d.ts +15 -7
  391. package/lib/state/substates/CoreState.js +21 -17
  392. package/lib/state/substates/IAMState.d.ts +1 -1
  393. package/lib/state/substates/IAMState.js +12 -5
  394. package/lib/state/substates/LayoutState.js +12 -0
  395. package/lib/state/substates/ProfileState.d.ts +1 -0
  396. package/lib/state/substates/ProfileState.js +1 -4
  397. package/lib/state/substates/index.d.ts +0 -1
  398. package/lib/state/substates/index.js +0 -1
  399. package/lib/utils/Jwt.d.ts +26 -0
  400. package/lib/utils/Jwt.js +37 -0
  401. package/lib/utils/Lazy.d.ts +20 -0
  402. package/lib/utils/Lazy.js +32 -6
  403. package/lib/utils/Screencapture.js +3 -0
  404. package/lib/utils/WithSuspense.d.ts +11 -1
  405. package/lib/utils/WithSuspense.js +11 -1
  406. package/lib/views/api-keys/APIKeyEdit.d.ts +1 -1
  407. package/lib/views/api-keys/APIKeyNew.d.ts +1 -1
  408. package/lib/views/api-keys/APIKeys.d.ts +1 -1
  409. package/lib/views/api-keys/APIKeys.js +30 -4
  410. package/lib/views/api-keys/APIKeysStandalone.d.ts +5 -1
  411. package/lib/views/api-keys/APIKeysStandalone.js +2 -2
  412. package/lib/views/datasources/DatasourceDetail.d.ts +12 -5
  413. package/lib/views/datasources/DatasourceDetail.js +80 -110
  414. package/lib/views/datasources/DatasourceNew.d.ts +14 -8
  415. package/lib/views/datasources/DatasourceNew.js +129 -118
  416. package/lib/views/datasources/Datasources.d.ts +39 -7
  417. package/lib/views/datasources/Datasources.js +95 -40
  418. package/lib/views/datasources/DatasourcesMock.d.ts +3 -0
  419. package/lib/views/datasources/DatasourcesMock.js +57 -0
  420. package/lib/views/iam/SignInSimple.d.ts +12 -0
  421. package/lib/views/iam/SignInSimple.js +4 -4
  422. package/lib/views/index.d.ts +1 -0
  423. package/lib/views/index.js +1 -0
  424. package/lib/views/mcp/AdmittedClients.d.ts +44 -0
  425. package/lib/views/mcp/AdmittedClients.js +59 -0
  426. package/lib/views/mcp/AlertDestinations.d.ts +34 -0
  427. package/lib/views/mcp/AlertDestinations.js +75 -0
  428. package/lib/views/mcp/AlertRules.d.ts +32 -0
  429. package/lib/views/mcp/AlertRules.js +245 -0
  430. package/lib/views/mcp/ApprovalQueue.d.ts +66 -0
  431. package/lib/views/mcp/ApprovalQueue.js +95 -0
  432. package/lib/views/mcp/AuditLog.d.ts +42 -0
  433. package/lib/views/mcp/AuditLog.js +144 -0
  434. package/lib/views/mcp/ConnectedAgents.d.ts +34 -0
  435. package/lib/views/mcp/ConnectedAgents.js +135 -0
  436. package/lib/views/mcp/EnterpriseConsole.d.ts +74 -0
  437. package/lib/views/mcp/EnterpriseConsole.js +195 -0
  438. package/lib/views/mcp/IdentityProviders.d.ts +33 -0
  439. package/lib/views/mcp/IdentityProviders.js +299 -0
  440. package/lib/views/mcp/McpDashboard.d.ts +50 -0
  441. package/lib/views/mcp/McpDashboard.js +430 -0
  442. package/lib/views/mcp/McpHome.d.ts +92 -0
  443. package/lib/views/mcp/McpHome.js +153 -0
  444. package/lib/views/mcp/McpObservability.d.ts +79 -0
  445. package/lib/views/mcp/McpObservability.js +236 -0
  446. package/lib/views/mcp/NotebookRuns.d.ts +39 -0
  447. package/lib/views/mcp/NotebookRuns.js +44 -0
  448. package/lib/views/mcp/OrganizationPolicy.d.ts +45 -0
  449. package/lib/views/mcp/OrganizationPolicy.js +108 -0
  450. package/lib/views/mcp/OrganizationUsage.d.ts +69 -0
  451. package/lib/views/mcp/OrganizationUsage.js +113 -0
  452. package/lib/views/mcp/PersonalPolicy.d.ts +54 -0
  453. package/lib/views/mcp/PersonalPolicy.js +126 -0
  454. package/lib/views/mcp/Policies.d.ts +53 -0
  455. package/lib/views/mcp/Policies.js +210 -0
  456. package/lib/views/mcp/PolicyForm.d.ts +83 -0
  457. package/lib/views/mcp/PolicyForm.js +113 -0
  458. package/lib/views/mcp/PolicyHistory.d.ts +58 -0
  459. package/lib/views/mcp/PolicyHistory.js +75 -0
  460. package/lib/views/mcp/RunDetail.d.ts +87 -0
  461. package/lib/views/mcp/RunDetail.js +186 -0
  462. package/lib/views/mcp/ScimProvisioning.d.ts +54 -0
  463. package/lib/views/mcp/ScimProvisioning.js +173 -0
  464. package/lib/views/mcp/ServiceAgents.d.ts +46 -0
  465. package/lib/views/mcp/ServiceAgents.js +194 -0
  466. package/lib/views/mcp/TeamPolicies.d.ts +33 -0
  467. package/lib/views/mcp/TeamPolicies.js +159 -0
  468. package/lib/views/mcp/ToolAccess.d.ts +60 -0
  469. package/lib/views/mcp/ToolAccess.js +101 -0
  470. package/lib/views/mcp/TraceTimeline.d.ts +81 -0
  471. package/lib/views/mcp/TraceTimeline.js +132 -0
  472. package/lib/views/mcp/format.d.ts +25 -0
  473. package/lib/views/mcp/format.js +77 -0
  474. package/lib/views/mcp/index.d.ts +34 -0
  475. package/lib/views/mcp/index.js +42 -0
  476. package/lib/views/mcp/types.d.ts +66 -0
  477. package/lib/views/mcp/types.js +5 -0
  478. package/lib/views/otel/simpleAuthStore.js +3 -0
  479. package/lib/views/secrets/SecretEdit.d.ts +5 -1
  480. package/lib/views/secrets/SecretEdit.js +5 -4
  481. package/lib/views/secrets/SecretNew.d.ts +11 -1
  482. package/lib/views/secrets/SecretNew.js +7 -3
  483. package/lib/views/secrets/Secrets.d.ts +12 -1
  484. package/lib/views/secrets/Secrets.js +2 -2
  485. package/package.json +269 -260
  486. package/scripts/generate-contents-types.py +169 -0
  487. package/scripts/generate-mcp-types.py +233 -0
  488. package/scripts/generate-orchestration-types.py +920 -0
  489. package/lib/api/iam/datasources.d.ts +0 -86
  490. package/lib/api/iam/datasources.js +0 -185
  491. package/lib/components/toolbars/index.d.ts +0 -1
  492. package/lib/models/Datasource.d.ts +0 -181
  493. package/lib/models/Datasource.js +0 -154
  494. package/lib/state/substates/DatasourceState.d.ts +0 -11
  495. package/lib/state/substates/DatasourceState.js +0 -16
  496. /package/lib/{components/toolbars/index.js → api/contents/generated.js} +0 -0
@@ -101,7 +101,7 @@ const SignInInputGlobalStyle = createGlobalStyle `
101
101
  }
102
102
  `;
103
103
  // ── Component ────────────────────────────────────────────────────────
104
- export const SignInSimple = ({ onSignIn, onApiKeySignIn, loginUrl: loginUrlProp, name, title = 'Datalayer OTEL', description = 'Sign in to access the observability dashboard.', icon, leadingIcon = _jsx(TelescopeIcon, { size: 24 }), github = false, google = false, linkedin = false, apiKey = false, signUp = true, socialSignInNavigationTarget, asDoc = false, hideHero = false, calloutTitle, calloutDescription, passwordToggleLabel = 'Sign in with a password', signUpTitle = "Don't have an account?", signUpDescription = 'Create a free Datalayer account with your email address.', signUpLabel = 'Sign up with email', signUpHref = 'https://datalayer.ai/signup', forgotPasswordHref = '/password', forgotPasswordLabel = 'Forgot password?', showForgotPassword = true, socialButtonMarginTop = 3, actionButtonMaxWidth = 320, }) => {
104
+ export const SignInSimple = ({ onSignIn, onApiKeySignIn, loginUrl: loginUrlProp, name, title = 'Datalayer OTEL', description = 'Sign in to access the observability dashboard.', icon, leadingIcon = _jsx(TelescopeIcon, { size: 24 }), github = false, google = false, linkedin = false, apiKey = false, signUp = true, socialSignInNavigationTarget, asDoc = false, fillHeight = true, hideHero = false, calloutTitle, calloutDescription, passwordToggleLabel = 'Sign in with a password', signUpTitle = "Don't have an account?", signUpDescription = 'Create a free Datalayer account with your email address.', signUpLabel = 'Sign up with email', signUpHref = 'https://datalayer.ai/signup', forgotPasswordHref = '/password', forgotPasswordLabel = 'Forgot password?', showForgotPassword = true, socialButtonMarginTop = 3, actionButtonMaxWidth = 320, }) => {
105
105
  const compactDocMode = asDoc && !hideHero;
106
106
  const headingText = name ?? (asDoc && title === 'Datalayer OTEL' ? 'Datalayer Sign In' : title);
107
107
  const headingIcon = icon ?? (asDoc ? _jsx(SignInIcon, { size: 24 }) : leadingIcon);
@@ -316,9 +316,9 @@ export const SignInSimple = ({ onSignIn, onApiKeySignIn, loginUrl: loginUrlProp,
316
316
  const socialDisabled = socialLoading || loading || asDoc;
317
317
  return (_jsxs(Box, { className: "signin-input-theme-scope", sx: {
318
318
  display: 'flex',
319
- alignItems: hideHero || compactDocMode ? 'flex-start' : 'center',
319
+ alignItems: hideHero || compactDocMode || !fillHeight ? 'flex-start' : 'center',
320
320
  justifyContent: 'center',
321
- minHeight: hideHero || compactDocMode ? 'auto' : '100vh',
321
+ minHeight: hideHero || compactDocMode || !fillHeight ? 'auto' : '100vh',
322
322
  bg: hideHero ? 'transparent' : 'canvas.default',
323
323
  color: 'fg.default',
324
324
  py: hideHero ? 0 : compactDocMode ? 2 : 4,
@@ -407,7 +407,7 @@ export const SignInSimple = ({ onSignIn, onApiKeySignIn, loginUrl: loginUrlProp,
407
407
  bg: 'canvas.overlay',
408
408
  color: 'fg.default',
409
409
  boxShadow: 'shadow.large',
410
- }, children: [_jsx(Heading, { id: "signin-api-key-title", sx: { fontSize: 2, mb: 2 }, children: "Enter your API Key" }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "API Key" }), _jsx(Textarea, { block: true, required: true, autoFocus: true, placeholder: "Paste your API key here", value: apiKeyValue, onInput: (e) => setApiKeyValue(e.target.value), ref: apiKeyRef })] }), _jsxs(Box, { sx: {
410
+ }, children: [_jsx(Heading, { id: "signin-api-key-title", sx: { fontSize: 2, mb: 2 }, children: "Enter your API Key" }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "API Key" }), _jsx(Textarea, { block: true, required: true, autoFocus: true, placeholder: "Paste your API key here", value: apiKeyValue, onInput: e => setApiKeyValue(e.currentTarget.value), ref: apiKeyRef })] }), _jsxs(Box, { sx: {
411
411
  mt: 3,
412
412
  display: 'flex',
413
413
  justifyContent: 'flex-end',
@@ -1,3 +1,4 @@
1
1
  export * from './iam';
2
+ export * from './mcp';
2
3
  export * from './profile';
3
4
  export * from './otel';
@@ -3,5 +3,6 @@
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
5
  export * from './iam/index.js';
6
+ export * from './mcp/index.js';
6
7
  export * from './profile/index.js';
7
8
  export * from './otel/index.js';
@@ -0,0 +1,44 @@
1
+ /**
2
+ * What the admitted-clients list actually admits.
3
+ *
4
+ * The field above it is a textarea of client ids, because that is what they
5
+ * are: a client id is a URL somebody pastes, and there is nothing to pick
6
+ * from. What a textarea cannot do is tell whoever typed it whether an entry
7
+ * resolves — and this is the one policy rule whose typo fails silently in
8
+ * the direction that matters. A misspelled entry does not refuse anything
9
+ * loudly; it never matches, and every agent from that vendor is turned away
10
+ * with "your organization does not admit this client", which reads to its
11
+ * owner as a decision somebody made on purpose.
12
+ *
13
+ * So each stored entry is shown with what it names. Three states, and the
14
+ * reason this is a component rather than a line of text is that collapsing
15
+ * any two of them misleads:
16
+ *
17
+ * * a **hostname** admits every client that host publishes. There is no
18
+ * document and none is expected — shown as unresolved it would send
19
+ * somebody chasing a fetch that was never going to happen.
20
+ * * a **document that resolves**, with the name and publishing host.
21
+ * * a **document that does not**, with the reason. The state the whole
22
+ * thing is for.
23
+ *
24
+ * **It describes what is stored, not the draft.** Resolving on every
25
+ * keystroke would make a textarea a source of outbound requests, so this
26
+ * goes stale while somebody edits and says so rather than pretending to
27
+ * describe a line that has not been saved.
28
+ *
29
+ * @module views/mcp/AdmittedClients
30
+ */
31
+ import type { JSX } from 'react';
32
+ import type { McpPolicyScope } from '../../api/iam/mcpPolicy';
33
+ export interface AdmittedClientsProps {
34
+ scope: McpPolicyScope;
35
+ subjectUid: string;
36
+ /**
37
+ * Whether the textarea above differs from what is stored. The entries
38
+ * below describe the *stored* list, and saying so is the difference
39
+ * between a stale panel and a wrong one.
40
+ */
41
+ edited?: boolean;
42
+ }
43
+ export declare const AdmittedClients: ({ scope, subjectUid, edited, }: AdmittedClientsProps) => JSX.Element | null;
44
+ export default AdmittedClients;
@@ -0,0 +1,59 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Label, Link, Spinner, Text } from '@primer/react';
3
+ import { Box } from '@datalayer/primer-addons';
4
+ import { AlertIcon, CheckCircleIcon, GlobeIcon, QuestionIcon, } from '@primer/octicons-react';
5
+ import { useAdmittedClients } from '../../hooks/useMcp.js';
6
+ const Row = ({ client }) => {
7
+ const unreadable = client.kind === 'url' && client.resolved === false;
8
+ const unusable = client.kind === 'unusable';
9
+ const icon = unusable ? (_jsx(QuestionIcon, {})) : unreadable ? (_jsx(AlertIcon, {})) : client.kind === 'hostname' ? (_jsx(GlobeIcon, {})) : (_jsx(CheckCircleIcon, {}));
10
+ const tone = unusable || unreadable ? 'danger.fg' : 'fg.muted';
11
+ return (_jsxs(Box, { sx: {
12
+ display: 'grid',
13
+ gridTemplateColumns: 'auto 1fr',
14
+ gap: 2,
15
+ alignItems: 'start',
16
+ py: 2,
17
+ borderTop: '1px solid',
18
+ borderColor: 'border.muted',
19
+ }, children: [_jsx(Box, { sx: { color: tone, pt: '2px' }, children: icon }), _jsxs(Box, { sx: { display: 'grid', gap: 1, minWidth: 0 }, children: [_jsxs(Box, { sx: {
20
+ display: 'flex',
21
+ gap: 2,
22
+ alignItems: 'center',
23
+ flexWrap: 'wrap',
24
+ }, children: [client.clientName && (_jsx(Text, { sx: { fontWeight: 'semibold' }, children: client.clientName })), client.kind === 'hostname' && (_jsx(Label, { variant: "accent", size: "small", children: "Whole host" })), client.localhostOnly && (
25
+ // Worth a label of its own: every redirect goes to the reader's
26
+ // own machine, and a document cannot prove which local program
27
+ // is listening on the port.
28
+ _jsx(Label, { variant: "attention", size: "small", children: "Redirects to localhost" })), unreadable && (_jsx(Label, { variant: "danger", size: "small", children: "Cannot be read" })), unusable && (_jsx(Label, { variant: "danger", size: "small", children: "Matches nothing" }))] }), _jsx(Text, { sx: {
29
+ fontSize: 0,
30
+ fontFamily: 'mono',
31
+ color: 'fg.muted',
32
+ overflowWrap: 'anywhere',
33
+ }, children: client.entry }), client.detail && (_jsx(Text, { sx: { fontSize: 0, color: tone }, children: client.detail })), client.clientUri && (_jsx(Link, { href: client.clientUri, target: "_blank", rel: "noreferrer noopener", sx: { fontSize: 0 }, children: client.clientHostname || client.clientUri }))] })] }));
34
+ };
35
+ export const AdmittedClients = ({ scope, subjectUid, edited = false, }) => {
36
+ const described = useAdmittedClients(scope, subjectUid);
37
+ if (described.isPending && !described.data) {
38
+ return (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 3 }, children: _jsx(Spinner, { size: "small" }) }));
39
+ }
40
+ // An error here is not worth a blankslate: the field above still works and
41
+ // the policy is unaffected. Saying nothing would be worse than saying it
42
+ // could not be checked, so it says that and stays out of the way.
43
+ if (described.isError) {
44
+ return (_jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', m: 0 }, children: "The admitted clients could not be described just now. The list above is still what is enforced." }));
45
+ }
46
+ const answer = described.data;
47
+ if (!answer) {
48
+ return null;
49
+ }
50
+ if (!answer.allowlisted) {
51
+ // Said, not rendered as an empty list. An empty allowlist is not an
52
+ // allowlist, and "no clients admitted" would be the opposite of what
53
+ // the gateway does with a blank one.
54
+ return (_jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', m: 0 }, children: answer.detail ??
55
+ 'This layer names no client allowlist, so every client is admitted by it.' }));
56
+ }
57
+ return (_jsxs(Box, { sx: { display: 'grid', gap: 1 }, children: [edited && (_jsxs(Text, { as: "p", sx: { fontSize: 0, color: 'attention.fg', m: 0 }, children: ["Describing the ", _jsx("strong", { children: "saved" }), " list. Save to check what you have just typed."] })), answer.clients.map(client => (_jsx(Row, { client: client }, client.entry)))] }));
58
+ };
59
+ export default AdmittedClients;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Where a fired alert goes, besides the notice in the app.
3
+ *
4
+ * These sit beside the rules because they are half of the same decision: a
5
+ * rule with nowhere to go is a row somebody has to remember to look at, and
6
+ * a destination with no rules is nothing at all.
7
+ *
8
+ * They live on the organization rather than on each rule, and that is worth
9
+ * knowing while editing them: a URL repeated on twenty rules is nineteen
10
+ * places to forget when it rotates, and the rules would disagree about where
11
+ * the organization is reachable.
12
+ *
13
+ * **Slack has its own field.** Not fussiness — the transport is the same and
14
+ * the body is not. Slack renders a generic JSON POST as one grey line of
15
+ * text; given Block Kit it renders a coloured attachment with the reading,
16
+ * the severity and the scope as separate fields. IAM refuses a
17
+ * non-Slack URL here, because anything else sent Block Kit half-works and
18
+ * looks configured.
19
+ *
20
+ * Only what changed is sent. IAM merges these settings, and this form does
21
+ * not show retention or SIEM forwarding — sending them empty would clear
22
+ * decisions made on another page by somebody else.
23
+ *
24
+ * @module views/mcp/AlertDestinations
25
+ */
26
+ import type { JSX } from 'react';
27
+ import type { McpErrorStateFn } from './types';
28
+ export interface AlertDestinationsProps {
29
+ errorState: McpErrorStateFn;
30
+ orgUid: string;
31
+ readOnly?: boolean;
32
+ }
33
+ export declare const AlertDestinations: ({ errorState, orgUid, readOnly, }: AlertDestinationsProps) => JSX.Element;
34
+ export default AlertDestinations;
@@ -0,0 +1,75 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useState } from 'react';
3
+ import { Button, Flash, FormControl, Heading, Spinner, Text, TextInput, } from '@primer/react';
4
+ import { Box } from '@datalayer/primer-addons';
5
+ import { McpErrorBlankslate } from '../../components/mcp/index.js';
6
+ import { useAuditSettings, useSetAuditSettings } from '../../hooks/useMcp.js';
7
+ import { useToast } from '../../hooks/index.js';
8
+ import { AuditSettingInvalid } from '../../api/iam/mcpAuditSettings.js';
9
+ const EMPTY = {
10
+ alertEmails: '',
11
+ alertWebhookUrl: '',
12
+ alertSlackWebhookUrl: '',
13
+ };
14
+ export const AlertDestinations = ({ errorState, orgUid, readOnly = false, }) => {
15
+ const { enqueueToast } = useToast();
16
+ const settings = useAuditSettings(orgUid);
17
+ const save = useSetAuditSettings(orgUid);
18
+ const [draft, setDraft] = useState(EMPTY);
19
+ const [refusal, setRefusal] = useState('');
20
+ const stored = useMemo(() => ({
21
+ alertEmails: settings.data?.alertEmails ?? '',
22
+ alertWebhookUrl: settings.data?.alertWebhookUrl ?? '',
23
+ alertSlackWebhookUrl: settings.data?.alertSlackWebhookUrl ?? '',
24
+ }), [settings.data]);
25
+ useEffect(() => setDraft(stored), [stored]);
26
+ const changed = useMemo(() => Object.keys(EMPTY).some(key => draft[key] !== stored[key]), [draft, stored]);
27
+ const set = (key, value) => setDraft(current => ({ ...current, [key]: value }));
28
+ const apply = () => {
29
+ setRefusal('');
30
+ // Only the fields this form owns, and only those that changed. Sending
31
+ // an untouched retention as empty would clear a decision made on
32
+ // another page by somebody else.
33
+ const changes = {};
34
+ for (const key of Object.keys(EMPTY)) {
35
+ if (draft[key] !== stored[key]) {
36
+ changes[key] = draft[key].trim();
37
+ }
38
+ }
39
+ save.mutate({ settings: changes, expectedVersion: settings.data?.version }, {
40
+ onSuccess: () => {
41
+ enqueueToast('Saved. The next firing goes there.', {
42
+ variant: 'success',
43
+ });
44
+ },
45
+ onError: error => {
46
+ if (error instanceof AuditSettingInvalid) {
47
+ // IAM's own words. "That is not a Slack incoming webhook" is the
48
+ // whole answer, and a generic failure would send somebody
49
+ // looking for a problem that is already named.
50
+ setRefusal(error.message);
51
+ return;
52
+ }
53
+ enqueueToast(`Could not save: ${error.message}`, {
54
+ variant: 'error',
55
+ });
56
+ },
57
+ });
58
+ };
59
+ if (settings.isError) {
60
+ return (_jsx(McpErrorBlankslate, { state: errorState(settings.error, 'Alert destinations'), onRetry: () => settings.refetch() }));
61
+ }
62
+ if (settings.isPending && settings.data === undefined) {
63
+ return (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 4 }, children: _jsx(Spinner, {}) }));
64
+ }
65
+ return (_jsxs(Box, { sx: {
66
+ display: 'grid',
67
+ gap: 3,
68
+ maxWidth: '42rem',
69
+ p: 3,
70
+ border: '1px solid',
71
+ borderColor: 'border.default',
72
+ borderRadius: 2,
73
+ }, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h3", sx: { fontSize: 2, mb: 1 }, children: "Where alerts go" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "Set once for the organization, not per rule \u2014 a URL repeated on twenty rules is nineteen places to forget when it rotates. Every firing also appears in the app, and that copy is sent first so it is not lost when one of these is down." })] }), refusal && (_jsx(Flash, { variant: "danger", children: _jsx(Text, { sx: { fontSize: 1 }, children: refusal }) })), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Email" }), _jsx(TextInput, { block: true, disabled: readOnly, value: draft.alertEmails, onChange: event => set('alertEmails', event.target.value), placeholder: "ops@example.co, oncall@example.co" }), _jsx(FormControl.Caption, { children: "Comma-separated, up to twenty. An alert list is the people who want to know, not a mailing list \u2014 a firing that emails two hundred people is a firing that gets the rule switched off." })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Slack" }), _jsx(TextInput, { block: true, disabled: readOnly, value: draft.alertSlackWebhookUrl, onChange: event => set('alertSlackWebhookUrl', event.target.value), placeholder: "https://hooks.slack.com/services/\u2026" }), _jsx(FormControl.Caption, { children: "A Slack incoming webhook, and only Slack\u2019s \u2014 anything else belongs in the field below. Through this one Slack gets a coloured attachment with the reading, the severity and the scope as separate fields; through the generic webhook it shows one grey line." })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Webhook" }), _jsx(TextInput, { block: true, disabled: readOnly, value: draft.alertWebhookUrl, onChange: event => set('alertWebhookUrl', event.target.value), placeholder: "https://events.pagerduty.com/\u2026" }), _jsxs(FormControl.Caption, { children: ["Anything that takes a JSON POST: PagerDuty, a chat relay, your own endpoint. ", _jsx("strong", { children: "https only" }), " \u2014 an alert names your organization and what its agents did. It carries no credential."] })] }), !readOnly && (_jsxs(Box, { sx: { display: 'flex', gap: 2 }, children: [_jsx(Button, { variant: "primary", onClick: apply, disabled: !changed || save.isPending, children: "Save destinations" }), changed && (_jsx(Button, { variant: "invisible", onClick: () => setDraft(stored), children: "Discard changes" }))] })), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: ["Each copy is attempted on its own: if the webhook is down you still get the email. A copy that fails is recorded and", ' ', _jsx("strong", { children: "not retried" }), " \u2014 retrying a notice against an endpoint that is down turns its outage into a loop against it, and the alert is already in the app."] })] }));
74
+ };
75
+ export default AlertDestinations;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * What this organization asked to be told about.
3
+ *
4
+ * A rule is a condition over a number the gateway already counts, checked
5
+ * once a minute, firing at most once per condition per window. The
6
+ * evaluator has been able to evaluate these since milestone 1; until this
7
+ * page they could only be written with `curl`.
8
+ *
9
+ * The form is built from the vocabulary the evaluator publishes, and that
10
+ * is the point rather than a convenience. A rule it cannot evaluate is
11
+ * refused at the write — and a rule that never fires because of a typo is
12
+ * indistinguishable from a condition that never happened, which is what
13
+ * somebody will believe. A dropdown cannot produce one.
14
+ *
15
+ * The same reasoning runs one level deeper. A condition the evaluator knows
16
+ * but has **no reader** for is stored, evaluated every minute, counted
17
+ * `unreadable`, and never fires — worse than a typo, because it looks
18
+ * configured. Those are shown as not yet measurable and cannot be chosen.
19
+ *
20
+ * @module views/mcp/AlertRules
21
+ */
22
+ import type { JSX } from 'react';
23
+ import type { McpErrorStateFn } from './types';
24
+ export interface AlertRulesProps {
25
+ errorState: McpErrorStateFn;
26
+ orgUid: string;
27
+ /** Read-only for anybody who is not an owner. */
28
+ readOnly?: boolean;
29
+ showTitle?: boolean;
30
+ }
31
+ export declare const AlertRules: ({ errorState, orgUid, readOnly, showTitle, }: AlertRulesProps) => JSX.Element;
32
+ export default AlertRules;
@@ -0,0 +1,245 @@
1
+ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useMemo, useRef, useState } from 'react';
3
+ import { ActionList, ActionMenu, Button, Flash, FormControl, Heading, Label, Select, Spinner, Text, TextInput, ToggleSwitch, } from '@primer/react';
4
+ import { Blankslate, DataTable, Dialog, Table, } from '@primer/react/experimental';
5
+ import { Box } from '@datalayer/primer-addons';
6
+ import { BellIcon, KebabHorizontalIcon } from '@primer/octicons-react';
7
+ import { McpErrorBlankslate } from '../../components/mcp/index.js';
8
+ import { AlertDestinations } from './AlertDestinations.js';
9
+ import { useAlertRules, useTestAlertRule, useCreateAlertRule, useDeleteAlertRule, useUpdateAlertRule, } from '../../hooks/useMcp.js';
10
+ import { useToast } from '../../hooks/index.js';
11
+ import { ALERT_CONDITIONS, ALERT_OPERATORS, ALERT_SEVERITIES, AlertRuleInvalid, } from '../../api/iam/mcpAlertRules.js';
12
+ /** The windows worth offering, in seconds. */
13
+ const WINDOWS = [
14
+ { seconds: 300, label: '5 minutes' },
15
+ { seconds: 900, label: '15 minutes' },
16
+ { seconds: 3600, label: 'an hour' },
17
+ { seconds: 21600, label: '6 hours' },
18
+ { seconds: 86400, label: 'a day' },
19
+ ];
20
+ const MEASURABLE = ALERT_CONDITIONS.filter(condition => condition.measurable);
21
+ const BLANK = {
22
+ condition: MEASURABLE[0]?.name ?? 'tasks.open',
23
+ operator: 'gt',
24
+ threshold: 1,
25
+ severity: 'warning',
26
+ windowSeconds: 3600,
27
+ scopeKind: 'organization',
28
+ scopeUid: '',
29
+ enabled: true,
30
+ };
31
+ const labelOf = (condition) => ALERT_CONDITIONS.find(entry => entry.name === condition)?.label ?? condition;
32
+ const operatorOf = (operator) => ALERT_OPERATORS.find(entry => entry.name === operator)?.label ?? operator;
33
+ const windowOf = (seconds) => WINDOWS.find(entry => entry.seconds === seconds)?.label ?? `${seconds}s`;
34
+ export const AlertRules = ({ errorState, orgUid, readOnly = false, showTitle = true, }) => {
35
+ const { enqueueToast } = useToast();
36
+ const rules = useAlertRules(orgUid);
37
+ const create = useCreateAlertRule(orgUid);
38
+ const update = useUpdateAlertRule(orgUid);
39
+ const remove = useDeleteAlertRule(orgUid);
40
+ const test = useTestAlertRule();
41
+ const [editing, setEditing] = useState(null);
42
+ const [creating, setCreating] = useState(false);
43
+ const [draft, setDraft] = useState(BLANK);
44
+ const [refusal, setRefusal] = useState('');
45
+ const [trial, setTrial] = useState(null);
46
+ const [removing, setRemoving] = useState(null);
47
+ // Primer 37 types Dialog's focus refs with React 18's non-nullable
48
+ // `RefObject<HTMLElement>`. React 19's `useRef(null)` is nullable, and this
49
+ // ref is only handed to Dialog, so narrow it once here.
50
+ const returnFocusRef = useRef(null);
51
+ const rows = useMemo(() => (rules.data ?? []).map(rule => ({ ...rule, id: rule.uid })), [rules.data]);
52
+ const openCreate = () => {
53
+ setDraft(BLANK);
54
+ setRefusal('');
55
+ setTrial(null);
56
+ setCreating(true);
57
+ };
58
+ const openEdit = (rule) => {
59
+ const { uid, orgUid: _org, version: _version, ...rest } = rule;
60
+ setDraft(rest);
61
+ setRefusal('');
62
+ setTrial(null);
63
+ setEditing(rule);
64
+ };
65
+ const close = () => {
66
+ setCreating(false);
67
+ setEditing(null);
68
+ setRefusal('');
69
+ };
70
+ const onError = (error) => {
71
+ if (error instanceof AlertRuleInvalid) {
72
+ // The evaluator's own words, beside the form rather than in a toast:
73
+ // it names what is wrong, and the person can still fix it.
74
+ setRefusal(error.message);
75
+ return;
76
+ }
77
+ enqueueToast(`Could not save the rule: ${error.message}`, {
78
+ variant: 'error',
79
+ });
80
+ };
81
+ const apply = () => {
82
+ setRefusal('');
83
+ if (draft.scopeKind !== 'organization' && !draft.scopeUid.trim()) {
84
+ setRefusal(`A ${draft.scopeKind} rule needs the ${draft.scopeKind} it is about. ` +
85
+ 'Without one it would be measured over the whole organization ' +
86
+ 'under a name saying otherwise.');
87
+ return;
88
+ }
89
+ if (!Number.isFinite(draft.threshold)) {
90
+ setRefusal('The threshold must be a number.');
91
+ return;
92
+ }
93
+ if (editing) {
94
+ update.mutate({ uid: editing.uid, rule: draft }, {
95
+ onSuccess: () => {
96
+ close();
97
+ enqueueToast('Rule saved.', { variant: 'success' });
98
+ },
99
+ onError,
100
+ });
101
+ return;
102
+ }
103
+ create.mutate(draft, {
104
+ onSuccess: () => {
105
+ close();
106
+ enqueueToast('Rule created. It is evaluated on the next tick.', {
107
+ variant: 'success',
108
+ });
109
+ },
110
+ onError,
111
+ });
112
+ };
113
+ /** Switching a rule off leaves it here; it stops being evaluated. */
114
+ const toggle = (rule, enabled) => {
115
+ const { uid, orgUid: _org, version: _version, ...rest } = rule;
116
+ update.mutate({ uid, rule: { ...rest, enabled } }, {
117
+ onError: error => enqueueToast(`Could not change the rule: ${error.message}`, {
118
+ variant: 'error',
119
+ }),
120
+ });
121
+ };
122
+ const confirmRemove = () => {
123
+ const rule = removing;
124
+ if (!rule) {
125
+ return;
126
+ }
127
+ remove.mutate(rule.uid, {
128
+ onSuccess: () => {
129
+ setRemoving(null);
130
+ enqueueToast('Rule removed. What it watched is unwatched.', {
131
+ variant: 'success',
132
+ });
133
+ },
134
+ onError: error => {
135
+ setRemoving(null);
136
+ enqueueToast(`Could not remove: ${error.message}`, {
137
+ variant: 'error',
138
+ });
139
+ },
140
+ });
141
+ };
142
+ const set = (key, value) => {
143
+ // A reading belongs to the rule that produced it. Left on screen after
144
+ // the condition changes, it would be somebody reading last question's
145
+ // answer as this question's.
146
+ setTrial(null);
147
+ setDraft(current => ({ ...current, [key]: value }));
148
+ };
149
+ const tryIt = () => {
150
+ setRefusal('');
151
+ test.mutate({
152
+ condition: draft.condition,
153
+ operator: draft.operator,
154
+ threshold: draft.threshold,
155
+ windowSeconds: draft.windowSeconds,
156
+ scopeKind: draft.scopeKind,
157
+ scopeUid: draft.scopeUid,
158
+ }, {
159
+ onSuccess: setTrial,
160
+ onError: error => setRefusal(error.message),
161
+ });
162
+ };
163
+ const columns = [
164
+ {
165
+ header: 'Tell me when',
166
+ id: 'condition',
167
+ rowHeader: true,
168
+ width: 'growCollapse',
169
+ renderCell: row => (_jsxs(Box, { sx: { display: 'grid' }, children: [_jsxs(Text, { sx: { fontSize: 1 }, children: [labelOf(row.condition), " ", operatorOf(row.operator), " ", row.threshold] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["over ", windowOf(row.windowSeconds), row.scopeKind !== 'organization' && ` · this ${row.scopeKind}`] })] })),
170
+ },
171
+ {
172
+ header: 'Severity',
173
+ id: 'severity',
174
+ width: '110px',
175
+ renderCell: row => (_jsx(Label, { size: "small", variant: row.severity === 'critical'
176
+ ? 'danger'
177
+ : row.severity === 'warning'
178
+ ? 'attention'
179
+ : 'secondary', children: row.severity })),
180
+ },
181
+ {
182
+ header: 'On',
183
+ id: 'enabled',
184
+ width: '90px',
185
+ renderCell: row => (
186
+ // The label is drawn and hidden rather than passed as `aria-label`:
187
+ // Primer's switch names itself from an element, and a row of
188
+ // unlabelled switches is a row a screen reader reads as "on, on,
189
+ // off" with nothing said about what.
190
+ _jsxs(_Fragment, { children: [_jsx(Text, { id: `alert-toggle-${row.uid}`, sx: { display: 'none' }, children: `Evaluate ${labelOf(row.condition)}` }), _jsx(ToggleSwitch, { size: "small", checked: row.enabled, disabled: readOnly || update.isPending, "aria-labelledby": `alert-toggle-${row.uid}`, onClick: () => toggle(row, !row.enabled) })] })),
191
+ },
192
+ {
193
+ header: '',
194
+ id: 'actions',
195
+ width: '48px',
196
+ align: 'end',
197
+ renderCell: row => readOnly ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: "\u2014" })) : (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Button, { variant: "invisible", size: "small", "aria-label": `Actions for ${labelOf(row.condition)}`, icon: KebabHorizontalIcon }) }), _jsx(ActionMenu.Overlay, { align: "end", children: _jsxs(ActionList, { children: [_jsx(ActionList.Item, { onSelect: () => openEdit(row), children: "Edit" }), _jsx(ActionList.Item, { variant: "danger", onSelect: () => setRemoving(row), children: "Remove" })] }) })] })),
198
+ },
199
+ ];
200
+ if (rules.isError) {
201
+ return (_jsx(McpErrorBlankslate, { state: errorState(rules.error, 'Alert rules'), onRetry: () => rules.refetch() }));
202
+ }
203
+ const chosen = ALERT_CONDITIONS.find(entry => entry.name === draft.condition);
204
+ return (_jsxs(Box, { sx: { display: 'grid', gap: 3, minWidth: 0 }, children: [showTitle && (_jsxs(Box, { sx: {
205
+ display: 'flex',
206
+ alignItems: 'start',
207
+ justifyContent: 'space-between',
208
+ gap: 3,
209
+ }, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Alerts" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "What this organization asked to be told about. Each rule is checked once a minute and fires at most once per window." })] }), !readOnly && (_jsx(Button, { variant: "primary", onClick: openCreate, children: "New rule" }))] })), rules.isPending && !rules.data ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 5 }, children: _jsx(Spinner, {}) })) : rows.length > 0 ? (_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h3", id: "alert-rules", children: "Rules" }), _jsx(Table.Subtitle, { as: "p", id: "alert-rules-subtitle", children: "A rule switched off stays here and stops being evaluated." }), _jsx(DataTable, { "aria-labelledby": "alert-rules", "aria-describedby": "alert-rules-subtitle", data: rows, columns: columns })] })) : (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(BellIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "Nothing is watched" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "Runs are recorded either way. A rule is what turns a number somebody would have to go and look at into something that reaches you." }) }), !readOnly && (_jsx(Button, { size: "small", onClick: openCreate, children: "New rule" }))] })), _jsx(AlertDestinations, { errorState: errorState, orgUid: orgUid, readOnly: readOnly }), (creating || editing) && (_jsx(Dialog, { title: editing ? 'Edit rule' : 'New alert rule', onClose: close, returnFocusRef: returnFocusRef, footerButtons: [
210
+ { buttonType: 'default', content: 'Cancel', onClick: close },
211
+ {
212
+ buttonType: 'default',
213
+ content: test.isPending ? 'Testing…' : 'Test',
214
+ onClick: tryIt,
215
+ disabled: test.isPending || !draft.condition,
216
+ },
217
+ {
218
+ buttonType: 'primary',
219
+ content: editing ? 'Save' : 'Create',
220
+ onClick: apply,
221
+ disabled: create.isPending || update.isPending,
222
+ },
223
+ ], children: _jsxs(Box, { sx: { display: 'grid', gap: 3 }, children: [refusal && (_jsx(Flash, { variant: "danger", children: _jsx(Text, { sx: { fontSize: 1 }, children: refusal }) })), trial && (_jsxs(Flash, { variant: trial.readable ? 'default' : 'warning', children: [_jsx(Text, { sx: { fontSize: 1 }, children: trial.readable
224
+ ? `Right now it reads ${trial.value}, so this rule ${trial.wouldFire ? 'would fire' : 'would not fire'}.`
225
+ : 'This cannot be read at the moment, so the rule would ' +
226
+ 'not fire — and a rule that never fires looks exactly ' +
227
+ 'like a condition that never happens.' }), trial.detail && (_jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', mt: 1, mb: 0 }, children: trial.detail }))] })), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Tell me when" }), _jsx(Select, { value: draft.condition, onChange: event => set('condition', event.target.value), children: ALERT_CONDITIONS.map(condition => (_jsxs(Select.Option, { value: condition.name,
228
+ // A condition nothing reads would be stored, evaluated
229
+ // every minute and never fire. Offering it as though it
230
+ // worked is the silence rules exist to break.
231
+ disabled: !condition.measurable, children: [condition.label, condition.measurable ? '' : ' — not measurable yet'] }, condition.name))) }), chosen && (_jsx(FormControl.Caption, { children: chosen.help }))] }), _jsxs(Box, { sx: { display: 'grid', gap: 2, gridTemplateColumns: '1fr 1fr' }, children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Comparison" }), _jsx(Select, { value: draft.operator, onChange: event => set('operator', event.target.value), children: ALERT_OPERATORS.map(operator => (_jsx(Select.Option, { value: operator.name, children: operator.label }, operator.name))) })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Threshold" }), _jsx(TextInput, { block: true, type: "number", value: String(draft.threshold), onChange: event => set('threshold', Number(event.target.value)) })] })] }), _jsxs(Box, { sx: { display: 'grid', gap: 2, gridTemplateColumns: '1fr 1fr' }, children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Over" }), _jsx(Select, { value: String(draft.windowSeconds), onChange: event => set('windowSeconds', Number(event.target.value)), children: WINDOWS.map(window => (_jsx(Select.Option, { value: String(window.seconds), children: window.label }, window.seconds))) }), _jsx(FormControl.Caption, { children: "It fires once per window, not once per check." })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Severity" }), _jsx(Select, { value: draft.severity, onChange: event => set('severity', event.target.value), children: ALERT_SEVERITIES.map(severity => (_jsx(Select.Option, { value: severity, children: severity }, severity))) }), _jsx(FormControl.Caption, { children: "Sets the colour in Slack and the wording of the notice." })] })] }), _jsxs(Box, { sx: { display: 'grid', gap: 2, gridTemplateColumns: '1fr 1fr' }, children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Measured over" }), _jsxs(Select, { value: draft.scopeKind, onChange: event => set('scopeKind', event.target.value), children: [_jsx(Select.Option, { value: "organization", children: "The whole organization" }), _jsx(Select.Option, { value: "team", children: "One team" }), _jsx(Select.Option, { value: "user", children: "One person" }), _jsx(Select.Option, { value: "agent", children: "One agent" })] })] }), draft.scopeKind !== 'organization' && (_jsxs(FormControl, { required: true, children: [_jsxs(FormControl.Label, { children: ["Which ", draft.scopeKind] }), _jsx(TextInput, { block: true, value: draft.scopeUid, onChange: event => set('scopeUid', event.target.value), placeholder: "uid" }), _jsx(FormControl.Caption, { children: "Without one the rule would be measured over the whole organization under a name saying otherwise." })] }))] })] }) })), removing && (_jsx(Dialog, { title: "Remove this rule?", onClose: () => setRemoving(null), returnFocusRef: returnFocusRef, footerButtons: [
232
+ {
233
+ buttonType: 'default',
234
+ content: 'Keep it',
235
+ onClick: () => setRemoving(null),
236
+ },
237
+ {
238
+ buttonType: 'danger',
239
+ content: 'Remove',
240
+ onClick: confirmRemove,
241
+ disabled: remove.isPending,
242
+ },
243
+ ], children: _jsx(Text, { sx: { fontSize: 1 }, children: "What it watched is unwatched from the next check, and nothing will say so again. If you only want it quiet for now, switch it off instead \u2014 it stays in the list." }) }))] }));
244
+ };
245
+ export default AlertRules;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * The calls an agent cannot make without somebody saying yes.
3
+ *
4
+ * A source set to `explicit` stops every call it does not already hold an
5
+ * approval for. The call waits as `pending-approval`, and the person who
6
+ * owns the source is the only one who can move it — which means that until
7
+ * this page existed, "approval required" was a setting that stopped agents
8
+ * and gave nobody a way to unstop them.
9
+ *
10
+ * **An approval is bound to the arguments it was asked about.** Contents
11
+ * hashes them and re-checks the hash when the call runs, so approving is
12
+ * approving *those* arguments and not that tool in general. That is why the
13
+ * redacted arguments are drawn in full rather than summarised: a reader who
14
+ * cannot see what they are allowing is a reader who approves everything.
15
+ *
16
+ * **A pending approval that has expired is not decidable**, and the buttons
17
+ * go rather than fail. Contents expires them lazily — the record still says
18
+ * `pending` until something looks at it — so a row can arrive here already
19
+ * over, and offering an Approve button on it would be offering a decision
20
+ * the server will refuse.
21
+ *
22
+ * @module views/mcp/ApprovalQueue
23
+ */
24
+ import type { JSX } from 'react';
25
+ import type { McpApproval } from '../../api/contents/generated';
26
+ import { type McpErrorStateFn } from './types';
27
+ /** How each state of an approval is drawn. */
28
+ export declare const APPROVAL_LOOK: Record<McpApproval['status'], {
29
+ label: string;
30
+ variant: 'attention' | 'success' | 'danger' | 'secondary';
31
+ }>;
32
+ /**
33
+ * Whether this approval can still be decided.
34
+ *
35
+ * Two conditions, and the second is the one that matters: the record says
36
+ * `pending`, *and* its deadline has not passed. Contents expires an approval
37
+ * when something next reads it rather than on a timer, so a row fetched a
38
+ * minute ago can be `pending` and over. Trusting the status alone would draw
39
+ * buttons whose only outcome is an error.
40
+ *
41
+ * An unparseable deadline is treated as passed. That is the safe direction:
42
+ * the worst case is somebody has to ask the agent to try again, where the
43
+ * other way round is a decision taken on a record nobody can date.
44
+ */
45
+ export declare const isDecidable: (approval: Pick<McpApproval, "status" | "expiresAt">, now?: number) => boolean;
46
+ /**
47
+ * What a row says about its own deadline.
48
+ *
49
+ * A pending approval that has run out is drawn as expired even though the
50
+ * record still says pending — the reader's question is "can I still act on
51
+ * this", and the record's answer to that is stale by construction.
52
+ */
53
+ export declare const approvalLook: (approval: Pick<McpApproval, "status" | "expiresAt">, now?: number) => {
54
+ label: string;
55
+ variant: "attention" | "success" | "danger" | "secondary";
56
+ };
57
+ /** The states this page can be filtered to. `pending` is what it opens on. */
58
+ export declare const APPROVAL_FILTERS: McpApproval['status'][];
59
+ export interface ApprovalQueueProps {
60
+ /** The application's words for a failed request. */
61
+ errorState: McpErrorStateFn;
62
+ /** Only the approvals of one source, when the caller has one in mind. */
63
+ sourceUid?: string;
64
+ }
65
+ export declare const ApprovalQueue: ({ errorState, sourceUid, }: ApprovalQueueProps) => JSX.Element;
66
+ export default ApprovalQueue;