@datalayer/core 1.1.59 → 1.1.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/api/DatalayerApi.d.ts +42 -1
- package/lib/api/DatalayerApi.js +90 -3
- package/lib/api/constants.d.ts +18 -0
- package/lib/api/constants.js +18 -0
- package/lib/api/contents/attachments.d.ts +9 -0
- package/lib/api/contents/attachments.js +43 -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 +15 -0
- package/lib/api/contents/datasets.js +45 -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 +53 -0
- package/lib/api/contents/sandboxUid.js +78 -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/iam/connectedAgents.d.ts +39 -0
- package/lib/api/iam/connectedAgents.js +52 -0
- package/lib/api/iam/index.d.ts +2 -1
- package/lib/api/iam/index.js +2 -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 +80 -0
- package/lib/api/iam/mcpPolicy.js +132 -0
- package/lib/api/iam/organizationTeams.d.ts +13 -0
- package/lib/api/iam/organizationTeams.js +43 -0
- package/lib/api/iam/serviceAgents.d.ts +68 -0
- package/lib/api/iam/serviceAgents.js +119 -0
- package/lib/api/index.d.ts +4 -1
- package/lib/api/index.js +3 -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 +125 -0
- package/lib/api/mcp/observability.js +254 -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/utils/validation.d.ts +1 -1
- package/lib/api/utils/validation.js +1 -1
- 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/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 +1 -0
- package/lib/components/animation/AnimatedText.js +0 -4
- 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 +18 -1
- package/lib/components/avatars/UserAvatar.js +14 -14
- 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 +10 -0
- package/lib/components/billing/BillingEntitySelect.js +0 -17
- package/lib/components/billing/index.js +0 -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 +31 -0
- package/lib/components/collaboration/LiveEditorCollaborators.js +98 -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 -2
- package/lib/components/display/DatalayerBox.js +6 -6
- 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/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 +10 -0
- package/lib/components/labels/StatusLabels.js +30 -1
- 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 +1 -0
- package/lib/components/principal/PrincipalAppearance.js +0 -8
- package/lib/components/principal/PrincipalAvatar.d.ts +9 -1
- package/lib/components/principal/PrincipalAvatar.js +25 -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 +31 -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 +7 -15
- 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/ScreencaptureButton.d.ts +1 -1
- package/lib/components/sharing/ShareAccessComponent.d.ts +15 -1
- package/lib/components/sharing/ShareAccessComponent.js +36 -23
- package/lib/components/sharing/SharingEditor.d.ts +17 -0
- package/lib/components/sharing/SharingEditor.js +0 -24
- 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/index.d.ts +2 -0
- package/lib/hooks/index.js +2 -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/useCache.d.ts +310 -105
- package/lib/hooks/useCache.js +142 -355
- package/lib/hooks/useContainsFocus.d.ts +1 -1
- package/lib/hooks/useContents.d.ts +313 -0
- package/lib/hooks/useContents.js +964 -0
- package/lib/hooks/useFocusTrap.d.ts +4 -4
- package/lib/hooks/useFocusTrap.js +1 -1
- package/lib/hooks/useMcp.d.ts +229 -0
- package/lib/hooks/useMcp.js +656 -0
- package/lib/hooks/useMobile.js +0 -5
- 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/useToast.js +0 -4
- package/lib/hooks/useUser.js +42 -0
- 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/McpAuditEvent.d.ts +52 -0
- package/lib/models/McpAuditEvent.js +5 -0
- package/lib/models/McpBinding.d.ts +51 -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/StartedBy.d.ts +57 -0
- package/lib/models/StartedBy.js +81 -0
- package/lib/models/UserDTO.js +4 -2
- package/lib/models/contents/__fixtures__/solr-codec.json +57 -0
- package/lib/models/contents/__fixtures__/v1-contracts.json +66 -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/state/substates/CoreState.d.ts +15 -7
- package/lib/state/substates/CoreState.js +18 -14
- package/lib/state/substates/IAMState.d.ts +1 -1
- package/lib/state/substates/IAMState.js +5 -5
- package/lib/state/substates/ProfileState.js +0 -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/WithSuspense.d.ts +1 -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/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/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 +100 -0
- package/lib/views/mcp/EnterpriseConsole.d.ts +74 -0
- package/lib/views/mcp/EnterpriseConsole.js +173 -0
- package/lib/views/mcp/McpDashboard.d.ts +50 -0
- package/lib/views/mcp/McpDashboard.js +347 -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 +50 -0
- package/lib/views/mcp/McpObservability.js +150 -0
- package/lib/views/mcp/OrganizationPolicy.d.ts +45 -0
- package/lib/views/mcp/OrganizationPolicy.js +107 -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 +125 -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 +67 -0
- package/lib/views/mcp/PolicyForm.js +91 -0
- package/lib/views/mcp/PolicyHistory.d.ts +45 -0
- package/lib/views/mcp/PolicyHistory.js +62 -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 +98 -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 +29 -0
- package/lib/views/mcp/index.js +37 -0
- package/lib/views/mcp/types.d.ts +66 -0
- package/lib/views/mcp/types.js +5 -0
- package/lib/views/secrets/SecretEdit.d.ts +5 -1
- package/lib/views/secrets/SecretEdit.js +2 -2
- package/lib/views/secrets/SecretNew.d.ts +11 -1
- package/lib/views/secrets/SecretNew.js +2 -2
- package/lib/views/secrets/Secrets.d.ts +12 -1
- package/lib/views/secrets/Secrets.js +2 -2
- package/package.json +28 -24
- package/scripts/generate-contents-types.py +169 -0
- package/scripts/generate-mcp-types.py +233 -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,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a service agent may be granted.
|
|
3
|
+
*
|
|
4
|
+
* A subset of the OAuth scopes, and deliberately not all of them: the ones
|
|
5
|
+
* about a *person* — reading their profile, acting as them — mean nothing
|
|
6
|
+
* for a principal that is not one, and IAM refuses them. Offering one would
|
|
7
|
+
* invite somebody to grant something that silently does nothing.
|
|
8
|
+
*/
|
|
9
|
+
export declare const SERVICE_AGENT_SCOPES: readonly ["runtimes:read", "runtimes:write", "data:read", "sandboxes:manage"];
|
|
10
|
+
export type ServiceAgentScope = (typeof SERVICE_AGENT_SCOPES)[number];
|
|
11
|
+
export interface ServiceAgent {
|
|
12
|
+
uid: string;
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
/** The team it belongs to, where it is a team's rather than the organization's. */
|
|
16
|
+
teamUid: string;
|
|
17
|
+
/** Space-separated, as the token's `scope` claim carries them. */
|
|
18
|
+
scopes: string;
|
|
19
|
+
/**
|
|
20
|
+
* Revoked rather than removed. Its audit rows name it, and a uid that
|
|
21
|
+
* resolves to nothing makes a year-old row unreadable — so this is a
|
|
22
|
+
* state to render, never a reason to hide the row.
|
|
23
|
+
*/
|
|
24
|
+
revoked: boolean;
|
|
25
|
+
createdBy: string;
|
|
26
|
+
createdAt?: string | null;
|
|
27
|
+
/** When the key was last replaced, so a listing can show a stale one. */
|
|
28
|
+
keyRotatedAt?: string | null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A service agent as it comes back from a write, with the key.
|
|
32
|
+
*
|
|
33
|
+
* The key is present exactly twice in this API — creating and rotating —
|
|
34
|
+
* and nowhere else, ever.
|
|
35
|
+
*/
|
|
36
|
+
export interface ServiceAgentWithKey extends ServiceAgent {
|
|
37
|
+
key: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* One organization's service agents, revoked ones included.
|
|
41
|
+
*
|
|
42
|
+
* Included because hiding them makes a revoked agent invisible to whoever
|
|
43
|
+
* is deciding whether it is still needed, while its audit rows still name
|
|
44
|
+
* it. Any member of the organization may read this; only owners may write.
|
|
45
|
+
*/
|
|
46
|
+
export declare const listServiceAgents: (token: string, orgUid: string, baseUrl?: string) => Promise<ServiceAgent[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Create one. **The key is in this answer and in no other.**
|
|
49
|
+
*
|
|
50
|
+
* Scopes are sent as the array the caller holds; IAM joins and validates
|
|
51
|
+
* them, and refuses one that is not grantable to a principal that is not a
|
|
52
|
+
* person.
|
|
53
|
+
*/
|
|
54
|
+
export declare const createServiceAgent: (token: string, orgUid: string, agent: {
|
|
55
|
+
name: string;
|
|
56
|
+
scopes: string[];
|
|
57
|
+
description?: string;
|
|
58
|
+
teamUid?: string;
|
|
59
|
+
}, baseUrl?: string) => Promise<ServiceAgentWithKey>;
|
|
60
|
+
/**
|
|
61
|
+
* Replace the agent's key. The old one stops working with this call.
|
|
62
|
+
*
|
|
63
|
+
* No grace period, which is the point of rotating: a leaked key that still
|
|
64
|
+
* works for an hour is a leaked key that still works.
|
|
65
|
+
*/
|
|
66
|
+
export declare const rotateServiceAgentKey: (token: string, orgUid: string, agentUid: string, baseUrl?: string) => Promise<ServiceAgentWithKey>;
|
|
67
|
+
/** Stop the agent, keeping it readable for its audit. */
|
|
68
|
+
export declare const revokeServiceAgent: (token: string, orgUid: string, agentUid: string, baseUrl?: string) => Promise<ServiceAgent>;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
7
|
+
* Distributed under the terms of the Modified BSD License.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* An organization's service agents: agents that are principals rather than
|
|
11
|
+
* a person's proxy.
|
|
12
|
+
*
|
|
13
|
+
* A connected agent is a grant — somebody's authority, narrowed to one
|
|
14
|
+
* client, dying with their account. A service agent is the other kind: it
|
|
15
|
+
* belongs to the organization, holds its own key, spends under its own name
|
|
16
|
+
* and outlives whoever set it up. An organization whose nightly pipeline
|
|
17
|
+
* runs on an engineer's grant loses the pipeline when the engineer leaves,
|
|
18
|
+
* and its spend shows against somebody who was asleep.
|
|
19
|
+
*
|
|
20
|
+
* **The key exists in one response and no other.** IAM stores a hash of it,
|
|
21
|
+
* so no later read can return it — `create` and `rotate` carry it and
|
|
22
|
+
* `list` never does. Anything rendering it must say so in the same breath,
|
|
23
|
+
* because somebody who does not know stores nothing and rotates an hour
|
|
24
|
+
* later.
|
|
25
|
+
*
|
|
26
|
+
* @module api/iam/serviceAgents
|
|
27
|
+
*/
|
|
28
|
+
import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
29
|
+
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
30
|
+
/**
|
|
31
|
+
* What a service agent may be granted.
|
|
32
|
+
*
|
|
33
|
+
* A subset of the OAuth scopes, and deliberately not all of them: the ones
|
|
34
|
+
* about a *person* — reading their profile, acting as them — mean nothing
|
|
35
|
+
* for a principal that is not one, and IAM refuses them. Offering one would
|
|
36
|
+
* invite somebody to grant something that silently does nothing.
|
|
37
|
+
*/
|
|
38
|
+
export const SERVICE_AGENT_SCOPES = [
|
|
39
|
+
'runtimes:read',
|
|
40
|
+
'runtimes:write',
|
|
41
|
+
'data:read',
|
|
42
|
+
'sandboxes:manage',
|
|
43
|
+
];
|
|
44
|
+
const fromWire = (agent) => ({
|
|
45
|
+
uid: agent.uid,
|
|
46
|
+
name: agent.name ?? '',
|
|
47
|
+
description: agent.description ?? '',
|
|
48
|
+
teamUid: agent.team_uid ?? '',
|
|
49
|
+
scopes: agent.scopes ?? '',
|
|
50
|
+
revoked: Boolean(agent.revoked),
|
|
51
|
+
createdBy: agent.created_by ?? '',
|
|
52
|
+
createdAt: agent.created_at ?? null,
|
|
53
|
+
keyRotatedAt: agent.key_rotated_at ?? null,
|
|
54
|
+
});
|
|
55
|
+
const withKey = (agent) => ({
|
|
56
|
+
...fromWire(agent),
|
|
57
|
+
key: agent.key ?? '',
|
|
58
|
+
});
|
|
59
|
+
const agentsUrl = (baseUrl, orgUid, suffix = '') => `${baseUrl}${API_BASE_PATHS.IAM}/organizations/${encodeURIComponent(orgUid)}` +
|
|
60
|
+
`/mcp-service-agents${suffix}`;
|
|
61
|
+
/**
|
|
62
|
+
* One organization's service agents, revoked ones included.
|
|
63
|
+
*
|
|
64
|
+
* Included because hiding them makes a revoked agent invisible to whoever
|
|
65
|
+
* is deciding whether it is still needed, while its audit rows still name
|
|
66
|
+
* it. Any member of the organization may read this; only owners may write.
|
|
67
|
+
*/
|
|
68
|
+
export const listServiceAgents = async (token, orgUid, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
69
|
+
const response = await requestDatalayerAPI({
|
|
70
|
+
url: agentsUrl(baseUrl, orgUid),
|
|
71
|
+
method: 'GET',
|
|
72
|
+
token,
|
|
73
|
+
});
|
|
74
|
+
return (response.agents ?? []).map(fromWire);
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Create one. **The key is in this answer and in no other.**
|
|
78
|
+
*
|
|
79
|
+
* Scopes are sent as the array the caller holds; IAM joins and validates
|
|
80
|
+
* them, and refuses one that is not grantable to a principal that is not a
|
|
81
|
+
* person.
|
|
82
|
+
*/
|
|
83
|
+
export const createServiceAgent = async (token, orgUid, agent, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
84
|
+
const response = await requestDatalayerAPI({
|
|
85
|
+
url: agentsUrl(baseUrl, orgUid),
|
|
86
|
+
method: 'POST',
|
|
87
|
+
token,
|
|
88
|
+
body: {
|
|
89
|
+
name: agent.name,
|
|
90
|
+
scopes: agent.scopes,
|
|
91
|
+
description: agent.description ?? '',
|
|
92
|
+
team_uid: agent.teamUid ?? '',
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
return withKey(response.agent ?? { uid: '' });
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Replace the agent's key. The old one stops working with this call.
|
|
99
|
+
*
|
|
100
|
+
* No grace period, which is the point of rotating: a leaked key that still
|
|
101
|
+
* works for an hour is a leaked key that still works.
|
|
102
|
+
*/
|
|
103
|
+
export const rotateServiceAgentKey = async (token, orgUid, agentUid, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
104
|
+
const response = await requestDatalayerAPI({
|
|
105
|
+
url: agentsUrl(baseUrl, orgUid, `/${encodeURIComponent(agentUid)}/rotate`),
|
|
106
|
+
method: 'POST',
|
|
107
|
+
token,
|
|
108
|
+
});
|
|
109
|
+
return withKey(response.agent ?? { uid: agentUid });
|
|
110
|
+
};
|
|
111
|
+
/** Stop the agent, keeping it readable for its audit. */
|
|
112
|
+
export const revokeServiceAgent = async (token, orgUid, agentUid, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
113
|
+
const response = await requestDatalayerAPI({
|
|
114
|
+
url: agentsUrl(baseUrl, orgUid, `/${encodeURIComponent(agentUid)}/revoke`),
|
|
115
|
+
method: 'POST',
|
|
116
|
+
token,
|
|
117
|
+
});
|
|
118
|
+
return fromWire(response.agent ?? { uid: agentUid });
|
|
119
|
+
};
|
package/lib/api/index.d.ts
CHANGED
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module @datalayer/core/api
|
|
8
8
|
*/
|
|
9
|
-
export { requestDatalayerAPI, RunResponseError, NetworkError, } from './DatalayerApi';
|
|
9
|
+
export { requestDatalayerAPI, requestDatalayerAPIWithResponse, RunResponseError, NetworkError, TokenExpiredError, } from './DatalayerApi';
|
|
10
10
|
export type { IRequestDatalayerAPIOptions } from './DatalayerApi';
|
|
11
|
+
export type { IDatalayerAPIResponse } from './DatalayerApi';
|
|
11
12
|
export * as iam from './iam';
|
|
13
|
+
export * as contents from './contents';
|
|
14
|
+
export * as mcp from './mcp';
|
|
12
15
|
export * as otel from './otel';
|
|
13
16
|
export * from '../api/DatalayerApi';
|
package/lib/api/index.js
CHANGED
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
* @module @datalayer/core/api
|
|
12
12
|
*/
|
|
13
13
|
// Base client exports
|
|
14
|
-
export { requestDatalayerAPI, RunResponseError, NetworkError, } from './DatalayerApi.js';
|
|
14
|
+
export { requestDatalayerAPI, requestDatalayerAPIWithResponse, RunResponseError, NetworkError, TokenExpiredError, } from './DatalayerApi.js';
|
|
15
15
|
// Domain-organized API exports
|
|
16
16
|
export * as iam from './iam/index.js';
|
|
17
|
+
export * as contents from './contents/index.js';
|
|
18
|
+
export * as mcp from './mcp/index.js';
|
|
17
19
|
export * as otel from './otel/index.js';
|
|
18
20
|
export * from '../api/DatalayerApi.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { McpAuditEvent } from '../../models/McpAuditEvent';
|
|
2
|
+
import type { McpBinding } from '../../models/McpBinding';
|
|
3
|
+
import type { McpTask } from '../../models/McpTask';
|
|
4
|
+
/** A connected client, as the dashboard shows it, with its last call. */
|
|
5
|
+
export interface McpActiveClient {
|
|
6
|
+
clientId: string;
|
|
7
|
+
clientName?: string | null;
|
|
8
|
+
/** The IAM grant behind the connection, what **Disconnect** revokes. */
|
|
9
|
+
grantUid?: string | null;
|
|
10
|
+
scopes?: string[];
|
|
11
|
+
connectedAt?: string | null;
|
|
12
|
+
lastCall?: McpAuditEvent | null;
|
|
13
|
+
}
|
|
14
|
+
/** Today's counts for the caller, or for the organization. */
|
|
15
|
+
export interface McpActivityCounts {
|
|
16
|
+
calls: number;
|
|
17
|
+
refusals: number;
|
|
18
|
+
tasks: number;
|
|
19
|
+
/** Credits spent by agents today. */
|
|
20
|
+
credits: number;
|
|
21
|
+
}
|
|
22
|
+
export interface McpActivity {
|
|
23
|
+
/** The moment the answer was assembled; the cache is five seconds. */
|
|
24
|
+
at: string;
|
|
25
|
+
orgUid?: string | null;
|
|
26
|
+
clients: McpActiveClient[];
|
|
27
|
+
sandboxes: McpBinding[];
|
|
28
|
+
tasks: McpTask[];
|
|
29
|
+
calls: McpAuditEvent[];
|
|
30
|
+
today: McpActivityCounts;
|
|
31
|
+
}
|
|
32
|
+
export interface McpActivityFilters {
|
|
33
|
+
/** An owner's view of an organization. */
|
|
34
|
+
org?: string;
|
|
35
|
+
team?: string;
|
|
36
|
+
}
|
|
37
|
+
export declare const getMcpActivity: (token: string, filters?: McpActivityFilters, baseUrl?: string) => Promise<McpActivity>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
7
|
+
* Distributed under the terms of the Modified BSD License.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* "What is going on" for the caller, in one answer: the connected clients
|
|
11
|
+
* joined with their last call, the bound sandboxes with their state, the
|
|
12
|
+
* tasks in `working`/`input_required`, the last calls and today's counts.
|
|
13
|
+
*
|
|
14
|
+
* Read from `mcp-gateway`, `mcp-tasks` and `mcp-audit` with bounded
|
|
15
|
+
* queries, cached for five seconds per caller. An owner adds `?org=`.
|
|
16
|
+
*
|
|
17
|
+
* @module api/mcp/activity
|
|
18
|
+
*/
|
|
19
|
+
import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
20
|
+
import { DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
21
|
+
import { fromWire, mcpUrl } from './gateway.js';
|
|
22
|
+
export const getMcpActivity = async (token, filters = {}, baseUrl = DEFAULT_SERVICE_URLS.JUPYTER_MCP_SERVER) => fromWire(await requestDatalayerAPI({
|
|
23
|
+
url: mcpUrl(baseUrl, '/activity', { ...filters }),
|
|
24
|
+
method: 'GET',
|
|
25
|
+
token,
|
|
26
|
+
}));
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface McpAlertRuleTrial {
|
|
2
|
+
/** Whether anything could answer the condition at all. */
|
|
3
|
+
readable: boolean;
|
|
4
|
+
/** The reading, when there was one. */
|
|
5
|
+
value?: number;
|
|
6
|
+
/** Whether the rule would fire on it. */
|
|
7
|
+
wouldFire: boolean;
|
|
8
|
+
/** Why it could not be read, or what the reader had to add. */
|
|
9
|
+
detail: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* What this rule would see now.
|
|
13
|
+
*
|
|
14
|
+
* The organization is the caller's own, whatever is sent — testing another
|
|
15
|
+
* organization's numbers is reading their numbers, and the gateway refuses
|
|
16
|
+
* to do it rather than trusting the body.
|
|
17
|
+
*/
|
|
18
|
+
export declare const testAlertRule: (token: string, rule: {
|
|
19
|
+
condition: string;
|
|
20
|
+
operator: string;
|
|
21
|
+
threshold: number;
|
|
22
|
+
windowSeconds: number;
|
|
23
|
+
scopeKind?: string;
|
|
24
|
+
scopeUid?: string;
|
|
25
|
+
}, mcpServerUrl?: string) => Promise<McpAlertRuleTrial>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
7
|
+
* Distributed under the terms of the Modified BSD License.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Trying a rule before trusting it.
|
|
11
|
+
*
|
|
12
|
+
* The gateway answers what a rule would see *right now*, recording nothing
|
|
13
|
+
* and telling nobody. The question worth asking is not what the number is
|
|
14
|
+
* but whether the condition can be **read at all**: a rule on something
|
|
15
|
+
* nothing reads never fires, and never firing is exactly what a
|
|
16
|
+
* correctly-quiet rule looks like — so writing one and waiting teaches
|
|
17
|
+
* nothing, for as long as somebody is willing to wait.
|
|
18
|
+
*
|
|
19
|
+
* @module api/mcp/alerts
|
|
20
|
+
*/
|
|
21
|
+
import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
22
|
+
import { DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
23
|
+
import { mcpUrl } from './gateway.js';
|
|
24
|
+
/**
|
|
25
|
+
* What this rule would see now.
|
|
26
|
+
*
|
|
27
|
+
* The organization is the caller's own, whatever is sent — testing another
|
|
28
|
+
* organization's numbers is reading their numbers, and the gateway refuses
|
|
29
|
+
* to do it rather than trusting the body.
|
|
30
|
+
*/
|
|
31
|
+
export const testAlertRule = async (token, rule, mcpServerUrl = DEFAULT_SERVICE_URLS.JUPYTER_MCP_SERVER) => {
|
|
32
|
+
const response = await requestDatalayerAPI({
|
|
33
|
+
url: mcpUrl(mcpServerUrl, '/alerts/test'),
|
|
34
|
+
method: 'POST',
|
|
35
|
+
token,
|
|
36
|
+
body: {
|
|
37
|
+
condition: rule.condition,
|
|
38
|
+
operator: rule.operator,
|
|
39
|
+
threshold: rule.threshold,
|
|
40
|
+
window_seconds: rule.windowSeconds,
|
|
41
|
+
scope_kind: rule.scopeKind ?? 'organization',
|
|
42
|
+
scope_uid: rule.scopeUid ?? '',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
readable: Boolean(response.readable),
|
|
47
|
+
value: response.value,
|
|
48
|
+
wouldFire: Boolean(response.would_fire),
|
|
49
|
+
detail: response.detail ?? '',
|
|
50
|
+
};
|
|
51
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { McpAuditDecision, McpAuditEventList, McpAuditExportFormat, McpAuditOutcome } from '../../models/McpAuditEvent';
|
|
2
|
+
export type { McpAuditDecision, McpAuditEvent, McpAuditEventList, McpAuditExportFormat, McpAuditOutcome, McpClientInfo, } from '../../models/McpAuditEvent';
|
|
3
|
+
export interface McpAuditFilters {
|
|
4
|
+
org?: string;
|
|
5
|
+
team?: string;
|
|
6
|
+
/** The `client_id` of the agent, or a service agent's uid. */
|
|
7
|
+
agent?: string;
|
|
8
|
+
user?: string;
|
|
9
|
+
tool?: string;
|
|
10
|
+
method?: string;
|
|
11
|
+
decision?: McpAuditDecision;
|
|
12
|
+
outcome?: McpAuditOutcome;
|
|
13
|
+
/** ISO 8601, UTC. */
|
|
14
|
+
since?: string;
|
|
15
|
+
until?: string;
|
|
16
|
+
taskId?: string;
|
|
17
|
+
traceId?: string;
|
|
18
|
+
cursor?: string;
|
|
19
|
+
limit?: number;
|
|
20
|
+
}
|
|
21
|
+
/** One page of audit rows, newest first. */
|
|
22
|
+
export declare const listAuditEvents: (token: string, filters?: McpAuditFilters, baseUrl?: string) => Promise<McpAuditEventList>;
|
|
23
|
+
/**
|
|
24
|
+
* The rows matching the filters, whole, as one JSONL or CSV document.
|
|
25
|
+
*
|
|
26
|
+
* The cursor of the filters is ignored: an export is everything the filters
|
|
27
|
+
* select, which is what a SIEM or a spreadsheet wants.
|
|
28
|
+
*/
|
|
29
|
+
export declare const exportAuditEvents: (token: string, filters?: Omit<McpAuditFilters, "cursor" | "limit">, format?: McpAuditExportFormat, baseUrl?: string) => Promise<string>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
7
|
+
* Distributed under the terms of the Modified BSD License.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* The audit log of the Jupyter MCP Server, for `organization_security_auditor`s
|
|
11
|
+
* and owners: cursor-paged, exportable as JSONL or CSV.
|
|
12
|
+
*
|
|
13
|
+
* @module api/mcp/audit
|
|
14
|
+
*/
|
|
15
|
+
import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
16
|
+
import { DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
17
|
+
import { fromWire, mcpUrl } from './gateway.js';
|
|
18
|
+
const auditQuery = (filters) => ({
|
|
19
|
+
org: filters.org,
|
|
20
|
+
team: filters.team,
|
|
21
|
+
agent: filters.agent,
|
|
22
|
+
user: filters.user,
|
|
23
|
+
tool: filters.tool,
|
|
24
|
+
method: filters.method,
|
|
25
|
+
decision: filters.decision,
|
|
26
|
+
outcome: filters.outcome,
|
|
27
|
+
since: filters.since,
|
|
28
|
+
until: filters.until,
|
|
29
|
+
task_id: filters.taskId,
|
|
30
|
+
trace_id: filters.traceId,
|
|
31
|
+
cursor: filters.cursor,
|
|
32
|
+
limit: filters.limit,
|
|
33
|
+
});
|
|
34
|
+
/** One page of audit rows, newest first. */
|
|
35
|
+
export const listAuditEvents = async (token, filters = {}, baseUrl = DEFAULT_SERVICE_URLS.JUPYTER_MCP_SERVER) => fromWire(await requestDatalayerAPI({
|
|
36
|
+
url: mcpUrl(baseUrl, '/audit', auditQuery(filters)),
|
|
37
|
+
method: 'GET',
|
|
38
|
+
token,
|
|
39
|
+
}));
|
|
40
|
+
/**
|
|
41
|
+
* The rows matching the filters, whole, as one JSONL or CSV document.
|
|
42
|
+
*
|
|
43
|
+
* The cursor of the filters is ignored: an export is everything the filters
|
|
44
|
+
* select, which is what a SIEM or a spreadsheet wants.
|
|
45
|
+
*/
|
|
46
|
+
export const exportAuditEvents = async (token, filters = {}, format = 'jsonl', baseUrl = DEFAULT_SERVICE_URLS.JUPYTER_MCP_SERVER) => {
|
|
47
|
+
const data = await requestDatalayerAPI({
|
|
48
|
+
url: mcpUrl(baseUrl, '/audit', { ...auditQuery(filters), export: format }),
|
|
49
|
+
method: 'GET',
|
|
50
|
+
token,
|
|
51
|
+
headers: { Accept: format === 'csv' ? 'text/csv' : 'application/x-ndjson' },
|
|
52
|
+
responseType: 'text',
|
|
53
|
+
});
|
|
54
|
+
return typeof data === 'string' ? data : JSON.stringify(data);
|
|
55
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { McpBinding, McpBindingKind, McpBindingList, McpBindingState } from '../../models/McpBinding';
|
|
2
|
+
export type { McpBinding, McpBindingKind, McpBindingList, McpBindingOnLost, McpBindingState, } from '../../models/McpBinding';
|
|
3
|
+
export interface McpBindingListFilters {
|
|
4
|
+
kind?: McpBindingKind;
|
|
5
|
+
state?: McpBindingState;
|
|
6
|
+
/** The `client_id` of the agent holding the handle. */
|
|
7
|
+
agent?: string;
|
|
8
|
+
org?: string;
|
|
9
|
+
cursor?: string;
|
|
10
|
+
limit?: number;
|
|
11
|
+
}
|
|
12
|
+
/** Every handle the caller holds, optionally of one kind. */
|
|
13
|
+
export declare const listBindings: (token: string, filters?: McpBindingListFilters, baseUrl?: string) => Promise<McpBindingList>;
|
|
14
|
+
/**
|
|
15
|
+
* Release a handle. For a sandbox binding this terminates the runtime; a
|
|
16
|
+
* notebook or toolset binding is simply forgotten.
|
|
17
|
+
*/
|
|
18
|
+
export declare const terminateBinding: (token: string, bindingUid: string, baseUrl?: string) => Promise<McpBinding>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
7
|
+
* Distributed under the terms of the Modified BSD License.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* The caller's handles: notebooks, toolsets and the sandbox bindings that
|
|
11
|
+
* are their sessions.
|
|
12
|
+
*
|
|
13
|
+
* `DELETE /bindings/{uid}` on a sandbox binding terminates the runtime
|
|
14
|
+
* through Runtimes and ends the tasks running on it `SANDBOX_LOST`.
|
|
15
|
+
*
|
|
16
|
+
* @module api/mcp/bindings
|
|
17
|
+
*/
|
|
18
|
+
import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
19
|
+
import { DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
20
|
+
import { fromWire, mcpUrl } from './gateway.js';
|
|
21
|
+
/** Every handle the caller holds, optionally of one kind. */
|
|
22
|
+
export const listBindings = async (token, filters = {}, baseUrl = DEFAULT_SERVICE_URLS.JUPYTER_MCP_SERVER) => fromWire(await requestDatalayerAPI({
|
|
23
|
+
url: mcpUrl(baseUrl, '/bindings', {
|
|
24
|
+
kind: filters.kind,
|
|
25
|
+
state: filters.state,
|
|
26
|
+
agent: filters.agent,
|
|
27
|
+
org: filters.org,
|
|
28
|
+
cursor: filters.cursor,
|
|
29
|
+
limit: filters.limit,
|
|
30
|
+
}),
|
|
31
|
+
method: 'GET',
|
|
32
|
+
token,
|
|
33
|
+
}));
|
|
34
|
+
/**
|
|
35
|
+
* Release a handle. For a sandbox binding this terminates the runtime; a
|
|
36
|
+
* notebook or toolset binding is simply forgotten.
|
|
37
|
+
*/
|
|
38
|
+
export const terminateBinding = async (token, bindingUid, baseUrl = DEFAULT_SERVICE_URLS.JUPYTER_MCP_SERVER) => fromWire(await requestDatalayerAPI({
|
|
39
|
+
url: mcpUrl(baseUrl, `/bindings/${encodeURIComponent(bindingUid)}`),
|
|
40
|
+
method: 'DELETE',
|
|
41
|
+
token,
|
|
42
|
+
}));
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface McpForwardingState {
|
|
2
|
+
orgUid: string;
|
|
3
|
+
/** When a batch was last accepted by the destination. */
|
|
4
|
+
lastDeliveredAt?: string | null;
|
|
5
|
+
/** What the destination last said, when it refused. */
|
|
6
|
+
lastError?: string | null;
|
|
7
|
+
lastErrorAt?: string | null;
|
|
8
|
+
delivered: number;
|
|
9
|
+
failed: number;
|
|
10
|
+
/** Whether the last attempt succeeded. */
|
|
11
|
+
healthy: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface McpForwarding {
|
|
14
|
+
/**
|
|
15
|
+
* Whether anything has ever been delivered or attempted.
|
|
16
|
+
*
|
|
17
|
+
* Kept apart from `healthy` because "never attempted" and "working" read
|
|
18
|
+
* the same in a counter — and for an organization that configured a
|
|
19
|
+
* destination, the first is the worse state and the one that looks most
|
|
20
|
+
* like fine.
|
|
21
|
+
*/
|
|
22
|
+
configured: boolean;
|
|
23
|
+
state: McpForwardingState | null;
|
|
24
|
+
}
|
|
25
|
+
export declare const getMcpForwarding: (token: string, org?: string, mcpServerUrl?: string) => Promise<McpForwarding>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
7
|
+
* Distributed under the terms of the Modified BSD License.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Whether an organization's audit is reaching its own system of record.
|
|
11
|
+
*
|
|
12
|
+
* Forwarding never fails the call it describes — an audit row that could not
|
|
13
|
+
* be shipped is still a row, and holding up somebody's tool call because
|
|
14
|
+
* their SIEM is down would be the worse trade. Which means a failure is
|
|
15
|
+
* **invisible unless something reports it**, and a silently dropped record
|
|
16
|
+
* looks exactly like nothing having happened.
|
|
17
|
+
*
|
|
18
|
+
* This is that something.
|
|
19
|
+
*
|
|
20
|
+
* @module api/mcp/forwarding
|
|
21
|
+
*/
|
|
22
|
+
import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
23
|
+
import { DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
24
|
+
import { mcpUrl } from './gateway.js';
|
|
25
|
+
export const getMcpForwarding = async (token, org = '', mcpServerUrl = DEFAULT_SERVICE_URLS.JUPYTER_MCP_SERVER) => {
|
|
26
|
+
const response = await requestDatalayerAPI({
|
|
27
|
+
url: mcpUrl(mcpServerUrl, '/audit/forwarding', org ? { org } : {}),
|
|
28
|
+
method: 'GET',
|
|
29
|
+
token,
|
|
30
|
+
});
|
|
31
|
+
const wire = response.state;
|
|
32
|
+
return {
|
|
33
|
+
configured: Boolean(response.configured),
|
|
34
|
+
state: wire
|
|
35
|
+
? {
|
|
36
|
+
orgUid: wire.org_uid ?? '',
|
|
37
|
+
lastDeliveredAt: wire.last_delivered_at ?? null,
|
|
38
|
+
lastError: wire.last_error ?? null,
|
|
39
|
+
lastErrorAt: wire.last_error_at ?? null,
|
|
40
|
+
delivered: wire.delivered ?? 0,
|
|
41
|
+
failed: wire.failed ?? 0,
|
|
42
|
+
healthy: Boolean(wire.healthy),
|
|
43
|
+
}
|
|
44
|
+
: null,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** The host and scheme of the gateway, without the `/mcp` resource path. */
|
|
2
|
+
export declare const mcpGatewayOrigin: (mcpServerUrl?: string) => string;
|
|
3
|
+
export type McpQuery = Record<string, string | number | boolean | undefined | null>;
|
|
4
|
+
/** A REST route of the gateway, with its query string. */
|
|
5
|
+
export declare const mcpUrl: (mcpServerUrl: string, suffix: string, query?: McpQuery) => string;
|
|
6
|
+
/** A route outside the versioned API: `/api/mcp/version`, `/api/mcp/healthz`. */
|
|
7
|
+
export declare const mcpServiceUrl: (mcpServerUrl: string, suffix: string) => string;
|
|
8
|
+
/**
|
|
9
|
+
* A wire document as a model: snake case to camel case through the envelope,
|
|
10
|
+
* the preserved fields carried as they came.
|
|
11
|
+
*/
|
|
12
|
+
export declare const fromWire: <T>(value: unknown) => T;
|
|
13
|
+
/** A request body as the gateway reads it. */
|
|
14
|
+
export declare const toWire: (value: unknown) => unknown;
|
|
15
|
+
/** For the few answers with no tool-owned field, the Contents converter as is. */
|
|
16
|
+
export declare const fromWireStrict: <T>(value: unknown) => T;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
7
|
+
* Distributed under the terms of the Modified BSD License.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* What every gateway client shares: where the REST routes are, and how a
|
|
11
|
+
* wire document becomes a model.
|
|
12
|
+
*
|
|
13
|
+
* The configured URL is the MCP resource — `https://mcp.datalayer.run/mcp`,
|
|
14
|
+
* the address an agent connects to and the audience a token names. The
|
|
15
|
+
* REST routes live on the same host under `/api/mcp/v1`, so the resource
|
|
16
|
+
* path is taken off before a route is appended.
|
|
17
|
+
*
|
|
18
|
+
* Wire documents are snake case and the models camel case, as with
|
|
19
|
+
* Contents, with one difference: a task's `result` and an audit row's
|
|
20
|
+
* `redactedArguments` are a tool's own — their keys are the tool's
|
|
21
|
+
* argument and output names and must survive as typed — so the envelope is
|
|
22
|
+
* converted around them, never through them.
|
|
23
|
+
*
|
|
24
|
+
* @module api/mcp/gateway
|
|
25
|
+
*/
|
|
26
|
+
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
27
|
+
import { contentsToCamelCase, contentsToSnakeCase } from '../../models/contents/index.js';
|
|
28
|
+
/** The host and scheme of the gateway, without the `/mcp` resource path. */
|
|
29
|
+
export const mcpGatewayOrigin = (mcpServerUrl = DEFAULT_SERVICE_URLS.JUPYTER_MCP_SERVER) => {
|
|
30
|
+
const trimmed = mcpServerUrl.replace(/\/+$/, '');
|
|
31
|
+
return trimmed.endsWith('/mcp') ? trimmed.slice(0, -'/mcp'.length) : trimmed;
|
|
32
|
+
};
|
|
33
|
+
/** A REST route of the gateway, with its query string. */
|
|
34
|
+
export const mcpUrl = (mcpServerUrl, suffix, query = {}) => {
|
|
35
|
+
const parameters = new URLSearchParams();
|
|
36
|
+
for (const [key, value] of Object.entries(query)) {
|
|
37
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
38
|
+
parameters.set(key, String(value));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const search = parameters.toString();
|
|
42
|
+
return `${mcpGatewayOrigin(mcpServerUrl)}${API_BASE_PATHS.MCP}${suffix}${search ? `?${search}` : ''}`;
|
|
43
|
+
};
|
|
44
|
+
/** A route outside the versioned API: `/api/mcp/version`, `/api/mcp/healthz`. */
|
|
45
|
+
export const mcpServiceUrl = (mcpServerUrl, suffix) => `${mcpGatewayOrigin(mcpServerUrl)}/api/mcp${suffix}`;
|
|
46
|
+
/** The fields whose keys belong to a tool, not to the contract. */
|
|
47
|
+
const PRESERVED_FIELDS = new Set(['result', 'redacted_arguments', 'client_info', 'input', 'output']);
|
|
48
|
+
const isObject = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
49
|
+
const camelKey = (key) => key.replace(/_([a-zA-Z0-9])/g, (_, character) => character.toUpperCase());
|
|
50
|
+
/**
|
|
51
|
+
* A wire document as a model: snake case to camel case through the envelope,
|
|
52
|
+
* the preserved fields carried as they came.
|
|
53
|
+
*/
|
|
54
|
+
export const fromWire = (value) => {
|
|
55
|
+
if (Array.isArray(value)) {
|
|
56
|
+
return value.map(item => fromWire(item));
|
|
57
|
+
}
|
|
58
|
+
if (!isObject(value)) {
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
const converted = {};
|
|
62
|
+
for (const [key, item] of Object.entries(value)) {
|
|
63
|
+
converted[camelKey(key)] = PRESERVED_FIELDS.has(key) ? item : fromWire(item);
|
|
64
|
+
}
|
|
65
|
+
return converted;
|
|
66
|
+
};
|
|
67
|
+
/** A request body as the gateway reads it. */
|
|
68
|
+
export const toWire = (value) => contentsToSnakeCase(value);
|
|
69
|
+
/** For the few answers with no tool-owned field, the Contents converter as is. */
|
|
70
|
+
export const fromWireStrict = (value) => contentsToCamelCase(value);
|