@datalayer/agent-runtimes 1.0.4 → 1.0.6
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 +182 -1
- package/lib/AgentNode.d.ts +3 -0
- package/lib/AgentNode.js +676 -0
- package/lib/App.js +1 -1
- package/lib/agent-node/themeStore.d.ts +3 -0
- package/lib/agent-node/themeStore.js +156 -0
- package/lib/agent-node-main.d.ts +1 -0
- package/lib/agent-node-main.js +14 -0
- package/lib/agents/AgentDetails.d.ts +22 -1
- package/lib/agents/AgentDetails.js +34 -47
- package/lib/api/index.d.ts +0 -1
- package/lib/api/index.js +4 -2
- package/lib/chat/Chat.d.ts +5 -106
- package/lib/chat/Chat.js +20 -14
- package/lib/chat/ChatFloating.d.ts +7 -140
- package/lib/chat/ChatFloating.js +3 -3
- package/lib/chat/ChatPopupStandalone.d.ts +8 -47
- package/lib/chat/ChatPopupStandalone.js +3 -3
- package/lib/chat/ChatSidebar.d.ts +4 -69
- package/lib/chat/ChatSidebar.js +83 -51
- package/lib/chat/ChatStandalone.d.ts +4 -54
- package/lib/chat/ChatStandalone.js +3 -3
- package/lib/chat/base/ChatBase.js +1414 -174
- package/lib/chat/display/FloatingBrandButton.js +8 -1
- package/lib/chat/header/ChatHeader.d.ts +3 -1
- package/lib/chat/header/ChatHeader.js +15 -12
- package/lib/chat/header/ChatHeaderBase.d.ts +30 -5
- package/lib/chat/header/ChatHeaderBase.js +41 -16
- package/lib/chat/indicators/McpStatusIndicator.d.ts +7 -4
- package/lib/chat/indicators/McpStatusIndicator.js +7 -32
- package/lib/chat/indicators/SandboxStatusIndicator.d.ts +4 -1
- package/lib/chat/indicators/SandboxStatusIndicator.js +91 -56
- package/lib/chat/indicators/SkillsStatusIndicator.d.ts +7 -0
- package/lib/chat/indicators/SkillsStatusIndicator.js +88 -0
- package/lib/chat/indicators/index.d.ts +1 -0
- package/lib/chat/indicators/index.js +1 -0
- package/lib/chat/messages/ChatMessageList.d.ts +1 -1
- package/lib/chat/messages/ChatMessageList.js +154 -114
- package/lib/chat/messages/ChatMessages.js +6 -2
- package/lib/chat/prompt/InputFooter.d.ts +21 -6
- package/lib/chat/prompt/InputFooter.js +76 -20
- package/lib/chat/prompt/InputPrompt.d.ts +5 -1
- package/lib/chat/prompt/InputPrompt.js +4 -4
- package/lib/chat/prompt/InputPromptFooter.d.ts +3 -1
- package/lib/chat/prompt/InputPromptFooter.js +3 -3
- package/lib/chat/prompt/InputPromptLexical.d.ts +3 -1
- package/lib/chat/prompt/InputPromptLexical.js +12 -5
- package/lib/chat/prompt/InputPromptText.d.ts +3 -1
- package/lib/chat/prompt/InputPromptText.js +2 -2
- package/lib/chat/tools/ToolApprovalBanner.js +1 -1
- package/lib/chat/tools/ToolCallDisplay.d.ts +3 -1
- package/lib/chat/tools/ToolCallDisplay.js +2 -2
- package/lib/chat/usage/TokenUsageBar.js +20 -2
- package/lib/client/AgentRuntimesClientContext.d.ts +53 -0
- package/lib/client/AgentRuntimesClientContext.js +55 -0
- package/lib/client/AgentsMixin.d.ts +0 -18
- package/lib/client/AgentsMixin.js +20 -30
- package/lib/client/IAgentRuntimesClient.d.ts +215 -0
- package/lib/client/IAgentRuntimesClient.js +5 -0
- package/lib/client/SdkAgentRuntimesClient.d.ts +151 -0
- package/lib/client/SdkAgentRuntimesClient.js +134 -0
- package/lib/client/index.d.ts +4 -1
- package/lib/client/index.js +3 -1
- package/lib/components/NotificationEventCard.js +5 -1
- package/lib/config/AgentConfiguration.d.ts +22 -0
- package/lib/config/AgentConfiguration.js +319 -64
- package/lib/context/ContextDistribution.d.ts +3 -1
- package/lib/context/ContextDistribution.js +8 -27
- package/lib/context/ContextInspector.d.ts +3 -1
- package/lib/context/ContextInspector.js +19 -67
- package/lib/context/ContextPanel.d.ts +3 -1
- package/lib/context/ContextPanel.js +104 -64
- package/lib/context/ContextUsage.d.ts +3 -1
- package/lib/context/ContextUsage.js +3 -3
- package/lib/context/CostTracker.d.ts +9 -3
- package/lib/context/CostTracker.js +26 -47
- package/lib/context/CostUsageChart.d.ts +12 -0
- package/lib/context/CostUsageChart.js +378 -0
- package/lib/context/GraphFlowChart.d.ts +16 -0
- package/lib/context/GraphFlowChart.js +182 -0
- package/lib/context/TokenUsageChart.d.ts +8 -1
- package/lib/context/TokenUsageChart.js +349 -211
- package/lib/context/TurnGraphChart.d.ts +39 -0
- package/lib/context/TurnGraphChart.js +538 -0
- package/lib/context/otelWsPool.d.ts +20 -0
- package/lib/context/otelWsPool.js +69 -0
- package/lib/examples/A2UiComponentGalleryExample.d.ts +0 -17
- package/lib/examples/A2UiComponentGalleryExample.js +315 -522
- package/lib/examples/A2UiContactCardExample.d.ts +0 -18
- package/lib/examples/A2UiContactCardExample.js +154 -411
- package/lib/examples/A2UiRestaurantExample.d.ts +0 -30
- package/lib/examples/A2UiRestaurantExample.js +114 -212
- package/lib/examples/A2UiViewerExample.d.ts +0 -18
- package/lib/examples/A2UiViewerExample.js +283 -532
- package/lib/examples/AgUiBackendToolRenderingExample.js +1 -1
- package/lib/examples/AgUiHaikuGenUiExample.d.ts +1 -1
- package/lib/examples/AgUiHaikuGenUiExample.js +1 -1
- package/lib/examples/AgUiSharedStateExample.js +2 -1
- package/lib/examples/AgentCheckpointsExample.js +14 -28
- package/lib/examples/AgentCodemodeExample.d.ts +4 -6
- package/lib/examples/AgentCodemodeExample.js +603 -169
- package/lib/examples/AgentEvalsExample.js +339 -53
- package/lib/examples/AgentGuardrailsExample.js +383 -66
- package/lib/examples/AgentHooksExample.d.ts +3 -0
- package/lib/examples/AgentHooksExample.js +122 -0
- package/lib/examples/AgentInferenceProviderExample.d.ts +3 -0
- package/lib/examples/AgentInferenceProviderExample.js +329 -0
- package/lib/examples/AgentMCPExample.d.ts +3 -0
- package/lib/examples/AgentMCPExample.js +481 -0
- package/lib/examples/AgentMemoryExample.d.ts +1 -2
- package/lib/examples/AgentMemoryExample.js +78 -33
- package/lib/examples/AgentMonitoringExample.js +261 -200
- package/lib/examples/AgentNotificationsExample.d.ts +1 -2
- package/lib/examples/AgentNotificationsExample.js +114 -33
- package/lib/examples/AgentOtelExample.js +32 -42
- package/lib/examples/AgentOutputsExample.d.ts +11 -6
- package/lib/examples/AgentOutputsExample.js +433 -81
- package/lib/examples/AgentParametersExample.d.ts +3 -0
- package/lib/examples/AgentParametersExample.js +248 -0
- package/lib/examples/AgentSandboxExample.d.ts +3 -3
- package/lib/examples/AgentSandboxExample.js +74 -45
- package/lib/examples/AgentSkillsExample.js +95 -103
- package/lib/examples/AgentSubagentsExample.d.ts +14 -0
- package/lib/examples/AgentSubagentsExample.js +228 -0
- package/lib/examples/AgentToolApprovalsExample.js +49 -561
- package/lib/examples/AgentTriggersExample.js +823 -569
- package/lib/examples/{AgentspecExample.d.ts → AgentspecsExample.d.ts} +2 -2
- package/lib/examples/AgentspecsExample.js +1096 -0
- package/lib/examples/ChatCustomExample.js +16 -28
- package/lib/examples/ChatExample.js +13 -29
- package/lib/examples/CopilotKitLexicalExample.js +2 -1
- package/lib/examples/CopilotKitNotebookExample.js +2 -1
- package/lib/examples/HomeExample.d.ts +15 -0
- package/lib/examples/HomeExample.js +77 -0
- package/lib/examples/Lexical2Example.js +4 -2
- package/lib/examples/{LexicalExample.d.ts → LexicalAgentExample.d.ts} +4 -4
- package/lib/examples/{LexicalExample.js → LexicalAgentExample.js} +66 -17
- package/lib/examples/{LexicalSidebarExample.d.ts → LexicalAgentSidebarExample.d.ts} +5 -5
- package/lib/examples/LexicalAgentSidebarExample.js +261 -0
- package/lib/examples/NotebookAgentExample.d.ts +9 -0
- package/lib/examples/NotebookAgentExample.js +192 -0
- package/lib/examples/{NotebookSidebarExample.d.ts → NotebookAgentSidebarExample.d.ts} +2 -2
- package/lib/examples/NotebookAgentSidebarExample.js +221 -0
- package/lib/examples/{DatalayerNotebookExample.d.ts → NotebookCollaborationExample.d.ts} +4 -4
- package/lib/examples/{DatalayerNotebookExample.js → NotebookCollaborationExample.js} +3 -3
- package/lib/examples/NotebookExample.d.ts +4 -7
- package/lib/examples/NotebookExample.js +14 -146
- package/lib/examples/components/AuthRequiredView.d.ts +6 -0
- package/lib/examples/components/AuthRequiredView.js +33 -0
- package/lib/examples/components/ExampleWrapper.d.ts +9 -3
- package/lib/examples/components/ExampleWrapper.js +45 -9
- package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.js +1 -1
- package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.js +1 -1
- package/lib/examples/{ag-ui → components}/haiku/index.d.ts +1 -1
- package/lib/examples/{ag-ui → components}/haiku/index.js +1 -1
- package/lib/examples/components/index.d.ts +3 -0
- package/lib/examples/components/index.js +4 -0
- package/lib/examples/{ag-ui → components}/weather/index.d.ts +1 -1
- package/lib/examples/{ag-ui → components}/weather/index.js +1 -1
- package/lib/examples/example-selector.d.ts +17 -4
- package/lib/examples/example-selector.js +108 -41
- package/lib/examples/index.d.ts +10 -6
- package/lib/examples/index.js +10 -6
- package/lib/examples/lexical/initial-content.json +6 -6
- package/lib/examples/main.js +257 -27
- package/lib/examples/utils/a2ui.d.ts +18 -0
- package/lib/examples/utils/a2ui.js +69 -0
- package/lib/examples/utils/a2uiMarkdownProvider.d.ts +7 -0
- package/lib/examples/utils/a2uiMarkdownProvider.js +9 -0
- package/lib/examples/utils/agentId.d.ts +18 -0
- package/lib/examples/utils/agentId.js +54 -0
- package/lib/examples/utils/agents/earthquake-detector.json +11 -11
- package/lib/examples/utils/agents/sales-forecaster.json +11 -11
- package/lib/examples/utils/agents/social-post-generator.json +11 -11
- package/lib/examples/utils/agents/stock-market.json +11 -11
- package/lib/examples/utils/examplesStore.js +82 -27
- package/lib/examples/utils/useExampleAgentRuntimesUrl.d.ts +5 -0
- package/lib/examples/utils/useExampleAgentRuntimesUrl.js +19 -0
- package/lib/hooks/index.d.ts +8 -8
- package/lib/hooks/index.js +7 -7
- package/lib/hooks/useA2A.d.ts +2 -3
- package/lib/hooks/useAIAgentsWebSocket.d.ts +43 -4
- package/lib/hooks/useAIAgentsWebSocket.js +153 -12
- package/lib/hooks/useAcp.d.ts +1 -2
- package/lib/hooks/useAgUi.d.ts +1 -1
- package/lib/hooks/{useAgents.d.ts → useAgentRuntimes.d.ts} +70 -4
- package/lib/hooks/{useAgents.js → useAgentRuntimes.js} +237 -32
- package/lib/hooks/useAgentsCatalog.js +1 -1
- package/lib/hooks/useAgentsService.d.ts +2 -2
- package/lib/hooks/useAgentsService.js +7 -7
- package/lib/hooks/useCheckpoints.js +1 -1
- package/lib/hooks/useConfig.d.ts +4 -1
- package/lib/hooks/useConfig.js +10 -3
- package/lib/hooks/useContextSnapshot.d.ts +9 -4
- package/lib/hooks/useContextSnapshot.js +9 -37
- package/lib/hooks/useMonitoring.js +3 -0
- package/lib/hooks/useSandbox.d.ts +20 -8
- package/lib/hooks/useSandbox.js +105 -40
- package/lib/hooks/useSkills.d.ts +23 -5
- package/lib/hooks/useSkills.js +94 -39
- package/lib/hooks/useToolApprovals.d.ts +60 -36
- package/lib/hooks/useToolApprovals.js +318 -69
- package/lib/hooks/useVercelAI.d.ts +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +1 -0
- package/lib/inference/index.d.ts +0 -1
- package/lib/middleware/index.d.ts +0 -1
- package/lib/protocols/AGUIAdapter.js +6 -0
- package/lib/protocols/VercelAIAdapter.d.ts +7 -0
- package/lib/protocols/VercelAIAdapter.js +59 -7
- package/lib/specs/agents/agents.d.ts +21 -4
- package/lib/specs/agents/agents.js +2879 -316
- package/lib/specs/agents/index.js +3 -1
- package/lib/specs/benchmarks.d.ts +20 -0
- package/lib/specs/benchmarks.js +205 -0
- package/lib/specs/envvars.js +27 -20
- package/lib/specs/evals.d.ts +10 -9
- package/lib/specs/evals.js +128 -88
- package/lib/specs/events.d.ts +3 -10
- package/lib/specs/events.js +127 -84
- package/lib/specs/frontendTools.js +2 -2
- package/lib/specs/guardrails.d.ts +0 -7
- package/lib/specs/guardrails.js +240 -159
- package/lib/specs/mcpServers.js +35 -6
- package/lib/specs/memory.d.ts +0 -2
- package/lib/specs/memory.js +4 -17
- package/lib/specs/models.d.ts +0 -2
- package/lib/specs/models.js +20 -15
- package/lib/specs/notifications.js +102 -18
- package/lib/specs/outputs.js +15 -9
- package/lib/specs/personas.d.ts +41 -0
- package/lib/specs/personas.js +168 -0
- package/lib/specs/skills.d.ts +1 -1
- package/lib/specs/skills.js +23 -23
- package/lib/specs/teams/index.js +3 -1
- package/lib/specs/teams/teams.js +468 -348
- package/lib/specs/tools.js +4 -4
- package/lib/specs/triggers.js +61 -11
- package/lib/stores/agentRuntimeStore.d.ts +208 -0
- package/lib/stores/agentRuntimeStore.js +650 -0
- package/lib/stores/conversationStore.js +2 -2
- package/lib/stores/index.d.ts +1 -1
- package/lib/stores/index.js +1 -1
- package/lib/tools/adapters/copilotkit/lexicalHooks.d.ts +1 -2
- package/lib/tools/adapters/copilotkit/lexicalHooks.js +1 -3
- package/lib/tools/adapters/copilotkit/notebookHooks.d.ts +1 -2
- package/lib/tools/adapters/copilotkit/notebookHooks.js +1 -3
- package/lib/tools/index.d.ts +0 -2
- package/lib/tools/index.js +0 -1
- package/lib/types/agents-lifecycle.d.ts +18 -0
- package/lib/types/agents.d.ts +6 -0
- package/lib/types/agentspecs.d.ts +54 -1
- package/lib/types/benchmarks.d.ts +43 -0
- package/lib/types/benchmarks.js +5 -0
- package/lib/types/chat.d.ts +325 -8
- package/lib/types/context.d.ts +27 -0
- package/lib/types/cost.d.ts +2 -2
- package/lib/types/evals.d.ts +26 -17
- package/lib/types/index.d.ts +3 -0
- package/lib/types/index.js +3 -0
- package/lib/types/mcp.d.ts +8 -0
- package/lib/types/models.d.ts +2 -2
- package/lib/types/personas.d.ts +25 -0
- package/lib/types/personas.js +5 -0
- package/lib/types/skills.d.ts +43 -1
- package/lib/types/stream.d.ts +110 -0
- package/lib/types/stream.js +36 -0
- package/lib/utils/utils.d.ts +9 -5
- package/lib/utils/utils.js +9 -5
- package/package.json +19 -11
- package/scripts/codegen/__pycache__/generate_agents.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_benchmarks.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_evals.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_events.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
- package/scripts/codegen/generate_agents.py +187 -45
- package/scripts/codegen/generate_benchmarks.py +441 -0
- package/scripts/codegen/generate_evals.py +94 -16
- package/scripts/codegen/generate_events.py +35 -14
- package/scripts/codegen/generate_personas.py +319 -0
- package/scripts/codegen/generate_skills.py +9 -9
- package/scripts/sync-jupyter.sh +26 -7
- package/lib/api/tool-approvals.d.ts +0 -62
- package/lib/api/tool-approvals.js +0 -145
- package/lib/examples/AgentspecExample.js +0 -705
- package/lib/examples/LexicalSidebarExample.js +0 -163
- package/lib/examples/NotebookSidebarExample.js +0 -119
- package/lib/examples/NotebookSimpleExample.d.ts +0 -6
- package/lib/examples/NotebookSimpleExample.js +0 -22
- package/lib/examples/ag-ui/index.d.ts +0 -10
- package/lib/examples/ag-ui/index.js +0 -16
- package/lib/hooks/useAgentsRegistry.d.ts +0 -10
- package/lib/hooks/useAgentsRegistry.js +0 -20
- package/lib/stores/agentsStore.d.ts +0 -123
- package/lib/stores/agentsStore.js +0 -270
- /package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.d.ts +0 -0
- /package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.d.ts +0 -0
- /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.d.ts +0 -0
- /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.js +0 -0
|
@@ -10,6 +10,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
* @module chat/display/FloatingBrandButton
|
|
11
11
|
*/
|
|
12
12
|
import { useState } from 'react';
|
|
13
|
+
import { createPortal } from 'react-dom';
|
|
13
14
|
import { Box, IconButton, Tooltip, Text } from '@primer/react';
|
|
14
15
|
import { CommentDiscussionIcon, XIcon } from '@primer/octicons-react';
|
|
15
16
|
/**
|
|
@@ -26,7 +27,7 @@ export function FloatingBrandButton({ isOpen, onToggle, position = 'bottom-right
|
|
|
26
27
|
'top-left': { top: 20, left: 20 },
|
|
27
28
|
};
|
|
28
29
|
const posStyle = positionStyles[position];
|
|
29
|
-
|
|
30
|
+
const floatingButton = (_jsx(Box, { className: className, sx: {
|
|
30
31
|
position: 'fixed',
|
|
31
32
|
zIndex: 1000,
|
|
32
33
|
...posStyle,
|
|
@@ -84,5 +85,11 @@ export function FloatingBrandButton({ isOpen, onToggle, position = 'bottom-right
|
|
|
84
85
|
},
|
|
85
86
|
},
|
|
86
87
|
} }))] }) }));
|
|
88
|
+
// Render in a body portal so fixed positioning stays anchored to the
|
|
89
|
+
// actual viewport edge even inside transformed containers.
|
|
90
|
+
if (typeof document !== 'undefined' && document.body) {
|
|
91
|
+
return createPortal(floatingButton, document.body);
|
|
92
|
+
}
|
|
93
|
+
return floatingButton;
|
|
87
94
|
}
|
|
88
95
|
export default FloatingBrandButton;
|
|
@@ -9,6 +9,8 @@ export interface ChatHeaderProps {
|
|
|
9
9
|
description?: string;
|
|
10
10
|
/** Current connection state */
|
|
11
11
|
connectionState: ConnectionState;
|
|
12
|
+
/** Marks the runtime as actively executing for busy-state animation. */
|
|
13
|
+
runtimeBusy?: boolean;
|
|
12
14
|
/** Callback when reconnect is clicked */
|
|
13
15
|
onReconnect?: () => void;
|
|
14
16
|
/** Callback when disconnect is clicked */
|
|
@@ -36,5 +38,5 @@ export interface ChatHeaderProps {
|
|
|
36
38
|
* />
|
|
37
39
|
* ```
|
|
38
40
|
*/
|
|
39
|
-
export declare function ChatHeader({ title, description, connectionState, onReconnect, onDisconnect, onLogout, onCollapsePanel, }: ChatHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
41
|
+
export declare function ChatHeader({ title, description, connectionState, runtimeBusy, onReconnect, onDisconnect, onLogout, onCollapsePanel, }: ChatHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
40
42
|
export default ChatHeader;
|
|
@@ -10,6 +10,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
*/
|
|
11
11
|
import { Text, IconButton, Button } from '@primer/react';
|
|
12
12
|
import { Box } from '@datalayer/primer-addons';
|
|
13
|
+
import { KernelIndicator, KERNEL_STATE_VISUALS, } from '@datalayer/jupyter-react';
|
|
13
14
|
import { SyncIcon, SignOutIcon, SidebarCollapseIcon, } from '@primer/octicons-react';
|
|
14
15
|
/**
|
|
15
16
|
* Chat header component with connection status indicator.
|
|
@@ -29,13 +30,17 @@ import { SyncIcon, SignOutIcon, SidebarCollapseIcon, } from '@primer/octicons-re
|
|
|
29
30
|
* />
|
|
30
31
|
* ```
|
|
31
32
|
*/
|
|
32
|
-
export function ChatHeader({ title, description, connectionState, onReconnect, onDisconnect, onLogout, onCollapsePanel, }) {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
export function ChatHeader({ title, description, connectionState, runtimeBusy = false, onReconnect, onDisconnect, onLogout, onCollapsePanel, }) {
|
|
34
|
+
const indicatorState = connectionState === 'connected'
|
|
35
|
+
? runtimeBusy
|
|
36
|
+
? 'connected-busy'
|
|
37
|
+
: 'connected-idle'
|
|
38
|
+
: connectionState === 'connecting'
|
|
39
|
+
? 'connecting'
|
|
40
|
+
: connectionState === 'error'
|
|
41
|
+
? 'connected-dead'
|
|
42
|
+
: 'disconnected';
|
|
43
|
+
const statusColor = KERNEL_STATE_VISUALS[indicatorState].color;
|
|
39
44
|
const labels = {
|
|
40
45
|
connected: 'Connected',
|
|
41
46
|
connecting: 'Connecting...',
|
|
@@ -56,11 +61,9 @@ export function ChatHeader({ title, description, connectionState, onReconnect, o
|
|
|
56
61
|
gap: 2,
|
|
57
62
|
fontSize: 0,
|
|
58
63
|
}, children: [_jsx(Box, { sx: {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
backgroundColor: colors[connectionState],
|
|
63
|
-
} }), _jsx(Text, { sx: { color: colors[connectionState] }, children: labels[connectionState] }), (connectionState === 'disconnected' ||
|
|
64
|
+
display: 'inline-flex',
|
|
65
|
+
alignItems: 'center',
|
|
66
|
+
}, children: _jsx(KernelIndicator, { state: indicatorState }) }), _jsx(Text, { sx: { color: statusColor }, children: labels[connectionState] }), (connectionState === 'disconnected' ||
|
|
64
67
|
connectionState === 'error') &&
|
|
65
68
|
onReconnect && (_jsx(IconButton, { icon: SyncIcon, "aria-label": "Reconnect", size: "small", variant: "invisible", onClick: onReconnect }))] }), onDisconnect && connectionState === 'connected' && (_jsx(Button, { variant: "invisible", size: "small", onClick: onDisconnect, children: "Disconnect" })), onLogout && (_jsx(IconButton, { icon: SignOutIcon, "aria-label": "Logout", size: "small", variant: "invisible", onClick: onLogout })), onCollapsePanel && (_jsx(IconButton, { icon: SidebarCollapseIcon, "aria-label": "Collapse panel", size: "small", variant: "invisible", onClick: onCollapsePanel }))] }) }));
|
|
66
69
|
}
|
|
@@ -8,20 +8,44 @@
|
|
|
8
8
|
* @module chat/header/ChatHeaderBase
|
|
9
9
|
*/
|
|
10
10
|
import { type ReactNode } from 'react';
|
|
11
|
+
import { type ExecutionState } from '@datalayer/jupyter-react';
|
|
12
|
+
import type { IKernelConnection } from '@jupyterlab/services/lib/kernel/kernel';
|
|
11
13
|
import type { ChatViewMode, HeaderButtonsConfig } from '../../types/chat';
|
|
12
14
|
import type { SandboxStatusData } from '../../types/context';
|
|
15
|
+
import type { SandboxWsStatus } from '../../types/sandbox';
|
|
16
|
+
type RuntimeStatus = SandboxStatusData | SandboxWsStatus;
|
|
17
|
+
export declare function toRuntimeExecutionState(runtimeStatus?: RuntimeStatus | null): ExecutionState | undefined;
|
|
13
18
|
export interface ChatBaseHeaderProps {
|
|
14
19
|
title?: string;
|
|
20
|
+
subtitle?: string;
|
|
15
21
|
brandIcon?: ReactNode;
|
|
16
22
|
headerContent?: ReactNode;
|
|
17
23
|
headerActions?: ReactNode;
|
|
18
24
|
showInformation?: boolean;
|
|
19
25
|
onInformationClick?: () => void;
|
|
20
26
|
padding: number;
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
|
|
27
|
+
/** Optional kernel indicator state override from notebook runtime. */
|
|
28
|
+
kernelIndicatorState?: ExecutionState;
|
|
29
|
+
/**
|
|
30
|
+
* Runtime status from agent-runtimes sandbox status stream.
|
|
31
|
+
* Uses the same execution-state model as KernelIndicator.
|
|
32
|
+
*/
|
|
33
|
+
runtimeStatus?: RuntimeStatus | null;
|
|
34
|
+
/**
|
|
35
|
+
* Live kernel connection from the notebook runtime. When provided,
|
|
36
|
+
* the chat header renders the same `<KernelIndicator>` as the notebook
|
|
37
|
+
* toolbar — subscribing to the kernel's live signals so the colour and
|
|
38
|
+
* tooltip stay in sync with the notebook indicator.
|
|
39
|
+
*/
|
|
40
|
+
kernel?: IKernelConnection | null;
|
|
41
|
+
/** Optional environment name shown in indicator details. */
|
|
42
|
+
kernelEnvironmentName?: string;
|
|
43
|
+
/** Optional CPU info shown in indicator details. */
|
|
44
|
+
kernelCpu?: string;
|
|
45
|
+
/** Optional memory info shown in indicator details. */
|
|
46
|
+
kernelMemory?: string;
|
|
47
|
+
/** Optional GPU info shown in indicator details. */
|
|
48
|
+
kernelGpu?: string;
|
|
25
49
|
/** Header button configuration */
|
|
26
50
|
headerButtons?: HeaderButtonsConfig;
|
|
27
51
|
/** Current count of messages (used to conditionally show clear button) */
|
|
@@ -35,4 +59,5 @@ export interface ChatBaseHeaderProps {
|
|
|
35
59
|
/** Callback when view mode changes */
|
|
36
60
|
onChatViewModeChange?: (mode: ChatViewMode) => void;
|
|
37
61
|
}
|
|
38
|
-
export declare function ChatBaseHeader({ title, brandIcon, headerContent, headerActions, showInformation, onInformationClick, padding,
|
|
62
|
+
export declare function ChatBaseHeader({ title, subtitle, brandIcon, headerContent, headerActions, showInformation, onInformationClick, padding, kernelIndicatorState, runtimeStatus, kernel, kernelEnvironmentName, kernelCpu, kernelMemory, kernelGpu, headerButtons, messageCount, onNewChat, onClear, chatViewMode, onChatViewModeChange, }: ChatBaseHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
63
|
+
export {};
|
|
@@ -1,12 +1,36 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Heading, IconButton, Truncate } from '@primer/react';
|
|
2
|
+
import { Heading, IconButton, Text, Truncate } from '@primer/react';
|
|
3
3
|
import { Box } from '@datalayer/primer-addons';
|
|
4
|
-
import {
|
|
4
|
+
import { KernelIndicator } from '@datalayer/jupyter-react';
|
|
5
|
+
import { PlusIcon, TrashIcon, GearIcon, CommentDiscussionIcon, DeviceMobileIcon, SidebarExpandIcon, InfoIcon, } from '@primer/octicons-react';
|
|
5
6
|
import { AiAgentIcon } from '@datalayer/icons-react';
|
|
7
|
+
export function toRuntimeExecutionState(runtimeStatus) {
|
|
8
|
+
if (!runtimeStatus) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
if ('available' in runtimeStatus && runtimeStatus.available === false) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
if (runtimeStatus.variant === 'unavailable' ||
|
|
15
|
+
runtimeStatus.variant === 'error') {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
if (runtimeStatus.sandbox_running === false) {
|
|
19
|
+
return 'disconnected';
|
|
20
|
+
}
|
|
21
|
+
if (runtimeStatus.is_executing === true) {
|
|
22
|
+
return 'connected-busy';
|
|
23
|
+
}
|
|
24
|
+
if (runtimeStatus.sandbox_running === true) {
|
|
25
|
+
return 'connected-idle';
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
6
29
|
// ---------------------------------------------------------------------------
|
|
7
30
|
// Component
|
|
8
31
|
// ---------------------------------------------------------------------------
|
|
9
|
-
export function ChatBaseHeader({ title, brandIcon, headerContent, headerActions, showInformation, onInformationClick, padding,
|
|
32
|
+
export function ChatBaseHeader({ title, subtitle, brandIcon, headerContent, headerActions, showInformation, onInformationClick, padding, kernelIndicatorState, runtimeStatus, kernel, kernelEnvironmentName, kernelCpu, kernelMemory, kernelGpu, headerButtons, messageCount, onNewChat, onClear, chatViewMode, onChatViewModeChange, }) {
|
|
33
|
+
const effectiveIndicatorState = kernelIndicatorState ?? toRuntimeExecutionState(runtimeStatus);
|
|
10
34
|
return (_jsx(Box, { sx: {
|
|
11
35
|
display: 'flex',
|
|
12
36
|
flexDirection: 'column',
|
|
@@ -23,21 +47,22 @@ export function ChatBaseHeader({ title, brandIcon, headerContent, headerActions,
|
|
|
23
47
|
gap: 2,
|
|
24
48
|
minWidth: 0,
|
|
25
49
|
flex: '1 1 auto',
|
|
26
|
-
}, children: [brandIcon || _jsx(AiAgentIcon, { colored: true, size: 20 }), title && (
|
|
27
|
-
|
|
28
|
-
|
|
50
|
+
}, children: [brandIcon || _jsx(AiAgentIcon, { colored: true, size: 20 }), (title || subtitle) && (_jsxs(Box, { sx: {
|
|
51
|
+
display: 'flex',
|
|
52
|
+
flexDirection: 'column',
|
|
29
53
|
minWidth: 0,
|
|
30
54
|
maxWidth: '100%',
|
|
31
|
-
}, children:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
55
|
+
}, children: [title && (_jsx(Heading, { as: "h3", sx: {
|
|
56
|
+
fontSize: 2,
|
|
57
|
+
fontWeight: 'semibold',
|
|
58
|
+
minWidth: 0,
|
|
59
|
+
maxWidth: '100%',
|
|
60
|
+
}, children: _jsx(Truncate, { title: title, maxWidth: "28ch", children: title }) })), subtitle && (_jsx(Text, { sx: {
|
|
61
|
+
fontSize: 0,
|
|
62
|
+
color: 'fg.muted',
|
|
63
|
+
minWidth: 0,
|
|
64
|
+
maxWidth: '100%',
|
|
65
|
+
}, children: _jsx(Truncate, { title: subtitle, maxWidth: "40ch", children: subtitle }) }))] })), headerContent, showInformation && (_jsx(IconButton, { icon: InfoIcon, "aria-label": "Information", variant: "invisible", size: "small", onClick: onInformationClick }))] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1, flexShrink: 0 }, children: [kernel ? (_jsx(KernelIndicator, { kernel: kernel, environmentName: kernelEnvironmentName, cpu: kernelCpu, memory: kernelMemory, gpu: kernelGpu, position: "sw", bordered: false })) : (_jsx(KernelIndicator, { state: effectiveIndicatorState ?? 'undefined', environmentName: kernelEnvironmentName, cpu: kernelCpu, memory: kernelMemory, gpu: kernelGpu, position: "sw", bordered: false })), headerButtons?.showNewChat && (_jsx(IconButton, { icon: PlusIcon, "aria-label": "New chat", variant: "invisible", size: "small", onClick: onNewChat })), headerButtons?.showClear && messageCount > 0 && (_jsx(IconButton, { icon: TrashIcon, "aria-label": "Clear messages", variant: "invisible", size: "small", onClick: onClear })), headerButtons?.showSettings && (_jsx(IconButton, { icon: GearIcon, "aria-label": "Settings", variant: "invisible", size: "small", onClick: headerButtons.onSettings })), chatViewMode && onChatViewModeChange && (_jsx(Box, { sx: {
|
|
41
66
|
display: 'inline-flex',
|
|
42
67
|
alignItems: 'center',
|
|
43
68
|
bg: 'neutral.muted',
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import type { McpToolsetsStatusResponse } from '../../types/mcp';
|
|
1
2
|
export interface McpStatusIndicatorProps {
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
3
|
+
/** Pre-fetched MCP status data pushed via WebSocket. When provided the
|
|
4
|
+
* component will NOT poll the REST endpoint. */
|
|
5
|
+
data?: McpToolsetsStatusResponse | null;
|
|
6
|
+
/** @deprecated — Only used when `data` is not provided. */
|
|
4
7
|
apiBase?: string;
|
|
5
|
-
/**
|
|
8
|
+
/** @deprecated — Only used when `data` is not provided. */
|
|
6
9
|
authToken?: string;
|
|
7
10
|
}
|
|
8
|
-
export declare function McpStatusIndicator({ apiBase, authToken, }: McpStatusIndicatorProps): import("react/jsx-runtime").JSX.Element
|
|
11
|
+
export declare function McpStatusIndicator({ data: wsData, apiBase, authToken, }: McpStatusIndicatorProps): import("react/jsx-runtime").JSX.Element;
|
|
9
12
|
export default McpStatusIndicator;
|
|
@@ -21,19 +21,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
21
21
|
import { useEffect, useMemo } from 'react';
|
|
22
22
|
import { Tooltip } from '@primer/react';
|
|
23
23
|
import { Box } from '@datalayer/primer-addons';
|
|
24
|
-
import { useQuery } from '@tanstack/react-query';
|
|
25
24
|
import { MCP_STATUS_COLORS, MCP_STATUS_LABELS } from '../../types/mcp';
|
|
26
25
|
/* ── Helpers ───────────────────────────────────────────── */
|
|
27
|
-
function getApiBase(apiBase) {
|
|
28
|
-
if (apiBase)
|
|
29
|
-
return apiBase;
|
|
30
|
-
if (typeof window === 'undefined')
|
|
31
|
-
return '';
|
|
32
|
-
const host = window.location.hostname;
|
|
33
|
-
return host === 'localhost' || host === '127.0.0.1'
|
|
34
|
-
? 'http://127.0.0.1:8765'
|
|
35
|
-
: '';
|
|
36
|
-
}
|
|
37
26
|
function deriveAggregate(servers) {
|
|
38
27
|
if (!servers || servers.length === 0)
|
|
39
28
|
return 'none';
|
|
@@ -47,7 +36,7 @@ function deriveAggregate(servers) {
|
|
|
47
36
|
}
|
|
48
37
|
function buildTooltipText(aggregate, servers) {
|
|
49
38
|
if (aggregate === 'none')
|
|
50
|
-
return
|
|
39
|
+
return 'No MCP Server defined';
|
|
51
40
|
const lines = [MCP_STATUS_LABELS[aggregate]];
|
|
52
41
|
for (const s of servers) {
|
|
53
42
|
let detail = `• ${s.id}: ${s.status}`;
|
|
@@ -79,29 +68,15 @@ function useInjectKeyframes() {
|
|
|
79
68
|
}, []);
|
|
80
69
|
}
|
|
81
70
|
/* ── Component ─────────────────────────────────────────── */
|
|
82
|
-
export function McpStatusIndicator({ apiBase, authToken, }) {
|
|
71
|
+
export function McpStatusIndicator({ data: wsData, apiBase, authToken, }) {
|
|
83
72
|
useInjectKeyframes();
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const base = getApiBase(apiBase);
|
|
88
|
-
const headers = {};
|
|
89
|
-
if (authToken) {
|
|
90
|
-
headers['Authorization'] = `Bearer ${authToken}`;
|
|
91
|
-
}
|
|
92
|
-
const response = await fetch(`${base}/api/v1/configure/mcp-toolsets-status`, { headers });
|
|
93
|
-
if (!response.ok)
|
|
94
|
-
throw new Error('Failed to fetch MCP status');
|
|
95
|
-
return response.json();
|
|
96
|
-
},
|
|
97
|
-
refetchInterval: 5000,
|
|
98
|
-
});
|
|
99
|
-
const servers = data?.servers ?? [];
|
|
73
|
+
// REST polling removed — data comes exclusively via WS `agent.snapshot`.
|
|
74
|
+
const effectiveData = wsData;
|
|
75
|
+
const servers = effectiveData?.servers ?? [];
|
|
100
76
|
const aggregate = useMemo(() => deriveAggregate(servers), [servers]);
|
|
101
77
|
const tooltipText = useMemo(() => buildTooltipText(aggregate, servers), [aggregate, servers]);
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
return null;
|
|
78
|
+
// Show a subtle gray dot when no MCP servers are configured.
|
|
79
|
+
// The tooltip tells the user none are defined.
|
|
105
80
|
return (_jsx(Tooltip, { text: tooltipText, direction: "n", children: _jsx("button", { type: "button", "aria-label": tooltipText, style: {
|
|
106
81
|
display: 'inline-flex',
|
|
107
82
|
alignItems: 'center',
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SandboxWsStatus } from '../../types/sandbox';
|
|
1
2
|
export interface SandboxStatusIndicatorProps {
|
|
2
3
|
/** API base URL (e.g. "http://127.0.0.1:8765"). */
|
|
3
4
|
apiBase?: string;
|
|
@@ -5,6 +6,8 @@ export interface SandboxStatusIndicatorProps {
|
|
|
5
6
|
authToken?: string;
|
|
6
7
|
/** Agent ID to scope sandbox status to a specific agent. */
|
|
7
8
|
agentId?: string;
|
|
9
|
+
/** Optional status override to update indicator immediately from parent UI. */
|
|
10
|
+
statusOverride?: SandboxWsStatus | null;
|
|
8
11
|
}
|
|
9
|
-
export declare function SandboxStatusIndicator({ apiBase, authToken, agentId, }: SandboxStatusIndicatorProps): import("react/jsx-runtime").JSX.Element
|
|
12
|
+
export declare function SandboxStatusIndicator({ apiBase, authToken, agentId, statusOverride, }: SandboxStatusIndicatorProps): import("react/jsx-runtime").JSX.Element;
|
|
10
13
|
export default SandboxStatusIndicator;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
/*
|
|
3
3
|
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
@@ -7,12 +7,12 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
7
7
|
* SandboxStatusIndicator — Round coloured dot that shows the
|
|
8
8
|
* real-time sandbox execution status via a WebSocket connection.
|
|
9
9
|
*
|
|
10
|
-
* Aggregate logic
|
|
10
|
+
* Aggregate logic (mapped to jupyter-react KernelIndicator states)
|
|
11
11
|
* ───────────────
|
|
12
|
-
* - variant === "unavailable" →
|
|
13
|
-
* - sandbox_running === false →
|
|
14
|
-
* - is_executing === false →
|
|
15
|
-
* - is_executing === true →
|
|
12
|
+
* - variant === "unavailable" → connected-unknown
|
|
13
|
+
* - sandbox_running === false → disconnected
|
|
14
|
+
* - is_executing === false → connected-idle
|
|
15
|
+
* - is_executing === true → connected-busy (themed fade animation)
|
|
16
16
|
*
|
|
17
17
|
* The component connects to the `/configure/sandbox/ws` WebSocket
|
|
18
18
|
* and receives status updates in real time. It can also send
|
|
@@ -21,9 +21,14 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
21
21
|
* @module chat/indicators/SandboxStatusIndicator
|
|
22
22
|
*/
|
|
23
23
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
24
|
-
import { Tooltip } from '@primer/react';
|
|
25
24
|
import { Box } from '@datalayer/primer-addons';
|
|
26
|
-
import {
|
|
25
|
+
import { SANDBOX_STATUS_LABELS } from '../../types/sandbox';
|
|
26
|
+
const SANDBOX_INDICATOR_COLORS = {
|
|
27
|
+
unavailable: 'fg.muted',
|
|
28
|
+
stopped: 'fg.muted',
|
|
29
|
+
idle: 'success.fg',
|
|
30
|
+
executing: 'attention.fg',
|
|
31
|
+
};
|
|
27
32
|
/* ── Helpers ───────────────────────────────────────────── */
|
|
28
33
|
function getWsUrl(apiBase, authToken, agentId) {
|
|
29
34
|
if (typeof window === 'undefined')
|
|
@@ -63,27 +68,39 @@ function deriveAggregate(status) {
|
|
|
63
68
|
return 'executing';
|
|
64
69
|
return 'idle';
|
|
65
70
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
function renderSandboxGlyph(aggregate) {
|
|
72
|
+
return (_jsx(Box, { as: "span", sx: {
|
|
73
|
+
display: 'inline-block',
|
|
74
|
+
width: 10,
|
|
75
|
+
height: 10,
|
|
76
|
+
borderRadius: '50%',
|
|
77
|
+
bg: SANDBOX_INDICATOR_COLORS[aggregate],
|
|
78
|
+
...(aggregate === 'executing' && {
|
|
79
|
+
animation: 'sandbox-busy-fade 1.2s ease-in-out infinite',
|
|
80
|
+
'@keyframes sandbox-busy-fade': {
|
|
81
|
+
'0%': {
|
|
82
|
+
opacity: 1,
|
|
83
|
+
transform: 'scale(1)',
|
|
84
|
+
filter: 'saturate(1)',
|
|
85
|
+
},
|
|
86
|
+
'50%': {
|
|
87
|
+
opacity: 0.45,
|
|
88
|
+
transform: 'scale(0.92)',
|
|
89
|
+
filter: 'saturate(0.75)',
|
|
90
|
+
},
|
|
91
|
+
'100%': {
|
|
92
|
+
opacity: 1,
|
|
93
|
+
transform: 'scale(1)',
|
|
94
|
+
filter: 'saturate(1)',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
98
|
+
} }));
|
|
82
99
|
}
|
|
83
100
|
/* ── Component ─────────────────────────────────────────── */
|
|
84
|
-
export function SandboxStatusIndicator({ apiBase, authToken, agentId, }) {
|
|
85
|
-
useInjectKeyframes();
|
|
101
|
+
export function SandboxStatusIndicator({ apiBase, authToken, agentId, statusOverride, }) {
|
|
86
102
|
const [status, setStatus] = useState(null);
|
|
103
|
+
const [isOverlayOpen, setIsOverlayOpen] = useState(false);
|
|
87
104
|
const wsRef = useRef(null);
|
|
88
105
|
const reconnectTimerRef = useRef();
|
|
89
106
|
const wsUrl = useMemo(() => getWsUrl(apiBase, authToken, agentId), [apiBase, authToken, agentId]);
|
|
@@ -138,38 +155,56 @@ export function SandboxStatusIndicator({ apiBase, authToken, agentId, }) {
|
|
|
138
155
|
}
|
|
139
156
|
}, []);
|
|
140
157
|
// ---- Derived display values ----
|
|
141
|
-
const
|
|
158
|
+
const effectiveStatus = statusOverride ?? status;
|
|
159
|
+
const aggregate = useMemo(() => deriveAggregate(effectiveStatus), [effectiveStatus]);
|
|
142
160
|
const tooltipText = useMemo(() => {
|
|
143
|
-
if (!
|
|
144
|
-
return
|
|
161
|
+
if (!effectiveStatus)
|
|
162
|
+
return 'No Sandbox defined';
|
|
145
163
|
const label = SANDBOX_STATUS_LABELS[aggregate];
|
|
146
|
-
const variant =
|
|
164
|
+
const variant = effectiveStatus.variant;
|
|
147
165
|
return `${label} (${variant})`;
|
|
148
|
-
}, [aggregate,
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
borderRadius:
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
166
|
+
}, [aggregate, effectiveStatus]);
|
|
167
|
+
// Show a subtle gray dot when sandbox is unavailable.
|
|
168
|
+
// The tooltip tells the user none is configured.
|
|
169
|
+
return (_jsxs(Box, { as: "span", sx: {
|
|
170
|
+
position: 'relative',
|
|
171
|
+
display: 'inline-flex',
|
|
172
|
+
alignItems: 'center',
|
|
173
|
+
justifyContent: 'center',
|
|
174
|
+
}, onMouseEnter: () => setIsOverlayOpen(true), onMouseLeave: () => setIsOverlayOpen(false), children: [_jsx("button", { type: "button", "aria-label": tooltipText, onClick: aggregate === 'executing' ? sendInterrupt : undefined, onFocus: () => setIsOverlayOpen(true), onBlur: () => setIsOverlayOpen(false), style: {
|
|
175
|
+
display: 'inline-flex',
|
|
176
|
+
alignItems: 'center',
|
|
177
|
+
justifyContent: 'center',
|
|
178
|
+
width: 28,
|
|
179
|
+
height: 28,
|
|
180
|
+
padding: 0,
|
|
181
|
+
border: 'none',
|
|
182
|
+
background: 'none',
|
|
183
|
+
outline: 'none',
|
|
184
|
+
boxShadow: 'none',
|
|
185
|
+
borderRadius: 0,
|
|
186
|
+
WebkitAppearance: 'none',
|
|
187
|
+
appearance: 'none',
|
|
188
|
+
cursor: aggregate === 'executing' ? 'pointer' : 'default',
|
|
189
|
+
lineHeight: 0,
|
|
190
|
+
}, children: _jsx(Box, { as: "span", sx: { display: 'inline-flex', alignItems: 'center', flexShrink: 0 }, children: renderSandboxGlyph(aggregate) }) }), isOverlayOpen && (_jsxs(Box, { role: "tooltip", sx: {
|
|
191
|
+
position: 'absolute',
|
|
192
|
+
right: 0,
|
|
193
|
+
top: 'calc(100% + 6px)',
|
|
194
|
+
minWidth: 220,
|
|
195
|
+
px: 2,
|
|
196
|
+
py: 2,
|
|
197
|
+
borderRadius: 2,
|
|
198
|
+
bg: 'canvas.overlay',
|
|
199
|
+
color: 'fg.default',
|
|
200
|
+
fontSize: 0,
|
|
201
|
+
lineHeight: 1.5,
|
|
202
|
+
boxShadow: 'shadow.medium',
|
|
203
|
+
border: '1px solid',
|
|
204
|
+
borderColor: 'border.default',
|
|
205
|
+
zIndex: 1000,
|
|
206
|
+
fontFamily: 'mono',
|
|
207
|
+
pointerEvents: 'none',
|
|
208
|
+
}, children: [_jsx(Box, { sx: { mb: 1, fontWeight: 600, fontFamily: 'normal' }, children: tooltipText }), effectiveStatus ? (_jsxs(_Fragment, { children: [_jsxs(Box, { children: [_jsxs(Box, { as: "span", sx: { fontWeight: 600 }, children: ["variant:", ' '] }), _jsx(Box, { as: "span", children: effectiveStatus.variant })] }), _jsxs(Box, { children: [_jsxs(Box, { as: "span", sx: { fontWeight: 600 }, children: ["sandbox_running:", ' '] }), _jsx(Box, { as: "span", children: String(effectiveStatus.sandbox_running) })] }), _jsxs(Box, { children: [_jsxs(Box, { as: "span", sx: { fontWeight: 600 }, children: ["is_executing:", ' '] }), _jsx(Box, { as: "span", children: String(effectiveStatus.is_executing) })] }), effectiveStatus.jupyter_url && (_jsxs(Box, { sx: { wordBreak: 'break-all' }, children: [_jsxs(Box, { as: "span", sx: { fontWeight: 600 }, children: ["jupyter_url:", ' '] }), _jsx(Box, { as: "span", children: effectiveStatus.jupyter_url })] })), effectiveStatus.error && (_jsx(Box, { sx: { mt: 1, color: 'danger.fg' }, children: effectiveStatus.error })), aggregate === 'executing' && (_jsx(Box, { sx: { mt: 1, fontFamily: 'normal', color: 'fg.muted' }, children: "Click to interrupt execution" }))] })) : (_jsx(Box, { sx: { fontFamily: 'normal', color: 'fg.muted' }, children: "No sandbox configured for this agent." }))] }))] }));
|
|
174
209
|
}
|
|
175
210
|
export default SandboxStatusIndicator;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface SkillsStatusIndicatorProps {
|
|
2
|
+
skillsCount: number;
|
|
3
|
+
enabledCount: number;
|
|
4
|
+
loading?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function SkillsStatusIndicator({ skillsCount, enabledCount, loading, }: SkillsStatusIndicatorProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export default SkillsStatusIndicator;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* SkillsStatusIndicator — Round status dot representing skill state.
|
|
8
|
+
*
|
|
9
|
+
* Aggregate logic:
|
|
10
|
+
* - no skills configured -> none (gray)
|
|
11
|
+
* - skills loading -> loading (amber, pulsing)
|
|
12
|
+
* - some enabled -> active (green)
|
|
13
|
+
* - none enabled -> inactive (gray)
|
|
14
|
+
*/
|
|
15
|
+
import { useEffect, useMemo } from 'react';
|
|
16
|
+
import { Tooltip } from '@primer/react';
|
|
17
|
+
import { Box } from '@datalayer/primer-addons';
|
|
18
|
+
const SKILLS_STATUS_COLORS = {
|
|
19
|
+
none: '#8b949e',
|
|
20
|
+
loading: '#d29922',
|
|
21
|
+
inactive: '#8b949e',
|
|
22
|
+
active: '#3fb950',
|
|
23
|
+
};
|
|
24
|
+
const SKILLS_PULSE_KEYFRAMES = `
|
|
25
|
+
@keyframes skills-pulse {
|
|
26
|
+
0%, 100% { opacity: 1; }
|
|
27
|
+
50% { opacity: 0.4; }
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
function useInjectKeyframes() {
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const id = '__skills-pulse-keyframes__';
|
|
33
|
+
if (document.getElementById(id))
|
|
34
|
+
return;
|
|
35
|
+
const style = document.createElement('style');
|
|
36
|
+
style.id = id;
|
|
37
|
+
style.textContent = SKILLS_PULSE_KEYFRAMES;
|
|
38
|
+
document.head.appendChild(style);
|
|
39
|
+
}, []);
|
|
40
|
+
}
|
|
41
|
+
function deriveAggregate(skillsCount, enabledCount, loading) {
|
|
42
|
+
if (skillsCount <= 0)
|
|
43
|
+
return 'none';
|
|
44
|
+
if (loading)
|
|
45
|
+
return 'loading';
|
|
46
|
+
if (enabledCount > 0)
|
|
47
|
+
return 'active';
|
|
48
|
+
return 'inactive';
|
|
49
|
+
}
|
|
50
|
+
function buildTooltip(aggregate, skillsCount, enabledCount) {
|
|
51
|
+
if (aggregate === 'none')
|
|
52
|
+
return 'No Skills defined';
|
|
53
|
+
if (aggregate === 'loading') {
|
|
54
|
+
return `Skills loading (${enabledCount}/${skillsCount} enabled)`;
|
|
55
|
+
}
|
|
56
|
+
if (aggregate === 'active') {
|
|
57
|
+
return `Skills active (${enabledCount}/${skillsCount} enabled)`;
|
|
58
|
+
}
|
|
59
|
+
return `Skills available (${enabledCount}/${skillsCount} enabled)`;
|
|
60
|
+
}
|
|
61
|
+
export function SkillsStatusIndicator({ skillsCount, enabledCount, loading = false, }) {
|
|
62
|
+
useInjectKeyframes();
|
|
63
|
+
const aggregate = useMemo(() => deriveAggregate(skillsCount, enabledCount, loading), [skillsCount, enabledCount, loading]);
|
|
64
|
+
const tooltipText = useMemo(() => buildTooltip(aggregate, skillsCount, enabledCount), [aggregate, skillsCount, enabledCount]);
|
|
65
|
+
return (_jsx(Tooltip, { text: tooltipText, direction: "n", children: _jsx("button", { type: "button", "aria-label": tooltipText, style: {
|
|
66
|
+
display: 'inline-flex',
|
|
67
|
+
alignItems: 'center',
|
|
68
|
+
justifyContent: 'center',
|
|
69
|
+
width: 28,
|
|
70
|
+
height: 28,
|
|
71
|
+
padding: 0,
|
|
72
|
+
border: 'none',
|
|
73
|
+
background: 'none',
|
|
74
|
+
cursor: 'default',
|
|
75
|
+
lineHeight: 0,
|
|
76
|
+
}, children: _jsx(Box, { as: "span", sx: {
|
|
77
|
+
display: 'inline-block',
|
|
78
|
+
width: 12,
|
|
79
|
+
height: 12,
|
|
80
|
+
borderRadius: '50%',
|
|
81
|
+
bg: SKILLS_STATUS_COLORS[aggregate],
|
|
82
|
+
flexShrink: 0,
|
|
83
|
+
...(aggregate === 'loading' && {
|
|
84
|
+
animation: 'skills-pulse 1.5s ease-in-out infinite',
|
|
85
|
+
}),
|
|
86
|
+
} }) }) }));
|
|
87
|
+
}
|
|
88
|
+
export default SkillsStatusIndicator;
|
|
@@ -15,3 +15,4 @@ export { McpStatusIndicator, type McpStatusIndicatorProps, } from './McpStatusIn
|
|
|
15
15
|
export type { McpServerStatus, McpAggregateStatus } from '../../types/mcp';
|
|
16
16
|
export { SandboxStatusIndicator, type SandboxStatusIndicatorProps, } from './SandboxStatusIndicator';
|
|
17
17
|
export type { SandboxAggregateStatus, SandboxWsStatus, } from '../../types/sandbox';
|
|
18
|
+
export { SkillsStatusIndicator, type SkillsStatusIndicatorProps, } from './SkillsStatusIndicator';
|