@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.
Files changed (93) 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/agents/index.d.ts +6 -0
  13. package/lib/components/{students → agents}/index.js +6 -1
  14. package/lib/components/{NotificationEventCard.js → cards/NotificationEventCard.js} +1 -1
  15. package/lib/components/{OutputCard.js → cards/OutputCard.js} +1 -1
  16. package/lib/components/cards/index.d.ts +9 -0
  17. package/lib/components/cards/index.js +13 -0
  18. package/lib/components/{runtimes/RuntimeCellVariables.d.ts → code-sandboxes/CodeSandboxCellVariables.d.ts} +3 -3
  19. package/lib/components/{runtimes/RuntimeCellVariables.js → code-sandboxes/CodeSandboxCellVariables.js} +2 -2
  20. package/lib/components/{runtimes/RuntimeCellVariablesDialog.d.ts → code-sandboxes/CodeSandboxCellVariablesDialog.d.ts} +4 -4
  21. package/lib/components/{runtimes/RuntimeCellVariablesDialog.js → code-sandboxes/CodeSandboxCellVariablesDialog.js} +4 -4
  22. package/lib/components/{runtimes/RuntimeLauncherDialog.d.ts → code-sandboxes/CodeSandboxLauncher.d.ts} +4 -4
  23. package/lib/components/{runtimes/RuntimeLauncherDialog.js → code-sandboxes/CodeSandboxLauncher.js} +33 -38
  24. package/lib/components/code-sandboxes/CodeSandboxPicker.d.ts +96 -0
  25. package/lib/components/code-sandboxes/CodeSandboxPicker.js +296 -0
  26. package/lib/components/{runtimes/RuntimePickerCell.d.ts → code-sandboxes/CodeSandboxPickerCell.d.ts} +5 -5
  27. package/lib/components/{runtimes/RuntimePickerCell.js → code-sandboxes/CodeSandboxPickerCell.js} +7 -7
  28. package/lib/components/{runtimes/RuntimeReservationControl.d.ts → code-sandboxes/CodeSandboxReservationControl.d.ts} +3 -3
  29. package/lib/components/{runtimes/RuntimeReservationControl.js → code-sandboxes/CodeSandboxReservationControl.js} +11 -4
  30. package/lib/components/{runtimes/RuntimeTransfer.d.ts → code-sandboxes/CodeSandboxTransfer.d.ts} +1 -1
  31. package/lib/components/{runtimes/RuntimeUtils.d.ts → code-sandboxes/CodeSandboxUtils.d.ts} +3 -3
  32. package/lib/components/{runtimes/RuntimeUtils.js → code-sandboxes/CodeSandboxUtils.js} +35 -19
  33. package/lib/components/code-sandboxes/CodeSandboxVariables.d.ts +71 -0
  34. package/lib/components/{runtimes/RuntimeVariables.js → code-sandboxes/CodeSandboxVariables.js} +77 -2
  35. package/lib/components/code-sandboxes/NewCodeSandboxControls.d.ts +42 -0
  36. package/lib/components/code-sandboxes/NewCodeSandboxControls.js +76 -0
  37. package/lib/components/code-sandboxes/index.d.ts +21 -0
  38. package/lib/components/code-sandboxes/index.js +25 -0
  39. package/lib/components/index.d.ts +4 -6
  40. package/lib/components/index.js +4 -6
  41. package/lib/components/progress/CreditsIndicator.d.ts +7 -0
  42. package/lib/components/progress/CreditsIndicator.js +3 -3
  43. package/lib/context/CostUsageChart.d.ts +2 -2
  44. package/lib/context/CostUsageChart.js +7 -7
  45. package/lib/context/TokenUsageChart.d.ts +2 -2
  46. package/lib/context/TokenUsageChart.js +6 -6
  47. package/lib/context/TurnGraphChart.d.ts +1 -1
  48. package/lib/context/TurnGraphChart.js +6 -6
  49. package/lib/examples/AgentEvalsExample.js +1 -1
  50. package/lib/examples/AgentGuardrailsExample.js +3 -3
  51. package/lib/examples/AgentInferenceProviderExample.js +1 -1
  52. package/lib/examples/AgentMonitoringExample.js +6 -6
  53. package/lib/examples/AgentOtelExample.d.ts +2 -2
  54. package/lib/examples/AgentOtelExample.js +5 -5
  55. package/lib/examples/AgentspecsExample.js +1 -1
  56. package/lib/examples/NotebookCollaborationExample.js +8 -8
  57. package/lib/examples/main.js +5 -5
  58. package/lib/examples2/DatalayerNotebookExample.js +8 -8
  59. package/lib/examples2/main.js +5 -5
  60. package/lib/hooks/useAgentRuntimes.js +3 -3
  61. package/lib/hooks/useMonitoring.d.ts +5 -5
  62. package/lib/hooks/useMonitoring.js +10 -10
  63. package/lib/protocols/AGUIAdapter.js +4 -0
  64. package/lib/protocols/VercelAIAdapter.js +3 -0
  65. package/lib/types/chat.d.ts +23 -0
  66. package/lib/types/tools.d.ts +11 -0
  67. package/package.json +4 -4
  68. package/lib/components/runtimes/RuntimePickerBase.d.ts +0 -69
  69. package/lib/components/runtimes/RuntimePickerBase.js +0 -157
  70. package/lib/components/runtimes/RuntimePickerNotebook.d.ts +0 -42
  71. package/lib/components/runtimes/RuntimePickerNotebook.js +0 -232
  72. package/lib/components/runtimes/RuntimeSimplePicker.d.ts +0 -38
  73. package/lib/components/runtimes/RuntimeSimplePicker.js +0 -156
  74. package/lib/components/runtimes/RuntimeVariables.d.ts +0 -38
  75. package/lib/components/runtimes/index.d.ts +0 -11
  76. package/lib/components/runtimes/index.js +0 -15
  77. package/lib/components/students/StudentItemStatus.d.ts +0 -7
  78. package/lib/components/students/StudentItemStatus.js +0 -68
  79. package/lib/components/students/index.d.ts +0 -1
  80. package/lib/components/toolbars/AssignmentEditorToolbar.d.ts +0 -4
  81. package/lib/components/toolbars/AssignmentEditorToolbar.js +0 -18
  82. package/lib/components/toolbars/DocumentEditorToolbar.d.ts +0 -2
  83. package/lib/components/toolbars/DocumentEditorToolbar.js +0 -12
  84. package/lib/components/toolbars/NotebookEditorToolbar.d.ts +0 -29
  85. package/lib/components/toolbars/NotebookEditorToolbar.js +0 -30
  86. package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
  87. /package/lib/components/{AgentSummary.d.ts → agents/AgentSummary.d.ts} +0 -0
  88. /package/lib/components/{AgentSummary.js → agents/AgentSummary.js} +0 -0
  89. /package/lib/components/{NotificationEventCard.d.ts → cards/NotificationEventCard.d.ts} +0 -0
  90. /package/lib/components/{OutputCard.d.ts → cards/OutputCard.d.ts} +0 -0
  91. /package/lib/components/{ToolApprovalCard.d.ts → cards/ToolApprovalCard.d.ts} +0 -0
  92. /package/lib/components/{ToolApprovalCard.js → cards/ToolApprovalCard.js} +0 -0
  93. /package/lib/components/{runtimes/RuntimeTransfer.js → code-sandboxes/CodeSandboxTransfer.js} +0 -0
@@ -12,13 +12,20 @@ import { Slider } from '@datalayer/primer-addons';
12
12
  *
13
13
  * TODO this should be configurable
14
14
  */
15
- export const MAXIMAL_RUNTIME_TIME_RESERVATION_MINUTES = 24 * 60;
15
+ export const MAXIMAL_CODE_SANDBOX_TIME_RESERVATION_MINUTES = 24 * 60;
16
16
  /**
17
17
  * Runtime reservation control
18
18
  */
19
- export function RuntimeReservationControl(props) {
19
+ export function CodeSandboxReservationControl(props) {
20
20
  const { addCredits, burningRate, disabled, error, label, max: maxProps, onTimeChange, time, } = props;
21
- const max = Math.max(1, Math.min(maxProps, MAXIMAL_RUNTIME_TIME_RESERVATION_MINUTES));
21
+ // The caller computes its maximum from the credits and the burning rate of
22
+ // an environment, either of which may not be known yet — and a slider given
23
+ // `NaN` renders nothing but warnings. Fall back to what a reservation may
24
+ // hold in any case.
25
+ const requestedMax = Number.isFinite(maxProps)
26
+ ? maxProps
27
+ : MAXIMAL_CODE_SANDBOX_TIME_RESERVATION_MINUTES;
28
+ const max = Math.max(1, Math.min(requestedMax, MAXIMAL_CODE_SANDBOX_TIME_RESERVATION_MINUTES));
22
29
  const displayedTime = Number.isFinite(time)
23
30
  ? Math.min(max, Math.max(1, time))
24
31
  : 1;
@@ -38,5 +45,5 @@ export function RuntimeReservationControl(props) {
38
45
  gridTemplateColumns: 'max-content 1fr max-content max-content',
39
46
  gridGap: 'var(--stack-gap-condensed)',
40
47
  width: '100%',
41
- }, children: [_jsx(Slider, { step: 1, min: 1, max: max, value: displayedTime, onChange: handleTimeChange, disabled: disabled, label: "", displayValue: false }), _jsx(TextInput, { type: "number", step: "1", min: "1", max: max, disabled: disabled, value: displayedTime.toFixed(2), onChange: handleTimeChange }), (max === 0 || max > Number.EPSILON) && (_jsxs(_Fragment, { children: [_jsxs(Text, { children: ["out of ", maxProps, " available minutes"] }), addCredits && (_jsx(IconButton, { icon: PlusIcon, "aria-label": "Add credits", onClick: () => addCredits() }))] }))] }), _jsxs(FormControl.Caption, { children: ["Maximum execution time that can be consumed by the runtime. It must be less than ", (MAXIMAL_RUNTIME_TIME_RESERVATION_MINUTES / 60).toFixed(0), ' ', "hours.", burningRate && (_jsxs(_Fragment, { children: [_jsx("br", {}), `With the current value, the runtime execution will consume at most ${(time * burningRate * 60).toFixed(2)} credits.`] }))] }), error && (_jsx(FormControl.Validation, { variant: "error", children: error }))] })) : (_jsx(_Fragment, {}));
48
+ }, children: [_jsx(Slider, { step: 1, min: 1, max: max, value: displayedTime, onChange: handleTimeChange, disabled: disabled, label: "", displayValue: false }), _jsx(TextInput, { type: "number", step: "1", min: "1", max: max, disabled: disabled, value: displayedTime.toFixed(2), onChange: handleTimeChange }), (max === 0 || max > Number.EPSILON) && (_jsxs(_Fragment, { children: [_jsxs(Text, { children: ["out of ", maxProps, " available minutes"] }), addCredits && (_jsx(IconButton, { icon: PlusIcon, "aria-label": "Add credits", onClick: () => addCredits() }))] }))] }), _jsxs(FormControl.Caption, { children: ["Maximum execution time that can be consumed by the runtime. It must be less than ", (MAXIMAL_CODE_SANDBOX_TIME_RESERVATION_MINUTES / 60).toFixed(0), ' ', "hours.", burningRate && (_jsxs(_Fragment, { children: [_jsx("br", {}), `With the current value, the runtime execution will consume at most ${(time * burningRate * 60).toFixed(2)} credits.`] }))] }), error && (_jsx(FormControl.Validation, { variant: "error", children: error }))] })) : (_jsx(_Fragment, {}));
42
49
  }
@@ -1,5 +1,5 @@
1
1
  import { type IRuntimeOptions } from '../../runtimes';
2
- export interface RuntimeTransfer {
2
+ export interface CodeSandboxTransfer {
3
3
  /**
4
4
  * Selected Kernel.
5
5
  */
@@ -2,14 +2,14 @@ import { SessionContext } from '@jupyterlab/apputils';
2
2
  import { ITranslator } from '@jupyterlab/translation';
3
3
  import { IMultiServiceManager } from '../../runtimes';
4
4
  import { IRuntimeDesc } from '../../models';
5
- export type IDatalayerRuntimeDesc = IRuntimeDesc & {
5
+ export type IDatalayerCodeSandboxDesc = IRuntimeDesc & {
6
6
  gpu?: string;
7
7
  };
8
8
  /**
9
9
  * Create the grouped runtime descriptions.
10
10
  */
11
- export declare function getGroupedRuntimeDescs(multiServiceManager: IMultiServiceManager, kernelId?: string, translator?: ITranslator, filterKernels?: (desc: IDatalayerRuntimeDesc) => boolean, variant?: 'document' | 'cell'): {
12
- [g: string]: IDatalayerRuntimeDesc[];
11
+ export declare function getGroupedCodeSandboxDescs(multiServiceManager: IMultiServiceManager, kernelId?: string, translator?: ITranslator, filterKernels?: (desc: IDatalayerCodeSandboxDesc) => boolean, variant?: 'document' | 'cell'): {
12
+ [g: string]: IDatalayerCodeSandboxDesc[];
13
13
  } | undefined;
14
14
  /**
15
15
  * Get the default kernel name given a selector.
@@ -10,23 +10,25 @@ const ASSIGN_EXISTING_RUNTIME_LABEL = 'Assign an existing Runtime';
10
10
  /**
11
11
  * Create the grouped runtime descriptions.
12
12
  */
13
- export function getGroupedRuntimeDescs(multiServiceManager, kernelId, translator, filterKernels = () => true, variant) {
13
+ export function getGroupedCodeSandboxDescs(multiServiceManager, kernelId, translator, filterKernels = () => true, variant) {
14
14
  translator = translator ?? nullTranslator;
15
15
  const trans = translator.load('jupyterlab');
16
+ // The specifications land asynchronously, and a runtime that already runs
17
+ // is listed with or without them: what a kernel needs to be picked is its
18
+ // identifier, the specification only names it. Only the environments to
19
+ // start a new runtime in come from the specifications, and they wait.
16
20
  const specs = multiServiceManager.local.kernelspecs.specs;
17
21
  const sessions = multiServiceManager.local.sessions.running();
18
22
  const kernels = {};
19
23
  // Add the sessions.
20
24
  const runningSessions = Array.from(sessions)
21
- .filter(session => session.kernel &&
22
- session.kernel.id !== kernelId &&
23
- specs.kernelspecs[session.kernel.name])
25
+ .filter(session => session.kernel && session.kernel.id !== kernelId)
24
26
  .map(session => {
25
- const spec = specs.kernelspecs[session.kernel.name];
27
+ const spec = specs?.kernelspecs[session.kernel.name];
26
28
  return {
27
29
  kernelId: session.kernel.id,
28
- name: spec.name,
29
- language: spec.language,
30
+ name: spec?.name ?? session.kernel.name,
31
+ language: spec?.language ?? '',
30
32
  displayName: session.name || PathExt.basename(session.path),
31
33
  location: 'local',
32
34
  };
@@ -34,12 +36,13 @@ export function getGroupedRuntimeDescs(multiServiceManager, kernelId, translator
34
36
  .concat(Array.from(multiServiceManager.browser?.sessions.running() ?? [])
35
37
  .filter(session => session.kernel && session.kernel.id !== kernelId)
36
38
  .map(session => {
37
- const spec = multiServiceManager.browser.kernelspecs.specs.kernelspecs[session.kernel.name];
39
+ // The browser specifications load on their own schedule.
40
+ const spec = multiServiceManager.browser?.kernelspecs.specs?.kernelspecs[session.kernel.name];
38
41
  return {
39
42
  id: '', // TODO Assign a proper ID.
40
43
  kernelId: session.kernel.id,
41
- name: spec.name,
42
- language: spec.language,
44
+ name: spec?.name ?? session.kernel.name,
45
+ language: spec?.language ?? '',
43
46
  displayName: session.name || PathExt.basename(session.path),
44
47
  location: 'browser',
45
48
  };
@@ -50,12 +53,12 @@ export function getGroupedRuntimeDescs(multiServiceManager, kernelId, translator
50
53
  const runningKernels = Array.from(multiServiceManager.local.kernels.running())
51
54
  .filter(k => !listedAsSession.includes(k.id))
52
55
  .map(k => {
53
- const spec = specs.kernelspecs[k.name];
56
+ const spec = specs?.kernelspecs[k.name];
54
57
  return {
55
58
  kernelId: k.id,
56
- name: spec.name,
57
- language: spec.language,
58
- displayName: spec.display_name,
59
+ name: spec?.name ?? k.name,
60
+ language: spec?.language ?? '',
61
+ displayName: spec?.display_name ?? k.name,
59
62
  location: 'local',
60
63
  };
61
64
  })
@@ -78,17 +81,30 @@ export function getGroupedRuntimeDescs(multiServiceManager, kernelId, translator
78
81
  .concat(Array.from(multiServiceManager.browser?.kernels.running() ?? [])
79
82
  .filter(k => !listedAsSession.includes(k.id))
80
83
  .map(k => {
81
- const spec = multiServiceManager.browser.kernelspecs.specs.kernelspecs[k.name];
84
+ const spec = multiServiceManager.browser?.kernelspecs.specs?.kernelspecs[k.name];
82
85
  return {
83
86
  kernelId: k.id,
84
- name: spec.name,
85
- language: spec.language,
86
- displayName: spec.display_name,
87
+ name: spec?.name ?? k.name,
88
+ language: spec?.language ?? '',
89
+ displayName: spec?.display_name ?? k.name,
87
90
  location: 'browser',
88
91
  };
89
92
  }))
90
93
  .filter(filterKernels);
91
94
  runningSessions.push(...runningKernels);
95
+ // The sources overlap — a kernel of a session, a manager standing in for
96
+ // another — and a runtime listed twice would be picked twice.
97
+ const seen = new Set();
98
+ const distinctRunning = runningSessions.filter(desc => {
99
+ const key = `${desc.location}:${desc.kernelId ?? desc.name}`;
100
+ if (seen.has(key)) {
101
+ return false;
102
+ }
103
+ seen.add(key);
104
+ return true;
105
+ });
106
+ runningSessions.length = 0;
107
+ runningSessions.push(...distinctRunning);
92
108
  if (runningSessions.length) {
93
109
  const key = variant === 'cell'
94
110
  ? ASSIGN_EXISTING_REMOTE_RUNTIME_LABEL
@@ -96,7 +112,7 @@ export function getGroupedRuntimeDescs(multiServiceManager, kernelId, translator
96
112
  kernels[key] = runningSessions;
97
113
  }
98
114
  // Environments.
99
- const environments = Object.values(specs.kernelspecs)
115
+ const environments = Object.values(specs?.kernelspecs ?? {})
100
116
  .filter(spec => !!spec)
101
117
  .map(spec => ({
102
118
  name: spec.name,
@@ -0,0 +1,71 @@
1
+ import { ReactElement } from 'react';
2
+ import { ISessionContext } from '@jupyterlab/apputils';
3
+ import { ITranslator } from '@jupyterlab/translation';
4
+ import type { IRuntimeDesc } from '../../models';
5
+ /** What {@link useCodeSandboxVariablesTransfer} answers. */
6
+ export interface ICodeSandboxVariablesTransfer {
7
+ /**
8
+ * Whether carrying variables over is possible at all.
9
+ *
10
+ * Both ends must speak a language the snippets know how to serialize: the
11
+ * sandbox the variables come from, and the one they would go to.
12
+ */
13
+ available: boolean;
14
+ /** The variables of the current sandbox, by name and type. */
15
+ variables?: {
16
+ [name: string]: string;
17
+ };
18
+ /** Those the user chose to carry over. */
19
+ selected: string[];
20
+ setSelected: (names: string[]) => void;
21
+ /** Whether the user asked for the transfer at all. */
22
+ transfer: boolean;
23
+ setTransfer: (value: boolean) => void;
24
+ }
25
+ /**
26
+ * The variables of the current sandbox, and which of them to carry over.
27
+ *
28
+ * Listing them runs code in the sandbox — the snippet that names them — so it
29
+ * is deferred until the user asks for the transfer, and done once.
30
+ *
31
+ * @param sessionContext The session the variables are read from
32
+ * @param target The sandbox they would be carried to
33
+ * @param enabled Whether the transfer is offered at all
34
+ */
35
+ export declare function useCodeSandboxVariablesTransfer(sessionContext: ISessionContext | undefined, target: IRuntimeDesc | undefined, enabled?: boolean): ICodeSandboxVariablesTransfer;
36
+ /**
37
+ * {@link CodeSandboxVariables} properties
38
+ */
39
+ export interface ICodeSandboxVariablesProps {
40
+ /**
41
+ * Component class name
42
+ */
43
+ className?: string;
44
+ /**
45
+ * Available kernel variables
46
+ *
47
+ * Mapping (variable name, variable type)
48
+ */
49
+ kernelVariables?: {
50
+ [name: string]: string;
51
+ };
52
+ /**
53
+ * Kernel variables to be transferred.
54
+ */
55
+ selectedVariables: string[];
56
+ setSelectVariable: (l: string[]) => void;
57
+ /**
58
+ * Whether to transfer the variable from the current
59
+ * to the selected kernel or not.
60
+ */
61
+ transferVariables: boolean;
62
+ setTransferVariable: (v: boolean) => void;
63
+ /**
64
+ * Application translator
65
+ */
66
+ translator?: ITranslator;
67
+ }
68
+ /**
69
+ * Runtime variables selector component.
70
+ */
71
+ export declare function CodeSandboxVariables(props: ICodeSandboxVariablesProps): ReactElement;
@@ -3,16 +3,91 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  * Copyright (c) 2025-2026 Datalayer, Inc.
4
4
  * Distributed under the terms of the Modified BSD License.
5
5
  */
6
- import { useMemo } from 'react';
6
+ import { useCallback, useMemo, useState } from 'react';
7
7
  import { IconButton, ToggleSwitch, FormControl } from '@primer/react';
8
8
  import { Box } from '@datalayer/primer-addons';
9
9
  import { Blankslate, DataTable, Table } from '@primer/react/experimental';
10
10
  import { nullTranslator } from '@jupyterlab/translation';
11
11
  import { checkIcon } from '@jupyterlab/ui-components';
12
+ import { JSONExt } from '@lumino/coreutils';
13
+ import { KernelExecutor } from '@datalayer/jupyter-react';
14
+ import { RuntimeSnippetsFacade } from '../../jupyter';
15
+ /**
16
+ * The variables of the current sandbox, and which of them to carry over.
17
+ *
18
+ * Listing them runs code in the sandbox — the snippet that names them — so it
19
+ * is deferred until the user asks for the transfer, and done once.
20
+ *
21
+ * @param sessionContext The session the variables are read from
22
+ * @param target The sandbox they would be carried to
23
+ * @param enabled Whether the transfer is offered at all
24
+ */
25
+ export function useCodeSandboxVariablesTransfer(sessionContext, target, enabled = true) {
26
+ const [variables, setVariables] = useState();
27
+ const [selected, setSelectedState] = useState([]);
28
+ const [transfer, setTransferState] = useState(false);
29
+ const [listed, setListed] = useState(false);
30
+ const sourceLanguage = sessionContext?.session?.kernel?.name && sessionContext.specsManager.specs
31
+ ? sessionContext.specsManager.specs.kernelspecs[sessionContext.session.kernel.name]?.language
32
+ : undefined;
33
+ const available = enabled &&
34
+ RuntimeSnippetsFacade.supports(sourceLanguage ?? '') &&
35
+ RuntimeSnippetsFacade.supports(target?.language ?? '');
36
+ const list = useCallback(async () => {
37
+ if (listed) {
38
+ return;
39
+ }
40
+ setListed(true);
41
+ const connection = sessionContext?.session?.kernel;
42
+ const spec = connection &&
43
+ sessionContext?.specsManager.specs?.kernelspecs[connection.model.name];
44
+ if (!connection || !spec) {
45
+ setVariables({});
46
+ return;
47
+ }
48
+ const snippets = new RuntimeSnippetsFacade(spec.language);
49
+ const outputs = await new KernelExecutor({ connection }).execute(snippets.listVariables());
50
+ const content = outputs.get(0).data['text/plain'];
51
+ if (!content) {
52
+ setVariables({});
53
+ return;
54
+ }
55
+ // The payload comes quoted, as the representation of a string.
56
+ const listedVariables = JSON.parse(content.slice(1, content.length - 1));
57
+ setVariables(listedVariables);
58
+ // Everything is carried over unless the user says otherwise.
59
+ setSelectedState(Object.keys(listedVariables ?? {}));
60
+ }, [listed, sessionContext]);
61
+ const setSelected = useCallback((names) => {
62
+ setSelectedState(current => JSONExt.deepEqual(current, names) ? current : names);
63
+ }, [setSelectedState]);
64
+ const setTransfer = useCallback((value) => {
65
+ setTransferState(current => {
66
+ if (current === value) {
67
+ return current;
68
+ }
69
+ if (value) {
70
+ list().catch(reason => {
71
+ console.error('Failed to list the variables of the sandbox', reason);
72
+ setListed(false);
73
+ });
74
+ }
75
+ return value;
76
+ });
77
+ }, [list]);
78
+ return {
79
+ available,
80
+ variables,
81
+ selected: available && transfer ? selected : [],
82
+ setSelected,
83
+ transfer,
84
+ setTransfer,
85
+ };
86
+ }
12
87
  /**
13
88
  * Runtime variables selector component.
14
89
  */
15
- export function RuntimeVariables(props) {
90
+ export function CodeSandboxVariables(props) {
16
91
  const { className, translator, selectedVariables, setSelectVariable, transferVariables, setTransferVariable, kernelVariables, } = props;
17
92
  const trans = useMemo(() => (translator ?? nullTranslator).load('jupyterlab'), [translator]);
18
93
  const nRows = Object.keys(kernelVariables ?? {}).length;
@@ -0,0 +1,42 @@
1
+ /** What the account allows for a new sandbox of a given burning rate. */
2
+ export interface INewCodeSandboxAllowance {
3
+ /** Minutes the available credits pay for; undefined without a rate. */
4
+ maxFromCredits?: number;
5
+ /** The ceiling offered by the reservation control. */
6
+ effectiveMaxMinutes: number;
7
+ /** Whether a paid start is impossible: no runs left and no credits. */
8
+ outOfCredits: boolean;
9
+ hasKnownCredits: boolean;
10
+ hasKnownRunAllowance: boolean;
11
+ hasRemainingRuns: boolean;
12
+ }
13
+ /**
14
+ * The credits arithmetic both the launcher and the picker ask.
15
+ *
16
+ * @param burningRate Credits per second of the chosen environment
17
+ */
18
+ export declare function useNewCodeSandboxAllowance(burningRate: number | undefined): INewCodeSandboxAllowance;
19
+ /** The credits a time reservation stands for. */
20
+ export declare function creditsLimitFor(timeLimitMinutes: number, burningRate: number): number;
21
+ export interface INewCodeSandboxControlsProps {
22
+ /** Whether the time reservation is offered; it is by default. */
23
+ withReservation?: boolean;
24
+ /** Credits per second of the chosen environment. */
25
+ burningRate?: number;
26
+ timeLimit: number;
27
+ onTimeChange: (minutes: number) => void;
28
+ /** The ceiling of the reservation control. */
29
+ max: number;
30
+ disabled?: boolean;
31
+ error?: string;
32
+ /** Offered next to the error when credits can be added from here. */
33
+ addCredits?: () => void;
34
+ userStorage: boolean;
35
+ onUserStorageToggle: () => void;
36
+ storageDisabled?: boolean;
37
+ }
38
+ /**
39
+ * The two questions of a new sandbox: the time reservation, and the storage.
40
+ * The storage is withheld on white-label deployments, as it always was.
41
+ */
42
+ export declare function NewCodeSandboxControls(props: INewCodeSandboxControlsProps): JSX.Element;
@@ -0,0 +1,76 @@
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
+ /**
7
+ * What launching a NEW code sandbox asks of the user, in one place.
8
+ *
9
+ * The launcher dialog and the picker both offer to start a sandbox, and both
10
+ * used to carry their own copy of the same questions — how long to reserve,
11
+ * whether to mount the user storage — and of the same arithmetic over the
12
+ * credits of the account. This module is the single copy: the hook computes
13
+ * what the account allows, the component renders the two controls, and the
14
+ * helper turns a time limit into the credits reservation.
15
+ *
16
+ * @module components/code-sandboxes/NewCodeSandboxControls
17
+ */
18
+ import { FormControl, ToggleSwitch, Tooltip, IconButton } from '@primer/react';
19
+ import { AlertIcon } from '@primer/octicons-react';
20
+ import { useCoreStore, useIAMStore } from '../../state/substates';
21
+ import { CodeSandboxReservationControl, MAXIMAL_CODE_SANDBOX_TIME_RESERVATION_MINUTES, } from './CodeSandboxReservationControl';
22
+ /**
23
+ * The credits arithmetic both the launcher and the picker ask.
24
+ *
25
+ * @param burningRate Credits per second of the chosen environment
26
+ */
27
+ export function useNewCodeSandboxAllowance(burningRate) {
28
+ const { credits, user } = useIAMStore();
29
+ const includedRuns = user?.subscription?.usage?.included_runs ??
30
+ user?.subscription?.included_runs;
31
+ const currentRuns = user?.subscription?.usage?.current_runs ??
32
+ user?.subscription?.current_runs ??
33
+ user?.subscription?.used_runs;
34
+ const hasKnownRunAllowance = typeof includedRuns === 'number';
35
+ const hasRemainingRuns = hasKnownRunAllowance &&
36
+ typeof currentRuns === 'number' &&
37
+ includedRuns > 0 &&
38
+ currentRuns < includedRuns;
39
+ const hasKnownCredits = typeof credits?.available === 'number';
40
+ const maxFromCredits = burningRate
41
+ ? Math.floor((credits?.available ?? 0) / burningRate / 60.0)
42
+ : undefined;
43
+ const effectiveMaxMinutes = hasKnownCredits && hasKnownRunAllowance && !hasRemainingRuns
44
+ ? Math.max(1, maxFromCredits ?? 0)
45
+ : Math.max(10, maxFromCredits && maxFromCredits > 0 ? maxFromCredits : 0);
46
+ const outOfCredits = hasKnownCredits &&
47
+ hasKnownRunAllowance &&
48
+ !hasRemainingRuns &&
49
+ ((credits?.available ?? 0) <= 0 || (maxFromCredits ?? 0) < Number.EPSILON);
50
+ return {
51
+ maxFromCredits,
52
+ effectiveMaxMinutes,
53
+ outOfCredits,
54
+ hasKnownCredits,
55
+ hasKnownRunAllowance,
56
+ hasRemainingRuns,
57
+ };
58
+ }
59
+ /** The credits a time reservation stands for. */
60
+ export function creditsLimitFor(timeLimitMinutes, burningRate) {
61
+ return (Math.min(timeLimitMinutes, MAXIMAL_CODE_SANDBOX_TIME_RESERVATION_MINUTES) *
62
+ burningRate *
63
+ 60);
64
+ }
65
+ /**
66
+ * The two questions of a new sandbox: the time reservation, and the storage.
67
+ * The storage is withheld on white-label deployments, as it always was.
68
+ */
69
+ export function NewCodeSandboxControls(props) {
70
+ const { addCredits, burningRate, withReservation = true, disabled, error, max, onTimeChange, onUserStorageToggle, storageDisabled, timeLimit, userStorage, } = props;
71
+ const { configuration } = useCoreStore();
72
+ return (_jsxs(_Fragment, { children: [withReservation && (_jsx(CodeSandboxReservationControl, { addCredits: addCredits, disabled: disabled, label: 'Time reservation', max: max, time: timeLimit, burningRate: burningRate, onTimeChange: onTimeChange, error: error })), !configuration.whiteLabel && (_jsxs(FormControl, { disabled: storageDisabled, layout: "horizontal", children: [_jsxs(FormControl.Label, { id: "new-sandbox-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, { disabled: storageDisabled, checked: userStorage, size: "small", onClick: event => {
73
+ event.preventDefault();
74
+ onUserStorageToggle();
75
+ }, "aria-labelledby": "new-sandbox-user-storage-label" })] }))] }));
76
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The code sandboxes: what runs the code of a notebook, a document or a cell.
3
+ *
4
+ * One launcher and one picker, and everything they are made of. The launcher
5
+ * asks for a NEW sandbox and starts it; the picker lists what already runs
6
+ * next to the environments a new one could be started in. The pickers of a
7
+ * notebook, of a cell and of a toolbar are compositions of those two — none
8
+ * of them carries a second copy of either.
9
+ *
10
+ * @module components/code-sandboxes
11
+ */
12
+ export * from './CodeSandboxCellVariables';
13
+ export * from './CodeSandboxCellVariablesDialog';
14
+ export * from './CodeSandboxLauncher';
15
+ export * from './CodeSandboxPicker';
16
+ export * from './CodeSandboxPickerCell';
17
+ export * from './CodeSandboxReservationControl';
18
+ export * from './CodeSandboxTransfer';
19
+ export * from './CodeSandboxUtils';
20
+ export * from './CodeSandboxVariables';
21
+ export * from './NewCodeSandboxControls';
@@ -0,0 +1,25 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * The code sandboxes: what runs the code of a notebook, a document or a cell.
7
+ *
8
+ * One launcher and one picker, and everything they are made of. The launcher
9
+ * asks for a NEW sandbox and starts it; the picker lists what already runs
10
+ * next to the environments a new one could be started in. The pickers of a
11
+ * notebook, of a cell and of a toolbar are compositions of those two — none
12
+ * of them carries a second copy of either.
13
+ *
14
+ * @module components/code-sandboxes
15
+ */
16
+ export * from './CodeSandboxCellVariables';
17
+ export * from './CodeSandboxCellVariablesDialog';
18
+ export * from './CodeSandboxLauncher';
19
+ export * from './CodeSandboxPicker';
20
+ export * from './CodeSandboxPickerCell';
21
+ export * from './CodeSandboxReservationControl';
22
+ export * from './CodeSandboxTransfer';
23
+ export * from './CodeSandboxUtils';
24
+ export * from './CodeSandboxVariables';
25
+ export * from './NewCodeSandboxControls';
@@ -1,8 +1,6 @@
1
- export * from './ToolApprovalCard';
2
- export * from './NotificationEventCard';
3
- export * from './OutputCard';
4
- export * from './AgentSummary';
5
1
  export * from './a2ui';
6
- export * from './runtimes';
7
- export * from './snapshots';
2
+ export * from './agents';
3
+ export * from './cards';
4
+ export * from './code-sandboxes';
8
5
  export * from './scheduler';
6
+ export * from './snapshots';
@@ -2,11 +2,9 @@
2
2
  * Copyright (c) 2025-2026 Datalayer, Inc.
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
- export * from './ToolApprovalCard';
6
- export * from './NotificationEventCard';
7
- export * from './OutputCard';
8
- export * from './AgentSummary';
9
5
  export * from './a2ui';
10
- export * from './runtimes';
11
- export * from './snapshots';
6
+ export * from './agents';
7
+ export * from './cards';
8
+ export * from './code-sandboxes';
12
9
  export * from './scheduler';
10
+ export * from './snapshots';
@@ -25,6 +25,13 @@ type ICreditsIndicatorProps = {
25
25
  * Duration is the kernel max duration
26
26
  */
27
27
  onUpdate?: (progress: number, duration: number) => void;
28
+ /**
29
+ * Paddings of the indicator, each defaulting to the current ones.
30
+ */
31
+ paddingLeft?: number | string;
32
+ paddingRight?: number | string;
33
+ paddingTop?: number | string;
34
+ paddingBottom?: number | string;
28
35
  };
29
36
  /**
30
37
  * Credits indicator component.
@@ -5,13 +5,13 @@ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
5
5
  */
6
6
  import { useState, useEffect } from 'react';
7
7
  import { Box } from '@datalayer/primer-addons';
8
- import { useNavigate } from '@datalayer/core/lib/hooks/useNavigate';
9
8
  import { ConsumptionBar } from '@datalayer/core/lib/components/progress/ConsumptionBar';
9
+ import { useNavigate } from '@datalayer/core/lib/hooks/useNavigate';
10
10
  /**
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
  }
@@ -3,11 +3,11 @@ export interface CostUsageChartProps {
3
3
  agentId?: string;
4
4
  runtimeId?: string;
5
5
  apiKey?: string;
6
- datalayerUrl?: string;
6
+ otelUrl?: string;
7
7
  wsUrl?: string;
8
8
  liveCumulativeUsd?: number;
9
9
  liveTimestampMs?: number | null;
10
10
  height?: number;
11
11
  }
12
- export declare function CostUsageChart({ serviceName, agentId, runtimeId, apiKey, datalayerUrl, wsUrl, liveCumulativeUsd, liveTimestampMs, height, }: CostUsageChartProps): import("react/jsx-runtime").JSX.Element;
12
+ export declare function CostUsageChart({ serviceName, agentId, runtimeId, apiKey, otelUrl, wsUrl, liveCumulativeUsd, liveTimestampMs, height, }: CostUsageChartProps): import("react/jsx-runtime").JSX.Element;
13
13
  export default CostUsageChart;
@@ -278,7 +278,7 @@ function maxDefined(rows, selector) {
278
278
  return max === undefined ? value : Math.max(max, value);
279
279
  }, undefined);
280
280
  }
281
- export function CostUsageChart({ serviceName, agentId, runtimeId, apiKey, datalayerUrl, wsUrl, liveCumulativeUsd, liveTimestampMs, height = 160, }) {
281
+ export function CostUsageChart({ serviceName, agentId, runtimeId, apiKey, otelUrl, wsUrl, liveCumulativeUsd, liveTimestampMs, height = 160, }) {
282
282
  const cacheServiceKey = String(serviceName || runtimeId || '').trim() || undefined;
283
283
  const monitoringCache = useAgentRuntimeStore(s => s.monitoringCache);
284
284
  const mergeCostPoints = useAgentRuntimeStore(s => s.mergeCostPoints);
@@ -327,7 +327,7 @@ export function CostUsageChart({ serviceName, agentId, runtimeId, apiKey, datala
327
327
  }, [agentId, cacheServiceKey, cachedEntry]);
328
328
  // Bootstrap chart with existing OTEL cost metrics before websocket updates.
329
329
  useEffect(() => {
330
- if (!cacheServiceKey || !apiKey || !datalayerUrl) {
330
+ if (!cacheServiceKey || !apiKey || !otelUrl) {
331
331
  return;
332
332
  }
333
333
  let cancelled = false;
@@ -337,14 +337,14 @@ export function CostUsageChart({ serviceName, agentId, runtimeId, apiKey, datala
337
337
  fetchOtelMetricRows({
338
338
  metric: COST_RUN_METRIC,
339
339
  serviceName,
340
- datalayerUrl,
340
+ otelUrl,
341
341
  apiKey,
342
342
  limit: 1000,
343
343
  }),
344
344
  fetchOtelMetricRows({
345
345
  metric: COST_CUMULATIVE_METRIC,
346
346
  serviceName,
347
- datalayerUrl,
347
+ otelUrl,
348
348
  apiKey,
349
349
  limit: 1000,
350
350
  }),
@@ -391,7 +391,7 @@ export function CostUsageChart({ serviceName, agentId, runtimeId, apiKey, datala
391
391
  agentId,
392
392
  apiKey,
393
393
  cacheServiceKey,
394
- datalayerUrl,
394
+ otelUrl,
395
395
  mergeCostPoints,
396
396
  runtimeId,
397
397
  serviceName,
@@ -439,7 +439,7 @@ export function CostUsageChart({ serviceName, agentId, runtimeId, apiKey, datala
439
439
  if (!cacheServiceKey || !apiKey)
440
440
  return;
441
441
  const rawBaseUrl = wsUrl ||
442
- datalayerUrl ||
442
+ otelUrl ||
443
443
  (typeof window !== 'undefined' ? window.location.origin : '');
444
444
  if (!rawBaseUrl)
445
445
  return;
@@ -496,7 +496,7 @@ export function CostUsageChart({ serviceName, agentId, runtimeId, apiKey, datala
496
496
  apiKey,
497
497
  cacheServiceKey,
498
498
  mergeCostPoints,
499
- datalayerUrl,
499
+ otelUrl,
500
500
  runtimeId,
501
501
  serviceName,
502
502
  wsUrl,