@datalayer/core 1.1.60 → 1.1.66

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 (364) hide show
  1. package/README.md +2 -2
  2. package/lib/api/DatalayerApi.d.ts +42 -1
  3. package/lib/api/DatalayerApi.js +90 -3
  4. package/lib/api/constants.d.ts +18 -0
  5. package/lib/api/constants.js +18 -0
  6. package/lib/api/contents/attachments.d.ts +9 -0
  7. package/lib/api/contents/attachments.js +43 -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 +15 -0
  17. package/lib/api/contents/datasets.js +45 -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 +53 -0
  32. package/lib/api/contents/sandboxUid.js +78 -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/iam/connectedAgents.d.ts +39 -0
  40. package/lib/api/iam/connectedAgents.js +52 -0
  41. package/lib/api/iam/index.d.ts +2 -1
  42. package/lib/api/iam/index.js +2 -1
  43. package/lib/api/iam/mcpAlertRules.d.ts +51 -0
  44. package/lib/api/iam/mcpAlertRules.js +198 -0
  45. package/lib/api/iam/mcpAuditSettings.d.ts +46 -0
  46. package/lib/api/iam/mcpAuditSettings.js +120 -0
  47. package/lib/api/iam/mcpPolicy.d.ts +80 -0
  48. package/lib/api/iam/mcpPolicy.js +132 -0
  49. package/lib/api/iam/organizationTeams.d.ts +13 -0
  50. package/lib/api/iam/organizationTeams.js +43 -0
  51. package/lib/api/iam/serviceAgents.d.ts +68 -0
  52. package/lib/api/iam/serviceAgents.js +119 -0
  53. package/lib/api/index.d.ts +4 -1
  54. package/lib/api/index.js +3 -1
  55. package/lib/api/mcp/activity.d.ts +37 -0
  56. package/lib/api/mcp/activity.js +26 -0
  57. package/lib/api/mcp/alerts.d.ts +25 -0
  58. package/lib/api/mcp/alerts.js +51 -0
  59. package/lib/api/mcp/audit.d.ts +29 -0
  60. package/lib/api/mcp/audit.js +55 -0
  61. package/lib/api/mcp/bindings.d.ts +18 -0
  62. package/lib/api/mcp/bindings.js +42 -0
  63. package/lib/api/mcp/forwarding.d.ts +25 -0
  64. package/lib/api/mcp/forwarding.js +46 -0
  65. package/lib/api/mcp/gateway.d.ts +16 -0
  66. package/lib/api/mcp/gateway.js +70 -0
  67. package/lib/api/mcp/generated.d.ts +22 -0
  68. package/lib/api/mcp/generated.js +213 -0
  69. package/lib/api/mcp/index.d.ts +17 -0
  70. package/lib/api/mcp/index.js +25 -0
  71. package/lib/api/mcp/observability.d.ts +125 -0
  72. package/lib/api/mcp/observability.js +254 -0
  73. package/lib/api/mcp/operations.d.ts +83 -0
  74. package/lib/api/mcp/operations.js +50 -0
  75. package/lib/api/mcp/organizations.d.ts +102 -0
  76. package/lib/api/mcp/organizations.js +46 -0
  77. package/lib/api/mcp/policy.d.ts +9 -0
  78. package/lib/api/mcp/policy.js +23 -0
  79. package/lib/api/mcp/tasks.d.ts +49 -0
  80. package/lib/api/mcp/tasks.js +147 -0
  81. package/lib/api/utils/validation.d.ts +1 -1
  82. package/lib/api/utils/validation.js +1 -1
  83. package/lib/client/auth/index.js +0 -5
  84. package/lib/client/auth/storage.js +0 -5
  85. package/lib/client/auth/strategies.js +0 -5
  86. package/lib/client/base.d.ts +6 -0
  87. package/lib/client/base.js +8 -0
  88. package/lib/client/index.d.ts +0 -10
  89. package/lib/client/index.js +2 -2
  90. package/lib/client/mixins/ContentsMixin.d.ts +71 -0
  91. package/lib/client/mixins/ContentsMixin.js +157 -0
  92. package/lib/client/mixins/IAMMixin.d.ts +0 -31
  93. package/lib/client/mixins/IAMMixin.js +0 -58
  94. package/lib/components/animation/AnimatedText.d.ts +1 -0
  95. package/lib/components/animation/AnimatedText.js +0 -4
  96. package/lib/components/auth/SigInAPIKey.d.ts +1 -0
  97. package/lib/components/auth/SigInAPIKey.js +0 -6
  98. package/lib/components/auth/SignIn.d.ts +1 -0
  99. package/lib/components/auth/SignIn.js +0 -4
  100. package/lib/components/auth/SignIn.stories.d.ts +2 -2
  101. package/lib/components/avatars/BoringAvatar.d.ts +1 -1
  102. package/lib/components/avatars/BoringAvatar.stories.d.ts +1 -1
  103. package/lib/components/avatars/DLAvatar.d.ts +1 -1
  104. package/lib/components/avatars/DLAvatar.js +0 -4
  105. package/lib/components/avatars/UserAvatar.d.ts +9 -0
  106. package/lib/components/avatars/UserAvatar.js +0 -12
  107. package/lib/components/avatars/UserProfileAvatar.d.ts +1 -1
  108. package/lib/components/banners/NoAutomationBanner.d.ts +1 -1
  109. package/lib/components/billing/BillingEntitySelect.d.ts +10 -0
  110. package/lib/components/billing/BillingEntitySelect.js +0 -17
  111. package/lib/components/billing/index.js +0 -4
  112. package/lib/components/buttons/DownloadCSVButton.d.ts +1 -1
  113. package/lib/components/buttons/DownloadJsonButton.d.ts +1 -1
  114. package/lib/components/buttons/LongActionButton.d.ts +1 -0
  115. package/lib/components/buttons/LongActionButton.js +0 -4
  116. package/lib/components/buttons/UploadButton.d.ts +1 -0
  117. package/lib/components/buttons/UploadButton.js +0 -4
  118. package/lib/components/checkout/StripeCheckout.d.ts +1 -1
  119. package/lib/components/collaboration/LiveEditorCollaborators.d.ts +31 -0
  120. package/lib/components/collaboration/LiveEditorCollaborators.js +86 -53
  121. package/lib/components/collaboration/index.js +0 -4
  122. package/lib/components/confetti/ConfettiSuccess.d.ts +1 -1
  123. package/lib/components/contents/ContentSourceCard.d.ts +8 -0
  124. package/lib/components/contents/ContentSourceCard.js +23 -0
  125. package/lib/components/contents/HomeFolderObjectsBrowser.d.ts +10 -0
  126. package/lib/components/contents/HomeFolderObjectsBrowser.js +148 -0
  127. package/lib/components/contents/index.d.ts +2 -0
  128. package/lib/components/contents/index.js +6 -0
  129. package/lib/components/context/OrganizationSelect.d.ts +1 -1
  130. package/lib/components/display/AvatarSkeleton.d.ts +1 -1
  131. package/lib/components/display/BusyDots.d.ts +1 -1
  132. package/lib/components/display/CenteredSpinner.d.ts +1 -1
  133. package/lib/components/display/CodePreview.d.ts +1 -1
  134. package/lib/components/display/DatalayerBox.d.ts +7 -2
  135. package/lib/components/display/DatalayerBox.js +6 -6
  136. package/lib/components/display/HorizontalCenter.d.ts +1 -1
  137. package/lib/components/display/JupyterDialog.d.ts +1 -0
  138. package/lib/components/display/JupyterDialog.js +1 -7
  139. package/lib/components/display/Markdown.d.ts +1 -0
  140. package/lib/components/display/NotebookSkeleton.d.ts +1 -1
  141. package/lib/components/display/Placeholder.d.ts +1 -1
  142. package/lib/components/display/ToTopBranded.d.ts +1 -1
  143. package/lib/components/echarts/EChartsReact.d.ts +1 -1
  144. package/lib/components/flashes/FlashClosable.d.ts +1 -0
  145. package/lib/components/flashes/FlashClosable.js +0 -4
  146. package/lib/components/flashes/FlashGuest.d.ts +1 -1
  147. package/lib/components/flashes/FlashSurveys.d.ts +1 -1
  148. package/lib/components/flashes/FlashUnauthorized.d.ts +1 -0
  149. package/lib/components/flashes/FlashUnauthorized.js +0 -6
  150. package/lib/components/flashes/surveys/Survey2025_1.d.ts +1 -1
  151. package/lib/components/iam/ExternalTokenSilentLogin.d.ts +1 -1
  152. package/lib/components/index.d.ts +2 -0
  153. package/lib/components/index.js +2 -0
  154. package/lib/components/labels/StatusLabels.d.ts +1 -0
  155. package/lib/components/labels/VisibilityLabel.d.ts +1 -1
  156. package/lib/components/landings/StepBlock.d.ts +1 -1
  157. package/lib/components/mcp/ClientBadge.d.ts +41 -0
  158. package/lib/components/mcp/ClientBadge.js +33 -0
  159. package/lib/components/mcp/McpErrorBlankslate.d.ts +21 -0
  160. package/lib/components/mcp/McpErrorBlankslate.js +17 -0
  161. package/lib/components/mcp/ScopeList.d.ts +28 -0
  162. package/lib/components/mcp/ScopeList.js +14 -0
  163. package/lib/components/mcp/index.d.ts +10 -0
  164. package/lib/components/mcp/index.js +18 -0
  165. package/lib/components/navbar/NavigationVisbilityObserver.d.ts +2 -1
  166. package/lib/components/navbar/SubdomainNavBar.d.ts +10 -5
  167. package/lib/components/navbar/SubdomainNavBar.js +2 -1
  168. package/lib/components/notebooks/JupyterNotebook.d.ts +1 -1
  169. package/lib/components/notebooks/JupyterNotebookToolbar.d.ts +1 -1
  170. package/lib/components/principal/PrincipalAppearance.d.ts +1 -0
  171. package/lib/components/principal/PrincipalAppearance.js +0 -8
  172. package/lib/components/principal/PrincipalAvatar.d.ts +1 -0
  173. package/lib/components/principal/PrincipalAvatar.js +17 -9
  174. package/lib/components/principal/PrincipalBadge.d.ts +1 -1
  175. package/lib/components/principal/PrincipalBanner.d.ts +1 -1
  176. package/lib/components/principal/PrincipalDetailsOverlay.d.ts +31 -1
  177. package/lib/components/principal/PrincipalDetailsOverlay.js +64 -33
  178. package/lib/components/principal/PrincipalHoverCard.d.ts +31 -0
  179. package/lib/components/principal/PrincipalHoverCard.js +52 -0
  180. package/lib/components/principal/PrincipalSwitcherMenu.d.ts +1 -0
  181. package/lib/components/principal/PrincipalSwitcherMenu.js +5 -14
  182. package/lib/components/principal/index.d.ts +2 -1
  183. package/lib/components/principal/index.js +2 -1
  184. package/lib/components/progress/ConsumptionBar.d.ts +1 -0
  185. package/lib/components/progress/ConsumptionBar.js +0 -4
  186. package/lib/components/progress/ProgressRing.d.ts +1 -0
  187. package/lib/components/progress/SpinnerBar.d.ts +1 -1
  188. package/lib/components/progress/Timer.d.ts +1 -0
  189. package/lib/components/progress/Timer.js +0 -4
  190. package/lib/components/screencapture/ScreencaptureButton.d.ts +1 -1
  191. package/lib/components/sharing/ShareAccessComponent.d.ts +15 -1
  192. package/lib/components/sharing/ShareAccessComponent.js +36 -23
  193. package/lib/components/sharing/SharingEditor.d.ts +17 -0
  194. package/lib/components/sharing/SharingEditor.js +0 -24
  195. package/lib/components/sparklines/Sparklines.js +3 -4
  196. package/lib/components/sparklines/index.js +0 -4
  197. package/lib/components/storage/ContentsBrowser.d.ts +25 -1
  198. package/lib/components/storage/ContentsBrowser.js +145 -52
  199. package/lib/components/storage/ContentsBrowserMock.d.ts +3 -0
  200. package/lib/components/storage/ContentsBrowserMock.js +75 -0
  201. package/lib/components/storage/ContentsItems.d.ts +2 -1
  202. package/lib/components/storage/ContentsItems.js +0 -4
  203. package/lib/components/storage/ContentsTable.d.ts +50 -0
  204. package/lib/components/storage/ContentsTable.js +134 -0
  205. package/lib/components/storage/HomeFolderDrive.d.ts +71 -0
  206. package/lib/components/storage/HomeFolderDrive.js +248 -0
  207. package/lib/components/storage/index.d.ts +2 -0
  208. package/lib/components/storage/index.js +2 -0
  209. package/lib/components/students/StudentItemStatus.d.ts +1 -1
  210. package/lib/components/students/StudentResultCircle.d.ts +1 -1
  211. package/lib/components/subnav/SubNav.d.ts +5 -5
  212. package/lib/components/subnav/SubNav.js +11 -9
  213. package/lib/components/tables/DataTable.d.ts +1 -1
  214. package/lib/components/text-reveal/TextRevealAnimation.d.ts +2 -2
  215. package/lib/components/text-reveal/useTextRevealAnimationLines.d.ts +1 -1
  216. package/lib/components/time/LiveRelativeTime.d.ts +1 -0
  217. package/lib/components/time/LiveRelativeTime.js +0 -8
  218. package/lib/components/time/index.js +0 -4
  219. package/lib/components/timeline/Timeline.d.ts +1 -1
  220. package/lib/components/timeline/index.js +0 -4
  221. package/lib/components/users/PeerIndicator.d.ts +1 -0
  222. package/lib/components/users/PeerIndicator.js +0 -4
  223. package/lib/config/Configuration.d.ts +15 -17
  224. package/lib/config/Configuration.js +7 -0
  225. package/lib/hooks/index.d.ts +2 -0
  226. package/lib/hooks/index.js +2 -0
  227. package/lib/hooks/layouts/LayoutBackdrop.d.ts +1 -1
  228. package/lib/hooks/layouts/LayoutScreencapture.d.ts +1 -1
  229. package/lib/hooks/useBackdrop.d.ts +1 -1
  230. package/lib/hooks/useBackdropJupyterLab.d.ts +3 -2
  231. package/lib/hooks/useBackdropJupyterLab.js +0 -4
  232. package/lib/hooks/useCache.d.ts +310 -105
  233. package/lib/hooks/useCache.js +142 -355
  234. package/lib/hooks/useContainsFocus.d.ts +1 -1
  235. package/lib/hooks/useContents.d.ts +313 -0
  236. package/lib/hooks/useContents.js +964 -0
  237. package/lib/hooks/useFocusTrap.d.ts +4 -4
  238. package/lib/hooks/useFocusTrap.js +1 -1
  239. package/lib/hooks/useMcp.d.ts +229 -0
  240. package/lib/hooks/useMcp.js +656 -0
  241. package/lib/hooks/useMobile.js +0 -5
  242. package/lib/hooks/useProjectStore.d.ts +3 -3
  243. package/lib/hooks/useProjectStore.js +4 -4
  244. package/lib/hooks/useRef.d.ts +1 -1
  245. package/lib/hooks/useRef.js +3 -0
  246. package/lib/hooks/useScreencapture.d.ts +2 -1
  247. package/lib/hooks/useScreencapture.js +0 -4
  248. package/lib/hooks/useToast.js +0 -4
  249. package/lib/hooks/useVisibilityObserver.d.ts +1 -1
  250. package/lib/index.d.ts +4 -1
  251. package/lib/index.js +3 -1
  252. package/lib/mocks/components/FlashMock.d.ts +1 -1
  253. package/lib/mocks/views/ActionMenuMock.d.ts +1 -1
  254. package/lib/mocks/views/ChartMock.d.ts +1 -1
  255. package/lib/mocks/views/DashboardMock.d.ts +1 -1
  256. package/lib/mocks/views/FormMock.d.ts +1 -1
  257. package/lib/mocks/views/TableMock.d.ts +1 -1
  258. package/lib/mocks/views/WipMock.d.ts +1 -1
  259. package/lib/models/Credits.d.ts +16 -0
  260. package/lib/models/Credits.js +22 -0
  261. package/lib/models/McpAuditEvent.d.ts +52 -0
  262. package/lib/models/McpAuditEvent.js +5 -0
  263. package/lib/models/McpBinding.d.ts +51 -0
  264. package/lib/models/McpBinding.js +5 -0
  265. package/lib/models/McpPolicy.d.ts +77 -0
  266. package/lib/models/McpPolicy.js +5 -0
  267. package/lib/models/McpTask.d.ts +94 -0
  268. package/lib/models/McpTask.js +7 -0
  269. package/lib/models/StartedBy.d.ts +57 -0
  270. package/lib/models/StartedBy.js +81 -0
  271. package/lib/models/UserDTO.js +4 -2
  272. package/lib/models/contents/__fixtures__/solr-codec.json +57 -0
  273. package/lib/models/contents/__fixtures__/v1-contracts.json +66 -0
  274. package/lib/models/contents/fieldCase.d.ts +8 -0
  275. package/lib/models/contents/fieldCase.js +37 -0
  276. package/lib/models/contents/index.d.ts +2 -0
  277. package/lib/models/contents/index.js +6 -0
  278. package/lib/models/contents/permissions.d.ts +16 -0
  279. package/lib/models/contents/permissions.js +34 -0
  280. package/lib/models/index.d.ts +5 -1
  281. package/lib/models/index.js +5 -1
  282. package/lib/state/substates/CoreState.d.ts +15 -7
  283. package/lib/state/substates/CoreState.js +18 -14
  284. package/lib/state/substates/IAMState.d.ts +1 -1
  285. package/lib/state/substates/IAMState.js +5 -5
  286. package/lib/state/substates/ProfileState.js +0 -4
  287. package/lib/state/substates/index.d.ts +0 -1
  288. package/lib/state/substates/index.js +0 -1
  289. package/lib/utils/Jwt.d.ts +26 -0
  290. package/lib/utils/Jwt.js +37 -0
  291. package/lib/utils/WithSuspense.d.ts +1 -1
  292. package/lib/views/api-keys/APIKeyEdit.d.ts +1 -1
  293. package/lib/views/api-keys/APIKeyNew.d.ts +1 -1
  294. package/lib/views/api-keys/APIKeys.d.ts +1 -1
  295. package/lib/views/api-keys/APIKeys.js +30 -4
  296. package/lib/views/api-keys/APIKeysStandalone.d.ts +5 -1
  297. package/lib/views/api-keys/APIKeysStandalone.js +2 -2
  298. package/lib/views/datasources/DatasourceDetail.d.ts +12 -5
  299. package/lib/views/datasources/DatasourceDetail.js +80 -110
  300. package/lib/views/datasources/DatasourceNew.d.ts +14 -8
  301. package/lib/views/datasources/DatasourceNew.js +129 -118
  302. package/lib/views/datasources/Datasources.d.ts +39 -7
  303. package/lib/views/datasources/Datasources.js +95 -40
  304. package/lib/views/datasources/DatasourcesMock.d.ts +3 -0
  305. package/lib/views/datasources/DatasourcesMock.js +57 -0
  306. package/lib/views/iam/SignInSimple.d.ts +12 -0
  307. package/lib/views/iam/SignInSimple.js +4 -4
  308. package/lib/views/index.d.ts +1 -0
  309. package/lib/views/index.js +1 -0
  310. package/lib/views/mcp/AlertDestinations.d.ts +34 -0
  311. package/lib/views/mcp/AlertDestinations.js +75 -0
  312. package/lib/views/mcp/AlertRules.d.ts +32 -0
  313. package/lib/views/mcp/AlertRules.js +245 -0
  314. package/lib/views/mcp/AuditLog.d.ts +42 -0
  315. package/lib/views/mcp/AuditLog.js +144 -0
  316. package/lib/views/mcp/ConnectedAgents.d.ts +34 -0
  317. package/lib/views/mcp/ConnectedAgents.js +100 -0
  318. package/lib/views/mcp/EnterpriseConsole.d.ts +74 -0
  319. package/lib/views/mcp/EnterpriseConsole.js +173 -0
  320. package/lib/views/mcp/McpDashboard.d.ts +50 -0
  321. package/lib/views/mcp/McpDashboard.js +347 -0
  322. package/lib/views/mcp/McpHome.d.ts +92 -0
  323. package/lib/views/mcp/McpHome.js +153 -0
  324. package/lib/views/mcp/McpObservability.d.ts +50 -0
  325. package/lib/views/mcp/McpObservability.js +150 -0
  326. package/lib/views/mcp/OrganizationPolicy.d.ts +45 -0
  327. package/lib/views/mcp/OrganizationPolicy.js +107 -0
  328. package/lib/views/mcp/OrganizationUsage.d.ts +69 -0
  329. package/lib/views/mcp/OrganizationUsage.js +113 -0
  330. package/lib/views/mcp/PersonalPolicy.d.ts +54 -0
  331. package/lib/views/mcp/PersonalPolicy.js +125 -0
  332. package/lib/views/mcp/Policies.d.ts +53 -0
  333. package/lib/views/mcp/Policies.js +210 -0
  334. package/lib/views/mcp/PolicyForm.d.ts +67 -0
  335. package/lib/views/mcp/PolicyForm.js +91 -0
  336. package/lib/views/mcp/PolicyHistory.d.ts +45 -0
  337. package/lib/views/mcp/PolicyHistory.js +62 -0
  338. package/lib/views/mcp/ServiceAgents.d.ts +46 -0
  339. package/lib/views/mcp/ServiceAgents.js +194 -0
  340. package/lib/views/mcp/TeamPolicies.d.ts +33 -0
  341. package/lib/views/mcp/TeamPolicies.js +98 -0
  342. package/lib/views/mcp/format.d.ts +25 -0
  343. package/lib/views/mcp/format.js +77 -0
  344. package/lib/views/mcp/index.d.ts +29 -0
  345. package/lib/views/mcp/index.js +37 -0
  346. package/lib/views/mcp/types.d.ts +66 -0
  347. package/lib/views/mcp/types.js +5 -0
  348. package/lib/views/secrets/SecretEdit.d.ts +5 -1
  349. package/lib/views/secrets/SecretEdit.js +2 -2
  350. package/lib/views/secrets/SecretNew.d.ts +11 -1
  351. package/lib/views/secrets/SecretNew.js +2 -2
  352. package/lib/views/secrets/Secrets.d.ts +12 -1
  353. package/lib/views/secrets/Secrets.js +2 -2
  354. package/package.json +28 -24
  355. package/scripts/generate-contents-types.py +169 -0
  356. package/scripts/generate-mcp-types.py +233 -0
  357. package/lib/api/iam/datasources.d.ts +0 -86
  358. package/lib/api/iam/datasources.js +0 -185
  359. package/lib/components/toolbars/index.d.ts +0 -1
  360. package/lib/models/Datasource.d.ts +0 -181
  361. package/lib/models/Datasource.js +0 -154
  362. package/lib/state/substates/DatasourceState.d.ts +0 -11
  363. package/lib/state/substates/DatasourceState.js +0 -16
  364. /package/lib/{components/toolbars/index.js → api/contents/generated.js} +0 -0
@@ -0,0 +1,62 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import { Label, RelativeTime, Spinner, Text } from '@primer/react';
4
+ import { Box } from '@datalayer/primer-addons';
5
+ import { useAuditEvents } from '../../hooks/useMcp.js';
6
+ /** The methods IAM writes when a policy layer is written or removed. */
7
+ export const POLICY_AUDIT_METHODS = [
8
+ 'mcp.policy.set',
9
+ 'mcp.policy.remove',
10
+ ];
11
+ /** What one row says about a change, in the words of the page it is on. */
12
+ export const describeChange = (event) => {
13
+ const info = (event.clientInfo ?? {});
14
+ const scope = String(info.scope ?? '');
15
+ const rules = String(info.rules ?? '');
16
+ if (event.method === 'mcp.policy.remove') {
17
+ return `removed the ${scope || 'policy'} layer`;
18
+ }
19
+ if (rules && rules !== '(none)') {
20
+ return `set ${rules.split(',').join(', ')}`;
21
+ }
22
+ // A layer written with no rules narrows nothing. Saying "set (none)" would
23
+ // read as a failure; saying what it means is the point of the row.
24
+ return 'set a layer that narrows nothing';
25
+ };
26
+ export const PolicyHistory = ({ orgUid, subjectUid, limit = 20, }) => {
27
+ // Both methods in one read: two queries would page independently and
28
+ // interleave wrongly, showing a removal before the set that preceded it.
29
+ const events = useAuditEvents({ org: orgUid, method: POLICY_AUDIT_METHODS[0], limit }, { enabled: Boolean(orgUid) });
30
+ const removals = useAuditEvents({ org: orgUid, method: POLICY_AUDIT_METHODS[1], limit }, { enabled: Boolean(orgUid) });
31
+ const rows = useMemo(() => {
32
+ const all = [
33
+ ...(events.data?.items ?? []),
34
+ ...(removals.data?.items ?? []),
35
+ ];
36
+ const mine = subjectUid
37
+ ? all.filter(event => String(event.clientInfo?.subject_uid ?? '') === subjectUid)
38
+ : all;
39
+ // Newest first, merged across the two reads.
40
+ return mine
41
+ .slice()
42
+ .sort((a, b) => (a.at < b.at ? 1 : a.at > b.at ? -1 : 0))
43
+ .slice(0, limit);
44
+ }, [events.data, removals.data, subjectUid, limit]);
45
+ if ((events.isPending || removals.isPending) && rows.length === 0) {
46
+ return (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 3 }, children: _jsx(Spinner, { size: "small" }) }));
47
+ }
48
+ if (events.isError || removals.isError) {
49
+ return (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "The history could not be read. The policy above is unaffected." }));
50
+ }
51
+ if (rows.length === 0) {
52
+ return (_jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', m: 0 }, children: "No recorded change. Either this layer has not been edited, or this deployment routes identity records to a log pipeline rather than to the audit \u2014 an administrator can tell you which." }));
53
+ }
54
+ return (_jsx(Box, { sx: { display: 'grid', gap: 2 }, children: rows.map(event => (_jsxs(Box, { sx: {
55
+ display: 'flex',
56
+ gap: 2,
57
+ alignItems: 'baseline',
58
+ flexWrap: 'wrap',
59
+ fontSize: 0,
60
+ }, children: [_jsx(Text, { sx: { color: 'fg.muted', whiteSpace: 'nowrap' }, children: _jsx(RelativeTime, { datetime: event.at }) }), _jsx(Text, { sx: { fontWeight: 'semibold' }, children: event.userUid || 'unknown' }), _jsx(Text, { children: describeChange(event) }), String(event.clientInfo?.version ?? '') && (_jsxs(Label, { size: "small", variant: "secondary", children: ["v", String(event.clientInfo?.version ?? '')] }))] }, event.uid))) }));
61
+ };
62
+ export default PolicyHistory;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The organization's service agents: principals rather than proxies.
3
+ *
4
+ * The Agents page next door lists *grants* — somebody's authority narrowed
5
+ * to one client, dying with their account. This page lists the other kind:
6
+ * an agent that belongs to the organization, holds its own key, spends
7
+ * under its own name and outlives whoever set it up. An organization whose
8
+ * nightly pipeline runs on an engineer's grant loses the pipeline when the
9
+ * engineer leaves, and its spend shows against somebody who was asleep.
10
+ *
11
+ * Three things this page has to get right, all of them about the key:
12
+ *
13
+ * **It is shown once**, in the dialog that creates or rotates it, and the
14
+ * dialog says so before it says anything else. IAM stores a hash and cannot
15
+ * show it again, so somebody who does not read that sentence stores nothing
16
+ * and rotates an hour later.
17
+ *
18
+ * **Rotating breaks the old key immediately.** There is no grace period, by
19
+ * design, so the confirmation says what will stop rather than asking a
20
+ * yes/no about a word.
21
+ *
22
+ * **Revoking does not remove the row.** Its audit rows name it, and a uid
23
+ * that resolves to nothing makes a year-old row unreadable. Revoked is a
24
+ * state in the table, never a reason to hide it.
25
+ *
26
+ * @module views/mcp/ServiceAgents
27
+ */
28
+ import type { JSX } from 'react';
29
+ import type { McpErrorStateFn } from './types';
30
+ export interface ServiceAgentsProps {
31
+ /** The application's words for a failed request. */
32
+ errorState: McpErrorStateFn;
33
+ /** The organization whose agents these are. */
34
+ orgUid: string;
35
+ /**
36
+ * Read-only for anybody who is not an owner. Members may *see* the list —
37
+ * an agent spending their organization's budget is one they will ask
38
+ * about — and IAM refuses their writes either way; this only keeps the
39
+ * page from offering an action that would be refused.
40
+ */
41
+ readOnly?: boolean;
42
+ /** Drawn without its heading, when the page around it carries one. */
43
+ showTitle?: boolean;
44
+ }
45
+ export declare const ServiceAgents: ({ errorState, orgUid, readOnly, showTitle, }: ServiceAgentsProps) => JSX.Element;
46
+ export default ServiceAgents;
@@ -0,0 +1,194 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useRef, useState } from 'react';
3
+ import { ActionList, ActionMenu, Button, Checkbox, FormControl, Heading, Label, RelativeTime, Spinner, Text, TextInput, } from '@primer/react';
4
+ import { Blankslate, DataTable, Dialog, Table, } from '@primer/react/experimental';
5
+ import { Box } from '@datalayer/primer-addons';
6
+ import { KebabHorizontalIcon, KeyIcon } from '@primer/octicons-react';
7
+ import { McpErrorBlankslate, ScopeList } from '../../components/mcp/index.js';
8
+ import { useCreateServiceAgent, useRevokeServiceAgent, useRotateServiceAgentKey, useServiceAgents, } from '../../hooks/useMcp.js';
9
+ import { useToast } from '../../hooks/index.js';
10
+ import { SERVICE_AGENT_SCOPES, } from '../../api/iam/serviceAgents.js';
11
+ export const ServiceAgents = ({ errorState, orgUid, readOnly = false, showTitle = true, }) => {
12
+ const { enqueueToast } = useToast();
13
+ const agents = useServiceAgents(orgUid);
14
+ const create = useCreateServiceAgent(orgUid);
15
+ const rotate = useRotateServiceAgentKey(orgUid);
16
+ const revoke = useRevokeServiceAgent(orgUid);
17
+ const [creating, setCreating] = useState(false);
18
+ const [name, setName] = useState('');
19
+ const [scopes, setScopes] = useState(['runtimes:read']);
20
+ const [rotating, setRotating] = useState(null);
21
+ const [revoking, setRevoking] = useState(null);
22
+ const [keyShown, setKeyShown] = useState(null);
23
+ // Primer 37 types Dialog's focus refs with React 18's non-nullable
24
+ // `RefObject<HTMLElement>`. React 19's `useRef(null)` is nullable, and this
25
+ // ref is only handed to Dialog, so narrow it once here.
26
+ const returnFocusRef = useRef(null);
27
+ const rows = useMemo(() => (agents.data ?? []).map(agent => ({ ...agent, id: agent.uid })), [agents.data]);
28
+ const closeCreate = () => {
29
+ setCreating(false);
30
+ setName('');
31
+ setScopes(['runtimes:read']);
32
+ };
33
+ const confirmCreate = () => {
34
+ create.mutate({ name: name.trim(), scopes }, {
35
+ onSuccess: agent => {
36
+ closeCreate();
37
+ setKeyShown({
38
+ agent: agent.name || agent.uid,
39
+ key: agent.key,
40
+ rotated: false,
41
+ });
42
+ },
43
+ onError: reason => {
44
+ enqueueToast(`Could not create the agent: ${reason.message}`, {
45
+ variant: 'error',
46
+ });
47
+ },
48
+ });
49
+ };
50
+ const confirmRotate = () => {
51
+ const agent = rotating;
52
+ if (!agent) {
53
+ return;
54
+ }
55
+ rotate.mutate(agent.uid, {
56
+ onSuccess: rotated => {
57
+ setRotating(null);
58
+ setKeyShown({
59
+ agent: agent.name || agent.uid,
60
+ key: rotated.key,
61
+ rotated: true,
62
+ });
63
+ },
64
+ onError: reason => {
65
+ enqueueToast(`Could not rotate the key: ${reason.message}`, {
66
+ variant: 'error',
67
+ });
68
+ setRotating(null);
69
+ },
70
+ });
71
+ };
72
+ const confirmRevoke = () => {
73
+ const agent = revoking;
74
+ if (!agent) {
75
+ return;
76
+ }
77
+ revoke.mutate(agent.uid, {
78
+ onSuccess: () => {
79
+ enqueueToast(`${agent.name || agent.uid} is revoked.`, {
80
+ variant: 'success',
81
+ });
82
+ setRevoking(null);
83
+ },
84
+ onError: reason => {
85
+ enqueueToast(`Could not revoke: ${reason.message}`, {
86
+ variant: 'error',
87
+ });
88
+ setRevoking(null);
89
+ },
90
+ });
91
+ };
92
+ const toggleScope = (scope, on) => setScopes(current => on
93
+ ? [...current, scope]
94
+ : current.filter(candidate => candidate !== scope));
95
+ const columns = [
96
+ {
97
+ header: 'Agent',
98
+ field: 'name',
99
+ rowHeader: true,
100
+ renderCell: row => (_jsxs(Box, { sx: { display: 'grid' }, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: row.name || row.uid }), row.description && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: row.description }))] })),
101
+ },
102
+ {
103
+ header: 'Kind',
104
+ id: 'kind',
105
+ width: '110px',
106
+ renderCell: () => (_jsx(Label, { size: "small", variant: "accent", children: "Service" })),
107
+ },
108
+ {
109
+ header: 'Allowed to',
110
+ id: 'scopes',
111
+ width: 'growCollapse',
112
+ renderCell: row => (_jsx(ScopeList, { scopes: row.scopes.split(' ').filter(Boolean) })),
113
+ },
114
+ {
115
+ header: 'State',
116
+ id: 'state',
117
+ width: '110px',
118
+ renderCell: row => row.revoked ? (_jsx(Label, { size: "small", variant: "danger", children: "Revoked" })) : (_jsx(Label, { size: "small", variant: "success", children: "Active" })),
119
+ },
120
+ {
121
+ header: 'Key rotated',
122
+ id: 'rotated',
123
+ width: '130px',
124
+ renderCell: row => row.keyRotatedAt ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: _jsx(RelativeTime, { datetime: row.keyRotatedAt }) })) : (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "\u2014" })),
125
+ },
126
+ {
127
+ header: '',
128
+ id: 'actions',
129
+ width: '48px',
130
+ align: 'end',
131
+ renderCell: row => readOnly || row.revoked ? (_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 ${row.name || row.uid}`, icon: KebabHorizontalIcon }) }), _jsx(ActionMenu.Overlay, { align: "end", children: _jsxs(ActionList, { children: [_jsx(ActionList.Item, { onSelect: () => setRotating(row), children: "Rotate key" }), _jsx(ActionList.Item, { variant: "danger", onSelect: () => setRevoking(row), children: "Revoke" })] }) })] })),
132
+ },
133
+ ];
134
+ if (agents.isError) {
135
+ return (_jsx(McpErrorBlankslate, { state: errorState(agents.error, 'Service agents'), onRetry: () => agents.refetch() }));
136
+ }
137
+ return (_jsxs(Box, { sx: { display: 'grid', gap: 3, minWidth: 0 }, children: [showTitle && (_jsxs(Box, { sx: {
138
+ display: 'flex',
139
+ alignItems: 'start',
140
+ justifyContent: 'space-between',
141
+ gap: 3,
142
+ }, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Service Agents" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "Agents that belong to this organization rather than to a person: a pipeline, a CI job, a bot. Each holds its own key and spends under its own name." })] }), !readOnly && (_jsx(Button, { variant: "primary", onClick: () => setCreating(true), children: "New service agent" }))] })), agents.isPending && !agents.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: "service-agents", children: "Service agents" }), _jsx(Table.Subtitle, { as: "p", id: "service-agents-subtitle", children: "A revoked agent stays listed: its audit rows name it, and a uid that resolves to nothing makes them unreadable a year from now." }), _jsx(DataTable, { "aria-labelledby": "service-agents", "aria-describedby": "service-agents-subtitle", data: rows, columns: columns })] })) : (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(KeyIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "No service agent" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "An agent that runs on somebody\u2019s grant stops when that person leaves, and its spend shows against them. A service agent is the organization\u2019s own." }) }), !readOnly && (_jsx(Button, { size: "small", onClick: () => setCreating(true), children: "New service agent" }))] })), creating && (_jsx(Dialog, { title: "New service agent", onClose: closeCreate, returnFocusRef: returnFocusRef, footerButtons: [
143
+ { buttonType: 'default', content: 'Cancel', onClick: closeCreate },
144
+ {
145
+ buttonType: 'primary',
146
+ content: 'Create',
147
+ onClick: confirmCreate,
148
+ // Both are refused by IAM anyway — a nameless agent is
149
+ // unreadable in an audit row, and a scopeless one is a key
150
+ // that fails at its first call. Disabling here turns a refusal
151
+ // into an obvious gap in the form.
152
+ disabled: create.isPending || !name.trim() || scopes.length === 0,
153
+ },
154
+ ], children: _jsxs(Box, { sx: { display: 'grid', gap: 3 }, children: [_jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Name" }), _jsx(TextInput, { block: true, value: name, onChange: event => setName(event.target.value), placeholder: "nightly ingest" }), _jsx(FormControl.Caption, { children: "What somebody reading an audit row or a spend line a year from now has to go on." })] }), _jsxs(Box, { children: [_jsx(Text, { as: "p", sx: { fontSize: 1, fontWeight: 'semibold', mb: 1 }, children: "Allowed to" }), _jsx(Box, { sx: { display: 'grid', gap: 1 }, children: SERVICE_AGENT_SCOPES.map(scope => (_jsxs(FormControl, { children: [_jsx(Checkbox, { checked: scopes.includes(scope), onChange: event => toggleScope(scope, event.target.checked) }), _jsx(FormControl.Label, { children: scope })] }, scope))) }), _jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', mt: 1 }, children: "The scopes about a person \u2014 their profile, acting as them \u2014 are not here: a pipeline is not a person, and granting one to it would do nothing while looking like it did something." })] })] }) })), keyShown && (_jsx(Dialog, { title: keyShown.rotated ? 'The new key' : 'The key', onClose: () => setKeyShown(null), returnFocusRef: returnFocusRef, footerButtons: [
155
+ {
156
+ buttonType: 'primary',
157
+ content: 'I have stored it',
158
+ onClick: () => setKeyShown(null),
159
+ },
160
+ ], children: _jsxs(Box, { sx: { display: 'grid', gap: 2 }, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: "This is shown once and cannot be shown again." }), _jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "We store a hash of it, so there is no page and no support request that can show it to you a second time. If you lose it, rotate \u2014 that issues a new key and stops this one." }), _jsx(Box, { as: "pre", sx: {
161
+ fontFamily: 'mono',
162
+ fontSize: 1,
163
+ p: 2,
164
+ m: 0,
165
+ bg: 'canvas.subtle',
166
+ borderRadius: 2,
167
+ overflowX: 'auto',
168
+ }, children: keyShown.key }), keyShown.rotated && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: [keyShown.agent, "\u2019s previous key stopped working when this one was issued."] }))] }) })), rotating && (_jsx(Dialog, { title: "Rotate this key?", onClose: () => setRotating(null), returnFocusRef: returnFocusRef, footerButtons: [
169
+ {
170
+ buttonType: 'default',
171
+ content: 'Keep it',
172
+ onClick: () => setRotating(null),
173
+ },
174
+ {
175
+ buttonType: 'danger',
176
+ content: 'Rotate',
177
+ onClick: confirmRotate,
178
+ disabled: rotate.isPending,
179
+ },
180
+ ], children: _jsxs(Text, { sx: { fontSize: 1 }, children: [rotating.name || rotating.uid, " gets a new key and the current one stops working immediately \u2014 there is no grace period, which is the point of rotating. Anything still using the old key fails until you give it the new one. The new key is shown once."] }) })), revoking && (_jsx(Dialog, { title: "Revoke this agent?", onClose: () => setRevoking(null), returnFocusRef: returnFocusRef, footerButtons: [
181
+ {
182
+ buttonType: 'default',
183
+ content: 'Keep it',
184
+ onClick: () => setRevoking(null),
185
+ },
186
+ {
187
+ buttonType: 'danger',
188
+ content: 'Revoke',
189
+ onClick: confirmRevoke,
190
+ disabled: revoke.isPending,
191
+ },
192
+ ], children: _jsxs(Text, { sx: { fontSize: 1 }, children: [revoking.name || revoking.uid, " stops authenticating within a minute and anything running on its key fails. It stays in this list, marked revoked, because its audit rows name it \u2014 and nothing it already did is undone."] }) }))] }));
193
+ };
194
+ export default ServiceAgents;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * What each team narrows, on top of the organization's own layer.
3
+ *
4
+ * A team is a scope, not a label: its layer sits between the
5
+ * organization's and the person's, and everything intersects. A team can be
6
+ * stricter than its organization and never looser — permitting a tool the
7
+ * organization denies does nothing, and a cap above the organization's
8
+ * leaves the organization's in force.
9
+ *
10
+ * The one rule that behaves differently is worth saying on this page rather
11
+ * than leaving to be discovered: **a team's sandbox limit counts the team's
12
+ * own sandboxes**, not the organization's. Every other rule is one number
13
+ * checked once; a counted quota belongs to a scope, and a team cap measured
14
+ * against the organization's count would refuse a team running nothing
15
+ * because other teams are busy.
16
+ *
17
+ * Team owners administer their own slice — no new role, the existing
18
+ * `team_owner` handle carries it — and an organization owner may write any
19
+ * of them, since an owner who could not narrow one of their own teams would
20
+ * have to remove the team to do it.
21
+ *
22
+ * @module views/mcp/TeamPolicies
23
+ */
24
+ import type { JSX } from 'react';
25
+ import type { McpErrorStateFn } from './types';
26
+ export interface TeamPoliciesProps {
27
+ errorState: McpErrorStateFn;
28
+ orgUid: string;
29
+ readOnly?: boolean;
30
+ showTitle?: boolean;
31
+ }
32
+ export declare const TeamPolicies: ({ errorState, orgUid, readOnly, showTitle, }: TeamPoliciesProps) => JSX.Element;
33
+ export default TeamPolicies;
@@ -0,0 +1,98 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useState } from 'react';
3
+ import { Button, Flash, Heading, Select, Spinner, Text } from '@primer/react';
4
+ import { Blankslate } from '@primer/react/experimental';
5
+ import { Box } from '@datalayer/primer-addons';
6
+ import { PeopleIcon } from '@primer/octicons-react';
7
+ import { McpErrorBlankslate } from '../../components/mcp/index.js';
8
+ import { useMcpPolicyLayer, useOrganizationTeams, useSetMcpPolicyLayer, useDeleteMcpPolicyLayer, } from '../../hooks/useMcp.js';
9
+ import { useToast } from '../../hooks/index.js';
10
+ import { McpPolicyConflict } from '../../api/iam/mcpPolicy.js';
11
+ import { PolicyHistory } from './PolicyHistory.js';
12
+ import { EMPTY_POLICY_DRAFT, PolicyForm, draftOf, policyChanged, rulesFrom, } from './PolicyForm.js';
13
+ /**
14
+ * The form for one team.
15
+ *
16
+ * Its own component so that choosing a different team unmounts it: a form
17
+ * that kept its draft across a change of team would offer to save one
18
+ * team's rules onto another, which is the one mistake on this page nobody
19
+ * would notice until it had happened.
20
+ */
21
+ const TeamPolicyForm = ({ orgUid, teamUid, teamName, readOnly, }) => {
22
+ const { enqueueToast } = useToast();
23
+ const layer = useMcpPolicyLayer('team', teamUid);
24
+ const save = useSetMcpPolicyLayer('team', teamUid);
25
+ const remove = useDeleteMcpPolicyLayer('team', teamUid);
26
+ const [draft, setDraft] = useState(EMPTY_POLICY_DRAFT);
27
+ const [conflict, setConflict] = useState('');
28
+ const [refusal, setRefusal] = useState('');
29
+ const stored = useMemo(() => draftOf(layer.data), [layer.data]);
30
+ useEffect(() => setDraft(stored), [stored]);
31
+ const changed = useMemo(() => policyChanged(draft, stored), [draft, stored]);
32
+ const set = (key, value) => setDraft(current => ({ ...current, [key]: value }));
33
+ const apply = () => {
34
+ const rules = rulesFrom(draft);
35
+ if (typeof rules === 'string') {
36
+ setRefusal(rules);
37
+ return;
38
+ }
39
+ setRefusal('');
40
+ setConflict('');
41
+ save.mutate({ rules, expectedVersion: layer.data?.version }, {
42
+ onSuccess: () => enqueueToast(`${teamName}'s policy saved.`, { variant: 'success' }),
43
+ onError: error => {
44
+ if (error instanceof McpPolicyConflict) {
45
+ setConflict(error.message);
46
+ return;
47
+ }
48
+ enqueueToast(`Could not save: ${error.message}`, {
49
+ variant: 'error',
50
+ });
51
+ },
52
+ });
53
+ };
54
+ if (layer.isPending && layer.data === undefined) {
55
+ return (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 4 }, children: _jsx(Spinner, {}) }));
56
+ }
57
+ return (_jsxs(Box, { sx: { display: 'grid', gap: 3 }, children: [conflict && (_jsxs(Flash, { variant: "warning", children: [_jsx(Text, { sx: { fontSize: 1 }, children: conflict }), _jsx(Box, { sx: { mt: 2 }, children: _jsx(Button, { size: "small", onClick: () => {
58
+ setConflict('');
59
+ layer.refetch();
60
+ }, children: "Read it again" }) })] })), refusal && (_jsx(Flash, { variant: "danger", children: _jsx(Text, { sx: { fontSize: 1 }, children: refusal }) })), _jsx(PolicyForm, { draft: draft, onChange: set, disabled: readOnly, notes: {
61
+ maxConcurrentSandboxes: "Counted over this team's own sandboxes, not the organization's " +
62
+ '— so another team being busy never uses up this limit. The ' +
63
+ "organization's cap still applies on top.",
64
+ } }), !readOnly && (_jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'center' }, children: [_jsxs(Button, { variant: "primary", onClick: apply, disabled: !changed || save.isPending, children: ["Save ", teamName, "\u2019s policy"] }), changed && (_jsx(Button, { variant: "invisible", onClick: () => setDraft(stored), children: "Discard changes" })), layer.data && (_jsx(Box, { sx: { marginLeft: 'auto' }, children: _jsx(Button, { variant: "danger", disabled: remove.isPending, onClick: () => remove.mutate(undefined, {
65
+ onSuccess: () => enqueueToast(`${teamName} narrows nothing of its own.`, {
66
+ variant: 'success',
67
+ }),
68
+ onError: error => enqueueToast(`Could not remove: ${error.message}`, {
69
+ variant: 'error',
70
+ }),
71
+ }), children: "Remove" }) }))] })), _jsxs(Box, { sx: {
72
+ borderTop: '1px solid',
73
+ borderColor: 'border.muted',
74
+ pt: 3,
75
+ display: 'grid',
76
+ gap: 2,
77
+ }, children: [_jsx(Text, { as: "h3", sx: { fontSize: 1, fontWeight: 'semibold', m: 0 }, children: "History" }), _jsx(PolicyHistory, { orgUid: orgUid, subjectUid: teamUid })] }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: "A team can be stricter than its organization and never looser. Permitting a tool the organization denies does nothing, and a cap above the organization\u2019s leaves the organization\u2019s in force." })] }));
78
+ };
79
+ export const TeamPolicies = ({ errorState, orgUid, readOnly = false, showTitle = true, }) => {
80
+ const teams = useOrganizationTeams(orgUid);
81
+ const [chosen, setChosen] = useState('');
82
+ const current = useMemo(() => (teams.data ?? []).find(team => team.uid === chosen) ??
83
+ (teams.data ?? [])[0], [teams.data, chosen]);
84
+ if (teams.isError) {
85
+ return (_jsx(McpErrorBlankslate, { state: errorState(teams.error, "The organization's teams"), onRetry: () => teams.refetch() }));
86
+ }
87
+ if (teams.isPending && !teams.data) {
88
+ return (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 5 }, children: _jsx(Spinner, {}) }));
89
+ }
90
+ if ((teams.data ?? []).length === 0) {
91
+ return (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(PeopleIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "No teams" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "A team is a scope, not a label: it gets its own rules, its own sandbox limit and its own alerts. Create one in the organization\u2019s settings and it appears here." }) })] }));
92
+ }
93
+ return (_jsxs(Box, { sx: { display: 'grid', gap: 3, minWidth: 0, maxWidth: '52rem' }, children: [showTitle && (_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Team policies" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "What each team narrows, on top of this organization\u2019s own rules. A team owner may write their own team\u2019s." })] })), _jsx(Box, { sx: { maxWidth: '20rem' }, children: _jsx(Select, { value: current?.uid ?? '', onChange: event => setChosen(event.target.value), "aria-label": "Team", children: (teams.data ?? []).map(team => (_jsx(Select.Option, { value: team.uid, children: team.name }, team.uid))) }) }), current && (
94
+ // Keyed by the team, so choosing another unmounts the form rather
95
+ // than carrying one team's unsaved draft onto the next.
96
+ _jsx(TeamPolicyForm, { orgUid: orgUid, teamUid: current.uid, teamName: current.name, readOnly: readOnly }, current.uid))] }));
97
+ };
98
+ export default TeamPolicies;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The small readings every MCP surface shares: how long ago, how long it
3
+ * took, and whether a client is still there.
4
+ *
5
+ * Plain functions with no React in them, so the wording of "4m ago" is one
6
+ * decision rather than one per view.
7
+ *
8
+ * @module views/mcp/format
9
+ */
10
+ /** A client that called within this window is drawn as active. */
11
+ export declare const MCP_ACTIVE_WINDOW_MS: number;
12
+ /**
13
+ * A client idle longer than this has left the activity answer, and its card
14
+ * leaves the home grid — the same window the gateway bounds `/activity` by.
15
+ */
16
+ export declare const MCP_ACTIVITY_WINDOW_MS: number;
17
+ /** Where a client is, from when it last called. */
18
+ export type McpClientStatus = 'active' | 'idle' | 'disconnected';
19
+ export declare const clientStatusOf: (lastCallAt: string | null | undefined, now?: number) => McpClientStatus;
20
+ /** How long ago a moment was, in the words the home page uses. */
21
+ export declare const timeAgo: (iso: string | null | undefined, now?: number) => string;
22
+ /** A duration in the unit that reads: milliseconds, seconds, minutes. */
23
+ export declare const durationLabel: (milliseconds: number | null | undefined) => string;
24
+ /** A count in the page's terms: `1 call`, `12 calls`, `no call`. */
25
+ export declare const plural: (count: number, singular: string, many?: string) => string;
@@ -0,0 +1,77 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /*
6
+ * Copyright (c) 2023-2026 Datalayer, Inc.
7
+ * Distributed under the terms of the Modified BSD License.
8
+ */
9
+ /**
10
+ * The small readings every MCP surface shares: how long ago, how long it
11
+ * took, and whether a client is still there.
12
+ *
13
+ * Plain functions with no React in them, so the wording of "4m ago" is one
14
+ * decision rather than one per view.
15
+ *
16
+ * @module views/mcp/format
17
+ */
18
+ /** A client that called within this window is drawn as active. */
19
+ export const MCP_ACTIVE_WINDOW_MS = 5 * 60_000;
20
+ /**
21
+ * A client idle longer than this has left the activity answer, and its card
22
+ * leaves the home grid — the same window the gateway bounds `/activity` by.
23
+ */
24
+ export const MCP_ACTIVITY_WINDOW_MS = 30 * 60_000;
25
+ export const clientStatusOf = (lastCallAt, now = Date.now()) => {
26
+ if (!lastCallAt) {
27
+ // A grant that has never been used is connected but has done nothing.
28
+ return 'idle';
29
+ }
30
+ const at = Date.parse(lastCallAt);
31
+ if (Number.isNaN(at)) {
32
+ return 'idle';
33
+ }
34
+ const age = now - at;
35
+ if (age <= MCP_ACTIVE_WINDOW_MS) {
36
+ return 'active';
37
+ }
38
+ return age <= MCP_ACTIVITY_WINDOW_MS ? 'idle' : 'disconnected';
39
+ };
40
+ /** How long ago a moment was, in the words the home page uses. */
41
+ export const timeAgo = (iso, now = Date.now()) => {
42
+ if (!iso) {
43
+ return '';
44
+ }
45
+ const at = Date.parse(iso);
46
+ if (Number.isNaN(at)) {
47
+ return '';
48
+ }
49
+ const seconds = Math.max(0, (now - at) / 1000);
50
+ if (seconds < 60) {
51
+ return 'just now';
52
+ }
53
+ if (seconds < 3600) {
54
+ return `${Math.floor(seconds / 60)}m ago`;
55
+ }
56
+ if (seconds < 86400) {
57
+ return `${Math.floor(seconds / 3600)}h ago`;
58
+ }
59
+ return `${Math.floor(seconds / 86400)}d ago`;
60
+ };
61
+ /** A duration in the unit that reads: milliseconds, seconds, minutes. */
62
+ export const durationLabel = (milliseconds) => {
63
+ if (milliseconds === null || milliseconds === undefined) {
64
+ return '';
65
+ }
66
+ if (milliseconds < 1000) {
67
+ return `${Math.round(milliseconds)}ms`;
68
+ }
69
+ if (milliseconds < 60_000) {
70
+ return `${(milliseconds / 1000).toFixed(1)}s`;
71
+ }
72
+ const minutes = Math.floor(milliseconds / 60_000);
73
+ const seconds = Math.round((milliseconds % 60_000) / 1000);
74
+ return `${minutes}m ${seconds}s`;
75
+ };
76
+ /** A count in the page's terms: `1 call`, `12 calls`, `no call`. */
77
+ export const plural = (count, singular, many = `${singular}s`) => `${count} ${count === 1 ? singular : many}`;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The MCP surfaces, as views the application composes: the dashboard, the
3
+ * setup page, the connected agents, the audit log, the observability panes,
4
+ * the effective policy and the organization's console.
5
+ *
6
+ * Every one of them owns its data and its states and nothing about routing,
7
+ * which is what lets the web application, JupyterLab, VS Code and Desktop
8
+ * draw the same page.
9
+ *
10
+ * @module views/mcp
11
+ */
12
+ export * from './types';
13
+ export * from './format';
14
+ export * from './McpDashboard';
15
+ export * from './McpHome';
16
+ export * from './ConnectedAgents';
17
+ export * from './AlertDestinations';
18
+ export * from './AlertRules';
19
+ export * from './OrganizationPolicy';
20
+ export * from './PersonalPolicy';
21
+ export * from './PolicyForm';
22
+ export * from './PolicyHistory';
23
+ export * from './TeamPolicies';
24
+ export * from './ServiceAgents';
25
+ export * from './AuditLog';
26
+ export * from './McpObservability';
27
+ export * from './Policies';
28
+ export * from './OrganizationUsage';
29
+ export * from './EnterpriseConsole';
@@ -0,0 +1,37 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /*
6
+ * Copyright (c) 2023-2026 Datalayer, Inc.
7
+ * Distributed under the terms of the Modified BSD License.
8
+ */
9
+ /**
10
+ * The MCP surfaces, as views the application composes: the dashboard, the
11
+ * setup page, the connected agents, the audit log, the observability panes,
12
+ * the effective policy and the organization's console.
13
+ *
14
+ * Every one of them owns its data and its states and nothing about routing,
15
+ * which is what lets the web application, JupyterLab, VS Code and Desktop
16
+ * draw the same page.
17
+ *
18
+ * @module views/mcp
19
+ */
20
+ export * from './types.js';
21
+ export * from './format.js';
22
+ export * from './McpDashboard.js';
23
+ export * from './McpHome.js';
24
+ export * from './ConnectedAgents.js';
25
+ export * from './AlertDestinations.js';
26
+ export * from './AlertRules.js';
27
+ export * from './OrganizationPolicy.js';
28
+ export * from './PersonalPolicy.js';
29
+ export * from './PolicyForm.js';
30
+ export * from './PolicyHistory.js';
31
+ export * from './TeamPolicies.js';
32
+ export * from './ServiceAgents.js';
33
+ export * from './AuditLog.js';
34
+ export * from './McpObservability.js';
35
+ export * from './Policies.js';
36
+ export * from './OrganizationUsage.js';
37
+ export * from './EnterpriseConsole.js';