@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.
- package/README.md +41 -18
- package/lib/api/DatalayerApi.d.ts +42 -1
- package/lib/api/DatalayerApi.js +90 -3
- package/lib/api/constants.d.ts +19 -1
- package/lib/api/constants.js +19 -1
- package/lib/api/contents/attachments.d.ts +9 -0
- package/lib/api/contents/attachments.js +39 -0
- package/lib/api/contents/bridges.d.ts +22 -0
- package/lib/api/contents/bridges.js +79 -0
- package/lib/api/contents/capabilities.d.ts +11 -0
- package/lib/api/contents/capabilities.js +21 -0
- package/lib/api/contents/cloudStorage.d.ts +31 -0
- package/lib/api/contents/cloudStorage.js +89 -0
- package/lib/api/contents/dataservers.d.ts +37 -0
- package/lib/api/contents/dataservers.js +121 -0
- package/lib/api/contents/datasets.d.ts +63 -0
- package/lib/api/contents/datasets.js +82 -0
- package/lib/api/contents/datasources.d.ts +70 -0
- package/lib/api/contents/datasources.js +149 -0
- package/lib/api/contents/generated.d.ts +1070 -0
- package/lib/api/contents/index.d.ts +16 -0
- package/lib/api/contents/index.js +20 -0
- package/lib/api/contents/mcp.d.ts +46 -0
- package/lib/api/contents/mcp.js +157 -0
- package/lib/api/contents/objects.d.ts +31 -0
- package/lib/api/contents/objects.js +88 -0
- package/lib/api/contents/operations.d.ts +3 -0
- package/lib/api/contents/operations.js +19 -0
- package/lib/api/contents/runtimeMounts.d.ts +40 -0
- package/lib/api/contents/runtimeMounts.js +59 -0
- package/lib/api/contents/sandboxUid.d.ts +21 -0
- package/lib/api/contents/sandboxUid.js +27 -0
- package/lib/api/contents/sources.d.ts +19 -0
- package/lib/api/contents/sources.js +119 -0
- package/lib/api/contents/sync.d.ts +18 -0
- package/lib/api/contents/sync.js +69 -0
- package/lib/api/contents/transfers.d.ts +38 -0
- package/lib/api/contents/transfers.js +123 -0
- package/lib/api/evals/client.d.ts +402 -0
- package/lib/api/evals/client.js +359 -0
- package/lib/api/evals/index.d.ts +10 -0
- package/lib/api/evals/index.js +18 -0
- package/lib/api/evals/request.d.ts +43 -0
- package/lib/api/evals/request.js +67 -0
- package/lib/api/evals/status.d.ts +27 -0
- package/lib/api/evals/status.js +122 -0
- package/lib/api/evals/types.d.ts +1335 -0
- package/lib/api/evals/types.js +5 -0
- package/lib/api/iam/connectedAgents.d.ts +68 -0
- package/lib/api/iam/connectedAgents.js +87 -0
- package/lib/api/iam/identityProviders.d.ts +76 -0
- package/lib/api/iam/identityProviders.js +187 -0
- package/lib/api/iam/index.d.ts +3 -1
- package/lib/api/iam/index.js +3 -1
- package/lib/api/iam/mcpAlertRules.d.ts +51 -0
- package/lib/api/iam/mcpAlertRules.js +198 -0
- package/lib/api/iam/mcpAuditSettings.d.ts +46 -0
- package/lib/api/iam/mcpAuditSettings.js +120 -0
- package/lib/api/iam/mcpPolicy.d.ts +181 -0
- package/lib/api/iam/mcpPolicy.js +168 -0
- package/lib/api/iam/organizationTeams.d.ts +13 -0
- package/lib/api/iam/organizationTeams.js +43 -0
- package/lib/api/iam/profile.d.ts +17 -1
- package/lib/api/iam/profile.js +27 -0
- package/lib/api/iam/scimTokens.d.ts +79 -0
- package/lib/api/iam/scimTokens.js +141 -0
- package/lib/api/iam/secrets.js +9 -21
- package/lib/api/iam/serviceAgents.d.ts +68 -0
- package/lib/api/iam/serviceAgents.js +119 -0
- package/lib/api/iam/trials.d.ts +38 -0
- package/lib/api/iam/trials.js +66 -0
- package/lib/api/index.d.ts +8 -1
- package/lib/api/index.js +7 -1
- package/lib/api/mcp/activity.d.ts +37 -0
- package/lib/api/mcp/activity.js +26 -0
- package/lib/api/mcp/alerts.d.ts +25 -0
- package/lib/api/mcp/alerts.js +51 -0
- package/lib/api/mcp/audit.d.ts +29 -0
- package/lib/api/mcp/audit.js +55 -0
- package/lib/api/mcp/bindings.d.ts +18 -0
- package/lib/api/mcp/bindings.js +42 -0
- package/lib/api/mcp/forwarding.d.ts +25 -0
- package/lib/api/mcp/forwarding.js +46 -0
- package/lib/api/mcp/gateway.d.ts +16 -0
- package/lib/api/mcp/gateway.js +70 -0
- package/lib/api/mcp/generated.d.ts +22 -0
- package/lib/api/mcp/generated.js +213 -0
- package/lib/api/mcp/index.d.ts +17 -0
- package/lib/api/mcp/index.js +25 -0
- package/lib/api/mcp/observability.d.ts +141 -0
- package/lib/api/mcp/observability.js +267 -0
- package/lib/api/mcp/operations.d.ts +83 -0
- package/lib/api/mcp/operations.js +50 -0
- package/lib/api/mcp/organizations.d.ts +102 -0
- package/lib/api/mcp/organizations.js +46 -0
- package/lib/api/mcp/policy.d.ts +9 -0
- package/lib/api/mcp/policy.js +23 -0
- package/lib/api/mcp/tasks.d.ts +49 -0
- package/lib/api/mcp/tasks.js +147 -0
- package/lib/api/orchestration/client.d.ts +53 -0
- package/lib/api/orchestration/client.js +105 -0
- package/lib/api/orchestration/events.d.ts +88 -0
- package/lib/api/orchestration/events.js +245 -0
- package/lib/api/orchestration/generated.d.ts +693 -0
- package/lib/api/orchestration/generated.js +687 -0
- package/lib/api/orchestration/index.d.ts +30 -0
- package/lib/api/orchestration/index.js +34 -0
- package/lib/api/orchestration/lifecycle.d.ts +39 -0
- package/lib/api/orchestration/lifecycle.js +57 -0
- package/lib/api/orchestration/measures.d.ts +55 -0
- package/lib/api/orchestration/measures.js +99 -0
- package/lib/api/otel/dashboards.d.ts +56 -0
- package/lib/api/otel/dashboards.js +50 -0
- package/lib/api/otel/index.d.ts +1 -0
- package/lib/api/otel/index.js +1 -0
- package/lib/api/otel/metrics.d.ts +16 -0
- package/lib/api/otel/metrics.js +15 -0
- package/lib/api/scheduler/client.d.ts +32 -0
- package/lib/api/scheduler/client.js +42 -0
- package/lib/api/scheduler/index.d.ts +8 -0
- package/lib/api/scheduler/index.js +16 -0
- package/lib/api/scheduler/request.d.ts +28 -0
- package/lib/api/scheduler/request.js +50 -0
- package/lib/api/scheduler/types.d.ts +88 -0
- package/lib/api/scheduler/types.js +5 -0
- package/lib/api/spacer/comments.d.ts +97 -0
- package/lib/api/spacer/comments.js +45 -0
- package/lib/api/spacer/index.d.ts +9 -0
- package/lib/api/spacer/index.js +17 -0
- package/lib/api/spacer/notebooks.d.ts +33 -0
- package/lib/api/spacer/notebooks.js +39 -0
- package/lib/api/spacer/request.d.ts +25 -0
- package/lib/api/spacer/request.js +46 -0
- package/lib/api/spacer/spaces.d.ts +68 -0
- package/lib/api/spacer/spaces.js +45 -0
- package/lib/api/utils/validation.d.ts +4 -4
- package/lib/api/utils/validation.js +10 -7
- package/lib/client/auth/index.js +0 -5
- package/lib/client/auth/storage.js +0 -5
- package/lib/client/auth/strategies.js +0 -5
- package/lib/client/base.d.ts +6 -0
- package/lib/client/base.js +8 -0
- package/lib/client/constants.d.ts +1 -0
- package/lib/client/constants.js +1 -0
- package/lib/client/index.d.ts +0 -10
- package/lib/client/index.js +2 -2
- package/lib/client/mixins/ContentsMixin.d.ts +71 -0
- package/lib/client/mixins/ContentsMixin.js +157 -0
- package/lib/client/mixins/IAMMixin.d.ts +0 -31
- package/lib/client/mixins/IAMMixin.js +0 -58
- package/lib/components/animation/AnimatedText.d.ts +2 -44
- package/lib/components/animation/AnimatedText.js +6 -126
- package/lib/components/anonymous/AnonymousKeyExpired.d.ts +56 -0
- package/lib/components/anonymous/AnonymousKeyExpired.js +96 -0
- package/lib/components/anonymous/AnonymousKeyTimer.d.ts +63 -0
- package/lib/components/anonymous/AnonymousKeyTimer.js +140 -0
- package/lib/components/anonymous/index.d.ts +7 -0
- package/lib/components/anonymous/index.js +15 -0
- package/lib/components/auth/SigInAPIKey.d.ts +1 -0
- package/lib/components/auth/SigInAPIKey.js +0 -6
- package/lib/components/auth/SignIn.d.ts +1 -0
- package/lib/components/auth/SignIn.js +0 -4
- package/lib/components/auth/SignIn.stories.d.ts +2 -2
- package/lib/components/avatars/BoringAvatar.d.ts +1 -1
- package/lib/components/avatars/BoringAvatar.stories.d.ts +1 -1
- package/lib/components/avatars/DLAvatar.d.ts +1 -1
- package/lib/components/avatars/DLAvatar.js +0 -4
- package/lib/components/avatars/UserAvatar.d.ts +16 -1
- package/lib/components/avatars/UserAvatar.js +15 -13
- package/lib/components/avatars/UserProfileAvatar.d.ts +1 -1
- package/lib/components/banners/NoAutomationBanner.d.ts +1 -1
- package/lib/components/billing/BillingEntitySelect.d.ts +16 -0
- package/lib/components/billing/BillingEntitySelect.js +49 -27
- package/lib/components/billing/eligibility.d.ts +22 -0
- package/lib/components/billing/eligibility.js +27 -0
- package/lib/components/billing/index.d.ts +1 -0
- package/lib/components/billing/index.js +1 -4
- package/lib/components/buttons/DownloadCSVButton.d.ts +1 -1
- package/lib/components/buttons/DownloadJsonButton.d.ts +1 -1
- package/lib/components/buttons/LongActionButton.d.ts +1 -0
- package/lib/components/buttons/LongActionButton.js +0 -4
- package/lib/components/buttons/UploadButton.d.ts +1 -0
- package/lib/components/buttons/UploadButton.js +0 -4
- package/lib/components/checkout/StripeCheckout.d.ts +1 -1
- package/lib/components/collaboration/LiveEditorCollaborators.d.ts +36 -0
- package/lib/components/collaboration/LiveEditorCollaborators.js +88 -53
- package/lib/components/collaboration/index.js +0 -4
- package/lib/components/confetti/ConfettiSuccess.d.ts +1 -1
- package/lib/components/contents/ContentSourceCard.d.ts +8 -0
- package/lib/components/contents/ContentSourceCard.js +23 -0
- package/lib/components/contents/HomeFolderObjectsBrowser.d.ts +10 -0
- package/lib/components/contents/HomeFolderObjectsBrowser.js +148 -0
- package/lib/components/contents/index.d.ts +2 -0
- package/lib/components/contents/index.js +6 -0
- package/lib/components/context/OrganizationSelect.d.ts +1 -1
- package/lib/components/display/AvatarSkeleton.d.ts +1 -1
- package/lib/components/display/BusyDots.d.ts +1 -1
- package/lib/components/display/CenteredSpinner.d.ts +1 -1
- package/lib/components/display/CodePreview.d.ts +1 -1
- package/lib/components/display/DatalayerBox.d.ts +7 -3
- package/lib/components/display/DatalayerBox.js +7 -7
- package/lib/components/display/HorizontalCenter.d.ts +1 -1
- package/lib/components/display/JupyterDialog.d.ts +1 -0
- package/lib/components/display/JupyterDialog.js +1 -7
- package/lib/components/display/Markdown.d.ts +1 -0
- package/lib/components/display/NavLink.js +3 -2
- package/lib/components/display/NotebookSkeleton.d.ts +1 -1
- package/lib/components/display/Placeholder.d.ts +1 -1
- package/lib/components/display/ToTopBranded.d.ts +1 -1
- package/lib/components/echarts/EChartsReact.d.ts +1 -1
- package/lib/components/flashes/FlashClosable.d.ts +1 -0
- package/lib/components/flashes/FlashClosable.js +0 -4
- package/lib/components/flashes/FlashGuest.d.ts +1 -1
- package/lib/components/flashes/FlashSurveys.d.ts +1 -1
- package/lib/components/flashes/FlashUnauthorized.d.ts +1 -0
- package/lib/components/flashes/FlashUnauthorized.js +0 -6
- package/lib/components/flashes/surveys/Survey2025_1.d.ts +1 -1
- package/lib/components/iam/ExternalTokenSilentLogin.d.ts +1 -1
- package/lib/components/index.d.ts +2 -0
- package/lib/components/index.js +2 -0
- package/lib/components/labels/StatusLabels.d.ts +2 -9
- package/lib/components/labels/StatusLabels.js +2 -26
- package/lib/components/labels/VisibilityLabel.d.ts +1 -1
- package/lib/components/landings/StepBlock.d.ts +1 -1
- package/lib/components/mcp/ClientBadge.d.ts +41 -0
- package/lib/components/mcp/ClientBadge.js +33 -0
- package/lib/components/mcp/McpErrorBlankslate.d.ts +21 -0
- package/lib/components/mcp/McpErrorBlankslate.js +17 -0
- package/lib/components/mcp/ScopeList.d.ts +28 -0
- package/lib/components/mcp/ScopeList.js +14 -0
- package/lib/components/mcp/index.d.ts +10 -0
- package/lib/components/mcp/index.js +18 -0
- package/lib/components/navbar/NavigationVisbilityObserver.d.ts +2 -1
- package/lib/components/navbar/SubdomainNavBar.d.ts +10 -5
- package/lib/components/navbar/SubdomainNavBar.js +2 -1
- package/lib/components/notebooks/JupyterNotebook.d.ts +1 -1
- package/lib/components/notebooks/JupyterNotebookToolbar.d.ts +1 -1
- package/lib/components/principal/PrincipalAppearance.d.ts +22 -42
- package/lib/components/principal/PrincipalAppearance.js +232 -182
- package/lib/components/principal/PrincipalAvatar.d.ts +9 -1
- package/lib/components/principal/PrincipalAvatar.js +18 -10
- package/lib/components/principal/PrincipalBadge.d.ts +1 -1
- package/lib/components/principal/PrincipalBanner.d.ts +1 -1
- package/lib/components/principal/PrincipalDetailsOverlay.d.ts +38 -1
- package/lib/components/principal/PrincipalDetailsOverlay.js +64 -33
- package/lib/components/principal/PrincipalHoverCard.d.ts +31 -0
- package/lib/components/principal/PrincipalHoverCard.js +52 -0
- package/lib/components/principal/PrincipalSwitcherMenu.d.ts +1 -0
- package/lib/components/principal/PrincipalSwitcherMenu.js +5 -14
- package/lib/components/principal/index.d.ts +2 -1
- package/lib/components/principal/index.js +2 -1
- package/lib/components/progress/ConsumptionBar.d.ts +1 -0
- package/lib/components/progress/ConsumptionBar.js +0 -4
- package/lib/components/progress/ProgressRing.d.ts +1 -0
- package/lib/components/progress/SpinnerBar.d.ts +1 -1
- package/lib/components/progress/Timer.d.ts +1 -0
- package/lib/components/progress/Timer.js +0 -4
- package/lib/components/screencapture/Screencapture.js +46 -3
- package/lib/components/screencapture/ScreencaptureButton.d.ts +1 -1
- package/lib/components/sharing/ShareAccessComponent.d.ts +58 -3
- package/lib/components/sharing/ShareAccessComponent.js +143 -98
- package/lib/components/sharing/SharingEditor.d.ts +21 -0
- package/lib/components/sharing/SharingEditor.js +9 -28
- package/lib/components/sharing/index.d.ts +1 -0
- package/lib/components/sharing/index.js +1 -0
- package/lib/components/sharing/sandboxSharing.d.ts +26 -0
- package/lib/components/sharing/sandboxSharing.js +41 -0
- package/lib/components/spaces/SpaceDetailsOverlay.d.ts +39 -0
- package/lib/components/spaces/SpaceDetailsOverlay.js +80 -0
- package/lib/components/spaces/SpaceDisplay.d.ts +38 -0
- package/lib/components/spaces/SpaceDisplay.js +92 -0
- package/lib/components/spaces/index.d.ts +4 -0
- package/lib/components/spaces/index.js +7 -0
- package/lib/components/spaces/spaceDisplayModel.d.ts +93 -0
- package/lib/components/spaces/spaceDisplayModel.js +170 -0
- package/lib/components/sparklines/Sparklines.js +3 -4
- package/lib/components/sparklines/index.js +0 -4
- package/lib/components/storage/ContentsBrowser.d.ts +25 -1
- package/lib/components/storage/ContentsBrowser.js +145 -52
- package/lib/components/storage/ContentsBrowserMock.d.ts +3 -0
- package/lib/components/storage/ContentsBrowserMock.js +75 -0
- package/lib/components/storage/ContentsItems.d.ts +2 -1
- package/lib/components/storage/ContentsItems.js +0 -4
- package/lib/components/storage/ContentsTable.d.ts +50 -0
- package/lib/components/storage/ContentsTable.js +134 -0
- package/lib/components/storage/HomeFolderDrive.d.ts +71 -0
- package/lib/components/storage/HomeFolderDrive.js +248 -0
- package/lib/components/storage/index.d.ts +2 -0
- package/lib/components/storage/index.js +2 -0
- package/lib/components/students/StudentItemStatus.d.ts +1 -1
- package/lib/components/students/StudentResultCircle.d.ts +1 -1
- package/lib/components/subnav/SubNav.d.ts +5 -5
- package/lib/components/subnav/SubNav.js +11 -9
- package/lib/components/tables/DataTable.d.ts +1 -1
- package/lib/components/text-reveal/TextRevealAnimation.d.ts +2 -2
- package/lib/components/text-reveal/useTextRevealAnimationLines.d.ts +1 -1
- package/lib/components/time/LiveRelativeTime.d.ts +1 -0
- package/lib/components/time/LiveRelativeTime.js +0 -8
- package/lib/components/time/index.js +0 -4
- package/lib/components/timeline/Timeline.d.ts +1 -1
- package/lib/components/timeline/index.js +0 -4
- package/lib/components/users/PeerIndicator.d.ts +1 -0
- package/lib/components/users/PeerIndicator.js +0 -4
- package/lib/config/Configuration.d.ts +15 -17
- package/lib/config/Configuration.js +7 -0
- package/lib/hooks/cacheConverters.d.ts +0 -7
- package/lib/hooks/cacheConverters.js +0 -25
- package/lib/hooks/index.d.ts +3 -0
- package/lib/hooks/index.js +3 -0
- package/lib/hooks/layouts/LayoutBackdrop.d.ts +1 -1
- package/lib/hooks/layouts/LayoutScreencapture.d.ts +1 -1
- package/lib/hooks/useBackdrop.d.ts +1 -1
- package/lib/hooks/useBackdropJupyterLab.d.ts +3 -2
- package/lib/hooks/useBackdropJupyterLab.js +0 -4
- package/lib/hooks/useBillingEntityStore.js +3 -0
- package/lib/hooks/useCache.d.ts +478 -130
- package/lib/hooks/useCache.js +1580 -676
- package/lib/hooks/useContainsFocus.d.ts +1 -1
- package/lib/hooks/useContents.d.ts +334 -0
- package/lib/hooks/useContents.js +1033 -0
- package/lib/hooks/useFocusTrap.d.ts +4 -4
- package/lib/hooks/useFocusTrap.js +1 -1
- package/lib/hooks/useMcp.d.ts +315 -0
- package/lib/hooks/useMcp.js +891 -0
- package/lib/hooks/useMobile.js +0 -5
- package/lib/hooks/useNavigate.d.ts +41 -3
- package/lib/hooks/useNavigate.js +106 -52
- package/lib/hooks/usePrincipalCacheStore.js +3 -0
- package/lib/hooks/usePrincipalStore.js +3 -0
- package/lib/hooks/useProjectStore.d.ts +3 -3
- package/lib/hooks/useProjectStore.js +4 -4
- package/lib/hooks/useRef.d.ts +1 -1
- package/lib/hooks/useRef.js +3 -0
- package/lib/hooks/useScreencapture.d.ts +2 -1
- package/lib/hooks/useScreencapture.js +0 -4
- package/lib/hooks/useSpaceCacheStore.d.ts +50 -0
- package/lib/hooks/useSpaceCacheStore.js +85 -0
- package/lib/hooks/useToast.js +0 -4
- package/lib/hooks/useVisibilityObserver.d.ts +1 -1
- package/lib/index.d.ts +4 -1
- package/lib/index.js +3 -1
- package/lib/mocks/components/FlashMock.d.ts +1 -1
- package/lib/mocks/views/ActionMenuMock.d.ts +1 -1
- package/lib/mocks/views/ChartMock.d.ts +1 -1
- package/lib/mocks/views/DashboardMock.d.ts +1 -1
- package/lib/mocks/views/FormMock.d.ts +1 -1
- package/lib/mocks/views/TableMock.d.ts +1 -1
- package/lib/mocks/views/WipMock.d.ts +1 -1
- package/lib/models/Credits.d.ts +16 -0
- package/lib/models/Credits.js +22 -0
- package/lib/models/CreditsDTO.d.ts +6 -5
- package/lib/models/CreditsDTO.js +7 -5
- package/lib/models/McpAuditEvent.d.ts +52 -0
- package/lib/models/McpAuditEvent.js +5 -0
- package/lib/models/McpBinding.d.ts +57 -0
- package/lib/models/McpBinding.js +5 -0
- package/lib/models/McpPolicy.d.ts +77 -0
- package/lib/models/McpPolicy.js +5 -0
- package/lib/models/McpTask.d.ts +94 -0
- package/lib/models/McpTask.js +7 -0
- package/lib/models/Organization.d.ts +69 -0
- package/lib/models/Organization.js +96 -0
- package/lib/models/Secret.d.ts +1 -2
- package/lib/models/Secret.js +2 -18
- package/lib/models/StartedBy.d.ts +91 -0
- package/lib/models/StartedBy.js +117 -0
- package/lib/models/Team.d.ts +2 -0
- package/lib/models/Team.js +2 -0
- package/lib/models/User.d.ts +4 -0
- package/lib/models/User.js +3 -0
- package/lib/models/UserDTO.js +4 -2
- package/lib/models/UserSettings.d.ts +13 -0
- package/lib/models/UserSettings.js +9 -0
- package/lib/models/contents/__fixtures__/solr-codec.json +57 -0
- package/lib/models/contents/__fixtures__/v1-contracts.json +194 -0
- package/lib/models/contents/fieldCase.d.ts +8 -0
- package/lib/models/contents/fieldCase.js +37 -0
- package/lib/models/contents/index.d.ts +2 -0
- package/lib/models/contents/index.js +6 -0
- package/lib/models/contents/permissions.d.ts +16 -0
- package/lib/models/contents/permissions.js +34 -0
- package/lib/models/index.d.ts +5 -1
- package/lib/models/index.js +5 -1
- package/lib/navigation/components.js +2 -3
- package/lib/routes/publicPaths.js +4 -0
- package/lib/state/index.d.ts +1 -0
- package/lib/state/index.js +1 -0
- package/lib/state/sessionEnd.d.ts +55 -0
- package/lib/state/sessionEnd.js +162 -0
- package/lib/state/substates/CoreState.d.ts +15 -7
- package/lib/state/substates/CoreState.js +21 -17
- package/lib/state/substates/IAMState.d.ts +1 -1
- package/lib/state/substates/IAMState.js +12 -5
- package/lib/state/substates/LayoutState.js +12 -0
- package/lib/state/substates/ProfileState.d.ts +1 -0
- package/lib/state/substates/ProfileState.js +1 -4
- package/lib/state/substates/index.d.ts +0 -1
- package/lib/state/substates/index.js +0 -1
- package/lib/utils/Jwt.d.ts +26 -0
- package/lib/utils/Jwt.js +37 -0
- package/lib/utils/Lazy.d.ts +20 -0
- package/lib/utils/Lazy.js +32 -6
- package/lib/utils/Screencapture.js +3 -0
- package/lib/utils/WithSuspense.d.ts +11 -1
- package/lib/utils/WithSuspense.js +11 -1
- package/lib/views/api-keys/APIKeyEdit.d.ts +1 -1
- package/lib/views/api-keys/APIKeyNew.d.ts +1 -1
- package/lib/views/api-keys/APIKeys.d.ts +1 -1
- package/lib/views/api-keys/APIKeys.js +30 -4
- package/lib/views/api-keys/APIKeysStandalone.d.ts +5 -1
- package/lib/views/api-keys/APIKeysStandalone.js +2 -2
- package/lib/views/datasources/DatasourceDetail.d.ts +12 -5
- package/lib/views/datasources/DatasourceDetail.js +80 -110
- package/lib/views/datasources/DatasourceNew.d.ts +14 -8
- package/lib/views/datasources/DatasourceNew.js +129 -118
- package/lib/views/datasources/Datasources.d.ts +39 -7
- package/lib/views/datasources/Datasources.js +95 -40
- package/lib/views/datasources/DatasourcesMock.d.ts +3 -0
- package/lib/views/datasources/DatasourcesMock.js +57 -0
- package/lib/views/iam/SignInSimple.d.ts +12 -0
- package/lib/views/iam/SignInSimple.js +4 -4
- package/lib/views/index.d.ts +1 -0
- package/lib/views/index.js +1 -0
- package/lib/views/mcp/AdmittedClients.d.ts +44 -0
- package/lib/views/mcp/AdmittedClients.js +59 -0
- package/lib/views/mcp/AlertDestinations.d.ts +34 -0
- package/lib/views/mcp/AlertDestinations.js +75 -0
- package/lib/views/mcp/AlertRules.d.ts +32 -0
- package/lib/views/mcp/AlertRules.js +245 -0
- package/lib/views/mcp/ApprovalQueue.d.ts +66 -0
- package/lib/views/mcp/ApprovalQueue.js +95 -0
- package/lib/views/mcp/AuditLog.d.ts +42 -0
- package/lib/views/mcp/AuditLog.js +144 -0
- package/lib/views/mcp/ConnectedAgents.d.ts +34 -0
- package/lib/views/mcp/ConnectedAgents.js +135 -0
- package/lib/views/mcp/EnterpriseConsole.d.ts +74 -0
- package/lib/views/mcp/EnterpriseConsole.js +195 -0
- package/lib/views/mcp/IdentityProviders.d.ts +33 -0
- package/lib/views/mcp/IdentityProviders.js +299 -0
- package/lib/views/mcp/McpDashboard.d.ts +50 -0
- package/lib/views/mcp/McpDashboard.js +430 -0
- package/lib/views/mcp/McpHome.d.ts +92 -0
- package/lib/views/mcp/McpHome.js +153 -0
- package/lib/views/mcp/McpObservability.d.ts +79 -0
- package/lib/views/mcp/McpObservability.js +236 -0
- package/lib/views/mcp/NotebookRuns.d.ts +39 -0
- package/lib/views/mcp/NotebookRuns.js +44 -0
- package/lib/views/mcp/OrganizationPolicy.d.ts +45 -0
- package/lib/views/mcp/OrganizationPolicy.js +108 -0
- package/lib/views/mcp/OrganizationUsage.d.ts +69 -0
- package/lib/views/mcp/OrganizationUsage.js +113 -0
- package/lib/views/mcp/PersonalPolicy.d.ts +54 -0
- package/lib/views/mcp/PersonalPolicy.js +126 -0
- package/lib/views/mcp/Policies.d.ts +53 -0
- package/lib/views/mcp/Policies.js +210 -0
- package/lib/views/mcp/PolicyForm.d.ts +83 -0
- package/lib/views/mcp/PolicyForm.js +113 -0
- package/lib/views/mcp/PolicyHistory.d.ts +58 -0
- package/lib/views/mcp/PolicyHistory.js +75 -0
- package/lib/views/mcp/RunDetail.d.ts +87 -0
- package/lib/views/mcp/RunDetail.js +186 -0
- package/lib/views/mcp/ScimProvisioning.d.ts +54 -0
- package/lib/views/mcp/ScimProvisioning.js +173 -0
- package/lib/views/mcp/ServiceAgents.d.ts +46 -0
- package/lib/views/mcp/ServiceAgents.js +194 -0
- package/lib/views/mcp/TeamPolicies.d.ts +33 -0
- package/lib/views/mcp/TeamPolicies.js +159 -0
- package/lib/views/mcp/ToolAccess.d.ts +60 -0
- package/lib/views/mcp/ToolAccess.js +101 -0
- package/lib/views/mcp/TraceTimeline.d.ts +81 -0
- package/lib/views/mcp/TraceTimeline.js +132 -0
- package/lib/views/mcp/format.d.ts +25 -0
- package/lib/views/mcp/format.js +77 -0
- package/lib/views/mcp/index.d.ts +34 -0
- package/lib/views/mcp/index.js +42 -0
- package/lib/views/mcp/types.d.ts +66 -0
- package/lib/views/mcp/types.js +5 -0
- package/lib/views/otel/simpleAuthStore.js +3 -0
- package/lib/views/secrets/SecretEdit.d.ts +5 -1
- package/lib/views/secrets/SecretEdit.js +5 -4
- package/lib/views/secrets/SecretNew.d.ts +11 -1
- package/lib/views/secrets/SecretNew.js +7 -3
- package/lib/views/secrets/Secrets.d.ts +12 -1
- package/lib/views/secrets/Secrets.js +2 -2
- package/package.json +269 -260
- package/scripts/generate-contents-types.py +169 -0
- package/scripts/generate-mcp-types.py +233 -0
- package/scripts/generate-orchestration-types.py +920 -0
- package/lib/api/iam/datasources.d.ts +0 -86
- package/lib/api/iam/datasources.js +0 -185
- package/lib/components/toolbars/index.d.ts +0 -1
- package/lib/models/Datasource.d.ts +0 -181
- package/lib/models/Datasource.js +0 -154
- package/lib/state/substates/DatasourceState.d.ts +0 -11
- package/lib/state/substates/DatasourceState.js +0 -16
- /package/lib/{components/toolbars/index.js → api/contents/generated.js} +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Button, Heading, IconButton, Link, Text } from '@primer/react';
|
|
4
|
+
import { Box } from '@datalayer/primer-addons';
|
|
5
|
+
import { CheckIcon, CopyIcon, KeyIcon, PlugIcon, PulseIcon, ShareIcon, TelescopeIcon, ToolsIcon, } from '@primer/octicons-react';
|
|
6
|
+
import { useConnectedAgents, useMcpActivity, useMcpMetrics, useTasks, } from '../../hooks/useMcp.js';
|
|
7
|
+
import { useNavigate } from '../../hooks/index.js';
|
|
8
|
+
import { useCoreStore, useIAMStore } from '../../state/index.js';
|
|
9
|
+
import { plural, timeAgo } from './format.js';
|
|
10
|
+
/**
|
|
11
|
+
* The clients the documentation carries a page for, in the order it lists
|
|
12
|
+
* them, with the name `datalayer mcp setup` takes.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* The command that writes a client's configuration.
|
|
16
|
+
*
|
|
17
|
+
* One function rather than the string written wherever it is shown. It is
|
|
18
|
+
* shown in two places that must not disagree — the Access view and the
|
|
19
|
+
* documentation page for each client — and a command a reader copies from
|
|
20
|
+
* the documentation that differs by a word from the one the interface shows
|
|
21
|
+
* is worse than either alone: it is two answers to "what do I run", and no
|
|
22
|
+
* way to tell which is current.
|
|
23
|
+
*/
|
|
24
|
+
export const mcpSetupCommand = (client) => `datalayer mcp setup ${client}`;
|
|
25
|
+
export const MCP_CLIENTS = [
|
|
26
|
+
{ name: 'Claude Code', setup: 'claude-code' },
|
|
27
|
+
{ name: 'Claude Desktop', setup: 'claude-desktop' },
|
|
28
|
+
{ name: 'Codex', setup: 'codex' },
|
|
29
|
+
{ name: 'Cursor', setup: 'cursor' },
|
|
30
|
+
{ name: 'VS Code', setup: 'vscode' },
|
|
31
|
+
{ name: 'Windsurf', setup: 'windsurf' },
|
|
32
|
+
{ name: 'Cline', setup: 'cline' },
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* A line of text with the button that copies it.
|
|
36
|
+
*
|
|
37
|
+
* Exported so the documentation shows a command the same way this view
|
|
38
|
+
* does: a reader who has seen one and then the other should not have to
|
|
39
|
+
* work out whether they are the same affordance.
|
|
40
|
+
*/
|
|
41
|
+
export const Copyable = ({ text }) => {
|
|
42
|
+
const [copied, setCopied] = useState(false);
|
|
43
|
+
return (_jsxs(Box, { sx: {
|
|
44
|
+
display: 'flex',
|
|
45
|
+
alignItems: 'center',
|
|
46
|
+
gap: 2,
|
|
47
|
+
p: 2,
|
|
48
|
+
bg: 'canvas.inset',
|
|
49
|
+
borderRadius: 2,
|
|
50
|
+
minWidth: 0,
|
|
51
|
+
}, children: [_jsx(Text, { sx: {
|
|
52
|
+
fontFamily: 'mono',
|
|
53
|
+
fontSize: 0,
|
|
54
|
+
flex: 1,
|
|
55
|
+
minWidth: 0,
|
|
56
|
+
overflow: 'hidden',
|
|
57
|
+
textOverflow: 'ellipsis',
|
|
58
|
+
whiteSpace: 'nowrap',
|
|
59
|
+
}, children: text }), _jsx(IconButton, { size: "small", variant: "invisible", "aria-label": copied ? 'Copied' : `Copy ${text}`, icon: copied ? CheckIcon : CopyIcon, onClick: () => {
|
|
60
|
+
navigator.clipboard?.writeText(text);
|
|
61
|
+
setCopied(true);
|
|
62
|
+
window.setTimeout(() => setCopied(false), 1500);
|
|
63
|
+
} })] }));
|
|
64
|
+
};
|
|
65
|
+
/** One of the five summaries: a heading, what it holds, and the way in. */
|
|
66
|
+
const Summary = ({ icon: Icon, title, children, action, }) => (_jsxs(Box, { sx: {
|
|
67
|
+
p: 3,
|
|
68
|
+
border: '1px solid',
|
|
69
|
+
borderColor: 'border.default',
|
|
70
|
+
borderRadius: 2,
|
|
71
|
+
display: 'grid',
|
|
72
|
+
gap: 2,
|
|
73
|
+
alignContent: 'start',
|
|
74
|
+
minWidth: 0,
|
|
75
|
+
}, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Icon, { size: 16 }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: title })] }), _jsx(Box, { sx: { fontSize: 0, color: 'fg.muted', display: 'grid', gap: 1 }, children: children }), action && (_jsx(Box, { children: _jsx(Link, { as: "button", sx: { fontSize: 0, cursor: 'pointer' }, onClick: action.onClick, children: action.label }) }))] }));
|
|
76
|
+
export const McpHome = ({ routes, clientDocsBase = '/docs/mcp-clients', showTitle = true, showSummaries = true, showSetup = true, onOpenDocs, }) => {
|
|
77
|
+
const navigate = useNavigate();
|
|
78
|
+
const endpoint = useCoreStore(state => state.configuration.jupyterMcpServerUrl);
|
|
79
|
+
// Whether there is a token, never what it is: this page shows an address
|
|
80
|
+
// and a status, and a credential belongs on neither.
|
|
81
|
+
const signedIn = Boolean(useIAMStore(state => state.token));
|
|
82
|
+
const agents = useConnectedAgents();
|
|
83
|
+
const tasks = useTasks({ limit: 5 });
|
|
84
|
+
const activity = useMcpActivity();
|
|
85
|
+
const metrics = useMcpMetrics();
|
|
86
|
+
const connected = agents.data ?? [];
|
|
87
|
+
const runs = tasks.data?.items ?? [];
|
|
88
|
+
const live = activity.data?.clients.length ?? 0;
|
|
89
|
+
return (_jsxs(Box, { sx: { display: 'grid', gap: 4, minWidth: 0 }, children: [showTitle && (_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "MCP" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "Connect your agents to your notebooks, data and sandboxes through the Model Context Protocol." })] })), showSetup && (_jsxs(_Fragment, { children: [_jsxs(Box, { sx: {
|
|
90
|
+
display: 'flex',
|
|
91
|
+
alignItems: 'center',
|
|
92
|
+
gap: 3,
|
|
93
|
+
flexWrap: 'wrap',
|
|
94
|
+
p: 3,
|
|
95
|
+
borderRadius: 2,
|
|
96
|
+
bg: 'canvas.subtle',
|
|
97
|
+
border: '1px solid',
|
|
98
|
+
borderColor: 'border.default',
|
|
99
|
+
}, children: [_jsx(Text, { sx: { fontSize: 1 }, children: live > 0
|
|
100
|
+
? `${plural(live, 'client')} connected right now.`
|
|
101
|
+
: 'No client is connected right now.' }), _jsx(Button, { size: "small", leadingVisual: PulseIcon, onClick: () => navigate(routes.dashboard), children: "What is going on" })] }), _jsxs(Box, { sx: { display: 'grid', gap: 2 }, children: [_jsx(Heading, { as: "h3", sx: { fontSize: 2 }, children: "The endpoint" }), _jsx(Copyable, { text: endpoint || 'https://mcp.datalayer.run/mcp' }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(KeyIcon, { size: 14 }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: signedIn
|
|
102
|
+
? 'You are signed in, so a client you set up from here authorizes through OAuth without a shared token.'
|
|
103
|
+
: 'Sign in to authorize a client through OAuth; without it a client can only use a personal access token.' })] })] }), _jsxs(Box, { sx: { display: 'grid', gap: 2 }, children: [_jsx(Heading, { as: "h3", sx: { fontSize: 2 }, children: "Set up a client" }), _jsx(Box, { sx: {
|
|
104
|
+
display: 'grid',
|
|
105
|
+
gap: 3,
|
|
106
|
+
gridTemplateColumns: [
|
|
107
|
+
'1fr',
|
|
108
|
+
'repeat(2, 1fr)',
|
|
109
|
+
'repeat(3, 1fr)',
|
|
110
|
+
],
|
|
111
|
+
}, children: MCP_CLIENTS.map(client => (_jsxs(Box, { sx: {
|
|
112
|
+
p: 3,
|
|
113
|
+
border: '1px solid',
|
|
114
|
+
borderColor: 'border.default',
|
|
115
|
+
borderRadius: 2,
|
|
116
|
+
display: 'grid',
|
|
117
|
+
gap: 2,
|
|
118
|
+
minWidth: 0,
|
|
119
|
+
}, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: client.name }), _jsx(Copyable, { text: mcpSetupCommand(client.setup) }), _jsx(Link, { href: `${clientDocsBase}/${client.setup}`, sx: { fontSize: 0, cursor: 'pointer', textAlign: 'left' }, onClick: event => {
|
|
120
|
+
// A modified click is the reader asking for a new tab or
|
|
121
|
+
// window, and `href` is real so it still leads to the
|
|
122
|
+
// full page — for that, for the status bar and for the
|
|
123
|
+
// context menu.
|
|
124
|
+
if (event.metaKey || event.ctrlKey || event.shiftKey) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
event.preventDefault();
|
|
128
|
+
onOpenDocs(`${clientDocsBase}/${client.setup}`);
|
|
129
|
+
}, children: "Configuration and authorization" })] }, client.setup))) })] })] })), showSummaries && (_jsxs(Box, { sx: {
|
|
130
|
+
display: 'grid',
|
|
131
|
+
gap: 3,
|
|
132
|
+
gridTemplateColumns: ['1fr', 'repeat(2, 1fr)', 'repeat(3, 1fr)'],
|
|
133
|
+
}, children: [_jsx(Summary, { icon: PlugIcon, title: "Agents", action: {
|
|
134
|
+
label: 'Connected agents',
|
|
135
|
+
onClick: () => navigate(routes.agents),
|
|
136
|
+
}, children: connected.length === 0 ? (_jsx(Text, { children: "No agent has been authorized yet. Set up a client above and approve the scopes it asks for." })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { children: [plural(connected.length, 'agent'), " authorized."] }), connected.slice(0, 3).map(agent => (_jsxs(Text, { children: [agent.clientName || agent.clientId, " \u2014", ' ', agent.lastUsedAt
|
|
137
|
+
? `used ${timeAgo(agent.lastUsedAt)}`
|
|
138
|
+
: 'never used'] }, agent.uid)))] })) }), _jsx(Summary, { icon: PulseIcon, title: "Runs", action: { label: 'All runs', onClick: () => navigate(routes.runs) }, children: runs.length === 0 ? (_jsx(Text, { children: "Nothing has run yet. A tool call that outlives its request becomes a run you can watch and cancel." })) : (runs.map(task => (_jsxs(Text, { children: [task.tool, " \u2014 ", task.status, " ", timeAgo(task.lastUpdatedAt)] }, task.uid)))) }), _jsxs(Summary, { icon: TelescopeIcon, title: "Observability", action: {
|
|
139
|
+
label: 'Runs and metrics',
|
|
140
|
+
onClick: () => navigate(routes.observability),
|
|
141
|
+
}, children: [_jsx(Text, { children: metrics.data?.slis.samples.calls
|
|
142
|
+
? `${plural(metrics.data.slis.samples.calls, 'call')} measured.`
|
|
143
|
+
: 'No call measured yet.' }), _jsx(Text, { children: metrics.data?.slis.p95CallDurationMs
|
|
144
|
+
? `p95 ${Math.round(metrics.data.slis.p95CallDurationMs)}ms`
|
|
145
|
+
: 'Latency not measured yet.' }), _jsx(Text, { children: metrics.data?.slis.availability === null ||
|
|
146
|
+
metrics.data?.slis.availability === undefined
|
|
147
|
+
? 'Error rate not measured yet.'
|
|
148
|
+
: `${((1 - metrics.data.slis.availability) * 100).toFixed(1)}% of calls failed.` })] }), _jsx(Summary, { icon: ToolsIcon, title: "Tools", children: _jsx(Text, { children: "The toolsets an agent may execute \u2014 the Contents sources you have enabled for it, their tools, their approval policy and their health \u2014 are managed here once toolset bindings ship." }) }), _jsx(Summary, { icon: ShareIcon, title: "Reach", children: _jsx(Text, { children: "Which notebooks and sources an agent can actually reach, as a list you can read at a glance, arrives with sharing to agents as principals." }) }), _jsx(Summary, { icon: KeyIcon, title: "Policies", action: {
|
|
149
|
+
label: 'What applies',
|
|
150
|
+
onClick: () => navigate(routes.policies),
|
|
151
|
+
}, children: _jsx(Text, { children: "What your agents are allowed to do, and which layer decided each rule." }) })] }))] }));
|
|
152
|
+
};
|
|
153
|
+
export default McpHome;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a call ran, as opposed to whether it was allowed.
|
|
3
|
+
*
|
|
4
|
+
* Two panes over the Datalayer OTEL service, read directly with the
|
|
5
|
+
* caller's token: **Runs**, the span tree of one call across the gateway,
|
|
6
|
+
* the policy check and the worker, with the durations that matter called
|
|
7
|
+
* out; and **Metrics**, the four service level indicators and the metric
|
|
8
|
+
* catalog for the caller's agents or, for an owner, the organization.
|
|
9
|
+
*
|
|
10
|
+
* There is no gateway route behind this and no second store: the gateway
|
|
11
|
+
* exports spans, metrics and logs through the collector the platform
|
|
12
|
+
* already runs, and this page queries that. Which is exactly why the page
|
|
13
|
+
* says on itself that it is telemetry — short retention, sampled, no
|
|
14
|
+
* security claim. The audit log is the trail that answers "was this
|
|
15
|
+
* allowed", and every pane links to it.
|
|
16
|
+
*
|
|
17
|
+
* Milestone 1 draws the two panes over synchronous calls. The workflow
|
|
18
|
+
* steps and sandbox spans of a durable task, and the live stream of calls
|
|
19
|
+
* as they land, arrive with milestone 2.
|
|
20
|
+
*
|
|
21
|
+
* @module views/mcp/McpObservability
|
|
22
|
+
*/
|
|
23
|
+
import type { JSX } from 'react';
|
|
24
|
+
import type { McpWorkflowsHealth } from '../../api/mcp/operations';
|
|
25
|
+
import { type McpErrorStateFn, type McpRoutes } from './types';
|
|
26
|
+
export type McpObservabilityPane = 'runs' | 'live' | 'metrics';
|
|
27
|
+
export interface McpObservabilityProps {
|
|
28
|
+
/** The application's words for a failed request. */
|
|
29
|
+
errorState: McpErrorStateFn;
|
|
30
|
+
/** Where this application puts the surfaces this view links to. */
|
|
31
|
+
routes: McpRoutes;
|
|
32
|
+
/** Which pane is open; the address owns it. */
|
|
33
|
+
pane: McpObservabilityPane;
|
|
34
|
+
onPaneChange: (pane: McpObservabilityPane) => void;
|
|
35
|
+
/** The run to open, when the address names one. */
|
|
36
|
+
taskUid?: string;
|
|
37
|
+
/** The trace to open — what a synchronous call leaves behind. */
|
|
38
|
+
traceId?: string;
|
|
39
|
+
/** Asked to write a new selection into the address. */
|
|
40
|
+
onSelect: (selection: {
|
|
41
|
+
task?: string;
|
|
42
|
+
trace?: string;
|
|
43
|
+
}) => void;
|
|
44
|
+
/** One agent's reading, rather than every agent of the caller. */
|
|
45
|
+
agent?: string;
|
|
46
|
+
/** An owner's reading of one organization. */
|
|
47
|
+
org?: string;
|
|
48
|
+
showTitle?: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* What part of the platform a span belongs to, from its name.
|
|
52
|
+
*
|
|
53
|
+
* By prefix rather than by service, because one service emits spans for more
|
|
54
|
+
* than one stage — the gateway does its own policy check — and because a
|
|
55
|
+
* durable run's spans arrive from a process the gateway never talks to. A
|
|
56
|
+
* name nothing recognises gets no label rather than a wrong one: the span is
|
|
57
|
+
* still drawn, still timed, and still named.
|
|
58
|
+
*/
|
|
59
|
+
export declare const stageOf: (name: string) => string;
|
|
60
|
+
/**
|
|
61
|
+
* What the durable engine's own report amounts to, in one line.
|
|
62
|
+
*
|
|
63
|
+
* Three states, not two. "Unreachable" is deliberately not "unhealthy": the
|
|
64
|
+
* gateway answers `/operations/workflows` even when it cannot reach the
|
|
65
|
+
* engine, precisely so an operator can tell "the engine says it is unwell"
|
|
66
|
+
* from "nobody could ask it" — the first is a problem with the engine, the
|
|
67
|
+
* second is usually a problem with the network between them, and sending
|
|
68
|
+
* somebody to the wrong one costs an hour.
|
|
69
|
+
*
|
|
70
|
+
* A healthy engine with a backlog is still healthy, and says so with the
|
|
71
|
+
* backlog beside it: a queue is a queue, not a fault.
|
|
72
|
+
*/
|
|
73
|
+
export declare const engineLook: (health: McpWorkflowsHealth | undefined, failed: boolean) => {
|
|
74
|
+
label: string;
|
|
75
|
+
variant: "success" | "attention" | "danger" | "secondary";
|
|
76
|
+
note: string;
|
|
77
|
+
};
|
|
78
|
+
export declare const McpObservability: ({ errorState, routes, pane, onPaneChange, taskUid, traceId, onSelect, agent, org, showTitle, }: McpObservabilityProps) => JSX.Element;
|
|
79
|
+
export default McpObservability;
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Button, Heading, Label, SegmentedControl, Spinner, Text, TextInput, } from '@primer/react';
|
|
4
|
+
import { Blankslate } from '@primer/react/experimental';
|
|
5
|
+
import { Box } from '@datalayer/primer-addons';
|
|
6
|
+
import { SearchIcon, TelescopeIcon } from '@primer/octicons-react';
|
|
7
|
+
import { McpErrorBlankslate } from '../../components/mcp/index.js';
|
|
8
|
+
import { useMcpMetrics, useMcpTrace, useMcpWorkflowsHealth, useRunTrace, useTasks, } from '../../hooks/useMcp.js';
|
|
9
|
+
import { TraceTimeline } from './TraceTimeline.js';
|
|
10
|
+
import { useNavigate } from '../../hooks/index.js';
|
|
11
|
+
import { MCP_METRIC_CATALOG } from '../../api/mcp/index.js';
|
|
12
|
+
import { durationLabel, timeAgo } from './format.js';
|
|
13
|
+
/**
|
|
14
|
+
* What part of the platform a span belongs to, from its name.
|
|
15
|
+
*
|
|
16
|
+
* By prefix rather than by service, because one service emits spans for more
|
|
17
|
+
* than one stage — the gateway does its own policy check — and because a
|
|
18
|
+
* durable run's spans arrive from a process the gateway never talks to. A
|
|
19
|
+
* name nothing recognises gets no label rather than a wrong one: the span is
|
|
20
|
+
* still drawn, still timed, and still named.
|
|
21
|
+
*/
|
|
22
|
+
export const stageOf = (name) => {
|
|
23
|
+
if (name.startsWith('mcp.policy')) {
|
|
24
|
+
return 'Policy';
|
|
25
|
+
}
|
|
26
|
+
if (name.startsWith('mcp.request')) {
|
|
27
|
+
return 'Gateway';
|
|
28
|
+
}
|
|
29
|
+
if (name.startsWith('sandbox.')) {
|
|
30
|
+
return 'Sandbox';
|
|
31
|
+
}
|
|
32
|
+
if (name.startsWith('durable.')) {
|
|
33
|
+
return 'Workflow';
|
|
34
|
+
}
|
|
35
|
+
// The Runtimes service is where a sandbox is actually started and a kernel
|
|
36
|
+
// actually executes; its spans are the ones that explain a run that spent
|
|
37
|
+
// its eleven minutes somewhere other than this gateway.
|
|
38
|
+
if (name.startsWith('runtimes.')) {
|
|
39
|
+
return 'Runtime';
|
|
40
|
+
}
|
|
41
|
+
return '';
|
|
42
|
+
};
|
|
43
|
+
const SpanRow = ({ node, depth, }) => {
|
|
44
|
+
const stage = stageOf(node.span.span_name);
|
|
45
|
+
const failed = (node.span.status_code ?? '').toUpperCase() === 'ERROR';
|
|
46
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Box, { sx: {
|
|
47
|
+
display: 'flex',
|
|
48
|
+
alignItems: 'center',
|
|
49
|
+
gap: 2,
|
|
50
|
+
py: 1,
|
|
51
|
+
pl: depth * 3,
|
|
52
|
+
borderBottom: '1px solid',
|
|
53
|
+
borderColor: 'border.muted',
|
|
54
|
+
minWidth: 0,
|
|
55
|
+
}, children: [_jsx(Text, { sx: {
|
|
56
|
+
fontSize: 0,
|
|
57
|
+
fontFamily: 'mono',
|
|
58
|
+
flex: 1,
|
|
59
|
+
minWidth: 0,
|
|
60
|
+
overflow: 'hidden',
|
|
61
|
+
textOverflow: 'ellipsis',
|
|
62
|
+
whiteSpace: 'nowrap',
|
|
63
|
+
color: failed ? 'danger.fg' : 'fg.default',
|
|
64
|
+
}, children: node.span.span_name }), stage && (_jsx(Label, { size: "small", variant: "secondary", children: stage })), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: node.span.service_name }), _jsx(Text, { sx: {
|
|
65
|
+
fontSize: 0,
|
|
66
|
+
fontWeight: 'semibold',
|
|
67
|
+
minWidth: 60,
|
|
68
|
+
textAlign: 'right',
|
|
69
|
+
}, children: durationLabel(node.span.duration_ms) })] }), node.children.map(child => (_jsx(SpanRow, { node: child, depth: depth + 1 }, child.span.span_id)))] }));
|
|
70
|
+
};
|
|
71
|
+
/** A number the reader can act on, or a plain statement that it is not measured. */
|
|
72
|
+
const Sli = ({ label, value, note, }) => (_jsxs(Box, { sx: {
|
|
73
|
+
p: 3,
|
|
74
|
+
border: '1px solid',
|
|
75
|
+
borderColor: 'border.default',
|
|
76
|
+
borderRadius: 2,
|
|
77
|
+
minWidth: 0,
|
|
78
|
+
}, children: [_jsx(Text, { sx: { display: 'block', fontSize: 3, fontWeight: 'bold' }, children: value }), _jsx(Text, { sx: { display: 'block', fontSize: 0, color: 'fg.muted' }, children: label }), note && (_jsx(Text, { sx: { display: 'block', fontSize: 0, color: 'fg.subtle' }, children: note }))] }));
|
|
79
|
+
/**
|
|
80
|
+
* What the durable engine's own report amounts to, in one line.
|
|
81
|
+
*
|
|
82
|
+
* Three states, not two. "Unreachable" is deliberately not "unhealthy": the
|
|
83
|
+
* gateway answers `/operations/workflows` even when it cannot reach the
|
|
84
|
+
* engine, precisely so an operator can tell "the engine says it is unwell"
|
|
85
|
+
* from "nobody could ask it" — the first is a problem with the engine, the
|
|
86
|
+
* second is usually a problem with the network between them, and sending
|
|
87
|
+
* somebody to the wrong one costs an hour.
|
|
88
|
+
*
|
|
89
|
+
* A healthy engine with a backlog is still healthy, and says so with the
|
|
90
|
+
* backlog beside it: a queue is a queue, not a fault.
|
|
91
|
+
*/
|
|
92
|
+
export const engineLook = (health, failed) => {
|
|
93
|
+
if (failed) {
|
|
94
|
+
return {
|
|
95
|
+
label: 'Unreachable',
|
|
96
|
+
variant: 'secondary',
|
|
97
|
+
note: 'The gateway could not ask the durable engine how it is. That is a question about the network between them, not about the engine.',
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (!health) {
|
|
101
|
+
return { label: 'Asking…', variant: 'secondary', note: '' };
|
|
102
|
+
}
|
|
103
|
+
const backlog = (health.queues ?? []).reduce((total, queue) => total + (queue.backlog ?? 0), 0);
|
|
104
|
+
if (!health.healthy) {
|
|
105
|
+
return {
|
|
106
|
+
label: 'Unhealthy',
|
|
107
|
+
variant: 'danger',
|
|
108
|
+
note: health.detail || 'The engine reports itself unhealthy.',
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
label: 'Healthy',
|
|
113
|
+
variant: backlog > 0 ? 'attention' : 'success',
|
|
114
|
+
note: backlog > 0
|
|
115
|
+
? `${backlog} ${backlog === 1 ? 'run is' : 'runs are'} waiting to be picked up.`
|
|
116
|
+
: 'Nothing is waiting to be picked up.',
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
const percentLabel = (value) => value === null || value === undefined
|
|
120
|
+
? 'Not measured'
|
|
121
|
+
: `${(value * 100).toFixed(1)}%`;
|
|
122
|
+
export const McpObservability = ({ errorState, routes, pane, onPaneChange, taskUid, traceId, onSelect, agent, org, showTitle = true, }) => {
|
|
123
|
+
const navigate = useNavigate();
|
|
124
|
+
const [find, setFind] = useState(taskUid ?? traceId ?? '');
|
|
125
|
+
// One of the two, never both: a task names its own trace, and a trace
|
|
126
|
+
// names itself.
|
|
127
|
+
const byTask = useRunTrace(taskUid, { enabled: Boolean(taskUid) });
|
|
128
|
+
const byTrace = useMcpTrace(traceId, {
|
|
129
|
+
enabled: Boolean(traceId) && !taskUid,
|
|
130
|
+
});
|
|
131
|
+
const run = taskUid ? byTask : byTrace;
|
|
132
|
+
const metrics = useMcpMetrics({ agent, org });
|
|
133
|
+
// Only while the Live pane is open. A pane nobody is looking at should not
|
|
134
|
+
// be asking the durable engine how it is every thirty seconds.
|
|
135
|
+
const engine = useMcpWorkflowsHealth({ enabled: pane === 'live' });
|
|
136
|
+
const live = useTasks({ status: 'working' }, { enabled: pane === 'live' });
|
|
137
|
+
const telemetryNotice = (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: ["This is telemetry: spans and metrics are sampled, kept for a short time and meant for understanding how a call ran. It is not the record of what was allowed \u2014", ' ', _jsx(Text, { as: "span", sx: { color: 'accent.fg', cursor: 'pointer' }, onClick: () => navigate(routes.audit), children: "the audit log" }), ' ', "is, and it is kept per plan and never changed."] }));
|
|
138
|
+
return (_jsxs(Box, { sx: { display: 'grid', gap: 3, minWidth: 0 }, children: [showTitle && (_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Observability" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "How the calls of your agents ran: where the time went, and how the service is behaving." })] })), _jsxs(SegmentedControl, { "aria-label": "Observability panes", size: "small", children: [_jsx(SegmentedControl.Button, { selected: pane === 'runs', onClick: () => onPaneChange('runs'), children: "Runs" }), _jsx(SegmentedControl.Button, { selected: pane === 'live', onClick: () => onPaneChange('live'), children: "Live" }), _jsx(SegmentedControl.Button, { selected: pane === 'metrics', onClick: () => onPaneChange('metrics'), children: "Metrics" })] }), telemetryNotice, pane === 'runs' && (_jsxs(Box, { sx: { display: 'grid', gap: 3 }, children: [_jsxs(Box, { sx: {
|
|
139
|
+
display: 'flex',
|
|
140
|
+
gap: 2,
|
|
141
|
+
alignItems: 'center',
|
|
142
|
+
flexWrap: 'wrap',
|
|
143
|
+
}, children: [_jsx(TextInput, { size: "small", leadingVisual: SearchIcon, "aria-label": "Task or trace id", placeholder: "Task uid or trace id", value: find, sx: { minWidth: 320 }, onChange: event => setFind(event.currentTarget.value) }), _jsx(Button, { size: "small", onClick: () => {
|
|
144
|
+
const value = find.trim();
|
|
145
|
+
if (!value) {
|
|
146
|
+
onSelect({});
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// A trace id is 32 hexadecimal characters; anything else is a
|
|
150
|
+
// task uid, and the gateway tells us which by answering.
|
|
151
|
+
onSelect(/^[0-9a-f]{32}$/i.test(value)
|
|
152
|
+
? { trace: value }
|
|
153
|
+
: { task: value });
|
|
154
|
+
}, children: "Show the run" })] }), !taskUid && !traceId ? (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(TelescopeIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "Pick a run" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "Open a call from the audit log or the dashboard, or paste its task uid or trace id here, and its spans across the gateway, the policy check and the worker appear with the time each took." }) }), _jsx(Button, { size: "small", onClick: () => navigate(routes.audit), children: "Open the audit log" })] })) : run.isError ? (_jsx(McpErrorBlankslate, { state: errorState(run.error, 'This run'), onRetry: () => run.refetch() })) : run.isPending ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 5 }, children: _jsx(Spinner, {}) })) : (run.data?.spans.length ?? 0) === 0 ? (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(TelescopeIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "No span for this call" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "Spans reach the collector a few seconds after the call and are kept for a short time. A call older than the retention window has an audit row but no trace." }) })] })) : (_jsxs(Box, { sx: { display: 'grid', gap: 2 }, children: [_jsxs(Box, { sx: {
|
|
155
|
+
display: 'flex',
|
|
156
|
+
gap: 3,
|
|
157
|
+
alignItems: 'center',
|
|
158
|
+
flexWrap: 'wrap',
|
|
159
|
+
}, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontFamily: 'mono' }, children: run.data?.traceId }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: [run.data?.spans.length, " spans"] }), _jsx(Button, { size: "small", onClick: () => navigate(`${routes.audit}?trace=${encodeURIComponent(run.data?.traceId ?? '')}`), children: "The audit row" })] }), _jsx(TraceTimeline, { tree: run.data?.tree ?? [] }), _jsx(Box, { sx: {
|
|
160
|
+
border: '1px solid',
|
|
161
|
+
borderColor: 'border.default',
|
|
162
|
+
borderRadius: 2,
|
|
163
|
+
overflowX: 'auto',
|
|
164
|
+
}, children: (run.data?.tree ?? []).map(node => (_jsx(SpanRow, { node: node, depth: 0 }, node.span.span_id))) })] }))] })), pane === 'live' && (_jsxs(Box, { sx: { display: 'grid', gap: 3 }, children: [(() => {
|
|
165
|
+
const look = engineLook(engine.data, engine.isError);
|
|
166
|
+
const queues = engine.data?.queues ?? [];
|
|
167
|
+
return (_jsxs(Box, { sx: {
|
|
168
|
+
border: '1px solid',
|
|
169
|
+
borderColor: 'border.default',
|
|
170
|
+
borderRadius: 2,
|
|
171
|
+
p: 3,
|
|
172
|
+
display: 'grid',
|
|
173
|
+
gap: 2,
|
|
174
|
+
}, children: [_jsxs(Box, { sx: {
|
|
175
|
+
display: 'flex',
|
|
176
|
+
gap: 2,
|
|
177
|
+
alignItems: 'center',
|
|
178
|
+
flexWrap: 'wrap',
|
|
179
|
+
}, children: [_jsx(Heading, { as: "h3", sx: { fontSize: 1 }, children: "The durable engine" }), _jsx(Label, { size: "small", variant: look.variant, children: look.label }), engine.data?.engine && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: engine.data.engine }))] }), look.note && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: look.note })), queues.length > 0 && (_jsx(Box, { sx: { display: 'grid', gap: 1 }, children: queues.map(queue => (_jsxs(Box, { sx: {
|
|
180
|
+
display: 'flex',
|
|
181
|
+
gap: 2,
|
|
182
|
+
alignItems: 'center',
|
|
183
|
+
fontSize: 0,
|
|
184
|
+
}, children: [_jsx(Text, { sx: { fontFamily: 'mono' }, children: queue.name }), _jsxs(Text, { sx: { color: 'fg.muted' }, children: [queue.backlog, " waiting"] }), typeof queue.oldestWaitSeconds === 'number' && (_jsxs(Text, { sx: { color: 'fg.muted' }, children: ["oldest", ' ', durationLabel(queue.oldestWaitSeconds * 1000)] }))] }, queue.name))) }))] }));
|
|
185
|
+
})(), _jsxs(Box, { sx: { display: 'grid', gap: 2 }, children: [_jsx(Heading, { as: "h3", sx: { fontSize: 1 }, children: "Running now" }), live.isError ? (_jsx(McpErrorBlankslate, { state: errorState(live.error, 'The running calls'), onRetry: () => live.refetch() })) : live.isPending ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 4 }, children: _jsx(Spinner, {}) })) : (live.data?.items.length ?? 0) === 0 ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Nothing of yours is running. A call that finishes inside its own request never appears here \u2014 it is over before this pane could draw it \u2014 and is found by its trace in Runs." })) : ((live.data?.items ?? []).map(task => (_jsxs(Box, { sx: {
|
|
186
|
+
display: 'flex',
|
|
187
|
+
gap: 2,
|
|
188
|
+
alignItems: 'center',
|
|
189
|
+
flexWrap: 'wrap',
|
|
190
|
+
py: 1,
|
|
191
|
+
borderBottom: '1px solid',
|
|
192
|
+
borderColor: 'border.muted',
|
|
193
|
+
}, children: [_jsx(Label, { size: "small", variant: "success", children: "Working" }), _jsx(Text, { sx: { fontSize: 0 }, children: task.tool || 'Run' }), _jsx(Text, { sx: {
|
|
194
|
+
fontSize: 0,
|
|
195
|
+
fontFamily: 'mono',
|
|
196
|
+
color: 'accent.fg',
|
|
197
|
+
cursor: 'pointer',
|
|
198
|
+
}, onClick: () => onSelect({ task: task.uid }), children: task.uid }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["started ", timeAgo(task.createdAt)] })] }, task.uid))))] })] })), pane === 'metrics' && (_jsx(Box, { sx: { display: 'grid', gap: 3 }, children: metrics.isError ? (_jsx(McpErrorBlankslate, { state: errorState(metrics.error, 'Metrics'), onRetry: () => metrics.refetch() })) : metrics.isPending && !metrics.data ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 5 }, children: _jsx(Spinner, {}) })) : (_jsxs(_Fragment, { children: [_jsxs(Box, { sx: {
|
|
199
|
+
display: 'grid',
|
|
200
|
+
gap: 3,
|
|
201
|
+
gridTemplateColumns: [
|
|
202
|
+
'1fr',
|
|
203
|
+
'repeat(2, 1fr)',
|
|
204
|
+
'repeat(4, 1fr)',
|
|
205
|
+
],
|
|
206
|
+
}, children: [_jsx(Sli, { label: "Availability", value: percentLabel(metrics.data?.slis.availability), note: `${metrics.data?.slis.samples.calls ?? 0} calls` }), _jsx(Sli, { label: "Call latency, p95", value: metrics.data?.slis.p95CallDurationMs === null ||
|
|
207
|
+
metrics.data?.slis.p95CallDurationMs === undefined
|
|
208
|
+
? 'Not measured'
|
|
209
|
+
: durationLabel(metrics.data.slis.p95CallDurationMs) }), _jsx(Sli, { label: "Task success", value: percentLabel(metrics.data?.slis.taskSuccessRate), note: `${metrics.data?.slis.samples.tasks ?? 0} tasks` }), _jsx(Sli, { label: "Sandbox launch, p95", value: Object.keys(metrics.data?.slis.p95SandboxLaunchSeconds ?? {}).length === 0
|
|
210
|
+
? 'Not measured'
|
|
211
|
+
: Object.entries(metrics.data?.slis.p95SandboxLaunchSeconds ?? {})
|
|
212
|
+
.map(([provider, seconds]) => `${provider} ${seconds.toFixed(1)}s`)
|
|
213
|
+
.join(' · '), note: `${metrics.data?.slis.samples.launches ?? 0} launches` })] }), _jsx(Box, { sx: {
|
|
214
|
+
border: '1px solid',
|
|
215
|
+
borderColor: 'border.default',
|
|
216
|
+
borderRadius: 2,
|
|
217
|
+
overflowX: 'auto',
|
|
218
|
+
}, children: MCP_METRIC_CATALOG.map(name => {
|
|
219
|
+
const reporting = metrics.data?.reporting.includes(name) ?? false;
|
|
220
|
+
return (_jsxs(Box, { sx: {
|
|
221
|
+
display: 'flex',
|
|
222
|
+
alignItems: 'center',
|
|
223
|
+
gap: 3,
|
|
224
|
+
py: 1,
|
|
225
|
+
px: 2,
|
|
226
|
+
borderBottom: '1px solid',
|
|
227
|
+
borderColor: 'border.muted',
|
|
228
|
+
}, children: [_jsx(Text, { sx: { fontSize: 0, fontFamily: 'mono', flex: 1 }, children: name }), _jsx(Text, { sx: {
|
|
229
|
+
fontSize: 0,
|
|
230
|
+
color: reporting ? 'success.fg' : 'fg.muted',
|
|
231
|
+
}, children: reporting ? 'reporting' : 'no point' })] }, name));
|
|
232
|
+
}) }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: ["Metrics carry no user, agent or organization label by design, so a per-agent reading is computed from the request spans, which do.", metrics.data?.spans.length
|
|
233
|
+
? ` ${metrics.data.spans.length} spans read.`
|
|
234
|
+
: ''] })] })) }))] }));
|
|
235
|
+
};
|
|
236
|
+
export default McpObservability;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runs of one notebook, beside the notebook.
|
|
3
|
+
*
|
|
4
|
+
* A run outlives the call that started it, so the agent that asked is
|
|
5
|
+
* usually gone — and the person who notices is the one looking at the
|
|
6
|
+
* notebook. `/mcp/runs` lists every run they own; this answers the narrower
|
|
7
|
+
* question they actually have in front of them: what is happening to *this*
|
|
8
|
+
* notebook, right now.
|
|
9
|
+
*
|
|
10
|
+
* It lists rather than acts. Cancelling and answering live on the run's own
|
|
11
|
+
* page, next to the output that gives the question its context; a second set
|
|
12
|
+
* of buttons here would be a second implementation of the same two calls,
|
|
13
|
+
* and a panel beside a notebook is a poor place to decide to stop something
|
|
14
|
+
* you cannot see the output of.
|
|
15
|
+
*
|
|
16
|
+
* @module views/mcp/NotebookRuns
|
|
17
|
+
*/
|
|
18
|
+
import type { JSX } from 'react';
|
|
19
|
+
import type { McpTask } from '../../models/McpTask';
|
|
20
|
+
import { type McpRoutes } from './types';
|
|
21
|
+
/**
|
|
22
|
+
* The runs worth a person's attention first.
|
|
23
|
+
*
|
|
24
|
+
* A notebook accumulates finished runs and keeps only one or two live ones,
|
|
25
|
+
* so ordering by time alone buries the live ones under yesterday's. Waiting
|
|
26
|
+
* first, then working, then whatever finished most recently — the same order
|
|
27
|
+
* the Runs panel uses, for the same reason.
|
|
28
|
+
*/
|
|
29
|
+
export declare const orderedRuns: (tasks: McpTask[]) => McpTask[];
|
|
30
|
+
export interface NotebookRunsProps {
|
|
31
|
+
/** The notebook whose runs these are. */
|
|
32
|
+
notebookUid: string;
|
|
33
|
+
/** Where this application puts the surfaces this view links to. */
|
|
34
|
+
routes: McpRoutes;
|
|
35
|
+
/** How many to draw; a rail, not a page. */
|
|
36
|
+
limit?: number;
|
|
37
|
+
}
|
|
38
|
+
export declare const NotebookRuns: ({ notebookUid, routes, limit, }: NotebookRunsProps) => JSX.Element;
|
|
39
|
+
export default NotebookRuns;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Heading, Label, Link, RelativeTime, Spinner, Text, } from '@primer/react';
|
|
3
|
+
import { Box } from '@datalayer/primer-addons';
|
|
4
|
+
import { useNotebookTasks } from '../../hooks/useMcp.js';
|
|
5
|
+
import { RUN_STATUS_LOOK, isRunOver } from './RunDetail.js';
|
|
6
|
+
/**
|
|
7
|
+
* The runs worth a person's attention first.
|
|
8
|
+
*
|
|
9
|
+
* A notebook accumulates finished runs and keeps only one or two live ones,
|
|
10
|
+
* so ordering by time alone buries the live ones under yesterday's. Waiting
|
|
11
|
+
* first, then working, then whatever finished most recently — the same order
|
|
12
|
+
* the Runs panel uses, for the same reason.
|
|
13
|
+
*/
|
|
14
|
+
export const orderedRuns = (tasks) => {
|
|
15
|
+
const rank = (task) => {
|
|
16
|
+
if (task.status === 'input_required') {
|
|
17
|
+
return 0;
|
|
18
|
+
}
|
|
19
|
+
return isRunOver(task.status) ? 2 : 1;
|
|
20
|
+
};
|
|
21
|
+
return [...tasks].sort((left, right) => rank(left) - rank(right) ||
|
|
22
|
+
right.lastUpdatedAt.localeCompare(left.lastUpdatedAt));
|
|
23
|
+
};
|
|
24
|
+
export const NotebookRuns = ({ notebookUid, routes, limit = 20, }) => {
|
|
25
|
+
const runs = useNotebookTasks(notebookUid);
|
|
26
|
+
const tasks = orderedRuns(runs.data?.items ?? []).slice(0, limit);
|
|
27
|
+
if (runs.isLoading) {
|
|
28
|
+
return (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', p: 3 }, children: _jsx(Spinner, { size: "small" }) }));
|
|
29
|
+
}
|
|
30
|
+
return (_jsxs(Box, { sx: { display: 'grid', gap: 2, minWidth: 0 }, children: [_jsx(Heading, { as: "h3", sx: { fontSize: 1 }, children: "Runs" }), tasks.length === 0 ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Nothing has run on this notebook yet. A tool call that outlives its request appears here while it runs." })) : (tasks.map(task => {
|
|
31
|
+
const look = RUN_STATUS_LOOK[task.status];
|
|
32
|
+
return (_jsxs(Box, { sx: {
|
|
33
|
+
display: 'grid',
|
|
34
|
+
gap: 1,
|
|
35
|
+
p: 2,
|
|
36
|
+
borderRadius: 2,
|
|
37
|
+
border: '1px solid',
|
|
38
|
+
borderColor: task.status === 'input_required'
|
|
39
|
+
? 'attention.emphasis'
|
|
40
|
+
: 'border.default',
|
|
41
|
+
}, children: [_jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'center' }, children: [_jsx(Label, { size: "small", variant: look.variant, children: look.label }), _jsx(Text, { sx: { fontSize: 0 }, children: task.tool || 'Run' })] }), _jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'center' }, children: [_jsxs(Link, { href: `${routes.runs}/${encodeURIComponent(task.uid)}`, sx: { fontFamily: 'mono', fontSize: 0 }, children: [task.uid.slice(0, 16), "\u2026"] }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: _jsx(RelativeTime, { datetime: task.lastUpdatedAt }) })] })] }, task.uid));
|
|
42
|
+
}))] }));
|
|
43
|
+
};
|
|
44
|
+
export default NotebookRuns;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an organization narrows for its agents, and the form that writes it.
|
|
3
|
+
*
|
|
4
|
+
* The sibling `Policies` view is the *read*: every layer intersected, with
|
|
5
|
+
* the layer that decided each rule. This is the *write*, and only one
|
|
6
|
+
* layer's — an organization owner cannot edit the platform's defaults or
|
|
7
|
+
* somebody's personal rules, and would not want to.
|
|
8
|
+
*
|
|
9
|
+
* Three things this page owes the person filling it in:
|
|
10
|
+
*
|
|
11
|
+
* **Only rules the gateway enforces.** IAM refuses anything else, so a form
|
|
12
|
+
* offering more would collect a setting that is thrown away at the write —
|
|
13
|
+
* and `toolDenyList` would read as a working denylist rather than a typo.
|
|
14
|
+
* The fields come from `MCP_POLICY_RULES` so the form cannot drift.
|
|
15
|
+
*
|
|
16
|
+
* **An empty allowlist is not an allowlist.** Leaving the field blank means
|
|
17
|
+
* "I have not set one", not "nothing is permitted" — the second would stop
|
|
18
|
+
* every agent in the organization, and the first conclusion anybody draws
|
|
19
|
+
* from that is that the platform is down. The captions say so where
|
|
20
|
+
* somebody is about to make that mistake.
|
|
21
|
+
*
|
|
22
|
+
* **A limit of zero is refused rather than stored.** The gateway reads a
|
|
23
|
+
* non-positive cap as *no cap*, so a zero written to stop an organization's
|
|
24
|
+
* agents lifts its limit instead — the one value whose stored meaning is the
|
|
25
|
+
* opposite of its plain reading.
|
|
26
|
+
*
|
|
27
|
+
* @module views/mcp/OrganizationPolicy
|
|
28
|
+
*/
|
|
29
|
+
import type { JSX } from 'react';
|
|
30
|
+
import type { McpErrorStateFn } from './types';
|
|
31
|
+
export interface OrganizationPolicyProps {
|
|
32
|
+
/** The application's words for a failed request. */
|
|
33
|
+
errorState: McpErrorStateFn;
|
|
34
|
+
/** The organization whose layer this is. */
|
|
35
|
+
orgUid: string;
|
|
36
|
+
/**
|
|
37
|
+
* Read-only for anybody who is not an owner. IAM refuses their writes
|
|
38
|
+
* either way; this keeps the page from offering an action that would be
|
|
39
|
+
* refused.
|
|
40
|
+
*/
|
|
41
|
+
readOnly?: boolean;
|
|
42
|
+
showTitle?: boolean;
|
|
43
|
+
}
|
|
44
|
+
export declare const OrganizationPolicy: ({ errorState, orgUid, readOnly, showTitle, }: OrganizationPolicyProps) => JSX.Element;
|
|
45
|
+
export default OrganizationPolicy;
|