@datalayer/agent-runtimes 1.3.10 → 1.3.11
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/lib/api/runtimes/environments.d.ts +22 -1
- package/lib/api/runtimes/environments.js +31 -0
- package/lib/chat/ChatFloating.d.ts +8 -1
- package/lib/chat/ChatFloating.js +5 -2
- package/lib/chat/display/ButtonGlow.d.ts +9 -0
- package/lib/chat/display/ButtonGlow.js +60 -0
- package/lib/chat/display/EmptyState.js +4 -1
- package/lib/chat/header/ChatHeaderBase.js +4 -56
- package/lib/chat/header/ChatViewModeToggle.d.ts +29 -0
- package/lib/chat/header/ChatViewModeToggle.js +55 -0
- package/lib/chat/index.d.ts +1 -0
- package/lib/chat/index.js +1 -0
- package/lib/components/code-sandboxes/CodeSandboxLauncher.d.ts +8 -0
- package/lib/components/code-sandboxes/CodeSandboxLauncher.js +54 -5
- package/lib/components/code-sandboxes/codeSandboxEnvironments.d.ts +12 -1
- package/lib/components/code-sandboxes/codeSandboxEnvironments.js +38 -1
- package/lib/components/icons/ArtifactIcon.js +2 -1
- package/lib/examples/DecksAgent.d.ts +1 -1
- package/lib/examples/DecksAgent.js +1 -1
- package/lib/loop/core/index.d.ts +11 -2
- package/lib/loop/embed/LoopEmbed.js +6 -0
- package/lib/loop/plugins/chat/ChatView.js +14 -5
- package/lib/loop/plugins/page-layout/index.d.ts +36 -0
- package/lib/loop/plugins/page-layout/index.js +87 -7
- package/lib/loop/presets.d.ts +14 -0
- package/lib/loop/presets.js +3 -1
- package/lib/models/Deck.d.ts +14 -0
- package/lib/models/Deck.js +5 -0
- package/lib/models/Environment.d.ts +117 -0
- package/lib/models/ItemType.d.ts +1 -1
- package/lib/models/Runtime.d.ts +6 -0
- package/lib/models/SpaceItem.d.ts +2 -1
- package/lib/models/environments.generated.d.ts +29 -1
- package/lib/models/environments.generated.js +1 -1
- package/lib/models/index.d.ts +1 -0
- package/lib/models/index.js +1 -0
- package/lib/protocols/BrowserAgentAdapter.d.ts +9 -1
- package/lib/protocols/BrowserAgentAdapter.js +11 -4
- package/lib/runtimes/actions.d.ts +5 -0
- package/lib/runtimes/actions.js +19 -0
- package/lib/specs/agents/agents.d.ts +2 -1
- package/lib/specs/agents/agents.js +314 -130
- package/lib/specs/frontendTools.d.ts +1 -0
- package/lib/specs/frontendTools.js +31 -0
- package/lib/specs/mcpServers.js +13 -13
- package/lib/specs/models.js +4 -4
- package/lib/specs/outputs.js +9 -0
- package/lib/specs/skills.js +7 -7
- package/lib/specs/teams/teams.js +1 -1
- package/lib/types/outputs.d.ts +2 -0
- package/package.json +1 -1
- package/scripts/codegen/generate_mcp_servers.py +2 -2
- package/scripts/codegen/generate_outputs.py +2 -0
- package/scripts/codegen/generate_skills.py +2 -2
- package/scripts/codegen/__pycache__/compose.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EnvironmentData, ListEnvironmentsResponse } from '../../models/EnvironmentDTO';
|
|
2
|
-
import type { ICreateEnvironmentBuildsRequest, ICreateEnvironmentRequest, ICreateEnvironmentVersionRequest, IDatalayerEnvironment, IEnvironmentArtifactsPage, IEnvironmentBuildLogChunk, IEnvironmentBuildLogPage, IEnvironmentBuildRecord, IEnvironmentBuildsCreated, IEnvironmentBuildsPage, IEnvironmentFork, IEnvironmentPublicationRecord, IEnvironmentRecord, IEnvironmentsError, IEnvironmentsPageQuery, IEnvironmentTrial, IEnvironmentValidationReport, IEnvironmentVersionRecord, IEnvironmentVersionsPage, IForkEnvironmentVersionRequest, IListEnvironmentsQuery, IPromoteEnvironmentVersionRequest, ITrialEnvironmentVersionRequest, IUpdateEnvironmentRequest, IUpdateEnvironmentVersionRequest, IValidateEnvironmentVersionRequest } from '../../models/Environment';
|
|
2
|
+
import type { ICreateEnvironmentBuildsRequest, ICreateEnvironmentRequest, ICreateEnvironmentVersionRequest, IDatalayerEnvironment, IEnvironmentArtifactsPage, IEnvironmentBuildLogChunk, IEnvironmentBuildLogPage, IEnvironmentBuildRecord, IEnvironmentBuildsCreated, IEnvironmentBuildsPage, IEnvironmentFork, IEnvironmentPublicationRecord, IEnvironmentQuotas, IEnvironmentRecord, IEnvironmentVersionSandboxes, IEnvironmentsError, IEnvironmentsPageQuery, IEnvironmentTrial, IEnvironmentValidationReport, IEnvironmentVersionRecord, IEnvironmentVersionsPage, IForkEnvironmentVersionRequest, IListEnvironmentsQuery, IPromoteEnvironmentVersionRequest, ITrialEnvironmentVersionRequest, IUpdateEnvironmentRequest, IUpdateEnvironmentVersionRequest, IValidateEnvironmentVersionRequest } from '../../models/Environment';
|
|
3
3
|
/** What every environments call may carry. */
|
|
4
4
|
export interface IEnvironmentsRequestOptions {
|
|
5
5
|
/** Sent as `X-Correlation-Id`; a refusal answers with it. */
|
|
@@ -197,6 +197,27 @@ export declare const createEnvironmentBuilds: (token: string, versionUid: string
|
|
|
197
197
|
* @returns Promise resolving to one page of builds
|
|
198
198
|
*/
|
|
199
199
|
export declare const listEnvironmentBuilds: (token: string, versionUid: string, page?: IEnvironmentsPageQuery, options?: IEnvironmentsRequestOptions, baseUrl?: string) => Promise<IEnvironmentBuildsPage>;
|
|
200
|
+
/**
|
|
201
|
+
* The sandboxes running a version now: yours by uid, anybody else's counted (E2-19).
|
|
202
|
+
* @param token - Authentication token
|
|
203
|
+
* @param versionUid - The version's uid
|
|
204
|
+
* @param options - Correlation id and abort signal
|
|
205
|
+
* @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
|
|
206
|
+
* @returns Promise resolving to the version's live sandboxes
|
|
207
|
+
*/
|
|
208
|
+
export declare const getEnvironmentVersionSandboxes: (token: string, versionUid: string, options?: IEnvironmentsRequestOptions, baseUrl?: string) => Promise<IEnvironmentVersionSandboxes>;
|
|
209
|
+
/**
|
|
210
|
+
* An owner's build quotas and what it holds against each (E1-13, E2-19).
|
|
211
|
+
* @param token - Authentication token
|
|
212
|
+
* @param owner - The caller's own when empty; an organization's by its uid
|
|
213
|
+
* @param options - Correlation id and abort signal
|
|
214
|
+
* @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
|
|
215
|
+
* @returns Promise resolving to the limits and the holdings
|
|
216
|
+
*/
|
|
217
|
+
export declare const getEnvironmentQuotas: (token: string, owner?: {
|
|
218
|
+
ownerType?: "user" | "organization";
|
|
219
|
+
ownerUid?: string;
|
|
220
|
+
}, options?: IEnvironmentsRequestOptions, baseUrl?: string) => Promise<IEnvironmentQuotas>;
|
|
200
221
|
/**
|
|
201
222
|
* List a version's artifacts, one per variant and region.
|
|
202
223
|
* @param token - Authentication token
|
|
@@ -293,6 +293,37 @@ export const listEnvironmentBuilds = async (token, versionUid, page = {}, option
|
|
|
293
293
|
validateToken(token);
|
|
294
294
|
return send(token, 'GET', registryUrl(baseUrl, `/environment-versions/${segment(versionUid, 'Version UID')}/builds`, { ...page }), options);
|
|
295
295
|
};
|
|
296
|
+
/**
|
|
297
|
+
* The sandboxes running a version now: yours by uid, anybody else's counted (E2-19).
|
|
298
|
+
* @param token - Authentication token
|
|
299
|
+
* @param versionUid - The version's uid
|
|
300
|
+
* @param options - Correlation id and abort signal
|
|
301
|
+
* @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
|
|
302
|
+
* @returns Promise resolving to the version's live sandboxes
|
|
303
|
+
*/
|
|
304
|
+
export const getEnvironmentVersionSandboxes = async (token, versionUid, options = {}, baseUrl = DEFAULT_SERVICE_URLS.RUNTIMES) => {
|
|
305
|
+
validateToken(token);
|
|
306
|
+
return send(token, 'GET', registryUrl(baseUrl, `/environment-versions/${segment(versionUid, 'Version UID')}/sandboxes`), options);
|
|
307
|
+
};
|
|
308
|
+
/**
|
|
309
|
+
* An owner's build quotas and what it holds against each (E1-13, E2-19).
|
|
310
|
+
* @param token - Authentication token
|
|
311
|
+
* @param owner - The caller's own when empty; an organization's by its uid
|
|
312
|
+
* @param options - Correlation id and abort signal
|
|
313
|
+
* @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
|
|
314
|
+
* @returns Promise resolving to the limits and the holdings
|
|
315
|
+
*/
|
|
316
|
+
export const getEnvironmentQuotas = async (token, owner = {}, options = {}, baseUrl = DEFAULT_SERVICE_URLS.RUNTIMES) => {
|
|
317
|
+
validateToken(token);
|
|
318
|
+
const query = {};
|
|
319
|
+
if (owner.ownerType) {
|
|
320
|
+
query.ownerType = owner.ownerType;
|
|
321
|
+
}
|
|
322
|
+
if (owner.ownerUid) {
|
|
323
|
+
query.ownerUid = owner.ownerUid;
|
|
324
|
+
}
|
|
325
|
+
return send(token, 'GET', registryUrl(baseUrl, '/environment-quotas', query), options);
|
|
326
|
+
};
|
|
296
327
|
/**
|
|
297
328
|
* List a version's artifacts, one per variant and region.
|
|
298
329
|
* @param token - Authentication token
|
|
@@ -49,6 +49,13 @@ export interface ChatFloatingProps extends ChatCommonProps {
|
|
|
49
49
|
buttonTooltip?: string;
|
|
50
50
|
/** Brand color override. Defaults to the theme's `accent.emphasis` token. */
|
|
51
51
|
brandColor?: string;
|
|
52
|
+
/**
|
|
53
|
+
* A soft light breathing around the button while the chat is closed, as
|
|
54
|
+
* if it were alive (see `ButtonGlow`). Still, and dimmer, for a reader who
|
|
55
|
+
* asks the system for reduced motion.
|
|
56
|
+
* @default true
|
|
57
|
+
*/
|
|
58
|
+
buttonGlow?: boolean;
|
|
52
59
|
/** Offset from edge (in pixels) */
|
|
53
60
|
offset?: number;
|
|
54
61
|
/** Animation duration (in ms) */
|
|
@@ -92,5 +99,5 @@ export interface ChatFloatingProps extends ChatCommonProps {
|
|
|
92
99
|
* ChatFloating component
|
|
93
100
|
* A floating chat window built on ChatBase
|
|
94
101
|
*/
|
|
95
|
-
export declare function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode, title, description, position, defaultOpen, width, height, showHeader, showButton, showNewChatButton, showClearButton, showSettingsButton, enableKeyboardShortcuts, toggleShortcut, showPoweredBy, promptVariant, mentionableAgents, poweredByProps, clickOutsideToClose, escapeToClose, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip, brandColor, offset, animationDuration, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick, hideMessagesAfterToolUI, defaultViewMode, onViewModeChange, sidebarMountPoint, showPanelBackdrop, availableModels, showModelSelector, showToolsMenu, showSkillsMenu, showTokenUsage, showContextRing, themeVariant, colorMode, runtimeId, historyEndpoint, authToken, historyAuthToken, pendingPrompt, showInformation, onInformationClick, onToolCallStart, onToolCallComplete, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, panelProps, launching, launchingMessage, }: ChatFloatingProps): React.JSX.Element;
|
|
102
|
+
export declare function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode, title, description, position, defaultOpen, width, height, showHeader, showButton, showNewChatButton, showClearButton, showSettingsButton, enableKeyboardShortcuts, toggleShortcut, showPoweredBy, promptVariant, mentionableAgents, poweredByProps, clickOutsideToClose, escapeToClose, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip, brandColor, buttonGlow, offset, animationDuration, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick, hideMessagesAfterToolUI, defaultViewMode, onViewModeChange, sidebarMountPoint, showPanelBackdrop, availableModels, showModelSelector, showToolsMenu, showSkillsMenu, showTokenUsage, showContextRing, themeVariant, colorMode, runtimeId, historyEndpoint, authToken, historyAuthToken, pendingPrompt, showInformation, onInformationClick, onToolCallStart, onToolCallComplete, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, panelProps, launching, launchingMessage, }: ChatFloatingProps): React.JSX.Element;
|
|
96
103
|
export default ChatFloating;
|
package/lib/chat/ChatFloating.js
CHANGED
|
@@ -23,6 +23,7 @@ import { XIcon, CommentDiscussionIcon, GrabberIcon, } from '@primer/octicons-rea
|
|
|
23
23
|
import { AiAgentIcon } from '@datalayer/icons-react';
|
|
24
24
|
import { createPortal } from 'react-dom';
|
|
25
25
|
import { ChatBase } from './base/ChatBase';
|
|
26
|
+
import { ButtonGlow } from './display/ButtonGlow';
|
|
26
27
|
import { useViewportDrag } from './useViewportDrag';
|
|
27
28
|
import { disabledChatViewModes, resolveMountPoint } from './viewModes';
|
|
28
29
|
import { useChatOpen, useChatMessages, useChatStore, } from '../stores/chatStore';
|
|
@@ -46,7 +47,7 @@ function useIsMobile(breakpoint = 640) {
|
|
|
46
47
|
* ChatFloating component
|
|
47
48
|
* A floating chat window built on ChatBase
|
|
48
49
|
*/
|
|
49
|
-
export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode = true, title = 'Chat', description = 'Start a conversation with the AI agent.', position = 'bottom-right', defaultOpen = false, width = 400, height = 550, showHeader = true, showButton = true, showNewChatButton = true, showClearButton = true, showSettingsButton = false, enableKeyboardShortcuts = true, toggleShortcut = '/', showPoweredBy = true, promptVariant, mentionableAgents, poweredByProps, clickOutsideToClose = false, escapeToClose = true, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip = 'Chat with AI', brandColor, offset = 20, animationDuration = 200, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick = true, hideMessagesAfterToolUI = false, defaultViewMode = 'floating', onViewModeChange, sidebarMountPoint = null, showPanelBackdrop = false, availableModels, showModelSelector = false, showToolsMenu = false, showSkillsMenu = false, showTokenUsage = true, showContextRing = false, themeVariant, colorMode, runtimeId, historyEndpoint, authToken, historyAuthToken, pendingPrompt, showInformation = false, onInformationClick, onToolCallStart, onToolCallComplete, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, panelProps, launching = false, launchingMessage, }) {
|
|
50
|
+
export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode = true, title = 'Chat', description = 'Start a conversation with the AI agent.', position = 'bottom-right', defaultOpen = false, width = 400, height = 550, showHeader = true, showButton = true, showNewChatButton = true, showClearButton = true, showSettingsButton = false, enableKeyboardShortcuts = true, toggleShortcut = '/', showPoweredBy = true, promptVariant, mentionableAgents, poweredByProps, clickOutsideToClose = false, escapeToClose = true, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip = 'Chat with AI', brandColor, buttonGlow = true, offset = 20, animationDuration = 200, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick = true, hideMessagesAfterToolUI = false, defaultViewMode = 'floating', onViewModeChange, sidebarMountPoint = null, showPanelBackdrop = false, availableModels, showModelSelector = false, showToolsMenu = false, showSkillsMenu = false, showTokenUsage = true, showContextRing = false, themeVariant, colorMode, runtimeId, historyEndpoint, authToken, historyAuthToken, pendingPrompt, showInformation = false, onInformationClick, onToolCallStart, onToolCallComplete, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, panelProps, launching = false, launchingMessage, }) {
|
|
50
51
|
// Store-based state
|
|
51
52
|
const storeIsOpen = useChatOpen();
|
|
52
53
|
const storeMessages = useChatMessages();
|
|
@@ -555,7 +556,9 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
|
|
|
555
556
|
}, children: _jsxs(Box, { sx: {
|
|
556
557
|
position: 'relative',
|
|
557
558
|
display: 'inline-flex',
|
|
558
|
-
|
|
559
|
+
// The glow's halos go behind the button, not behind the page.
|
|
560
|
+
isolation: 'isolate',
|
|
561
|
+
}, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [buttonGlow && _jsx(ButtonGlow, { color: brandColor }), _jsx(Tooltip, { text: `${buttonTooltip}${shortcutHint ? ` (${shortcutHint})` : ''}`, direction: position.includes('right') ? 'w' : 'e', children: _jsx(IconButton, { icon: buttonIcon
|
|
559
562
|
? buttonIcon
|
|
560
563
|
: CommentDiscussionIcon, "aria-label": buttonTooltip, onClick: handleToggle, size: "large", sx: {
|
|
561
564
|
width: 56,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface ButtonGlowProps {
|
|
2
|
+
/**
|
|
3
|
+
* The colour of the light: the button's own. A theme token or any CSS
|
|
4
|
+
* colour; the theme's `accent.emphasis` when absent.
|
|
5
|
+
*/
|
|
6
|
+
color?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function ButtonGlow({ color }: ButtonGlowProps): import("react").JSX.Element;
|
|
9
|
+
export default ButtonGlow;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* A soft light breathing around a round button, as if it were alive.
|
|
8
|
+
*
|
|
9
|
+
* Two blurred halos in the button's colour swell and fade on cycles of
|
|
10
|
+
* different lengths, 3.4 s and 5.3 s, so the light drifts rather than
|
|
11
|
+
* blinks: the two never line up the same way twice in a row. For a reader
|
|
12
|
+
* who asks the system for less motion, the halos hold still, a little dimmer.
|
|
13
|
+
*
|
|
14
|
+
* The halos sit behind the button: the parent must be `position: relative`
|
|
15
|
+
* and make a stacking context of its own (`isolation: 'isolate'`), or they
|
|
16
|
+
* would slip behind the page instead.
|
|
17
|
+
*
|
|
18
|
+
* @module chat/display/ButtonGlow
|
|
19
|
+
*/
|
|
20
|
+
import { Box } from '@datalayer/primer-addons';
|
|
21
|
+
const halo = (color) => ({
|
|
22
|
+
position: 'absolute',
|
|
23
|
+
inset: 0,
|
|
24
|
+
borderRadius: '50%',
|
|
25
|
+
bg: color || 'accent.emphasis',
|
|
26
|
+
zIndex: -1,
|
|
27
|
+
pointerEvents: 'none',
|
|
28
|
+
willChange: 'transform, opacity',
|
|
29
|
+
});
|
|
30
|
+
export function ButtonGlow({ color }) {
|
|
31
|
+
return (_jsxs(_Fragment, { children: [_jsx(Box, { "aria-hidden": true, "data-button-glow": "breath", sx: {
|
|
32
|
+
...halo(color),
|
|
33
|
+
filter: 'blur(10px)',
|
|
34
|
+
animation: 'agentRuntimesGlowBreath 3.4s ease-in-out infinite',
|
|
35
|
+
'@keyframes agentRuntimesGlowBreath': {
|
|
36
|
+
'0%, 100%': { transform: 'scale(0.9)', opacity: 0.35 },
|
|
37
|
+
'50%': { transform: 'scale(1.25)', opacity: 0.7 },
|
|
38
|
+
},
|
|
39
|
+
'@media (prefers-reduced-motion: reduce)': {
|
|
40
|
+
animation: 'none',
|
|
41
|
+
transform: 'scale(1.1)',
|
|
42
|
+
opacity: 0.4,
|
|
43
|
+
},
|
|
44
|
+
} }), _jsx(Box, { "aria-hidden": true, "data-button-glow": "aura", sx: {
|
|
45
|
+
...halo(color),
|
|
46
|
+
filter: 'blur(18px)',
|
|
47
|
+
animation: 'agentRuntimesGlowAura 5.3s ease-in-out infinite',
|
|
48
|
+
'@keyframes agentRuntimesGlowAura': {
|
|
49
|
+
'0%, 100%': { transform: 'scale(1)', opacity: 0.15 },
|
|
50
|
+
'40%': { transform: 'scale(1.55)', opacity: 0.4 },
|
|
51
|
+
'70%': { transform: 'scale(1.3)', opacity: 0.25 },
|
|
52
|
+
},
|
|
53
|
+
'@media (prefers-reduced-motion: reduce)': {
|
|
54
|
+
animation: 'none',
|
|
55
|
+
transform: 'scale(1.3)',
|
|
56
|
+
opacity: 0.2,
|
|
57
|
+
},
|
|
58
|
+
} })] }));
|
|
59
|
+
}
|
|
60
|
+
export default ButtonGlow;
|
|
@@ -50,6 +50,9 @@ export function ChatEmptyState({ emptyState, brandIcon, description, suggestions
|
|
|
50
50
|
cursor: 'pointer',
|
|
51
51
|
display: 'inline-flex',
|
|
52
52
|
alignItems: 'center',
|
|
53
|
+
// A short opener sits in the middle of its fixed-width chip, not
|
|
54
|
+
// against its left edge with the rest of the chip empty.
|
|
55
|
+
justifyContent: 'center',
|
|
53
56
|
width: SUGGESTION_CHIP_WIDTH,
|
|
54
57
|
flex: `0 0 ${SUGGESTION_CHIP_WIDTH}px`,
|
|
55
58
|
'&:hover': {
|
|
@@ -57,7 +60,7 @@ export function ChatEmptyState({ emptyState, brandIcon, description, suggestions
|
|
|
57
60
|
color: 'var(--button-primary-fgColor-rest)',
|
|
58
61
|
borderColor: 'accent.emphasis',
|
|
59
62
|
},
|
|
60
|
-
}, onClick: () => handleSuggestionClick(suggestion), children: _jsx(Truncate, { title: suggestion.message, maxWidth: "100%", sx: { minWidth: 0 }, children: suggestion.title }) }, index))) }));
|
|
63
|
+
}, onClick: () => handleSuggestionClick(suggestion), children: _jsx(Truncate, { inline: true, title: suggestion.message, maxWidth: "100%", sx: { minWidth: 0 }, children: suggestion.title }) }, index))) }));
|
|
61
64
|
return (_jsx(ThemeProvider, { children: _jsxs(Box, { sx: {
|
|
62
65
|
display: 'flex',
|
|
63
66
|
flexDirection: 'column',
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Heading, IconButton, Label, Text,
|
|
2
|
+
import { Heading, IconButton, Label, Text, Truncate } from '@primer/react';
|
|
3
3
|
import { Box } from '@datalayer/primer-addons';
|
|
4
4
|
import { KernelIndicator } from '@datalayer/jupyter-react';
|
|
5
|
-
import { PlusIcon, TrashIcon, GearIcon,
|
|
6
|
-
import {
|
|
5
|
+
import { PlusIcon, TrashIcon, GearIcon, InfoIcon, } from '@primer/octicons-react';
|
|
6
|
+
import { ChatViewModeToggle } from './ChatViewModeToggle';
|
|
7
7
|
import { AiAgentIcon } from '@datalayer/icons-react';
|
|
8
8
|
import { EphemeralSurfaceControl } from '../EphemeralSurfaceControl';
|
|
9
9
|
export function toRuntimeExecutionState(runtimeStatus) {
|
|
@@ -29,16 +29,6 @@ export function toRuntimeExecutionState(runtimeStatus) {
|
|
|
29
29
|
return undefined;
|
|
30
30
|
}
|
|
31
31
|
// ---------------------------------------------------------------------------
|
|
32
|
-
// Props
|
|
33
|
-
// ---------------------------------------------------------------------------
|
|
34
|
-
/** The drawing of each mode in the header's toggle. */
|
|
35
|
-
const VIEW_MODE_ICONS = {
|
|
36
|
-
floating: CommentDiscussionIcon,
|
|
37
|
-
'floating-small': DeviceMobileIcon,
|
|
38
|
-
'floating-draggable': GrabberIcon,
|
|
39
|
-
sidebar: SidebarExpandIcon,
|
|
40
|
-
};
|
|
41
|
-
// ---------------------------------------------------------------------------
|
|
42
32
|
// Component
|
|
43
33
|
// ---------------------------------------------------------------------------
|
|
44
34
|
export function ChatBaseHeader({ title, subtitle, disableReason, brandIcon, headerContent, headerActions, showInformation, onInformationClick, padding, kernelIndicatorState, kernelIndicatorPlacement = 'left', runtimeStatus, kernel, kernelEnvironmentName, kernelCpu, kernelMemory, kernelGpu, headerButtons, messageCount, onNewChat, onClear, chatViewMode, onChatViewModeChange, disabledViewModes = [], showEphemeralSurfaceControl = false, enableEphemeralNotebookOption = false, enableEphemeralDocumentOption = false, ephemeralSurfaceMode = 'none', onEphemeralSurfaceModeChange, }) {
|
|
@@ -90,47 +80,5 @@ export function ChatBaseHeader({ title, subtitle, disableReason, brandIcon, head
|
|
|
90
80
|
color: 'fg.muted',
|
|
91
81
|
minWidth: 0,
|
|
92
82
|
maxWidth: '100%',
|
|
93
|
-
}, children: _jsx(Truncate, { title: subtitle, maxWidth: "40ch", children: subtitle }) }))] })), disableReason && (_jsx(Label, { variant: "attention", sx: { flexShrink: 0 }, children: disableReason })), headerContent, showInformation && (_jsx(IconButton, { icon: InfoIcon, "aria-label": "Information", variant: "invisible", size: "small", onClick: onInformationClick })), kernelIndicatorPlacement === 'center' && kernelIndicatorElement] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1, flexShrink: 0 }, children: [kernelIndicatorPlacement === 'right' && kernelIndicatorElement, headerButtons?.showNewChat && (_jsx(IconButton, { icon: PlusIcon, "aria-label": "New chat", variant: "invisible", size: "small", onClick: onNewChat })), headerButtons?.showClear && messageCount > 0 && (_jsx(IconButton, { icon: TrashIcon, "aria-label": "Clear messages", variant: "invisible", size: "small", onClick: onClear })), headerButtons?.showSettings && (_jsx(IconButton, { icon: GearIcon, "aria-label": "Settings", variant: "invisible", size: "small", onClick: headerButtons.onSettings })), showEphemeralSurfaceControl && (_jsx(EphemeralSurfaceControl, { mode: ephemeralSurfaceMode, onChange: onEphemeralSurfaceModeChange, enableNotebook: enableEphemeralNotebookOption, enableDocument: enableEphemeralDocumentOption })), chatViewMode && onChatViewModeChange && (_jsx(
|
|
94
|
-
display: 'inline-flex',
|
|
95
|
-
alignItems: 'center',
|
|
96
|
-
bg: 'neutral.muted',
|
|
97
|
-
borderRadius: '6px',
|
|
98
|
-
p: '2px',
|
|
99
|
-
gap: '1px',
|
|
100
|
-
}, children: CHAT_VIEW_MODES.map(({ mode, label }) => {
|
|
101
|
-
const ModeIcon = VIEW_MODE_ICONS[mode];
|
|
102
|
-
const selected = chatViewMode === mode;
|
|
103
|
-
/* Greyed rather than left out: the person sees the mode
|
|
104
|
-
exists, and that this page has no place for it. */
|
|
105
|
-
const disabled = disabledViewModes.includes(mode);
|
|
106
|
-
return (_jsx(Tooltip, { text: disabled && mode === 'sidebar'
|
|
107
|
-
? `${label} — ${SIDEBAR_NEEDS_MOUNT_POINT}`
|
|
108
|
-
: label, direction: "n", children: _jsx(Box, { as: "button", "aria-label": label, "aria-disabled": disabled || undefined, onClick: () => {
|
|
109
|
-
if (!disabled) {
|
|
110
|
-
onChatViewModeChange(mode);
|
|
111
|
-
}
|
|
112
|
-
}, sx: {
|
|
113
|
-
display: 'inline-flex',
|
|
114
|
-
alignItems: 'center',
|
|
115
|
-
justifyContent: 'center',
|
|
116
|
-
width: 26,
|
|
117
|
-
height: 24,
|
|
118
|
-
borderRadius: '4px',
|
|
119
|
-
border: 'none',
|
|
120
|
-
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
121
|
-
opacity: disabled ? 0.45 : 1,
|
|
122
|
-
bg: selected ? 'canvas.default' : 'transparent',
|
|
123
|
-
boxShadow: selected ? 'shadow.small' : 'none',
|
|
124
|
-
color: selected ? 'fg.default' : 'fg.muted',
|
|
125
|
-
transition: 'all 0.15s ease',
|
|
126
|
-
'&:hover': disabled
|
|
127
|
-
? {}
|
|
128
|
-
: {
|
|
129
|
-
color: 'fg.default',
|
|
130
|
-
bg: selected
|
|
131
|
-
? 'canvas.default'
|
|
132
|
-
: 'neutral.subtle',
|
|
133
|
-
},
|
|
134
|
-
}, children: _jsx(ModeIcon, { size: 14 }) }) }, mode));
|
|
135
|
-
}) })), headerActions] })] }) }));
|
|
83
|
+
}, children: _jsx(Truncate, { title: subtitle, maxWidth: "40ch", children: subtitle }) }))] })), disableReason && (_jsx(Label, { variant: "attention", sx: { flexShrink: 0 }, children: disableReason })), headerContent, showInformation && (_jsx(IconButton, { icon: InfoIcon, "aria-label": "Information", variant: "invisible", size: "small", onClick: onInformationClick })), kernelIndicatorPlacement === 'center' && kernelIndicatorElement] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1, flexShrink: 0 }, children: [kernelIndicatorPlacement === 'right' && kernelIndicatorElement, headerButtons?.showNewChat && (_jsx(IconButton, { icon: PlusIcon, "aria-label": "New chat", variant: "invisible", size: "small", onClick: onNewChat })), headerButtons?.showClear && messageCount > 0 && (_jsx(IconButton, { icon: TrashIcon, "aria-label": "Clear messages", variant: "invisible", size: "small", onClick: onClear })), headerButtons?.showSettings && (_jsx(IconButton, { icon: GearIcon, "aria-label": "Settings", variant: "invisible", size: "small", onClick: headerButtons.onSettings })), showEphemeralSurfaceControl && (_jsx(EphemeralSurfaceControl, { mode: ephemeralSurfaceMode, onChange: onEphemeralSurfaceModeChange, enableNotebook: enableEphemeralNotebookOption, enableDocument: enableEphemeralDocumentOption })), chatViewMode && onChatViewModeChange && (_jsx(ChatViewModeToggle, { value: chatViewMode, onChange: onChatViewModeChange, disabledModes: disabledViewModes })), headerActions] })] }) }));
|
|
136
84
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The segmented toggle for how a chat is shown — the four modes of
|
|
3
|
+
* `CHAT_VIEW_MODES`, drawn as icons in a pill, the current one raised.
|
|
4
|
+
*
|
|
5
|
+
* It grew up in the chat header, and lives apart from it so the same
|
|
6
|
+
* control can stand elsewhere: a composer floating over a page as a
|
|
7
|
+
* draggable card carries it in its own footer, where the person deciding
|
|
8
|
+
* how the chat should sit has the chat under their hands. The rules — the
|
|
9
|
+
* order, the words, which modes are greyed out — stay in `viewModes.ts`;
|
|
10
|
+
* this is only their drawing.
|
|
11
|
+
*
|
|
12
|
+
* @module chat/header/ChatViewModeToggle
|
|
13
|
+
*/
|
|
14
|
+
import type { JSX } from 'react';
|
|
15
|
+
import { type Icon } from '@primer/octicons-react';
|
|
16
|
+
import type { ChatViewMode } from '../../types/chat';
|
|
17
|
+
/** The drawing of each mode. */
|
|
18
|
+
export declare const VIEW_MODE_ICONS: Record<ChatViewMode, Icon>;
|
|
19
|
+
export type ChatViewModeToggleProps = {
|
|
20
|
+
/** The mode the chat is in now. */
|
|
21
|
+
value?: ChatViewMode;
|
|
22
|
+
/** The mode the person picked. */
|
|
23
|
+
onChange: (mode: ChatViewMode) => void;
|
|
24
|
+
/** Modes shown greyed out: the sidebar, when the host has no mount point. */
|
|
25
|
+
disabledModes?: readonly ChatViewMode[];
|
|
26
|
+
/** Where the tooltips open. Above by default; below for a control at the top of its window. */
|
|
27
|
+
tooltipDirection?: 'n' | 's';
|
|
28
|
+
};
|
|
29
|
+
export declare function ChatViewModeToggle({ value, onChange, disabledModes, tooltipDirection, }: ChatViewModeToggleProps): JSX.Element;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Tooltip } from '@primer/react';
|
|
3
|
+
import { Box } from '@datalayer/primer-addons';
|
|
4
|
+
import { CommentDiscussionIcon, DeviceMobileIcon, GrabberIcon, SidebarExpandIcon, } from '@primer/octicons-react';
|
|
5
|
+
import { CHAT_VIEW_MODES, SIDEBAR_NEEDS_MOUNT_POINT } from '../viewModes';
|
|
6
|
+
/** The drawing of each mode. */
|
|
7
|
+
export const VIEW_MODE_ICONS = {
|
|
8
|
+
floating: CommentDiscussionIcon,
|
|
9
|
+
'floating-small': DeviceMobileIcon,
|
|
10
|
+
'floating-draggable': GrabberIcon,
|
|
11
|
+
sidebar: SidebarExpandIcon,
|
|
12
|
+
};
|
|
13
|
+
export function ChatViewModeToggle({ value, onChange, disabledModes = [], tooltipDirection = 'n', }) {
|
|
14
|
+
return (_jsx(Box, { role: "group", "aria-label": "Display mode", "data-chat-view-mode-toggle": "", sx: {
|
|
15
|
+
display: 'inline-flex',
|
|
16
|
+
alignItems: 'center',
|
|
17
|
+
bg: 'neutral.muted',
|
|
18
|
+
borderRadius: '6px',
|
|
19
|
+
p: '2px',
|
|
20
|
+
gap: '1px',
|
|
21
|
+
}, children: CHAT_VIEW_MODES.map(({ mode, label }) => {
|
|
22
|
+
const ModeIcon = VIEW_MODE_ICONS[mode];
|
|
23
|
+
const selected = value === mode;
|
|
24
|
+
/* Greyed rather than left out: the person sees the mode exists, and
|
|
25
|
+
that this page has no place for it. */
|
|
26
|
+
const disabled = disabledModes.includes(mode);
|
|
27
|
+
return (_jsx(Tooltip, { text: disabled && mode === 'sidebar'
|
|
28
|
+
? `${label} — ${SIDEBAR_NEEDS_MOUNT_POINT}`
|
|
29
|
+
: label, direction: tooltipDirection, children: _jsx(Box, { as: "button", type: "button", "aria-label": label, "aria-pressed": selected, "aria-disabled": disabled || undefined, onClick: () => {
|
|
30
|
+
if (!disabled) {
|
|
31
|
+
onChange(mode);
|
|
32
|
+
}
|
|
33
|
+
}, sx: {
|
|
34
|
+
display: 'inline-flex',
|
|
35
|
+
alignItems: 'center',
|
|
36
|
+
justifyContent: 'center',
|
|
37
|
+
width: 26,
|
|
38
|
+
height: 24,
|
|
39
|
+
borderRadius: '4px',
|
|
40
|
+
border: 'none',
|
|
41
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
42
|
+
opacity: disabled ? 0.45 : 1,
|
|
43
|
+
bg: selected ? 'canvas.default' : 'transparent',
|
|
44
|
+
boxShadow: selected ? 'shadow.small' : 'none',
|
|
45
|
+
color: selected ? 'fg.default' : 'fg.muted',
|
|
46
|
+
transition: 'all 0.15s ease',
|
|
47
|
+
'&:hover': disabled
|
|
48
|
+
? {}
|
|
49
|
+
: {
|
|
50
|
+
color: 'fg.default',
|
|
51
|
+
bg: selected ? 'canvas.default' : 'neutral.subtle',
|
|
52
|
+
},
|
|
53
|
+
}, children: _jsx(ModeIcon, { size: 14 }) }) }, mode));
|
|
54
|
+
}) }));
|
|
55
|
+
}
|
package/lib/chat/index.d.ts
CHANGED
|
@@ -59,6 +59,7 @@ export { McpStatusIndicator, type McpStatusIndicatorProps, type McpServerStatus,
|
|
|
59
59
|
export { PoweredByTag, type PoweredByTagProps } from './display/PoweredByTag';
|
|
60
60
|
export { FloatingBrandButton, type FloatingBrandButtonProps, } from './display/FloatingBrandButton';
|
|
61
61
|
export { ChatHeader, type ChatHeaderProps } from './header/ChatHeader';
|
|
62
|
+
export { ChatViewModeToggle, VIEW_MODE_ICONS, type ChatViewModeToggleProps, } from './header/ChatViewModeToggle';
|
|
62
63
|
export { MessagePart, type MessagePartProps, TextPart, type TextPartProps, ReasoningPart, type ReasoningPartProps, ToolPart, type ToolPartProps, DynamicToolPart, type DynamicToolPartProps, } from './parts';
|
|
63
64
|
export { ToolCallDisplay, type ToolCallDisplayProps } from './tools';
|
|
64
65
|
export { ToolApprovalDialog, useToolApprovalDialog, type ToolApprovalDialogProps, } from './tools/ToolApprovalDialog';
|
package/lib/chat/index.js
CHANGED
|
@@ -68,6 +68,7 @@ export { McpStatusIndicator, SandboxStatusIndicator, } from './indicators';
|
|
|
68
68
|
export { PoweredByTag } from './display/PoweredByTag';
|
|
69
69
|
export { FloatingBrandButton, } from './display/FloatingBrandButton';
|
|
70
70
|
export { ChatHeader } from './header/ChatHeader';
|
|
71
|
+
export { ChatViewModeToggle, VIEW_MODE_ICONS, } from './header/ChatViewModeToggle';
|
|
71
72
|
// Components - Message part renderers
|
|
72
73
|
export { MessagePart, TextPart, ReasoningPart, ToolPart, DynamicToolPart, } from './parts';
|
|
73
74
|
// Components - Tool UI
|
|
@@ -62,6 +62,14 @@ export interface ICodeSandboxLauncherProps {
|
|
|
62
62
|
* Optional submit button label override.
|
|
63
63
|
*/
|
|
64
64
|
submitLabel?: string;
|
|
65
|
+
/**
|
|
66
|
+
* A published environment to offer and select: the version uid of its
|
|
67
|
+
* publication, as the Library page that sent the reader here names it.
|
|
68
|
+
* Nobody's listing holds another account's environment, so it is read from
|
|
69
|
+
* the publication, offered under *Library* and priced by the rate the
|
|
70
|
+
* publication carries (D-12, E2-19).
|
|
71
|
+
*/
|
|
72
|
+
libraryVersionUid?: string;
|
|
65
73
|
}
|
|
66
74
|
/**
|
|
67
75
|
* The launcher of a new code sandbox.
|
|
@@ -10,7 +10,8 @@ import { NO_RUNTIME_AVAILABLE_LABEL } from '@datalayer/core/lib/i18n';
|
|
|
10
10
|
import { isCodeSandboxProviderAvailable } from './codeSandboxProviders';
|
|
11
11
|
import { CodeSandboxVariant, codeSandboxVariantOf, codeSandboxVariantTitle, } from '../../models/CodeSandboxVariant';
|
|
12
12
|
import { CodeSandboxEnvironmentSelect, } from './CodeSandboxEnvironmentSelect';
|
|
13
|
-
import { codeSandboxEnvironmentOptions, codeSandboxEnvironmentVersion, firstLaunchableCodeSandboxEnvironment, } from './codeSandboxEnvironments';
|
|
13
|
+
import { codeSandboxEnvironmentOptions, codeSandboxEnvironmentVersion, firstLaunchableCodeSandboxEnvironment, libraryEnvironmentOf, } from './codeSandboxEnvironments';
|
|
14
|
+
import { getEnvironmentPublication } from '../../api/runtimes/environments';
|
|
14
15
|
import { getCodeSandboxGivenName, listCodeSandboxGivenNames, nextCodeSandboxGivenName, setCodeSandboxGivenName, } from './CodeSandboxNames';
|
|
15
16
|
import { iamStore, runtimesStore, useCoreStore, useIAMStore, } from '../../state/substates';
|
|
16
17
|
import { createRuntime as createRuntimeRecord } from '../../runtimes/actions';
|
|
@@ -42,7 +43,7 @@ const NOT_AVAILABLE_RETRIES = 5;
|
|
|
42
43
|
* The launcher of a new code sandbox.
|
|
43
44
|
*/
|
|
44
45
|
export function CodeSandboxLauncher(props) {
|
|
45
|
-
const { dialogTitle, kernelSnapshot, manager, onSubmit, markdownParser, sanitizer, upgradeSubscription, usageRoute = '/plans', submitLabel, startRuntime = true, } = props;
|
|
46
|
+
const { dialogTitle, kernelSnapshot, manager, onSubmit, markdownParser, sanitizer, upgradeSubscription, usageRoute = '/plans', submitLabel, startRuntime = true, libraryVersionUid, } = props;
|
|
46
47
|
const hasExample = startRuntime === 'with-example';
|
|
47
48
|
const shouldStartRuntime = startRuntime !== 'defer';
|
|
48
49
|
const user = iamStore.getState().user;
|
|
@@ -56,7 +57,45 @@ export function CodeSandboxLauncher(props) {
|
|
|
56
57
|
* below.
|
|
57
58
|
*/
|
|
58
59
|
const jupyterAvailable = isCodeSandboxProviderAvailable('local', runtimesStore.getState().multiServiceManager);
|
|
59
|
-
const
|
|
60
|
+
const listed = manager.environments.get();
|
|
61
|
+
/*
|
|
62
|
+
* A publication somebody else owns, which no listing of the viewer's holds
|
|
63
|
+
* (D-12, E2-19): read by its version uid, offered under *Library* beside
|
|
64
|
+
* the rest, priced by the rate the publication carries, and selected below,
|
|
65
|
+
* since it is what the reader came here to launch.
|
|
66
|
+
*/
|
|
67
|
+
const [libraryEntry, setLibraryEntry] = useState();
|
|
68
|
+
const [libraryRefusal, setLibraryRefusal] = useState('');
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (!libraryVersionUid) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
let current = true;
|
|
74
|
+
getEnvironmentPublication(iamStore.getState().token ?? '', libraryVersionUid, {}, runtimesStore.getState().runtimesUrl)
|
|
75
|
+
.then(publication => {
|
|
76
|
+
if (!current) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const entry = libraryEnvironmentOf(publication);
|
|
80
|
+
if (entry) {
|
|
81
|
+
setLibraryEntry(entry);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
setLibraryRefusal('This environment is no longer published, so it cannot be launched from the Library.');
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
.catch(() => {
|
|
88
|
+
if (current) {
|
|
89
|
+
setLibraryRefusal('This published environment could not be read, so it cannot be launched from here.');
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return () => {
|
|
93
|
+
current = false;
|
|
94
|
+
};
|
|
95
|
+
}, [libraryVersionUid]);
|
|
96
|
+
const environments = useMemo(() => libraryEntry && !listed.some(entry => entry.name === libraryEntry.name)
|
|
97
|
+
? [...listed, libraryEntry]
|
|
98
|
+
: listed, [listed, libraryEntry]);
|
|
60
99
|
/*
|
|
61
100
|
* The sandboxes of this Jupyter Server, offered beside those of the platform.
|
|
62
101
|
*
|
|
@@ -168,6 +207,17 @@ export function CodeSandboxLauncher(props) {
|
|
|
168
207
|
const [runtimeName, setRuntimeName] = useState(() => givenNameFor(firstLaunchableCodeSandboxEnvironment(environments)));
|
|
169
208
|
// Whether the runtim name has been changed by the user or not
|
|
170
209
|
const [hasCustomRuntimeName, setHasCustomRuntimeName] = useState(false);
|
|
210
|
+
// The publication the reader came to launch, selected once it is read.
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
if (!libraryEntry) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
setSelection(libraryEntry.name);
|
|
216
|
+
if (!hasCustomRuntimeName) {
|
|
217
|
+
setRuntimeName(givenNameFor(libraryEntry));
|
|
218
|
+
}
|
|
219
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
220
|
+
}, [libraryEntry]);
|
|
171
221
|
const [homeFolder, setHomeFolder] = useState(false);
|
|
172
222
|
const [openExample, setOpenExample] = useState(false);
|
|
173
223
|
const [waitingForRuntime, setWaitingForRuntime] = useState(false);
|
|
@@ -294,7 +344,6 @@ export function CodeSandboxLauncher(props) {
|
|
|
294
344
|
}
|
|
295
345
|
}
|
|
296
346
|
else if (shouldStartRuntime) {
|
|
297
|
-
success = false;
|
|
298
347
|
let availableTrial = 1;
|
|
299
348
|
let retryDelay = NOT_AVAILABLE_INIT_RETRY;
|
|
300
349
|
// Should return success status.
|
|
@@ -437,7 +486,7 @@ export function CodeSandboxLauncher(props) {
|
|
|
437
486
|
event.preventDefault();
|
|
438
487
|
handleSubmitRuntime();
|
|
439
488
|
}
|
|
440
|
-
}, children: [_jsxs(FormControl, { disabled: !!kernelSnapshot?.environment || environments.length === 0, children: [_jsx(FormControl.Label, { children: "Environment" }), _jsx(CodeSandboxEnvironmentSelect, { disabled: !!kernelSnapshot?.environment || environments.length === 0, options: environmentOptions, selectedKey: selection, onSelect: handleSelectionChange }), _jsx(FormControl.Caption, { children: _jsx(_Fragment, { children: markdownParser ? (_jsx(Box, { sx: { img: { maxWidth: '100%' } }, children: _jsx(Markdown, { text: description, markdownParser: markdownParser, sanitizer: sanitizer }) })) : sanitizer ? (
|
|
489
|
+
}, children: [libraryRefusal ? (_jsx(Text, { as: "p", sx: { color: 'attention.fg' }, "data-testid": "library-refusal", children: libraryRefusal })) : null, _jsxs(FormControl, { disabled: !!kernelSnapshot?.environment || environments.length === 0, children: [_jsx(FormControl.Label, { children: "Environment" }), _jsx(CodeSandboxEnvironmentSelect, { disabled: !!kernelSnapshot?.environment || environments.length === 0, options: environmentOptions, selectedKey: selection, onSelect: handleSelectionChange }), _jsx(FormControl.Caption, { children: _jsx(_Fragment, { children: markdownParser ? (_jsx(Box, { sx: { img: { maxWidth: '100%' } }, children: _jsx(Markdown, { text: description, markdownParser: markdownParser, sanitizer: sanitizer }) })) : sanitizer ? (
|
|
441
490
|
// The description of an environment carries markup. With no
|
|
442
491
|
// parser to render it, the sanitizer of the application is
|
|
443
492
|
// enough to show it as what it is rather than as its tags.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @module components/code-sandboxes/codeSandboxEnvironments
|
|
16
16
|
*/
|
|
17
|
-
import type { IDatalayerEnvironment } from '../../models';
|
|
17
|
+
import type { IDatalayerEnvironment, IEnvironmentPublicationRecord } from '../../models';
|
|
18
18
|
import type { ICodeSandboxEnvironmentOption } from './CodeSandboxEnvironmentSelect';
|
|
19
19
|
/**
|
|
20
20
|
* The variant a sandbox of THIS platform starts on.
|
|
@@ -84,3 +84,14 @@ export declare function codeSandboxEnvironmentOption(environment: IDatalayerEnvi
|
|
|
84
84
|
export declare function codeSandboxEnvironmentOptions(environments: readonly IDatalayerEnvironment[], viewer?: ICodeSandboxEnvironmentViewer, decorate?: (environment: IDatalayerEnvironment) => Partial<ICodeSandboxEnvironmentOption>): ICodeSandboxEnvironmentOption[];
|
|
85
85
|
/** The first entry a launcher may open on: never one that cannot be launched. */
|
|
86
86
|
export declare function firstLaunchableCodeSandboxEnvironment(environments: readonly IDatalayerEnvironment[]): IDatalayerEnvironment | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* A publication, as the picker offers it to somebody who does not own it
|
|
89
|
+
* (D-12, E2-19).
|
|
90
|
+
*
|
|
91
|
+
* Nobody's listing holds another account's environment, so a reader who came
|
|
92
|
+
* from its Library page is offered it from the publication itself: launched by
|
|
93
|
+
* its environment uid and the version the publication froze, listed under
|
|
94
|
+
* *Library*, and priced by the rate the publication carries. `undefined` for a
|
|
95
|
+
* publication that has been withdrawn, which is no longer anyone's to launch.
|
|
96
|
+
*/
|
|
97
|
+
export declare function libraryEnvironmentOf(publication: IEnvironmentPublicationRecord): IDatalayerEnvironment | undefined;
|
|
@@ -121,7 +121,7 @@ export function codeSandboxEnvironmentOption(environment, viewer, extra = {}) {
|
|
|
121
121
|
return {
|
|
122
122
|
key: environment.name,
|
|
123
123
|
title: environment.title || environment.name,
|
|
124
|
-
name: environment.name,
|
|
124
|
+
name: environment.label || environment.name,
|
|
125
125
|
group: CODE_SANDBOX_ENVIRONMENT_GROUP_TITLES[group],
|
|
126
126
|
version: version === undefined ? undefined : `v${version}`,
|
|
127
127
|
sizeClass: environment.sizeClass || undefined,
|
|
@@ -145,3 +145,40 @@ export function codeSandboxEnvironmentOptions(environments, viewer, decorate) {
|
|
|
145
145
|
export function firstLaunchableCodeSandboxEnvironment(environments) {
|
|
146
146
|
return environments.find(isCodeSandboxEnvironmentLaunchable);
|
|
147
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* A publication, as the picker offers it to somebody who does not own it
|
|
150
|
+
* (D-12, E2-19).
|
|
151
|
+
*
|
|
152
|
+
* Nobody's listing holds another account's environment, so a reader who came
|
|
153
|
+
* from its Library page is offered it from the publication itself: launched by
|
|
154
|
+
* its environment uid and the version the publication froze, listed under
|
|
155
|
+
* *Library*, and priced by the rate the publication carries. `undefined` for a
|
|
156
|
+
* publication that has been withdrawn, which is no longer anyone's to launch.
|
|
157
|
+
*/
|
|
158
|
+
export function libraryEnvironmentOf(publication) {
|
|
159
|
+
if (publication.status !== 'published') {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
const snapshot = publication.snapshot;
|
|
163
|
+
const spec = snapshot.spec
|
|
164
|
+
?.spec;
|
|
165
|
+
const version = snapshot.versionNumber;
|
|
166
|
+
return {
|
|
167
|
+
name: publication.environmentUid,
|
|
168
|
+
label: snapshot.environmentName || undefined,
|
|
169
|
+
uid: publication.environmentUid,
|
|
170
|
+
title: snapshot.title || snapshot.environmentName,
|
|
171
|
+
description: snapshot.readme ?? '',
|
|
172
|
+
language: spec?.language?.name ?? 'python',
|
|
173
|
+
origin: 'user',
|
|
174
|
+
owner: publication.ownerUid,
|
|
175
|
+
fromLibrary: true,
|
|
176
|
+
sizeClass: snapshot.sizeClass,
|
|
177
|
+
burning_rate: publication.burningRate ?? undefined,
|
|
178
|
+
promotedVersion: version === null || version === undefined
|
|
179
|
+
? null
|
|
180
|
+
: { uid: publication.versionUid, version, status: 'ready' },
|
|
181
|
+
variants: Object.keys(snapshot.variants ?? {}),
|
|
182
|
+
availableVariants: Object.keys(snapshot.variants ?? {}),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
import { createElement } from 'react';
|
|
6
|
-
import { DatabaseIcon, RowsIcon, BookIcon, DiffModifiedIcon, PencilIcon, FeedIssueDraftIcon, FeedRocketIcon, MilestoneIcon, OrganizationIcon, PeopleIcon, RocketIcon, FileIcon, StackIcon, GearIcon, GraphIcon, NumberIcon, PaperAirplaneIcon, ArchiveIcon, TagIcon, MortarBoardIcon, ContainerIcon, HomeIcon, ShareIcon, FileDirectoryIcon, TrophyIcon, QuestionIcon, PersonIcon, MailIcon, ZapIcon, } from '@primer/octicons-react';
|
|
6
|
+
import { DatabaseIcon, RowsIcon, BookIcon, DiffModifiedIcon, PencilIcon, FeedIssueDraftIcon, FeedRocketIcon, MilestoneIcon, OrganizationIcon, PeopleIcon, RocketIcon, FileIcon, StackIcon, GearIcon, GraphIcon, NumberIcon, PaperAirplaneIcon, ArchiveIcon, TagIcon, MortarBoardIcon, ContainerIcon, HomeIcon, ShareIcon, FileDirectoryIcon, TrophyIcon, QuestionIcon, PersonIcon, MailIcon, FileMediaIcon, ZapIcon, } from '@primer/octicons-react';
|
|
7
7
|
import { GalileoIcon, CircleWhiteIcon, BookOpenIcon, CameraIcon, CellIcon, NotebookOutlineIcon, } from '@datalayer/icons-react';
|
|
8
8
|
const ARTIFACT_ICONS = new Map([
|
|
9
9
|
['assignment', MilestoneIcon],
|
|
@@ -13,6 +13,7 @@ const ARTIFACT_ICONS = new Map([
|
|
|
13
13
|
['credits', NumberIcon],
|
|
14
14
|
['dataset', StackIcon],
|
|
15
15
|
['datasource', DatabaseIcon],
|
|
16
|
+
['deck', FileMediaIcon],
|
|
16
17
|
['document', FileIcon],
|
|
17
18
|
['documentation', BookOpenIcon],
|
|
18
19
|
['environment', ContainerIcon],
|