@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.
Files changed (267) hide show
  1. package/README.md +34 -0
  2. package/lib/App.js +1 -1
  3. package/lib/agents/AgentDetails.d.ts +22 -1
  4. package/lib/agents/AgentDetails.js +34 -47
  5. package/lib/api/index.d.ts +0 -1
  6. package/lib/api/index.js +4 -2
  7. package/lib/chat/Chat.d.ts +5 -106
  8. package/lib/chat/Chat.js +4 -4
  9. package/lib/chat/ChatFloating.d.ts +7 -140
  10. package/lib/chat/ChatFloating.js +2 -2
  11. package/lib/chat/ChatPopupStandalone.d.ts +8 -47
  12. package/lib/chat/ChatPopupStandalone.js +3 -3
  13. package/lib/chat/ChatSidebar.d.ts +4 -69
  14. package/lib/chat/ChatSidebar.js +2 -2
  15. package/lib/chat/ChatStandalone.d.ts +4 -54
  16. package/lib/chat/ChatStandalone.js +3 -3
  17. package/lib/chat/base/ChatBase.js +1083 -157
  18. package/lib/chat/header/ChatHeaderBase.d.ts +11 -6
  19. package/lib/chat/header/ChatHeaderBase.js +18 -16
  20. package/lib/chat/indicators/McpStatusIndicator.d.ts +7 -4
  21. package/lib/chat/indicators/McpStatusIndicator.js +7 -32
  22. package/lib/chat/indicators/SandboxStatusIndicator.d.ts +4 -1
  23. package/lib/chat/indicators/SandboxStatusIndicator.js +9 -9
  24. package/lib/chat/indicators/SkillsStatusIndicator.d.ts +7 -0
  25. package/lib/chat/indicators/SkillsStatusIndicator.js +88 -0
  26. package/lib/chat/indicators/index.d.ts +1 -0
  27. package/lib/chat/indicators/index.js +1 -0
  28. package/lib/chat/messages/ChatMessageList.d.ts +1 -1
  29. package/lib/chat/messages/ChatMessageList.js +108 -113
  30. package/lib/chat/prompt/InputFooter.d.ts +19 -6
  31. package/lib/chat/prompt/InputFooter.js +71 -18
  32. package/lib/chat/prompt/InputPrompt.d.ts +3 -1
  33. package/lib/chat/prompt/InputPrompt.js +4 -4
  34. package/lib/chat/prompt/InputPromptFooter.js +1 -1
  35. package/lib/chat/prompt/InputPromptLexical.d.ts +3 -1
  36. package/lib/chat/prompt/InputPromptLexical.js +12 -5
  37. package/lib/chat/prompt/InputPromptText.d.ts +3 -1
  38. package/lib/chat/prompt/InputPromptText.js +2 -2
  39. package/lib/chat/tools/ToolApprovalBanner.js +1 -1
  40. package/lib/chat/tools/ToolCallDisplay.d.ts +3 -1
  41. package/lib/chat/tools/ToolCallDisplay.js +2 -2
  42. package/lib/chat/usage/TokenUsageBar.js +20 -2
  43. package/lib/client/AgentRuntimesClientContext.d.ts +53 -0
  44. package/lib/client/AgentRuntimesClientContext.js +55 -0
  45. package/lib/client/AgentsMixin.d.ts +0 -18
  46. package/lib/client/AgentsMixin.js +6 -30
  47. package/lib/client/IAgentRuntimesClient.d.ts +215 -0
  48. package/lib/client/IAgentRuntimesClient.js +5 -0
  49. package/lib/client/SdkAgentRuntimesClient.d.ts +151 -0
  50. package/lib/client/SdkAgentRuntimesClient.js +134 -0
  51. package/lib/client/index.d.ts +4 -1
  52. package/lib/client/index.js +3 -1
  53. package/lib/components/NotificationEventCard.js +5 -1
  54. package/lib/config/AgentConfiguration.js +3 -3
  55. package/lib/context/ContextDistribution.d.ts +3 -1
  56. package/lib/context/ContextDistribution.js +8 -27
  57. package/lib/context/ContextInspector.d.ts +3 -1
  58. package/lib/context/ContextInspector.js +19 -67
  59. package/lib/context/ContextPanel.d.ts +3 -1
  60. package/lib/context/ContextPanel.js +104 -64
  61. package/lib/context/ContextUsage.d.ts +3 -1
  62. package/lib/context/ContextUsage.js +3 -3
  63. package/lib/context/CostTracker.d.ts +9 -3
  64. package/lib/context/CostTracker.js +26 -47
  65. package/lib/context/CostUsageChart.d.ts +12 -0
  66. package/lib/context/CostUsageChart.js +378 -0
  67. package/lib/context/GraphFlowChart.d.ts +16 -0
  68. package/lib/context/GraphFlowChart.js +182 -0
  69. package/lib/context/TokenUsageChart.d.ts +8 -1
  70. package/lib/context/TokenUsageChart.js +349 -211
  71. package/lib/context/TurnGraphChart.d.ts +39 -0
  72. package/lib/context/TurnGraphChart.js +538 -0
  73. package/lib/context/otelWsPool.d.ts +20 -0
  74. package/lib/context/otelWsPool.js +69 -0
  75. package/lib/examples/A2UiComponentGalleryExample.d.ts +0 -17
  76. package/lib/examples/A2UiComponentGalleryExample.js +315 -522
  77. package/lib/examples/A2UiContactCardExample.d.ts +0 -18
  78. package/lib/examples/A2UiContactCardExample.js +154 -411
  79. package/lib/examples/A2UiRestaurantExample.d.ts +0 -30
  80. package/lib/examples/A2UiRestaurantExample.js +114 -212
  81. package/lib/examples/A2UiViewerExample.d.ts +0 -18
  82. package/lib/examples/A2UiViewerExample.js +283 -532
  83. package/lib/examples/AgUiBackendToolRenderingExample.js +1 -1
  84. package/lib/examples/AgUiHaikuGenUiExample.d.ts +1 -1
  85. package/lib/examples/AgUiHaikuGenUiExample.js +1 -1
  86. package/lib/examples/AgentCheckpointsExample.js +13 -27
  87. package/lib/examples/AgentCodemodeExample.d.ts +4 -6
  88. package/lib/examples/AgentCodemodeExample.js +591 -169
  89. package/lib/examples/AgentEvalsExample.js +12 -16
  90. package/lib/examples/AgentGuardrailsExample.js +370 -64
  91. package/lib/examples/AgentHooksExample.d.ts +3 -0
  92. package/lib/examples/AgentHooksExample.js +104 -0
  93. package/lib/examples/AgentMCPExample.d.ts +3 -0
  94. package/lib/examples/AgentMCPExample.js +480 -0
  95. package/lib/examples/AgentMemoryExample.js +13 -17
  96. package/lib/examples/AgentMonitoringExample.js +260 -199
  97. package/lib/examples/AgentNotificationsExample.js +49 -17
  98. package/lib/examples/AgentOtelExample.js +2 -3
  99. package/lib/examples/AgentOutputsExample.d.ts +11 -6
  100. package/lib/examples/AgentOutputsExample.js +382 -81
  101. package/lib/examples/AgentParametersExample.d.ts +3 -0
  102. package/lib/examples/AgentParametersExample.js +246 -0
  103. package/lib/examples/AgentSandboxExample.d.ts +2 -2
  104. package/lib/examples/AgentSandboxExample.js +68 -40
  105. package/lib/examples/AgentSkillsExample.js +91 -99
  106. package/lib/examples/{AgentspecExample.js → AgentSpecsExample.js} +10 -21
  107. package/lib/examples/AgentSubagentsExample.d.ts +14 -0
  108. package/lib/examples/AgentSubagentsExample.js +228 -0
  109. package/lib/examples/AgentToolApprovalsExample.js +29 -557
  110. package/lib/examples/AgentTriggersExample.js +819 -565
  111. package/lib/examples/ChatCustomExample.js +11 -24
  112. package/lib/examples/ChatExample.js +7 -24
  113. package/lib/examples/CopilotKitLexicalExample.js +2 -1
  114. package/lib/examples/CopilotKitNotebookExample.js +2 -1
  115. package/lib/examples/HomeExample.d.ts +15 -0
  116. package/lib/examples/HomeExample.js +77 -0
  117. package/lib/examples/Lexical2Example.js +4 -2
  118. package/lib/examples/{LexicalExample.d.ts → LexicalAgentExample.d.ts} +4 -4
  119. package/lib/examples/{LexicalExample.js → LexicalAgentExample.js} +65 -16
  120. package/lib/examples/{LexicalSidebarExample.d.ts → LexicalAgentSidebarExample.d.ts} +5 -5
  121. package/lib/examples/LexicalAgentSidebarExample.js +261 -0
  122. package/lib/examples/NotebookAgentExample.d.ts +9 -0
  123. package/lib/examples/NotebookAgentExample.js +192 -0
  124. package/lib/examples/{NotebookSidebarExample.d.ts → NotebookAgentSidebarExample.d.ts} +2 -2
  125. package/lib/examples/NotebookAgentSidebarExample.js +221 -0
  126. package/lib/examples/{DatalayerNotebookExample.d.ts → NotebookCollaborationExample.d.ts} +4 -4
  127. package/lib/examples/{DatalayerNotebookExample.js → NotebookCollaborationExample.js} +3 -3
  128. package/lib/examples/NotebookExample.d.ts +4 -7
  129. package/lib/examples/NotebookExample.js +14 -146
  130. package/lib/examples/components/AuthRequiredView.d.ts +6 -0
  131. package/lib/examples/components/AuthRequiredView.js +33 -0
  132. package/lib/examples/components/ExampleWrapper.d.ts +7 -0
  133. package/lib/examples/components/ExampleWrapper.js +25 -6
  134. package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.js +1 -1
  135. package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.js +1 -1
  136. package/lib/examples/{ag-ui → components}/haiku/index.d.ts +1 -1
  137. package/lib/examples/{ag-ui → components}/haiku/index.js +1 -1
  138. package/lib/examples/components/index.d.ts +3 -0
  139. package/lib/examples/components/index.js +4 -0
  140. package/lib/examples/{ag-ui → components}/weather/index.d.ts +1 -1
  141. package/lib/examples/{ag-ui → components}/weather/index.js +1 -1
  142. package/lib/examples/example-selector.d.ts +17 -4
  143. package/lib/examples/example-selector.js +107 -41
  144. package/lib/examples/index.d.ts +9 -6
  145. package/lib/examples/index.js +9 -6
  146. package/lib/examples/main.js +217 -27
  147. package/lib/examples/utils/a2ui.d.ts +18 -0
  148. package/lib/examples/utils/a2ui.js +69 -0
  149. package/lib/examples/utils/a2uiMarkdownProvider.d.ts +7 -0
  150. package/lib/examples/utils/a2uiMarkdownProvider.js +9 -0
  151. package/lib/examples/utils/agentId.d.ts +18 -0
  152. package/lib/examples/utils/agentId.js +54 -0
  153. package/lib/examples/utils/agents/earthquake-detector.json +11 -11
  154. package/lib/examples/utils/agents/sales-forecaster.json +11 -11
  155. package/lib/examples/utils/agents/social-post-generator.json +11 -11
  156. package/lib/examples/utils/agents/stock-market.json +11 -11
  157. package/lib/examples/utils/examplesStore.js +82 -27
  158. package/lib/hooks/index.d.ts +8 -8
  159. package/lib/hooks/index.js +7 -7
  160. package/lib/hooks/useA2A.d.ts +2 -3
  161. package/lib/hooks/useAIAgentsWebSocket.d.ts +43 -4
  162. package/lib/hooks/useAIAgentsWebSocket.js +118 -12
  163. package/lib/hooks/useAcp.d.ts +1 -2
  164. package/lib/hooks/useAgUi.d.ts +1 -1
  165. package/lib/hooks/{useAgents.d.ts → useAgentRuntimes.d.ts} +39 -2
  166. package/lib/hooks/{useAgents.js → useAgentRuntimes.js} +125 -15
  167. package/lib/hooks/useAgentsCatalog.js +1 -1
  168. package/lib/hooks/useAgentsService.d.ts +2 -2
  169. package/lib/hooks/useAgentsService.js +7 -7
  170. package/lib/hooks/useCheckpoints.js +1 -1
  171. package/lib/hooks/useConfig.d.ts +4 -1
  172. package/lib/hooks/useConfig.js +10 -3
  173. package/lib/hooks/useContextSnapshot.d.ts +9 -4
  174. package/lib/hooks/useContextSnapshot.js +9 -37
  175. package/lib/hooks/useMonitoring.js +3 -0
  176. package/lib/hooks/useSandbox.d.ts +20 -8
  177. package/lib/hooks/useSandbox.js +105 -40
  178. package/lib/hooks/useSkills.d.ts +23 -5
  179. package/lib/hooks/useSkills.js +94 -39
  180. package/lib/hooks/useToolApprovals.d.ts +60 -36
  181. package/lib/hooks/useToolApprovals.js +318 -69
  182. package/lib/hooks/useVercelAI.d.ts +1 -1
  183. package/lib/index.d.ts +2 -1
  184. package/lib/index.js +1 -0
  185. package/lib/inference/index.d.ts +0 -1
  186. package/lib/middleware/index.d.ts +0 -1
  187. package/lib/protocols/AGUIAdapter.js +6 -0
  188. package/lib/protocols/VercelAIAdapter.d.ts +7 -0
  189. package/lib/protocols/VercelAIAdapter.js +59 -7
  190. package/lib/specs/agents/agents.d.ts +10 -0
  191. package/lib/specs/agents/agents.js +2139 -262
  192. package/lib/specs/agents/index.js +3 -1
  193. package/lib/specs/envvars.d.ts +1 -0
  194. package/lib/specs/envvars.js +38 -20
  195. package/lib/specs/evals.js +6 -6
  196. package/lib/specs/events.d.ts +3 -10
  197. package/lib/specs/events.js +127 -84
  198. package/lib/specs/frontendTools.js +2 -2
  199. package/lib/specs/guardrails.d.ts +0 -7
  200. package/lib/specs/guardrails.js +240 -159
  201. package/lib/specs/index.d.ts +1 -0
  202. package/lib/specs/index.js +1 -0
  203. package/lib/specs/mcpServers.js +35 -6
  204. package/lib/specs/memory.d.ts +0 -2
  205. package/lib/specs/memory.js +4 -17
  206. package/lib/specs/models.js +25 -5
  207. package/lib/specs/notifications.js +102 -18
  208. package/lib/specs/outputs.js +15 -9
  209. package/lib/specs/personas.d.ts +41 -0
  210. package/lib/specs/personas.js +168 -0
  211. package/lib/specs/skills.d.ts +2 -1
  212. package/lib/specs/skills.js +41 -23
  213. package/lib/specs/teams/index.js +3 -1
  214. package/lib/specs/teams/teams.js +468 -348
  215. package/lib/specs/tools.js +4 -4
  216. package/lib/specs/triggers.js +61 -11
  217. package/lib/stores/agentRuntimeStore.d.ts +204 -0
  218. package/lib/stores/agentRuntimeStore.js +636 -0
  219. package/lib/stores/index.d.ts +1 -1
  220. package/lib/stores/index.js +1 -1
  221. package/lib/tools/adapters/copilotkit/lexicalHooks.d.ts +1 -2
  222. package/lib/tools/adapters/copilotkit/lexicalHooks.js +1 -3
  223. package/lib/tools/adapters/copilotkit/notebookHooks.d.ts +1 -2
  224. package/lib/tools/adapters/copilotkit/notebookHooks.js +1 -3
  225. package/lib/tools/index.d.ts +0 -2
  226. package/lib/tools/index.js +0 -1
  227. package/lib/types/agentspecs.d.ts +50 -1
  228. package/lib/types/chat.d.ts +309 -8
  229. package/lib/types/context.d.ts +27 -0
  230. package/lib/types/cost.d.ts +2 -2
  231. package/lib/types/index.d.ts +2 -0
  232. package/lib/types/index.js +2 -0
  233. package/lib/types/mcp.d.ts +8 -0
  234. package/lib/types/models.d.ts +2 -2
  235. package/lib/types/personas.d.ts +25 -0
  236. package/lib/types/personas.js +5 -0
  237. package/lib/types/skills.d.ts +43 -1
  238. package/lib/types/stream.d.ts +110 -0
  239. package/lib/types/stream.js +36 -0
  240. package/lib/utils/utils.d.ts +9 -5
  241. package/lib/utils/utils.js +9 -5
  242. package/package.json +13 -9
  243. package/scripts/codegen/__pycache__/generate_agents.cpython-313.pyc +0 -0
  244. package/scripts/codegen/__pycache__/generate_events.cpython-313.pyc +0 -0
  245. package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
  246. package/scripts/codegen/generate_agents.py +102 -6
  247. package/scripts/codegen/generate_events.py +35 -13
  248. package/scripts/codegen/generate_personas.py +319 -0
  249. package/scripts/codegen/generate_skills.py +9 -9
  250. package/scripts/sync-jupyter.sh +26 -7
  251. package/lib/api/tool-approvals.d.ts +0 -62
  252. package/lib/api/tool-approvals.js +0 -145
  253. package/lib/examples/LexicalSidebarExample.js +0 -163
  254. package/lib/examples/NotebookSidebarExample.js +0 -119
  255. package/lib/examples/NotebookSimpleExample.d.ts +0 -6
  256. package/lib/examples/NotebookSimpleExample.js +0 -22
  257. package/lib/examples/ag-ui/index.d.ts +0 -10
  258. package/lib/examples/ag-ui/index.js +0 -16
  259. package/lib/hooks/useAgentsRegistry.d.ts +0 -10
  260. package/lib/hooks/useAgentsRegistry.js +0 -20
  261. package/lib/stores/agentsStore.d.ts +0 -123
  262. package/lib/stores/agentsStore.js +0 -270
  263. /package/lib/examples/{AgentspecExample.d.ts → AgentSpecsExample.d.ts} +0 -0
  264. /package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.d.ts +0 -0
  265. /package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.d.ts +0 -0
  266. /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.d.ts +0 -0
  267. /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 (local-eval / jupyter) with a live
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 "local-eval" and "jupyter" variants
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 (local-eval / jupyter) with a live
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 "local-eval" and "jupyter" variants
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, SignOutIcon, StopIcon, TerminalIcon, } from '@primer/octicons-react';
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(AGENT_NAME);
71
+ const [agentId, setAgentId] = useState(agentName);
72
72
  const [isReconnectedAgent, setIsReconnectedAgent] = useState(false);
73
73
  // ── Sandbox variant toggle ──
74
- const [variant, setVariant] = useState('local-eval');
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/${AGENT_NAME}`, {
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: AGENT_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: 'local-eval',
133
+ sandbox_variant: 'eval',
133
134
  }),
134
135
  });
135
- let resolvedAgentId = AGENT_NAME;
136
+ let resolvedAgentId = agentName;
136
137
  if (response.ok) {
137
138
  const data = await response.json();
138
- resolvedAgentId = data?.id || AGENT_NAME;
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:local-eval}');
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: 'local-eval',
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 || 'local-eval'),
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 => void switchVariant(index === 0 ? 'local-eval' : 'jupyter'), children: [_jsx(SegmentedControl.Button, { selected: variant === 'local-eval', leadingIcon: TerminalIcon, children: "local-eval" }), _jsx(SegmentedControl.Button, { selected: variant === 'jupyter', leadingIcon: CodeIcon, children: "jupyter" })] }), variantSwitching && _jsx(Spinner, { size: "small" }), token && _jsx(UserBadge, { token: token, variant: "small" }), _jsx(Button, { size: "small", variant: "invisible", onClick: onLogout, leadingVisual: SignOutIcon, sx: { color: 'fg.muted' }, children: "Sign out" })] }), suggestions: [
444
- {
445
- title: 'Run some Python',
446
- message: 'Write a Python script that computes the first 20 Fibonacci numbers and prints them.',
447
- },
448
- {
449
- title: 'Generate a plot',
450
- message: 'Write Python code to generate a matplotlib bar chart of the top 5 programming languages by popularity, and save it to chart.png.',
451
- },
452
- {
453
- title: 'Long-running task',
454
- message: 'Write Python code that counts from 1 to 30 with a 1-second sleep between each number, printing each one.',
455
- },
456
- ], submitOnSuggestionClick: true }) }), sidebar] })] }));
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, setAuth, clearAuth } = useSimpleAuthStore();
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(SignInSimple, { onSignIn: handleSignIn, onApiKeySignIn: apiKey => handleSignIn(apiKey, 'api-key-user'), title: "Sandbox Agent", description: "Sign in to explore sandbox variants and live WebSocket status.", leadingIcon: _jsx(TerminalIcon, { size: 24 }) }) }));
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
  };