@datalayer/agent-runtimes 1.0.21 → 1.0.26
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/AgentNode.js +26 -26
- package/lib/chat/Chat.d.ts +1 -1
- package/lib/chat/Chat.js +2 -2
- package/lib/chat/base/ChatBase.js +44 -9
- package/lib/chat/document/EphemeralDocument.d.ts +12 -1
- package/lib/chat/document/EphemeralDocument.js +4 -4
- package/lib/chat/notebook/EphemeralNotebook.d.ts +11 -1
- package/lib/chat/notebook/EphemeralNotebook.js +13 -2
- package/lib/collaboration/DatalayerCollaborationProvider.d.ts +1 -1
- package/lib/collaboration/DatalayerCollaborationProvider.js +5 -5
- package/lib/components/agents/index.d.ts +6 -0
- package/lib/components/{students → agents}/index.js +6 -1
- package/lib/components/{NotificationEventCard.js → cards/NotificationEventCard.js} +1 -1
- package/lib/components/{OutputCard.js → cards/OutputCard.js} +1 -1
- package/lib/components/cards/index.d.ts +9 -0
- package/lib/components/cards/index.js +13 -0
- package/lib/components/{runtimes/RuntimeCellVariables.d.ts → code-sandboxes/CodeSandboxCellVariables.d.ts} +3 -3
- package/lib/components/{runtimes/RuntimeCellVariables.js → code-sandboxes/CodeSandboxCellVariables.js} +2 -2
- package/lib/components/{runtimes/RuntimeCellVariablesDialog.d.ts → code-sandboxes/CodeSandboxCellVariablesDialog.d.ts} +4 -4
- package/lib/components/{runtimes/RuntimeCellVariablesDialog.js → code-sandboxes/CodeSandboxCellVariablesDialog.js} +4 -4
- package/lib/components/{runtimes/RuntimeLauncherDialog.d.ts → code-sandboxes/CodeSandboxLauncher.d.ts} +4 -4
- package/lib/components/{runtimes/RuntimeLauncherDialog.js → code-sandboxes/CodeSandboxLauncher.js} +33 -38
- package/lib/components/code-sandboxes/CodeSandboxPicker.d.ts +96 -0
- package/lib/components/code-sandboxes/CodeSandboxPicker.js +296 -0
- package/lib/components/{runtimes/RuntimePickerCell.d.ts → code-sandboxes/CodeSandboxPickerCell.d.ts} +5 -5
- package/lib/components/{runtimes/RuntimePickerCell.js → code-sandboxes/CodeSandboxPickerCell.js} +7 -7
- package/lib/components/{runtimes/RuntimeReservationControl.d.ts → code-sandboxes/CodeSandboxReservationControl.d.ts} +3 -3
- package/lib/components/{runtimes/RuntimeReservationControl.js → code-sandboxes/CodeSandboxReservationControl.js} +11 -4
- package/lib/components/{runtimes/RuntimeTransfer.d.ts → code-sandboxes/CodeSandboxTransfer.d.ts} +1 -1
- package/lib/components/{runtimes/RuntimeUtils.d.ts → code-sandboxes/CodeSandboxUtils.d.ts} +3 -3
- package/lib/components/{runtimes/RuntimeUtils.js → code-sandboxes/CodeSandboxUtils.js} +35 -19
- package/lib/components/code-sandboxes/CodeSandboxVariables.d.ts +71 -0
- package/lib/components/{runtimes/RuntimeVariables.js → code-sandboxes/CodeSandboxVariables.js} +77 -2
- package/lib/components/code-sandboxes/NewCodeSandboxControls.d.ts +42 -0
- package/lib/components/code-sandboxes/NewCodeSandboxControls.js +76 -0
- package/lib/components/code-sandboxes/index.d.ts +21 -0
- package/lib/components/code-sandboxes/index.js +25 -0
- package/lib/components/index.d.ts +4 -6
- package/lib/components/index.js +4 -6
- package/lib/components/progress/CreditsIndicator.d.ts +7 -0
- package/lib/components/progress/CreditsIndicator.js +3 -3
- package/lib/context/CostUsageChart.d.ts +2 -2
- package/lib/context/CostUsageChart.js +7 -7
- package/lib/context/TokenUsageChart.d.ts +2 -2
- package/lib/context/TokenUsageChart.js +6 -6
- package/lib/context/TurnGraphChart.d.ts +1 -1
- package/lib/context/TurnGraphChart.js +6 -6
- package/lib/examples/AgentEvalsExample.js +1 -1
- package/lib/examples/AgentGuardrailsExample.js +3 -3
- package/lib/examples/AgentInferenceProviderExample.js +1 -1
- package/lib/examples/AgentMonitoringExample.js +6 -6
- package/lib/examples/AgentOtelExample.d.ts +2 -2
- package/lib/examples/AgentOtelExample.js +5 -5
- package/lib/examples/AgentspecsExample.js +1 -1
- package/lib/examples/NotebookCollaborationExample.js +8 -8
- package/lib/examples/main.js +5 -5
- package/lib/examples2/DatalayerNotebookExample.js +8 -8
- package/lib/examples2/main.js +5 -5
- package/lib/hooks/useAgentRuntimes.js +3 -3
- package/lib/hooks/useMonitoring.d.ts +5 -5
- package/lib/hooks/useMonitoring.js +10 -10
- package/lib/protocols/AGUIAdapter.js +4 -0
- package/lib/protocols/VercelAIAdapter.js +3 -0
- package/lib/types/chat.d.ts +23 -0
- package/lib/types/tools.d.ts +11 -0
- package/package.json +4 -4
- package/lib/components/runtimes/RuntimePickerBase.d.ts +0 -69
- package/lib/components/runtimes/RuntimePickerBase.js +0 -157
- package/lib/components/runtimes/RuntimePickerNotebook.d.ts +0 -42
- package/lib/components/runtimes/RuntimePickerNotebook.js +0 -232
- package/lib/components/runtimes/RuntimeSimplePicker.d.ts +0 -38
- package/lib/components/runtimes/RuntimeSimplePicker.js +0 -156
- package/lib/components/runtimes/RuntimeVariables.d.ts +0 -38
- package/lib/components/runtimes/index.d.ts +0 -11
- package/lib/components/runtimes/index.js +0 -15
- package/lib/components/students/StudentItemStatus.d.ts +0 -7
- package/lib/components/students/StudentItemStatus.js +0 -68
- package/lib/components/students/index.d.ts +0 -1
- package/lib/components/toolbars/AssignmentEditorToolbar.d.ts +0 -4
- package/lib/components/toolbars/AssignmentEditorToolbar.js +0 -18
- package/lib/components/toolbars/DocumentEditorToolbar.d.ts +0 -2
- package/lib/components/toolbars/DocumentEditorToolbar.js +0 -12
- package/lib/components/toolbars/NotebookEditorToolbar.d.ts +0 -29
- package/lib/components/toolbars/NotebookEditorToolbar.js +0 -30
- package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
- /package/lib/components/{AgentSummary.d.ts → agents/AgentSummary.d.ts} +0 -0
- /package/lib/components/{AgentSummary.js → agents/AgentSummary.js} +0 -0
- /package/lib/components/{NotificationEventCard.d.ts → cards/NotificationEventCard.d.ts} +0 -0
- /package/lib/components/{OutputCard.d.ts → cards/OutputCard.d.ts} +0 -0
- /package/lib/components/{ToolApprovalCard.d.ts → cards/ToolApprovalCard.d.ts} +0 -0
- /package/lib/components/{ToolApprovalCard.js → cards/ToolApprovalCard.js} +0 -0
- /package/lib/components/{runtimes/RuntimeTransfer.js → code-sandboxes/CodeSandboxTransfer.js} +0 -0
package/lib/components/{runtimes/RuntimeLauncherDialog.js → code-sandboxes/CodeSandboxLauncher.js}
RENAMED
|
@@ -5,9 +5,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
5
5
|
*/
|
|
6
6
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
7
7
|
import { useIsMounted } from 'usehooks-ts';
|
|
8
|
-
import { Button, FormControl, Select, Spinner, Text, TextInput, ToggleSwitch,
|
|
8
|
+
import { Button, FormControl, Select, Spinner, Text, TextInput, ToggleSwitch, } from '@primer/react';
|
|
9
9
|
import { Dialog } from '@primer/react/experimental';
|
|
10
|
-
import { AlertIcon } from '@primer/octicons-react';
|
|
11
10
|
import { Box } from '@datalayer/primer-addons';
|
|
12
11
|
import { useJupyterReactStore } from '@datalayer/jupyter-react';
|
|
13
12
|
import { USAGE_ROUTE } from '@datalayer/core/lib/routes';
|
|
@@ -18,7 +17,18 @@ import { createNotebook, sleep } from '@datalayer/core/lib/utils';
|
|
|
18
17
|
import { Markdown } from '@datalayer/core/lib/components/display';
|
|
19
18
|
import { Timer } from '@datalayer/core/lib/components/progress';
|
|
20
19
|
import { FlashClosable } from '@datalayer/core/lib/components/flashes';
|
|
21
|
-
import {
|
|
20
|
+
import { creditsLimitFor, NewCodeSandboxControls, useNewCodeSandboxAllowance, } from './NewCodeSandboxControls';
|
|
21
|
+
/**
|
|
22
|
+
* The text a fragment of markup reads as.
|
|
23
|
+
*
|
|
24
|
+
* @param html Markup to read
|
|
25
|
+
*/
|
|
26
|
+
function asPlainText(html) {
|
|
27
|
+
if (!html || typeof DOMParser === 'undefined') {
|
|
28
|
+
return html;
|
|
29
|
+
}
|
|
30
|
+
return (new DOMParser().parseFromString(html, 'text/html').body.textContent ?? '');
|
|
31
|
+
}
|
|
22
32
|
/**
|
|
23
33
|
* Initial time in milliseconds before retrying in case no kernels are available
|
|
24
34
|
*/
|
|
@@ -28,16 +38,16 @@ const NOT_AVAILABLE_INIT_RETRY = 10_000;
|
|
|
28
38
|
*/
|
|
29
39
|
const NOT_AVAILABLE_RETRIES = 5;
|
|
30
40
|
/**
|
|
31
|
-
*
|
|
41
|
+
* The launcher of a new code sandbox.
|
|
32
42
|
*/
|
|
33
|
-
export function
|
|
43
|
+
export function CodeSandboxLauncher(props) {
|
|
34
44
|
const { dialogTitle, kernelSnapshot, manager, onSubmit, markdownParser, sanitizer, upgradeSubscription, submitLabel, startRuntime = true, } = props;
|
|
35
45
|
const hasExample = startRuntime === 'with-example';
|
|
36
46
|
const shouldStartRuntime = startRuntime !== 'defer';
|
|
37
47
|
const user = iamStore.getState().user;
|
|
38
48
|
const environments = manager.environments.get();
|
|
39
49
|
const { configuration } = useCoreStore();
|
|
40
|
-
const {
|
|
50
|
+
const { refreshCredits } = useIAMStore();
|
|
41
51
|
let navigate;
|
|
42
52
|
try {
|
|
43
53
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
@@ -68,29 +78,10 @@ export function RuntimeLauncherDialog(props) {
|
|
|
68
78
|
const spec = useMemo(() => environments.find(spec => spec.name === selection), [environments, selection]);
|
|
69
79
|
const description = spec?.description ?? '';
|
|
70
80
|
const burningRate = spec?.burning_rate ?? 1;
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
user?.subscription?.current_runs ??
|
|
76
|
-
user?.subscription?.used_runs;
|
|
77
|
-
const hasKnownRunAllowance = typeof includedRuns === 'number';
|
|
78
|
-
const hasRemainingRuns = hasKnownRunAllowance &&
|
|
79
|
-
typeof currentRuns === 'number' &&
|
|
80
|
-
includedRuns > 0 &&
|
|
81
|
-
currentRuns < includedRuns;
|
|
82
|
-
const hasKnownCredits = typeof credits?.available === 'number';
|
|
83
|
-
const maxFromCredits = hasKnownCredits
|
|
84
|
-
? Math.floor((credits.available ?? 0) * creditsToMinutes)
|
|
85
|
-
: 10;
|
|
86
|
-
const effectiveMaxMinutes = hasKnownCredits && hasKnownRunAllowance && !hasRemainingRuns
|
|
87
|
-
? Math.max(1, maxFromCredits)
|
|
88
|
-
: Math.max(10, maxFromCredits > 0 ? maxFromCredits : 0);
|
|
89
|
-
const outOfCredits = shouldStartRuntime &&
|
|
90
|
-
hasKnownCredits &&
|
|
91
|
-
hasKnownRunAllowance &&
|
|
92
|
-
!hasRemainingRuns &&
|
|
93
|
-
((credits.available ?? 0) <= 0 || maxFromCredits < Number.EPSILON);
|
|
81
|
+
// The arithmetic the picker asks too — one copy for both, see the module.
|
|
82
|
+
const allowance = useNewCodeSandboxAllowance(burningRate);
|
|
83
|
+
const effectiveMaxMinutes = allowance.effectiveMaxMinutes;
|
|
84
|
+
const outOfCredits = shouldStartRuntime && allowance.outOfCredits;
|
|
94
85
|
const handleSelectionChange = useCallback((e) => {
|
|
95
86
|
const selection = e.target.value;
|
|
96
87
|
setSelection(selection);
|
|
@@ -110,8 +101,7 @@ export function RuntimeLauncherDialog(props) {
|
|
|
110
101
|
location: 'remote',
|
|
111
102
|
displayName: runtimeName ?? spec?.title,
|
|
112
103
|
};
|
|
113
|
-
const creditsLimit =
|
|
114
|
-
creditsToMinutes;
|
|
104
|
+
const creditsLimit = creditsLimitFor(timeLimit, burningRate);
|
|
115
105
|
desc.params = {};
|
|
116
106
|
if (startRuntime === 'defer') {
|
|
117
107
|
desc.params['creditsLimit'] = creditsLimit;
|
|
@@ -218,10 +208,6 @@ export function RuntimeLauncherDialog(props) {
|
|
|
218
208
|
shouldStartRuntime,
|
|
219
209
|
isMounted,
|
|
220
210
|
]);
|
|
221
|
-
const handleUserStorageChange = useCallback((e) => {
|
|
222
|
-
e.preventDefault();
|
|
223
|
-
setUserStorage(!userStorage);
|
|
224
|
-
}, [userStorage]);
|
|
225
211
|
const handleSwitchClick = useCallback((e) => {
|
|
226
212
|
e.preventDefault();
|
|
227
213
|
setOpenExample(!openExample);
|
|
@@ -239,7 +225,7 @@ export function RuntimeLauncherDialog(props) {
|
|
|
239
225
|
}, []);
|
|
240
226
|
// TODO title color is enforced for JupyterLab.
|
|
241
227
|
// This may be fixed in the jupyter-react theme (Primer generates h1 for the dialog title).
|
|
242
|
-
return (_jsx(Dialog, { title: _jsx("span", { style: { color: 'var(--fgColor-default)' }, children: dialogTitle || 'Launch a new
|
|
228
|
+
return (_jsx(Dialog, { title: _jsx("span", { style: { color: 'var(--fgColor-default)' }, children: dialogTitle || 'Launch a new Code Sandbox' }), onClose: () => {
|
|
243
229
|
onSubmit(undefined);
|
|
244
230
|
}, footerButtons: [
|
|
245
231
|
{
|
|
@@ -265,11 +251,20 @@ export function RuntimeLauncherDialog(props) {
|
|
|
265
251
|
event.preventDefault();
|
|
266
252
|
handleSubmitRuntime();
|
|
267
253
|
}
|
|
268
|
-
}, children: [_jsxs(FormControl, { disabled: !!kernelSnapshot?.environment || environments.length === 0, children: [_jsx(FormControl.Label, { children: "Environment" }), _jsx(Select, { name: "environment", disabled: !!kernelSnapshot?.environment || environments.length === 0, value: selection, onChange: handleSelectionChange, block: true, children: environments.map(spec => (_jsxs(Select.Option, { value: spec.name, children: [spec.name, spec.title && (_jsxs(_Fragment, { children: [' - ', spec.title] }))] }, spec.name))) }), _jsx(FormControl.Caption, { children: _jsx(_Fragment, { children: markdownParser ? (_jsx(Box, { sx: { img: { maxWidth: '100%' } }, children: _jsx(Markdown, { text: description, markdownParser: markdownParser, sanitizer: sanitizer }) })) :
|
|
254
|
+
}, children: [_jsxs(FormControl, { disabled: !!kernelSnapshot?.environment || environments.length === 0, children: [_jsx(FormControl.Label, { children: "Environment" }), _jsx(Select, { name: "environment", disabled: !!kernelSnapshot?.environment || environments.length === 0, value: selection, onChange: handleSelectionChange, block: true, children: environments.map(spec => (_jsxs(Select.Option, { value: spec.name, children: [spec.name, spec.title && (_jsxs(_Fragment, { children: [' - ', spec.title] }))] }, spec.name))) }), _jsx(FormControl.Caption, { children: _jsx(_Fragment, { children: markdownParser ? (_jsx(Box, { sx: { img: { maxWidth: '100%' } }, children: _jsx(Markdown, { text: description, markdownParser: markdownParser, sanitizer: sanitizer }) })) : sanitizer ? (
|
|
255
|
+
// The description of an environment carries markup. With no
|
|
256
|
+
// parser to render it, the sanitizer of the application is
|
|
257
|
+
// enough to show it as what it is rather than as its tags.
|
|
258
|
+
_jsx(Box, { sx: { img: { maxWidth: '100%' } }, dangerouslySetInnerHTML: {
|
|
259
|
+
__html: sanitizer.sanitize(description),
|
|
260
|
+
} })) : (
|
|
261
|
+
// Neither a parser nor a sanitizer: the text of the markup,
|
|
262
|
+
// which is still better than the markup itself.
|
|
263
|
+
asPlainText(description)) }) })] }), _jsx(NewCodeSandboxControls, { withReservation: !!startRuntime, burningRate: burningRate, timeLimit: timeLimit, onTimeChange: setTimeLimit, max: effectiveMaxMinutes, disabled: outOfCredits, error: outOfCredits ? 'You must add credits to your account.' : undefined, addCredits: navigate
|
|
269
264
|
? () => {
|
|
270
265
|
navigate(USAGE_ROUTE);
|
|
271
266
|
}
|
|
272
|
-
: undefined,
|
|
267
|
+
: undefined, userStorage: userStorage, onUserStorageToggle: () => setUserStorage(current => !current) }), _jsxs(FormControl, { sx: { paddingTop: '10px' }, children: [_jsx(FormControl.Label, { children: "Runtime name" }), _jsx(TextInput, { name: "name", value: runtimeName, onChange: handleKernelNameChange, block: true })] }), hasExample &&
|
|
273
268
|
jupyterLabAdapter?.jupyterLab &&
|
|
274
269
|
!configuration.whiteLabel && (_jsxs(FormControl, { sx: { paddingTop: '10px' }, children: [_jsx(FormControl.Label, { id: "open-example-label", children: "Open example notebook" }), _jsx(ToggleSwitch, { disabled: !environments.find(spec => spec.name === selection)?.example, checked: openExample, size: "small", onClick: handleSwitchClick, "aria-labelledby": "open-example-label" })] })), error && (_jsx(FlashClosable, { variant: flashLevel, actions: navigate && upgradeSubscription && flashLevel === 'warning' ? (_jsx(Button, { onClick: handleUpgrade, title: 'Upgrade your subscription.', children: "Upgrade" })) : undefined, children: error }))] }) }));
|
|
275
270
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import { ISessionContext } from '@jupyterlab/apputils';
|
|
3
|
+
import { ITranslator } from '@jupyterlab/translation';
|
|
4
|
+
import { IRuntimeDesc } from '../../models';
|
|
5
|
+
import { type IMultiServiceManager } from '../../runtimes';
|
|
6
|
+
import type { CodeSandboxTransfer } from './CodeSandboxTransfer';
|
|
7
|
+
type IDisplayMode = 'menu' | 'radio';
|
|
8
|
+
/**
|
|
9
|
+
* {@link CodeSandboxPicker} properties
|
|
10
|
+
*/
|
|
11
|
+
export interface ICodeSandboxPickerProps {
|
|
12
|
+
/**
|
|
13
|
+
* The display mode.
|
|
14
|
+
*/
|
|
15
|
+
display: IDisplayMode;
|
|
16
|
+
/**
|
|
17
|
+
* Additional actions items to be placed at the top of the picker
|
|
18
|
+
*/
|
|
19
|
+
preActions?: ReactNode;
|
|
20
|
+
/**
|
|
21
|
+
* Additional actions items to be placed at the bottom of the picker
|
|
22
|
+
*/
|
|
23
|
+
postActions?: ReactNode;
|
|
24
|
+
/**
|
|
25
|
+
* Whether the picker is disabled or not.
|
|
26
|
+
*/
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Runtime description passing this filter function will be displayed.
|
|
30
|
+
*/
|
|
31
|
+
filterRuntime?: (desc: IRuntimeDesc) => boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Session preference.
|
|
34
|
+
*/
|
|
35
|
+
preference?: {
|
|
36
|
+
id?: string;
|
|
37
|
+
kernelDisplayName?: string;
|
|
38
|
+
language?: string;
|
|
39
|
+
location?: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* The sandbox shown as chosen.
|
|
43
|
+
*
|
|
44
|
+
* Given with {@link setRuntimeDesc}, the choice belongs to the host — a
|
|
45
|
+
* cell keeps it in its metadata. Omitted, the picker holds it itself and
|
|
46
|
+
* reports it through {@link onTransferChange}, which is what a dialog with
|
|
47
|
+
* no state of its own needs.
|
|
48
|
+
*/
|
|
49
|
+
runtimeDesc?: IRuntimeDesc;
|
|
50
|
+
/**
|
|
51
|
+
* Set runtime description.
|
|
52
|
+
*/
|
|
53
|
+
setRuntimeDesc?: (desc?: IRuntimeDesc) => void;
|
|
54
|
+
/**
|
|
55
|
+
* Document session context.
|
|
56
|
+
*/
|
|
57
|
+
sessionContext?: ISessionContext;
|
|
58
|
+
/**
|
|
59
|
+
* Application service manager
|
|
60
|
+
*/
|
|
61
|
+
multiServiceManager: IMultiServiceManager;
|
|
62
|
+
/**
|
|
63
|
+
* Application translator.
|
|
64
|
+
*/
|
|
65
|
+
translator?: ITranslator;
|
|
66
|
+
/**
|
|
67
|
+
* Change the look depending on the menu integration.
|
|
68
|
+
*/
|
|
69
|
+
variant?: 'document' | 'cell';
|
|
70
|
+
/**
|
|
71
|
+
* Whether the questions of a NEW sandbox are asked below the list.
|
|
72
|
+
*
|
|
73
|
+
* They are the launcher's own — see `NewCodeSandboxControls` — and only
|
|
74
|
+
* concern a sandbox that does not run yet.
|
|
75
|
+
*/
|
|
76
|
+
withNewSandboxControls?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Whether the variables of the current sandbox may be carried to the
|
|
79
|
+
* chosen one, when both speak a language the snippets can serialize.
|
|
80
|
+
*/
|
|
81
|
+
withVariablesTransfer?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Called with the answer a dialog would return: the sandbox to assign and
|
|
84
|
+
* the variables to carry over.
|
|
85
|
+
*
|
|
86
|
+
* The sandbox is named the way the callers start it: `remote-` and
|
|
87
|
+
* `browser-` prefix an environment to start one in, a local environment is
|
|
88
|
+
* named by its specification alone, and `id` names one that already runs.
|
|
89
|
+
*/
|
|
90
|
+
onTransferChange?: (transfer: CodeSandboxTransfer) => void;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The picker of a code sandbox: what runs already, and what could run.
|
|
94
|
+
*/
|
|
95
|
+
export declare function CodeSandboxPicker(props: ICodeSandboxPickerProps): ReactElement;
|
|
96
|
+
export default CodeSandboxPicker;
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
import { useCallback, useEffect, useMemo, useState, } from 'react';
|
|
7
|
+
import { nullTranslator } from '@jupyterlab/translation';
|
|
8
|
+
//import { kernelIcon } from '@jupyterlab/ui-components';
|
|
9
|
+
import { ActionList, ActionMenu, IconButton, Text, RadioGroup, Radio, FormControl, LabelGroup, Label, } from '@primer/react';
|
|
10
|
+
import CloudUploadIcon from '@datalayer/icons-react/data1/CloudUploadIcon';
|
|
11
|
+
import { Box } from '@datalayer/primer-addons';
|
|
12
|
+
import { CpuIcon } from '@primer/octicons-react';
|
|
13
|
+
import { BrowserIcon, LaptopSimpleIcon } from '@datalayer/icons-react';
|
|
14
|
+
import { CreditsIndicator } from '../progress';
|
|
15
|
+
import { isRuntimeRemote, } from '../../runtimes';
|
|
16
|
+
import { useIAMStore } from '../../state/substates';
|
|
17
|
+
import { getGroupedCodeSandboxDescs, } from './CodeSandboxUtils';
|
|
18
|
+
import { creditsLimitFor, NewCodeSandboxControls, useNewCodeSandboxAllowance, } from './NewCodeSandboxControls';
|
|
19
|
+
import { CodeSandboxVariables, useCodeSandboxVariablesTransfer, } from './CodeSandboxVariables';
|
|
20
|
+
/**
|
|
21
|
+
* Maximal runtime display name length after which it is trimmed.
|
|
22
|
+
*/
|
|
23
|
+
const RUNTIME_DISPLAY_NAME_MAX_LENGTH = 25;
|
|
24
|
+
/**
|
|
25
|
+
* The picker of a code sandbox: what runs already, and what could run.
|
|
26
|
+
*/
|
|
27
|
+
export function CodeSandboxPicker(props) {
|
|
28
|
+
const { disabled, display, filterRuntime, multiServiceManager, onTransferChange, postActions, preActions, preference, sessionContext, translator, variant, withNewSandboxControls, withVariablesTransfer, } = props;
|
|
29
|
+
/*
|
|
30
|
+
* The choice, held here when the host does not hold it.
|
|
31
|
+
*
|
|
32
|
+
* A cell keeps its sandbox in its metadata and passes both the value and
|
|
33
|
+
* the setter; a dialog has nowhere to keep it, so the picker does.
|
|
34
|
+
*/
|
|
35
|
+
const isControlled = props.setRuntimeDesc !== undefined;
|
|
36
|
+
const [ownRuntimeDesc, setOwnRuntimeDesc] = useState();
|
|
37
|
+
const runtimeDesc = isControlled ? props.runtimeDesc : ownRuntimeDesc;
|
|
38
|
+
const setRuntimeDesc = useCallback((desc) => {
|
|
39
|
+
if (!isControlled) {
|
|
40
|
+
setOwnRuntimeDesc(desc ? { ...desc } : undefined);
|
|
41
|
+
}
|
|
42
|
+
props.setRuntimeDesc?.(desc);
|
|
43
|
+
}, [isControlled, props.setRuntimeDesc]);
|
|
44
|
+
const [groupedRuntimeDescs, setGroupedRuntimeDescs] = useState(getGroupedCodeSandboxDescs(multiServiceManager, preference?.id, translator, filterRuntime, variant));
|
|
45
|
+
const trans = useMemo(() => (translator ?? nullTranslator).load('jupyterlab'), [translator]);
|
|
46
|
+
const [defaultSet, setDefaultSet] = useState(false);
|
|
47
|
+
const [remoteModelsReady, setRemoteModelsReady] = useState(!multiServiceManager.remote);
|
|
48
|
+
// Trick because overflow is an unknown prop of ActionMenu.Overlay.
|
|
49
|
+
const overlayProps = {
|
|
50
|
+
maxHeight: 'large',
|
|
51
|
+
width: (variant === 'cell' ? 'small' : 'auto'),
|
|
52
|
+
};
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
let disposed = false;
|
|
55
|
+
const updateGroupedRuntimeDescs = () => {
|
|
56
|
+
if (disposed) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
setGroupedRuntimeDescs(getGroupedCodeSandboxDescs(multiServiceManager, preference?.id, translator, filterRuntime, variant));
|
|
60
|
+
};
|
|
61
|
+
const refreshRuntimeModels = multiServiceManager.remote?.runtimesManager.refreshRuntimeModels?.();
|
|
62
|
+
if (refreshRuntimeModels) {
|
|
63
|
+
refreshRuntimeModels
|
|
64
|
+
.catch(reason => {
|
|
65
|
+
console.error('Failed to resolve remote runtimes for the runtime picker.', reason);
|
|
66
|
+
})
|
|
67
|
+
.finally(() => {
|
|
68
|
+
if (disposed) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
updateGroupedRuntimeDescs();
|
|
72
|
+
setRemoteModelsReady(true);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
setRemoteModelsReady(true);
|
|
77
|
+
}
|
|
78
|
+
// Recompute immediately in case a runtime changed between the initial
|
|
79
|
+
// render and connecting the manager signals.
|
|
80
|
+
updateGroupedRuntimeDescs();
|
|
81
|
+
multiServiceManager.browser?.kernels.runningChanged.connect(updateGroupedRuntimeDescs);
|
|
82
|
+
multiServiceManager.browser?.kernelspecs.specsChanged.connect(updateGroupedRuntimeDescs);
|
|
83
|
+
multiServiceManager.browser?.sessions.runningChanged.connect(updateGroupedRuntimeDescs);
|
|
84
|
+
multiServiceManager.local.kernels.runningChanged.connect(updateGroupedRuntimeDescs);
|
|
85
|
+
multiServiceManager.local.kernelspecs.specsChanged.connect(updateGroupedRuntimeDescs);
|
|
86
|
+
multiServiceManager.local.sessions.runningChanged.connect(updateGroupedRuntimeDescs);
|
|
87
|
+
multiServiceManager.remote?.runtimesManager.changed.connect(updateGroupedRuntimeDescs);
|
|
88
|
+
multiServiceManager.remote?.environments.changed.connect(updateGroupedRuntimeDescs);
|
|
89
|
+
return () => {
|
|
90
|
+
disposed = true;
|
|
91
|
+
multiServiceManager.browser?.kernels.runningChanged.disconnect(updateGroupedRuntimeDescs);
|
|
92
|
+
multiServiceManager.browser?.kernelspecs.specsChanged.disconnect(updateGroupedRuntimeDescs);
|
|
93
|
+
multiServiceManager.browser?.sessions.runningChanged.disconnect(updateGroupedRuntimeDescs);
|
|
94
|
+
multiServiceManager.local.kernels.runningChanged.disconnect(updateGroupedRuntimeDescs);
|
|
95
|
+
multiServiceManager.local.kernelspecs.specsChanged.disconnect(updateGroupedRuntimeDescs);
|
|
96
|
+
multiServiceManager.local.sessions.runningChanged.disconnect(updateGroupedRuntimeDescs);
|
|
97
|
+
multiServiceManager.remote?.runtimesManager.changed.disconnect(updateGroupedRuntimeDescs);
|
|
98
|
+
multiServiceManager.remote?.environments.changed.disconnect(updateGroupedRuntimeDescs);
|
|
99
|
+
};
|
|
100
|
+
}, [multiServiceManager, preference?.id, translator, filterRuntime, variant]);
|
|
101
|
+
/*
|
|
102
|
+
* The sandbox the session already runs on, shown as chosen.
|
|
103
|
+
*
|
|
104
|
+
* Preferably the very row of the list, so the choice is visibly one of
|
|
105
|
+
* them. A session whose sandbox is not listed — the list may leave the
|
|
106
|
+
* current one out, and the remote ones land late — is named from the
|
|
107
|
+
* specifications instead, so the picker still opens on what is running
|
|
108
|
+
* rather than on nothing.
|
|
109
|
+
*/
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
if (defaultSet) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (sessionContext && groupedRuntimeDescs) {
|
|
115
|
+
const kernelId = sessionContext.session?.kernel?.id;
|
|
116
|
+
if (kernelId) {
|
|
117
|
+
let matched = false;
|
|
118
|
+
Object.entries(groupedRuntimeDescs).forEach(([group, runtimeDescs]) => {
|
|
119
|
+
runtimeDescs.forEach(runtimeDesc => {
|
|
120
|
+
if (runtimeDesc.kernelId === kernelId) {
|
|
121
|
+
matched = true;
|
|
122
|
+
setRuntimeDesc(runtimeDesc);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
if (!matched) {
|
|
127
|
+
if (!remoteModelsReady) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const kernelName = sessionContext.session?.kernel?.name;
|
|
131
|
+
const spec = kernelName
|
|
132
|
+
? sessionContext.specsManager.specs?.kernelspecs[kernelName]
|
|
133
|
+
: undefined;
|
|
134
|
+
if (spec) {
|
|
135
|
+
setRuntimeDesc({
|
|
136
|
+
name: spec.name,
|
|
137
|
+
kernelId,
|
|
138
|
+
language: spec.language,
|
|
139
|
+
displayName: sessionContext.kernelDisplayName,
|
|
140
|
+
location: sessionContext.location ??
|
|
141
|
+
'local',
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
setDefaultSet(true);
|
|
148
|
+
}, [
|
|
149
|
+
defaultSet,
|
|
150
|
+
groupedRuntimeDescs,
|
|
151
|
+
remoteModelsReady,
|
|
152
|
+
sessionContext,
|
|
153
|
+
setRuntimeDesc,
|
|
154
|
+
]);
|
|
155
|
+
/*
|
|
156
|
+
* What a NEW sandbox costs, and the answer the host is given.
|
|
157
|
+
*
|
|
158
|
+
* Only asked when the host wants them: a cell picking among the sandboxes
|
|
159
|
+
* that already run has neither a reservation to make nor an answer to
|
|
160
|
+
* shape. The arithmetic is the launcher's, from its own module.
|
|
161
|
+
*/
|
|
162
|
+
const { refreshCredits } = useIAMStore();
|
|
163
|
+
const [timeLimit, setTimeLimit] = useState(10);
|
|
164
|
+
const [userStorage, setUserStorage] = useState(false);
|
|
165
|
+
const asksForNewSandbox = withNewSandboxControls || !!onTransferChange;
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
if (asksForNewSandbox) {
|
|
168
|
+
refreshCredits();
|
|
169
|
+
}
|
|
170
|
+
}, [asksForNewSandbox]);
|
|
171
|
+
const resolvedBurningRate = runtimeDesc?.burningRate ??
|
|
172
|
+
multiServiceManager.remote?.environments
|
|
173
|
+
.get()
|
|
174
|
+
.find(env => env.name === runtimeDesc?.name)?.burning_rate;
|
|
175
|
+
const allowance = useNewCodeSandboxAllowance(resolvedBurningRate);
|
|
176
|
+
const isNewSandbox = !!runtimeDesc && !runtimeDesc.kernelId;
|
|
177
|
+
const effectiveMaxMinutes = runtimeDesc?.location === 'remote'
|
|
178
|
+
? allowance.effectiveMaxMinutes
|
|
179
|
+
: Math.max(1, allowance.maxFromCredits ?? -1);
|
|
180
|
+
const outOfCredits = allowance.hasKnownCredits &&
|
|
181
|
+
allowance.hasKnownRunAllowance &&
|
|
182
|
+
!allowance.hasRemainingRuns &&
|
|
183
|
+
(allowance.maxFromCredits ?? -1) < Number.EPSILON;
|
|
184
|
+
const variables = useCodeSandboxVariablesTransfer(sessionContext, runtimeDesc, withVariablesTransfer);
|
|
185
|
+
const selectedVariables = variables.selected;
|
|
186
|
+
useEffect(() => {
|
|
187
|
+
if (!onTransferChange) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const maxMinutes = runtimeDesc?.location === 'remote' ? allowance.maxFromCredits : undefined;
|
|
191
|
+
const effectiveTimeLimit = runtimeDesc?.location === 'remote'
|
|
192
|
+
? Math.max(1, Math.min(timeLimit, maxMinutes && maxMinutes > 0 ? maxMinutes : 10))
|
|
193
|
+
: timeLimit;
|
|
194
|
+
const creditsLimit = runtimeDesc?.location === 'remote' && resolvedBurningRate
|
|
195
|
+
? creditsLimitFor(effectiveTimeLimit, resolvedBurningRate)
|
|
196
|
+
: undefined;
|
|
197
|
+
// A new remote sandbox that the account cannot pay for is no answer at
|
|
198
|
+
// all: the dialog is left with nothing to assign rather than with a
|
|
199
|
+
// start that would be refused.
|
|
200
|
+
if (isNewSandbox && runtimeDesc?.location === 'remote') {
|
|
201
|
+
if (!resolvedBurningRate || !Number.isFinite(resolvedBurningRate)) {
|
|
202
|
+
onTransferChange({ runtime: null, selectedVariables });
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (allowance.hasKnownCredits &&
|
|
206
|
+
allowance.hasKnownRunAllowance &&
|
|
207
|
+
!allowance.hasRemainingRuns &&
|
|
208
|
+
(!creditsLimit || creditsLimit <= 0)) {
|
|
209
|
+
onTransferChange({ runtime: null, selectedVariables });
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
onTransferChange({
|
|
214
|
+
runtime: runtimeDesc
|
|
215
|
+
? {
|
|
216
|
+
environmentName: ['browser', 'remote'].includes(runtimeDesc.location)
|
|
217
|
+
? `${runtimeDesc.location}-${runtimeDesc.name}`
|
|
218
|
+
: runtimeDesc.name,
|
|
219
|
+
id: runtimeDesc.kernelId,
|
|
220
|
+
creditsLimit,
|
|
221
|
+
capabilities: userStorage ? ['user_storage'] : undefined,
|
|
222
|
+
}
|
|
223
|
+
: null,
|
|
224
|
+
selectedVariables,
|
|
225
|
+
});
|
|
226
|
+
}, [
|
|
227
|
+
allowance,
|
|
228
|
+
isNewSandbox,
|
|
229
|
+
onTransferChange,
|
|
230
|
+
resolvedBurningRate,
|
|
231
|
+
runtimeDesc,
|
|
232
|
+
selectedVariables,
|
|
233
|
+
timeLimit,
|
|
234
|
+
userStorage,
|
|
235
|
+
]);
|
|
236
|
+
// For cell using submenu instead of group would be nice unfortunately the feature
|
|
237
|
+
// is not yet implemented in the component there has been a not-great demo story.
|
|
238
|
+
// https://github.com/primer/react/pull/3585
|
|
239
|
+
return (_jsxs(_Fragment, { children: [display === 'menu' ? (
|
|
240
|
+
/*
|
|
241
|
+
* Section for Menu display.
|
|
242
|
+
*/
|
|
243
|
+
_jsxs(ActionMenu, { children: [variant === 'cell' ? (_jsx(ActionMenu.Anchor, { children: _jsx(IconButton, { disabled: disabled || groupedRuntimeDescs === null,
|
|
244
|
+
// icon={() => <kernelIcon.react className="dla-Cell-runtime-icon" tag={'span'} />}
|
|
245
|
+
icon: () => (_jsx("span", { className: "dla-Cell-runtime-icon", children: _jsx(CpuIcon, {}) })), "aria-label": trans.__('Assign a Runtime to the Cell.'), title: trans.__('Assign a Runtime to the Cell.'), size: "small", variant: "invisible" }) })) : (_jsxs(ActionMenu.Button, { variant: "default", disabled: disabled || groupedRuntimeDescs === null, children: [_jsx(Text, { fontWeight: 'bold', children: trans.__('Runtime:') }), ' ' + (runtimeDesc?.displayName ?? trans.__('No Runtime'))] })), _jsx(ActionMenu.Overlay, { ...overlayProps, width: "medium", sx: { overflowY: 'auto' }, side: variant === 'cell' ? 'outside-left' : 'outside-right', children: _jsxs(ActionList, { selectionVariant: "single", children: [variant === 'cell' && (_jsxs(ActionList.Item, { selected: runtimeDesc === undefined, onSelect: () => {
|
|
246
|
+
setRuntimeDesc(undefined);
|
|
247
|
+
}, children: [preference?.location && (_jsx(ActionList.LeadingVisual, { children: preference.location === 'local' ? (_jsx(LaptopSimpleIcon, {})) : preference.location === 'browser' ? (_jsx(BrowserIcon, {})) : (_jsx(CloudUploadIcon, {})) })), trans.__('Assign the Notebook Runtime')] }, 'null')), !!preActions && preActions, Object.entries(groupedRuntimeDescs ?? {}).map(([group, runtimeDescs]) => (_jsxs(ActionList.Group, { children: [_jsx(ActionList.GroupHeading, { children: group }), runtimeDescs.map(candidateRuntimeDesc => {
|
|
248
|
+
const annotation = candidateRuntimeDesc.podName
|
|
249
|
+
? ` - ${candidateRuntimeDesc.podName.split('-', 2).reverse()[0]}`
|
|
250
|
+
: candidateRuntimeDesc.kernelId
|
|
251
|
+
? ` - ${candidateRuntimeDesc.kernelId}`
|
|
252
|
+
: '';
|
|
253
|
+
const fullDisplayName = (candidateRuntimeDesc.displayName ?? '') + annotation;
|
|
254
|
+
const displayName = (candidateRuntimeDesc.displayName?.length ?? 0) >
|
|
255
|
+
RUNTIME_DISPLAY_NAME_MAX_LENGTH
|
|
256
|
+
? candidateRuntimeDesc.displayName.slice(0, RUNTIME_DISPLAY_NAME_MAX_LENGTH) + '…'
|
|
257
|
+
: (candidateRuntimeDesc.displayName ?? '');
|
|
258
|
+
return (_jsxs(ActionList.Item, { title: fullDisplayName, selected: (candidateRuntimeDesc.location ===
|
|
259
|
+
runtimeDesc?.location ||
|
|
260
|
+
(isRuntimeRemote(candidateRuntimeDesc.location) &&
|
|
261
|
+
isRuntimeRemote(runtimeDesc?.location ?? 'local'))) &&
|
|
262
|
+
(candidateRuntimeDesc.kernelId ??
|
|
263
|
+
candidateRuntimeDesc.name) ===
|
|
264
|
+
(runtimeDesc?.kernelId ?? runtimeDesc?.name), onSelect: () => {
|
|
265
|
+
setRuntimeDesc(candidateRuntimeDesc);
|
|
266
|
+
}, children: [_jsx(ActionList.LeadingVisual, { children: candidateRuntimeDesc.location === 'local' ? (_jsx(LaptopSimpleIcon, {})) : candidateRuntimeDesc.location === 'browser' ? (_jsx(BrowserIcon, {})) : (_jsx(CloudUploadIcon, {})) }), displayName + annotation.slice(0, 10)] }, candidateRuntimeDesc.name));
|
|
267
|
+
})] }, group))), !!postActions && (_jsxs(_Fragment, { children: [_jsx(ActionList.Divider, {}), postActions] }))] }) })] })) : (
|
|
268
|
+
/*
|
|
269
|
+
* Section for Radio display.
|
|
270
|
+
*/
|
|
271
|
+
_jsxs(_Fragment, { children: [defaultSet && (_jsx(RadioGroup, { name: "kernel-options", "aria-labelledby": "kernel-options", children: Object.entries(groupedRuntimeDescs ?? {}).map(([group, runtimeDescs]) => (_jsxs(Box, { children: [_jsx(Box, { as: "h4", style: { marginTop: 0 }, children: group }), runtimeDescs.map(k => {
|
|
272
|
+
return (
|
|
273
|
+
// A kernel identifies a runtime that already runs; an
|
|
274
|
+
// environment to start one in has none, and is named
|
|
275
|
+
// by where it runs and what it runs.
|
|
276
|
+
_jsxs(Box, { title: k.name, children: [_jsxs(FormControl, { children: [_jsx(Radio, { value: k.kernelId, onChange: () => {
|
|
277
|
+
setRuntimeDesc(k);
|
|
278
|
+
}, checked: (k.location === runtimeDesc?.location ||
|
|
279
|
+
(isRuntimeRemote(k.location) &&
|
|
280
|
+
isRuntimeRemote(runtimeDesc?.location ?? 'local'))) &&
|
|
281
|
+
(k.kernelId ?? k.name) ===
|
|
282
|
+
(runtimeDesc?.kernelId ?? runtimeDesc?.name) }), _jsx(FormControl.Label, { children: _jsxs(Box, { display: "flex", children: [_jsx(Box, { children: k.displayName }), k.kernelId && k.location === 'remote' && (_jsx(Box, { ml: 3, mt: 1, children: _jsx(CreditsIndicator, { kernelId: k.kernelId, serviceManager: multiServiceManager.remote }, "credits-indicator") }))] }) }), _jsx(FormControl.Caption, { children: _jsxs(LabelGroup, { sx: { marginTop: 1 }, children: [_jsx(Label, { variant: "secondary", children: k.name }), _jsx(Label, { variant: "secondary", sx: { marginLeft: 1 }, children: k.location }), k.burningRate && (_jsxs(Label, { variant: "sponsors", sx: { marginLeft: 1 }, children: [k.burningRate, " credits/second"] })), k.gpu && (_jsx(Label, { variant: "success", sx: { marginLeft: 1 }, children: "GPU" }))] }) })] }), _jsx(ActionList.Divider, {})] }, `${k.location}:${k.kernelId ?? k.name}`));
|
|
283
|
+
})] }, group))) })), !!postActions && _jsx(_Fragment, { children: postActions })] })), withNewSandboxControls && isNewSandbox && (
|
|
284
|
+
// The user asked for a NEW sandbox: the questions are the launcher's,
|
|
285
|
+
// asked through the launcher's own controls. A sandbox of this page
|
|
286
|
+
// or of this server reserves nothing, so only the time of a remote
|
|
287
|
+
// one is asked for.
|
|
288
|
+
_jsx(NewCodeSandboxControls, { withReservation: runtimeDesc?.location === 'remote', burningRate: resolvedBurningRate, timeLimit: timeLimit, onTimeChange: setTimeLimit, max: effectiveMaxMinutes, disabled: outOfCredits, error: runtimeDesc?.location !== 'remote'
|
|
289
|
+
? undefined
|
|
290
|
+
: outOfCredits && (allowance.maxFromCredits ?? -1) >= 0
|
|
291
|
+
? 'You must add credits to your account.'
|
|
292
|
+
: timeLimit === 0
|
|
293
|
+
? 'You must set a time limit.'
|
|
294
|
+
: undefined, userStorage: userStorage, onUserStorageToggle: () => setUserStorage(current => !current) })), variables.available && (_jsx(CodeSandboxVariables, { selectedVariables: variables.selected, setSelectVariable: variables.setSelected, transferVariables: variables.transfer, setTransferVariable: variables.setTransfer, kernelVariables: variables.variables, translator: translator }))] }));
|
|
295
|
+
}
|
|
296
|
+
export default CodeSandboxPicker;
|
package/lib/components/{runtimes/RuntimePickerCell.d.ts → code-sandboxes/CodeSandboxPickerCell.d.ts}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ISessionContext } from '@jupyterlab/apputils';
|
|
2
2
|
import { CodeCellModel } from '@jupyterlab/cells';
|
|
3
3
|
import type { IMarkdownParser, IRenderMime } from '@jupyterlab/rendermime';
|
|
4
|
-
import {
|
|
4
|
+
import { type ICodeSandboxPickerProps } from './CodeSandboxPicker';
|
|
5
5
|
/**
|
|
6
|
-
* {@link
|
|
6
|
+
* {@link CodeSandboxPickerCell} properties
|
|
7
7
|
*/
|
|
8
|
-
export type
|
|
8
|
+
export type ICodeSandboxPickerCellProps = Pick<ICodeSandboxPickerProps, 'multiServiceManager' | 'preference' | 'translator'> & {
|
|
9
9
|
/**
|
|
10
10
|
* Callback to allow the user to login
|
|
11
11
|
*/
|
|
@@ -30,5 +30,5 @@ export type IRuntimePickerCellProps = Pick<IRuntimePickerBaseProps, 'multiServic
|
|
|
30
30
|
/**
|
|
31
31
|
* Runtime picker component for a cell.
|
|
32
32
|
*/
|
|
33
|
-
export declare function
|
|
34
|
-
export default
|
|
33
|
+
export declare function CodeSandboxPickerCell(props: ICodeSandboxPickerCellProps): JSX.Element;
|
|
34
|
+
export default CodeSandboxPickerCell;
|
package/lib/components/{runtimes/RuntimePickerCell.js → code-sandboxes/CodeSandboxPickerCell.js}
RENAMED
|
@@ -12,13 +12,13 @@ import { isRuntimeRemote } from '../../runtimes';
|
|
|
12
12
|
import { RuntimeSnippetsFacade } from '../../jupyter';
|
|
13
13
|
import { ExternalTokenSilentLogin } from '@datalayer/core/lib/components/iam';
|
|
14
14
|
import { SnippetDialog } from '../../components/snippets/SnippetDialog';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
15
|
+
import { CodeSandboxPicker, } from './CodeSandboxPicker';
|
|
16
|
+
import { CodeSandboxLauncher } from './CodeSandboxLauncher';
|
|
17
|
+
import { CodeSandboxCellVariablesDialog } from './CodeSandboxCellVariablesDialog';
|
|
18
18
|
/**
|
|
19
19
|
* Runtime picker component for a cell.
|
|
20
20
|
*/
|
|
21
|
-
export function
|
|
21
|
+
export function CodeSandboxPickerCell(props) {
|
|
22
22
|
const { logIn, markdownParser, model, preference, sanitizer, multiServiceManager, sessionContext, translator, } = props;
|
|
23
23
|
const { token } = useIAMStore();
|
|
24
24
|
const { configuration } = useCoreStore();
|
|
@@ -97,8 +97,8 @@ export function RuntimePickerCell(props) {
|
|
|
97
97
|
setIsKernelDialogOpen(false);
|
|
98
98
|
}, [setSelectedRuntimeDesc]);
|
|
99
99
|
const datalayerMeta = model.getMetadata('datalayer') ?? {};
|
|
100
|
-
return (_jsxs(_Fragment, { children: [_jsx(
|
|
100
|
+
return (_jsxs(_Fragment, { children: [_jsx(CodeSandboxPicker, { display: "menu", filterRuntime: filterKernel, preference: preference, multiServiceManager: multiServiceManager, runtimeDesc: datalayerMeta.kernel ? datalayerMeta.kernel : undefined, setRuntimeDesc: setSelectedRuntimeDesc, variant: 'cell', preActions: _jsxs(ActionList.Item, { disabled: !multiServiceManager.remote, onSelect: setCell, selected: hasCellRuntime, title: !multiServiceManager.remote
|
|
101
101
|
? 'You are not connected with Datalayer.'
|
|
102
|
-
: 'Assign a new temporary Runtime on each Cell execution.', children: [_jsx(ActionList.LeadingVisual, { children: _jsx(CloudUploadIcon, {}) }), trans.__('Assign a Cell Runtime')] }), postActions: token || !logIn ? (_jsxs(_Fragment, { children: [RuntimeSnippetsFacade.supports(preference?.language ?? '') && (_jsx(ActionList.Item, { onSelect: openVariableDialog, disabled: !isForeign, title: trans.__('Define variables to transfer between the document kernel and the cell kernel.'), children: trans.__('Define Cell Variables Transfer') })), !configuration.whiteLabel && (_jsx(ActionList.Item, { onSelect: openSnippetDialog, disabled: snippets.length === 0, title: trans.__('Inject a code snippet at the end of the cell.'), children: trans.__('Inject Code Snippet') }))] })) : (_jsx(ActionList.Item, { onSelect: props.logIn, title: 'Runtime Provider.', children: _jsx(ExternalTokenSilentLogin, { message: "Click to sign in" }) })), translator: translator }), isVariableDialogOpen && (_jsx(
|
|
102
|
+
: 'Assign a new temporary Runtime on each Cell execution.', children: [_jsx(ActionList.LeadingVisual, { children: _jsx(CloudUploadIcon, {}) }), trans.__('Assign a Cell Runtime')] }), postActions: token || !logIn ? (_jsxs(_Fragment, { children: [RuntimeSnippetsFacade.supports(preference?.language ?? '') && (_jsx(ActionList.Item, { onSelect: openVariableDialog, disabled: !isForeign, title: trans.__('Define variables to transfer between the document kernel and the cell kernel.'), children: trans.__('Define Cell Variables Transfer') })), !configuration.whiteLabel && (_jsx(ActionList.Item, { onSelect: openSnippetDialog, disabled: snippets.length === 0, title: trans.__('Inject a code snippet at the end of the cell.'), children: trans.__('Inject Code Snippet') }))] })) : (_jsx(ActionList.Item, { onSelect: props.logIn, title: 'Runtime Provider.', children: _jsx(ExternalTokenSilentLogin, { message: "Click to sign in" }) })), translator: translator }), isVariableDialogOpen && (_jsx(CodeSandboxCellVariablesDialog, { model: model, onClose: closeVariableDialog, preference: preference, sessionContext: sessionContext, translator: translator })), isSnippetDialogOpen && (_jsx(SnippetDialog, { language: language, model: model, snippets: snippets, onClose: closeSnippetDialog, markdownParser: markdownParser, sanitizer: sanitizer })), isKernelDialogOpen && (_jsx(CodeSandboxLauncher, { manager: multiServiceManager.remote, onSubmit: onStartRemote, startRuntime: 'defer', submitLabel: "Assign", markdownParser: markdownParser, sanitizer: sanitizer }))] }));
|
|
103
103
|
}
|
|
104
|
-
export default
|
|
104
|
+
export default CodeSandboxPickerCell;
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* TODO this should be configurable
|
|
5
5
|
*/
|
|
6
|
-
export declare const
|
|
6
|
+
export declare const MAXIMAL_CODE_SANDBOX_TIME_RESERVATION_MINUTES: number;
|
|
7
7
|
/**
|
|
8
8
|
* Time control properties
|
|
9
9
|
*/
|
|
10
|
-
export interface
|
|
10
|
+
export interface ICodeSandboxReservationControlProps {
|
|
11
11
|
/**
|
|
12
12
|
* Callback on add credits button
|
|
13
13
|
*/
|
|
@@ -44,4 +44,4 @@ export interface IKernelReservationControlProps {
|
|
|
44
44
|
/**
|
|
45
45
|
* Runtime reservation control
|
|
46
46
|
*/
|
|
47
|
-
export declare function
|
|
47
|
+
export declare function CodeSandboxReservationControl(props: ICodeSandboxReservationControlProps): JSX.Element;
|