@datalayer/agent-runtimes 1.0.20 → 1.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +2 -2
  2. package/lib/AgentNode.js +26 -26
  3. package/lib/chat/Chat.d.ts +1 -1
  4. package/lib/chat/Chat.js +2 -2
  5. package/lib/chat/base/ChatBase.js +44 -9
  6. package/lib/chat/document/EphemeralDocument.d.ts +12 -1
  7. package/lib/chat/document/EphemeralDocument.js +4 -4
  8. package/lib/chat/notebook/EphemeralNotebook.d.ts +11 -1
  9. package/lib/chat/notebook/EphemeralNotebook.js +13 -2
  10. package/lib/collaboration/DatalayerCollaborationProvider.d.ts +1 -1
  11. package/lib/collaboration/DatalayerCollaborationProvider.js +5 -5
  12. package/lib/components/code-sandboxes/CodeSandboxLauncher.d.ts +59 -0
  13. package/lib/components/code-sandboxes/CodeSandboxLauncher.js +272 -0
  14. package/lib/components/code-sandboxes/CodeSandboxPicker.d.ts +71 -0
  15. package/lib/components/code-sandboxes/CodeSandboxPicker.js +163 -0
  16. package/lib/components/code-sandboxes/NewCodeSandboxControls.d.ts +42 -0
  17. package/lib/components/code-sandboxes/NewCodeSandboxControls.js +76 -0
  18. package/lib/components/code-sandboxes/index.d.ts +3 -0
  19. package/lib/components/code-sandboxes/index.js +7 -0
  20. package/lib/components/progress/CreditsIndicator.d.ts +7 -0
  21. package/lib/components/progress/CreditsIndicator.js +2 -2
  22. package/lib/components/runtimes/RuntimeLauncherDialog.d.ts +5 -55
  23. package/lib/components/runtimes/RuntimeLauncherDialog.js +5 -269
  24. package/lib/components/runtimes/RuntimePickerBase.d.ts +6 -67
  25. package/lib/components/runtimes/RuntimePickerBase.js +6 -151
  26. package/lib/components/runtimes/RuntimePickerCell.d.ts +2 -2
  27. package/lib/components/runtimes/RuntimePickerCell.js +4 -4
  28. package/lib/components/runtimes/RuntimePickerNotebook.js +35 -70
  29. package/lib/components/runtimes/RuntimeReservationControl.js +8 -1
  30. package/lib/components/runtimes/RuntimeSimplePicker.js +1 -1
  31. package/lib/components/runtimes/RuntimeUtils.js +34 -18
  32. package/lib/components/runtimes/index.d.ts +1 -0
  33. package/lib/components/runtimes/index.js +2 -0
  34. package/lib/context/CostUsageChart.d.ts +2 -2
  35. package/lib/context/CostUsageChart.js +7 -7
  36. package/lib/context/TokenUsageChart.d.ts +2 -2
  37. package/lib/context/TokenUsageChart.js +6 -6
  38. package/lib/context/TurnGraphChart.d.ts +1 -1
  39. package/lib/context/TurnGraphChart.js +6 -6
  40. package/lib/examples/AgentEvalsExample.js +1 -1
  41. package/lib/examples/AgentGuardrailsExample.js +3 -3
  42. package/lib/examples/AgentInferenceProviderExample.js +1 -1
  43. package/lib/examples/AgentMonitoringExample.js +6 -6
  44. package/lib/examples/AgentOtelExample.d.ts +2 -2
  45. package/lib/examples/AgentOtelExample.js +5 -5
  46. package/lib/examples/AgentspecsExample.js +1 -1
  47. package/lib/examples/NotebookCollaborationExample.js +8 -8
  48. package/lib/examples/main.js +5 -5
  49. package/lib/examples2/DatalayerNotebookExample.js +8 -8
  50. package/lib/examples2/main.js +5 -5
  51. package/lib/hooks/useAgentRuntimes.js +3 -3
  52. package/lib/hooks/useMonitoring.d.ts +5 -5
  53. package/lib/hooks/useMonitoring.js +10 -10
  54. package/lib/protocols/AGUIAdapter.js +4 -0
  55. package/lib/protocols/VercelAIAdapter.js +3 -0
  56. package/lib/types/chat.d.ts +23 -0
  57. package/lib/types/tools.d.ts +11 -0
  58. package/package.json +3 -3
  59. package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
  60. package/lib/components/toolbars/AssignmentEditorToolbar.d.ts +0 -4
  61. package/lib/components/toolbars/AssignmentEditorToolbar.js +0 -18
  62. package/lib/components/toolbars/DocumentEditorToolbar.d.ts +0 -2
  63. package/lib/components/toolbars/DocumentEditorToolbar.js +0 -12
  64. package/lib/components/toolbars/NotebookEditorToolbar.d.ts +0 -29
  65. package/lib/components/toolbars/NotebookEditorToolbar.js +0 -30
@@ -11,7 +11,7 @@ import { ConsumptionBar } from '@datalayer/core/lib/components/progress/Consumpt
11
11
  * Credits indicator component.
12
12
  */
13
13
  export function CreditsIndicator(props) {
14
- const { serviceManager, kernelId, navigateTo, onClick, onUpdate } = props;
14
+ const { serviceManager, kernelId, navigateTo, onClick, onUpdate, paddingLeft, paddingRight, paddingTop, paddingBottom, } = props;
15
15
  const navigate = useNavigate();
16
16
  const [model, setModel] = useState();
17
17
  useEffect(() => {
@@ -19,5 +19,5 @@ export function CreditsIndicator(props) {
19
19
  setModel(model);
20
20
  });
21
21
  }, [kernelId, serviceManager]);
22
- return model ? (_jsx(Box, { display: "flex", style: { alignItems: 'center' }, children: _jsx(ConsumptionBar, { startedAt: parseFloat(model.started_at), expiredAt: model.expired_at ? parseFloat(model.expired_at) : undefined, burningRate: model.burning_rate, onClick: onClick ?? (navigateTo ? () => navigate(navigateTo) : undefined), onUpdate: onUpdate, style: { cursor: 'pointer' } }) })) : (_jsx(_Fragment, {}));
22
+ return model ? (_jsx(Box, { display: "flex", style: { alignItems: 'center' }, children: _jsx(ConsumptionBar, { startedAt: parseFloat(model.started_at), expiredAt: model.expired_at ? parseFloat(model.expired_at) : undefined, burningRate: model.burning_rate, onClick: onClick ?? (navigateTo ? () => navigate(navigateTo) : undefined), onUpdate: onUpdate, style: { cursor: 'pointer' }, paddingLeft: paddingLeft, paddingRight: paddingRight, paddingTop: paddingTop, paddingBottom: paddingBottom }) })) : (_jsx(_Fragment, {}));
23
23
  }
@@ -1,57 +1,7 @@
1
- import type { IMarkdownParser, IRenderMime } from '@jupyterlab/rendermime';
2
- import type { IRemoteServicesManager } from '../../runtimes';
3
- import type { ICodeSandboxSnapshot, IRuntimeDesc } from '../../models';
4
1
  /**
5
- * {@link RuntimeLauncherDialog} properties.
2
+ * Moved: the launcher lives with the code sandboxes now.
3
+ *
4
+ * @deprecated Import from `components/code-sandboxes/CodeSandboxLauncher`.
5
+ * @module components/runtimes/RuntimeLauncherDialog
6
6
  */
7
- export interface IRuntimeLauncherDialogProps {
8
- /**
9
- * Dialog title
10
- */
11
- dialogTitle?: string;
12
- /**
13
- * Remote Jupyter service manager
14
- */
15
- manager: IRemoteServicesManager;
16
- /**
17
- * Form submission callback
18
- */
19
- onSubmit: (spec?: IRuntimeDesc) => void;
20
- /**
21
- * Whether to start the kernel or not.
22
- *
23
- * If `with-example`, a kernel will be started an
24
- * an example document will be opened (if available).
25
- * If `defer`, a kernel will not be started but the
26
- * kernel params will have a `creditsLimit` defined
27
- * for spinning a runtime.
28
- *
29
- * Default: `true`
30
- */
31
- startRuntime?: boolean | 'with-example' | 'defer';
32
- /**
33
- * Markdown parser
34
- */
35
- markdownParser?: IMarkdownParser;
36
- /**
37
- * If provided the kernel will be started and will
38
- * restore the provided snapshot in the kernel.
39
- */
40
- kernelSnapshot?: ICodeSandboxSnapshot;
41
- /**
42
- * HTML sanitizer
43
- */
44
- sanitizer?: IRenderMime.ISanitizer;
45
- /**
46
- * Upgrade subscription URL
47
- */
48
- upgradeSubscription?: string;
49
- /**
50
- * Optional submit button label override.
51
- */
52
- submitLabel?: string;
53
- }
54
- /**
55
- * Start Runtime Launcher Dialog.
56
- */
57
- export declare function RuntimeLauncherDialog(props: IRuntimeLauncherDialogProps): JSX.Element;
7
+ export { CodeSandboxLauncher, RuntimeLauncherDialog, type ICodeSandboxLauncherProps, type IRuntimeLauncherDialogProps, } from '../code-sandboxes/CodeSandboxLauncher';
@@ -1,275 +1,11 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
1
  /*
3
2
  * Copyright (c) 2025-2026 Datalayer, Inc.
4
3
  * Distributed under the terms of the Modified BSD License.
5
4
  */
6
- import { useCallback, useEffect, useMemo, useState } from 'react';
7
- import { useIsMounted } from 'usehooks-ts';
8
- import { Button, FormControl, Select, Spinner, Text, TextInput, ToggleSwitch, Tooltip, IconButton, } from '@primer/react';
9
- import { Dialog } from '@primer/react/experimental';
10
- import { AlertIcon } from '@primer/octicons-react';
11
- import { Box } from '@datalayer/primer-addons';
12
- import { useJupyterReactStore } from '@datalayer/jupyter-react';
13
- import { USAGE_ROUTE } from '@datalayer/core/lib/routes';
14
- import { useNavigate } from '@datalayer/core/lib/hooks';
15
- import { NO_RUNTIME_AVAILABLE_LABEL } from '@datalayer/core/lib/i18n';
16
- import { iamStore, useCoreStore, useIAMStore } from '../../state/substates';
17
- import { createNotebook, sleep } from '@datalayer/core/lib/utils';
18
- import { Markdown } from '@datalayer/core/lib/components/display';
19
- import { Timer } from '@datalayer/core/lib/components/progress';
20
- import { FlashClosable } from '@datalayer/core/lib/components/flashes';
21
- import { RuntimeReservationControl, MAXIMAL_RUNTIME_TIME_RESERVATION_MINUTES, } from './RuntimeReservationControl';
22
5
  /**
23
- * Initial time in milliseconds before retrying in case no kernels are available
6
+ * Moved: the launcher lives with the code sandboxes now.
7
+ *
8
+ * @deprecated Import from `components/code-sandboxes/CodeSandboxLauncher`.
9
+ * @module components/runtimes/RuntimeLauncherDialog
24
10
  */
25
- const NOT_AVAILABLE_INIT_RETRY = 10_000;
26
- /**
27
- * Number of trials in case of unavailable code sandboxes
28
- */
29
- const NOT_AVAILABLE_RETRIES = 5;
30
- /**
31
- * Start Runtime Launcher Dialog.
32
- */
33
- export function RuntimeLauncherDialog(props) {
34
- const { dialogTitle, kernelSnapshot, manager, onSubmit, markdownParser, sanitizer, upgradeSubscription, submitLabel, startRuntime = true, } = props;
35
- const hasExample = startRuntime === 'with-example';
36
- const shouldStartRuntime = startRuntime !== 'defer';
37
- const user = iamStore.getState().user;
38
- const environments = manager.environments.get();
39
- const { configuration } = useCoreStore();
40
- const { credits, refreshCredits } = useIAMStore();
41
- let navigate;
42
- try {
43
- // eslint-disable-next-line react-hooks/rules-of-hooks
44
- navigate = useNavigate();
45
- }
46
- catch (reason) {
47
- // TODO when would this component be shown outside of a react-router? navigation is only available within a react-router.
48
- console.warn(reason);
49
- }
50
- const jupyterReactStore = useJupyterReactStore();
51
- const jupyterLabAdapter = jupyterReactStore.jupyterLabAdapter;
52
- const [selection, setSelection] = useState((kernelSnapshot?.environment || environments[0]?.name) ?? '');
53
- const [timeLimit, setTimeLimit] = useState(10);
54
- const [runtimeName, setRuntimeName] = useState(environments[0]?.runtime?.givenNameTemplate || environments[0]?.title || '');
55
- // Whether the runtim name has been changed by the user or not
56
- const [hasCustomRuntimeName, setHasCustomRuntimeName] = useState(false);
57
- const [userStorage, setUserStorage] = useState(false);
58
- const [openExample, setOpenExample] = useState(false);
59
- const [waitingForRuntime, setWaitingForRuntime] = useState(false);
60
- const [error, setError] = useState();
61
- const [flashLevel, setFlashLevel] = useState('danger');
62
- const isMounted = useIsMounted();
63
- useEffect(() => {
64
- if (shouldStartRuntime) {
65
- refreshCredits();
66
- }
67
- }, [shouldStartRuntime]);
68
- const spec = useMemo(() => environments.find(spec => spec.name === selection), [environments, selection]);
69
- const description = spec?.description ?? '';
70
- const burningRate = spec?.burning_rate ?? 1;
71
- const creditsToMinutes = 1.0 / burningRate / 60.0;
72
- const includedRuns = user?.subscription?.usage?.included_runs ??
73
- user?.subscription?.included_runs;
74
- const currentRuns = user?.subscription?.usage?.current_runs ??
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);
94
- const handleSelectionChange = useCallback((e) => {
95
- const selection = e.target.value;
96
- setSelection(selection);
97
- if (!hasCustomRuntimeName) {
98
- const spec = environments.find(env => env.name === selection);
99
- setRuntimeName(spec?.runtime?.givenNameTemplate || spec?.title || '');
100
- }
101
- }, [setSelection, hasCustomRuntimeName]);
102
- const handleSubmitRuntime = useCallback(async () => {
103
- if (selection) {
104
- setError(undefined);
105
- setWaitingForRuntime(shouldStartRuntime);
106
- const spec = environments.find(s => s.name === selection);
107
- const desc = {
108
- name: selection,
109
- language: spec?.language ?? '',
110
- location: 'remote',
111
- displayName: runtimeName ?? spec?.title,
112
- };
113
- const creditsLimit = Math.min(timeLimit, MAXIMAL_RUNTIME_TIME_RESERVATION_MINUTES) /
114
- creditsToMinutes;
115
- desc.params = {};
116
- if (startRuntime === 'defer') {
117
- desc.params['creditsLimit'] = creditsLimit;
118
- }
119
- if (userStorage) {
120
- desc.params['capabilities'] = ['user_storage'];
121
- }
122
- let success = true;
123
- if (shouldStartRuntime) {
124
- success = false;
125
- let availableTrial = 1;
126
- let retryDelay = NOT_AVAILABLE_INIT_RETRY;
127
- // Should return success status.
128
- const startNewKernel = async () => {
129
- try {
130
- const connection = await manager.runtimesManager.startNew({
131
- environmentName: selection,
132
- type: 'notebook',
133
- givenName: runtimeName,
134
- creditsLimit: creditsLimit,
135
- capabilities: userStorage ? ['user_storage'] : undefined,
136
- snapshot: kernelSnapshot?.id,
137
- }, {
138
- username: user?.handle,
139
- handleComms: true,
140
- });
141
- desc.kernelId = connection.id;
142
- if (jupyterLabAdapter?.jupyterLab && hasExample && openExample) {
143
- const example = environments.find(spec => spec.name === selection)?.example;
144
- if (example) {
145
- const options = {
146
- kernelId: connection.id,
147
- kernelName: connection.name,
148
- };
149
- createNotebook({
150
- app: jupyterLabAdapter.jupyterLab,
151
- name: selection,
152
- url: example,
153
- options,
154
- });
155
- }
156
- }
157
- // Close the connection as we are not using it.
158
- connection.dispose();
159
- }
160
- catch (error) {
161
- let msg = _jsx(Text, { children: "Failed to create the remote runtime\u2026" });
162
- let level = 'danger';
163
- let retry = false;
164
- if (error.response?.status === 503) {
165
- if (availableTrial++ <= NOT_AVAILABLE_RETRIES) {
166
- retry = true;
167
- msg = (_jsxs(Text, { children: ["The runtime you have requested is currently not available due to resource limitations. Leave this dialog open, new trial in ", _jsx(Timer, { duration: retryDelay * 0.001 }), ` (${availableTrial - 1}/${NOT_AVAILABLE_RETRIES}).`] }));
168
- }
169
- else {
170
- msg = _jsx(Text, { children: NO_RUNTIME_AVAILABLE_LABEL });
171
- }
172
- level = 'warning';
173
- }
174
- else if (error.name === 'MaxRuntimesExceededError') {
175
- msg = (_jsx(Text, { children: "You reached your remote runtime limits. Stop existing runtimes before starting new ones." }));
176
- level = 'warning';
177
- }
178
- else if (error.name === 'RuntimeUnreachable') {
179
- msg = (_jsx(Text, { children: "The runtime has been created but can not be accessed. Please contact your IT support team to report this issue." }));
180
- }
181
- setFlashLevel(level);
182
- console.error(msg, error);
183
- setError(msg);
184
- if (retry) {
185
- await sleep(retryDelay);
186
- retryDelay *= 2;
187
- if (isMounted()) {
188
- return await startNewKernel();
189
- }
190
- }
191
- return false;
192
- }
193
- finally {
194
- setWaitingForRuntime(false);
195
- }
196
- return true;
197
- };
198
- // Start the kernel if the reservation succeeded.
199
- success = await startNewKernel();
200
- }
201
- if (success && isMounted()) {
202
- if (!shouldStartRuntime) {
203
- setWaitingForRuntime(false);
204
- }
205
- onSubmit(desc);
206
- }
207
- }
208
- }, [
209
- manager,
210
- selection,
211
- startRuntime,
212
- runtimeName,
213
- onSubmit,
214
- userStorage,
215
- openExample,
216
- jupyterLabAdapter,
217
- timeLimit,
218
- shouldStartRuntime,
219
- isMounted,
220
- ]);
221
- const handleUserStorageChange = useCallback((e) => {
222
- e.preventDefault();
223
- setUserStorage(!userStorage);
224
- }, [userStorage]);
225
- const handleSwitchClick = useCallback((e) => {
226
- e.preventDefault();
227
- setOpenExample(!openExample);
228
- }, [openExample]);
229
- const handleUpgrade = useCallback(() => {
230
- if (upgradeSubscription) {
231
- navigate?.(upgradeSubscription);
232
- }
233
- }, [navigate, upgradeSubscription]);
234
- const handleKernelNameChange = useCallback((e) => {
235
- if (typeof e.target.value === 'string') {
236
- setRuntimeName(e.target.value);
237
- setHasCustomRuntimeName(true);
238
- }
239
- }, []);
240
- // TODO title color is enforced for JupyterLab.
241
- // 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 Runtime' }), onClose: () => {
243
- onSubmit(undefined);
244
- }, footerButtons: [
245
- {
246
- buttonType: 'default',
247
- onClick: () => {
248
- onSubmit(undefined);
249
- },
250
- content: 'Cancel',
251
- disabled: waitingForRuntime,
252
- },
253
- {
254
- buttonType: 'primary',
255
- onClick: handleSubmitRuntime,
256
- content: waitingForRuntime ? (_jsx(Spinner, { size: "small" })) : ((submitLabel ?? ((startRuntime ?? true) ? 'Launch' : 'Assign'))),
257
- disabled: waitingForRuntime || !selection || outOfCredits,
258
- autoFocus: true,
259
- },
260
- ], children: _jsxs(Box, { as: "form", onKeyDown: event => {
261
- if (event.defaultPrevented) {
262
- return;
263
- }
264
- if (event.key === 'Enter') {
265
- event.preventDefault();
266
- handleSubmitRuntime();
267
- }
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 }) })) : (description) }) })] }), startRuntime && (_jsx(RuntimeReservationControl, { addCredits: navigate
269
- ? () => {
270
- navigate(USAGE_ROUTE);
271
- }
272
- : undefined, disabled: outOfCredits, label: 'Time reservation', max: effectiveMaxMinutes, time: timeLimit, burningRate: burningRate, onTimeChange: setTimeLimit, error: outOfCredits ? 'You must add credits to your account.' : undefined })), !configuration.whiteLabel && (_jsxs(FormControl, { layout: "horizontal", children: [_jsxs(FormControl.Label, { id: "user-storage-label", children: ["User storage", _jsx(Tooltip, { text: 'The runtime will be slower to start.', direction: "e", style: { marginLeft: 3 }, children: _jsx(IconButton, { icon: AlertIcon, "aria-label": "", variant: "invisible" }) })] }), _jsx(ToggleSwitch, { checked: userStorage, size: "small", onClick: handleUserStorageChange, "aria-labelledby": "user-storage-label" })] })), _jsxs(FormControl, { sx: { paddingTop: '10px' }, children: [_jsx(FormControl.Label, { children: "Runtime name" }), _jsx(TextInput, { name: "name", value: runtimeName, onChange: handleKernelNameChange, block: true })] }), hasExample &&
273
- jupyterLabAdapter?.jupyterLab &&
274
- !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
- }
11
+ export { CodeSandboxLauncher, RuntimeLauncherDialog, } from '../code-sandboxes/CodeSandboxLauncher';
@@ -1,69 +1,8 @@
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 { IMultiServiceManager } from '../../runtimes';
6
- type IDisplayMode = 'menu' | 'radio';
7
1
  /**
8
- * {@link RuntimePickerBase} properties
2
+ * Moved: the picker lives with the code sandboxes now.
3
+ *
4
+ * @deprecated Import from `components/code-sandboxes/CodeSandboxPicker`.
5
+ * @module components/runtimes/RuntimePickerBase
9
6
  */
10
- export interface IRuntimePickerBaseProps {
11
- /**
12
- * The display mode.
13
- */
14
- display: IDisplayMode;
15
- /**
16
- * Additional actions items to be placed at the top of the picker
17
- */
18
- preActions?: ReactNode;
19
- /**
20
- * Additional actions items to be placed at the bottom of the picker
21
- */
22
- postActions?: ReactNode;
23
- /**
24
- * Whether the picker is disabled or not.
25
- */
26
- disabled?: boolean;
27
- /**
28
- * Runtime description passing this filter function will be displayed.
29
- */
30
- filterRuntime?: (desc: IRuntimeDesc) => boolean;
31
- /**
32
- * Session preference.
33
- */
34
- preference?: {
35
- id?: string;
36
- kernelDisplayName?: string;
37
- language?: string;
38
- location?: string;
39
- };
40
- /**
41
- * Runtime description.
42
- */
43
- runtimeDesc?: IRuntimeDesc;
44
- /**
45
- * Set runtime description.
46
- */
47
- setRuntimeDesc: (desc?: IRuntimeDesc) => void;
48
- /**
49
- * Document session context.
50
- */
51
- sessionContext?: ISessionContext;
52
- /**
53
- * Application service manager
54
- */
55
- multiServiceManager: IMultiServiceManager;
56
- /**
57
- * Application translator.
58
- */
59
- translator?: ITranslator;
60
- /**
61
- * Change the look depending on the menu integration.
62
- */
63
- variant?: 'document' | 'cell';
64
- }
65
- /**
66
- * Base Kernel Picker component.
67
- */
68
- export declare function RuntimePickerBase(props: IRuntimePickerBaseProps): ReactElement;
69
- export default RuntimePickerBase;
7
+ export { CodeSandboxPicker, RuntimePickerBase, type ICodeSandboxPickerProps, type IRuntimePickerBaseProps, } from '../code-sandboxes/CodeSandboxPicker';
8
+ export { default } from '../code-sandboxes/CodeSandboxPicker';
@@ -1,157 +1,12 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
1
  /*
3
2
  * Copyright (c) 2025-2026 Datalayer, Inc.
4
3
  * Distributed under the terms of the Modified BSD License.
5
4
  */
6
- import { 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 '../../components/progress';
15
- import { isRuntimeRemote } from '../../runtimes';
16
- import { getGroupedRuntimeDescs } from './RuntimeUtils';
17
5
  /**
18
- * Maximal runtime display name length after which it is trimmed.
6
+ * Moved: the picker lives with the code sandboxes now.
7
+ *
8
+ * @deprecated Import from `components/code-sandboxes/CodeSandboxPicker`.
9
+ * @module components/runtimes/RuntimePickerBase
19
10
  */
20
- const RUNTIME_DISPLAY_NAME_MAX_LENGTH = 25;
21
- /**
22
- * Base Kernel Picker component.
23
- */
24
- export function RuntimePickerBase(props) {
25
- const { disabled, display, filterRuntime, multiServiceManager, postActions, preActions, preference, runtimeDesc, sessionContext, setRuntimeDesc, translator, variant, } = props;
26
- const [groupedRuntimeDescs, setGroupedRuntimeDescs] = useState(getGroupedRuntimeDescs(multiServiceManager, preference?.id, translator, filterRuntime, variant));
27
- const trans = useMemo(() => (translator ?? nullTranslator).load('jupyterlab'), [translator]);
28
- const [defaultSet, setDefaultSet] = useState(false);
29
- const [remoteModelsReady, setRemoteModelsReady] = useState(!multiServiceManager.remote);
30
- // Trick because overflow is an unknown prop of ActionMenu.Overlay.
31
- const overlayProps = {
32
- maxHeight: 'large',
33
- width: (variant === 'cell' ? 'small' : 'auto'),
34
- };
35
- useEffect(() => {
36
- let disposed = false;
37
- const updateGroupedRuntimeDescs = () => {
38
- if (disposed) {
39
- return;
40
- }
41
- setGroupedRuntimeDescs(getGroupedRuntimeDescs(multiServiceManager, preference?.id, translator, filterRuntime, variant));
42
- };
43
- const refreshRuntimeModels = multiServiceManager.remote?.runtimesManager.refreshRuntimeModels?.();
44
- if (refreshRuntimeModels) {
45
- refreshRuntimeModels
46
- .catch(reason => {
47
- console.error('Failed to resolve remote runtimes for the runtime picker.', reason);
48
- })
49
- .finally(() => {
50
- if (disposed) {
51
- return;
52
- }
53
- updateGroupedRuntimeDescs();
54
- setRemoteModelsReady(true);
55
- });
56
- }
57
- else {
58
- setRemoteModelsReady(true);
59
- }
60
- // Recompute immediately in case a runtime changed between the initial
61
- // render and connecting the manager signals.
62
- updateGroupedRuntimeDescs();
63
- multiServiceManager.browser?.kernels.runningChanged.connect(updateGroupedRuntimeDescs);
64
- multiServiceManager.browser?.kernelspecs.specsChanged.connect(updateGroupedRuntimeDescs);
65
- multiServiceManager.browser?.sessions.runningChanged.connect(updateGroupedRuntimeDescs);
66
- multiServiceManager.local.kernels.runningChanged.connect(updateGroupedRuntimeDescs);
67
- multiServiceManager.local.kernelspecs.specsChanged.connect(updateGroupedRuntimeDescs);
68
- multiServiceManager.local.sessions.runningChanged.connect(updateGroupedRuntimeDescs);
69
- multiServiceManager.remote?.runtimesManager.changed.connect(updateGroupedRuntimeDescs);
70
- multiServiceManager.remote?.environments.changed.connect(updateGroupedRuntimeDescs);
71
- return () => {
72
- disposed = true;
73
- multiServiceManager.browser?.kernels.runningChanged.disconnect(updateGroupedRuntimeDescs);
74
- multiServiceManager.browser?.kernelspecs.specsChanged.disconnect(updateGroupedRuntimeDescs);
75
- multiServiceManager.browser?.sessions.runningChanged.disconnect(updateGroupedRuntimeDescs);
76
- multiServiceManager.local.kernels.runningChanged.disconnect(updateGroupedRuntimeDescs);
77
- multiServiceManager.local.kernelspecs.specsChanged.disconnect(updateGroupedRuntimeDescs);
78
- multiServiceManager.local.sessions.runningChanged.disconnect(updateGroupedRuntimeDescs);
79
- multiServiceManager.remote?.runtimesManager.changed.disconnect(updateGroupedRuntimeDescs);
80
- multiServiceManager.remote?.environments.changed.disconnect(updateGroupedRuntimeDescs);
81
- };
82
- }, [multiServiceManager, preference?.id, translator, filterRuntime, variant]);
83
- useEffect(() => {
84
- if (defaultSet) {
85
- return;
86
- }
87
- if (sessionContext && groupedRuntimeDescs) {
88
- const kernelId = sessionContext.session?.kernel?.id;
89
- if (kernelId) {
90
- let matched = false;
91
- Object.entries(groupedRuntimeDescs).forEach(([group, runtimeDescs]) => {
92
- runtimeDescs.forEach(runtimeDesc => {
93
- if (runtimeDesc.kernelId === kernelId) {
94
- matched = true;
95
- setRuntimeDesc(runtimeDesc);
96
- }
97
- });
98
- });
99
- if (!matched && !remoteModelsReady) {
100
- return;
101
- }
102
- }
103
- }
104
- setDefaultSet(true);
105
- }, [
106
- defaultSet,
107
- groupedRuntimeDescs,
108
- remoteModelsReady,
109
- sessionContext,
110
- setRuntimeDesc,
111
- ]);
112
- // For cell using submenu instead of group would be nice unfortunately the feature
113
- // is not yet implemented in the component there has been a not-great demo story.
114
- // https://github.com/primer/react/pull/3585
115
- return (_jsx(_Fragment, { children: display === 'menu' ? (
116
- /*
117
- * Section for Menu display.
118
- */
119
- _jsxs(ActionMenu, { children: [variant === 'cell' ? (_jsx(ActionMenu.Anchor, { children: _jsx(IconButton, { disabled: disabled || groupedRuntimeDescs === null,
120
- // icon={() => <kernelIcon.react className="dla-Cell-runtime-icon" tag={'span'} />}
121
- 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: () => {
122
- setRuntimeDesc(undefined);
123
- }, 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 => {
124
- const annotation = candidateRuntimeDesc.podName
125
- ? ` - ${candidateRuntimeDesc.podName.split('-', 2).reverse()[0]}`
126
- : candidateRuntimeDesc.kernelId
127
- ? ` - ${candidateRuntimeDesc.kernelId}`
128
- : '';
129
- const fullDisplayName = (candidateRuntimeDesc.displayName ?? '') + annotation;
130
- const displayName = (candidateRuntimeDesc.displayName?.length ?? 0) >
131
- RUNTIME_DISPLAY_NAME_MAX_LENGTH
132
- ? candidateRuntimeDesc.displayName.slice(0, RUNTIME_DISPLAY_NAME_MAX_LENGTH) + '…'
133
- : (candidateRuntimeDesc.displayName ?? '');
134
- return (_jsxs(ActionList.Item, { title: fullDisplayName, selected: (candidateRuntimeDesc.location ===
135
- runtimeDesc?.location ||
136
- (isRuntimeRemote(candidateRuntimeDesc.location) &&
137
- isRuntimeRemote(runtimeDesc?.location ?? 'local'))) &&
138
- (candidateRuntimeDesc.kernelId ??
139
- candidateRuntimeDesc.name) ===
140
- (runtimeDesc?.kernelId ?? runtimeDesc?.name), onSelect: () => {
141
- setRuntimeDesc(candidateRuntimeDesc);
142
- }, children: [_jsx(ActionList.LeadingVisual, { children: candidateRuntimeDesc.location === 'local' ? (_jsx(LaptopSimpleIcon, {})) : candidateRuntimeDesc.location === 'browser' ? (_jsx(BrowserIcon, {})) : (_jsx(CloudUploadIcon, {})) }), displayName + annotation.slice(0, 10)] }, candidateRuntimeDesc.name));
143
- })] }, group))), !!postActions && (_jsxs(_Fragment, { children: [_jsx(ActionList.Divider, {}), postActions] }))] }) })] })) : (
144
- /*
145
- * Section for Radio display.
146
- */
147
- _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 => {
148
- return (_jsxs(Box, { title: k.name, children: [_jsxs(FormControl, { children: [_jsx(Radio, { value: k.kernelId, onChange: () => {
149
- setRuntimeDesc(k);
150
- }, checked: (k.location === runtimeDesc?.location ||
151
- (isRuntimeRemote(k.location) &&
152
- isRuntimeRemote(runtimeDesc?.location ?? 'local'))) &&
153
- (k.kernelId ?? k.name) ===
154
- (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.kernelId));
155
- })] }, group))) })), !!postActions && _jsx(_Fragment, { children: postActions })] })) }));
156
- }
157
- export default RuntimePickerBase;
11
+ export { CodeSandboxPicker, RuntimePickerBase, } from '../code-sandboxes/CodeSandboxPicker';
12
+ export { default } from '../code-sandboxes/CodeSandboxPicker';
@@ -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 { IRuntimePickerBaseProps } from './RuntimePickerBase';
4
+ import { type ICodeSandboxPickerProps } from '../code-sandboxes/CodeSandboxPicker';
5
5
  /**
6
6
  * {@link RuntimePickerCell} properties
7
7
  */
8
- export type IRuntimePickerCellProps = Pick<IRuntimePickerBaseProps, 'multiServiceManager' | 'preference' | 'translator'> & {
8
+ export type IRuntimePickerCellProps = Pick<ICodeSandboxPickerProps, 'multiServiceManager' | 'preference' | 'translator'> & {
9
9
  /**
10
10
  * Callback to allow the user to login
11
11
  */
@@ -12,8 +12,8 @@ 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 { RuntimeLauncherDialog } from './RuntimeLauncherDialog';
16
- import { RuntimePickerBase } from './RuntimePickerBase';
15
+ import { CodeSandboxPicker, } from '../code-sandboxes/CodeSandboxPicker';
16
+ import { CodeSandboxLauncher } from '../code-sandboxes/CodeSandboxLauncher';
17
17
  import { RuntimeCellVariablesDialog } from './RuntimeCellVariablesDialog';
18
18
  /**
19
19
  * Runtime picker component for a cell.
@@ -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(RuntimePickerBase, { 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
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(RuntimeCellVariablesDialog, { 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(RuntimeLauncherDialog, { manager: multiServiceManager.remote, onSubmit: onStartRemote, startRuntime: 'defer', submitLabel: "Assign", markdownParser: markdownParser, sanitizer: sanitizer }))] }));
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(RuntimeCellVariablesDialog, { 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
104
  export default RuntimePickerCell;