@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
package/lib/AgentNode.js
ADDED
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
7
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
8
|
+
import { Box, DatalayerLogoText, DatalayerThemeProvider, getLogoColors, setupPrimerPortals, themeConfigs, } from '@datalayer/primer-addons';
|
|
9
|
+
import { AppearanceControlsWithStore } from '@datalayer/primer-addons/lib/components/appearance';
|
|
10
|
+
import { ActionList, ActionMenu, Avatar, Button, FormControl, Heading, Label, PageHeader, PageLayout, Text, } from '@primer/react';
|
|
11
|
+
import { CommentIcon, HomeIcon, KeyAsteriskIcon, LockIcon, MoonIcon, PeopleIcon, PersonIcon, GearIcon, SignInIcon, SignOutIcon, } from '@primer/octicons-react';
|
|
12
|
+
import { SignInSimple } from '@datalayer/core/lib/views/iam';
|
|
13
|
+
import { UserBadge } from '@datalayer/core/lib/views/profile';
|
|
14
|
+
import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel';
|
|
15
|
+
import { useIAMStore } from '@datalayer/core/lib/state';
|
|
16
|
+
import { BillableAccountSelect, } from '@datalayer/core/lib/components/billing';
|
|
17
|
+
import { ShareAccessComponent } from '@datalayer/core/lib/components/sharing';
|
|
18
|
+
import { useAgentNodeThemeStore } from './agent-node/themeStore';
|
|
19
|
+
import { Chat } from './chat';
|
|
20
|
+
import '../style/primer-primitives.css';
|
|
21
|
+
setupPrimerPortals();
|
|
22
|
+
const AGENT_RUNTIMES_BASE_URL = (import.meta.env.VITE_DATALAYER_AGENT_RUNTIMES_URL ||
|
|
23
|
+
import.meta.env.VITE_BASE_URL ||
|
|
24
|
+
window.location.origin).replace(/\/$/, '');
|
|
25
|
+
const MODE_CARDS = [
|
|
26
|
+
{
|
|
27
|
+
mode: 'private',
|
|
28
|
+
name: 'Private',
|
|
29
|
+
description: 'Only you can use this Agent Node. Chat can be done directly from this node or from any supported Datalayer platform such as SaaS, VS Code, JupyterLab, or CLI.',
|
|
30
|
+
Icon: LockIcon,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
mode: 'shared',
|
|
34
|
+
name: 'Shared',
|
|
35
|
+
description: 'Allowed users can consume chat from any supported Datalayer platform such as SaaS, VS Code, JupyterLab, or CLI.',
|
|
36
|
+
Icon: PeopleIcon,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
mode: 'sleep',
|
|
40
|
+
name: 'Sleep',
|
|
41
|
+
description: 'The Agent Node stays registered and visible but does not accept new chat sessions. Existing sessions are not resumed until you switch back to Private or Shared.',
|
|
42
|
+
Icon: MoonIcon,
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
const DEFAULT_CONFIGURATION = {
|
|
46
|
+
mode: 'sleep',
|
|
47
|
+
sharing: {},
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Profile view rendered inside AgentNode when the user picks "Profile" from
|
|
51
|
+
* the header menu. Mirrors the shape of `ui/src/views/profile/UserProfileBase`
|
|
52
|
+
* but assembled exclusively from core building blocks so agent-runtimes does
|
|
53
|
+
* not pull in the `ui` package.
|
|
54
|
+
*/
|
|
55
|
+
function AgentNodeProfileView({ token }) {
|
|
56
|
+
const user = useIAMStore(state => state.user);
|
|
57
|
+
const display = useMemo(() => {
|
|
58
|
+
if (!user)
|
|
59
|
+
return null;
|
|
60
|
+
const u = user;
|
|
61
|
+
const displayName = [u.first_name, u.last_name].filter(Boolean).join(' ').trim() ||
|
|
62
|
+
u.display_name ||
|
|
63
|
+
u.name ||
|
|
64
|
+
u.handle ||
|
|
65
|
+
u.email ||
|
|
66
|
+
'Datalayer user';
|
|
67
|
+
const username = u.username || u.handle || (u.email ? String(u.email).split('@')[0] : '');
|
|
68
|
+
const initials = u.initials ||
|
|
69
|
+
String(displayName)
|
|
70
|
+
.split(/\s+/)
|
|
71
|
+
.filter(Boolean)
|
|
72
|
+
.slice(0, 2)
|
|
73
|
+
.map((part) => part[0]?.toUpperCase() || '')
|
|
74
|
+
.join('');
|
|
75
|
+
return {
|
|
76
|
+
id: String(u.id || u.uid || ''),
|
|
77
|
+
username,
|
|
78
|
+
displayName,
|
|
79
|
+
initials,
|
|
80
|
+
origin: String(u.origin || 'datalayer'),
|
|
81
|
+
handle: u.handle ? `@${u.handle}` : '',
|
|
82
|
+
email: u.email || '',
|
|
83
|
+
avatarUrl: u.avatar_url || u.profile?.avatar_url || '',
|
|
84
|
+
roles: Array.isArray(u.roles) ? u.roles : [],
|
|
85
|
+
};
|
|
86
|
+
}, [user]);
|
|
87
|
+
return (_jsx(Box, { sx: {
|
|
88
|
+
border: '1px solid',
|
|
89
|
+
borderColor: 'border.default',
|
|
90
|
+
borderRadius: 2,
|
|
91
|
+
p: 4,
|
|
92
|
+
display: 'flex',
|
|
93
|
+
flexDirection: 'column',
|
|
94
|
+
gap: 3,
|
|
95
|
+
}, children: !token ? (_jsx(Text, { sx: { color: 'fg.muted' }, children: "Sign in to view your profile." })) : !display ? (_jsx(Text, { sx: { color: 'fg.muted' }, children: "Loading profile\u2026" })) : (_jsxs(_Fragment, { children: [_jsx(Heading, { sx: { fontSize: 2, mb: 2 }, children: "Identity" }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 3 }, children: [display.avatarUrl ? (_jsx(Avatar, { src: display.avatarUrl, size: 72, alt: display.displayName })) : (_jsx(Box, { sx: {
|
|
96
|
+
width: 72,
|
|
97
|
+
height: 72,
|
|
98
|
+
borderRadius: '50%',
|
|
99
|
+
bg: 'canvas.subtle',
|
|
100
|
+
display: 'inline-flex',
|
|
101
|
+
alignItems: 'center',
|
|
102
|
+
justifyContent: 'center',
|
|
103
|
+
color: 'fg.muted',
|
|
104
|
+
}, children: _jsx(PersonIcon, { size: 30 }) })), _jsxs(Box, { sx: { display: 'flex', flexDirection: 'column' }, children: [_jsx(Heading, { sx: { fontSize: 3, mb: 1 }, children: display.displayName }), display.handle && (_jsx(Text, { sx: { color: 'fg.muted' }, children: display.handle })), display.email && (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: display.email }))] })] }), display.id && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(Label, { size: "large", variant: "secondary", children: display.id }) })), _jsxs(Box, { sx: {
|
|
105
|
+
display: 'grid',
|
|
106
|
+
gridTemplateColumns: '1fr 2fr',
|
|
107
|
+
rowGap: 2,
|
|
108
|
+
columnGap: 3,
|
|
109
|
+
maxWidth: 560,
|
|
110
|
+
}, children: [_jsx(Text, { sx: { fontWeight: 'bold' }, children: "Username" }), _jsx(Text, { children: display.username || '-' }), _jsx(Text, { sx: { fontWeight: 'bold' }, children: "Display name" }), _jsx(Text, { children: display.displayName || '-' }), _jsx(Text, { sx: { fontWeight: 'bold' }, children: "Initials" }), _jsx(Text, { children: display.initials || '-' }), _jsx(Text, { sx: { fontWeight: 'bold' }, children: "Origin" }), _jsx(Text, { children: display.origin || '-' })] }), display.roles.length > 0 && (_jsx(Box, { sx: { display: 'flex', gap: 2, flexWrap: 'wrap' }, children: display.roles.map(role => (_jsx(Label, { size: "small", variant: "secondary", children: role }, role))) }))] })) }));
|
|
111
|
+
}
|
|
112
|
+
export function AgentNode() {
|
|
113
|
+
const { token, setAuth, clearAuth } = useSimpleAuthStore();
|
|
114
|
+
const tokenForCore = token ?? undefined;
|
|
115
|
+
const queryClient = useQueryClient();
|
|
116
|
+
const iamUser = useIAMStore(state => state.user);
|
|
117
|
+
const { colorMode, theme: themeVariant } = useAgentNodeThemeStore();
|
|
118
|
+
const cfg = themeConfigs[themeVariant];
|
|
119
|
+
const logoColors = getLogoColors(themeVariant, colorMode);
|
|
120
|
+
const resolvedMode = colorMode === 'auto'
|
|
121
|
+
? typeof window !== 'undefined' &&
|
|
122
|
+
window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
123
|
+
? 'dark'
|
|
124
|
+
: 'light'
|
|
125
|
+
: colorMode === 'dark'
|
|
126
|
+
? 'dark'
|
|
127
|
+
: 'light';
|
|
128
|
+
const authGradient = cfg.cardGradient[resolvedMode];
|
|
129
|
+
const [step, setStep] = useState('auth');
|
|
130
|
+
const [disableAutoBootstrap, setDisableAutoBootstrap] = useState(false);
|
|
131
|
+
const [configuration, setConfiguration] = useState(DEFAULT_CONFIGURATION);
|
|
132
|
+
const [, setSelectedBillableAccount] = useState(undefined);
|
|
133
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
134
|
+
const [error, setError] = useState(null);
|
|
135
|
+
const [inferenceProvider, setInferenceProvider] = useState('datalayer');
|
|
136
|
+
const [inferenceModels, setInferenceModels] = useState([]);
|
|
137
|
+
const [inferenceDefaultModel, setInferenceDefaultModel] = useState(null);
|
|
138
|
+
const [banner, setBanner] = useState(null);
|
|
139
|
+
const bannerTimerRef = useRef(null);
|
|
140
|
+
const showBanner = useCallback((kind, message) => {
|
|
141
|
+
if (bannerTimerRef.current) {
|
|
142
|
+
clearTimeout(bannerTimerRef.current);
|
|
143
|
+
bannerTimerRef.current = null;
|
|
144
|
+
}
|
|
145
|
+
const id = Date.now();
|
|
146
|
+
setBanner({ id, kind, message });
|
|
147
|
+
const duration = kind === 'error' ? 6000 : 3500;
|
|
148
|
+
bannerTimerRef.current = setTimeout(() => {
|
|
149
|
+
setBanner(current => (current && current.id === id ? null : current));
|
|
150
|
+
bannerTimerRef.current = null;
|
|
151
|
+
}, duration);
|
|
152
|
+
}, []);
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
return () => {
|
|
155
|
+
if (bannerTimerRef.current) {
|
|
156
|
+
clearTimeout(bannerTimerRef.current);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}, []);
|
|
160
|
+
const pushCredentials = useCallback((authToken, payloadToken = authToken) => {
|
|
161
|
+
const runUrl = import.meta.env?.VITE_DATALAYER_RUN_URL ||
|
|
162
|
+
'https://prod1.datalayer.run';
|
|
163
|
+
const runtimesRunUrl = import.meta.env?.VITE_DATALAYER_RUNTIMES_URL || runUrl;
|
|
164
|
+
const headers = {
|
|
165
|
+
'Content-Type': 'application/json',
|
|
166
|
+
};
|
|
167
|
+
if (authToken) {
|
|
168
|
+
headers.Authorization = `Bearer ${authToken}`;
|
|
169
|
+
}
|
|
170
|
+
return fetch(`${AGENT_RUNTIMES_BASE_URL}/api/v1/agent-node/credentials`, {
|
|
171
|
+
method: 'POST',
|
|
172
|
+
headers,
|
|
173
|
+
body: JSON.stringify({
|
|
174
|
+
token: payloadToken || null,
|
|
175
|
+
runtimes_url: payloadToken ? runtimesRunUrl : null,
|
|
176
|
+
}),
|
|
177
|
+
});
|
|
178
|
+
}, []);
|
|
179
|
+
// Refs kept in sync with state so the BillableAccountSelect callbacks
|
|
180
|
+
// (passed via stable identities) can read the latest values without
|
|
181
|
+
// being re-created on every render — re-created callbacks made
|
|
182
|
+
// BillableAccountSelect re-fire onAccountsResolved and trigger an
|
|
183
|
+
// infinite setState loop.
|
|
184
|
+
const configurationRef = useRef(configuration);
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
configurationRef.current = configuration;
|
|
187
|
+
}, [configuration]);
|
|
188
|
+
const iamUserRef = useRef(iamUser);
|
|
189
|
+
useEffect(() => {
|
|
190
|
+
iamUserRef.current = iamUser;
|
|
191
|
+
}, [iamUser]);
|
|
192
|
+
const handleBillableAccountChange = useCallback((uid) => {
|
|
193
|
+
setConfiguration(prev => ({ ...prev, billable_account_uid: uid }));
|
|
194
|
+
}, []);
|
|
195
|
+
const handleSelectedAccountChange = useCallback((account) => {
|
|
196
|
+
setSelectedBillableAccount(account);
|
|
197
|
+
setConfiguration(prev => ({
|
|
198
|
+
...prev,
|
|
199
|
+
billable_account_type: account?.accountType,
|
|
200
|
+
billable_account_handle: account?.accountHandle,
|
|
201
|
+
}));
|
|
202
|
+
}, []);
|
|
203
|
+
const handleAccountsResolved = useCallback((_state) => {
|
|
204
|
+
// BillableAccountSelect persists the chosen account in a cookie and
|
|
205
|
+
// falls back to the personal account when none is stored, so the node
|
|
206
|
+
// no longer needs to force an organization default here.
|
|
207
|
+
}, []);
|
|
208
|
+
const handleSharingInlineClose = useCallback(() => {
|
|
209
|
+
// Inline mode has no close action, but the prop is required.
|
|
210
|
+
}, []);
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
const load = async () => {
|
|
213
|
+
try {
|
|
214
|
+
const response = await fetch(`${AGENT_RUNTIMES_BASE_URL}/api/v1/agent-node/configuration`);
|
|
215
|
+
if (!response.ok) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const payload = await response.json();
|
|
219
|
+
const loadedConfiguration = {
|
|
220
|
+
...DEFAULT_CONFIGURATION,
|
|
221
|
+
...(payload?.configuration || {}),
|
|
222
|
+
};
|
|
223
|
+
setConfiguration(loadedConfiguration);
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
// Ignore initial-load failures in local development.
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
load();
|
|
230
|
+
}, []);
|
|
231
|
+
useEffect(() => {
|
|
232
|
+
const loadInferenceProvider = async () => {
|
|
233
|
+
try {
|
|
234
|
+
const response = await fetch(`${AGENT_RUNTIMES_BASE_URL}/api/v1/configure/inference/provider`);
|
|
235
|
+
if (!response.ok) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const payload = await response.json();
|
|
239
|
+
const provider = payload?.provider;
|
|
240
|
+
if (provider === 'local' || provider === 'datalayer') {
|
|
241
|
+
setInferenceProvider(provider);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
// Ignore initial-load failures in local development.
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
loadInferenceProvider();
|
|
249
|
+
}, []);
|
|
250
|
+
useEffect(() => {
|
|
251
|
+
if (inferenceProvider !== 'datalayer') {
|
|
252
|
+
setInferenceModels([]);
|
|
253
|
+
setInferenceDefaultModel(null);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const loadInferenceModels = async () => {
|
|
257
|
+
try {
|
|
258
|
+
const response = await fetch(`${AGENT_RUNTIMES_BASE_URL}/api/v1/configure/inference/models`);
|
|
259
|
+
if (!response.ok) {
|
|
260
|
+
setInferenceModels([]);
|
|
261
|
+
setInferenceDefaultModel(null);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const payload = await response.json();
|
|
265
|
+
const fromModels = Array.isArray(payload.models)
|
|
266
|
+
? payload.models.filter(Boolean)
|
|
267
|
+
: [];
|
|
268
|
+
const fromBedrock = Array.isArray(payload.bedrock_anthropic_models)
|
|
269
|
+
? payload.bedrock_anthropic_models.filter(Boolean)
|
|
270
|
+
: [];
|
|
271
|
+
const fallback = [
|
|
272
|
+
'bedrock/us.anthropic.claude-3-5-sonnet-20240620-v1:0',
|
|
273
|
+
'bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0',
|
|
274
|
+
'bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0',
|
|
275
|
+
];
|
|
276
|
+
const models = fromModels.length > 0
|
|
277
|
+
? fromModels
|
|
278
|
+
: fromBedrock.length > 0
|
|
279
|
+
? fromBedrock
|
|
280
|
+
: fallback;
|
|
281
|
+
setInferenceModels(models);
|
|
282
|
+
const specDefault = Array.isArray(payload.bedrock_anthropic_model_specs)
|
|
283
|
+
? payload.bedrock_anthropic_model_specs.find(s => s?.default)?.id
|
|
284
|
+
: undefined;
|
|
285
|
+
const selected = (specDefault && models.includes(specDefault) ? specDefault : null) ||
|
|
286
|
+
(payload.default_model && models.includes(payload.default_model)
|
|
287
|
+
? payload.default_model
|
|
288
|
+
: null) ||
|
|
289
|
+
models[0] ||
|
|
290
|
+
null;
|
|
291
|
+
setInferenceDefaultModel(selected);
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
setInferenceModels([]);
|
|
295
|
+
setInferenceDefaultModel(null);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
loadInferenceModels();
|
|
299
|
+
}, [inferenceProvider]);
|
|
300
|
+
// If the container was started with DATALAYER_API_KEY, the backend exchanges
|
|
301
|
+
// it for a session token via /auth/bootstrap so the UI can skip sign-in.
|
|
302
|
+
useEffect(() => {
|
|
303
|
+
if (token) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (disableAutoBootstrap) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
let cancelled = false;
|
|
310
|
+
(async () => {
|
|
311
|
+
try {
|
|
312
|
+
const resp = await fetch(`${AGENT_RUNTIMES_BASE_URL}/api/v1/agent-node/auth/bootstrap`);
|
|
313
|
+
if (!resp.ok) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const data = await resp.json().catch(() => ({}));
|
|
317
|
+
if (cancelled) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (data?.has_key && data?.token) {
|
|
321
|
+
setAuth(String(data.token), String(data.handle || 'api-key-user'));
|
|
322
|
+
setStep('config');
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
catch {
|
|
326
|
+
// Best-effort; fall back to the sign-in screen.
|
|
327
|
+
}
|
|
328
|
+
})();
|
|
329
|
+
return () => {
|
|
330
|
+
cancelled = true;
|
|
331
|
+
};
|
|
332
|
+
}, [token, setAuth, disableAutoBootstrap]);
|
|
333
|
+
// Push the authenticated user's bearer token + runtimes base URL to the
|
|
334
|
+
// local Agent Node backend so the background sync can register the node
|
|
335
|
+
// and start sending heartbeats/health to the central runtimes service.
|
|
336
|
+
useEffect(() => {
|
|
337
|
+
if (!token) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
pushCredentials(token, token).catch(() => {
|
|
341
|
+
// Best-effort; backend may not be reachable in some local setups.
|
|
342
|
+
});
|
|
343
|
+
}, [token, pushCredentials]);
|
|
344
|
+
useEffect(() => {
|
|
345
|
+
import('@datalayer/core/lib/state').then(({ iamStore, coreStore }) => {
|
|
346
|
+
const runUrl = import.meta.env?.VITE_DATALAYER_RUN_URL ||
|
|
347
|
+
'https://prod1.datalayer.run';
|
|
348
|
+
const runtimesRunUrl = import.meta.env?.VITE_DATALAYER_RUNTIMES_URL || runUrl;
|
|
349
|
+
const aiInferenceRunUrl = import.meta.env?.VITE_DATALAYER_AI_INFERENCE_URL || runUrl;
|
|
350
|
+
// Seed all per-service URLs to match the main UI login behavior.
|
|
351
|
+
const coreApi = coreStore.getState();
|
|
352
|
+
const prevCfg = coreApi.configuration ?? {};
|
|
353
|
+
const urls = {
|
|
354
|
+
iamRunUrl: runUrl,
|
|
355
|
+
runtimesRunUrl,
|
|
356
|
+
spacerRunUrl: runUrl,
|
|
357
|
+
libraryRunUrl: runUrl,
|
|
358
|
+
aiagentsRunUrl: runUrl,
|
|
359
|
+
aiinferenceRunUrl: aiInferenceRunUrl,
|
|
360
|
+
mcpserversRunUrl: runUrl,
|
|
361
|
+
otelRunUrl: runUrl,
|
|
362
|
+
growthRunUrl: runUrl,
|
|
363
|
+
successRunUrl: runUrl,
|
|
364
|
+
supportRunUrl: runUrl,
|
|
365
|
+
};
|
|
366
|
+
if (typeof coreApi.setConfiguration === 'function') {
|
|
367
|
+
coreApi.setConfiguration({ ...prevCfg, ...urls });
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
coreStore.setState((s) => ({
|
|
371
|
+
configuration: { ...(s.configuration || {}), ...urls },
|
|
372
|
+
}));
|
|
373
|
+
}
|
|
374
|
+
const api = iamStore.getState();
|
|
375
|
+
iamStore.setState({ token: tokenForCore, iamRunUrl: runUrl });
|
|
376
|
+
if (tokenForCore && typeof api.refreshUserByToken === 'function') {
|
|
377
|
+
void Promise.resolve(api.refreshUserByToken(tokenForCore)).then(() => {
|
|
378
|
+
queryClient.invalidateQueries({ queryKey: ['organizations'] });
|
|
379
|
+
queryClient.invalidateQueries({ queryKey: ['subscription'] });
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
}, [tokenForCore, queryClient]);
|
|
384
|
+
useEffect(() => {
|
|
385
|
+
if (!token && step !== 'auth') {
|
|
386
|
+
setStep('auth');
|
|
387
|
+
}
|
|
388
|
+
}, [token, step]);
|
|
389
|
+
useEffect(() => {
|
|
390
|
+
// If a persisted session is already authenticated on first load,
|
|
391
|
+
// skip the auth screen and land on the main configuration view.
|
|
392
|
+
if (token && step === 'auth') {
|
|
393
|
+
setStep('config');
|
|
394
|
+
}
|
|
395
|
+
}, [token, step]);
|
|
396
|
+
useEffect(() => {
|
|
397
|
+
if (step === 'chat' && configuration.mode !== 'private') {
|
|
398
|
+
setStep('config');
|
|
399
|
+
}
|
|
400
|
+
}, [step, configuration.mode]);
|
|
401
|
+
const handleSignIn = (newToken, handle) => {
|
|
402
|
+
setDisableAutoBootstrap(false);
|
|
403
|
+
setAuth(newToken, handle);
|
|
404
|
+
setStep('config');
|
|
405
|
+
};
|
|
406
|
+
// API keys are exchanged for a session token before login so billing and
|
|
407
|
+
// plans endpoints (/api/iam/v1/plans/*) resolve the correct paid plan.
|
|
408
|
+
const handleApiKeySignIn = async (apiKey) => {
|
|
409
|
+
const runUrl = import.meta.env?.VITE_DATALAYER_RUN_URL ||
|
|
410
|
+
'https://prod1.datalayer.run';
|
|
411
|
+
try {
|
|
412
|
+
const resp = await fetch(`${runUrl}/api/iam/v1/login`, {
|
|
413
|
+
method: 'POST',
|
|
414
|
+
headers: { 'Content-Type': 'application/json' },
|
|
415
|
+
body: JSON.stringify({ token: apiKey }),
|
|
416
|
+
});
|
|
417
|
+
const data = await resp.json().catch(() => ({}));
|
|
418
|
+
if (resp.ok && data?.success && data?.token) {
|
|
419
|
+
const sessionToken = String(data.token);
|
|
420
|
+
const userHandle = (data.user && (data.user.handle_s || data.user.handle)) ||
|
|
421
|
+
'api-key-user';
|
|
422
|
+
handleSignIn(sessionToken, String(userHandle));
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
catch {
|
|
426
|
+
// Keep the user on auth screen when key exchange fails.
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
const handleSignOut = () => {
|
|
430
|
+
setDisableAutoBootstrap(true);
|
|
431
|
+
// Clear backend fallback credentials while still authenticated.
|
|
432
|
+
void pushCredentials(token, null).catch(() => {
|
|
433
|
+
// Best-effort; if this fails, local state is still signed out.
|
|
434
|
+
});
|
|
435
|
+
clearAuth();
|
|
436
|
+
setStep('auth');
|
|
437
|
+
};
|
|
438
|
+
const saveConfiguration = async () => {
|
|
439
|
+
setIsSaving(true);
|
|
440
|
+
setError(null);
|
|
441
|
+
try {
|
|
442
|
+
const inferenceResponse = await fetch(`${AGENT_RUNTIMES_BASE_URL}/api/v1/configure/inference/provider`, {
|
|
443
|
+
method: 'PUT',
|
|
444
|
+
headers: {
|
|
445
|
+
'Content-Type': 'application/json',
|
|
446
|
+
},
|
|
447
|
+
body: JSON.stringify({ provider: inferenceProvider }),
|
|
448
|
+
});
|
|
449
|
+
if (!inferenceResponse.ok) {
|
|
450
|
+
throw new Error(`Failed to save inference provider (${inferenceResponse.status})`);
|
|
451
|
+
}
|
|
452
|
+
const nextConfiguration = { ...configuration };
|
|
453
|
+
const response = await fetch(`${AGENT_RUNTIMES_BASE_URL}/api/v1/agent-node/configuration`, {
|
|
454
|
+
method: 'POST',
|
|
455
|
+
headers: {
|
|
456
|
+
'Content-Type': 'application/json',
|
|
457
|
+
},
|
|
458
|
+
body: JSON.stringify(nextConfiguration),
|
|
459
|
+
});
|
|
460
|
+
if (!response.ok) {
|
|
461
|
+
throw new Error(`Failed to save configuration (${response.status})`);
|
|
462
|
+
}
|
|
463
|
+
const payload = await response.json().catch(() => null);
|
|
464
|
+
const saved = {
|
|
465
|
+
...nextConfiguration,
|
|
466
|
+
...(payload?.configuration || {}),
|
|
467
|
+
};
|
|
468
|
+
setConfiguration(saved);
|
|
469
|
+
showBanner('success', 'Agent Node configuration saved.');
|
|
470
|
+
if (saved.mode === 'private') {
|
|
471
|
+
setStep('chat');
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
catch (reason) {
|
|
475
|
+
const message = reason?.message || 'Unable to save configuration.';
|
|
476
|
+
setError(message);
|
|
477
|
+
showBanner('error', message);
|
|
478
|
+
}
|
|
479
|
+
finally {
|
|
480
|
+
setIsSaving(false);
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
const isStepEnabled = (nextStep) => {
|
|
484
|
+
if (nextStep === 'auth')
|
|
485
|
+
return true;
|
|
486
|
+
if (!token)
|
|
487
|
+
return false;
|
|
488
|
+
if (nextStep === 'chat')
|
|
489
|
+
return configuration.mode === 'private';
|
|
490
|
+
return true;
|
|
491
|
+
};
|
|
492
|
+
const StepEntry = ({ entryStep, label, leadingVisual, }) => {
|
|
493
|
+
const enabled = isStepEnabled(entryStep);
|
|
494
|
+
const active = step === entryStep;
|
|
495
|
+
return (_jsx(Button, { size: "small", variant: "invisible", leadingVisual: leadingVisual, disabled: !enabled, sx: {
|
|
496
|
+
fontWeight: active ? 'bold' : 'normal',
|
|
497
|
+
textDecoration: 'none',
|
|
498
|
+
opacity: enabled ? 1 : 0.5,
|
|
499
|
+
color: 'fg.default',
|
|
500
|
+
}, onClick: () => {
|
|
501
|
+
if (enabled) {
|
|
502
|
+
setStep(entryStep);
|
|
503
|
+
}
|
|
504
|
+
}, children: label }));
|
|
505
|
+
};
|
|
506
|
+
return (_jsx(DatalayerThemeProvider, { colorMode: colorMode, theme: cfg.primerTheme, themeStyles: cfg.themeStyles, children: _jsx(Box, { sx: {
|
|
507
|
+
minHeight: '100vh',
|
|
508
|
+
bg: 'canvas.default',
|
|
509
|
+
color: 'fg.default',
|
|
510
|
+
}, children: _jsxs(PageLayout, { containerWidth: "full", padding: "normal", sx: { bg: 'canvas.default', color: 'fg.default' }, style: { minHeight: '100vh', overflow: 'visible' }, children: [_jsx(PageLayout.Header, { children: _jsx(PageHeader, { children: _jsx(PageHeader.Actions, { children: _jsxs(Box, { sx: {
|
|
511
|
+
display: 'flex',
|
|
512
|
+
alignItems: 'center',
|
|
513
|
+
gap: 3,
|
|
514
|
+
fontSize: 2,
|
|
515
|
+
lineHeight: '22px',
|
|
516
|
+
}, children: [_jsx(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: token && (_jsxs(_Fragment, { children: [_jsx(StepEntry, { entryStep: "chat", label: "Chat", leadingVisual: CommentIcon }), _jsx(StepEntry, { entryStep: "config", label: "Configuration", leadingVisual: GearIcon })] })) }), _jsx(AppearanceControlsWithStore, { useStore: useAgentNodeThemeStore }), !token ? (_jsx(Button, { size: "small", variant: "invisible", onClick: () => setStep('auth'), leadingVisual: SignInIcon, sx: { color: 'fg.muted' }, children: "Sign in" })) : (_jsxs(Box, { sx: {
|
|
517
|
+
display: 'inline-flex',
|
|
518
|
+
alignItems: 'center',
|
|
519
|
+
gap: 1,
|
|
520
|
+
}, children: [_jsx(Box, { sx: {
|
|
521
|
+
textAlign: 'left',
|
|
522
|
+
display: 'inline-flex',
|
|
523
|
+
alignItems: 'center',
|
|
524
|
+
}, children: _jsx(UserBadge, { token: token, variant: "small", onTokenExpired: handleSignOut }) }), _jsx(StepEntry, { entryStep: "profile", label: "Profile", leadingVisual: PersonIcon }), _jsx(Button, { size: "small", variant: "invisible", onClick: handleSignOut, leadingVisual: SignOutIcon, sx: { color: 'fg.default' }, children: "Sign out" })] })), _jsx(Box, { as: "a", href: "https://datalayer.ai", target: "_blank", rel: "noopener noreferrer", "aria-label": "Open Datalayer website", sx: { display: 'inline-flex', alignItems: 'center' }, children: _jsx(DatalayerLogoText, { size: 24, variant: themeVariant, colorMode: colorMode, primaryColor: logoColors.primary, secondaryColor: logoColors.secondary, textColor: logoColors.textColor, primaryGradient: logoColors.primaryGradient, secondaryGradient: logoColors.secondaryGradient, gradient: true }) })] }) }) }) }), _jsxs(PageLayout.Content, { children: [_jsx(Box, { "aria-live": "polite", sx: {
|
|
525
|
+
position: 'fixed',
|
|
526
|
+
top: 0,
|
|
527
|
+
left: 0,
|
|
528
|
+
right: 0,
|
|
529
|
+
zIndex: 1000,
|
|
530
|
+
pointerEvents: 'none',
|
|
531
|
+
display: 'flex',
|
|
532
|
+
justifyContent: 'stretch',
|
|
533
|
+
}, children: _jsx(Box, { role: banner?.kind === 'error' ? 'alert' : 'status', sx: {
|
|
534
|
+
pointerEvents: banner ? 'auto' : 'none',
|
|
535
|
+
width: '100%',
|
|
536
|
+
px: 4,
|
|
537
|
+
py: 4,
|
|
538
|
+
borderRadius: 0,
|
|
539
|
+
borderBottom: '1px solid',
|
|
540
|
+
borderColor: banner?.kind === 'error'
|
|
541
|
+
? 'danger.emphasis'
|
|
542
|
+
: banner?.kind === 'warning'
|
|
543
|
+
? 'attention.emphasis'
|
|
544
|
+
: banner?.kind === 'success'
|
|
545
|
+
? 'success.emphasis'
|
|
546
|
+
: 'accent.emphasis',
|
|
547
|
+
bg: banner?.kind === 'error'
|
|
548
|
+
? 'danger.subtle'
|
|
549
|
+
: banner?.kind === 'warning'
|
|
550
|
+
? 'attention.subtle'
|
|
551
|
+
: banner?.kind === 'success'
|
|
552
|
+
? 'success.subtle'
|
|
553
|
+
: 'accent.subtle',
|
|
554
|
+
color: 'fg.default',
|
|
555
|
+
boxShadow: banner ? '0 4px 16px rgba(0, 0, 0, 0.12)' : 'none',
|
|
556
|
+
opacity: banner ? 1 : 0,
|
|
557
|
+
transform: banner ? 'translateY(0)' : 'translateY(-100%)',
|
|
558
|
+
transition: banner
|
|
559
|
+
? 'opacity 600ms ease, transform 700ms cubic-bezier(0.16, 1, 0.3, 1)'
|
|
560
|
+
: 'opacity 250ms ease, transform 350ms cubic-bezier(0.16, 1, 0.3, 1)',
|
|
561
|
+
textAlign: 'center',
|
|
562
|
+
}, children: _jsx(Text, { sx: { fontSize: 3, fontWeight: 'bold' }, children: banner?.message ?? '' }) }) }), _jsxs(Box, { sx: { mb: 3 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2, mb: 1 }, children: [_jsx(Box, { sx: { color: 'fg.muted', display: 'inline-flex' }, children: _jsx(KeyAsteriskIcon, { size: 18 }) }), _jsx(Heading, { sx: { fontSize: 3, m: 0 }, children: "Agent Node" })] }), _jsx(Text, { sx: { color: 'fg.muted' }, children: "Authenticate, configure Private/Shared/Sleep mode, then chat from this node." })] }), step === 'auth' && (_jsx(Box, { sx: {
|
|
563
|
+
border: '1px solid',
|
|
564
|
+
borderColor: 'border.default',
|
|
565
|
+
borderTop: '3px solid',
|
|
566
|
+
borderTopColor: cfg.brandColor,
|
|
567
|
+
borderRadius: 2,
|
|
568
|
+
p: 4,
|
|
569
|
+
backgroundImage: `linear-gradient(135deg, ${authGradient.from}1A 0%, ${authGradient.to}1A 100%)`,
|
|
570
|
+
}, children: _jsx(Box, { sx: {
|
|
571
|
+
maxWidth: 640,
|
|
572
|
+
mx: 'auto',
|
|
573
|
+
// SignInSimple renders a full-height shell; scope overrides
|
|
574
|
+
// here so the auth view inherits this page layout/theme.
|
|
575
|
+
'& > div': {
|
|
576
|
+
height: 'auto',
|
|
577
|
+
minHeight: 0,
|
|
578
|
+
bg: 'transparent',
|
|
579
|
+
py: 0,
|
|
580
|
+
},
|
|
581
|
+
'& > div > div': {
|
|
582
|
+
width: '100%',
|
|
583
|
+
bg: 'canvas.default',
|
|
584
|
+
borderColor: `${cfg.brandColor}66`,
|
|
585
|
+
boxShadow: `0 0 0 1px ${cfg.brandColor}2B`,
|
|
586
|
+
},
|
|
587
|
+
'& h2, & h3': {
|
|
588
|
+
color: cfg.brandColor,
|
|
589
|
+
},
|
|
590
|
+
}, children: _jsx(SignInSimple, { onSignIn: handleSignIn, onApiKeySignIn: handleApiKeySignIn, title: "Agent Node", description: "Sign in to configure node settings and run authenticated chat sessions.", leadingIcon: _jsx(Box, { sx: { color: cfg.brandColor, display: 'inline-flex' }, children: _jsx(HomeIcon, { size: 24 }) }) }) }) })), step === 'config' && (_jsxs(Box, { sx: {
|
|
591
|
+
border: '1px solid',
|
|
592
|
+
borderColor: 'border.default',
|
|
593
|
+
borderRadius: 2,
|
|
594
|
+
p: 3,
|
|
595
|
+
display: 'flex',
|
|
596
|
+
flexDirection: 'column',
|
|
597
|
+
gap: 3,
|
|
598
|
+
}, children: [_jsxs(Box, { sx: {
|
|
599
|
+
display: 'grid',
|
|
600
|
+
gridTemplateColumns: ['1fr', null, '1fr 1fr'],
|
|
601
|
+
gap: 4,
|
|
602
|
+
alignItems: 'start',
|
|
603
|
+
}, children: [_jsxs(Box, { sx: {
|
|
604
|
+
display: 'flex',
|
|
605
|
+
flexDirection: 'column',
|
|
606
|
+
gap: 3,
|
|
607
|
+
}, children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Mode" }), _jsx(Box, { sx: {
|
|
608
|
+
display: 'grid',
|
|
609
|
+
gridTemplateColumns: 'repeat(3, 1fr)',
|
|
610
|
+
gap: 3,
|
|
611
|
+
}, children: MODE_CARDS.map(card => {
|
|
612
|
+
const isSelected = configuration.mode === card.mode;
|
|
613
|
+
const Icon = card.Icon;
|
|
614
|
+
return (_jsxs(Box, { as: "button", type: "button", onClick: () => setConfiguration(prev => ({
|
|
615
|
+
...prev,
|
|
616
|
+
mode: card.mode,
|
|
617
|
+
})), "aria-pressed": isSelected, sx: {
|
|
618
|
+
textAlign: 'left',
|
|
619
|
+
cursor: 'pointer',
|
|
620
|
+
display: 'flex',
|
|
621
|
+
flexDirection: 'column',
|
|
622
|
+
gap: 2,
|
|
623
|
+
p: 3,
|
|
624
|
+
borderRadius: 2,
|
|
625
|
+
border: '1px solid',
|
|
626
|
+
borderColor: isSelected
|
|
627
|
+
? cfg.brandColor
|
|
628
|
+
: 'border.default',
|
|
629
|
+
bg: isSelected
|
|
630
|
+
? 'canvas.subtle'
|
|
631
|
+
: 'canvas.default',
|
|
632
|
+
color: 'fg.default',
|
|
633
|
+
boxShadow: isSelected
|
|
634
|
+
? `0 0 0 1px ${cfg.brandColor}`
|
|
635
|
+
: 'none',
|
|
636
|
+
'&:hover': {
|
|
637
|
+
borderColor: cfg.brandColor,
|
|
638
|
+
},
|
|
639
|
+
}, children: [_jsxs(Box, { sx: {
|
|
640
|
+
display: 'flex',
|
|
641
|
+
alignItems: 'center',
|
|
642
|
+
gap: 2,
|
|
643
|
+
color: isSelected
|
|
644
|
+
? cfg.brandColor
|
|
645
|
+
: 'fg.default',
|
|
646
|
+
}, children: [_jsx(Icon, { size: 20 }), _jsx(Text, { sx: { fontWeight: 'bold' }, children: card.name })] }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: card.description })] }, card.mode));
|
|
647
|
+
}) })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Inference" }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 1, mb: 2 }, children: "Used inference provider for newly launched agent sessions." }), _jsxs(Box, { sx: {
|
|
648
|
+
display: 'flex',
|
|
649
|
+
gap: 2,
|
|
650
|
+
flexWrap: 'wrap',
|
|
651
|
+
mb: inferenceProvider === 'datalayer' ? 2 : 0,
|
|
652
|
+
}, children: [_jsx(Button, { size: "small", variant: inferenceProvider === 'local'
|
|
653
|
+
? 'primary'
|
|
654
|
+
: 'default', onClick: () => setInferenceProvider('local'), children: "local" }), _jsx(Button, { size: "small", variant: inferenceProvider === 'datalayer'
|
|
655
|
+
? 'primary'
|
|
656
|
+
: 'default', onClick: () => setInferenceProvider('datalayer'), children: "datalayer" })] }), inferenceProvider === 'datalayer' && (_jsxs(Box, { sx: {
|
|
657
|
+
border: '1px solid',
|
|
658
|
+
borderColor: 'border.default',
|
|
659
|
+
borderRadius: 2,
|
|
660
|
+
p: 2,
|
|
661
|
+
bg: 'canvas.subtle',
|
|
662
|
+
display: 'flex',
|
|
663
|
+
flexDirection: 'column',
|
|
664
|
+
gap: 1,
|
|
665
|
+
}, children: [_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Bedrock Anthropic model" }), inferenceModels.length === 0 ? (_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "No model list available." })) : (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Button, { children: inferenceDefaultModel || inferenceModels[0] }), _jsx(ActionMenu.Overlay, { width: "large", children: _jsx(ActionList, { selectionVariant: "single", children: inferenceModels.map(model => (_jsx(ActionList.Item, { selected: inferenceDefaultModel === model, inactiveText: "Selection is locked", children: model }, model))) }) })] }))] }))] }), iamUser ? (_jsx(BillableAccountSelect, { value: configuration.billable_account_uid || '', onChange: handleBillableAccountChange, onSelectedAccountChange: handleSelectedAccountChange, onAccountsResolved: handleAccountsResolved })) : (_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Run this agent under" }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "Loading billable accounts..." })] }))] }), _jsxs(Box, { sx: {
|
|
666
|
+
display: 'flex',
|
|
667
|
+
flexDirection: 'column',
|
|
668
|
+
gap: 2,
|
|
669
|
+
}, children: [_jsx(Heading, { sx: { fontSize: 2, m: 0 }, children: "Share" }), _jsx(ShareAccessComponent, { isOpen: true, displayMode: "inline", requestUrl: `${AGENT_RUNTIMES_BASE_URL}/api/v1/agent-node/sharing`, resourceLabel: "Agent Node", resourceName: "this Agent Node", onClose: handleSharingInlineClose })] })] }), error && _jsx(Text, { sx: { color: 'danger.fg' }, children: error }), _jsx(Box, { sx: { display: 'flex', justifyContent: 'flex-end' }, children: _jsx(Button, { variant: "primary", onClick: saveConfiguration, disabled: isSaving, children: isSaving ? 'Saving...' : 'Save' }) })] })), step === 'profile' && _jsx(AgentNodeProfileView, { token: token }), step === 'chat' && (_jsx(Box, { sx: {
|
|
670
|
+
border: '1px solid',
|
|
671
|
+
borderColor: 'border.default',
|
|
672
|
+
borderRadius: 2,
|
|
673
|
+
overflow: 'hidden',
|
|
674
|
+
}, children: _jsx(Chat, { protocol: "ag-ui", baseUrl: AGENT_RUNTIMES_BASE_URL, agentId: "default", title: "Agent Node Chat", placeholder: "Send a message...", description: "Node-local chat", showHeader: true, height: '70vh', showModelSelector: true, showToolsMenu: true, showSkillsMenu: true, showTokenUsage: true, showInformation: true, autoFocus: true, runtimeId: "default", historyEndpoint: `${AGENT_RUNTIMES_BASE_URL}/api/v1/history` }) }))] })] }) }) }));
|
|
675
|
+
}
|
|
676
|
+
export default AgentNode;
|