@datalayer/agent-runtimes 1.0.4 → 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 +34 -0
- 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 -106
- 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 +1083 -157
- 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 +108 -113
- 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 +0 -18
- package/lib/client/AgentsMixin.js +6 -30
- package/lib/client/IAgentRuntimesClient.d.ts +215 -0
- package/lib/client/IAgentRuntimesClient.js +5 -0
- package/lib/client/SdkAgentRuntimesClient.d.ts +151 -0
- package/lib/client/SdkAgentRuntimesClient.js +134 -0
- package/lib/client/index.d.ts +4 -1
- package/lib/client/index.js +3 -1
- package/lib/components/NotificationEventCard.js +5 -1
- package/lib/config/AgentConfiguration.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 +13 -27
- package/lib/examples/AgentCodemodeExample.d.ts +4 -6
- package/lib/examples/AgentCodemodeExample.js +591 -169
- package/lib/examples/AgentEvalsExample.js +12 -16
- package/lib/examples/AgentGuardrailsExample.js +370 -64
- 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 +13 -17
- package/lib/examples/AgentMonitoringExample.js +260 -199
- package/lib/examples/AgentNotificationsExample.js +49 -17
- package/lib/examples/AgentOtelExample.js +2 -3
- package/lib/examples/AgentOutputsExample.d.ts +11 -6
- package/lib/examples/AgentOutputsExample.js +382 -81
- 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 +68 -40
- package/lib/examples/AgentSkillsExample.js +91 -99
- 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 +29 -557
- package/lib/examples/AgentTriggersExample.js +819 -565
- package/lib/examples/ChatCustomExample.js +11 -24
- package/lib/examples/ChatExample.js +7 -24
- 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/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 +3 -0
- package/lib/examples/components/index.js +4 -0
- package/lib/examples/{ag-ui → components}/weather/index.d.ts +1 -1
- package/lib/examples/{ag-ui → components}/weather/index.js +1 -1
- package/lib/examples/example-selector.d.ts +17 -4
- package/lib/examples/example-selector.js +107 -41
- package/lib/examples/index.d.ts +9 -6
- package/lib/examples/index.js +9 -6
- package/lib/examples/main.js +217 -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 +7 -0
- package/lib/protocols/VercelAIAdapter.js +59 -7
- package/lib/specs/agents/agents.d.ts +10 -0
- package/lib/specs/agents/agents.js +2139 -262
- package/lib/specs/agents/index.js +3 -1
- package/lib/specs/envvars.d.ts +1 -0
- package/lib/specs/envvars.js +38 -20
- package/lib/specs/evals.js +6 -6
- package/lib/specs/events.d.ts +3 -10
- package/lib/specs/events.js +127 -84
- package/lib/specs/frontendTools.js +2 -2
- package/lib/specs/guardrails.d.ts +0 -7
- package/lib/specs/guardrails.js +240 -159
- package/lib/specs/index.d.ts +1 -0
- package/lib/specs/index.js +1 -0
- package/lib/specs/mcpServers.js +35 -6
- package/lib/specs/memory.d.ts +0 -2
- package/lib/specs/memory.js +4 -17
- package/lib/specs/models.js +25 -5
- package/lib/specs/notifications.js +102 -18
- package/lib/specs/outputs.js +15 -9
- package/lib/specs/personas.d.ts +41 -0
- package/lib/specs/personas.js +168 -0
- package/lib/specs/skills.d.ts +2 -1
- package/lib/specs/skills.js +41 -23
- package/lib/specs/teams/index.js +3 -1
- package/lib/specs/teams/teams.js +468 -348
- package/lib/specs/tools.js +4 -4
- package/lib/specs/triggers.js +61 -11
- package/lib/stores/agentRuntimeStore.d.ts +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/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 +102 -6
- package/scripts/codegen/generate_events.py +35 -13
- package/scripts/codegen/generate_personas.py +319 -0
- package/scripts/codegen/generate_skills.py +9 -9
- package/scripts/sync-jupyter.sh +26 -7
- package/lib/api/tool-approvals.d.ts +0 -62
- package/lib/api/tool-approvals.js +0 -145
- package/lib/examples/LexicalSidebarExample.js +0 -163
- package/lib/examples/NotebookSidebarExample.js +0 -119
- package/lib/examples/NotebookSimpleExample.d.ts +0 -6
- package/lib/examples/NotebookSimpleExample.js +0 -22
- package/lib/examples/ag-ui/index.d.ts +0 -10
- package/lib/examples/ag-ui/index.js +0 -16
- package/lib/hooks/useAgentsRegistry.d.ts +0 -10
- package/lib/hooks/useAgentsRegistry.js +0 -20
- package/lib/stores/agentsStore.d.ts +0 -123
- package/lib/stores/agentsStore.js +0 -270
- /package/lib/examples/{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,13 +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 { ErrorView } from './components';
|
|
24
|
+
import { AuthRequiredView, ErrorView } from './components';
|
|
25
25
|
import { Button, Flash, Heading, Label, SegmentedControl, Spinner, Text, } from '@primer/react';
|
|
26
|
-
import { CodeIcon,
|
|
26
|
+
import { CodeIcon, StopIcon, TerminalIcon } from '@primer/octicons-react';
|
|
27
27
|
import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel';
|
|
28
|
-
import { SignInSimple } from '@datalayer/core/lib/views/iam';
|
|
29
|
-
import { UserBadge } from '@datalayer/core/lib/views/profile';
|
|
30
28
|
import { ThemedProvider } from './utils/themedProvider';
|
|
29
|
+
import { uniqueAgentId } from './utils/agentId';
|
|
31
30
|
import { Chat } from '../chat';
|
|
32
31
|
import { SANDBOX_STATUS_COLORS, SANDBOX_STATUS_LABELS } from '../types/sandbox';
|
|
33
32
|
// ─── Constants ─────────────────────────────────────────────────────────────
|
|
@@ -62,16 +61,18 @@ function apiVariantFromUi(variant) {
|
|
|
62
61
|
// ─── Inner component (after auth) ──────────────────────────────────────────
|
|
63
62
|
const AgentSandboxInner = ({ onLogout, }) => {
|
|
64
63
|
const { token } = useSimpleAuthStore();
|
|
64
|
+
const agentName = useRef(uniqueAgentId(AGENT_NAME)).current;
|
|
65
65
|
const chatAuthToken = token === null ? undefined : token;
|
|
66
66
|
const agentBaseUrl = DEFAULT_LOCAL_BASE_URL;
|
|
67
67
|
// ── Agent lifecycle ──
|
|
68
68
|
const [runtimeStatus, setRuntimeStatus] = useState('launching');
|
|
69
69
|
const [isReady, setIsReady] = useState(false);
|
|
70
70
|
const [hookError, setHookError] = useState(null);
|
|
71
|
-
const [agentId, setAgentId] = useState(
|
|
71
|
+
const [agentId, setAgentId] = useState(agentName);
|
|
72
72
|
const [isReconnectedAgent, setIsReconnectedAgent] = useState(false);
|
|
73
73
|
// ── Sandbox variant toggle ──
|
|
74
|
-
const [variant, setVariant] = useState('
|
|
74
|
+
const [variant, setVariant] = useState('eval');
|
|
75
|
+
const [pendingVariant, setPendingVariant] = useState(null);
|
|
75
76
|
const [variantSwitching, setVariantSwitching] = useState(false);
|
|
76
77
|
const [lastSwitch, setLastSwitch] = useState(null);
|
|
77
78
|
// ── WebSocket state ──
|
|
@@ -107,7 +108,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
107
108
|
try {
|
|
108
109
|
// Always delete any existing agent with this name first so we
|
|
109
110
|
// recreate it with the latest configuration (system prompt, toolsets).
|
|
110
|
-
await authFetch(`${agentBaseUrl}/api/v1/agents/${
|
|
111
|
+
await authFetch(`${agentBaseUrl}/api/v1/agents/${agentName}`, {
|
|
111
112
|
method: 'DELETE',
|
|
112
113
|
}).catch(() => {
|
|
113
114
|
/* ignore 404 / not-found */
|
|
@@ -115,7 +116,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
115
116
|
const response = await authFetch(`${agentBaseUrl}/api/v1/agents`, {
|
|
116
117
|
method: 'POST',
|
|
117
118
|
body: JSON.stringify({
|
|
118
|
-
name:
|
|
119
|
+
name: agentName,
|
|
119
120
|
description: 'Agent with sandbox code execution',
|
|
120
121
|
agent_library: 'pydantic-ai',
|
|
121
122
|
transport: 'vercel-ai',
|
|
@@ -129,13 +130,13 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
129
130
|
tools: [],
|
|
130
131
|
selected_mcp_servers: [],
|
|
131
132
|
enable_codemode: true,
|
|
132
|
-
sandbox_variant: '
|
|
133
|
+
sandbox_variant: 'eval',
|
|
133
134
|
}),
|
|
134
135
|
});
|
|
135
|
-
let resolvedAgentId =
|
|
136
|
+
let resolvedAgentId = agentName;
|
|
136
137
|
if (response.ok) {
|
|
137
138
|
const data = await response.json();
|
|
138
|
-
resolvedAgentId = data?.id ||
|
|
139
|
+
resolvedAgentId = data?.id || agentName;
|
|
139
140
|
}
|
|
140
141
|
else {
|
|
141
142
|
const contentType = response.headers.get('content-type') || '';
|
|
@@ -166,11 +167,11 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
166
167
|
const text = await toggleResp.text().catch(() => '');
|
|
167
168
|
throw new Error(text || `Failed to activate codemode (${toggleResp.status})`);
|
|
168
169
|
}
|
|
169
|
-
addLog('sent', 'POST /agents/sandbox/configure {variant:
|
|
170
|
+
addLog('sent', 'POST /agents/sandbox/configure {variant:eval}');
|
|
170
171
|
const configureResp = await authFetch(`${agentBaseUrl}/api/v1/agents/sandbox/configure`, {
|
|
171
172
|
method: 'POST',
|
|
172
173
|
body: JSON.stringify({
|
|
173
|
-
variant: '
|
|
174
|
+
variant: 'eval',
|
|
174
175
|
}),
|
|
175
176
|
});
|
|
176
177
|
addLog('recv', `HTTP ${configureResp.status} /agents/sandbox/configure`);
|
|
@@ -191,7 +192,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
191
192
|
}
|
|
192
193
|
await restartResp.json().catch(() => null);
|
|
193
194
|
setLastSwitch({
|
|
194
|
-
variant: String(configureData?.variant || '
|
|
195
|
+
variant: String(configureData?.variant || 'eval'),
|
|
195
196
|
switchedAt: new Date().toISOString(),
|
|
196
197
|
});
|
|
197
198
|
setAgentId(resolvedAgentId);
|
|
@@ -217,6 +218,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
217
218
|
if (newVariant === variant)
|
|
218
219
|
return;
|
|
219
220
|
setVariantSwitching(true);
|
|
221
|
+
setPendingVariant(newVariant);
|
|
220
222
|
try {
|
|
221
223
|
// Keep codemode active, then reconfigure sandbox manager variant.
|
|
222
224
|
addLog('sent', 'POST /configure/codemode/toggle {enabled:true}');
|
|
@@ -264,6 +266,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
264
266
|
setHookError(error instanceof Error ? error.message : 'Failed to switch variant');
|
|
265
267
|
}
|
|
266
268
|
finally {
|
|
269
|
+
setPendingVariant(null);
|
|
267
270
|
setVariantSwitching(false);
|
|
268
271
|
}
|
|
269
272
|
}, [variant, agentBaseUrl, authFetch]);
|
|
@@ -329,6 +332,25 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
329
332
|
}, [addLog]);
|
|
330
333
|
// ── Derived display ──
|
|
331
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]);
|
|
332
354
|
const statusColor = SANDBOX_STATUS_COLORS[aggregate];
|
|
333
355
|
const statusLabel = SANDBOX_STATUS_LABELS[aggregate];
|
|
334
356
|
// ── Loading state ──
|
|
@@ -376,7 +398,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
376
398
|
borderRadius: '50%',
|
|
377
399
|
bg: statusColor,
|
|
378
400
|
flexShrink: 0,
|
|
379
|
-
} }), _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
|
|
380
402
|
? `${lastSwitch.variant} at ${formatSwitchTime(lastSwitch.switchedAt)}`
|
|
381
403
|
: 'n/a'] })] }), sandboxStatus && (_jsxs(Box, { sx: {
|
|
382
404
|
mx: 2,
|
|
@@ -388,7 +410,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
388
410
|
bg: 'canvas.default',
|
|
389
411
|
fontSize: 0,
|
|
390
412
|
fontFamily: 'mono',
|
|
391
|
-
}, 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: {
|
|
392
414
|
mx: 2,
|
|
393
415
|
mt: 2,
|
|
394
416
|
mb: 2,
|
|
@@ -408,7 +430,7 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
408
430
|
display: 'flex',
|
|
409
431
|
alignItems: 'center',
|
|
410
432
|
justifyContent: 'space-between',
|
|
411
|
-
}, 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: {
|
|
412
434
|
overflow: 'auto',
|
|
413
435
|
flex: 1,
|
|
414
436
|
fontFamily: 'mono',
|
|
@@ -440,20 +462,31 @@ const AgentSandboxInner = ({ onLogout, }) => {
|
|
|
440
462
|
py: 1,
|
|
441
463
|
borderBottom: '1px solid',
|
|
442
464
|
borderColor: 'border.default',
|
|
443
|
-
}, 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 =>
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
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] })] }));
|
|
457
490
|
};
|
|
458
491
|
// ─── Auth wrapper ──────────────────────────────────────────────────────────
|
|
459
492
|
const syncTokenToIamStore = (newToken) => {
|
|
@@ -462,7 +495,7 @@ const syncTokenToIamStore = (newToken) => {
|
|
|
462
495
|
});
|
|
463
496
|
};
|
|
464
497
|
const AgentSandboxExample = () => {
|
|
465
|
-
const { token,
|
|
498
|
+
const { token, clearAuth } = useSimpleAuthStore();
|
|
466
499
|
const hasSynced = useRef(false);
|
|
467
500
|
useEffect(() => {
|
|
468
501
|
if (token && !hasSynced.current) {
|
|
@@ -470,11 +503,6 @@ const AgentSandboxExample = () => {
|
|
|
470
503
|
syncTokenToIamStore(token);
|
|
471
504
|
}
|
|
472
505
|
}, [token]);
|
|
473
|
-
const handleSignIn = useCallback((newToken, handle) => {
|
|
474
|
-
setAuth(newToken, handle);
|
|
475
|
-
hasSynced.current = true;
|
|
476
|
-
syncTokenToIamStore(newToken);
|
|
477
|
-
}, [setAuth]);
|
|
478
506
|
const handleLogout = useCallback(() => {
|
|
479
507
|
clearAuth();
|
|
480
508
|
hasSynced.current = false;
|
|
@@ -483,7 +511,7 @@ const AgentSandboxExample = () => {
|
|
|
483
511
|
});
|
|
484
512
|
}, [clearAuth]);
|
|
485
513
|
if (!token) {
|
|
486
|
-
return (_jsx(ThemedProvider, { children: _jsx(
|
|
514
|
+
return (_jsx(ThemedProvider, { children: _jsx(AuthRequiredView, {}) }));
|
|
487
515
|
}
|
|
488
516
|
return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ThemedProvider, { children: _jsx(AgentSandboxInner, { onLogout: handleLogout }) }) }));
|
|
489
517
|
};
|