@datalayer/agent-runtimes 1.0.18 → 1.0.20
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 +14 -6
- package/lib/AgentNode.js +567 -67
- package/lib/App.js +2 -2
- package/lib/agent-node/AgentNodeGallery.d.ts +80 -0
- package/lib/agent-node/AgentNodeGallery.js +627 -0
- package/lib/agent-notebook-main.js +0 -1
- package/lib/api/runtimes/runtimes.d.ts +57 -0
- package/lib/api/runtimes/runtimes.js +55 -1
- package/lib/chat/Chat.d.ts +14 -1
- package/lib/chat/Chat.js +22 -7
- package/lib/chat/base/ChatBase.js +86 -23
- package/lib/chat/document/EphemeralDocument.d.ts +49 -1
- package/lib/chat/document/EphemeralDocument.js +141 -15
- package/lib/chat/header/ChatHeaderBase.d.ts +3 -1
- package/lib/chat/header/ChatHeaderBase.js +5 -3
- package/lib/chat/messages/ChatMessageList.d.ts +19 -0
- package/lib/chat/messages/ChatMessageList.js +180 -9
- package/lib/chat/notebook/EphemeralNotebook.d.ts +40 -1
- package/lib/chat/notebook/EphemeralNotebook.js +49 -13
- package/lib/chat/prompt/InputPrompt.js +1 -1
- package/lib/chat/tools/SubagentActivity.d.ts +20 -0
- package/lib/chat/tools/SubagentActivity.js +154 -0
- package/lib/chat/tools/index.d.ts +1 -0
- package/lib/chat/tools/index.js +1 -0
- package/lib/chat/usage/TokenUsageBar.js +3 -3
- package/lib/client/AgentRuntimesClient.d.ts +5 -0
- package/lib/client/AgentsMixin.js +3 -1
- package/lib/client/mixins/RuntimesMixin.d.ts +12 -0
- package/lib/client/mixins/RuntimesMixin.js +24 -1
- package/lib/components/AgentSummary.d.ts +1 -0
- package/lib/components/AgentSummary.js +66 -10
- package/lib/components/runtimes/RuntimePickerBase.js +64 -29
- package/lib/components/runtimes/RuntimePickerCell.js +1 -1
- package/lib/components/runtimes/RuntimePickerNotebook.js +1 -1
- package/lib/components/runtimes/RuntimeSimplePicker.js +3 -2
- package/lib/components/runtimes/RuntimeUtils.js +2 -2
- package/lib/context/GraphFlowChart.js +1 -1
- package/lib/context/TokenUsageChart.js +1 -1
- package/lib/context/TurnGraphChart.js +2 -2
- package/lib/examples/A2UiAgentExample.js +4 -4
- package/lib/examples/A2UiComponentsGalleryExample.js +3 -3
- package/lib/examples/A2UiContactCardExample.js +3 -3
- package/lib/examples/A2UiRestaurantExample.js +2 -2
- package/lib/examples/A2UiViewerExample.js +3 -3
- package/lib/examples/AgUiAgenticExample.js +3 -3
- package/lib/examples/AgUiBackendToolRenderingExample.js +2 -2
- package/lib/examples/AgUiHaikuGenUiExample.js +3 -3
- package/lib/examples/AgUiHumanInTheLoopExample.js +5 -5
- package/lib/examples/AgUiSharedStateExample.js +3 -3
- package/lib/examples/AgUiToolsBasedGenUiExample.js +7 -5
- package/lib/examples/AgentCheckpointsExample.js +6 -5
- package/lib/examples/{AgentSandboxExample.d.ts → AgentCodeSandboxExample.d.ts} +4 -4
- package/lib/examples/{AgentSandboxExample.js → AgentCodeSandboxExample.js} +10 -9
- package/lib/examples/AgentCodeSandboxesExample.js +2 -2
- package/lib/examples/AgentCodemodeExample.js +3 -3
- package/lib/examples/AgentCompactionExample.d.ts +12 -0
- package/lib/examples/AgentCompactionExample.js +244 -0
- package/lib/examples/AgentEvalsExample.js +10 -20
- package/lib/examples/AgentGuardrailsExample.js +2 -2
- package/lib/examples/AgentHooksExample.js +1 -1
- package/lib/examples/AgentInferenceProviderExample.js +6 -8
- package/lib/examples/AgentLoopExample.js +3 -3
- package/lib/examples/AgentMCPExample.js +3 -3
- package/lib/examples/AgentMemoryExample.d.ts +4 -2
- package/lib/examples/AgentMemoryExample.js +93 -10
- package/lib/examples/AgentMonitoringExample.js +2 -2
- package/lib/examples/AgentNotificationsExample.js +1 -1
- package/lib/examples/AgentOtelExample.d.ts +2 -3
- package/lib/examples/AgentOtelExample.js +7 -12
- package/lib/examples/AgentOutputsExample.js +5 -5
- package/lib/examples/AgentParametersExample.js +3 -3
- package/lib/examples/AgentSkillsExample.js +4 -4
- package/lib/examples/AgentSubagentsExample.d.ts +2 -2
- package/lib/examples/AgentSubagentsExample.js +43 -34
- package/lib/examples/AgentToolApprovalsExample.js +1 -1
- package/lib/examples/AgentTriggersExample.js +9 -11
- package/lib/examples/AgentspecsExample.js +13 -5
- package/lib/examples/CellExample.d.ts +6 -0
- package/lib/examples/CellExample.js +84 -0
- package/lib/examples/ChatCustomExample.js +1 -1
- package/lib/examples/ChatExample.js +1 -1
- package/lib/examples/ChatStandaloneExample.js +2 -2
- package/lib/examples/HomeExample.js +29 -28
- package/lib/examples/Lexical2Example.js +2 -2
- package/lib/examples/LexicalAgentExample.js +1 -1
- package/lib/examples/LexicalAgentSidebarExample.js +2 -2
- package/lib/examples/NotebookAgentSidebarExample.d.ts +1 -1
- package/lib/examples/NotebookAgentSidebarExample.js +5 -4
- package/lib/examples/NotebookCollaborationExample.js +3 -3
- package/lib/examples/NotebookExample.js +2 -2
- package/lib/examples/components/ExampleWrapper.js +5 -0
- package/lib/examples/components/Header.js +2 -2
- package/lib/examples/components/HeaderControls.js +1 -1
- package/lib/examples/components/LexicalEditor.js +1 -1
- package/lib/examples/components/MainContent.js +1 -1
- package/lib/examples/components/MockFileBrowser.js +8 -8
- package/lib/examples/components/TimeTravel.js +1 -1
- package/lib/examples/components/haiku/HaikuDisplay.js +2 -2
- package/lib/examples/example-selector.js +4 -3
- package/lib/examples/hooks/useExampleAgentRuntime.js +11 -1
- package/lib/examples/hooks/useExampleAgentRuntimes.d.ts +7 -0
- package/lib/examples/hooks/useExampleAgentRuntimes.js +82 -0
- package/lib/examples/index.d.ts +2 -1
- package/lib/examples/index.js +2 -1
- package/lib/examples/main.js +359 -46
- package/lib/examples/utils/agentSummaryStore.d.ts +17 -0
- package/lib/examples/utils/themedProvider.js +32 -2
- package/lib/examples/utils/useExampleAgentRuntimesUrl.js +2 -1
- package/lib/examples2/NotebookMutationsKernel.js +6 -3
- package/lib/examples2/NotebookMutationsServiceManager.js +6 -3
- package/lib/examples2/ReactRouterExample.js +5 -5
- package/lib/examples2/main.js +38 -0
- package/lib/hooks/useAIAgentsWebSocket.js +35 -0
- package/lib/hooks/useAgentRuntimes.d.ts +22 -0
- package/lib/hooks/useAgentRuntimes.js +192 -5
- package/lib/hooks/useCheckpoints.js +2 -2
- package/lib/hooks/useToolApprovals.d.ts +10 -4
- package/lib/hooks/useToolApprovals.js +11 -5
- package/lib/identity/AgentIdentity.js +1 -2
- package/lib/models/Runtime.d.ts +10 -8
- package/lib/models/RuntimeDTO.d.ts +5 -3
- package/lib/models/RuntimeDTO.js +3 -3
- package/lib/runtimes/actions.js +3 -1
- package/lib/runtimes/apis.d.ts +7 -0
- package/lib/shims/primerAddonsBox.d.ts +1 -0
- package/lib/shims/primerAddonsBox.js +7 -0
- package/lib/specs/agents/agents.d.ts +51 -0
- package/lib/specs/agents/agents.js +3389 -94
- package/lib/specs/models.d.ts +2 -0
- package/lib/specs/models.js +37 -0
- package/lib/stores/agentRuntimeStore.d.ts +32 -1
- package/lib/stores/agentRuntimeStore.js +65 -1
- package/lib/stores/index.d.ts +1 -1
- package/lib/stores/index.js +1 -1
- package/lib/types/agents.d.ts +9 -3
- package/lib/types/agentspecs.d.ts +2 -0
- package/lib/types/chat.d.ts +83 -0
- package/lib/types/models.d.ts +5 -0
- package/lib/types/stream.d.ts +58 -1
- package/package.json +6 -5
- package/scripts/codegen/generate_agents.py +7 -0
- package/scripts/codegen/generate_models.py +22 -9
- package/scripts/gen_workers.py +340 -0
- package/lib/examples/CellSimpleExample.d.ts +0 -6
- package/lib/examples/CellSimpleExample.js +0 -20
- package/scripts/codegen/__pycache__/generate_sandbox_agents.cpython-313.pyc +0 -0
package/lib/examples/main.js
CHANGED
|
@@ -3,16 +3,15 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
|
-
import { createDatalayerServiceManager } from '../services/DatalayerServiceManager';
|
|
7
6
|
/// <reference types="vite/client" />
|
|
8
7
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
9
8
|
import { createRoot } from 'react-dom/client';
|
|
10
9
|
import { loadJupyterConfig, JupyterReactTheme, createServerSettings, setJupyterServerUrl, setJupyterServerToken, getJupyterServerUrl, getJupyterServerToken, } from '@datalayer/jupyter-react';
|
|
11
10
|
import { ServiceManager } from '@jupyterlab/services';
|
|
12
|
-
import { DatalayerThemeProvider, DatalayerLogoText, getLogoColors, themeConfigs, Box, } from '@datalayer/primer-addons';
|
|
11
|
+
import { DatalayerThemeProvider, DatalayerLogoText, getLogoColors, themeConfigs, Box, SlidingPanel, } from '@datalayer/primer-addons';
|
|
13
12
|
import { AgentSummary } from '../components';
|
|
14
13
|
import { HomeIcon, SignInIcon, SignOutIcon } from '@primer/octicons-react';
|
|
15
|
-
import { Button, Spinner, Text } from '@primer/react';
|
|
14
|
+
import { Button, SegmentedControl, Spinner, Text } from '@primer/react';
|
|
16
15
|
import { AppearanceControlsWithStore } from '@datalayer/primer-addons/lib/components/appearance';
|
|
17
16
|
import { coreStore, iamStore } from '@datalayer/core';
|
|
18
17
|
import { DATALAYER_IAM_TOKEN_KEY, DATALAYER_IAM_USER_KEY, } from '../state/substates';
|
|
@@ -29,9 +28,90 @@ import { useAgentSummaryStore } from './utils/agentSummaryStore';
|
|
|
29
28
|
import { useExampleThemeStore } from './utils/themeStore';
|
|
30
29
|
import { ExampleWrapper } from './components/ExampleWrapper';
|
|
31
30
|
import { ExampleErrorBoundary } from './components/ExampleErrorBoundary';
|
|
31
|
+
import { createServiceManagerFromAgentSandbox } from '../hooks/useAgentRuntimes';
|
|
32
|
+
import { DEFAULT_MODEL } from '../specs/models';
|
|
32
33
|
import nbformatExample from './utils/notebooks/NotebookExample1.ipynb.json';
|
|
33
34
|
import '../../style/primer-primitives.css';
|
|
34
35
|
const DEFAULT_RUNTIMES_URL = 'https://r1.datalayer.run';
|
|
36
|
+
const DEFAULT_LOCAL_JUPYTER_SERVER_URL = 'http://localhost:8888/api/jupyter-server';
|
|
37
|
+
const DEFAULT_LOCAL_JUPYTER_SERVER_TOKEN = '60c1661cc408f978c309d04157af55c9588ff9557c9380e4fb50785750703da6';
|
|
38
|
+
const DEFAULT_CLOUD_RUNTIME_ENVIRONMENT = 'ai-agents-env';
|
|
39
|
+
const isNotebookOrCellExample = (exampleId) => {
|
|
40
|
+
return ((exampleId.includes('Notebook') || exampleId.includes('Cell')) &&
|
|
41
|
+
!exampleId.includes('Agent'));
|
|
42
|
+
};
|
|
43
|
+
const wait = (ms) => new Promise(resolve => {
|
|
44
|
+
window.setTimeout(resolve, ms);
|
|
45
|
+
});
|
|
46
|
+
const safeExampleId = (value) => {
|
|
47
|
+
return value
|
|
48
|
+
.toLowerCase()
|
|
49
|
+
.replace(/[^a-z0-9-]+/g, '-')
|
|
50
|
+
.replace(/^-+|-+$/g, '')
|
|
51
|
+
.slice(0, 40);
|
|
52
|
+
};
|
|
53
|
+
const toAgentApiBaseUrl = (ingress) => {
|
|
54
|
+
const normalized = ingress.replace(/\/$/, '');
|
|
55
|
+
if (normalized.includes('/api/agent-runtimes')) {
|
|
56
|
+
return normalized;
|
|
57
|
+
}
|
|
58
|
+
if (normalized.includes('/api/jupyter-server')) {
|
|
59
|
+
return normalized.replace('/api/jupyter-server', '/api/agent-runtimes');
|
|
60
|
+
}
|
|
61
|
+
if (normalized.includes('/jupyter/server/')) {
|
|
62
|
+
return normalized.replace('/jupyter/server/', '/agent-runtimes/');
|
|
63
|
+
}
|
|
64
|
+
if (normalized.includes('/jupyter-server/')) {
|
|
65
|
+
return normalized.replace('/jupyter-server/', '/agent-runtimes/');
|
|
66
|
+
}
|
|
67
|
+
return normalized.replace('/jupyter/', '/agent-runtimes/');
|
|
68
|
+
};
|
|
69
|
+
const toSurfaceLabel = (exampleId) => {
|
|
70
|
+
if (exampleId.toLowerCase().includes('cell')) {
|
|
71
|
+
return 'cell';
|
|
72
|
+
}
|
|
73
|
+
return 'notebook';
|
|
74
|
+
};
|
|
75
|
+
const normalizeSandboxBaseUrl = (sandboxBaseUrl, agentBaseUrl) => {
|
|
76
|
+
const sandboxRaw = String(sandboxBaseUrl || '').trim();
|
|
77
|
+
const agentRaw = String(agentBaseUrl || '').trim();
|
|
78
|
+
if (!sandboxRaw) {
|
|
79
|
+
return agentRaw;
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const sandboxUrl = new URL(sandboxRaw);
|
|
83
|
+
const host = sandboxUrl.hostname;
|
|
84
|
+
const isInternalHost = host === '0.0.0.0' || host === '127.0.0.1' || host === 'localhost';
|
|
85
|
+
if (!isInternalHost) {
|
|
86
|
+
return sandboxRaw;
|
|
87
|
+
}
|
|
88
|
+
const agentUrl = new URL(agentRaw);
|
|
89
|
+
sandboxUrl.protocol = agentUrl.protocol;
|
|
90
|
+
sandboxUrl.host = agentUrl.host;
|
|
91
|
+
return sandboxUrl.toString();
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return sandboxRaw;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const withTokenQueryParam = (rawUrl, token) => {
|
|
98
|
+
const normalizedUrl = String(rawUrl || '').trim();
|
|
99
|
+
const normalizedToken = String(token || '').trim();
|
|
100
|
+
if (!normalizedUrl || !normalizedToken) {
|
|
101
|
+
return normalizedUrl;
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const parsed = new URL(normalizedUrl);
|
|
105
|
+
if (!parsed.searchParams.get('token') &&
|
|
106
|
+
!parsed.searchParams.get('jupyter_token')) {
|
|
107
|
+
parsed.searchParams.set('token', normalizedToken);
|
|
108
|
+
}
|
|
109
|
+
return parsed.toString();
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return normalizedUrl;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
35
115
|
const resolveRuntimesUrl = (configured) => {
|
|
36
116
|
const envRuntimeUrl = import.meta.env.VITE_DATALAYER_RUNTIMES_URL;
|
|
37
117
|
const envBaseUrl = import.meta.env.VITE_DATALAYER_URL;
|
|
@@ -54,6 +134,50 @@ const toAgentRuntimesBaseUrl = (value) => {
|
|
|
54
134
|
}
|
|
55
135
|
return normalized;
|
|
56
136
|
};
|
|
137
|
+
const isProd1JupyterServerUrl = (value) => {
|
|
138
|
+
if (!value) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
return new URL(value).hostname === 'prod1.datalayer.run';
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return value.includes('prod1.datalayer.run');
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
const resolveLocalJupyterServerUrl = () => {
|
|
149
|
+
const normalizeLoopbackHost = (raw) => {
|
|
150
|
+
const trimmed = raw.trim().replace(/\/$/, '');
|
|
151
|
+
if (!trimmed) {
|
|
152
|
+
return DEFAULT_LOCAL_JUPYTER_SERVER_URL;
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const parsed = new URL(trimmed);
|
|
156
|
+
if (parsed.hostname === '0.0.0.0') {
|
|
157
|
+
parsed.hostname = 'localhost';
|
|
158
|
+
}
|
|
159
|
+
return parsed.toString().replace(/\/$/, '');
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return trimmed.replace('://0.0.0.0', '://localhost');
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const envLocalUrl = import.meta.env.VITE_JUPYTER_SERVER_URL?.trim();
|
|
166
|
+
if (envLocalUrl) {
|
|
167
|
+
return normalizeLoopbackHost(envLocalUrl);
|
|
168
|
+
}
|
|
169
|
+
const configured = getJupyterServerUrl();
|
|
170
|
+
if (configured && !isProd1JupyterServerUrl(configured)) {
|
|
171
|
+
return normalizeLoopbackHost(configured);
|
|
172
|
+
}
|
|
173
|
+
return normalizeLoopbackHost(DEFAULT_LOCAL_JUPYTER_SERVER_URL);
|
|
174
|
+
};
|
|
175
|
+
const ensureLocalJupyterToken = () => {
|
|
176
|
+
const token = (getJupyterServerToken() || '').trim();
|
|
177
|
+
if (!token) {
|
|
178
|
+
setJupyterServerToken(DEFAULT_LOCAL_JUPYTER_SERVER_TOKEN);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
57
181
|
// Load configurations from DOM
|
|
58
182
|
const loadConfigurations = () => {
|
|
59
183
|
// Load Datalayer configuration
|
|
@@ -360,12 +484,19 @@ const NotebookOnlyApp = () => {
|
|
|
360
484
|
if (runtimeTargetStore.getState().target === 'cloud' &&
|
|
361
485
|
configuration?.token) {
|
|
362
486
|
try {
|
|
363
|
-
const
|
|
364
|
-
|
|
487
|
+
const activeSummary = agentSummaryStore.getState().active;
|
|
488
|
+
if (!activeSummary || activeSummary.location !== 'cloud') {
|
|
489
|
+
throw new Error('No active cloud agent sandbox found for notebook-only mode.');
|
|
490
|
+
}
|
|
491
|
+
const manager = await createServiceManagerFromAgentSandbox({
|
|
492
|
+
baseUrl: activeSummary.sandboxBaseUrl || activeSummary.baseUrl,
|
|
493
|
+
agentId: activeSummary.agentId,
|
|
494
|
+
agentBaseUrl: activeSummary.baseUrl,
|
|
495
|
+
}, configuration.token);
|
|
365
496
|
setServiceManager(manager);
|
|
366
497
|
}
|
|
367
498
|
catch (error) {
|
|
368
|
-
console.error('Failed to
|
|
499
|
+
console.error('Failed to connect to cloud sandbox:', error);
|
|
369
500
|
const serverSettings = createServerSettings(getJupyterServerUrl(), getJupyterServerToken());
|
|
370
501
|
const manager = new ServiceManager({ serverSettings });
|
|
371
502
|
await manager.ready;
|
|
@@ -373,6 +504,8 @@ const NotebookOnlyApp = () => {
|
|
|
373
504
|
}
|
|
374
505
|
}
|
|
375
506
|
else {
|
|
507
|
+
setJupyterServerUrl(resolveLocalJupyterServerUrl());
|
|
508
|
+
ensureLocalJupyterToken();
|
|
376
509
|
const serverSettings = createServerSettings(getJupyterServerUrl(), getJupyterServerToken());
|
|
377
510
|
const manager = new ServiceManager({ serverSettings });
|
|
378
511
|
await manager.ready;
|
|
@@ -415,8 +548,18 @@ export const ExampleApp = () => {
|
|
|
415
548
|
const [selectedExample, setSelectedExample] = useState(getDefaultExampleName());
|
|
416
549
|
const [searchQuery, setSearchQuery] = useState(getInitialSearchQuery());
|
|
417
550
|
const [isChangingExample, setIsChangingExample] = useState(false);
|
|
551
|
+
const [topNotice, setTopNotice] = useState(null);
|
|
418
552
|
const runtimeTarget = useRuntimeTargetStore(state => state.target);
|
|
419
553
|
const setRuntimeTarget = useRuntimeTargetStore(state => state.setTarget);
|
|
554
|
+
const showTopNotice = useCallback((message, tone = 'info', durationMs = 4500, details) => {
|
|
555
|
+
setTopNotice({
|
|
556
|
+
id: Date.now() + Math.floor(Math.random() * 1000),
|
|
557
|
+
message,
|
|
558
|
+
details,
|
|
559
|
+
tone,
|
|
560
|
+
durationMs,
|
|
561
|
+
});
|
|
562
|
+
}, []);
|
|
420
563
|
const filteredExampleEntries = useMemo(() => {
|
|
421
564
|
const normalized = searchQuery.trim().toLowerCase();
|
|
422
565
|
const all = getExampleEntriesList();
|
|
@@ -449,11 +592,14 @@ export const ExampleApp = () => {
|
|
|
449
592
|
}
|
|
450
593
|
catch (e) {
|
|
451
594
|
console.error('Failed to load example:', e);
|
|
595
|
+
showTopNotice(`Failed to load example: ${e instanceof Error ? e.message : String(e)}`, 'error', 6000);
|
|
452
596
|
setError(`Failed to load example: ${e}`);
|
|
453
597
|
setIsChangingExample(false);
|
|
454
598
|
}
|
|
455
599
|
};
|
|
456
600
|
const createLocalServiceManager = async () => {
|
|
601
|
+
setJupyterServerUrl(resolveLocalJupyterServerUrl());
|
|
602
|
+
ensureLocalJupyterToken();
|
|
457
603
|
const serverSettings = createServerSettings(getJupyterServerUrl(), getJupyterServerToken());
|
|
458
604
|
const manager = new ServiceManager({ serverSettings });
|
|
459
605
|
await manager.ready;
|
|
@@ -464,16 +610,182 @@ export const ExampleApp = () => {
|
|
|
464
610
|
if (!configuration?.token) {
|
|
465
611
|
throw new Error('Cloud runtime requires authentication. Please sign in.');
|
|
466
612
|
}
|
|
613
|
+
const connectFromSummary = async (summary) => {
|
|
614
|
+
const connectOnce = async (candidate) => {
|
|
615
|
+
const resolvedSandboxBaseUrl = normalizeSandboxBaseUrl(candidate.sandboxBaseUrl, candidate.baseUrl);
|
|
616
|
+
const manager = await createServiceManagerFromAgentSandbox({
|
|
617
|
+
baseUrl: resolvedSandboxBaseUrl,
|
|
618
|
+
agentId: candidate.agentId,
|
|
619
|
+
agentBaseUrl: candidate.baseUrl,
|
|
620
|
+
runtimeEnvironment: candidate.runtimeEnvironment,
|
|
621
|
+
}, configuration.token);
|
|
622
|
+
const cloudBaseUrl = String(manager.serverSettings.baseUrl || '').trim();
|
|
623
|
+
const cloudToken = String(manager.serverSettings.token || '').trim();
|
|
624
|
+
if (cloudBaseUrl) {
|
|
625
|
+
setJupyterServerUrl(cloudBaseUrl.replace(/\/$/, ''));
|
|
626
|
+
}
|
|
627
|
+
if (cloudToken) {
|
|
628
|
+
setJupyterServerToken(cloudToken);
|
|
629
|
+
}
|
|
630
|
+
return manager;
|
|
631
|
+
};
|
|
632
|
+
let lastError;
|
|
633
|
+
for (let attempt = 1; attempt <= 8; attempt += 1) {
|
|
634
|
+
try {
|
|
635
|
+
return await connectOnce(summary);
|
|
636
|
+
}
|
|
637
|
+
catch (error) {
|
|
638
|
+
lastError = error;
|
|
639
|
+
if (attempt === 8) {
|
|
640
|
+
break;
|
|
641
|
+
}
|
|
642
|
+
await wait(700 * attempt);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
throw lastError;
|
|
646
|
+
};
|
|
647
|
+
const bootstrapCloudSandbox = async () => {
|
|
648
|
+
const runtimesUrl = resolveRuntimesUrl(configuration.runtimesUrl);
|
|
649
|
+
const exampleSlug = safeExampleId(selectedExample || 'example');
|
|
650
|
+
const runtimeResp = await fetch(`${runtimesUrl}/api/runtimes/v1/runtimes`, {
|
|
651
|
+
method: 'POST',
|
|
652
|
+
headers: {
|
|
653
|
+
Authorization: `Bearer ${configuration.token}`,
|
|
654
|
+
'Content-Type': 'application/json',
|
|
655
|
+
},
|
|
656
|
+
body: JSON.stringify({
|
|
657
|
+
environment: {
|
|
658
|
+
name: DEFAULT_CLOUD_RUNTIME_ENVIRONMENT,
|
|
659
|
+
},
|
|
660
|
+
given_name: `${exampleSlug}-sandbox`,
|
|
661
|
+
credits_limit: 5,
|
|
662
|
+
type: 'notebook',
|
|
663
|
+
editor_variant: 'none',
|
|
664
|
+
}),
|
|
665
|
+
});
|
|
666
|
+
if (!runtimeResp.ok) {
|
|
667
|
+
const failure = await runtimeResp.json().catch(() => ({}));
|
|
668
|
+
throw new Error(String(failure.detail ||
|
|
669
|
+
`Failed to launch cloud runtime (${runtimeResp.status}).`));
|
|
670
|
+
}
|
|
671
|
+
const runtimePayload = (await runtimeResp.json());
|
|
672
|
+
const ingress = String(runtimePayload.runtime?.ingress || runtimePayload.ingress || '').trim();
|
|
673
|
+
if (!ingress) {
|
|
674
|
+
throw new Error('Cloud runtime launched but did not expose a Jupyter ingress URL.');
|
|
675
|
+
}
|
|
676
|
+
const agentBaseUrl = toAgentApiBaseUrl(ingress);
|
|
677
|
+
const agentId = `${exampleSlug}-cloud-agent`;
|
|
678
|
+
const agentResp = await fetch(`${agentBaseUrl}/api/v1/agents`, {
|
|
679
|
+
method: 'POST',
|
|
680
|
+
headers: {
|
|
681
|
+
Authorization: `Bearer ${configuration.token}`,
|
|
682
|
+
'Content-Type': 'application/json',
|
|
683
|
+
},
|
|
684
|
+
body: JSON.stringify({
|
|
685
|
+
name: agentId,
|
|
686
|
+
description: `Cloud sandbox agent for ${selectedExample}`,
|
|
687
|
+
agent_library: 'pydantic-ai',
|
|
688
|
+
transport: 'ag-ui',
|
|
689
|
+
model: DEFAULT_MODEL,
|
|
690
|
+
system_prompt: 'You are a helpful AI assistant.',
|
|
691
|
+
}),
|
|
692
|
+
});
|
|
693
|
+
if (!agentResp.ok &&
|
|
694
|
+
agentResp.status !== 400 &&
|
|
695
|
+
agentResp.status !== 409) {
|
|
696
|
+
const failure = await agentResp.json().catch(() => ({}));
|
|
697
|
+
throw new Error(String(failure.detail ||
|
|
698
|
+
`Cloud runtime launched but agent creation failed (${agentResp.status}).`));
|
|
699
|
+
}
|
|
700
|
+
const agentPayload = (await agentResp
|
|
701
|
+
.clone()
|
|
702
|
+
.json()
|
|
703
|
+
.catch(() => ({})));
|
|
704
|
+
const resolvedAgentId = String(agentPayload.agent_id ||
|
|
705
|
+
agentPayload.id ||
|
|
706
|
+
agentPayload.agent?.agent_id ||
|
|
707
|
+
agentPayload.agent?.id ||
|
|
708
|
+
'').trim() || agentId;
|
|
709
|
+
const resolvedJupyterToken = String(agentPayload.jupyter_token ||
|
|
710
|
+
agentPayload.token ||
|
|
711
|
+
runtimePayload.runtime?.jupyter_token ||
|
|
712
|
+
runtimePayload.runtime?.token ||
|
|
713
|
+
runtimePayload.jupyter_token ||
|
|
714
|
+
runtimePayload.token ||
|
|
715
|
+
'').trim();
|
|
716
|
+
const runtimeEnvironment = {
|
|
717
|
+
environmentName: String(runtimePayload.runtime?.environment?.name || '').trim() ||
|
|
718
|
+
undefined,
|
|
719
|
+
environmentTitle: String(runtimePayload.runtime?.environment?.title || '').trim() ||
|
|
720
|
+
undefined,
|
|
721
|
+
cpu: String(runtimePayload.runtime?.environment?.cpu ||
|
|
722
|
+
runtimePayload.runtime?.environment?.resources?.cpu ||
|
|
723
|
+
'').trim() || undefined,
|
|
724
|
+
memory: String(runtimePayload.runtime?.environment?.memory ||
|
|
725
|
+
runtimePayload.runtime?.environment?.resources?.memory ||
|
|
726
|
+
'').trim() || undefined,
|
|
727
|
+
gpu: [
|
|
728
|
+
runtimePayload.runtime?.environment?.gpu ||
|
|
729
|
+
runtimePayload.runtime?.environment?.resources?.gpu ||
|
|
730
|
+
runtimePayload.runtime?.environment?.resources?.gpu_count ||
|
|
731
|
+
runtimePayload.runtime?.environment?.resources?.['nvidia.com/gpu'] ||
|
|
732
|
+
'',
|
|
733
|
+
runtimePayload.runtime?.environment?.resources?.gpu_type || '',
|
|
734
|
+
runtimePayload.runtime?.environment?.resources?.gpu_memory ||
|
|
735
|
+
'',
|
|
736
|
+
]
|
|
737
|
+
.map(value => String(value || '').trim())
|
|
738
|
+
.filter(Boolean)
|
|
739
|
+
.join(' ') || undefined,
|
|
740
|
+
};
|
|
741
|
+
return {
|
|
742
|
+
agentBaseUrl,
|
|
743
|
+
agentId: resolvedAgentId,
|
|
744
|
+
ingress: withTokenQueryParam(ingress, resolvedJupyterToken),
|
|
745
|
+
runtimeEnvironment,
|
|
746
|
+
};
|
|
747
|
+
};
|
|
467
748
|
const activeSummary = agentSummaryStore.getState().active;
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
749
|
+
if (activeSummary?.location === 'cloud' &&
|
|
750
|
+
(activeSummary.sandboxBaseUrl || activeSummary.baseUrl)) {
|
|
751
|
+
try {
|
|
752
|
+
return await connectFromSummary({
|
|
753
|
+
baseUrl: activeSummary.baseUrl,
|
|
754
|
+
sandboxBaseUrl: activeSummary.sandboxBaseUrl,
|
|
755
|
+
agentId: activeSummary.agentId,
|
|
756
|
+
runtimeEnvironment: activeSummary.runtimeEnvironment,
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
catch (error) {
|
|
760
|
+
if (!isNotebookOrCellExample(selectedExample)) {
|
|
761
|
+
throw error;
|
|
762
|
+
}
|
|
763
|
+
showTopNotice('Existing cloud sandbox is unavailable. Launching a fresh sandbox...', 'warning', 3500);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
if (!isNotebookOrCellExample(selectedExample)) {
|
|
767
|
+
throw new Error('No active cloud agent sandbox found. Open an agent example and launch a cloud agent first.');
|
|
768
|
+
}
|
|
769
|
+
showTopNotice('Starting a cloud agent sandbox...', 'info', 2600);
|
|
770
|
+
const launched = await bootstrapCloudSandbox();
|
|
771
|
+
agentSummaryStore.getState().setActive({
|
|
772
|
+
exampleId: selectedExample,
|
|
773
|
+
agentName: launched.agentId,
|
|
774
|
+
agentId: launched.agentId,
|
|
775
|
+
location: 'cloud',
|
|
776
|
+
baseUrl: launched.agentBaseUrl,
|
|
777
|
+
sandboxBaseUrl: launched.ingress,
|
|
778
|
+
runtimeEnvironment: launched.runtimeEnvironment,
|
|
779
|
+
status: 'running',
|
|
780
|
+
isReady: true,
|
|
781
|
+
});
|
|
782
|
+
showTopNotice(`Cloud sandbox ready. Connecting ${toSurfaceLabel(selectedExample)} to it...`, 'success', 2600);
|
|
783
|
+
return connectFromSummary({
|
|
784
|
+
baseUrl: launched.agentBaseUrl,
|
|
785
|
+
sandboxBaseUrl: launched.ingress,
|
|
786
|
+
agentId: launched.agentId,
|
|
787
|
+
runtimeEnvironment: launched.runtimeEnvironment,
|
|
788
|
+
});
|
|
477
789
|
};
|
|
478
790
|
useEffect(() => {
|
|
479
791
|
// Load configurations
|
|
@@ -488,14 +800,13 @@ export const ExampleApp = () => {
|
|
|
488
800
|
try {
|
|
489
801
|
const manager = await createCloudServiceManager();
|
|
490
802
|
setServiceManager(manager);
|
|
803
|
+
showTopNotice('Code sandbox connected successfully (cloud).', 'success', 2600);
|
|
491
804
|
// Load initial example
|
|
492
805
|
await loadExample(selectedExample, manager);
|
|
493
806
|
}
|
|
494
807
|
catch (error) {
|
|
495
808
|
console.error('Failed to create DatalayerServiceManager:', error);
|
|
496
|
-
|
|
497
|
-
// app stays usable.
|
|
498
|
-
setError(`Cloud runtime unavailable, using local instead: ${error instanceof Error ? error.message : String(error)}`);
|
|
809
|
+
showTopNotice(`Cloud runtime unavailable, using local instead: ${error instanceof Error ? error.message : String(error)}`, 'warning', 5500);
|
|
499
810
|
const manager = await createLocalServiceManager();
|
|
500
811
|
setServiceManager(manager);
|
|
501
812
|
// Load initial example
|
|
@@ -513,6 +824,7 @@ export const ExampleApp = () => {
|
|
|
513
824
|
}
|
|
514
825
|
catch (e) {
|
|
515
826
|
console.error('Failed to initialize app:', e);
|
|
827
|
+
showTopNotice(`Failed to initialize app: ${e instanceof Error ? e.message : String(e)}`, 'error', 6000);
|
|
516
828
|
setError(`Failed to initialize app: ${e}`);
|
|
517
829
|
setLoading(false);
|
|
518
830
|
}
|
|
@@ -553,9 +865,9 @@ export const ExampleApp = () => {
|
|
|
553
865
|
: await createLocalServiceManager();
|
|
554
866
|
}
|
|
555
867
|
catch (switchError) {
|
|
556
|
-
|
|
868
|
+
showTopNotice(`Failed to switch to ${newTarget}: ${switchError instanceof Error
|
|
557
869
|
? switchError.message
|
|
558
|
-
: String(switchError)}
|
|
870
|
+
: String(switchError)}`, 'error', 6000);
|
|
559
871
|
return;
|
|
560
872
|
}
|
|
561
873
|
// 1) Unmount the current example FIRST so its cleanup hooks run against the
|
|
@@ -576,6 +888,7 @@ export const ExampleApp = () => {
|
|
|
576
888
|
setServiceManager(nextManager);
|
|
577
889
|
setError(null);
|
|
578
890
|
await loadExample(selectedExample, nextManager);
|
|
891
|
+
showTopNotice(`Code sandbox connected successfully (${newTarget}).`, 'success', 2600);
|
|
579
892
|
};
|
|
580
893
|
if (loading) {
|
|
581
894
|
return (_jsxs("div", { style: { padding: '20px', textAlign: 'center' }, children: [_jsxs("h2", { children: ["Loading Example: ", selectedExample] }), _jsx("p", { children: "Please wait..." })] }));
|
|
@@ -598,16 +911,17 @@ export const ExampleApp = () => {
|
|
|
598
911
|
exampleProps.onSelectExample = (name) => {
|
|
599
912
|
void handleExampleChange(name);
|
|
600
913
|
};
|
|
601
|
-
return (_jsx(ExampleAppThemed, { selectedExample: selectedExample, isChangingExample: isChangingExample, error: error, ExampleComponent: ExampleComponent, exampleProps: exampleProps, serviceManager: serviceManager, onExampleChange: handleExampleChange, onRuntimeTargetChange: handleRuntimeTargetChange, availableExamples: getExampleEntriesList() }));
|
|
914
|
+
return (_jsx(ExampleAppThemed, { selectedExample: selectedExample, isChangingExample: isChangingExample, error: error, ExampleComponent: ExampleComponent, exampleProps: exampleProps, serviceManager: serviceManager, onExampleChange: handleExampleChange, onRuntimeTargetChange: handleRuntimeTargetChange, availableExamples: getExampleEntriesList(), topNotice: topNotice, onDismissTopNotice: () => setTopNotice(null) }));
|
|
602
915
|
};
|
|
603
916
|
/**
|
|
604
917
|
* Inner shell that reads from the theme store and wires
|
|
605
918
|
* DatalayerThemeProvider + the header bar with selectors.
|
|
606
919
|
*/
|
|
607
|
-
const ExampleAppThemed = ({ selectedExample, isChangingExample, error, ExampleComponent, exampleProps, serviceManager, onExampleChange, onRuntimeTargetChange, availableExamples, }) => {
|
|
920
|
+
const ExampleAppThemed = ({ selectedExample, isChangingExample, error, ExampleComponent, exampleProps, serviceManager, onExampleChange, onRuntimeTargetChange, availableExamples, topNotice, onDismissTopNotice, }) => {
|
|
608
921
|
const { colorMode, theme: themeVariant } = useExampleThemeStore();
|
|
609
922
|
const runtimeTarget = useRuntimeTargetStore(state => state.target);
|
|
610
923
|
const agentSummary = useAgentSummaryStore(state => state.active);
|
|
924
|
+
const isHome = selectedExample === 'HomeExample';
|
|
611
925
|
const cfg = themeConfigs[themeVariant];
|
|
612
926
|
const logoColors = getLogoColors(themeVariant, colorMode);
|
|
613
927
|
const { token, setAuth, clearAuth } = useSimpleAuthStore();
|
|
@@ -619,8 +933,11 @@ const ExampleAppThemed = ({ selectedExample, isChangingExample, error, ExampleCo
|
|
|
619
933
|
});
|
|
620
934
|
}, []);
|
|
621
935
|
useEffect(() => {
|
|
622
|
-
const
|
|
623
|
-
|
|
936
|
+
const jupyterSandboxBaseUrl = toAgentRuntimesBaseUrl(serviceManager?.serverSettings.baseUrl);
|
|
937
|
+
const agentApiBaseUrl = resolveExampleAgentRuntimesUrl(runtimeTarget);
|
|
938
|
+
const isSandboxOnlyExample = (selectedExample.includes('Notebook') ||
|
|
939
|
+
selectedExample.includes('Cell')) &&
|
|
940
|
+
!selectedExample.includes('Agent');
|
|
624
941
|
// Seed a base summary for the selected example. Do NOT clobber a richer
|
|
625
942
|
// summary that the mounted example already published (spec id, agent id,
|
|
626
943
|
// readiness) for the same example + target — otherwise fast-settling local
|
|
@@ -639,7 +956,8 @@ const ExampleAppThemed = ({ selectedExample, isChangingExample, error, ExampleCo
|
|
|
639
956
|
exampleId: selectedExample,
|
|
640
957
|
agentName: selectedExample,
|
|
641
958
|
location: runtimeTarget,
|
|
642
|
-
baseUrl,
|
|
959
|
+
baseUrl: isSandboxOnlyExample ? '' : agentApiBaseUrl,
|
|
960
|
+
sandboxBaseUrl: isSandboxOnlyExample ? jupyterSandboxBaseUrl : undefined,
|
|
643
961
|
status: isChangingExample ? 'switching' : 'selected',
|
|
644
962
|
});
|
|
645
963
|
}, [selectedExample, runtimeTarget, isChangingExample, serviceManager]);
|
|
@@ -686,7 +1004,7 @@ const ExampleAppThemed = ({ selectedExample, isChangingExample, error, ExampleCo
|
|
|
686
1004
|
justifyContent: 'space-between',
|
|
687
1005
|
gap: 3,
|
|
688
1006
|
height: '60px',
|
|
689
|
-
bg: 'canvas.
|
|
1007
|
+
bg: 'canvas.default',
|
|
690
1008
|
borderBottom: '1px solid',
|
|
691
1009
|
borderColor: 'border.default',
|
|
692
1010
|
}, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Box, { as: "button", onClick: () => void onExampleChange('HomeExample'), title: "Home", "aria-label": "Go to examples home", sx: {
|
|
@@ -705,7 +1023,7 @@ const ExampleAppThemed = ({ selectedExample, isChangingExample, error, ExampleCo
|
|
|
705
1023
|
px: 2,
|
|
706
1024
|
py: '6px',
|
|
707
1025
|
fontSize: 1,
|
|
708
|
-
fontFamily: '
|
|
1026
|
+
fontFamily: 'inherit',
|
|
709
1027
|
border: '1px solid',
|
|
710
1028
|
borderColor: 'border.default',
|
|
711
1029
|
borderRadius: 2,
|
|
@@ -715,7 +1033,7 @@ const ExampleAppThemed = ({ selectedExample, isChangingExample, error, ExampleCo
|
|
|
715
1033
|
minWidth: '250px',
|
|
716
1034
|
outline: 'none',
|
|
717
1035
|
'&:focus-visible': {
|
|
718
|
-
boxShadow: '0 0 0 2px var(--bgColor-accent-muted, rgba(
|
|
1036
|
+
boxShadow: '0 0 0 2px var(--bgColor-accent-muted, rgba(26,188,156,0.3))',
|
|
719
1037
|
},
|
|
720
1038
|
}, children: (() => {
|
|
721
1039
|
const home = availableExamples.find(e => e.id === 'HomeExample');
|
|
@@ -798,23 +1116,18 @@ const ExampleAppThemed = ({ selectedExample, isChangingExample, error, ExampleCo
|
|
|
798
1116
|
}
|
|
799
1117
|
}
|
|
800
1118
|
return _jsx(_Fragment, { children: nodes });
|
|
801
|
-
})() }),
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
outline: 'none',
|
|
814
|
-
'&:focus-visible': {
|
|
815
|
-
boxShadow: '0 0 0 2px var(--bgColor-accent-muted, rgba(9,105,218,0.3))',
|
|
816
|
-
},
|
|
817
|
-
}, children: [_jsx("option", { value: "local", children: "Local" }), _jsx("option", { value: "cloud", children: "Cloud" })] }), _jsx(AgentSummary, { summary: agentSummary }), isChangingExample && (_jsx(Box, { as: "span", sx: { color: 'fg.muted', fontSize: 0 }, children: "Loading\u2026" })), error && (_jsxs(Box, { as: "span", sx: { color: 'danger.fg', fontSize: 0 }, children: ["Error: ", error] }))] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 3 }, children: [_jsx(AppearanceControlsWithStore, { useStore: useExampleThemeStore }), _jsx(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: token ? (_jsxs(_Fragment, { children: [_jsx(UserBadge, { token: token, variant: "small", onTokenExpired: () => {
|
|
1119
|
+
})() }), _jsx(Box, { "aria-label": "Runtime target", title: "Runtime target", sx: {
|
|
1120
|
+
minWidth: '160px',
|
|
1121
|
+
opacity: isHome || isChangingExample ? 0.6 : 1,
|
|
1122
|
+
}, children: _jsxs(SegmentedControl, { "aria-label": "Runtime target", fullWidth: true, children: [_jsx(SegmentedControl.Button, { selected: runtimeTarget === 'local', disabled: isHome, onClick: () => {
|
|
1123
|
+
if (!isHome && !isChangingExample) {
|
|
1124
|
+
void onRuntimeTargetChange('local');
|
|
1125
|
+
}
|
|
1126
|
+
}, children: "Local" }), _jsx(SegmentedControl.Button, { selected: runtimeTarget === 'cloud', disabled: isHome, onClick: () => {
|
|
1127
|
+
if (!isHome && !isChangingExample) {
|
|
1128
|
+
void onRuntimeTargetChange('cloud');
|
|
1129
|
+
}
|
|
1130
|
+
}, children: "Cloud" })] }) }), !isHome && _jsx(AgentSummary, { summary: agentSummary }), isChangingExample && (_jsx(Box, { as: "span", sx: { color: 'fg.muted', fontSize: 0 }, children: "Loading\u2026" }))] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 3 }, children: [_jsx(AppearanceControlsWithStore, { useStore: useExampleThemeStore }), _jsx(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: token ? (_jsxs(_Fragment, { children: [_jsx(UserBadge, { token: token, variant: "small", onTokenExpired: () => {
|
|
818
1131
|
handleHeaderLogout();
|
|
819
1132
|
setShowSignIn(true);
|
|
820
1133
|
} }), _jsx(Button, { size: "small", variant: "invisible", onClick: handleHeaderLogout, leadingVisual: SignOutIcon, sx: { color: 'fg.muted' }, children: "Sign out" })] })) : (_jsx(Button, { size: "small", variant: "invisible", onClick: () => setShowSignIn(true), leadingVisual: SignInIcon, sx: { color: 'fg.muted' }, children: "Sign in" })) }), _jsx(Box, { as: "a", href: "https://datalayer.ai", target: "_blank", rel: "noopener noreferrer", "aria-label": "Open Datalayer website", sx: { display: 'inline-flex', alignItems: 'center' }, children: _jsx(DatalayerLogoText, { size: 24, variant: themeVariant, colorMode: colorMode, primaryColor: logoColors.primary, secondaryColor: logoColors.secondary, textColor: logoColors.textColor, primaryGradient: logoColors.primaryGradient, secondaryGradient: logoColors.secondaryGradient, gradient: true }) })] })] }), _jsx(Box, { sx: {
|
|
@@ -827,7 +1140,7 @@ const ExampleAppThemed = ({ selectedExample, isChangingExample, error, ExampleCo
|
|
|
827
1140
|
bg: 'canvas.backdrop',
|
|
828
1141
|
p: 3,
|
|
829
1142
|
overflow: 'auto',
|
|
830
|
-
}, children: _jsx(Box, { sx: { maxWidth: 640, mx: 'auto' }, children: _jsx(SignInSimple, { onSignIn: handleHeaderSignIn, onApiKeySignIn: apiKey => handleHeaderSignIn(apiKey, 'api-key-user'), title: "Agent Runtimes Examples", description: "Sign in to run authenticated examples and tools.", leadingIcon: _jsx(HomeIcon, { size: 24 }) }) }) })) : isChangingExample ? (_jsxs(Box, { sx: { p: 5, textAlign: 'center', color: 'fg.muted' }, children: [_jsxs("h3", { children: ["Loading ", selectedExample, "\u2026"] }), _jsx("p", { children: "Please wait while the example loads." })] })) : ExampleComponent ? (_jsx(ExampleErrorBoundary, { children: _jsx(ExampleWrapper, { children: _jsx(ExampleComponent, { ...exampleProps }, `${selectedExample}:${runtimeTarget}`) }, `${selectedExample}:${runtimeTarget}`) }, `${selectedExample}:${runtimeTarget}`)) : null })] }) }));
|
|
1143
|
+
}, children: _jsx(Box, { sx: { maxWidth: 640, mx: 'auto' }, children: _jsx(SignInSimple, { onSignIn: handleHeaderSignIn, onApiKeySignIn: apiKey => handleHeaderSignIn(apiKey, 'api-key-user'), title: "Agent Runtimes Examples", description: "Sign in to run authenticated examples and tools.", leadingIcon: _jsx(HomeIcon, { size: 24 }) }) }) })) : isChangingExample ? (_jsxs(Box, { sx: { p: 5, textAlign: 'center', color: 'fg.muted' }, children: [_jsxs("h3", { children: ["Loading ", selectedExample, "\u2026"] }), _jsx("p", { children: "Please wait while the example loads." })] })) : ExampleComponent ? (_jsx(ExampleErrorBoundary, { children: _jsx(ExampleWrapper, { children: _jsx(ExampleComponent, { ...exampleProps }, `${selectedExample}:${runtimeTarget}`) }, `${selectedExample}:${runtimeTarget}`) }, `${selectedExample}:${runtimeTarget}`)) : null }), _jsx(SlidingPanel, { isOpen: Boolean(topNotice), onDismiss: onDismissTopNotice, position: "north", variant: topNotice?.tone ?? 'info', durationMs: topNotice?.durationMs ?? 0, fullWidth: true, offset: 60, zIndex: 160, message: topNotice?.message || '', details: topNotice?.details })] }) }));
|
|
831
1144
|
};
|
|
832
1145
|
// Mount the app - check route to determine which app to render
|
|
833
1146
|
const root = document.getElementById('root');
|
|
@@ -5,7 +5,24 @@ export interface AgentSummary {
|
|
|
5
5
|
agentId?: string;
|
|
6
6
|
specId?: string;
|
|
7
7
|
location: AgentSummaryLocation;
|
|
8
|
+
/**
|
|
9
|
+
* Base URL of the agent-runtimes API server. Hosts both the agent status
|
|
10
|
+
* endpoint (`/api/v1/runtime/status`) and the code sandbox status endpoint
|
|
11
|
+
* (`/api/v1/agents/sandbox/status`).
|
|
12
|
+
*/
|
|
8
13
|
baseUrl: string;
|
|
14
|
+
/**
|
|
15
|
+
* Base URL of the code sandbox (Jupyter for local runs). Shown for context;
|
|
16
|
+
* the sandbox status itself is reported by the agent-runtimes server.
|
|
17
|
+
*/
|
|
18
|
+
sandboxBaseUrl?: string;
|
|
19
|
+
runtimeEnvironment?: {
|
|
20
|
+
environmentName?: string;
|
|
21
|
+
environmentTitle?: string;
|
|
22
|
+
cpu?: string;
|
|
23
|
+
memory?: string;
|
|
24
|
+
gpu?: string;
|
|
25
|
+
};
|
|
9
26
|
status?: string;
|
|
10
27
|
isReady?: boolean;
|
|
11
28
|
error?: string;
|
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Theme-aware wrappers for example components.
|
|
8
|
+
*
|
|
9
|
+
* These are drop-in replacements for `DatalayerThemeProvider` and
|
|
10
|
+
* `JupyterReactTheme` that automatically read theme / color-mode
|
|
11
|
+
* from the shared `useExampleThemeStore`.
|
|
12
|
+
*
|
|
13
|
+
* Usage: replace
|
|
14
|
+
* import { DatalayerThemeProvider } from '@datalayer/primer-addons';
|
|
15
|
+
* with
|
|
16
|
+
* import { ThemedProvider } from './stores/themedProvider';
|
|
17
|
+
*
|
|
18
|
+
* and swap `<DatalayerThemeProvider>` → `<ThemedProvider>`.
|
|
19
|
+
*/
|
|
20
|
+
import { useEffect } from 'react';
|
|
21
|
+
import { DatalayerThemeProvider, themeConfigs, useThemeStore as usePrimerThemeStore, } from '@datalayer/primer-addons';
|
|
3
22
|
import { JupyterReactTheme } from '@datalayer/jupyter-react';
|
|
4
23
|
import { useExampleThemeStore } from './themeStore';
|
|
5
24
|
/**
|
|
@@ -11,6 +30,13 @@ import { useExampleThemeStore } from './themeStore';
|
|
|
11
30
|
export const ThemedProvider = ({ children, ...rest }) => {
|
|
12
31
|
const { colorMode, theme: themeVariant } = useExampleThemeStore();
|
|
13
32
|
const cfg = themeConfigs[themeVariant];
|
|
33
|
+
// <Chat> and other components read the shared primer-addons singleton
|
|
34
|
+
// `useThemeStore` (key 'datalayer-theme', which defaults to matrix/dark),
|
|
35
|
+
// not the examples' `useExampleThemeStore`. Mirror the selected theme into
|
|
36
|
+
// the singleton so the chat main view follows the picker.
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
usePrimerThemeStore.setState({ theme: themeVariant, colorMode });
|
|
39
|
+
}, [themeVariant, colorMode]);
|
|
14
40
|
return (_jsx(DatalayerThemeProvider, { colorMode: rest.colorMode ?? colorMode, theme: rest.theme ?? cfg.primerTheme, themeStyles: rest.themeStyles ?? cfg.themeStyles, ...rest, children: children }));
|
|
15
41
|
};
|
|
16
42
|
/**
|
|
@@ -50,5 +76,9 @@ export const ThemedJupyterProvider = ({ children, useJupyterReactTheme = true })
|
|
|
50
76
|
// Extract the canvas background from the theme's CSS-var overrides.
|
|
51
77
|
const modeStyles = resolvedMode === 'dark' ? cfg.themeStyles.dark : cfg.themeStyles.light;
|
|
52
78
|
const backgroundColor = modeStyles['--bgColor-default'];
|
|
53
|
-
return (_jsx(ThemedProvider, { children: useJupyterReactTheme ? (
|
|
79
|
+
return (_jsx(ThemedProvider, { children: useJupyterReactTheme ? (
|
|
80
|
+
// `ThemedProvider` (DatalayerThemeProvider) already applies Primer
|
|
81
|
+
// BaseStyles with the branded theme font. Disable the inner BaseStyles
|
|
82
|
+
// so Jupyter examples inherit that font instead of Primer's default.
|
|
83
|
+
_jsx(JupyterReactTheme, { colormode: colorMode, backgroundColor: backgroundColor, useBaseStyles: false, children: children })) : (children) }));
|
|
54
84
|
};
|