@datalayer/agent-runtimes 1.0.0 → 1.0.1

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 (32) hide show
  1. package/lib/Agent.js +1 -2
  2. package/lib/AgentLexical.js +1 -2
  3. package/lib/AgentNotebook.js +1 -2
  4. package/lib/components/chat/components/ChatFloating.d.ts +4 -2
  5. package/lib/components/chat/components/ChatFloating.js +1 -1
  6. package/lib/examples/A2UiRestaurantExample.js +2 -2
  7. package/lib/examples/AgUiAgenticExample.js +3 -3
  8. package/lib/examples/AgUiBackendToolRenderingExample.js +4 -3
  9. package/lib/examples/AgUiHaikuGenUIExample.js +4 -3
  10. package/lib/examples/AgUiHumanInTheLoopExample.js +4 -3
  11. package/lib/examples/AgUiSharedStateExample.js +4 -3
  12. package/lib/examples/AgUiToolsBasedGenUIExample.js +4 -3
  13. package/lib/examples/AgentRuntimeChatExample.js +3 -3
  14. package/lib/examples/AgentRuntimeCustomExample.js +2 -2
  15. package/lib/examples/AgentRuntimeFormExample.js +2 -2
  16. package/lib/examples/AgentRuntimeLexical2Example.js +3 -2
  17. package/lib/examples/AgentRuntimeLexicalExample.js +4 -3
  18. package/lib/examples/AgentRuntimeLexicalSidebarExample.js +3 -2
  19. package/lib/examples/AgentRuntimeNotebookExample.js +4 -3
  20. package/lib/examples/AgentRuntimeNotebookSidebarExample.js +3 -2
  21. package/lib/examples/AgentRuntimeStandaloneExample.js +3 -3
  22. package/lib/examples/CopilotKitLexicalExample.js +3 -2
  23. package/lib/examples/CopilotKitNotebookExample.js +3 -2
  24. package/lib/examples/DatalayerNotebookExample.js +3 -2
  25. package/lib/examples/JupyterCellExample.js +3 -2
  26. package/lib/examples/JupyterNotebookExample.js +3 -2
  27. package/lib/examples/main.js +68 -18
  28. package/lib/examples/stores/themeStore.d.ts +33 -0
  29. package/lib/examples/stores/themeStore.js +38 -0
  30. package/lib/examples/stores/themedProvider.d.ts +45 -0
  31. package/lib/examples/stores/themedProvider.js +54 -0
  32. package/package.json +4 -3
package/lib/Agent.js CHANGED
@@ -25,8 +25,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
25
25
  import { useEffect, useState } from 'react';
26
26
  import { Text, Spinner } from '@primer/react';
27
27
  import { AlertIcon } from '@primer/octicons-react';
28
- import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
29
- import { DatalayerThemeProvider } from '@datalayer/core';
28
+ import { Box, DatalayerThemeProvider, setupPrimerPortals, } from '@datalayer/primer-addons';
30
29
  import { Chat } from './components/chat';
31
30
  import { DEFAULT_MODEL } from './specs';
32
31
  import '../style/primer-primitives.css';
@@ -48,8 +48,7 @@ import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin';
48
48
  import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
49
49
  import { Text, Spinner } from '@primer/react';
50
50
  import { AlertIcon } from '@primer/octicons-react';
51
- import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
52
- import { DatalayerThemeProvider } from '@datalayer/core';
51
+ import { Box, DatalayerThemeProvider, setupPrimerPortals, } from '@datalayer/primer-addons';
53
52
  import { JupyterReactTheme, loadJupyterConfig, createServerSettings, getJupyterServerUrl, getJupyterServerToken, setJupyterServerUrl, setJupyterServerToken, useJupyter, } from '@datalayer/jupyter-react';
54
53
  import { ComponentPickerMenuPlugin, JupyterCellPlugin, JupyterInputOutputPlugin, DraggableBlockPlugin, ImagesPlugin, HorizontalRulePlugin, EquationsPlugin, YouTubePlugin, ExcalidrawPlugin, CollapsiblePlugin, AutoLinkPlugin, AutoEmbedPlugin, LexicalConfigProvider, LexicalStatePlugin, FloatingTextFormatToolbarPlugin, CodeActionMenuPlugin, ListMaxIndentLevelPlugin, TableCellResizerPlugin, TablePlugin, } from '@datalayer/jupyter-lexical';
55
54
  import { ServiceManager } from '@jupyterlab/services';
@@ -21,8 +21,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
21
21
  import { useEffect, useState } from 'react';
22
22
  import { Text, Spinner } from '@primer/react';
23
23
  import { AlertIcon } from '@primer/octicons-react';
24
- import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
25
- import { DatalayerThemeProvider } from '@datalayer/core';
24
+ import { Box, DatalayerThemeProvider, setupPrimerPortals, } from '@datalayer/primer-addons';
26
25
  import { Notebook, JupyterReactTheme, loadJupyterConfig, createServerSettings, getJupyterServerUrl, getJupyterServerToken, setJupyterServerUrl, setJupyterServerToken, } from '@datalayer/jupyter-react';
27
26
  import { ServiceManager } from '@jupyterlab/services';
28
27
  import { Chat } from './components/chat';
@@ -65,7 +65,9 @@ export interface ChatFloatingProps {
65
65
  showPoweredBy?: boolean;
66
66
  /** Powered by tag props */
67
67
  poweredByProps?: Partial<PoweredByTagProps>;
68
- /** Enable click outside to close */
68
+ /** Enable click outside to close
69
+ * @default false
70
+ */
69
71
  clickOutsideToClose?: boolean;
70
72
  /** Enable escape key to close */
71
73
  escapeToClose?: boolean;
@@ -89,7 +91,7 @@ export interface ChatFloatingProps {
89
91
  buttonIcon?: React.ReactNode;
90
92
  /** Button tooltip text */
91
93
  buttonTooltip?: string;
92
- /** Brand color */
94
+ /** Brand color override. Defaults to the theme's `accent.emphasis` token. */
93
95
  brandColor?: string;
94
96
  /** Offset from edge (in pixels) */
95
97
  offset?: number;
@@ -43,7 +43,7 @@ function useIsMobile(breakpoint = 640) {
43
43
  * ChatFloating component
44
44
  * A floating chat window built on ChatBase
45
45
  */
46
- export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode = true, title = 'Chat', description = 'Start a conversation with the AI agent.', position = 'bottom-right', defaultOpen = false, width = 400, height = 550, showHeader = true, showButton = true, showNewChatButton = true, showClearButton = true, showSettingsButton = false, enableKeyboardShortcuts = true, toggleShortcut = '/', showPoweredBy = true, poweredByProps, clickOutsideToClose = true, escapeToClose = true, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip = 'Chat with AI', brandColor = '#7c3aed', offset = 20, animationDuration = 200, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick = true, hideMessagesAfterToolUI = false, defaultViewMode = 'floating', onViewModeChange, showPanelBackdrop = false, availableModels, showModelSelector = false, showToolsMenu = false, showSkillsMenu = false, showTokenUsage = true, runtimeId, historyEndpoint, historyAuthToken, pendingPrompt, showInformation = false, onInformationClick, panelProps, }) {
46
+ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode = true, title = 'Chat', description = 'Start a conversation with the AI agent.', position = 'bottom-right', defaultOpen = false, width = 400, height = 550, showHeader = true, showButton = true, showNewChatButton = true, showClearButton = true, showSettingsButton = false, enableKeyboardShortcuts = true, toggleShortcut = '/', showPoweredBy = true, poweredByProps, clickOutsideToClose = false, escapeToClose = true, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip = 'Chat with AI', brandColor, offset = 20, animationDuration = 200, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick = true, hideMessagesAfterToolUI = false, defaultViewMode = 'floating', onViewModeChange, showPanelBackdrop = false, availableModels, showModelSelector = false, showToolsMenu = false, showSkillsMenu = false, showTokenUsage = true, runtimeId, historyEndpoint, historyAuthToken, pendingPrompt, showInformation = false, onInformationClick, panelProps, }) {
47
47
  // Store-based state
48
48
  const storeIsOpen = useChatOpen();
49
49
  const storeMessages = useChatMessages();
@@ -20,7 +20,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
20
20
  */
21
21
  import { useState, useCallback, useEffect, useRef } from 'react';
22
22
  import { Box } from '@datalayer/primer-addons';
23
- import { DatalayerThemeProvider } from '@datalayer/core';
23
+ import { ThemedProvider } from './stores/themedProvider';
24
24
  import { Text, Spinner, TextInput, Button } from '@primer/react';
25
25
  import { A2UIProvider, A2UIRenderer, useA2UI } from '../renderers/a2ui';
26
26
  // A2UI endpoint for pydantic-ai restaurant agent
@@ -278,7 +278,7 @@ const A2UiRestaurantExample = () => {
278
278
  console.log('A2UI Action:', action);
279
279
  // Actions are handled in the content component
280
280
  }, []);
281
- return (_jsx(DatalayerThemeProvider, { children: _jsx(A2UIProvider, { onAction: handleAction, children: _jsxs(Box, { sx: {
281
+ return (_jsx(ThemedProvider, { children: _jsx(A2UIProvider, { onAction: handleAction, children: _jsxs(Box, { sx: {
282
282
  display: 'flex',
283
283
  flexDirection: 'column',
284
284
  minHeight: '100vh',
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Text } from '@primer/react';
3
3
  import { Box } from '@datalayer/primer-addons';
4
- import { DatalayerThemeProvider } from '@datalayer/core';
4
+ import { ThemedProvider } from './stores/themedProvider';
5
5
  import { ChatFloating } from '../components/chat';
6
6
  // AG-UI endpoint for agentic chat example
7
7
  const AGENTIC_CHAT_ENDPOINT = 'http://localhost:8765/api/v1/examples/agentic_chat/';
@@ -17,7 +17,7 @@ const AGENTIC_CHAT_ENDPOINT = 'http://localhost:8765/api/v1/examples/agentic_cha
17
17
  * - Floating popup interface
18
18
  */
19
19
  const AgUiAgenticExample = () => {
20
- return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
20
+ return (_jsx(ThemedProvider, { children: _jsxs(Box, { sx: {
21
21
  minHeight: '100vh',
22
22
  backgroundColor: 'canvas.default',
23
23
  padding: 4,
@@ -49,7 +49,7 @@ const AgUiAgenticExample = () => {
49
49
  borderRadius: 2,
50
50
  border: '1px solid',
51
51
  borderColor: 'border.default',
52
- }, children: [_jsx(Text, { as: "h2", sx: { fontSize: 2, fontWeight: 'semibold', marginBottom: 2 }, children: "About This Example" }), _jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted' }, children: "This example demonstrates the AG-UI (Agent User Interface) protocol for streaming AI interactions. The agent uses SSE (Server-Sent Events) to stream responses and tool calls in real-time." }), _jsxs(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', marginTop: 2 }, children: [_jsx("strong", { children: "Protocol Events:" }), " TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT, TEXT_MESSAGE_END, TOOL_CALL_START, TOOL_CALL_END"] })] })] }), _jsx(ChatFloating, { endpoint: AGENTIC_CHAT_ENDPOINT, title: "Agentic Chat", description: "Chat with an AI agent that can use tools like getting the current time.", position: "bottom-right", brandColor: "#7c3aed", defaultOpen: true, suggestions: [
52
+ }, children: [_jsx(Text, { as: "h2", sx: { fontSize: 2, fontWeight: 'semibold', marginBottom: 2 }, children: "About This Example" }), _jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted' }, children: "This example demonstrates the AG-UI (Agent User Interface) protocol for streaming AI interactions. The agent uses SSE (Server-Sent Events) to stream responses and tool calls in real-time." }), _jsxs(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', marginTop: 2 }, children: [_jsx("strong", { children: "Protocol Events:" }), " TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT, TEXT_MESSAGE_END, TOOL_CALL_START, TOOL_CALL_END"] })] })] }), _jsx(ChatFloating, { endpoint: AGENTIC_CHAT_ENDPOINT, title: "Agentic Chat", description: "Chat with an AI agent that can use tools like getting the current time.", position: "bottom-right", defaultOpen: true, suggestions: [
53
53
  {
54
54
  title: 'What time is it?',
55
55
  message: 'What is the current time?',
@@ -18,7 +18,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
18
  import { useCallback } from 'react';
19
19
  import { Text } from '@primer/react';
20
20
  import { Box } from '@datalayer/primer-addons';
21
- import { DatalayerThemeProvider } from '@datalayer/core';
21
+ import { ThemedProvider, useThemeBrandColor } from './stores/themedProvider';
22
22
  import { ChatFloating } from '../components/chat';
23
23
  import { InlineWeatherCard } from './ag-ui/weather';
24
24
  // AG-UI endpoint for backend tool rendering example
@@ -53,12 +53,13 @@ const renderWeatherToolResult = (context) => {
53
53
  * - Loading states while fetching data
54
54
  */
55
55
  const AgUiBackendToolRenderingExample = () => {
56
+ const brandColor = useThemeBrandColor();
56
57
  // Optional: still track weather for sidebar display if needed
57
58
  const handleStateUpdate = useCallback((_state) => {
58
59
  // State updates are still available if needed for other purposes
59
60
  // Uncomment to debug: console.log('[WeatherExample] State update:', _state);
60
61
  }, []);
61
- return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
62
+ return (_jsx(ThemedProvider, { children: _jsxs(Box, { sx: {
62
63
  minHeight: '100vh',
63
64
  backgroundColor: 'canvas.default',
64
65
  padding: 4,
@@ -89,7 +90,7 @@ const AgUiBackendToolRenderingExample = () => {
89
90
  marginTop: 1,
90
91
  fontSize: 1,
91
92
  color: 'fg.muted',
92
- }, children: [_jsx("li", { children: "\"What's the weather in New York?\"" }), _jsx("li", { children: "\"Weather in London and Paris\"" }), _jsx("li", { children: "\"Is it sunny in Sydney?\"" }), _jsx("li", { children: "\"How's the weather in Tokyo today?\"" })] })] })] })] }), _jsx(ChatFloating, { endpoint: BACKEND_TOOL_RENDERING_ENDPOINT, title: "Weather Assistant", description: "Ask me about the weather anywhere in the world!", position: "bottom-right", brandColor: "#667eea", onStateUpdate: handleStateUpdate, renderToolResult: renderWeatherToolResult, suggestions: [
93
+ }, children: [_jsx("li", { children: "\"What's the weather in New York?\"" }), _jsx("li", { children: "\"Weather in London and Paris\"" }), _jsx("li", { children: "\"Is it sunny in Sydney?\"" }), _jsx("li", { children: "\"How's the weather in Tokyo today?\"" })] })] })] })] }), _jsx(ChatFloating, { endpoint: BACKEND_TOOL_RENDERING_ENDPOINT, title: "Weather Assistant", description: "Ask me about the weather anywhere in the world!", position: "bottom-right", brandColor: brandColor, onStateUpdate: handleStateUpdate, renderToolResult: renderWeatherToolResult, suggestions: [
93
94
  {
94
95
  title: 'Paris weather',
95
96
  message: "What's the weather like in Paris?",
@@ -19,7 +19,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
19
  import { useState, useCallback, useRef, useImperativeHandle, forwardRef, } from 'react';
20
20
  import { Text } from '@primer/react';
21
21
  import { Box } from '@datalayer/primer-addons';
22
- import { DatalayerThemeProvider } from '@datalayer/core';
22
+ import { ThemedProvider, useThemeBrandColor } from './stores/themedProvider';
23
23
  import { ChatFloating } from '../components/chat';
24
24
  import { InlineHaikuCard, HaikuDisplay } from './ag-ui/haiku';
25
25
  // AG-UI endpoint for haiku generative UI example
@@ -60,6 +60,7 @@ HaikuDisplayWithRef.displayName = 'HaikuDisplayWithRef';
60
60
  * - Japanese/English text rendering
61
61
  */
62
62
  const AgUiHaikuGenUIExample = () => {
63
+ const brandColor = useThemeBrandColor();
63
64
  // Ref to the main display for adding haikus
64
65
  const displayRef = useRef(null);
65
66
  // Track processed tool call IDs to avoid duplicates
@@ -95,7 +96,7 @@ const AgUiHaikuGenUIExample = () => {
95
96
  }
96
97
  return (_jsx(InlineHaikuCard, { haiku: haiku, status: context.status, error: context.error }));
97
98
  }, []);
98
- return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
99
+ return (_jsx(ThemedProvider, { children: _jsxs(Box, { sx: {
99
100
  minHeight: '100vh',
100
101
  backgroundColor: 'canvas.default',
101
102
  padding: 4,
@@ -133,7 +134,7 @@ const AgUiHaikuGenUIExample = () => {
133
134
  marginTop: 1,
134
135
  fontSize: 1,
135
136
  color: 'fg.muted',
136
- }, children: [_jsx("li", { children: "\"Write me a haiku about cherry blossoms\"" }), _jsx("li", { children: "\"Create a haiku about coding late at night\"" }), _jsx("li", { children: "\"Generate a haiku about the ocean\"" }), _jsx("li", { children: "\"Write a haiku about autumn leaves\"" })] })] })] })] }), _jsx(ChatFloating, { endpoint: HAIKU_ENDPOINT, title: "Haiku Generator", description: "Ask me to write haiku poetry about any topic!", position: "bottom-right", brandColor: "#667eea", defaultOpen: true, renderToolResult: renderHaikuToolResult, hideMessagesAfterToolUI: true, suggestions: [
137
+ }, children: [_jsx("li", { children: "\"Write me a haiku about cherry blossoms\"" }), _jsx("li", { children: "\"Create a haiku about coding late at night\"" }), _jsx("li", { children: "\"Generate a haiku about the ocean\"" }), _jsx("li", { children: "\"Write a haiku about autumn leaves\"" })] })] })] })] }), _jsx(ChatFloating, { endpoint: HAIKU_ENDPOINT, title: "Haiku Generator", description: "Ask me to write haiku poetry about any topic!", position: "bottom-right", brandColor: brandColor, defaultOpen: true, renderToolResult: renderHaikuToolResult, hideMessagesAfterToolUI: true, suggestions: [
137
138
  {
138
139
  title: 'Cherry blossoms',
139
140
  message: 'Write me a haiku about cherry blossoms in spring.',
@@ -18,7 +18,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
18
18
  import { useState, useEffect } from 'react';
19
19
  import { Text, Checkbox, FormControl, Label, ProgressBar, Button, } from '@primer/react';
20
20
  import { Box } from '@datalayer/primer-addons';
21
- import { DatalayerThemeProvider } from '@datalayer/core';
21
+ import { ThemedProvider, useThemeBrandColor } from './stores/themedProvider';
22
22
  import { ChatFloating } from '../components/chat';
23
23
  import { TasklistIcon, CheckCircleFillIcon, XCircleFillIcon, } from '@primer/octicons-react';
24
24
  // AG-UI endpoint for human in the loop example
@@ -178,7 +178,8 @@ const renderTaskStepsTool = (context) => {
178
178
  * - UI state changes based on user actions
179
179
  */
180
180
  const AgUiHumanInTheLoopExample = () => {
181
- return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
181
+ const brandColor = useThemeBrandColor();
182
+ return (_jsx(ThemedProvider, { children: _jsxs(Box, { sx: {
182
183
  minHeight: '100vh',
183
184
  backgroundColor: 'canvas.default',
184
185
  padding: 4,
@@ -206,7 +207,7 @@ const AgUiHumanInTheLoopExample = () => {
206
207
  borderRadius: 2,
207
208
  border: '1px solid',
208
209
  borderColor: 'accent.muted',
209
- }, children: [_jsx(Text, { as: "h2", sx: { fontSize: 2, fontWeight: 'semibold', marginBottom: 2 }, children: "Key Concept: respond() Callback" }), _jsxs(Text, { as: "p", sx: { fontSize: 1, color: 'fg.default' }, children: ["The ", _jsx("code", { children: "renderToolResult" }), " function receives a", ' ', _jsx("code", { children: "respond" }), " callback when the tool status is \"executing\". Calling ", _jsxs("code", { children: ["respond(", '{ accepted: true, steps: [...] }', ")"] }), ' ', "sends the user's decision back to the agent, completing the human-in-the-loop interaction."] })] })] }), _jsx(ChatFloating, { endpoint: HUMAN_IN_THE_LOOP_ENDPOINT, title: "Task Planner", description: "I can help you plan tasks. I'll generate steps for your review.", position: "bottom-right", brandColor: "#059669", renderToolResult: renderTaskStepsTool, hideMessagesAfterToolUI: true, suggestions: [
210
+ }, children: [_jsx(Text, { as: "h2", sx: { fontSize: 2, fontWeight: 'semibold', marginBottom: 2 }, children: "Key Concept: respond() Callback" }), _jsxs(Text, { as: "p", sx: { fontSize: 1, color: 'fg.default' }, children: ["The ", _jsx("code", { children: "renderToolResult" }), " function receives a", ' ', _jsx("code", { children: "respond" }), " callback when the tool status is \"executing\". Calling ", _jsxs("code", { children: ["respond(", '{ accepted: true, steps: [...] }', ")"] }), ' ', "sends the user's decision back to the agent, completing the human-in-the-loop interaction."] })] })] }), _jsx(ChatFloating, { endpoint: HUMAN_IN_THE_LOOP_ENDPOINT, title: "Task Planner", description: "I can help you plan tasks. I'll generate steps for your review.", position: "bottom-right", brandColor: brandColor, renderToolResult: renderTaskStepsTool, hideMessagesAfterToolUI: true, suggestions: [
210
211
  {
211
212
  title: 'Plan a trip',
212
213
  message: 'Plan a weekend trip to Paris.',
@@ -15,7 +15,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
15
  import { useState, useCallback } from 'react';
16
16
  import { Text, Button, TextInput, Label } from '@primer/react';
17
17
  import { Box } from '@datalayer/primer-addons';
18
- import { DatalayerThemeProvider } from '@datalayer/core';
18
+ import { ThemedProvider, useThemeBrandColor } from './stores/themedProvider';
19
19
  import { ChatFloating } from '../components/chat';
20
20
  import { PlusIcon, XIcon, BeakerIcon, ClockIcon, PersonIcon, } from '@primer/octicons-react';
21
21
  // AG-UI endpoint for shared state example
@@ -104,6 +104,7 @@ const RecipeDisplay = ({ recipe, onUpdate }) => {
104
104
  * - Editable UI that updates shared state
105
105
  */
106
106
  const AgUiSharedStateExample = () => {
107
+ const brandColor = useThemeBrandColor();
107
108
  const [recipe, setRecipe] = useState(DEFAULT_RECIPE);
108
109
  // Handle state updates from AG-UI
109
110
  const handleStateUpdate = useCallback((state) => {
@@ -125,7 +126,7 @@ const AgUiSharedStateExample = () => {
125
126
  const handleClear = useCallback(() => {
126
127
  setRecipe(DEFAULT_RECIPE);
127
128
  }, []);
128
- return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
129
+ return (_jsx(ThemedProvider, { children: _jsxs(Box, { sx: {
129
130
  minHeight: '100vh',
130
131
  backgroundColor: 'canvas.default',
131
132
  padding: 4,
@@ -167,7 +168,7 @@ const AgUiSharedStateExample = () => {
167
168
  marginTop: 1,
168
169
  fontSize: 1,
169
170
  color: 'fg.muted',
170
- }, children: [_jsx("li", { children: "\"Create a recipe for chocolate chip cookies\"" }), _jsx("li", { children: "\"Add butter and sugar to the ingredients\"" }), _jsx("li", { children: "\"Update the prep time to 20 minutes\"" }), _jsx("li", { children: "\"Suggest 3 more ingredients for my recipe\"" })] })] })] })] }), _jsx(ChatFloating, { endpoint: SHARED_STATE_ENDPOINT, title: "Recipe Assistant", description: "Let's build a recipe together! I can add ingredients, instructions, and more.", position: "bottom-right", brandColor: "#be185d", onStateUpdate: handleStateUpdate, suggestions: [
171
+ }, children: [_jsx("li", { children: "\"Create a recipe for chocolate chip cookies\"" }), _jsx("li", { children: "\"Add butter and sugar to the ingredients\"" }), _jsx("li", { children: "\"Update the prep time to 20 minutes\"" }), _jsx("li", { children: "\"Suggest 3 more ingredients for my recipe\"" })] })] })] })] }), _jsx(ChatFloating, { endpoint: SHARED_STATE_ENDPOINT, title: "Recipe Assistant", description: "Let's build a recipe together! I can add ingredients, instructions, and more.", position: "bottom-right", brandColor: brandColor, onStateUpdate: handleStateUpdate, suggestions: [
171
172
  {
172
173
  title: 'Pasta recipe',
173
174
  message: 'Help me create a simple pasta recipe.',
@@ -15,7 +15,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
15
  import { useState, useCallback } from 'react';
16
16
  import { Text, ProgressBar, Button } from '@primer/react';
17
17
  import { Box } from '@datalayer/primer-addons';
18
- import { DatalayerThemeProvider } from '@datalayer/core';
18
+ import { ThemedProvider, useThemeBrandColor } from './stores/themedProvider';
19
19
  import { ChatFloating } from '../components/chat';
20
20
  import { CheckCircleIcon, CircleIcon, DotFillIcon, CheckIcon, XIcon, } from '@primer/octicons-react';
21
21
  // AG-UI endpoint for agentic generative UI example
@@ -169,6 +169,7 @@ const PlanDisplay = ({ plan, isInteractive = true, onStepToggle, onConfirm, onRe
169
169
  * - Interactive step selection with Confirm/Reject buttons
170
170
  */
171
171
  const AgUiToolsBasedGenUIExample = () => {
172
+ const brandColor = useThemeBrandColor();
172
173
  const [plan, setPlan] = useState(null);
173
174
  const [decision, setDecision] = useState(null);
174
175
  // Handle state updates from AG-UI events
@@ -209,7 +210,7 @@ const AgUiToolsBasedGenUIExample = () => {
209
210
  setDecision('rejected');
210
211
  console.log('Plan rejected');
211
212
  }, []);
212
- return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
213
+ return (_jsx(ThemedProvider, { children: _jsxs(Box, { sx: {
213
214
  minHeight: '100vh',
214
215
  backgroundColor: 'canvas.default',
215
216
  padding: 4,
@@ -243,7 +244,7 @@ const AgUiToolsBasedGenUIExample = () => {
243
244
  marginTop: 1,
244
245
  fontSize: 1,
245
246
  color: 'fg.muted',
246
- }, children: [_jsx("li", { children: "STATE_SNAPSHOT - Full state replacement" }), _jsx("li", { children: "STATE_DELTA - Incremental JSON Patch updates (RFC 6902)" }), _jsx("li", { children: "TOOL_CALL_START / TOOL_CALL_END - Tool execution tracking" })] })] })] })] }), _jsx(ChatFloating, { endpoint: AGENTIC_GENERATIVE_UI_ENDPOINT, title: "Plan Generator", description: "I can create detailed plans and update them in real-time.", position: "bottom-right", brandColor: "#0969da", onStateUpdate: handleStateUpdate, suggestions: [
247
+ }, children: [_jsx("li", { children: "STATE_SNAPSHOT - Full state replacement" }), _jsx("li", { children: "STATE_DELTA - Incremental JSON Patch updates (RFC 6902)" }), _jsx("li", { children: "TOOL_CALL_START / TOOL_CALL_END - Tool execution tracking" })] })] })] })] }), _jsx(ChatFloating, { endpoint: AGENTIC_GENERATIVE_UI_ENDPOINT, title: "Plan Generator", description: "I can create detailed plans and update them in real-time.", position: "bottom-right", brandColor: brandColor, onStateUpdate: handleStateUpdate, suggestions: [
247
248
  {
248
249
  title: 'Project plan',
249
250
  message: 'Create a project plan for building a mobile app.',
@@ -19,7 +19,7 @@ import { useEffect, useState } from 'react';
19
19
  import { Text, Spinner } from '@primer/react';
20
20
  import { AlertIcon } from '@primer/octicons-react';
21
21
  import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
22
- import { DatalayerThemeProvider } from '@datalayer/core';
22
+ import { ThemedProvider } from './stores/themedProvider';
23
23
  import { Chat } from '../components/chat';
24
24
  setupPrimerPortals();
25
25
  const BASE_URL = 'http://localhost:8765';
@@ -89,7 +89,7 @@ const AgentRuntimeChatExample = () => {
89
89
  }, []);
90
90
  // Loading state while agent is being created
91
91
  if (isCreating) {
92
- return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
92
+ return (_jsx(ThemedProvider, { children: _jsxs(Box, { sx: {
93
93
  display: 'flex',
94
94
  flexDirection: 'column',
95
95
  alignItems: 'center',
@@ -101,7 +101,7 @@ const AgentRuntimeChatExample = () => {
101
101
  }
102
102
  // Error state
103
103
  if (error || !agentId) {
104
- return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
104
+ return (_jsx(ThemedProvider, { children: _jsxs(Box, { sx: {
105
105
  display: 'flex',
106
106
  flexDirection: 'column',
107
107
  alignItems: 'center',
@@ -7,7 +7,7 @@ import { useCallback, useEffect, useState } from 'react';
7
7
  import { Spinner, Text } from '@primer/react';
8
8
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
9
9
  import { Box } from '@datalayer/primer-addons';
10
- import { DatalayerThemeProvider } from '@datalayer/core';
10
+ import { ThemedProvider } from './stores/themedProvider';
11
11
  import { Chat } from '../components/chat';
12
12
  // Create a query client for React Query
13
13
  const queryClient = new QueryClient({
@@ -121,7 +121,7 @@ Be concise, helpful, and provide working code examples when appropriate.`,
121
121
  */
122
122
  const AgentRuntimeCustomExample = () => {
123
123
  const { agentId, isLoading, error, retry } = useEnsureAgent();
124
- return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
124
+ return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ThemedProvider, { children: _jsxs(Box, { sx: {
125
125
  display: 'flex',
126
126
  flexDirection: 'column',
127
127
  height: '100vh',
@@ -11,7 +11,7 @@ import { AiAgentIcon } from '@datalayer/icons-react';
11
11
  import { Blankslate } from '@primer/react/experimental';
12
12
  import { QueryClient, QueryClientProvider, useQuery, } from '@tanstack/react-query';
13
13
  import { Box } from '@datalayer/primer-addons';
14
- import { DatalayerThemeProvider } from '@datalayer/core';
14
+ import { ThemedProvider } from './stores/themedProvider';
15
15
  import { Chat, useChatStore } from '../components/chat';
16
16
  import { DEFAULT_MODEL } from '../specs';
17
17
  import { useAgentsStore } from './stores/examplesStore';
@@ -528,7 +528,7 @@ githubClientId, kaggleToken, }) => {
528
528
  }
529
529
  setIsConfigured(false);
530
530
  };
531
- return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(DatalayerThemeProvider, { children: _jsxs(PageLayout, { containerWidth: "full", children: [_jsx(Header, { activeSession: activeSession, agentName: isNewMode ? undefined : currentAgent?.name, agentDescription: isNewMode ? undefined : currentAgent?.description, agentStatus: currentAgent?.status, showContextTree: showContextTree, isNewAgent: isNewMode, isConfigured: isConfigured, onSessionChange: setActiveSession, onToggleContextTree: () => setShowContextTree(!showContextTree), onToggleStatus: currentAgent
531
+ return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ThemedProvider, { children: _jsxs(PageLayout, { containerWidth: "full", children: [_jsx(Header, { activeSession: activeSession, agentName: isNewMode ? undefined : currentAgent?.name, agentDescription: isNewMode ? undefined : currentAgent?.description, agentStatus: currentAgent?.status, showContextTree: showContextTree, isNewAgent: isNewMode, isConfigured: isConfigured, onSessionChange: setActiveSession, onToggleContextTree: () => setShowContextTree(!showContextTree), onToggleStatus: currentAgent
532
532
  ? () => toggleAgentStatus(currentAgent.id)
533
533
  : undefined }), leftPaneVisible ? (_jsxs(_Fragment, { children: [_jsx(Box, { sx: {
534
534
  position: 'fixed',
@@ -47,7 +47,8 @@ import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin';
47
47
  import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
48
48
  import { Box } from '@datalayer/primer-addons';
49
49
  import { Text } from '@primer/react';
50
- import { JupyterReactTheme, useJupyter } from '@datalayer/jupyter-react';
50
+ import { useJupyter } from '@datalayer/jupyter-react';
51
+ import { ThemedJupyterProvider } from './stores/themedProvider';
51
52
  import { ComponentPickerMenuPlugin, JupyterCellPlugin, JupyterInputOutputPlugin, DraggableBlockPlugin, ImagesPlugin, HorizontalRulePlugin, EquationsPlugin, YouTubePlugin, ExcalidrawPlugin, CollapsiblePlugin, AutoLinkPlugin, AutoEmbedPlugin, FloatingTextFormatToolbarPlugin, CodeActionMenuPlugin, ListMaxIndentLevelPlugin, TableCellResizerPlugin, TablePlugin, } from '@datalayer/jupyter-lexical';
52
53
  // Import Chat components
53
54
  import { ChatFloating, useChatStore, useFrontendTool, DatalayerInferenceProvider, } from '../components/chat';
@@ -228,7 +229,7 @@ export function ChatLexicalExampleInner({ serviceManager, }) {
228
229
  * Main example component with Simple wrapper
229
230
  */
230
231
  export function AgentRuntimePopupLexicalExample() {
231
- return (_jsx(JupyterReactTheme, { children: _jsx(JupyterWrapper, {}) }));
232
+ return (_jsx(ThemedJupyterProvider, { children: _jsx(JupyterWrapper, {}) }));
232
233
  }
233
234
  function JupyterWrapper() {
234
235
  const { serviceManager } = useJupyter();
@@ -44,7 +44,8 @@ import { ListPlugin } from '@lexical/react/LexicalListPlugin';
44
44
  import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin';
45
45
  import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
46
46
  import { Box } from '@datalayer/primer-addons';
47
- import { JupyterReactTheme, useJupyter } from '@datalayer/jupyter-react';
47
+ import { useJupyter } from '@datalayer/jupyter-react';
48
+ import { ThemedJupyterProvider } from './stores/themedProvider';
48
49
  import { ComponentPickerMenuPlugin, JupyterCellPlugin, JupyterInputOutputPlugin, DraggableBlockPlugin, ImagesPlugin, HorizontalRulePlugin, EquationsPlugin, YouTubePlugin, ExcalidrawPlugin, CollapsiblePlugin, AutoLinkPlugin, AutoEmbedPlugin, LexicalConfigProvider, LexicalStatePlugin, FloatingTextFormatToolbarPlugin, CodeActionMenuPlugin, ListMaxIndentLevelPlugin, TableCellResizerPlugin, TablePlugin, } from '@datalayer/jupyter-lexical';
49
50
  // Agent-runtimes imports
50
51
  import { ChatFloating } from '../components/chat';
@@ -215,7 +216,7 @@ const LexicalUI = React.memo(function LexicalUI({ content = INITIAL_CONTENT, ser
215
216
  padding: 3,
216
217
  backgroundColor: 'canvas.default',
217
218
  minHeight: '600px',
218
- }, children: _jsxs(LexicalConfigProvider, { lexicalId: LEXICAL_ID, serviceManager: serviceManager, children: [_jsx(LexicalToolsPlugin, { onToolsReady: onToolsReady }), _jsx(LexicalComposer, { initialConfig: editorConfig, children: _jsxs("div", { className: "lexical-editor-inner", ref: onRef, children: [_jsx(LexicalStatePlugin, {}), _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "lexical-editor-content", "aria-label": "Lexical Editor" }), ErrorBoundary: LexicalErrorBoundary }), _jsx(OnChangePlugin, { onChange: handleChange }), _jsx(HistoryPlugin, {}), _jsx(AutoFocusPlugin, {}), _jsx(ListPlugin, {}), _jsx(CheckListPlugin, {}), _jsx(LinkPlugin, {}), _jsx(AutoLinkPlugin, {}), _jsx(ListMaxIndentLevelPlugin, { maxDepth: 7 }), _jsx(MarkdownShortcutPlugin, { transformers: TRANSFORMERS }), _jsx(LoadContentPlugin, { content: content }), _jsx(CodeHighlightPlugin, {}), _jsx(ImagesPlugin, { captionsEnabled: false }), _jsx(HorizontalRulePlugin, {}), _jsx(EquationsPlugin, {}), _jsx(YouTubePlugin, {}), _jsx(ExcalidrawPlugin, {}), _jsx(CollapsiblePlugin, {}), _jsx(AutoEmbedPlugin, {}), _jsx(TablePlugin, {}), _jsx(TableCellResizerPlugin, {}), _jsx(JupyterCellPlugin, {}), _jsx(JupyterReactTheme, { children: _jsx(SimpleKernelPluginsInner, {}) }), floatingAnchorElem && (_jsxs(_Fragment, { children: [_jsx(DraggableBlockPlugin, { anchorElem: floatingAnchorElem }), _jsx(FloatingTextFormatToolbarPlugin, { anchorElem: floatingAnchorElem, setIsLinkEditMode: setIsLinkEditMode, extraItems: toolbarItems }), _jsx(CodeActionMenuPlugin, { anchorElem: floatingAnchorElem })] })), _jsx(ChatInlinePlugin, { protocol: {
219
+ }, children: _jsxs(LexicalConfigProvider, { lexicalId: LEXICAL_ID, serviceManager: serviceManager, children: [_jsx(LexicalToolsPlugin, { onToolsReady: onToolsReady }), _jsx(LexicalComposer, { initialConfig: editorConfig, children: _jsxs("div", { className: "lexical-editor-inner", ref: onRef, children: [_jsx(LexicalStatePlugin, {}), _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "lexical-editor-content", "aria-label": "Lexical Editor" }), ErrorBoundary: LexicalErrorBoundary }), _jsx(OnChangePlugin, { onChange: handleChange }), _jsx(HistoryPlugin, {}), _jsx(AutoFocusPlugin, {}), _jsx(ListPlugin, {}), _jsx(CheckListPlugin, {}), _jsx(LinkPlugin, {}), _jsx(AutoLinkPlugin, {}), _jsx(ListMaxIndentLevelPlugin, { maxDepth: 7 }), _jsx(MarkdownShortcutPlugin, { transformers: TRANSFORMERS }), _jsx(LoadContentPlugin, { content: content }), _jsx(CodeHighlightPlugin, {}), _jsx(ImagesPlugin, { captionsEnabled: false }), _jsx(HorizontalRulePlugin, {}), _jsx(EquationsPlugin, {}), _jsx(YouTubePlugin, {}), _jsx(ExcalidrawPlugin, {}), _jsx(CollapsiblePlugin, {}), _jsx(AutoEmbedPlugin, {}), _jsx(TablePlugin, {}), _jsx(TableCellResizerPlugin, {}), _jsx(JupyterCellPlugin, {}), _jsx(ThemedJupyterProvider, { children: _jsx(SimpleKernelPluginsInner, {}) }), floatingAnchorElem && (_jsxs(_Fragment, { children: [_jsx(DraggableBlockPlugin, { anchorElem: floatingAnchorElem }), _jsx(FloatingTextFormatToolbarPlugin, { anchorElem: floatingAnchorElem, setIsLinkEditMode: setIsLinkEditMode, extraItems: toolbarItems }), _jsx(CodeActionMenuPlugin, { anchorElem: floatingAnchorElem })] })), _jsx(ChatInlinePlugin, { protocol: {
219
220
  type: 'ag-ui',
220
221
  endpoint: AG_UI_ENDPOINT,
221
222
  }, isOpen: isAiOpen, onClose: closeAi, pendingPrompt: pendingPrompt, onPendingPromptConsumed: clearPendingPrompt })] }) })] }) })] }));
@@ -246,7 +247,7 @@ function LexicalWithChat({ content, serviceManager, }) {
246
247
  color: 'danger.fg',
247
248
  borderRadius: 2,
248
249
  maxWidth: 300,
249
- }, children: [_jsx("strong", { children: "Error:" }), " ", error] })), isReady && (_jsx(ChatFloating, { endpoint: AG_UI_ENDPOINT, title: "Lexical AI Agent Runtime", description: "Hi! I can help you edit documents. Try: 'Insert a heading', 'Add a code block', or 'Create a list'", defaultOpen: true, defaultViewMode: "panel", position: "bottom-right", brandColor: "#7c3aed", frontendTools: tools, useStore: false, showModelSelector: true, showToolsMenu: true, showSkillsMenu: true, suggestions: [
250
+ }, children: [_jsx("strong", { children: "Error:" }), " ", error] })), isReady && (_jsx(ChatFloating, { endpoint: AG_UI_ENDPOINT, title: "Lexical AI Agent Runtime", description: "Hi! I can help you edit documents. Try: 'Insert a heading', 'Add a code block', or 'Create a list'", defaultOpen: true, defaultViewMode: "panel", position: "bottom-right", frontendTools: tools, useStore: false, showModelSelector: true, showToolsMenu: true, showSkillsMenu: true, suggestions: [
250
251
  {
251
252
  title: 'Insert heading',
252
253
  message: 'Insert a heading that says "Welcome"',
@@ -45,7 +45,8 @@ import { ListPlugin } from '@lexical/react/LexicalListPlugin';
45
45
  import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin';
46
46
  import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
47
47
  import { Box } from '@datalayer/primer-addons';
48
- import { JupyterReactTheme, useJupyter } from '@datalayer/jupyter-react';
48
+ import { useJupyter } from '@datalayer/jupyter-react';
49
+ import { ThemedJupyterProvider } from './stores/themedProvider';
49
50
  import { ComponentPickerMenuPlugin, JupyterCellPlugin, JupyterInputOutputPlugin, DraggableBlockPlugin, ImagesPlugin, HorizontalRulePlugin, EquationsPlugin, YouTubePlugin, ExcalidrawPlugin, CollapsiblePlugin, AutoLinkPlugin, AutoEmbedPlugin, FloatingTextFormatToolbarPlugin, CodeActionMenuPlugin, ListMaxIndentLevelPlugin, LexicalConfigProvider, LexicalStatePlugin, TableCellResizerPlugin, TablePlugin, } from '@datalayer/jupyter-lexical';
50
51
  // Import Chat components
51
52
  import { ChatSidebar, } from '../components/chat';
@@ -165,7 +166,7 @@ export function ChatLexicalExampleInner({ serviceManager, }) {
165
166
  * Main example component with Simple wrapper
166
167
  */
167
168
  export function AgentRuntimeLexicalSidebarExample() {
168
- return (_jsx(JupyterReactTheme, { children: _jsx(SimpleWrapper, {}) }));
169
+ return (_jsx(ThemedJupyterProvider, { children: _jsx(SimpleWrapper, {}) }));
169
170
  }
170
171
  function SimpleWrapper() {
171
172
  const { serviceManager } = useJupyter();
@@ -17,7 +17,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
17
17
  */
18
18
  import React, { useEffect, useState } from 'react';
19
19
  import { Box } from '@datalayer/primer-addons';
20
- import { JupyterReactTheme, Notebook } from '@datalayer/jupyter-react';
20
+ import { Notebook } from '@datalayer/jupyter-react';
21
+ import { ThemedJupyterProvider } from './stores/themedProvider';
21
22
  // Agent-runtimes imports
22
23
  import { ChatFloating } from '../components/chat';
23
24
  import { useNotebookTools } from '../tools/adapters/agent-runtimes/notebookHooks';
@@ -107,7 +108,7 @@ const NotebookUI = React.memo(function NotebookUI({ serviceManager, }) {
107
108
  borderRadius: 2,
108
109
  padding: 3,
109
110
  backgroundColor: 'canvas.default',
110
- }, children: serviceManager ? (_jsx(JupyterReactTheme, { children: _jsx(Notebook, { nbformat: NOTEBOOK_CONTENT, id: NOTEBOOK_ID, serviceManager: serviceManager, height: "600px", cellSidebarMargin: 120, startDefaultKernel: true }) })) : (_jsx(Box, { sx: { padding: 3 }, children: _jsx("p", { children: "Loading service manager..." }) })) })] }));
111
+ }, children: serviceManager ? (_jsx(ThemedJupyterProvider, { children: _jsx(Notebook, { nbformat: NOTEBOOK_CONTENT, id: NOTEBOOK_ID, serviceManager: serviceManager, height: "600px", cellSidebarMargin: 120, startDefaultKernel: true }) })) : (_jsx(Box, { sx: { padding: 3 }, children: _jsx("p", { children: "Loading service manager..." }) })) })] }));
111
112
  });
112
113
  function NotebookWithChat({ serviceManager, }) {
113
114
  // Ensure the agent exists before rendering chat
@@ -128,7 +129,7 @@ function NotebookWithChat({ serviceManager, }) {
128
129
  color: 'danger.fg',
129
130
  borderRadius: 2,
130
131
  maxWidth: 300,
131
- }, children: [_jsx("strong", { children: "Error:" }), " ", error] })), isReady && (_jsx(ChatFloating, { endpoint: AG_UI_ENDPOINT, title: "Notebook AI Agent Runtime", description: "Hi! I can help you edit notebook cells. Try: 'Add a new code cell', 'Run cell 1', or 'Delete the last cell'", defaultOpen: true, defaultViewMode: "panel", position: "bottom-right", brandColor: "#7c3aed", frontendTools: frontendTools, useStore: false, showModelSelector: true, showToolsMenu: true, showSkillsMenu: true, suggestions: [
132
+ }, children: [_jsx("strong", { children: "Error:" }), " ", error] })), isReady && (_jsx(ChatFloating, { endpoint: AG_UI_ENDPOINT, title: "Notebook AI Agent Runtime", description: "Hi! I can help you edit notebook cells. Try: 'Add a new code cell', 'Run cell 1', or 'Delete the last cell'", defaultOpen: true, defaultViewMode: "panel", position: "bottom-right", frontendTools: frontendTools, useStore: false, showModelSelector: true, showToolsMenu: true, showSkillsMenu: true, suggestions: [
132
133
  {
133
134
  title: 'Add a cell',
134
135
  message: 'Insert a random cell to the notebook',
@@ -20,7 +20,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
20
20
  */
21
21
  import { useMemo } from 'react';
22
22
  import { Box } from '@datalayer/primer-addons';
23
- import { Notebook, JupyterReactTheme, useJupyter, } from '@datalayer/jupyter-react';
23
+ import { Notebook, useJupyter } from '@datalayer/jupyter-react';
24
+ import { ThemedJupyterProvider } from './stores/themedProvider';
24
25
  // Import Chat components
25
26
  import { ChatSidebar, } from '../components/chat';
26
27
  // Import agent-runtimes notebook tools
@@ -112,7 +113,7 @@ export function AgentRuntimeNotebookExampleInner({ serviceManager, }) {
112
113
  * Main example component with Simple wrapper
113
114
  */
114
115
  export function AgentRuntimeNotebookSidebarExample() {
115
- return (_jsx(JupyterReactTheme, { children: _jsx(SimpleWrapper, {}) }));
116
+ return (_jsx(ThemedJupyterProvider, { children: _jsx(SimpleWrapper, {}) }));
116
117
  }
117
118
  function SimpleWrapper() {
118
119
  const { serviceManager } = useJupyter();
@@ -18,7 +18,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
18
  import { useCallback } from 'react';
19
19
  import { Text } from '@primer/react';
20
20
  import { Box } from '@datalayer/primer-addons';
21
- import { DatalayerThemeProvider } from '@datalayer/core';
21
+ import { ThemedProvider } from './stores/themedProvider';
22
22
  import { ChatStandalone } from '../components/chat';
23
23
  /**
24
24
  * Simulated AI responses for demo purposes.
@@ -97,7 +97,7 @@ const AgentRuntimePopupStandaloneExample = () => {
97
97
  throw err;
98
98
  }
99
99
  }, []);
100
- return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
100
+ return (_jsx(ThemedProvider, { children: _jsxs(Box, { sx: {
101
101
  minHeight: '100vh',
102
102
  backgroundColor: 'canvas.default',
103
103
  padding: 4,
@@ -153,6 +153,6 @@ const AgentRuntimePopupStandaloneExample = () => {
153
153
  borderRadius: 2,
154
154
  border: '1px solid',
155
155
  borderColor: 'attention.muted',
156
- }, children: [_jsx(Text, { as: "h2", sx: { fontSize: 2, fontWeight: 'semibold', marginBottom: 2 }, children: "When to Use" }), _jsxs(Text, { as: "p", sx: { fontSize: 1, marginBottom: 2 }, children: ["Use ", _jsx("strong", { children: "ChatStandalone" }), " when:"] }), _jsxs(Box, { as: "ul", sx: { paddingLeft: 3, fontSize: 1 }, children: [_jsx("li", { children: "You have a custom AI backend that does not use AG-UI/ACP" }), _jsx("li", { children: "You want full control over the message handling logic" }), _jsx("li", { children: "You need to integrate with a specific API (OpenAI, etc.)" }), _jsx("li", { children: "You want a quick demo without setting up a backend server" })] }), _jsxs(Text, { as: "p", sx: { fontSize: 1, marginTop: 2 }, children: ["Use ", _jsx("strong", { children: "ChatFloating" }), " instead when:"] }), _jsxs(Box, { as: "ul", sx: { paddingLeft: 3, fontSize: 1 }, children: [_jsx("li", { children: "You have an AG-UI compatible backend" }), _jsx("li", { children: "You need built-in tool rendering support" }), _jsx("li", { children: "You want automatic protocol handling" })] })] })] }), _jsx(ChatStandalone, { title: "Demo Assistant", onSendMessage: handleSendMessage, position: "bottom-right", brandColor: "#7c3aed", enableStreaming: true, emptyStateMessage: "Hi! I'm a demo assistant. Try asking me for the time, a joke, or what I can do!", buttonTooltip: "Chat with Demo Assistant", showPoweredBy: true })] }) }));
156
+ }, children: [_jsx(Text, { as: "h2", sx: { fontSize: 2, fontWeight: 'semibold', marginBottom: 2 }, children: "When to Use" }), _jsxs(Text, { as: "p", sx: { fontSize: 1, marginBottom: 2 }, children: ["Use ", _jsx("strong", { children: "ChatStandalone" }), " when:"] }), _jsxs(Box, { as: "ul", sx: { paddingLeft: 3, fontSize: 1 }, children: [_jsx("li", { children: "You have a custom AI backend that does not use AG-UI/ACP" }), _jsx("li", { children: "You want full control over the message handling logic" }), _jsx("li", { children: "You need to integrate with a specific API (OpenAI, etc.)" }), _jsx("li", { children: "You want a quick demo without setting up a backend server" })] }), _jsxs(Text, { as: "p", sx: { fontSize: 1, marginTop: 2 }, children: ["Use ", _jsx("strong", { children: "ChatFloating" }), " instead when:"] }), _jsxs(Box, { as: "ul", sx: { paddingLeft: 3, fontSize: 1 }, children: [_jsx("li", { children: "You have an AG-UI compatible backend" }), _jsx("li", { children: "You need built-in tool rendering support" }), _jsx("li", { children: "You want automatic protocol handling" })] })] })] }), _jsx(ChatStandalone, { title: "Demo Assistant", onSendMessage: handleSendMessage, position: "bottom-right", enableStreaming: true, emptyStateMessage: "Hi! I'm a demo assistant. Try asking me for the time, a joke, or what I can do!", buttonTooltip: "Chat with Demo Assistant", showPoweredBy: true })] }) }));
157
157
  };
158
158
  export default AgentRuntimePopupStandaloneExample;
@@ -47,7 +47,8 @@ import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
47
47
  import { CopilotKit, useFrontendTool } from '@copilotkit/react-core';
48
48
  import { CopilotSidebar } from '@copilotkit/react-ui';
49
49
  import { Box } from '@datalayer/primer-addons';
50
- import { JupyterReactTheme, useJupyter } from '@datalayer/jupyter-react';
50
+ import { useJupyter } from '@datalayer/jupyter-react';
51
+ import { ThemedJupyterProvider } from './stores/themedProvider';
51
52
  import { ComponentPickerMenuPlugin, JupyterCellPlugin, JupyterInputOutputPlugin, DraggableBlockPlugin, ImagesPlugin, HorizontalRulePlugin, EquationsPlugin, YouTubePlugin, ExcalidrawPlugin, CollapsiblePlugin, AutoLinkPlugin, AutoEmbedPlugin, LexicalConfigProvider, LexicalStatePlugin, FloatingTextFormatToolbarPlugin, CodeActionMenuPlugin, ListMaxIndentLevelPlugin, TableCellResizerPlugin, TablePlugin, } from '@datalayer/jupyter-lexical';
52
53
  import { ActionRegistrar, useLexicalToolActions, } from '../tools/adapters/copilotkit/lexicalHooks';
53
54
  import { editorConfig } from './lexical/editorConfig';
@@ -146,7 +147,7 @@ const LexicalUI = React.memo(function LexicalUI({ content = INITIAL_CONTENT, ser
146
147
  padding: 3,
147
148
  backgroundColor: 'canvas.default',
148
149
  minHeight: '600px',
149
- }, children: _jsx(LexicalConfigProvider, { lexicalId: LEXICAL_ID, serviceManager: serviceManager, children: _jsx(LexicalComposer, { initialConfig: editorConfig, children: _jsxs("div", { className: "lexical-editor-inner", ref: onRef, children: [_jsx(LexicalStatePlugin, {}), _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "lexical-editor-content", "aria-label": "Lexical Editor" }), ErrorBoundary: LexicalErrorBoundary }), _jsx(OnChangePlugin, { onChange: handleChange }), _jsx(HistoryPlugin, {}), _jsx(AutoFocusPlugin, {}), _jsx(ListPlugin, {}), _jsx(CheckListPlugin, {}), _jsx(LinkPlugin, {}), _jsx(AutoLinkPlugin, {}), _jsx(TablePlugin, {}), _jsx(TableCellResizerPlugin, {}), _jsx(ListMaxIndentLevelPlugin, { maxDepth: 7 }), _jsx(MarkdownShortcutPlugin, { transformers: TRANSFORMERS }), _jsx(LoadContentPlugin, { content: content }), _jsx(CodeHighlightPlugin, {}), _jsx(ImagesPlugin, { captionsEnabled: false }), _jsx(HorizontalRulePlugin, {}), _jsx(EquationsPlugin, {}), _jsx(YouTubePlugin, {}), _jsx(ExcalidrawPlugin, {}), _jsx(CollapsiblePlugin, {}), _jsx(AutoEmbedPlugin, {}), _jsx(JupyterCellPlugin, {}), _jsx(JupyterReactTheme, { children: _jsx(SimpleKernelPluginsInner, {}) }), floatingAnchorElem && (_jsxs(_Fragment, { children: [_jsx(DraggableBlockPlugin, { anchorElem: floatingAnchorElem }), _jsx(FloatingTextFormatToolbarPlugin, { anchorElem: floatingAnchorElem, setIsLinkEditMode: setIsLinkEditMode }), _jsx(CodeActionMenuPlugin, { anchorElem: floatingAnchorElem })] }))] }) }) }) })] }) }));
150
+ }, children: _jsx(LexicalConfigProvider, { lexicalId: LEXICAL_ID, serviceManager: serviceManager, children: _jsx(LexicalComposer, { initialConfig: editorConfig, children: _jsxs("div", { className: "lexical-editor-inner", ref: onRef, children: [_jsx(LexicalStatePlugin, {}), _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "lexical-editor-content", "aria-label": "Lexical Editor" }), ErrorBoundary: LexicalErrorBoundary }), _jsx(OnChangePlugin, { onChange: handleChange }), _jsx(HistoryPlugin, {}), _jsx(AutoFocusPlugin, {}), _jsx(ListPlugin, {}), _jsx(CheckListPlugin, {}), _jsx(LinkPlugin, {}), _jsx(AutoLinkPlugin, {}), _jsx(TablePlugin, {}), _jsx(TableCellResizerPlugin, {}), _jsx(ListMaxIndentLevelPlugin, { maxDepth: 7 }), _jsx(MarkdownShortcutPlugin, { transformers: TRANSFORMERS }), _jsx(LoadContentPlugin, { content: content }), _jsx(CodeHighlightPlugin, {}), _jsx(ImagesPlugin, { captionsEnabled: false }), _jsx(HorizontalRulePlugin, {}), _jsx(EquationsPlugin, {}), _jsx(YouTubePlugin, {}), _jsx(ExcalidrawPlugin, {}), _jsx(CollapsiblePlugin, {}), _jsx(AutoEmbedPlugin, {}), _jsx(JupyterCellPlugin, {}), _jsx(ThemedJupyterProvider, { children: _jsx(SimpleKernelPluginsInner, {}) }), floatingAnchorElem && (_jsxs(_Fragment, { children: [_jsx(DraggableBlockPlugin, { anchorElem: floatingAnchorElem }), _jsx(FloatingTextFormatToolbarPlugin, { anchorElem: floatingAnchorElem, setIsLinkEditMode: setIsLinkEditMode }), _jsx(CodeActionMenuPlugin, { anchorElem: floatingAnchorElem })] }))] }) }) }) })] }) }));
150
151
  });
151
152
  function LexicalWithTools({ content, serviceManager, }) {
152
153
  // Get all actions for this lexical document
@@ -16,7 +16,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
16
16
  */
17
17
  import React from 'react';
18
18
  import { Box } from '@datalayer/primer-addons';
19
- import { JupyterReactTheme, Notebook } from '@datalayer/jupyter-react';
19
+ import { Notebook } from '@datalayer/jupyter-react';
20
+ import { ThemedJupyterProvider } from './stores/themedProvider';
20
21
  // CopilotKit imports
21
22
  import { CopilotKit, useFrontendTool } from '@copilotkit/react-core';
22
23
  import { CopilotSidebar } from '@copilotkit/react-ui';
@@ -50,7 +51,7 @@ const NotebookUI = React.memo(function NotebookUI({ serviceManager, }) {
50
51
  borderRadius: 8,
51
52
  padding: 24,
52
53
  backgroundColor: 'var(--bgColor-default)',
53
- }, children: serviceManager ? (_jsx(JupyterReactTheme, { children: _jsx(Notebook, { nbformat: NOTEBOOK_CONTENT, id: NOTEBOOK_ID, serviceManager: serviceManager, height: "600px", cellSidebarMargin: 120, startDefaultKernel: true }) })) : (_jsx(Box, { style: { padding: 24 }, children: _jsx("p", { children: "Loading service manager..." }) })) })] }) }));
54
+ }, children: serviceManager ? (_jsx(ThemedJupyterProvider, { children: _jsx(Notebook, { nbformat: NOTEBOOK_CONTENT, id: NOTEBOOK_ID, serviceManager: serviceManager, height: "600px", cellSidebarMargin: 120, startDefaultKernel: true }) })) : (_jsx(Box, { style: { padding: 24 }, children: _jsx("p", { children: "Loading service manager..." }) })) })] }) }));
54
55
  });
55
56
  /**
56
57
  * Component to register actions with CopilotKit.
@@ -7,7 +7,8 @@ import { useState, useEffect, useMemo } from 'react';
7
7
  import { Checkbox, FormControl, Heading } from '@primer/react';
8
8
  import { Box } from '@datalayer/primer-addons';
9
9
  import { useCoreStore, createDatalayerServiceManager, DatalayerCollaborationProvider, } from '@datalayer/core';
10
- import { loadJupyterConfig, JupyterReactTheme, Notebook, } from '@datalayer/jupyter-react';
10
+ import { loadJupyterConfig, Notebook } from '@datalayer/jupyter-react';
11
+ import { ThemedJupyterProvider } from './stores/themedProvider';
11
12
  import nbformatExample from './stores/notebooks/NotebookExample1.ipynb.json';
12
13
  // This corresponds to the notebook ID in the URL when you open an existing notbook in your library
13
14
  const NOTEBOOK_ID = '01JZQRQ35GG871QQCZW9TB1A8J';
@@ -64,7 +65,7 @@ const DatalayerNotebookExample = (props) => {
64
65
  token,
65
66
  });
66
67
  }, [enableCollaboration, configuration]);
67
- return (_jsx(JupyterReactTheme, { children: _jsxs(Box, { p: 3, children: [_jsx(Heading, { as: "h2", sx: { mb: 3 }, children: "Datalayer Notebook Collaboration Example" }), _jsx(Box, { sx: { mb: 3 }, children: _jsxs(FormControl, { children: [_jsx(Checkbox, { checked: enableCollaboration, onChange: e => setEnableCollaboration(e.target.checked) }), _jsx(FormControl.Label, { children: "Enable Datalayer Collaboration" })] }) }), (!configuration?.runUrl || !configuration?.token) && (_jsx(Box, { sx: { mb: 2, p: 2, bg: 'danger.subtle' }, children: "Warning: Datalayer configuration is missing. Please configure runUrl and token to use DatalayerServiceManager and collaboration features." })), !serviceManager && (_jsx(Box, { sx: { mb: 2, p: 2, bg: 'attention.subtle' }, children: "Note: DatalayerServiceManager is not available. Notebook functionality will be limited." })), enableCollaboration ? (_jsxs(Box, { sx: {
68
+ return (_jsx(ThemedJupyterProvider, { children: _jsxs(Box, { p: 3, children: [_jsx(Heading, { as: "h2", sx: { mb: 3 }, children: "Datalayer Notebook Collaboration Example" }), _jsx(Box, { sx: { mb: 3 }, children: _jsxs(FormControl, { children: [_jsx(Checkbox, { checked: enableCollaboration, onChange: e => setEnableCollaboration(e.target.checked) }), _jsx(FormControl.Label, { children: "Enable Datalayer Collaboration" })] }) }), (!configuration?.runUrl || !configuration?.token) && (_jsx(Box, { sx: { mb: 2, p: 2, bg: 'danger.subtle' }, children: "Warning: Datalayer configuration is missing. Please configure runUrl and token to use DatalayerServiceManager and collaboration features." })), !serviceManager && (_jsx(Box, { sx: { mb: 2, p: 2, bg: 'attention.subtle' }, children: "Note: DatalayerServiceManager is not available. Notebook functionality will be limited." })), enableCollaboration ? (_jsxs(Box, { sx: {
68
69
  display: 'flex',
69
70
  gap: 2,
70
71
  flexDirection: 'row',
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { JupyterReactTheme, Cell, KernelIndicator, useJupyter, useKernelsStore, useCellsStore, } from '@datalayer/jupyter-react';
2
+ import { Cell, KernelIndicator, useJupyter, useKernelsStore, useCellsStore, } from '@datalayer/jupyter-react';
3
+ import { ThemedJupyterProvider } from './stores/themedProvider';
3
4
  import { Button, Label } from '@primer/react';
4
5
  import { Box } from '@datalayer/primer-addons';
5
6
  const CELL_ID = 'cell-example-1';
@@ -14,6 +15,6 @@ const JupyterCellExampleContent = () => {
14
15
  return (_jsxs(Box, { p: 4, children: [_jsx(Box, { as: "h1", children: "Jupyter Cell Example" }), _jsxs(Box, { children: ["Source: ", cellsStore.getSource(CELL_ID)] }), _jsxs(Box, { children: ["Outputs Count: ", cellsStore.getOutputsCount(CELL_ID)] }), _jsxs(Box, { children: ["Kernel State:", ' ', _jsx(Label, { children: defaultKernel && kernelsStore.getExecutionState(defaultKernel.id) })] }), _jsxs(Box, { children: ["Kernel Phase:", ' ', _jsx(Label, { children: defaultKernel && kernelsStore.getExecutionPhase(defaultKernel.id) })] }), _jsxs(Box, { display: "flex", children: [_jsx(Box, { children: "Kernel Indicator:" }), _jsx(Box, { ml: 3, children: _jsx(KernelIndicator, { kernel: defaultKernel && defaultKernel.connection }) })] }), _jsx(Box, { children: _jsx(Button, { onClick: () => cellsStore.execute(CELL_ID), children: "Run cell" }) }), _jsx(Cell, { source: DEFAULT_SOURCE, id: CELL_ID, kernel: defaultKernel })] }));
15
16
  };
16
17
  export const JupyterCellExample = (props) => {
17
- return (_jsx(JupyterReactTheme, { children: _jsx(JupyterCellExampleContent, {}) }));
18
+ return (_jsx(ThemedJupyterProvider, { children: _jsx(JupyterCellExampleContent, {}) }));
18
19
  };
19
20
  export default JupyterCellExample;
@@ -10,12 +10,13 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
10
10
  */
11
11
  import { useMemo } from 'react';
12
12
  import { Box } from '@datalayer/primer-addons';
13
- import { JupyterReactTheme, Notebook, NotebookToolbar, CellSidebarExtension, CellSidebarButton, } from '@datalayer/jupyter-react';
13
+ import { Notebook, NotebookToolbar, CellSidebarExtension, CellSidebarButton, } from '@datalayer/jupyter-react';
14
+ import { ThemedJupyterProvider } from './stores/themedProvider';
14
15
  import nbformatExample from './stores/notebooks/NotebookExample1.ipynb.json';
15
16
  const NOTEBOOK_ID = 'notebook-example-1';
16
17
  export const JupyterNotebookExample = (props) => {
17
18
  const { serviceManager } = props;
18
19
  const extensions = useMemo(() => [new CellSidebarExtension({ factory: CellSidebarButton })], []);
19
- return (_jsxs(_Fragment, { children: [_jsx(Box, { as: "h1", children: "Jupyter Notebook Example" }), serviceManager && (_jsx(JupyterReactTheme, { children: _jsx(Notebook, { id: NOTEBOOK_ID, nbformat: nbformatExample, serviceManager: serviceManager, startDefaultKernel: true, extensions: extensions, Toolbar: NotebookToolbar }) }))] }));
20
+ return (_jsxs(_Fragment, { children: [_jsx(Box, { as: "h1", children: "Jupyter Notebook Example" }), serviceManager && (_jsx(ThemedJupyterProvider, { children: _jsx(Notebook, { id: NOTEBOOK_ID, nbformat: nbformatExample, serviceManager: serviceManager, startDefaultKernel: true, extensions: extensions, Toolbar: NotebookToolbar }) }))] }));
20
21
  };
21
22
  export default JupyterNotebookExample;
@@ -8,10 +8,15 @@ import { useEffect, useState } from 'react';
8
8
  import { createRoot } from 'react-dom/client';
9
9
  import { loadJupyterConfig, JupyterReactTheme, createServerSettings, setJupyterServerUrl, setJupyterServerToken, getJupyterServerUrl, getJupyterServerToken, } from '@datalayer/jupyter-react';
10
10
  import { ServiceManager } from '@jupyterlab/services';
11
- import { coreStore, iamStore, createDatalayerServiceManager, DatalayerThemeProvider, } from '@datalayer/core';
11
+ import { DatalayerThemeProvider, themeConfigs, themeVariants, } from '@datalayer/primer-addons';
12
+ import { SegmentedControl } from '@primer/react';
13
+ import { Box } from '@datalayer/primer-addons';
14
+ import { MoonIcon, SunIcon, DeviceDesktopIcon } from '@primer/octicons-react';
15
+ import { coreStore, iamStore, createDatalayerServiceManager, } from '@datalayer/core';
12
16
  import { useChatStore } from '../components/chat/store';
13
17
  import { OAuthCallback } from '../identity';
14
18
  import { EXAMPLES } from './example-selector';
19
+ import { useExampleThemeStore } from './stores/themeStore';
15
20
  import nbformatExample from './stores/notebooks/NotebookExample1.ipynb.json';
16
21
  // Load configurations from DOM
17
22
  const loadConfigurations = () => {
@@ -292,39 +297,84 @@ export const ExampleApp = () => {
292
297
  if (serviceManager) {
293
298
  exampleProps.serviceManager = serviceManager;
294
299
  }
295
- return (_jsx(DatalayerThemeProvider, { children: _jsxs("div", { style: { width: '100vw', height: '100vh', overflow: 'hidden' }, children: [_jsxs("div", { style: {
300
+ return (_jsx(ExampleAppThemed, { selectedExample: selectedExample, isChangingExample: isChangingExample, error: error, ExampleComponent: ExampleComponent, exampleProps: exampleProps, onExampleChange: handleExampleChange }));
301
+ };
302
+ /**
303
+ * Inner shell that reads from the theme store and wires
304
+ * DatalayerThemeProvider + the header bar with selectors.
305
+ */
306
+ const ExampleAppThemed = ({ selectedExample, isChangingExample, error, ExampleComponent, exampleProps, onExampleChange, }) => {
307
+ const { colorMode, theme: themeVariant } = useExampleThemeStore();
308
+ const cfg = themeConfigs[themeVariant];
309
+ return (_jsx(DatalayerThemeProvider, { colorMode: colorMode, theme: cfg.primerTheme, themeStyles: cfg.themeStyles, children: _jsxs(Box, { sx: {
310
+ width: '100vw',
311
+ height: '100vh',
312
+ overflow: 'hidden',
313
+ bg: 'canvas.default',
314
+ color: 'fg.default',
315
+ }, children: [_jsxs(Box, { sx: {
296
316
  position: 'fixed',
297
317
  top: 0,
298
318
  left: 0,
299
319
  right: 0,
300
320
  zIndex: 100,
301
- padding: '10px 20px',
302
- background: '#f0f0f0',
303
- borderBottom: '1px solid #ccc',
321
+ px: 3,
304
322
  display: 'flex',
305
323
  alignItems: 'center',
306
324
  justifyContent: 'space-between',
307
- gap: '15px',
308
- fontSize: '14px',
309
- fontFamily: 'system-ui, -apple-system, sans-serif',
325
+ gap: 3,
310
326
  height: '50px',
311
- boxSizing: 'border-box',
312
- }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '15px' }, children: [_jsx("label", { style: { fontWeight: 500, color: '#333' }, children: "Select Example:" }), _jsx("select", { value: selectedExample, onChange: e => handleExampleChange(e.target.value), disabled: isChangingExample, style: {
313
- padding: '6px 12px',
314
- fontSize: '14px',
315
- border: '1px solid #ccc',
316
- borderRadius: '4px',
317
- background: 'white',
327
+ bg: 'canvas.subtle',
328
+ borderBottom: '1px solid',
329
+ borderColor: 'border.default',
330
+ }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Box, { as: "select", value: selectedExample, onChange: (e) => onExampleChange(e.target.value), disabled: isChangingExample, sx: {
331
+ px: 2,
332
+ py: '6px',
333
+ fontSize: 1,
334
+ fontFamily: 'mono',
335
+ border: '1px solid',
336
+ borderColor: 'border.default',
337
+ borderRadius: 2,
338
+ bg: 'canvas.default',
339
+ color: 'fg.default',
318
340
  cursor: isChangingExample ? 'not-allowed' : 'pointer',
319
- fontFamily: 'monospace',
320
341
  minWidth: '250px',
342
+ outline: 'none',
343
+ '&:focus-visible': {
344
+ boxShadow: '0 0 0 2px var(--bgColor-accent-muted, rgba(9,105,218,0.3))',
345
+ },
321
346
  }, children: getExampleNames()
322
347
  .sort()
323
- .map(name => (_jsx("option", { value: name, children: name }, name))) }), isChangingExample && (_jsx("span", { style: { color: '#666', fontSize: '12px' }, children: "Loading..." })), error && (_jsxs("span", { style: { color: '#dc3545', fontSize: '12px' }, children: ["Error: ", error] }))] }), _jsx("img", { src: "https://assets.datalayer.tech/datalayer-25.svg", alt: "Datalayer", style: { height: '24px' } })] }), _jsx("div", { style: {
348
+ .map(name => (_jsx("option", { value: name, children: name }, name))) }), 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(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: themeVariants.map(variant => {
349
+ const tcfg = themeConfigs[variant];
350
+ const isSelected = themeVariant === variant;
351
+ return (_jsx(Box, { as: "button", "aria-label": tcfg.label, "aria-pressed": isSelected, onClick: () => useExampleThemeStore.getState().setTheme(variant, false), sx: {
352
+ width: 24,
353
+ height: 24,
354
+ borderRadius: '50%',
355
+ backgroundColor: tcfg.brandColor,
356
+ border: '2px solid',
357
+ borderColor: isSelected ? 'accent.fg' : 'border.default',
358
+ cursor: 'pointer',
359
+ padding: 0,
360
+ outline: 'none',
361
+ transition: 'border-color 0.15s ease',
362
+ boxShadow: isSelected
363
+ ? '0 0 0 2px var(--bgColor-accent-muted, rgba(9,105,218,0.3))'
364
+ : 'none',
365
+ '&:hover': { borderColor: 'accent.fg' },
366
+ '&:focus-visible': {
367
+ boxShadow: '0 0 0 2px var(--bgColor-accent-muted, rgba(9,105,218,0.3))',
368
+ },
369
+ } }, variant));
370
+ }) }), _jsxs(SegmentedControl, { "aria-label": "Color mode", size: "small", onChange: (index) => {
371
+ const modes = ['light', 'dark', 'auto'];
372
+ useExampleThemeStore.getState().setColorMode(modes[index]);
373
+ }, children: [_jsx(SegmentedControl.IconButton, { selected: colorMode === 'light', icon: SunIcon, "aria-label": "Light" }), _jsx(SegmentedControl.IconButton, { selected: colorMode === 'dark', icon: MoonIcon, "aria-label": "Dark" }), _jsx(SegmentedControl.IconButton, { selected: colorMode === 'auto', icon: DeviceDesktopIcon, "aria-label": "Auto" })] }), _jsx("img", { src: "https://assets.datalayer.tech/datalayer-25.svg", alt: "Datalayer", style: { height: '24px' } })] })] }), _jsx(Box, { sx: {
324
374
  marginTop: '50px',
325
375
  height: 'calc(100vh - 50px)',
326
376
  overflow: 'auto',
327
- }, children: isChangingExample ? (_jsxs("div", { style: { padding: '40px', textAlign: 'center', color: '#666' }, children: [_jsxs("h3", { children: ["Loading ", selectedExample, "..."] }), _jsx("p", { children: "Please wait while the example loads." })] })) : ExampleComponent ? (_jsx(ExampleComponent, { ...exampleProps })) : null })] }) }));
377
+ }, children: 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(ExampleComponent, { ...exampleProps })) : null })] }) }));
328
378
  };
329
379
  // Mount the app - check route to determine which app to render
330
380
  const root = document.getElementById('root');
@@ -0,0 +1,33 @@
1
+ import { type ThemeVariant, type ColorMode } from '@datalayer/primer-addons';
2
+ export type { ThemeVariant, ColorMode };
3
+ export interface ThemeState {
4
+ /** Current color mode (light, dark, or auto = follow OS). */
5
+ colorMode: ColorMode;
6
+ /** Current theme variant. */
7
+ theme: ThemeVariant;
8
+ /** Cycle through light → dark → auto. */
9
+ toggleColorMode: () => void;
10
+ /** Set a specific color mode. */
11
+ setColorMode: (mode: ColorMode) => void;
12
+ /**
13
+ * Set the active theme variant.
14
+ * @param applyDefaultColorMode When true (default), also switches the
15
+ * color mode to the theme's configured default.
16
+ */
17
+ setTheme: (theme: ThemeVariant, applyDefaultColorMode?: boolean) => void;
18
+ }
19
+ /**
20
+ * Zustand store for theme preferences in the examples app.
21
+ * Persisted to localStorage under 'agent-runtimes-theme' key.
22
+ */
23
+ export declare const useExampleThemeStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<ThemeState>, "persist"> & {
24
+ persist: {
25
+ setOptions: (options: Partial<import("zustand/middleware").PersistOptions<ThemeState, unknown>>) => void;
26
+ clearStorage: () => void;
27
+ rehydrate: () => Promise<void> | void;
28
+ hasHydrated: () => boolean;
29
+ onHydrate: (fn: (state: ThemeState) => void) => () => void;
30
+ onFinishHydration: (fn: (state: ThemeState) => void) => () => void;
31
+ getOptions: () => Partial<import("zustand/middleware").PersistOptions<ThemeState, unknown>>;
32
+ };
33
+ }>;
@@ -0,0 +1,38 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ import { create } from 'zustand';
6
+ import { persist, createJSONStorage } from 'zustand/middleware';
7
+ import { themeConfigs, } from '@datalayer/primer-addons';
8
+ /**
9
+ * Zustand store for theme preferences in the examples app.
10
+ * Persisted to localStorage under 'agent-runtimes-theme' key.
11
+ */
12
+ export const useExampleThemeStore = create()(persist(set => ({
13
+ colorMode: 'light',
14
+ theme: 'datalayer',
15
+ toggleColorMode: () => set(state => {
16
+ const cycle = {
17
+ light: 'dark',
18
+ dark: 'auto',
19
+ auto: 'light',
20
+ };
21
+ return { colorMode: cycle[state.colorMode] };
22
+ }),
23
+ setColorMode: (mode) => set({ colorMode: mode }),
24
+ setTheme: (theme, applyDefaultColorMode = true) => set(() => {
25
+ const next = { theme };
26
+ if (applyDefaultColorMode) {
27
+ next.colorMode = themeConfigs[theme].defaultColorMode;
28
+ }
29
+ return next;
30
+ }),
31
+ }), {
32
+ name: 'agent-runtimes-theme',
33
+ storage: createJSONStorage(() => localStorage),
34
+ partialize: state => ({
35
+ colorMode: state.colorMode,
36
+ theme: state.theme,
37
+ }),
38
+ }));
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Theme-aware wrappers for example components.
3
+ *
4
+ * These are drop-in replacements for `DatalayerThemeProvider` and
5
+ * `JupyterReactTheme` that automatically read theme / color-mode
6
+ * from the shared `useExampleThemeStore`.
7
+ *
8
+ * Usage: replace
9
+ * import { DatalayerThemeProvider } from '@datalayer/primer-addons';
10
+ * with
11
+ * import { ThemedProvider } from './stores/themedProvider';
12
+ *
13
+ * and swap `<DatalayerThemeProvider>` → `<ThemedProvider>`.
14
+ */
15
+ import React from 'react';
16
+ import { type IDatalayerThemeProviderProps } from '@datalayer/primer-addons';
17
+ /**
18
+ * Drop-in replacement for `<DatalayerThemeProvider>`.
19
+ * Reads theme/colorMode from the example theme store and
20
+ * forwards them to the real provider. Any explicit props
21
+ * (colorMode, theme, themeStyles) are still respected as overrides.
22
+ */
23
+ export declare const ThemedProvider: React.FC<React.PropsWithChildren<Omit<IDatalayerThemeProviderProps, 'ref'>>>;
24
+ /**
25
+ * Drop-in replacement for `<JupyterReactTheme>`.
26
+ * Wraps children in `ThemedProvider` so Jupyter components also
27
+ * pick up the selected theme/color-mode.
28
+ *
29
+ * The wrapper automatically derives `colormode` and `backgroundColor`
30
+ * from the shared theme store so every Jupyter component inherits
31
+ * the correct palette — mirroring the pattern used by
32
+ * `ProjectNotebookEditor`.
33
+ *
34
+ * @param useJupyterReactTheme - When `true`, wraps children in
35
+ * `<JupyterReactTheme>` inside the themed provider. Defaults to `true`.
36
+ */
37
+ /**
38
+ * Hook that returns the `brandColor` for the currently selected theme.
39
+ * Use this in example components to pass a dynamic brand color to
40
+ * `<ChatFloating>` or any other component that accepts a `brandColor` prop.
41
+ */
42
+ export declare const useThemeBrandColor: () => string;
43
+ export declare const ThemedJupyterProvider: React.FC<React.PropsWithChildren<{
44
+ useJupyterReactTheme?: boolean;
45
+ }>>;
@@ -0,0 +1,54 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { DatalayerThemeProvider, themeConfigs, } from '@datalayer/primer-addons';
3
+ import { JupyterReactTheme } from '@datalayer/jupyter-react';
4
+ import { useExampleThemeStore } from './themeStore';
5
+ /**
6
+ * Drop-in replacement for `<DatalayerThemeProvider>`.
7
+ * Reads theme/colorMode from the example theme store and
8
+ * forwards them to the real provider. Any explicit props
9
+ * (colorMode, theme, themeStyles) are still respected as overrides.
10
+ */
11
+ export const ThemedProvider = ({ children, ...rest }) => {
12
+ const { colorMode, theme: themeVariant } = useExampleThemeStore();
13
+ const cfg = themeConfigs[themeVariant];
14
+ return (_jsx(DatalayerThemeProvider, { colorMode: rest.colorMode ?? colorMode, theme: rest.theme ?? cfg.primerTheme, themeStyles: rest.themeStyles ?? cfg.themeStyles, ...rest, children: children }));
15
+ };
16
+ /**
17
+ * Drop-in replacement for `<JupyterReactTheme>`.
18
+ * Wraps children in `ThemedProvider` so Jupyter components also
19
+ * pick up the selected theme/color-mode.
20
+ *
21
+ * The wrapper automatically derives `colormode` and `backgroundColor`
22
+ * from the shared theme store so every Jupyter component inherits
23
+ * the correct palette — mirroring the pattern used by
24
+ * `ProjectNotebookEditor`.
25
+ *
26
+ * @param useJupyterReactTheme - When `true`, wraps children in
27
+ * `<JupyterReactTheme>` inside the themed provider. Defaults to `true`.
28
+ */
29
+ /**
30
+ * Hook that returns the `brandColor` for the currently selected theme.
31
+ * Use this in example components to pass a dynamic brand color to
32
+ * `<ChatFloating>` or any other component that accepts a `brandColor` prop.
33
+ */
34
+ export const useThemeBrandColor = () => {
35
+ const { theme: themeVariant } = useExampleThemeStore();
36
+ return themeConfigs[themeVariant].brandColor;
37
+ };
38
+ export const ThemedJupyterProvider = ({ children, useJupyterReactTheme = true }) => {
39
+ const { colorMode, theme: themeVariant } = useExampleThemeStore();
40
+ const cfg = themeConfigs[themeVariant];
41
+ // Resolve 'auto' to an actual mode so we can pick the right style set.
42
+ const resolvedMode = colorMode === 'auto'
43
+ ? typeof window !== 'undefined' &&
44
+ window.matchMedia('(prefers-color-scheme: dark)').matches
45
+ ? 'dark'
46
+ : 'light'
47
+ : colorMode === 'dark'
48
+ ? 'dark'
49
+ : 'light';
50
+ // Extract the canvas background from the theme's CSS-var overrides.
51
+ const modeStyles = resolvedMode === 'dark' ? cfg.themeStyles.dark : cfg.themeStyles.light;
52
+ const backgroundColor = modeStyles['--bgColor-default'];
53
+ return (_jsx(ThemedProvider, { children: useJupyterReactTheme ? (_jsx(JupyterReactTheme, { colormode: colorMode, backgroundColor: backgroundColor, children: children })) : (children) }));
54
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datalayer/agent-runtimes",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "workspaces": [
6
6
  ".",
@@ -130,10 +130,11 @@
130
130
  "@anthropic-ai/sdk": "^0.52.0",
131
131
  "@datalayer/core": "^1.0.1",
132
132
  "@datalayer/icons-react": "^1.0.6",
133
- "@datalayer/jupyter-lexical": "^1.0.11",
133
+ "@datalayer/jupyter-lexical": "^1.0.13",
134
134
  "@datalayer/jupyter-react": "^2.0.3",
135
- "@datalayer/primer-addons": "^1.0.7",
135
+ "@datalayer/primer-addons": "^1.0.10",
136
136
  "@datalayer/primer-rjsf": "^1.0.1",
137
+ "@excalidraw/excalidraw": "^0.18.0",
137
138
  "@jupyter-widgets/base-manager": "^1.0.12",
138
139
  "@jupyter-widgets/schema": "^0.5.6",
139
140
  "@jupyterlab/apputils": "^4.6.0",