@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
@@ -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,159 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef, useState } from 'react';
3
+ import { Button, Flash, Heading, Select, Spinner, Text } from '@primer/react';
4
+ import { Blankslate, Dialog } 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 { useDisconnectEveryAgentInTeam, 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 { AdmittedClients } from './AdmittedClients.js';
12
+ import { PolicyHistory } from './PolicyHistory.js';
13
+ import { EMPTY_POLICY_DRAFT, PolicyForm, draftOf, policyChanged, rulesFrom, } from './PolicyForm.js';
14
+ /**
15
+ * The form for one team.
16
+ *
17
+ * Its own component so that choosing a different team unmounts it: a form
18
+ * that kept its draft across a change of team would offer to save one
19
+ * team's rules onto another, which is the one mistake on this page nobody
20
+ * would notice until it had happened.
21
+ */
22
+ const TeamPolicyForm = ({ orgUid, teamUid, teamName, readOnly, }) => {
23
+ const { enqueueToast } = useToast();
24
+ const layer = useMcpPolicyLayer('team', teamUid);
25
+ const save = useSetMcpPolicyLayer('team', teamUid);
26
+ const remove = useDeleteMcpPolicyLayer('team', teamUid);
27
+ const [draft, setDraft] = useState(EMPTY_POLICY_DRAFT);
28
+ const [conflict, setConflict] = useState('');
29
+ const [refusal, setRefusal] = useState('');
30
+ const stored = useMemo(() => draftOf(layer.data), [layer.data]);
31
+ useEffect(() => setDraft(stored), [stored]);
32
+ const changed = useMemo(() => policyChanged(draft, stored), [draft, stored]);
33
+ const set = (key, value) => setDraft(current => ({ ...current, [key]: value }));
34
+ const apply = () => {
35
+ const rules = rulesFrom(draft);
36
+ if (typeof rules === 'string') {
37
+ setRefusal(rules);
38
+ return;
39
+ }
40
+ setRefusal('');
41
+ setConflict('');
42
+ save.mutate({ rules, expectedVersion: layer.data?.version }, {
43
+ onSuccess: () => enqueueToast(`${teamName}'s policy saved.`, { variant: 'success' }),
44
+ onError: error => {
45
+ if (error instanceof McpPolicyConflict) {
46
+ setConflict(error.message);
47
+ return;
48
+ }
49
+ enqueueToast(`Could not save: ${error.message}`, {
50
+ variant: 'error',
51
+ });
52
+ },
53
+ });
54
+ };
55
+ if (layer.isPending && layer.data === undefined) {
56
+ return (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 4 }, children: _jsx(Spinner, {}) }));
57
+ }
58
+ 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: () => {
59
+ setConflict('');
60
+ layer.refetch();
61
+ }, 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: {
62
+ maxConcurrentSandboxes: "Counted over this team's own sandboxes, not the organization's " +
63
+ '— so another team being busy never uses up this limit. The ' +
64
+ "organization's cap still applies on top.",
65
+ }, belowAllowedClients: _jsx(AdmittedClients, { scope: "team", subjectUid: teamUid, edited: draft.allowedClients !== stored.allowedClients }) }), !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, {
66
+ onSuccess: () => enqueueToast(`${teamName} narrows nothing of its own.`, {
67
+ variant: 'success',
68
+ }),
69
+ onError: error => enqueueToast(`Could not remove: ${error.message}`, {
70
+ variant: 'error',
71
+ }),
72
+ }), children: "Remove" }) }))] })), !readOnly && _jsx(TeamSessions, { teamUid: teamUid, teamName: teamName }), _jsxs(Box, { sx: {
73
+ borderTop: '1px solid',
74
+ borderColor: 'border.muted',
75
+ pt: 3,
76
+ display: 'grid',
77
+ gap: 2,
78
+ }, 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." })] }));
79
+ };
80
+ /**
81
+ * Ending every session consented in one team.
82
+ *
83
+ * On the team's own page rather than on Connected agents, because that page
84
+ * is a person's list of their own grants — "disconnect all" there means
85
+ * *yours*, and a control that quietly meant a whole team's would be the same
86
+ * word doing two very different things one click apart.
87
+ *
88
+ * It is the team's counterpart of the personal one, and the same authority
89
+ * as removing somebody from the team: IAM asks `_can_manage_team`, so a team
90
+ * owner or the organization's owner may do it and nobody else. Narrow in the
91
+ * way deprovisioning is — no personal agent and no other team's grant is
92
+ * touched.
93
+ *
94
+ * **Not a policy rule, and kept out of the form above on purpose.** Saving a
95
+ * policy is reversible and takes effect on the next call; this ends live
96
+ * sessions now. Folding it into the same Save button would make somebody
97
+ * adjusting a cap sign every one of their team's agents out.
98
+ */
99
+ const TeamSessions = ({ teamUid, teamName, }) => {
100
+ const { enqueueToast } = useToast();
101
+ const disconnect = useDisconnectEveryAgentInTeam();
102
+ const [asking, setAsking] = useState(false);
103
+ const returnFocusRef = useRef(null);
104
+ const confirm = () => {
105
+ disconnect.mutate(teamUid, {
106
+ onSuccess: answer => {
107
+ enqueueToast(answer.revoked === 1
108
+ ? `1 session ended for ${teamName}.`
109
+ : `${answer.revoked} sessions ended for ${teamName}.`, { variant: 'success' });
110
+ setAsking(false);
111
+ },
112
+ onError: error => {
113
+ setAsking(false);
114
+ enqueueToast(`Could not end sessions: ${error.message}`, {
115
+ variant: 'error',
116
+ });
117
+ },
118
+ });
119
+ };
120
+ return (_jsxs(Box, { sx: {
121
+ borderTop: '1px solid',
122
+ borderColor: 'border.muted',
123
+ pt: 3,
124
+ display: 'grid',
125
+ gap: 2,
126
+ }, children: [_jsx(Text, { as: "h3", sx: { fontSize: 1, fontWeight: 'semibold', m: 0 }, children: "Sessions" }), _jsxs(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', m: 0 }, children: ["Every agent connected while acting for ", teamName, " loses its grant at once. Each asks again the next time somebody connects it, and goes through the approval screen rather than being answered from what was agreed before \u2014 so this is also how a fresh approval is forced."] }), _jsx(Box, { children: _jsxs(Button, { variant: "danger", ref: returnFocusRef, onClick: () => setAsking(true), disabled: disconnect.isPending, children: ["End ", teamName, "\u2019s sessions"] }) }), asking && (_jsxs(Dialog, { title: `End every session in ${teamName}?`, onClose: () => setAsking(false), returnFocusRef: returnFocusRef, footerButtons: [
127
+ {
128
+ buttonType: 'default',
129
+ content: 'Keep them',
130
+ onClick: () => setAsking(false),
131
+ },
132
+ {
133
+ buttonType: 'danger',
134
+ content: 'End them',
135
+ onClick: confirm,
136
+ disabled: disconnect.isPending,
137
+ },
138
+ ], children: [_jsxs(Text, { sx: { fontSize: 1 }, children: ["Every grant consented in ", teamName, " ends now, whoever holds it. Work an agent is in the middle of stops where it is."] }), _jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', mt: 2, mb: 0 }, children: "This team only. Nobody\u2019s personal agents end, no other team\u2019s do, and nothing any agent already did is undone." })] }))] }));
139
+ };
140
+ export const TeamPolicies = ({ errorState, orgUid, readOnly = false, showTitle = true, }) => {
141
+ const teams = useOrganizationTeams(orgUid);
142
+ const [chosen, setChosen] = useState('');
143
+ const current = useMemo(() => (teams.data ?? []).find(team => team.uid === chosen) ??
144
+ (teams.data ?? [])[0], [teams.data, chosen]);
145
+ if (teams.isError) {
146
+ return (_jsx(McpErrorBlankslate, { state: errorState(teams.error, "The organization's teams"), onRetry: () => teams.refetch() }));
147
+ }
148
+ if (teams.isPending && !teams.data) {
149
+ return (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 5 }, children: _jsx(Spinner, {}) }));
150
+ }
151
+ if ((teams.data ?? []).length === 0) {
152
+ 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." }) })] }));
153
+ }
154
+ 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 && (
155
+ // Keyed by the team, so choosing another unmounts the form rather
156
+ // than carrying one team's unsaved draft onto the next.
157
+ _jsx(TeamPolicyForm, { orgUid: orgUid, teamUid: current.uid, teamName: current.name, readOnly: readOnly }, current.uid))] }));
158
+ };
159
+ export default TeamPolicies;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * What an agent may actually call, in one space or one organization.
3
+ *
4
+ * A source is not exposed to agents because it exists. Somebody allows a set
5
+ * of its tools on the source, and each session an agent opens narrows that
6
+ * further. This is where those two lists are read together — because the
7
+ * only list that matters is their **intersection**, and neither record shows
8
+ * it on its own.
9
+ *
10
+ * That gap is not theoretical. Contents computes the effective policy as
11
+ * `session ∩ source` and refuses anything outside it, so a tool removed from
12
+ * the source after a session opened goes on sitting in that session's
13
+ * `allowedTools` and is refused at every call. A page that drew the session's
14
+ * list would show a tool the agent cannot use, and the person debugging it
15
+ * would be reading a page that agreed with them.
16
+ *
17
+ * **An empty allowlist allows nothing.** It is not "unrestricted", here or
18
+ * in Contents: `check_tool` refuses every tool not in the list, so a session
19
+ * whose effective set is empty can call none of them. Said plainly on the
20
+ * row, because the opposite reading is the natural one and it is the
21
+ * dangerous direction to be wrong in.
22
+ *
23
+ * @module views/mcp/ToolAccess
24
+ */
25
+ import type { JSX } from 'react';
26
+ import type { ContentSource, McpConfiguration } from '../../api/contents/generated';
27
+ import { type McpErrorStateFn } from './types';
28
+ /**
29
+ * The tools a session can really call: what it was granted, still allowed by
30
+ * the source.
31
+ *
32
+ * The same intersection Contents applies, computed here so the page shows
33
+ * what will happen rather than what was asked for. Sorted, so two sessions
34
+ * of the same source read the same way.
35
+ */
36
+ export declare const effectiveTools: (sessionAllowed: readonly string[] | null | undefined, sourceAllowed: readonly string[] | null | undefined) => string[];
37
+ /**
38
+ * The tools a session still lists that its source has stopped allowing.
39
+ *
40
+ * Worth its own answer rather than a subtraction at the call site: this is
41
+ * the set that makes an agent fail in a way nobody can explain from either
42
+ * record alone, and naming it is the whole reason to read the two together.
43
+ */
44
+ export declare const withdrawnTools: (sessionAllowed: readonly string[] | null | undefined, sourceAllowed: readonly string[] | null | undefined) => string[];
45
+ /** How a source's approval policy reads to somebody deciding whether to trust it. */
46
+ export declare const APPROVAL_POLICY_LOOK: Record<McpConfiguration['approvalPolicy'], {
47
+ label: string;
48
+ variant: 'attention' | 'success' | 'secondary';
49
+ note: string;
50
+ }>;
51
+ /** The MCP configuration of a source, where it has one. */
52
+ export declare const mcpConfigOf: (source: ContentSource) => McpConfiguration | undefined;
53
+ export interface ToolAccessProps {
54
+ /** The application's words for a failed request. */
55
+ errorState: McpErrorStateFn;
56
+ /** One space's sources, rather than every source the caller can see. */
57
+ spaceUid?: string;
58
+ }
59
+ export declare const ToolAccess: ({ errorState, spaceUid, }: ToolAccessProps) => JSX.Element;
60
+ export default ToolAccess;
@@ -0,0 +1,101 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Button, Heading, Label, Spinner, Text, Truncate, } from '@primer/react';
4
+ import { Box } from '@datalayer/primer-addons';
5
+ import { McpErrorBlankslate } from '../../components/mcp/index.js';
6
+ import { useContentSources, useMcpSessions, useMcpTools, useRevokeMcpSession, } from '../../hooks/useContents.js';
7
+ /**
8
+ * The tools a session can really call: what it was granted, still allowed by
9
+ * the source.
10
+ *
11
+ * The same intersection Contents applies, computed here so the page shows
12
+ * what will happen rather than what was asked for. Sorted, so two sessions
13
+ * of the same source read the same way.
14
+ */
15
+ export const effectiveTools = (sessionAllowed, sourceAllowed) => {
16
+ const source = new Set(sourceAllowed ?? []);
17
+ return [...new Set(sessionAllowed ?? [])].filter(tool => source.has(tool)).sort();
18
+ };
19
+ /**
20
+ * The tools a session still lists that its source has stopped allowing.
21
+ *
22
+ * Worth its own answer rather than a subtraction at the call site: this is
23
+ * the set that makes an agent fail in a way nobody can explain from either
24
+ * record alone, and naming it is the whole reason to read the two together.
25
+ */
26
+ export const withdrawnTools = (sessionAllowed, sourceAllowed) => {
27
+ const source = new Set(sourceAllowed ?? []);
28
+ return [...new Set(sessionAllowed ?? [])].filter(tool => !source.has(tool)).sort();
29
+ };
30
+ /** How a source's approval policy reads to somebody deciding whether to trust it. */
31
+ export const APPROVAL_POLICY_LOOK = {
32
+ explicit: {
33
+ label: 'Approval required',
34
+ variant: 'attention',
35
+ note: 'Every call waits for somebody to allow it.',
36
+ },
37
+ 'auto-allowlisted': {
38
+ label: 'Allowlisted',
39
+ variant: 'success',
40
+ note: 'Calls to allowed tools run; anything else is refused.',
41
+ },
42
+ never: {
43
+ label: 'No approval',
44
+ variant: 'secondary',
45
+ note: 'Calls to allowed tools run without asking.',
46
+ },
47
+ };
48
+ /** The MCP configuration of a source, where it has one. */
49
+ export const mcpConfigOf = (source) => source.kind === 'mcp'
50
+ ? source.configuration
51
+ : undefined;
52
+ const SessionRow = ({ session, sourceTools, mayRevoke, onRevoke, revoking, }) => {
53
+ const effective = effectiveTools(session.allowedTools, sourceTools);
54
+ const withdrawn = withdrawnTools(session.allowedTools, sourceTools);
55
+ return (_jsxs(Box, { sx: {
56
+ display: 'grid',
57
+ gap: 1,
58
+ py: 2,
59
+ borderTop: '1px solid',
60
+ borderColor: 'border.muted',
61
+ }, children: [_jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'center', flexWrap: 'wrap' }, children: [_jsx(Label, { size: "small", variant: session.status === 'active' ? 'success' : 'secondary', children: session.status }), _jsx(Truncate, { title: session.actorUid, sx: { fontSize: 0, fontFamily: 'mono', maxWidth: '16rem' }, children: session.actorUid }), session.status === 'active' && mayRevoke && (_jsx(Button, { size: "small", variant: "danger", disabled: revoking, onClick: onRevoke, children: revoking ? 'Revoking…' : 'Revoke' }))] }), effective.length === 0 ? (_jsx(Text, { sx: { fontSize: 0, color: 'attention.fg' }, children: "This session can call nothing. An empty allowlist allows no tool \u2014 it does not mean unrestricted." })) : (_jsx(Box, { sx: { display: 'flex', gap: 1, flexWrap: 'wrap' }, children: effective.map(tool => (_jsx(Label, { size: "small", variant: "secondary", children: tool }, tool))) })), withdrawn.length > 0 && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["Refused at every call, because the source no longer allows", ' ', withdrawn.join(', '), " \u2014 the session still lists it."] }))] }));
62
+ };
63
+ const SourceCard = ({ source, permissions, errorState, }) => {
64
+ const config = mcpConfigOf(source);
65
+ const sourceTools = config?.allowedTools ?? [];
66
+ const sessions = useMcpSessions({ sourceUid: source.uid });
67
+ const revoke = useRevokeMcpSession();
68
+ const manifest = useMcpTools(source.uid);
69
+ const [revoking, setRevoking] = useState('');
70
+ const look = config ? APPROVAL_POLICY_LOOK[config.approvalPolicy] : undefined;
71
+ const offered = manifest.data?.tools?.length ?? 0;
72
+ return (_jsxs(Box, { sx: {
73
+ border: '1px solid',
74
+ borderColor: 'border.default',
75
+ borderRadius: 2,
76
+ p: 3,
77
+ display: 'grid',
78
+ gap: 2,
79
+ minWidth: 0,
80
+ }, children: [_jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'center', flexWrap: 'wrap' }, children: [_jsx(Heading, { as: "h3", sx: { fontSize: 1 }, children: source.name }), look && (_jsx(Label, { size: "small", variant: look.variant, children: look.label })), config?.transport && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: config.transport }))] }), look && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: look.note })), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: sourceTools.length === 0
81
+ ? 'No tool is allowed on this source, so an agent can call none of it.'
82
+ : `${sourceTools.length} of ${offered || sourceTools.length} tools allowed to agents.` }), sourceTools.length > 0 && (_jsx(Box, { sx: { display: 'flex', gap: 1, flexWrap: 'wrap' }, children: [...sourceTools].sort().map(tool => (_jsx(Label, { size: "small", variant: "accent", children: tool }, tool))) })), _jsxs(Box, { children: [_jsx(Heading, { as: "h4", sx: { fontSize: 0, color: 'fg.muted', mb: 1 }, children: "Open sessions" }), sessions.isError ? (_jsx(McpErrorBlankslate, { state: errorState(sessions.error, 'The sessions'), onRetry: () => sessions.refetch() })) : sessions.isPending ? (_jsx(Spinner, { size: "small" })) : (sessions.data?.items.length ?? 0) === 0 ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "No agent has opened this source." })) : ((sessions.data?.items ?? []).map(session => (_jsx(SessionRow, { session: session, sourceTools: sourceTools,
83
+ // Revoking a session withdraws an agent's access to this
84
+ // source, so it follows the source's own write permission
85
+ // rather than being offered to everyone who can read the page.
86
+ mayRevoke: permissions.update || permissions.isOwner, revoking: revoking === session.uid, onRevoke: () => {
87
+ setRevoking(session.uid);
88
+ revoke.mutate(session.uid, {
89
+ onSettled: () => setRevoking(''),
90
+ });
91
+ } }, session.uid))))] })] }));
92
+ };
93
+ export const ToolAccess = ({ errorState, spaceUid, }) => {
94
+ const sources = useContentSources({ kind: 'mcp', ...(spaceUid ? { spaceUid } : {}) });
95
+ // The listing wraps each source with what this caller may do with it, and
96
+ // both halves are used: the source to read the allowlist, the permissions
97
+ // to decide whether revoking is offered at all.
98
+ const items = (sources.data?.items ?? []);
99
+ return (_jsxs(Box, { sx: { display: 'grid', gap: 3, minWidth: 0 }, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Tools" }), _jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', m: 0 }, children: "The MCP sources your agents may reach, the tools allowed on each, and the sessions open against them. A session can only narrow what the source allows, never widen it." })] }), sources.isError ? (_jsx(McpErrorBlankslate, { state: errorState(sources.error, 'The sources'), onRetry: () => sources.refetch() })) : sources.isPending ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 5 }, children: _jsx(Spinner, {}) })) : items.length === 0 ? (_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "No MCP source is connected here. A source has to be created before its tools can be offered to an agent." })) : (items.map(entry => (_jsx(SourceCard, { source: entry.source, permissions: entry.permissions, errorState: errorState }, entry.source.uid))))] }));
100
+ };
101
+ export default ToolAccess;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Where a run's time went.
3
+ *
4
+ * A run crosses four processes — the gateway that accepted the call, the
5
+ * durable engine that recorded it, the worker that executed it, and the
6
+ * sandbox that ran the code — and the question a person actually has when a
7
+ * run took eleven minutes is *which of them* took the eleven minutes. A list
8
+ * of spans does not answer that; the same spans laid against one clock do.
9
+ *
10
+ * **The bars are proportional, the rows are the tree.** Nesting comes from
11
+ * `parent_span_id`, so a step that waited on a sandbox sits under the step
12
+ * that waited, and its bar sits inside its parent's — a gap between a
13
+ * parent's bar and its children's is queue time, which is the thing worth
14
+ * seeing and the thing a table of durations hides.
15
+ *
16
+ * **It draws spans from every service, not the gateway's alone.** The
17
+ * `durable.*` and `runtimes.*` spans are the ones that explain a slow run;
18
+ * showing only what the gateway emitted would show the eleven minutes as one
19
+ * unexplained bar. Services are told apart by colour and named on the row.
20
+ *
21
+ * @module views/mcp/TraceTimeline
22
+ */
23
+ import type { JSX } from 'react';
24
+ import type { OtelSpan } from '../../api/otel/types';
25
+ import type { McpSpanNode } from '../../api/mcp/observability';
26
+ /**
27
+ * The narrowest a bar is drawn, as a percentage of the run.
28
+ *
29
+ * A 2ms authorization check inside a ten-minute run is 0.003% wide, which is
30
+ * nothing at all — and the check happening is exactly what somebody reading
31
+ * a trace is looking for. It is drawn as a mark rather than dropped; the
32
+ * label carries the real duration.
33
+ */
34
+ export declare const MIN_BAR_PERCENT = 0.75;
35
+ /** One span, placed against the run's clock. */
36
+ export interface TimelineRow {
37
+ span: OtelSpan;
38
+ /** How deep in the span tree, for the indent. */
39
+ depth: number;
40
+ /** Where the bar starts, as a percentage of the whole run. */
41
+ left: number;
42
+ /** How wide it is, as a percentage. Never zero — an instant is still a mark. */
43
+ width: number;
44
+ }
45
+ /**
46
+ * The spans of a trace, flattened depth-first and placed against one clock.
47
+ *
48
+ * Three cases are not the ordinary one and each is drawn rather than
49
+ * dropped, because a trace a person opens is a trace they need to read:
50
+ *
51
+ * - a span whose timestamps do not parse is placed at the left as a mark —
52
+ * it happened, we cannot say when;
53
+ * - a trace with no duration at all — one instant, or a single unfinished
54
+ * span — gives every bar the full width, since there is nothing to divide;
55
+ * - a child that starts before its parent, which clock skew between two
56
+ * services makes real, is clamped into the run rather than drawn off the
57
+ * end of it.
58
+ */
59
+ export declare const timelineRows: (tree: McpSpanNode[]) => TimelineRow[];
60
+ /**
61
+ * A colour per service, so the four processes are told apart at a glance.
62
+ *
63
+ * Named by what the service *is* rather than by its span prefix: the same
64
+ * palette has to hold when a fifth service starts emitting, and the fallback
65
+ * is a neutral rather than a collision.
66
+ */
67
+ export declare const SERVICE_TONE: Record<string, string>;
68
+ /** The bar colour of a span, by the service that emitted it and how it ended. */
69
+ export declare const toneOf: (span: OtelSpan) => string;
70
+ export interface TraceTimelineProps {
71
+ /** The spans, already parented — `McpRunTrace.tree`. */
72
+ tree: McpSpanNode[];
73
+ /** The trace these are of, shown so it can be copied into a log query. */
74
+ traceId?: string;
75
+ /** Whether the run is still going, which is why the trace may be short. */
76
+ live?: boolean;
77
+ }
78
+ export declare const TraceTimeline: ({ tree, traceId, live, }: TraceTimelineProps) => JSX.Element;
79
+ /** The timeline under its own heading, as the Runs detail draws it. */
80
+ export declare const TraceTimelineSection: (props: TraceTimelineProps) => JSX.Element;
81
+ export default TraceTimeline;