@datalayer/agent-runtimes 0.0.5 → 0.0.7
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 +141 -22
- package/lib/components/chat/components/AgentDetails.d.ts +1 -1
- package/lib/components/chat/components/AgentDetails.js +7 -92
- package/lib/components/chat/components/Chat.d.ts +5 -1
- package/lib/components/chat/components/Chat.js +28 -19
- package/lib/components/chat/components/ContextDistribution.d.ts +47 -0
- package/lib/components/chat/components/ContextDistribution.js +146 -0
- package/lib/components/chat/components/ContextUsage.d.ts +33 -0
- package/lib/components/chat/components/ContextUsage.js +127 -0
- package/lib/components/chat/components/base/ChatBase.d.ts +5 -1
- package/lib/components/chat/components/base/ChatBase.js +40 -15
- package/lib/components/chat/components/index.d.ts +2 -0
- package/lib/components/chat/components/index.js +2 -0
- package/lib/examples/AgentSpaceFormExample.js +41 -6
- package/lib/examples/components/AgentConfiguration.d.ts +22 -0
- package/lib/examples/components/AgentConfiguration.js +37 -10
- package/lib/examples/components/Header.d.ts +0 -2
- package/lib/examples/components/Header.js +2 -16
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/runtime/index.d.ts +35 -0
- package/lib/runtime/index.js +40 -0
- package/lib/runtime/runtimeStore.d.ts +77 -0
- package/lib/runtime/runtimeStore.js +184 -0
- package/lib/runtime/types.d.ts +84 -0
- package/lib/runtime/types.js +15 -0
- package/lib/runtime/useAgentConnection.d.ts +46 -0
- package/lib/runtime/useAgentConnection.js +112 -0
- package/lib/runtime/useAgentRuntime.d.ts +94 -0
- package/lib/runtime/useAgentRuntime.js +125 -0
- package/package.json +1 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
// Distributed under the terms of the Modified BSD License.
|
|
4
|
+
/**
|
|
5
|
+
* ContextUsage component - Shows context usage details with token breakdown.
|
|
6
|
+
*/
|
|
7
|
+
import { CommentDiscussionIcon, DatabaseIcon, FileIcon, ToolsIcon, ClockIcon, } from '@primer/octicons-react';
|
|
8
|
+
import { Box, Heading, Text, ProgressBar, Spinner } from '@primer/react';
|
|
9
|
+
import { useQuery } from '@tanstack/react-query';
|
|
10
|
+
function getLocalApiBase() {
|
|
11
|
+
if (typeof window === 'undefined') {
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
14
|
+
const host = window.location.hostname;
|
|
15
|
+
return host === 'localhost' || host === '127.0.0.1'
|
|
16
|
+
? 'http://127.0.0.1:8765'
|
|
17
|
+
: '';
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Format token count for display
|
|
21
|
+
*/
|
|
22
|
+
function formatTokens(tokens) {
|
|
23
|
+
if (tokens >= 1000000) {
|
|
24
|
+
return `${(tokens / 1000000).toFixed(1)}M`;
|
|
25
|
+
}
|
|
26
|
+
if (tokens >= 1000) {
|
|
27
|
+
return `${(tokens / 1000).toFixed(1)}K`;
|
|
28
|
+
}
|
|
29
|
+
return tokens.toString();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get icon for context category
|
|
33
|
+
*/
|
|
34
|
+
function getCategoryIcon(name) {
|
|
35
|
+
switch (name.toLowerCase()) {
|
|
36
|
+
case 'files':
|
|
37
|
+
return FileIcon;
|
|
38
|
+
case 'messages':
|
|
39
|
+
return CommentDiscussionIcon;
|
|
40
|
+
case 'tools':
|
|
41
|
+
return ToolsIcon;
|
|
42
|
+
case 'memory':
|
|
43
|
+
return DatabaseIcon;
|
|
44
|
+
case 'system':
|
|
45
|
+
return FileIcon;
|
|
46
|
+
case 'cache':
|
|
47
|
+
return DatabaseIcon;
|
|
48
|
+
default:
|
|
49
|
+
return ClockIcon;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* ContextUsage component displays token usage breakdown by category.
|
|
54
|
+
*/
|
|
55
|
+
export function ContextUsage({ agentId }) {
|
|
56
|
+
const { data: contextData, isLoading, error, } = useQuery({
|
|
57
|
+
queryKey: ['context-details', agentId],
|
|
58
|
+
queryFn: async () => {
|
|
59
|
+
const apiBase = getLocalApiBase();
|
|
60
|
+
const response = await fetch(`${apiBase}/api/v1/configure/agents/${encodeURIComponent(agentId)}/context-details`);
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
throw new Error('Failed to fetch context details');
|
|
63
|
+
}
|
|
64
|
+
return response.json();
|
|
65
|
+
},
|
|
66
|
+
refetchInterval: 10000, // Refresh every 10 seconds
|
|
67
|
+
refetchOnMount: 'always', // Always refetch when component mounts
|
|
68
|
+
staleTime: 0, // Data is always considered stale
|
|
69
|
+
});
|
|
70
|
+
if (isLoading) {
|
|
71
|
+
return (_jsxs(Box, { children: [_jsx(Heading, { as: "h4", sx: {
|
|
72
|
+
fontSize: 1,
|
|
73
|
+
fontWeight: 'semibold',
|
|
74
|
+
mb: 2,
|
|
75
|
+
color: 'fg.muted',
|
|
76
|
+
}, children: "Cumulative Context Usage" }), _jsxs(Box, { sx: {
|
|
77
|
+
p: 3,
|
|
78
|
+
bg: 'canvas.subtle',
|
|
79
|
+
borderRadius: 2,
|
|
80
|
+
border: '1px solid',
|
|
81
|
+
borderColor: 'border.default',
|
|
82
|
+
display: 'flex',
|
|
83
|
+
alignItems: 'center',
|
|
84
|
+
gap: 2,
|
|
85
|
+
}, children: [_jsx(Spinner, { size: "small" }), _jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Loading context details..." })] })] }));
|
|
86
|
+
}
|
|
87
|
+
if (error || !contextData) {
|
|
88
|
+
return (_jsxs(Box, { children: [_jsx(Heading, { as: "h4", sx: {
|
|
89
|
+
fontSize: 1,
|
|
90
|
+
fontWeight: 'semibold',
|
|
91
|
+
mb: 2,
|
|
92
|
+
color: 'fg.muted',
|
|
93
|
+
}, children: "Cumulative Context Usage" }), _jsx(Box, { sx: {
|
|
94
|
+
p: 3,
|
|
95
|
+
bg: 'canvas.subtle',
|
|
96
|
+
borderRadius: 2,
|
|
97
|
+
border: '1px solid',
|
|
98
|
+
borderColor: 'border.default',
|
|
99
|
+
}, children: _jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Failed to load context details" }) })] }));
|
|
100
|
+
}
|
|
101
|
+
const contextUsagePercent = (contextData.usedTokens / contextData.totalTokens) * 100;
|
|
102
|
+
return (_jsxs(Box, { children: [_jsx(Heading, { as: "h4", sx: {
|
|
103
|
+
fontSize: 1,
|
|
104
|
+
fontWeight: 'semibold',
|
|
105
|
+
mb: 2,
|
|
106
|
+
color: 'fg.muted',
|
|
107
|
+
}, children: "Cumulative Context Usage" }), _jsxs(Box, { sx: {
|
|
108
|
+
p: 3,
|
|
109
|
+
bg: 'canvas.subtle',
|
|
110
|
+
borderRadius: 2,
|
|
111
|
+
border: '1px solid',
|
|
112
|
+
borderColor: 'border.default',
|
|
113
|
+
}, children: [_jsxs(Box, { sx: { mb: 3 }, children: [_jsxs(Box, { sx: {
|
|
114
|
+
display: 'flex',
|
|
115
|
+
justifyContent: 'space-between',
|
|
116
|
+
mb: 1,
|
|
117
|
+
}, children: [_jsxs(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: [formatTokens(contextData.usedTokens), " /", ' ', formatTokens(contextData.totalTokens), " tokens"] }), _jsxs(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: [contextUsagePercent.toFixed(0), "%"] })] }), _jsx(ProgressBar, { progress: contextUsagePercent, sx: { height: 8 }, bg: contextUsagePercent > 80 ? 'danger.emphasis' : 'accent.emphasis' })] }), _jsx(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: contextData.children.map(category => {
|
|
118
|
+
const CategoryIcon = getCategoryIcon(category.name);
|
|
119
|
+
const categoryPercent = (category.value / contextData.totalTokens) * 100;
|
|
120
|
+
return (_jsxs(Box, { sx: {
|
|
121
|
+
display: 'flex',
|
|
122
|
+
alignItems: 'center',
|
|
123
|
+
gap: 2,
|
|
124
|
+
}, children: [_jsx(Box, { sx: { color: 'fg.muted', width: 20 }, children: _jsx(CategoryIcon, { size: 16 }) }), _jsx(Text, { sx: { fontSize: 1, flex: 1 }, children: category.name }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', minWidth: 60 }, children: formatTokens(category.value) }), _jsx(Box, { sx: { width: 80 }, children: _jsx(ProgressBar, { progress: categoryPercent, sx: { height: 4 } }) })] }, category.name));
|
|
125
|
+
}) })] })] }));
|
|
126
|
+
}
|
|
127
|
+
export default ContextUsage;
|
|
@@ -201,6 +201,10 @@ export interface ChatBaseProps {
|
|
|
201
201
|
showModelSelector?: boolean;
|
|
202
202
|
/** Show tools menu (for protocols that support it) */
|
|
203
203
|
showToolsMenu?: boolean;
|
|
204
|
+
/** Initial model ID to select (e.g., 'openai:gpt-4o-mini') */
|
|
205
|
+
initialModel?: string;
|
|
206
|
+
/** Initial MCP server IDs to enable (others will be disabled) */
|
|
207
|
+
initialMcpServers?: string[];
|
|
204
208
|
/** Custom class name */
|
|
205
209
|
className?: string;
|
|
206
210
|
/** Custom loading state */
|
|
@@ -305,6 +309,6 @@ export interface ChatBaseProps {
|
|
|
305
309
|
/**
|
|
306
310
|
* ChatBase component - Universal chat panel supporting store, protocol, and custom modes
|
|
307
311
|
*/
|
|
308
|
-
export declare function ChatBase({ title, showHeader, showLoadingIndicator, showErrors, showInput, showModelSelector, showToolsMenu, className, loadingState, headerActions, useStore: useStoreMode, protocol, onSendMessage, enableStreaming, brandIcon, avatarConfig, headerButtons, showPoweredBy, poweredByProps, emptyState, renderToolResult, footerContent, headerContent, children, borderRadius, backgroundColor, border, boxShadow, compact, placeholder, description, onStateUpdate, onNewChat, onClear, onMessagesChange, autoFocus, suggestions, submitOnSuggestionClick, hideMessagesAfterToolUI, focusTrigger, frontendTools, }: ChatBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
312
|
+
export declare function ChatBase({ title, showHeader, showLoadingIndicator, showErrors, showInput, showModelSelector, showToolsMenu, initialModel, initialMcpServers, className, loadingState, headerActions, useStore: useStoreMode, protocol, onSendMessage, enableStreaming, brandIcon, avatarConfig, headerButtons, showPoweredBy, poweredByProps, emptyState, renderToolResult, footerContent, headerContent, children, borderRadius, backgroundColor, border, boxShadow, compact, placeholder, description, onStateUpdate, onNewChat, onClear, onMessagesChange, autoFocus, suggestions, submitOnSuggestionClick, hideMessagesAfterToolUI, focusTrigger, frontendTools, }: ChatBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
309
313
|
export type { PoweredByTagProps };
|
|
310
314
|
export default ChatBase;
|
|
@@ -160,7 +160,7 @@ function useConfigQuery(enabled, configEndpoint, authToken) {
|
|
|
160
160
|
/**
|
|
161
161
|
* ChatBase component - Universal chat panel supporting store, protocol, and custom modes
|
|
162
162
|
*/
|
|
163
|
-
export function ChatBase({ title, showHeader = false, showLoadingIndicator = true, showErrors = true, showInput = true, showModelSelector = false, showToolsMenu = false, className, loadingState, headerActions,
|
|
163
|
+
export function ChatBase({ title, showHeader = false, showLoadingIndicator = true, showErrors = true, showInput = true, showModelSelector = false, showToolsMenu = false, initialModel, initialMcpServers, className, loadingState, headerActions,
|
|
164
164
|
// Mode selection
|
|
165
165
|
useStore: useStoreMode = true, protocol, onSendMessage, enableStreaming = false,
|
|
166
166
|
// Extended props
|
|
@@ -169,15 +169,15 @@ brandIcon, avatarConfig, headerButtons, showPoweredBy = false, poweredByProps, e
|
|
|
169
169
|
const existingQueryClient = useContext(QueryClientContext);
|
|
170
170
|
// If no QueryClient is available, wrap with our internal provider
|
|
171
171
|
if (!existingQueryClient) {
|
|
172
|
-
return (_jsx(QueryClientProvider, { client: internalQueryClient, children: _jsx(ChatBaseInner, { title: title, showHeader: showHeader, showLoadingIndicator: showLoadingIndicator, showErrors: showErrors, showInput: showInput, showModelSelector: showModelSelector, showToolsMenu: showToolsMenu, className: className, loadingState: loadingState, headerActions: headerActions, useStore: useStoreMode, protocol: protocol, onSendMessage: onSendMessage, enableStreaming: enableStreaming, brandIcon: brandIcon, avatarConfig: avatarConfig, headerButtons: headerButtons, showPoweredBy: showPoweredBy, poweredByProps: poweredByProps, emptyState: emptyState, renderToolResult: renderToolResult, footerContent: footerContent, headerContent: headerContent, children: children, borderRadius: borderRadius, backgroundColor: backgroundColor, border: border, boxShadow: boxShadow, compact: compact, placeholder: placeholder, description: description, onStateUpdate: onStateUpdate, onNewChat: onNewChat, onClear: onClear, onMessagesChange: onMessagesChange, autoFocus: autoFocus, suggestions: suggestions, submitOnSuggestionClick: submitOnSuggestionClick, hideMessagesAfterToolUI: hideMessagesAfterToolUI, focusTrigger: focusTrigger, frontendTools: frontendTools }) }));
|
|
172
|
+
return (_jsx(QueryClientProvider, { client: internalQueryClient, children: _jsx(ChatBaseInner, { title: title, showHeader: showHeader, showLoadingIndicator: showLoadingIndicator, showErrors: showErrors, showInput: showInput, showModelSelector: showModelSelector, showToolsMenu: showToolsMenu, initialModel: initialModel, initialMcpServers: initialMcpServers, className: className, loadingState: loadingState, headerActions: headerActions, useStore: useStoreMode, protocol: protocol, onSendMessage: onSendMessage, enableStreaming: enableStreaming, brandIcon: brandIcon, avatarConfig: avatarConfig, headerButtons: headerButtons, showPoweredBy: showPoweredBy, poweredByProps: poweredByProps, emptyState: emptyState, renderToolResult: renderToolResult, footerContent: footerContent, headerContent: headerContent, children: children, borderRadius: borderRadius, backgroundColor: backgroundColor, border: border, boxShadow: boxShadow, compact: compact, placeholder: placeholder, description: description, onStateUpdate: onStateUpdate, onNewChat: onNewChat, onClear: onClear, onMessagesChange: onMessagesChange, autoFocus: autoFocus, suggestions: suggestions, submitOnSuggestionClick: submitOnSuggestionClick, hideMessagesAfterToolUI: hideMessagesAfterToolUI, focusTrigger: focusTrigger, frontendTools: frontendTools }) }));
|
|
173
173
|
}
|
|
174
174
|
// QueryClient already available, render inner component directly
|
|
175
|
-
return (_jsx(ChatBaseInner, { title: title, showHeader: showHeader, showLoadingIndicator: showLoadingIndicator, showErrors: showErrors, showInput: showInput, showModelSelector: showModelSelector, showToolsMenu: showToolsMenu, className: className, loadingState: loadingState, headerActions: headerActions, useStore: useStoreMode, protocol: protocol, onSendMessage: onSendMessage, enableStreaming: enableStreaming, brandIcon: brandIcon, avatarConfig: avatarConfig, headerButtons: headerButtons, showPoweredBy: showPoweredBy, poweredByProps: poweredByProps, emptyState: emptyState, renderToolResult: renderToolResult, footerContent: footerContent, headerContent: headerContent, children: children, borderRadius: borderRadius, backgroundColor: backgroundColor, border: border, boxShadow: boxShadow, compact: compact, placeholder: placeholder, description: description, onStateUpdate: onStateUpdate, onNewChat: onNewChat, onClear: onClear, onMessagesChange: onMessagesChange, autoFocus: autoFocus, suggestions: suggestions, submitOnSuggestionClick: submitOnSuggestionClick, hideMessagesAfterToolUI: hideMessagesAfterToolUI, focusTrigger: focusTrigger, frontendTools: frontendTools }));
|
|
175
|
+
return (_jsx(ChatBaseInner, { title: title, showHeader: showHeader, showLoadingIndicator: showLoadingIndicator, showErrors: showErrors, showInput: showInput, showModelSelector: showModelSelector, showToolsMenu: showToolsMenu, initialModel: initialModel, initialMcpServers: initialMcpServers, className: className, loadingState: loadingState, headerActions: headerActions, useStore: useStoreMode, protocol: protocol, onSendMessage: onSendMessage, enableStreaming: enableStreaming, brandIcon: brandIcon, avatarConfig: avatarConfig, headerButtons: headerButtons, showPoweredBy: showPoweredBy, poweredByProps: poweredByProps, emptyState: emptyState, renderToolResult: renderToolResult, footerContent: footerContent, headerContent: headerContent, children: children, borderRadius: borderRadius, backgroundColor: backgroundColor, border: border, boxShadow: boxShadow, compact: compact, placeholder: placeholder, description: description, onStateUpdate: onStateUpdate, onNewChat: onNewChat, onClear: onClear, onMessagesChange: onMessagesChange, autoFocus: autoFocus, suggestions: suggestions, submitOnSuggestionClick: submitOnSuggestionClick, hideMessagesAfterToolUI: hideMessagesAfterToolUI, focusTrigger: focusTrigger, frontendTools: frontendTools }));
|
|
176
176
|
}
|
|
177
177
|
/**
|
|
178
178
|
* Inner ChatBase component - contains all the actual logic
|
|
179
179
|
*/
|
|
180
|
-
function ChatBaseInner({ title, showHeader = false, showLoadingIndicator = true, showErrors = true, showInput = true, showModelSelector = false, showToolsMenu = false, className, loadingState, headerActions,
|
|
180
|
+
function ChatBaseInner({ title, showHeader = false, showLoadingIndicator = true, showErrors = true, showInput = true, showModelSelector = false, showToolsMenu = false, initialModel, initialMcpServers, className, loadingState, headerActions,
|
|
181
181
|
// Mode selection
|
|
182
182
|
useStore: useStoreMode = true, protocol, onSendMessage, enableStreaming = false,
|
|
183
183
|
// Extended props
|
|
@@ -269,27 +269,52 @@ brandIcon, avatarConfig, headerButtons, showPoweredBy = false, poweredByProps, e
|
|
|
269
269
|
// Initialize model and tools when config is available
|
|
270
270
|
useEffect(() => {
|
|
271
271
|
if (configQuery.data && !selectedModel) {
|
|
272
|
-
//
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
272
|
+
// Use initialModel if provided, otherwise select first available model
|
|
273
|
+
if (initialModel) {
|
|
274
|
+
// Check if the initial model exists in the config
|
|
275
|
+
const modelExists = configQuery.data.models.some(m => m.id === initialModel);
|
|
276
|
+
if (modelExists) {
|
|
277
|
+
setSelectedModel(initialModel);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
// Fallback to first available model if initialModel not found
|
|
281
|
+
const firstAvailableModel = configQuery.data.models.find(m => m.isAvailable !== false);
|
|
282
|
+
const firstModel = firstAvailableModel || configQuery.data.models[0];
|
|
283
|
+
if (firstModel) {
|
|
284
|
+
setSelectedModel(firstModel.id);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
279
287
|
}
|
|
280
|
-
|
|
288
|
+
else {
|
|
289
|
+
// No initialModel provided, select first available model
|
|
290
|
+
const firstAvailableModel = configQuery.data.models.find(m => m.isAvailable !== false);
|
|
291
|
+
const firstModel = firstAvailableModel || configQuery.data.models[0];
|
|
292
|
+
if (firstModel) {
|
|
293
|
+
setSelectedModel(firstModel.id);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const allToolIds = configQuery.data.builtinTools?.map(tool => tool.id) || [];
|
|
297
|
+
setEnabledTools(allToolIds);
|
|
298
|
+
// Initialize MCP server tools
|
|
281
299
|
if (configQuery.data.mcpServers) {
|
|
282
300
|
const newEnabledMcpTools = new Map();
|
|
283
301
|
for (const server of configQuery.data.mcpServers) {
|
|
284
302
|
if (server.isAvailable && server.enabled) {
|
|
285
|
-
|
|
286
|
-
|
|
303
|
+
// If initialMcpServers is provided, only enable those servers
|
|
304
|
+
// If not provided, enable all available servers
|
|
305
|
+
const shouldEnableServer = initialMcpServers
|
|
306
|
+
? initialMcpServers.includes(server.id)
|
|
307
|
+
: true;
|
|
308
|
+
if (shouldEnableServer) {
|
|
309
|
+
const enabledToolNames = new Set(server.tools.filter(t => t.enabled).map(t => t.name));
|
|
310
|
+
newEnabledMcpTools.set(server.id, enabledToolNames);
|
|
311
|
+
}
|
|
287
312
|
}
|
|
288
313
|
}
|
|
289
314
|
setEnabledMcpTools(newEnabledMcpTools);
|
|
290
315
|
}
|
|
291
316
|
}
|
|
292
|
-
}, [configQuery.data, selectedModel]);
|
|
317
|
+
}, [configQuery.data, selectedModel, initialModel, initialMcpServers]);
|
|
293
318
|
// Helper to toggle MCP tool enabled state
|
|
294
319
|
const toggleMcpTool = useCallback((serverId, toolName) => {
|
|
295
320
|
setEnabledMcpTools(prev => {
|
|
@@ -9,6 +9,8 @@ export { ChatSidebar, type ChatSidebarProps } from './ChatSidebar';
|
|
|
9
9
|
export { ChatStandalone, type ChatStandaloneProps, type MessageHandler, } from './ChatStandalone';
|
|
10
10
|
export { ChatBase, type ChatBaseProps, type ProtocolConfig, } from './base/ChatBase';
|
|
11
11
|
export { AgentDetails, type AgentDetailsProps } from './AgentDetails';
|
|
12
|
+
export { ContextUsage, type ContextUsageProps, type ContextDetailsResponse, } from './ContextUsage';
|
|
13
|
+
export { ContextDistribution, type ContextDistributionProps, type ContextSnapshotResponse, } from './ContextDistribution';
|
|
12
14
|
export { ToolApprovalDialog, useToolApprovalDialog, type ToolApprovalDialogProps, } from './elements/ToolApprovalDialog';
|
|
13
15
|
export { PoweredByTag, type PoweredByTagProps } from './elements/PoweredByTag';
|
|
14
16
|
export { FloatingBrandButton, type FloatingBrandButtonProps, } from './elements/FloatingBrandButton';
|
|
@@ -13,6 +13,8 @@ export { ChatSidebar } from './ChatSidebar';
|
|
|
13
13
|
export { ChatStandalone, } from './ChatStandalone';
|
|
14
14
|
export { ChatBase, } from './base/ChatBase';
|
|
15
15
|
export { AgentDetails } from './AgentDetails';
|
|
16
|
+
export { ContextUsage, } from './ContextUsage';
|
|
17
|
+
export { ContextDistribution, } from './ContextDistribution';
|
|
16
18
|
export { ToolApprovalDialog, useToolApprovalDialog, } from './elements/ToolApprovalDialog';
|
|
17
19
|
export { PoweredByTag } from './elements/PoweredByTag';
|
|
18
20
|
export { FloatingBrandButton, } from './elements/FloatingBrandButton';
|
|
@@ -59,12 +59,31 @@ const AgentSpaceFormExample = () => {
|
|
|
59
59
|
const [agentLibrary, setAgentLibrary] = useState('pydantic-ai');
|
|
60
60
|
const [transport, setTransport] = useState('ag-ui');
|
|
61
61
|
const [extensions, setExtensions] = useState([]);
|
|
62
|
+
const [model, setModel] = useState('openai:gpt-4o-mini');
|
|
62
63
|
const [isConfigured, setIsConfigured] = useState(false);
|
|
64
|
+
// Agent capabilities state (moved from Header toggles)
|
|
65
|
+
const [enableSkills, setEnableSkills] = useState(false);
|
|
66
|
+
const [enableCodemode, setEnableCodemode] = useState(false);
|
|
67
|
+
const [allowDirectToolCalls, setAllowDirectToolCalls] = useState(false);
|
|
68
|
+
const [enableToolReranker, setEnableToolReranker] = useState(false);
|
|
69
|
+
const [selectedMcpServers, setSelectedMcpServers] = useState([]);
|
|
70
|
+
// Handle codemode change - clear MCP servers when enabled
|
|
71
|
+
const handleEnableCodemodeChange = (enabled) => {
|
|
72
|
+
setEnableCodemode(enabled);
|
|
73
|
+
if (enabled) {
|
|
74
|
+
// Clear selected MCP servers when codemode is enabled
|
|
75
|
+
setSelectedMcpServers([]);
|
|
76
|
+
}
|
|
77
|
+
if (!enabled) {
|
|
78
|
+
setAllowDirectToolCalls(false);
|
|
79
|
+
setEnableToolReranker(false);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
63
82
|
// UI state
|
|
64
83
|
const [activeSession, setActiveSession] = useState('session-1');
|
|
65
84
|
const [richEditor, setRichEditor] = useState(false);
|
|
66
85
|
const [durable, setDurable] = useState(true);
|
|
67
|
-
const [codemode,
|
|
86
|
+
const [codemode, _] = useState(false);
|
|
68
87
|
const [showContextTree, setShowContextTree] = useState(false);
|
|
69
88
|
const [showNotebook] = useState(true);
|
|
70
89
|
const [leftPaneVisible, setLeftPaneVisible] = useState(true);
|
|
@@ -116,8 +135,13 @@ const AgentSpaceFormExample = () => {
|
|
|
116
135
|
description: `Agent created via UI (${agentLibrary})`,
|
|
117
136
|
agent_library: agentLibrary,
|
|
118
137
|
transport: transport,
|
|
119
|
-
model:
|
|
138
|
+
model: model,
|
|
120
139
|
system_prompt: 'You are a helpful AI assistant.',
|
|
140
|
+
enable_skills: enableSkills,
|
|
141
|
+
enable_codemode: enableCodemode,
|
|
142
|
+
allow_direct_tool_calls: allowDirectToolCalls,
|
|
143
|
+
enable_tool_reranker: enableToolReranker,
|
|
144
|
+
selected_mcp_servers: enableCodemode ? [] : selectedMcpServers,
|
|
121
145
|
}),
|
|
122
146
|
});
|
|
123
147
|
if (!response.ok) {
|
|
@@ -139,7 +163,18 @@ const AgentSpaceFormExample = () => {
|
|
|
139
163
|
finally {
|
|
140
164
|
setIsCreatingAgent(false);
|
|
141
165
|
}
|
|
142
|
-
}, [
|
|
166
|
+
}, [
|
|
167
|
+
baseUrl,
|
|
168
|
+
agentName,
|
|
169
|
+
agentLibrary,
|
|
170
|
+
transport,
|
|
171
|
+
model,
|
|
172
|
+
enableSkills,
|
|
173
|
+
enableCodemode,
|
|
174
|
+
allowDirectToolCalls,
|
|
175
|
+
enableToolReranker,
|
|
176
|
+
selectedMcpServers,
|
|
177
|
+
]);
|
|
143
178
|
/**
|
|
144
179
|
* Delete an agent via the API
|
|
145
180
|
*/
|
|
@@ -206,7 +241,7 @@ const AgentSpaceFormExample = () => {
|
|
|
206
241
|
};
|
|
207
242
|
return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(DatalayerThemeProvider, { theme: datalayerTheme, children: _jsxs(PageLayout, { containerWidth: "full", children: [_jsx(Header, { activeSession: activeSession, agentName: selectedAgentId === 'new-agent' ? undefined : currentAgent?.name, agentDescription: selectedAgentId === 'new-agent'
|
|
208
243
|
? undefined
|
|
209
|
-
: currentAgent?.description, agentStatus: currentAgent?.status, richEditor: richEditor, durable: durable,
|
|
244
|
+
: currentAgent?.description, agentStatus: currentAgent?.status, richEditor: richEditor, durable: durable, showContextTree: showContextTree, isNewAgent: selectedAgentId === 'new-agent', isConfigured: isConfigured, onSessionChange: setActiveSession, onRichEditorChange: setRichEditor, onDurableChange: setDurable, onToggleContextTree: () => setShowContextTree(!showContextTree), onToggleStatus: currentAgent
|
|
210
245
|
? () => toggleAgentStatus(currentAgent.id)
|
|
211
246
|
: undefined }), leftPaneVisible ? (_jsxs(_Fragment, { children: [_jsx(Box, { sx: {
|
|
212
247
|
position: 'fixed',
|
|
@@ -249,9 +284,9 @@ const AgentSpaceFormExample = () => {
|
|
|
249
284
|
display: 'flex',
|
|
250
285
|
flexDirection: 'column',
|
|
251
286
|
p: 2,
|
|
252
|
-
}, children: !isConfigured ? (_jsx(AgentConfiguration, { agentLibrary: agentLibrary, transport: currentAgent?.transport || transport, extensions: extensions, wsUrl: wsUrl, baseUrl: baseUrl, agentName: agentName, agents: agents, selectedAgentId: selectedAgentId, isCreatingAgent: isCreatingAgent, createError: createError, onAgentLibraryChange: setAgentLibrary, onTransportChange: setTransport, onExtensionsChange: setExtensions, onWsUrlChange: setWsUrl, onBaseUrlChange: setBaseUrl, onAgentNameChange: setAgentName, onAgentSelect: handleAgentSelect, onConnect: handleConnect })) : (
|
|
287
|
+
}, children: !isConfigured ? (_jsx(AgentConfiguration, { agentLibrary: agentLibrary, transport: currentAgent?.transport || transport, extensions: extensions, wsUrl: wsUrl, baseUrl: baseUrl, agentName: agentName, model: model, agents: agents, selectedAgentId: selectedAgentId, isCreatingAgent: isCreatingAgent, createError: createError, enableSkills: enableSkills, enableCodemode: enableCodemode, allowDirectToolCalls: allowDirectToolCalls, enableToolReranker: enableToolReranker, selectedMcpServers: selectedMcpServers, onAgentLibraryChange: setAgentLibrary, onTransportChange: setTransport, onExtensionsChange: setExtensions, onWsUrlChange: setWsUrl, onBaseUrlChange: setBaseUrl, onAgentNameChange: setAgentName, onModelChange: setModel, onAgentSelect: handleAgentSelect, onConnect: handleConnect, onEnableSkillsChange: setEnableSkills, onEnableCodemodeChange: handleEnableCodemodeChange, onAllowDirectToolCallsChange: setAllowDirectToolCalls, onEnableToolRerankerChange: setEnableToolReranker, onSelectedMcpServersChange: setSelectedMcpServers })) : (
|
|
253
288
|
/* Chat Interface */
|
|
254
|
-
_jsx(Box, { sx: { flex: 1 }, children: _jsx(Chat, { transport: currentAgent?.transport || transport, extensions: extensions, wsUrl: wsUrl, baseUrl: baseUrl, agentId: currentAgent?.id || agentName, title: currentAgent?.name || agentName || 'AI Assistant', autoConnect: true, autoFocus: true, placeholder: "Type your message to the agent...", height: "calc(100vh - 250px)", suggestions: [
|
|
289
|
+
_jsx(Box, { sx: { flex: 1 }, children: _jsx(Chat, { transport: currentAgent?.transport || transport, extensions: extensions, wsUrl: wsUrl, baseUrl: baseUrl, agentId: currentAgent?.id || agentName, title: currentAgent?.name || agentName || 'AI Assistant', autoConnect: true, autoFocus: true, placeholder: "Type your message to the agent...", height: "calc(100vh - 250px)", showModelSelector: true, showToolsMenu: true, initialModel: model, initialMcpServers: selectedMcpServers, suggestions: [
|
|
255
290
|
{
|
|
256
291
|
title: '👋 Say hello',
|
|
257
292
|
message: 'Hello! What can you help me with today?',
|
|
@@ -43,6 +43,16 @@ declare const EXTENSIONS: {
|
|
|
43
43
|
label: string;
|
|
44
44
|
description: string;
|
|
45
45
|
}[];
|
|
46
|
+
/**
|
|
47
|
+
* AI Model configuration from backend
|
|
48
|
+
*/
|
|
49
|
+
export interface AIModelConfig {
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
builtinTools?: string[];
|
|
53
|
+
requiredEnvVars?: string[];
|
|
54
|
+
isAvailable?: boolean;
|
|
55
|
+
}
|
|
46
56
|
interface AgentConfigurationProps {
|
|
47
57
|
agentLibrary: AgentLibrary;
|
|
48
58
|
transport: Transport;
|
|
@@ -50,18 +60,30 @@ interface AgentConfigurationProps {
|
|
|
50
60
|
wsUrl: string;
|
|
51
61
|
baseUrl: string;
|
|
52
62
|
agentName: string;
|
|
63
|
+
model: string;
|
|
53
64
|
agents: readonly Agent[];
|
|
54
65
|
selectedAgentId: string;
|
|
55
66
|
isCreatingAgent?: boolean;
|
|
56
67
|
createError?: string | null;
|
|
68
|
+
enableSkills?: boolean;
|
|
69
|
+
enableCodemode?: boolean;
|
|
70
|
+
allowDirectToolCalls?: boolean;
|
|
71
|
+
enableToolReranker?: boolean;
|
|
72
|
+
selectedMcpServers?: string[];
|
|
57
73
|
onAgentLibraryChange: (library: AgentLibrary) => void;
|
|
58
74
|
onTransportChange: (transport: Transport) => void;
|
|
59
75
|
onExtensionsChange: (extensions: Extension[]) => void;
|
|
60
76
|
onWsUrlChange: (url: string) => void;
|
|
61
77
|
onBaseUrlChange: (url: string) => void;
|
|
62
78
|
onAgentNameChange: (name: string) => void;
|
|
79
|
+
onModelChange: (model: string) => void;
|
|
63
80
|
onAgentSelect: (agentId: string) => void;
|
|
64
81
|
onConnect: () => void;
|
|
82
|
+
onEnableSkillsChange?: (enabled: boolean) => void;
|
|
83
|
+
onEnableCodemodeChange?: (enabled: boolean) => void;
|
|
84
|
+
onAllowDirectToolCallsChange?: (enabled: boolean) => void;
|
|
85
|
+
onEnableToolRerankerChange?: (enabled: boolean) => void;
|
|
86
|
+
onSelectedMcpServersChange?: (servers: string[]) => void;
|
|
65
87
|
}
|
|
66
88
|
/**
|
|
67
89
|
* Agent Configuration Component
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* Distributed under the terms of the Modified BSD License.
|
|
5
|
-
*/
|
|
6
|
-
import React from 'react';
|
|
7
|
-
import { Text, TextInput, Button, FormControl, Select, Checkbox, Spinner, Flash, Label, ActionList, } from '@primer/react';
|
|
8
|
-
import { CheckIcon, XIcon, ToolsIcon } from '@primer/octicons-react';
|
|
2
|
+
import { Text, TextInput, Button, FormControl, Select, Checkbox, Spinner, Flash, Label, } from '@primer/react';
|
|
3
|
+
import { ToolsIcon } from '@primer/octicons-react';
|
|
9
4
|
import { useQuery } from '@tanstack/react-query';
|
|
10
5
|
import { Box } from '@datalayer/primer-addons';
|
|
11
6
|
const AGENT_LIBRARIES = [
|
|
@@ -71,7 +66,7 @@ const EXTENSIONS = [
|
|
|
71
66
|
*
|
|
72
67
|
* Form for configuring agent connection settings.
|
|
73
68
|
*/
|
|
74
|
-
export const AgentConfiguration = ({ agentLibrary, transport, extensions, wsUrl, baseUrl, agentName, agents, selectedAgentId, isCreatingAgent = false, createError = null, onAgentLibraryChange, onTransportChange, onExtensionsChange, onWsUrlChange, onBaseUrlChange, onAgentNameChange, onAgentSelect, onConnect, }) => {
|
|
69
|
+
export const AgentConfiguration = ({ agentLibrary, transport, extensions, wsUrl, baseUrl, agentName, model, agents, selectedAgentId, isCreatingAgent = false, createError = null, enableSkills = false, enableCodemode = false, allowDirectToolCalls = false, enableToolReranker = false, selectedMcpServers = [], onAgentLibraryChange, onTransportChange, onExtensionsChange, onWsUrlChange, onBaseUrlChange, onAgentNameChange, onModelChange, onAgentSelect, onConnect, onEnableSkillsChange, onEnableCodemodeChange, onAllowDirectToolCallsChange, onEnableToolRerankerChange, onSelectedMcpServersChange, }) => {
|
|
75
70
|
// Fetch MCP servers configuration from the backend
|
|
76
71
|
const configQuery = useQuery({
|
|
77
72
|
queryKey: ['agent-config', baseUrl],
|
|
@@ -87,6 +82,18 @@ export const AgentConfiguration = ({ agentLibrary, transport, extensions, wsUrl,
|
|
|
87
82
|
retry: 1,
|
|
88
83
|
});
|
|
89
84
|
const mcpServers = configQuery.data?.mcpServers || [];
|
|
85
|
+
const models = configQuery.data?.models || [];
|
|
86
|
+
// Handle MCP server checkbox change
|
|
87
|
+
const handleMcpServerChange = (serverId, checked) => {
|
|
88
|
+
if (checked) {
|
|
89
|
+
onSelectedMcpServersChange?.([...selectedMcpServers, serverId]);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
onSelectedMcpServersChange?.(selectedMcpServers.filter(id => id !== serverId));
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
// MCP servers are disabled when codemode is enabled
|
|
96
|
+
const mcpServersDisabled = enableCodemode || selectedAgentId !== 'new-agent';
|
|
90
97
|
// Determine which extensions are enabled based on transport
|
|
91
98
|
const isExtensionEnabled = (ext) => {
|
|
92
99
|
if (selectedAgentId !== 'new-agent')
|
|
@@ -119,7 +126,14 @@ export const AgentConfiguration = ({ agentLibrary, transport, extensions, wsUrl,
|
|
|
119
126
|
marginBottom: 3,
|
|
120
127
|
}, children: "Create a new Agent" }), _jsxs(FormControl, { sx: { marginBottom: 3 }, children: [_jsx(FormControl.Label, { children: "Available Agents" }), _jsxs(Select, { value: selectedAgentId, onChange: e => onAgentSelect(e.target.value), sx: { width: '100%' }, children: [_jsx(Select.Option, { value: "new-agent", children: "+ New Agent..." }), agents.map(agent => (_jsxs(Select.Option, { value: agent.id, children: [agent.status === 'running' && '● ', agent.name] }, agent.id)))] }), _jsx(FormControl.Caption, { children: selectedAgentId === 'new-agent'
|
|
121
128
|
? 'Configure a new custom agent'
|
|
122
|
-
: 'Selected agent - form fields below are disabled' })] }), _jsxs(Box, { sx: { display: 'flex', gap: 3, marginBottom: 3 }, children: [_jsxs(FormControl, { sx: { flex: 1 }, children: [_jsx(FormControl.Label, { children: "Agent Library" }), _jsx(Select, { value: agentLibrary, onChange: e => onAgentLibraryChange(e.target.value), disabled: selectedAgentId !== 'new-agent', sx: { width: '100%' }, children: AGENT_LIBRARIES.map(lib => (_jsxs(Select.Option, { value: lib.value, disabled: lib.disabled, children: [lib.label, lib.disabled && ' (Coming Soon)'] }, lib.value))) })] }), _jsxs(FormControl, { sx: { flex: 1 }, children: [_jsx(FormControl.Label, { children: "Transport" }), _jsx(Select, { value: transport, onChange: e => onTransportChange(e.target.value), disabled: selectedAgentId !== 'new-agent', sx: { width: '100%' }, children: TRANSPORTS.map(t => (_jsx(Select.Option, { value: t.value, children: t.label }, t.value))) })] }), _jsxs(FormControl, { sx: { flex: 1 }, children: [_jsx(FormControl.Label, { children: "Extensions" }), _jsx(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: EXTENSIONS.map(ext => (_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { value: ext.value, checked: extensions.includes(ext.value), disabled: !isExtensionEnabled(ext.value), onChange: e => handleExtensionChange(ext.value, e.target.checked) }), _jsx(Text, { children: ext.label })] }, ext.value))) })] })] }), _jsxs(
|
|
129
|
+
: 'Selected agent - form fields below are disabled' })] }), _jsxs(Box, { sx: { display: 'flex', gap: 3, marginBottom: 3 }, children: [_jsxs(FormControl, { sx: { flex: 1 }, children: [_jsx(FormControl.Label, { children: "Agent Library" }), _jsx(Select, { value: agentLibrary, onChange: e => onAgentLibraryChange(e.target.value), disabled: selectedAgentId !== 'new-agent', sx: { width: '100%' }, children: AGENT_LIBRARIES.map(lib => (_jsxs(Select.Option, { value: lib.value, disabled: lib.disabled, children: [lib.label, lib.disabled && ' (Coming Soon)'] }, lib.value))) })] }), _jsxs(FormControl, { sx: { flex: 1 }, children: [_jsx(FormControl.Label, { children: "Model" }), _jsx(Select, { value: model, onChange: e => onModelChange(e.target.value), disabled: selectedAgentId !== 'new-agent' || models.length === 0, sx: { width: '100%' }, children: models.length === 0 ? (_jsx(Select.Option, { value: "", children: "Loading models..." })) : (models.map(m => (_jsxs(Select.Option, { value: m.id, disabled: !m.isAvailable, children: [m.name, !m.isAvailable && ' (API key required)'] }, m.id)))) })] }), _jsxs(FormControl, { sx: { flex: 1 }, children: [_jsx(FormControl.Label, { children: "Transport" }), _jsx(Select, { value: transport, onChange: e => onTransportChange(e.target.value), disabled: selectedAgentId !== 'new-agent', sx: { width: '100%' }, children: TRANSPORTS.map(t => (_jsx(Select.Option, { value: t.value, children: t.label }, t.value))) })] }), _jsxs(FormControl, { sx: { flex: 1 }, children: [_jsx(FormControl.Label, { children: "Extensions" }), _jsx(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: EXTENSIONS.map(ext => (_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { value: ext.value, checked: extensions.includes(ext.value), disabled: !isExtensionEnabled(ext.value), onChange: e => handleExtensionChange(ext.value, e.target.checked) }), _jsx(Text, { children: ext.label })] }, ext.value))) })] })] }), _jsxs(Box, { sx: {
|
|
130
|
+
marginBottom: 3,
|
|
131
|
+
padding: 3,
|
|
132
|
+
border: '1px solid',
|
|
133
|
+
borderColor: 'border.default',
|
|
134
|
+
borderRadius: 2,
|
|
135
|
+
backgroundColor: 'canvas.default',
|
|
136
|
+
}, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold', display: 'block', mb: 2 }, children: "Agent Capabilities" }), _jsxs(Box, { sx: { display: 'flex', gap: 4 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: enableSkills, disabled: selectedAgentId !== 'new-agent', onChange: e => onEnableSkillsChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Skills" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Enable reusable skill compositions" })] })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: enableCodemode, disabled: selectedAgentId !== 'new-agent', onChange: e => onEnableCodemodeChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Codemode" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Execute code to compose tools" })] })] })] }), enableSkills && enableCodemode && (_jsx(Flash, { variant: "default", sx: { mt: 3 }, children: _jsx(Text, { sx: { fontSize: 0 }, children: "Skills provide curated capabilities; Codemode composes tools with Python for multi-step execution." }) })), enableCodemode && (_jsxs(Box, { sx: { mt: 3, display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: allowDirectToolCalls, disabled: selectedAgentId !== 'new-agent', onChange: e => onAllowDirectToolCallsChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Allow direct tool calls" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Expose call_tool for simple, single-tool operations" })] })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: enableToolReranker, disabled: selectedAgentId !== 'new-agent', onChange: e => onEnableToolRerankerChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Enable tool reranker" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Reorder search results using the configured reranker" })] })] })] }))] }), _jsxs(FormControl, { sx: { marginBottom: 3 }, children: [_jsx(FormControl.Label, { children: transport === 'acp' ? 'WebSocket URL' : 'Base URL' }), _jsx(TextInput, { value: transport === 'acp' ? wsUrl : baseUrl, onChange: e => transport === 'acp'
|
|
123
137
|
? onWsUrlChange(e.target.value)
|
|
124
138
|
: onBaseUrlChange(e.target.value), disabled: selectedAgentId !== 'new-agent', placeholder: transport === 'acp'
|
|
125
139
|
? 'ws://localhost:8000/api/v1/acp/ws'
|
|
@@ -139,7 +153,20 @@ export const AgentConfiguration = ({ agentLibrary, transport, extensions, wsUrl,
|
|
|
139
153
|
marginBottom: 2,
|
|
140
154
|
}, children: [_jsx(ToolsIcon, { size: 16 }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold' }, children: "MCP Servers" }), configQuery.isLoading && _jsx(Spinner, { size: "small" })] }), configQuery.isError && (_jsx(Flash, { variant: "warning", sx: { marginBottom: 2 }, children: _jsx(Text, { sx: { fontSize: 0 }, children: "Unable to fetch MCP servers. Check that the server is running." }) })), mcpServers.length === 0 &&
|
|
141
155
|
!configQuery.isLoading &&
|
|
142
|
-
!configQuery.isError && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "No MCP servers configured." })),
|
|
156
|
+
!configQuery.isError && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "No MCP servers configured." })), enableCodemode && (_jsx(Flash, { variant: "warning", sx: { marginBottom: 2 }, children: _jsx(Text, { sx: { fontSize: 0 }, children: "MCP servers are disabled when Codemode is enabled. Codemode provides its own tool discovery and execution." }) })), mcpServers.length > 0 && (_jsx(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: mcpServers.map(server => (_jsxs(Box, { sx: {
|
|
157
|
+
display: 'flex',
|
|
158
|
+
alignItems: 'flex-start',
|
|
159
|
+
gap: 2,
|
|
160
|
+
padding: 2,
|
|
161
|
+
borderRadius: 1,
|
|
162
|
+
backgroundColor: 'canvas.subtle',
|
|
163
|
+
opacity: mcpServersDisabled || !server.isAvailable ? 0.6 : 1,
|
|
164
|
+
}, children: [_jsx(Checkbox, { checked: !enableCodemode && selectedMcpServers.includes(server.id), disabled: mcpServersDisabled || !server.isAvailable, onChange: e => handleMcpServerChange(server.id, e.target.checked) }), _jsxs(Box, { sx: {
|
|
165
|
+
display: 'flex',
|
|
166
|
+
flexDirection: 'column',
|
|
167
|
+
gap: 1,
|
|
168
|
+
flex: 1,
|
|
169
|
+
}, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Text, { sx: { fontWeight: 'semibold' }, children: server.name }), _jsx(Label, { variant: server.isAvailable ? 'success' : 'secondary', size: "small", children: server.isAvailable ? 'Available' : 'Not Available' })] }), server.tools.length > 0 && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["Tools: ", server.tools.map(t => t.name).join(', ')] }))] })] }, server.id))) }))] }), createError && (_jsx(Flash, { variant: "danger", sx: { marginBottom: 3 }, children: createError })), _jsx(Button, { variant: "primary", onClick: onConnect, disabled: isCreatingAgent ||
|
|
143
170
|
!agentName ||
|
|
144
171
|
(transport === 'acp' ? !wsUrl : !baseUrl), sx: { width: '100%' }, children: isCreatingAgent ? (_jsxs(Box, { sx: {
|
|
145
172
|
display: 'flex',
|
|
@@ -6,14 +6,12 @@ interface HeaderProps {
|
|
|
6
6
|
agentStatus?: 'running' | 'paused';
|
|
7
7
|
richEditor: boolean;
|
|
8
8
|
durable: boolean;
|
|
9
|
-
codemode: boolean;
|
|
10
9
|
showContextTree: boolean;
|
|
11
10
|
isNewAgent?: boolean;
|
|
12
11
|
isConfigured?: boolean;
|
|
13
12
|
onSessionChange: (sessionId: string) => void;
|
|
14
13
|
onRichEditorChange: (value: boolean) => void;
|
|
15
14
|
onDurableChange: (value: boolean) => void;
|
|
16
|
-
onCodemodeChange: (value: boolean) => void;
|
|
17
15
|
onToggleContextTree: () => void;
|
|
18
16
|
onToggleStatus?: () => void;
|
|
19
17
|
}
|
|
@@ -112,7 +112,7 @@ const OPTIMIZED_CONTEXT_DATA = {
|
|
|
112
112
|
* Main header for the agent runtime interface with session tabs,
|
|
113
113
|
* toggle switches, controls, and optional context treemap.
|
|
114
114
|
*/
|
|
115
|
-
export const Header = ({ activeSession, agentName, agentDescription, agentStatus, richEditor, durable,
|
|
115
|
+
export const Header = ({ activeSession, agentName, agentDescription, agentStatus, richEditor, durable, showContextTree, isNewAgent = false, isConfigured = false, onSessionChange, onRichEditorChange, onDurableChange, onToggleContextTree, onToggleStatus, }) => {
|
|
116
116
|
const [isOptimizing, setIsOptimizing] = useState(false);
|
|
117
117
|
const [contextData, setContextData] = useState(MOCK_CONTEXT_DATA);
|
|
118
118
|
const [totalTokens, setTotalTokens] = useState('1.52M');
|
|
@@ -121,7 +121,6 @@ export const Header = ({ activeSession, agentName, agentDescription, agentStatus
|
|
|
121
121
|
const [openOverlay, setOpenOverlay] = useState(null);
|
|
122
122
|
const richEditorRef = useRef(null);
|
|
123
123
|
const durableRef = useRef(null);
|
|
124
|
-
const codemodeRef = useRef(null);
|
|
125
124
|
const handleOptimize = () => {
|
|
126
125
|
setIsOptimizing(true);
|
|
127
126
|
setTimeout(() => {
|
|
@@ -142,20 +141,7 @@ export const Header = ({ activeSession, agentName, agentDescription, agentStatus
|
|
|
142
141
|
alignItems: 'center',
|
|
143
142
|
gap: 3,
|
|
144
143
|
marginLeft: 'auto',
|
|
145
|
-
}, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(ToggleSwitch, { size: "small", checked:
|
|
146
|
-
p: 3,
|
|
147
|
-
maxWidth: '300px',
|
|
148
|
-
bg: 'canvas.overlay',
|
|
149
|
-
border: '1px solid',
|
|
150
|
-
borderColor: 'border.default',
|
|
151
|
-
borderRadius: 2,
|
|
152
|
-
boxShadow: 'shadow.large',
|
|
153
|
-
}, children: [_jsx(Text, { sx: {
|
|
154
|
-
fontSize: 0,
|
|
155
|
-
display: 'block',
|
|
156
|
-
mb: 1,
|
|
157
|
-
fontWeight: 'bold',
|
|
158
|
-
}, children: "Codemode" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Optimize the agent for code-focused tasks including code generation, debugging, and technical problem-solving." })] }) })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(ToggleSwitch, { size: "small", checked: richEditor, onClick: () => onRichEditorChange(!richEditor), "aria-labelledby": "rich-editor-label", disabled: isNewAgent || !isConfigured }), _jsx(Text, { id: "rich-editor-label", sx: { fontSize: 0 }, children: "Rich Editor" }), _jsx(IconButton, { ref: richEditorRef, icon: InfoIcon, size: "small", variant: "invisible", "aria-label": "Rich Editor info", onClick: () => setOpenOverlay(openOverlay === 'richEditor' ? null : 'richEditor') }), _jsx(AnchoredOverlay, { open: openOverlay === 'richEditor', onOpen: () => setOpenOverlay('richEditor'), onClose: () => setOpenOverlay(null), renderAnchor: () => _jsx("span", {}), anchorRef: richEditorRef, children: _jsxs(Box, { sx: {
|
|
144
|
+
}, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(ToggleSwitch, { size: "small", checked: richEditor, onClick: () => onRichEditorChange(!richEditor), "aria-labelledby": "rich-editor-label", disabled: isNewAgent || !isConfigured }), _jsx(Text, { id: "rich-editor-label", sx: { fontSize: 0 }, children: "Rich Editor" }), _jsx(IconButton, { ref: richEditorRef, icon: InfoIcon, size: "small", variant: "invisible", "aria-label": "Rich Editor info", onClick: () => setOpenOverlay(openOverlay === 'richEditor' ? null : 'richEditor') }), _jsx(AnchoredOverlay, { open: openOverlay === 'richEditor', onOpen: () => setOpenOverlay('richEditor'), onClose: () => setOpenOverlay(null), renderAnchor: () => _jsx("span", {}), anchorRef: richEditorRef, children: _jsxs(Box, { sx: {
|
|
159
145
|
p: 3,
|
|
160
146
|
maxWidth: '300px',
|
|
161
147
|
bg: 'canvas.overlay',
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime management module for agent-runtimes.
|
|
3
|
+
*
|
|
4
|
+
* Provides a Zustand store and hooks for launching and managing cloud runtimes
|
|
5
|
+
* with integrated AI agent support.
|
|
6
|
+
*
|
|
7
|
+
* @module runtime
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { useRuntimeStore, useRuntime, useAgent } from '@datalayer/agent-runtimes/lib/runtime';
|
|
12
|
+
*
|
|
13
|
+
* // Launch a new runtime
|
|
14
|
+
* const { launchRuntime, createAgent } = useRuntimeStore();
|
|
15
|
+
* const runtime = await launchRuntime({ environmentName: 'python-simple', creditsLimit: 100 });
|
|
16
|
+
* const agent = await createAgent({ model: 'anthropic:claude-sonnet-4-5' });
|
|
17
|
+
*
|
|
18
|
+
* // Use in ChatFloating
|
|
19
|
+
* <ChatFloating endpoint={agent.endpoint} />
|
|
20
|
+
*
|
|
21
|
+
* // Or connect to an existing runtime
|
|
22
|
+
* const { connectToRuntime } = useRuntimeStore();
|
|
23
|
+
* connectToRuntime({
|
|
24
|
+
* podName: 'my-pod',
|
|
25
|
+
* environmentName: 'python-simple',
|
|
26
|
+
* serviceManager: myServiceManager,
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export { useRuntimeStore, useRuntime, useAgent, useRuntimeStatus, useRuntimeError, useIsLaunching, getRuntimeState, subscribeToRuntime, } from './runtimeStore';
|
|
31
|
+
export { useAgentConnection } from './useAgentConnection';
|
|
32
|
+
export { useAgentRuntime } from './useAgentRuntime';
|
|
33
|
+
export type { IRuntimeLocation, IRuntimeType, IRuntimeCapabilities, IRuntimePod, IRuntimeOptions, IRuntimeDesc, } from './types';
|
|
34
|
+
export type { RuntimeConnection, AgentRuntimeStatus as RuntimeStatus, AgentConfig, AgentConnection, AgentRuntimeState, } from './types';
|
|
35
|
+
export { DEFAULT_AGENT_CONFIG } from './types';
|