@datalayer/agent-runtimes 1.0.3 → 1.0.5
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 +35 -119
- package/lib/App.js +1 -1
- 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 -104
- package/lib/chat/Chat.js +4 -4
- package/lib/chat/ChatFloating.d.ts +7 -140
- package/lib/chat/ChatFloating.js +2 -2
- 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 +2 -2
- package/lib/chat/ChatStandalone.d.ts +4 -54
- package/lib/chat/ChatStandalone.js +3 -3
- package/lib/chat/base/ChatBase.js +1118 -141
- package/lib/chat/header/ChatHeaderBase.d.ts +11 -6
- package/lib/chat/header/ChatHeaderBase.js +18 -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 +9 -9
- 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 +110 -102
- package/lib/chat/prompt/InputFooter.d.ts +19 -6
- package/lib/chat/prompt/InputFooter.js +71 -18
- package/lib/chat/prompt/InputPrompt.d.ts +3 -1
- package/lib/chat/prompt/InputPrompt.js +4 -4
- package/lib/chat/prompt/InputPromptFooter.js +1 -1
- 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 +48 -19
- package/lib/client/AgentsMixin.js +115 -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 +55 -26
- package/lib/components/OutputCard.js +21 -7
- package/lib/components/ToolApprovalCard.js +20 -2
- package/lib/config/AgentConfiguration.js +3 -3
- 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/AgentCheckpointsExample.js +14 -34
- package/lib/examples/AgentCodemodeExample.d.ts +4 -6
- package/lib/examples/AgentCodemodeExample.js +591 -175
- package/lib/examples/AgentEvalsExample.js +13 -23
- package/lib/examples/AgentGuardrailsExample.js +371 -71
- package/lib/examples/AgentHooksExample.d.ts +3 -0
- package/lib/examples/AgentHooksExample.js +104 -0
- package/lib/examples/AgentMCPExample.d.ts +3 -0
- package/lib/examples/AgentMCPExample.js +480 -0
- package/lib/examples/AgentMemoryExample.js +14 -24
- package/lib/examples/AgentMonitoringExample.js +261 -206
- package/lib/examples/AgentNotificationsExample.js +50 -24
- package/lib/examples/AgentOtelExample.js +2 -3
- package/lib/examples/AgentOutputsExample.d.ts +11 -6
- package/lib/examples/AgentOutputsExample.js +383 -88
- package/lib/examples/AgentParametersExample.d.ts +3 -0
- package/lib/examples/AgentParametersExample.js +246 -0
- package/lib/examples/AgentSandboxExample.d.ts +2 -2
- package/lib/examples/AgentSandboxExample.js +69 -47
- package/lib/examples/AgentSkillsExample.js +92 -106
- package/lib/examples/{AgentspecExample.js → AgentSpecsExample.js} +10 -21
- package/lib/examples/AgentSubagentsExample.d.ts +14 -0
- package/lib/examples/AgentSubagentsExample.js +228 -0
- package/lib/examples/AgentToolApprovalsExample.js +30 -493
- package/lib/examples/AgentTriggersExample.js +1067 -246
- package/lib/examples/ChatCustomExample.js +11 -24
- package/lib/examples/ChatExample.js +9 -34
- 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} +65 -16
- 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/ErrorView.d.ts +14 -0
- package/lib/examples/components/ErrorView.js +20 -0
- package/lib/examples/components/ExampleWrapper.d.ts +7 -0
- package/lib/examples/components/ExampleWrapper.js +25 -6
- 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 +5 -0
- package/lib/examples/components/index.js +5 -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 +107 -41
- package/lib/examples/index.d.ts +9 -6
- package/lib/examples/index.js +9 -6
- package/lib/examples/main.d.ts +1 -0
- package/lib/examples/main.js +218 -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/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 +118 -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} +39 -2
- package/lib/hooks/{useAgents.js → useAgentRuntimes.js} +125 -15
- 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 +9 -0
- package/lib/protocols/VercelAIAdapter.js +144 -26
- package/lib/shims/json5.d.ts +4 -0
- package/lib/shims/json5.js +8 -0
- package/lib/specs/agents/agents.d.ts +10 -0
- package/lib/specs/agents/agents.js +752 -24
- package/lib/specs/envvars.d.ts +1 -0
- package/lib/specs/envvars.js +11 -0
- package/lib/specs/events.d.ts +1 -0
- package/lib/specs/events.js +1 -0
- package/lib/specs/index.d.ts +1 -0
- package/lib/specs/index.js +1 -0
- package/lib/specs/personas.d.ts +41 -0
- package/lib/specs/personas.js +168 -0
- package/lib/specs/skills.d.ts +2 -1
- package/lib/specs/skills.js +23 -5
- package/lib/specs/tools.js +3 -0
- package/lib/stores/agentRuntimeStore.d.ts +204 -0
- package/lib/stores/agentRuntimeStore.js +636 -0
- 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/agentspecs.d.ts +50 -1
- package/lib/types/chat.d.ts +309 -8
- package/lib/types/context.d.ts +27 -0
- package/lib/types/cost.d.ts +2 -2
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.js +2 -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/types/tools.d.ts +2 -0
- package/lib/utils/utils.d.ts +9 -5
- package/lib/utils/utils.js +9 -5
- package/package.json +13 -9
- package/scripts/codegen/__pycache__/generate_agents.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 +106 -7
- package/scripts/codegen/generate_events.py +47 -17
- package/scripts/codegen/generate_personas.py +319 -0
- package/scripts/codegen/generate_skills.py +9 -9
- package/scripts/codegen/generate_tools.py +20 -0
- package/scripts/sync-jupyter.sh +26 -7
- package/style/primer-primitives.css +1 -6
- package/lib/api/tool-approvals.d.ts +0 -62
- package/lib/api/tool-approvals.js +0 -145
- 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/scripts/codegen/__pycache__/generate_envvars.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_evals.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_guardrails.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_mcp_servers.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_memory.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_models.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_notifications.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_outputs.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_skills.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_teams.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_tools.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_triggers.cpython-313.pyc +0 -0
- /package/lib/examples/{AgentspecExample.d.ts → AgentSpecsExample.d.ts} +0 -0
- /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
|
@@ -0,0 +1,246 @@
|
|
|
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 { useEffect, useMemo, useState } from 'react';
|
|
7
|
+
import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
|
|
8
|
+
import { Button, Heading, Label, Spinner, Text } from '@primer/react';
|
|
9
|
+
import validator from '@rjsf/validator-ajv8';
|
|
10
|
+
import { Form, yamlSchemaToJsonSchema } from '@datalayer/primer-rjsf';
|
|
11
|
+
import { ThemedProvider } from './utils/themedProvider';
|
|
12
|
+
import { uniqueAgentId } from './utils/agentId';
|
|
13
|
+
import { ErrorView } from './components';
|
|
14
|
+
import { Chat } from '../chat';
|
|
15
|
+
setupPrimerPortals();
|
|
16
|
+
const BASE_URL = 'http://localhost:8765';
|
|
17
|
+
const AGENT_SPEC_ID = 'demo-parameters';
|
|
18
|
+
const AGENT_NAME = 'parameters-demo';
|
|
19
|
+
function isRecord(value) {
|
|
20
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
21
|
+
}
|
|
22
|
+
function looksLikeJsonSchema(value) {
|
|
23
|
+
if (!isRecord(value)) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return (typeof value.type === 'string' ||
|
|
27
|
+
isRecord(value.properties) ||
|
|
28
|
+
Array.isArray(value.required));
|
|
29
|
+
}
|
|
30
|
+
function unwrapTypedLiterals(value) {
|
|
31
|
+
if (Array.isArray(value)) {
|
|
32
|
+
return value.map(unwrapTypedLiterals);
|
|
33
|
+
}
|
|
34
|
+
if (!isRecord(value)) {
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
const keys = Object.keys(value);
|
|
38
|
+
const hasTypedDefault = typeof value.type === 'string' && 'default' in value && keys.length <= 2;
|
|
39
|
+
if (hasTypedDefault) {
|
|
40
|
+
return unwrapTypedLiterals(value.default);
|
|
41
|
+
}
|
|
42
|
+
const normalized = {};
|
|
43
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
44
|
+
normalized[key] = unwrapTypedLiterals(nested);
|
|
45
|
+
}
|
|
46
|
+
return normalized;
|
|
47
|
+
}
|
|
48
|
+
function hasWrappedSchemaLiterals(value) {
|
|
49
|
+
const schema = value;
|
|
50
|
+
const typeIsWrapped = isRecord(schema.type);
|
|
51
|
+
const requiredHasWrapped = Array.isArray(schema.required) &&
|
|
52
|
+
schema.required.some(item => isRecord(item));
|
|
53
|
+
return typeIsWrapped || requiredHasWrapped;
|
|
54
|
+
}
|
|
55
|
+
function toRjsfSchema(parameters) {
|
|
56
|
+
if (looksLikeJsonSchema(parameters)) {
|
|
57
|
+
return parameters;
|
|
58
|
+
}
|
|
59
|
+
const converted = yamlSchemaToJsonSchema(parameters ?? {});
|
|
60
|
+
if (hasWrappedSchemaLiterals(converted)) {
|
|
61
|
+
return unwrapTypedLiterals(converted);
|
|
62
|
+
}
|
|
63
|
+
return converted;
|
|
64
|
+
}
|
|
65
|
+
function collectTopLevelDefaults(schema) {
|
|
66
|
+
const defaults = {};
|
|
67
|
+
const properties = schema.properties && typeof schema.properties === 'object'
|
|
68
|
+
? schema.properties
|
|
69
|
+
: {};
|
|
70
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
71
|
+
if (value &&
|
|
72
|
+
typeof value === 'object' &&
|
|
73
|
+
!Array.isArray(value) &&
|
|
74
|
+
'default' in value) {
|
|
75
|
+
defaults[key] = value.default;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return defaults;
|
|
79
|
+
}
|
|
80
|
+
function hasRequiredValues(schema, formData) {
|
|
81
|
+
if (!schema ||
|
|
82
|
+
!Array.isArray(schema.required) ||
|
|
83
|
+
schema.required.length === 0) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
return schema.required.every(fieldName => {
|
|
87
|
+
if (typeof fieldName !== 'string') {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
const value = formData[fieldName];
|
|
91
|
+
if (value === undefined || value === null) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
if (typeof value === 'string') {
|
|
95
|
+
return value.trim().length > 0;
|
|
96
|
+
}
|
|
97
|
+
if (Array.isArray(value)) {
|
|
98
|
+
return value.length > 0;
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const AgentParametersExample = () => {
|
|
104
|
+
const [showSchemaForm, setShowSchemaForm] = useState(false);
|
|
105
|
+
const [isSchemaLoading, setIsSchemaLoading] = useState(false);
|
|
106
|
+
const [schema, setSchema] = useState(null);
|
|
107
|
+
const [formData, setFormData] = useState({});
|
|
108
|
+
const [agentId, setAgentId] = useState(null);
|
|
109
|
+
const [isCreating, setIsCreating] = useState(false);
|
|
110
|
+
const [error, setError] = useState(null);
|
|
111
|
+
const [formTouched, setFormTouched] = useState(false);
|
|
112
|
+
const hasRequired = useMemo(() => hasRequiredValues(schema, formData), [schema, formData]);
|
|
113
|
+
const canLaunch = useMemo(() => {
|
|
114
|
+
return showSchemaForm && schema !== null && !isSchemaLoading && hasRequired;
|
|
115
|
+
}, [schema, showSchemaForm, isSchemaLoading, hasRequired]);
|
|
116
|
+
const loadSchemaForm = async () => {
|
|
117
|
+
if (schema) {
|
|
118
|
+
setShowSchemaForm(true);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
setIsSchemaLoading(true);
|
|
122
|
+
setError(null);
|
|
123
|
+
try {
|
|
124
|
+
const response = await fetch(`${BASE_URL}/api/v1/agents/library/${AGENT_SPEC_ID}`);
|
|
125
|
+
if (!response.ok) {
|
|
126
|
+
throw new Error(`Failed to load schema: ${response.status}`);
|
|
127
|
+
}
|
|
128
|
+
const data = (await response.json());
|
|
129
|
+
const convertedSchema = toRjsfSchema(data.parameters ?? {});
|
|
130
|
+
setSchema(convertedSchema);
|
|
131
|
+
setFormData(collectTopLevelDefaults(convertedSchema));
|
|
132
|
+
setShowSchemaForm(true);
|
|
133
|
+
setFormTouched(false);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
setError(err instanceof Error ? err.message : 'Failed to load schema');
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
setIsSchemaLoading(false);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
const launchAgent = async () => {
|
|
143
|
+
if (!canLaunch) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
setIsCreating(true);
|
|
147
|
+
setError(null);
|
|
148
|
+
try {
|
|
149
|
+
const name = uniqueAgentId(AGENT_NAME);
|
|
150
|
+
const response = await fetch(`${BASE_URL}/api/v1/agents`, {
|
|
151
|
+
method: 'POST',
|
|
152
|
+
headers: { 'Content-Type': 'application/json' },
|
|
153
|
+
body: JSON.stringify({
|
|
154
|
+
name,
|
|
155
|
+
agent_spec_id: AGENT_SPEC_ID,
|
|
156
|
+
transport: 'vercel-ai',
|
|
157
|
+
agent_parameters: formData,
|
|
158
|
+
}),
|
|
159
|
+
});
|
|
160
|
+
if (!response.ok) {
|
|
161
|
+
const data = await response
|
|
162
|
+
.json()
|
|
163
|
+
.catch(() => ({ detail: 'Unknown error' }));
|
|
164
|
+
throw new Error(data.detail || `Failed to create agent: ${response.status}`);
|
|
165
|
+
}
|
|
166
|
+
const data = await response.json();
|
|
167
|
+
setAgentId(data.id);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
setError(err instanceof Error ? err.message : 'Failed to launch agent');
|
|
171
|
+
}
|
|
172
|
+
finally {
|
|
173
|
+
setIsCreating(false);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
return () => {
|
|
178
|
+
if (!agentId) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
void fetch(`${BASE_URL}/api/v1/agents/${encodeURIComponent(agentId)}`, {
|
|
182
|
+
method: 'DELETE',
|
|
183
|
+
}).catch(() => {
|
|
184
|
+
// Ignore teardown failures in example mode.
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
}, [agentId]);
|
|
188
|
+
if (!agentId) {
|
|
189
|
+
return (_jsx(ThemedProvider, { children: _jsxs(Box, { sx: {
|
|
190
|
+
maxWidth: 760,
|
|
191
|
+
mx: 'auto',
|
|
192
|
+
mt: 6,
|
|
193
|
+
px: 3,
|
|
194
|
+
py: 2,
|
|
195
|
+
border: '1px solid',
|
|
196
|
+
borderColor: 'border.default',
|
|
197
|
+
borderRadius: 2,
|
|
198
|
+
display: 'flex',
|
|
199
|
+
flexDirection: 'column',
|
|
200
|
+
gap: 2,
|
|
201
|
+
bg: 'canvas.subtle',
|
|
202
|
+
}, children: [_jsx(Text, { sx: { fontSize: 0, fontWeight: 'bold', color: 'fg.muted' }, children: "CONFIGURE AGENT" }), _jsx(Heading, { as: "h2", sx: { fontSize: 2 }, children: "Launch Parameterized Agent" }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 1, maxWidth: 620 }, children: "Load the runtime schema directly from demo-parameters, fill the generated form, then launch with validated parameters." }), _jsxs(Box, { sx: {
|
|
203
|
+
display: 'flex',
|
|
204
|
+
alignItems: 'center',
|
|
205
|
+
gap: 2,
|
|
206
|
+
flexWrap: 'wrap',
|
|
207
|
+
}, children: [_jsxs(Label, { variant: "accent", children: ["Spec: ", AGENT_SPEC_ID] }), _jsx(Label, { variant: "secondary", children: "Transport: vercel-ai" })] }), _jsxs(Box, { sx: { display: 'flex', gap: 2, flexWrap: 'wrap' }, children: [_jsx(Button, { variant: "primary", size: "small", type: "button", onClick: loadSchemaForm, disabled: isSchemaLoading, children: isSchemaLoading ? (_jsxs(_Fragment, { children: [_jsx(Spinner, { size: "small" }), " Loading Schema..."] })) : ('Show Parameter Form') }), schema && (_jsx(Button, { variant: "invisible", size: "small", type: "button", onClick: () => {
|
|
208
|
+
setShowSchemaForm(v => !v);
|
|
209
|
+
}, children: showSchemaForm ? 'Hide Form' : 'Show Form' }))] }), schema && (_jsxs(Box, { sx: {
|
|
210
|
+
display: 'flex',
|
|
211
|
+
gap: 2,
|
|
212
|
+
flexWrap: 'wrap',
|
|
213
|
+
alignItems: 'center',
|
|
214
|
+
py: 2,
|
|
215
|
+
px: 3,
|
|
216
|
+
border: '1px solid',
|
|
217
|
+
borderColor: 'border.default',
|
|
218
|
+
borderRadius: 2,
|
|
219
|
+
bg: 'canvas.subtle',
|
|
220
|
+
}, children: [_jsxs(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: ["Required fields:", ' ', Array.isArray(schema.required) ? schema.required.length : 0] }), _jsx(Label, { variant: hasRequired ? 'success' : 'attention', children: hasRequired ? 'Ready to launch' : 'Complete required fields' })] })), showSchemaForm && schema && (_jsx(Box, { sx: {
|
|
221
|
+
border: '1px solid',
|
|
222
|
+
borderColor: 'border.default',
|
|
223
|
+
borderRadius: 2,
|
|
224
|
+
p: 2,
|
|
225
|
+
bg: 'canvas.default',
|
|
226
|
+
}, children: _jsx(Form, { schema: schema, formData: formData, uiSchema: { 'ui:submitButtonOptions': { norender: true } }, validator: validator, onChange: ({ formData: nextData }) => {
|
|
227
|
+
setFormTouched(true);
|
|
228
|
+
setFormData(nextData ?? {});
|
|
229
|
+
}, onSubmit: (_, event) => {
|
|
230
|
+
event?.preventDefault();
|
|
231
|
+
event?.stopPropagation();
|
|
232
|
+
// Prevent implicit form submission; launching is click-only.
|
|
233
|
+
}, noHtml5Validate: true }) })), _jsx(Button, { variant: "primary", size: "small", type: "button", onClick: launchAgent, disabled: !canLaunch || isCreating, sx: { width: '100%' }, children: isCreating ? (_jsxs(_Fragment, { children: [_jsx(Spinner, { size: "small" }), " Launching..."] })) : ('Launch Agent') }), schema && formTouched && (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "Parameters are sent as agent_parameters in the create-agent request." })), error && _jsx(ErrorView, { error: "Launch failed", detail: error })] }) }));
|
|
234
|
+
}
|
|
235
|
+
return (_jsx(Chat, { protocol: "vercel-ai", baseUrl: BASE_URL, agentId: agentId, title: `Parameterized Agent: ${String(formData.project ?? 'Project')}`, placeholder: "Ask something about your configured project...", description: `Role: ${String(formData.role ?? 'n/a')} · Tone: ${String(formData.tone ?? 'n/a')}`, showHeader: true, showModelSelector: true, showToolsMenu: true, showSkillsMenu: true, showTokenUsage: true, showInformation: true, autoFocus: true, height: "100vh", runtimeId: agentId, historyEndpoint: `${BASE_URL}/api/v1/history`, suggestions: [
|
|
236
|
+
{
|
|
237
|
+
title: 'Print demo_params',
|
|
238
|
+
message: 'Use execute_code to print(demo_params) from the sandbox, then explain what it is.',
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
title: 'Inspect demo_params',
|
|
242
|
+
message: "Use execute_code to print('demo_params =', demo_params) and confirm its type.",
|
|
243
|
+
},
|
|
244
|
+
], submitOnSuggestionClick: true }));
|
|
245
|
+
};
|
|
246
|
+
export default AgentParametersExample;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AgentSandboxExample
|
|
3
3
|
*
|
|
4
|
-
* Demonstrates sandbox variant switching (
|
|
4
|
+
* Demonstrates sandbox variant switching (eval / jupyter) with a live
|
|
5
5
|
* sidebar that streams WebSocket messages to and from the
|
|
6
6
|
* `/configure/sandbox/ws` endpoint.
|
|
7
7
|
*
|
|
8
8
|
* - Creates a local agent (spec: demo-full) with codemode enabled
|
|
9
|
-
* - SegmentedControl toggles between "
|
|
9
|
+
* - SegmentedControl toggles between "eval" and "jupyter" variants
|
|
10
10
|
* - Sidebar shows live sandbox status, WebSocket event log, and an
|
|
11
11
|
* interrupt button
|
|
12
12
|
*
|
|
@@ -6,12 +6,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
/**
|
|
7
7
|
* AgentSandboxExample
|
|
8
8
|
*
|
|
9
|
-
* Demonstrates sandbox variant switching (
|
|
9
|
+
* Demonstrates sandbox variant switching (eval / jupyter) with a live
|
|
10
10
|
* sidebar that streams WebSocket messages to and from the
|
|
11
11
|
* `/configure/sandbox/ws` endpoint.
|
|
12
12
|
*
|
|
13
13
|
* - Creates a local agent (spec: demo-full) with codemode enabled
|
|
14
|
-
* - SegmentedControl toggles between "
|
|
14
|
+
* - SegmentedControl toggles between "eval" and "jupyter" variants
|
|
15
15
|
* - Sidebar shows live sandbox status, WebSocket event log, and an
|
|
16
16
|
* interrupt button
|
|
17
17
|
*
|
|
@@ -21,12 +21,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
21
21
|
import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
22
22
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
23
23
|
import { Box } from '@datalayer/primer-addons';
|
|
24
|
+
import { AuthRequiredView, ErrorView } from './components';
|
|
24
25
|
import { Button, Flash, Heading, Label, SegmentedControl, Spinner, Text, } from '@primer/react';
|
|
25
|
-
import {
|
|
26
|
+
import { CodeIcon, StopIcon, TerminalIcon } from '@primer/octicons-react';
|
|
26
27
|
import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel';
|
|
27
|
-
import { SignInSimple } from '@datalayer/core/lib/views/iam';
|
|
28
|
-
import { UserBadge } from '@datalayer/core/lib/views/profile';
|
|
29
28
|
import { ThemedProvider } from './utils/themedProvider';
|
|
29
|
+
import { uniqueAgentId } from './utils/agentId';
|
|
30
30
|
import { Chat } from '../chat';
|
|
31
31
|
import { SANDBOX_STATUS_COLORS, SANDBOX_STATUS_LABELS } from '../types/sandbox';
|
|
32
32
|
// ─── Constants ─────────────────────────────────────────────────────────────
|
|
@@ -61,16 +61,18 @@ function apiVariantFromUi(variant) {
|
|
|
61
61
|
// ─── Inner component (after auth) ──────────────────────────────────────────
|
|
62
62
|
const AgentSandboxInner = ({ onLogout, }) => {
|
|
63
63
|
const { token } = useSimpleAuthStore();
|
|
64
|
+
const agentName = useRef(uniqueAgentId(AGENT_NAME)).current;
|
|
64
65
|
const chatAuthToken = token === null ? undefined : token;
|
|
65
66
|
const agentBaseUrl = DEFAULT_LOCAL_BASE_URL;
|
|
66
67
|
// ── Agent lifecycle ──
|
|
67
68
|
const [runtimeStatus, setRuntimeStatus] = useState('launching');
|
|
68
69
|
const [isReady, setIsReady] = useState(false);
|
|
69
70
|
const [hookError, setHookError] = useState(null);
|
|
70
|
-
const [agentId, setAgentId] = useState(
|
|
71
|
+
const [agentId, setAgentId] = useState(agentName);
|
|
71
72
|
const [isReconnectedAgent, setIsReconnectedAgent] = useState(false);
|
|
72
73
|
// ── Sandbox variant toggle ──
|
|
73
|
-
const [variant, setVariant] = useState('
|
|
74
|
+
const [variant, setVariant] = useState('eval');
|
|
75
|
+
const [pendingVariant, setPendingVariant] = useState(null);
|
|
74
76
|
const [variantSwitching, setVariantSwitching] = useState(false);
|
|
75
77
|
const [lastSwitch, setLastSwitch] = useState(null);
|
|
76
78
|
// ── WebSocket state ──
|
|
@@ -106,7 +108,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
106
108
|
try {
|
|
107
109
|
// Always delete any existing agent with this name first so we
|
|
108
110
|
// recreate it with the latest configuration (system prompt, toolsets).
|
|
109
|
-
await authFetch(`${agentBaseUrl}/api/v1/agents/${
|
|
111
|
+
await authFetch(`${agentBaseUrl}/api/v1/agents/${agentName}`, {
|
|
110
112
|
method: 'DELETE',
|
|
111
113
|
}).catch(() => {
|
|
112
114
|
/* ignore 404 / not-found */
|
|
@@ -114,7 +116,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
114
116
|
const response = await authFetch(`${agentBaseUrl}/api/v1/agents`, {
|
|
115
117
|
method: 'POST',
|
|
116
118
|
body: JSON.stringify({
|
|
117
|
-
name:
|
|
119
|
+
name: agentName,
|
|
118
120
|
description: 'Agent with sandbox code execution',
|
|
119
121
|
agent_library: 'pydantic-ai',
|
|
120
122
|
transport: 'vercel-ai',
|
|
@@ -128,13 +130,13 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
128
130
|
tools: [],
|
|
129
131
|
selected_mcp_servers: [],
|
|
130
132
|
enable_codemode: true,
|
|
131
|
-
sandbox_variant: '
|
|
133
|
+
sandbox_variant: 'eval',
|
|
132
134
|
}),
|
|
133
135
|
});
|
|
134
|
-
let resolvedAgentId =
|
|
136
|
+
let resolvedAgentId = agentName;
|
|
135
137
|
if (response.ok) {
|
|
136
138
|
const data = await response.json();
|
|
137
|
-
resolvedAgentId = data?.id ||
|
|
139
|
+
resolvedAgentId = data?.id || agentName;
|
|
138
140
|
}
|
|
139
141
|
else {
|
|
140
142
|
const contentType = response.headers.get('content-type') || '';
|
|
@@ -165,11 +167,11 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
165
167
|
const text = await toggleResp.text().catch(() => '');
|
|
166
168
|
throw new Error(text || `Failed to activate codemode (${toggleResp.status})`);
|
|
167
169
|
}
|
|
168
|
-
addLog('sent', 'POST /agents/sandbox/configure {variant:
|
|
170
|
+
addLog('sent', 'POST /agents/sandbox/configure {variant:eval}');
|
|
169
171
|
const configureResp = await authFetch(`${agentBaseUrl}/api/v1/agents/sandbox/configure`, {
|
|
170
172
|
method: 'POST',
|
|
171
173
|
body: JSON.stringify({
|
|
172
|
-
variant: '
|
|
174
|
+
variant: 'eval',
|
|
173
175
|
}),
|
|
174
176
|
});
|
|
175
177
|
addLog('recv', `HTTP ${configureResp.status} /agents/sandbox/configure`);
|
|
@@ -190,7 +192,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
190
192
|
}
|
|
191
193
|
await restartResp.json().catch(() => null);
|
|
192
194
|
setLastSwitch({
|
|
193
|
-
variant: String(configureData?.variant || '
|
|
195
|
+
variant: String(configureData?.variant || 'eval'),
|
|
194
196
|
switchedAt: new Date().toISOString(),
|
|
195
197
|
});
|
|
196
198
|
setAgentId(resolvedAgentId);
|
|
@@ -216,6 +218,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
216
218
|
if (newVariant === variant)
|
|
217
219
|
return;
|
|
218
220
|
setVariantSwitching(true);
|
|
221
|
+
setPendingVariant(newVariant);
|
|
219
222
|
try {
|
|
220
223
|
// Keep codemode active, then reconfigure sandbox manager variant.
|
|
221
224
|
addLog('sent', 'POST /configure/codemode/toggle {enabled:true}');
|
|
@@ -263,6 +266,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
263
266
|
setHookError(error instanceof Error ? error.message : 'Failed to switch variant');
|
|
264
267
|
}
|
|
265
268
|
finally {
|
|
269
|
+
setPendingVariant(null);
|
|
266
270
|
setVariantSwitching(false);
|
|
267
271
|
}
|
|
268
272
|
}, [variant, agentBaseUrl, authFetch]);
|
|
@@ -328,6 +332,25 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
328
332
|
}, [addLog]);
|
|
329
333
|
// ── Derived display ──
|
|
330
334
|
const aggregate = useMemo(() => deriveAggregate(sandboxStatus), [sandboxStatus]);
|
|
335
|
+
const displayedVariant = pendingVariant ?? variant;
|
|
336
|
+
const isTransitionLocked = variantSwitching;
|
|
337
|
+
// Always use the example's authoritative variant (pending or confirmed)
|
|
338
|
+
// merged with the live WebSocket execution data. The WS status may lag
|
|
339
|
+
// behind after a configure+restart, so we never rely on its `variant` field.
|
|
340
|
+
const chatSandboxStatus = useMemo(() => {
|
|
341
|
+
if (sandboxStatus) {
|
|
342
|
+
return {
|
|
343
|
+
...sandboxStatus,
|
|
344
|
+
variant: displayedVariant,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
// No WS status yet — construct an optimistic placeholder.
|
|
348
|
+
return {
|
|
349
|
+
variant: displayedVariant,
|
|
350
|
+
sandbox_running: true,
|
|
351
|
+
is_executing: false,
|
|
352
|
+
};
|
|
353
|
+
}, [displayedVariant, sandboxStatus]);
|
|
331
354
|
const statusColor = SANDBOX_STATUS_COLORS[aggregate];
|
|
332
355
|
const statusLabel = SANDBOX_STATUS_LABELS[aggregate];
|
|
333
356
|
// ── Loading state ──
|
|
@@ -343,14 +366,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
343
366
|
}
|
|
344
367
|
// ── Error state ──
|
|
345
368
|
if (runtimeStatus === 'error' || hookError) {
|
|
346
|
-
return (
|
|
347
|
-
display: 'flex',
|
|
348
|
-
flexDirection: 'column',
|
|
349
|
-
alignItems: 'center',
|
|
350
|
-
justifyContent: 'center',
|
|
351
|
-
height: '100vh',
|
|
352
|
-
gap: 3,
|
|
353
|
-
}, children: [_jsx(AlertIcon, { size: 48 }), _jsx(Text, { sx: { color: 'danger.fg' }, children: hookError || 'Agent failed to start' })] }));
|
|
369
|
+
return _jsx(ErrorView, { error: hookError, onLogout: onLogout });
|
|
354
370
|
}
|
|
355
371
|
// ── Sidebar ──
|
|
356
372
|
const sidebar = (_jsxs(Box, { sx: {
|
|
@@ -382,7 +398,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
382
398
|
borderRadius: '50%',
|
|
383
399
|
bg: statusColor,
|
|
384
400
|
flexShrink: 0,
|
|
385
|
-
} }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: statusLabel })] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', mt: 1, display: 'block' }, children: ["Last switch:", ' ', lastSwitch
|
|
401
|
+
} }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: statusLabel })] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', mt: 1, display: 'block' }, children: ["Active variant: ", displayedVariant, pendingVariant ? ' (switching...)' : ''] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', mt: 1, display: 'block' }, children: ["Last switch:", ' ', lastSwitch
|
|
386
402
|
? `${lastSwitch.variant} at ${formatSwitchTime(lastSwitch.switchedAt)}`
|
|
387
403
|
: 'n/a'] })] }), sandboxStatus && (_jsxs(Box, { sx: {
|
|
388
404
|
mx: 2,
|
|
@@ -394,7 +410,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
394
410
|
bg: 'canvas.default',
|
|
395
411
|
fontSize: 0,
|
|
396
412
|
fontFamily: 'mono',
|
|
397
|
-
}, children: [_jsxs(Box, { sx: { mb: 1 }, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "variant: " }), _jsx(Text, { children: sandboxStatus.variant })] }), _jsxs(Box, { sx: { mb: 1 }, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "sandbox_running: " }), _jsx(Text, { children: String(sandboxStatus.sandbox_running) })] }), _jsxs(Box, { sx: { mb: 1 }, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "is_executing: " }), _jsx(Label, { variant: sandboxStatus.is_executing ? 'accent' : 'secondary', children: String(sandboxStatus.is_executing) })] }), sandboxStatus.jupyter_url && (_jsxs(Box, { sx: { mb: 1 }, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "jupyter_url: " }), _jsx(Text, { sx: { wordBreak: 'break-all' }, children: sandboxStatus.jupyter_url })] })), sandboxStatus.error && (_jsx(Flash, { variant: "danger", sx: { mt: 1, fontSize: 0, p: 1 }, children: sandboxStatus.error }))] })), _jsx(Box, { sx: { mx: 2, mt: 2 }, children: _jsx(Button, { size: "small", variant: "danger", disabled: aggregate !== 'executing', onClick: sendInterrupt, leadingVisual: StopIcon, block: true, children: "Interrupt Execution" }) }), _jsxs(Box, { sx: {
|
|
413
|
+
}, children: [_jsxs(Box, { sx: { mb: 1 }, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "variant: " }), _jsx(Text, { children: pendingVariant ? displayedVariant : sandboxStatus.variant })] }), _jsxs(Box, { sx: { mb: 1 }, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "sandbox_running: " }), _jsx(Text, { children: String(sandboxStatus.sandbox_running) })] }), _jsxs(Box, { sx: { mb: 1 }, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "is_executing: " }), _jsx(Label, { variant: sandboxStatus.is_executing ? 'accent' : 'secondary', children: String(sandboxStatus.is_executing) })] }), sandboxStatus.jupyter_url && (_jsxs(Box, { sx: { mb: 1 }, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "jupyter_url: " }), _jsx(Text, { sx: { wordBreak: 'break-all' }, children: sandboxStatus.jupyter_url })] })), sandboxStatus.error && (_jsx(Flash, { variant: "danger", sx: { mt: 1, fontSize: 0, p: 1 }, children: sandboxStatus.error }))] })), _jsx(Box, { sx: { mx: 2, mt: 2 }, children: _jsx(Button, { size: "small", variant: "danger", disabled: aggregate !== 'executing' || isTransitionLocked, onClick: sendInterrupt, leadingVisual: StopIcon, block: true, children: "Interrupt Execution" }) }), _jsxs(Box, { sx: {
|
|
398
414
|
mx: 2,
|
|
399
415
|
mt: 2,
|
|
400
416
|
mb: 2,
|
|
@@ -414,7 +430,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
414
430
|
display: 'flex',
|
|
415
431
|
alignItems: 'center',
|
|
416
432
|
justifyContent: 'space-between',
|
|
417
|
-
}, children: [_jsxs(Text, { sx: { fontWeight: 600, fontSize: 0 }, children: ["WebSocket Log (", wsLog.length, ")"] }), _jsx(Button, { size: "small", variant: "invisible", onClick: () => setWsLog([]), sx: { fontSize: 0, px: 1 }, children: "Clear" })] }), _jsx(Box, { sx: {
|
|
433
|
+
}, children: [_jsxs(Text, { sx: { fontWeight: 600, fontSize: 0 }, children: ["WebSocket Log (", wsLog.length, ")"] }), _jsx(Button, { size: "small", variant: "invisible", disabled: isTransitionLocked, onClick: () => setWsLog([]), sx: { fontSize: 0, px: 1 }, children: "Clear" })] }), _jsx(Box, { sx: {
|
|
418
434
|
overflow: 'auto',
|
|
419
435
|
flex: 1,
|
|
420
436
|
fontFamily: 'mono',
|
|
@@ -446,20 +462,31 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
446
462
|
py: 1,
|
|
447
463
|
borderBottom: '1px solid',
|
|
448
464
|
borderColor: 'border.default',
|
|
449
|
-
}, children: _jsx(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: "Agent already running \u2014 reconnected." }) })), _jsxs(Box, { sx: { flex: 1, minHeight: 0, display: 'flex' }, children: [_jsx(Box, { sx: { flex: 1, minWidth: 0 }, children: _jsx(Chat, { protocol: "vercel-ai", baseUrl: agentBaseUrl, agentId: agentId, authToken: chatAuthToken, title: "Sandbox Agent", placeholder: "Ask the agent to write and run code\u2026", showHeader: true, showNewChatButton: true, showClearButton: false, showTokenUsage: true, autoFocus: true, height: "100%", runtimeId: agentId, historyEndpoint: `${agentBaseUrl}/api/v1/history`, headerActions: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsxs(SegmentedControl, { "aria-label": "Sandbox variant", size: "small", onChange: index =>
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
465
|
+
}, children: _jsx(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: "Agent already running \u2014 reconnected." }) })), _jsxs(Box, { sx: { flex: 1, minHeight: 0, display: 'flex' }, children: [_jsx(Box, { sx: { flex: 1, minWidth: 0 }, children: _jsxs(Box, { sx: { position: 'relative', height: '100%' }, children: [_jsx(Chat, { protocol: "vercel-ai", baseUrl: agentBaseUrl, agentId: agentId, authToken: chatAuthToken, title: "Sandbox Agent", placeholder: "Ask the agent to write and run code\u2026", showHeader: true, showNewChatButton: true, showClearButton: false, showTokenUsage: true, autoFocus: true, height: "100%", runtimeId: agentId, historyEndpoint: `${agentBaseUrl}/api/v1/history`, headerActions: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsxs(SegmentedControl, { "aria-label": "Sandbox variant", size: "small", onChange: index => {
|
|
466
|
+
if (isTransitionLocked)
|
|
467
|
+
return;
|
|
468
|
+
void switchVariant(index === 0 ? 'eval' : 'jupyter');
|
|
469
|
+
}, children: [_jsx(SegmentedControl.Button, { selected: displayedVariant === 'eval', leadingIcon: TerminalIcon, disabled: isTransitionLocked, children: "eval" }), _jsx(SegmentedControl.Button, { selected: displayedVariant === 'jupyter', leadingIcon: CodeIcon, disabled: isTransitionLocked, children: "jupyter" })] }), variantSwitching && _jsx(Spinner, { size: "small" })] }), suggestions: [
|
|
470
|
+
{
|
|
471
|
+
title: 'Run some Python',
|
|
472
|
+
message: 'Write a Python script that computes the first 20 Fibonacci numbers and prints them.',
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
title: 'Generate a plot',
|
|
476
|
+
message: 'Write Python code to generate a matplotlib bar chart of the top 5 programming languages by popularity, and save it to chart.png.',
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
title: 'Long-running task',
|
|
480
|
+
message: 'Write Python code that counts from 1 to 30 with a 1-second sleep between each number, printing each one.',
|
|
481
|
+
},
|
|
482
|
+
], submitOnSuggestionClick: true, sandboxStatusData: chatSandboxStatus }), isTransitionLocked && (_jsx(Box, { sx: {
|
|
483
|
+
position: 'absolute',
|
|
484
|
+
inset: 0,
|
|
485
|
+
bg: 'canvas.default',
|
|
486
|
+
opacity: 0.35,
|
|
487
|
+
zIndex: 2,
|
|
488
|
+
cursor: 'wait',
|
|
489
|
+
} }))] }) }), sidebar] })] }));
|
|
463
490
|
};
|
|
464
491
|
// ─── Auth wrapper ──────────────────────────────────────────────────────────
|
|
465
492
|
const syncTokenToIamStore = (newToken) => {
|
|
@@ -468,7 +495,7 @@ const syncTokenToIamStore = (newToken) => {
|
|
|
468
495
|
});
|
|
469
496
|
};
|
|
470
497
|
const AgentSandboxExample = () => {
|
|
471
|
-
const { token,
|
|
498
|
+
const { token, clearAuth } = useSimpleAuthStore();
|
|
472
499
|
const hasSynced = useRef(false);
|
|
473
500
|
useEffect(() => {
|
|
474
501
|
if (token && !hasSynced.current) {
|
|
@@ -476,11 +503,6 @@ const AgentSandboxExample = () => {
|
|
|
476
503
|
syncTokenToIamStore(token);
|
|
477
504
|
}
|
|
478
505
|
}, [token]);
|
|
479
|
-
const handleSignIn = useCallback((newToken, handle) => {
|
|
480
|
-
setAuth(newToken, handle);
|
|
481
|
-
hasSynced.current = true;
|
|
482
|
-
syncTokenToIamStore(newToken);
|
|
483
|
-
}, [setAuth]);
|
|
484
506
|
const handleLogout = useCallback(() => {
|
|
485
507
|
clearAuth();
|
|
486
508
|
hasSynced.current = false;
|
|
@@ -489,7 +511,7 @@ const AgentSandboxExample = () => {
|
|
|
489
511
|
});
|
|
490
512
|
}, [clearAuth]);
|
|
491
513
|
if (!token) {
|
|
492
|
-
return (_jsx(ThemedProvider, { children: _jsx(
|
|
514
|
+
return (_jsx(ThemedProvider, { children: _jsx(AuthRequiredView, {}) }));
|
|
493
515
|
}
|
|
494
516
|
return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ThemedProvider, { children: _jsx(AgentSandboxInner, { onLogout: handleLogout }) }) }));
|
|
495
517
|
};
|