@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.
Files changed (275) hide show
  1. package/README.md +35 -119
  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 -104
  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 +1118 -141
  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 +110 -102
  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 +48 -19
  46. package/lib/client/AgentsMixin.js +115 -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 +55 -26
  54. package/lib/components/OutputCard.js +21 -7
  55. package/lib/components/ToolApprovalCard.js +20 -2
  56. package/lib/config/AgentConfiguration.js +3 -3
  57. package/lib/context/ContextDistribution.d.ts +3 -1
  58. package/lib/context/ContextDistribution.js +8 -27
  59. package/lib/context/ContextInspector.d.ts +3 -1
  60. package/lib/context/ContextInspector.js +19 -67
  61. package/lib/context/ContextPanel.d.ts +3 -1
  62. package/lib/context/ContextPanel.js +104 -64
  63. package/lib/context/ContextUsage.d.ts +3 -1
  64. package/lib/context/ContextUsage.js +3 -3
  65. package/lib/context/CostTracker.d.ts +9 -3
  66. package/lib/context/CostTracker.js +26 -47
  67. package/lib/context/CostUsageChart.d.ts +12 -0
  68. package/lib/context/CostUsageChart.js +378 -0
  69. package/lib/context/GraphFlowChart.d.ts +16 -0
  70. package/lib/context/GraphFlowChart.js +182 -0
  71. package/lib/context/TokenUsageChart.d.ts +8 -1
  72. package/lib/context/TokenUsageChart.js +349 -211
  73. package/lib/context/TurnGraphChart.d.ts +39 -0
  74. package/lib/context/TurnGraphChart.js +538 -0
  75. package/lib/context/otelWsPool.d.ts +20 -0
  76. package/lib/context/otelWsPool.js +69 -0
  77. package/lib/examples/A2UiComponentGalleryExample.d.ts +0 -17
  78. package/lib/examples/A2UiComponentGalleryExample.js +315 -522
  79. package/lib/examples/A2UiContactCardExample.d.ts +0 -18
  80. package/lib/examples/A2UiContactCardExample.js +154 -411
  81. package/lib/examples/A2UiRestaurantExample.d.ts +0 -30
  82. package/lib/examples/A2UiRestaurantExample.js +114 -212
  83. package/lib/examples/A2UiViewerExample.d.ts +0 -18
  84. package/lib/examples/A2UiViewerExample.js +283 -532
  85. package/lib/examples/AgUiBackendToolRenderingExample.js +1 -1
  86. package/lib/examples/AgUiHaikuGenUiExample.d.ts +1 -1
  87. package/lib/examples/AgUiHaikuGenUiExample.js +1 -1
  88. package/lib/examples/AgentCheckpointsExample.js +14 -34
  89. package/lib/examples/AgentCodemodeExample.d.ts +4 -6
  90. package/lib/examples/AgentCodemodeExample.js +591 -175
  91. package/lib/examples/AgentEvalsExample.js +13 -23
  92. package/lib/examples/AgentGuardrailsExample.js +371 -71
  93. package/lib/examples/AgentHooksExample.d.ts +3 -0
  94. package/lib/examples/AgentHooksExample.js +104 -0
  95. package/lib/examples/AgentMCPExample.d.ts +3 -0
  96. package/lib/examples/AgentMCPExample.js +480 -0
  97. package/lib/examples/AgentMemoryExample.js +14 -24
  98. package/lib/examples/AgentMonitoringExample.js +261 -206
  99. package/lib/examples/AgentNotificationsExample.js +50 -24
  100. package/lib/examples/AgentOtelExample.js +2 -3
  101. package/lib/examples/AgentOutputsExample.d.ts +11 -6
  102. package/lib/examples/AgentOutputsExample.js +383 -88
  103. package/lib/examples/AgentParametersExample.d.ts +3 -0
  104. package/lib/examples/AgentParametersExample.js +246 -0
  105. package/lib/examples/AgentSandboxExample.d.ts +2 -2
  106. package/lib/examples/AgentSandboxExample.js +69 -47
  107. package/lib/examples/AgentSkillsExample.js +92 -106
  108. package/lib/examples/{AgentspecExample.js → AgentSpecsExample.js} +10 -21
  109. package/lib/examples/AgentSubagentsExample.d.ts +14 -0
  110. package/lib/examples/AgentSubagentsExample.js +228 -0
  111. package/lib/examples/AgentToolApprovalsExample.js +30 -493
  112. package/lib/examples/AgentTriggersExample.js +1067 -246
  113. package/lib/examples/ChatCustomExample.js +11 -24
  114. package/lib/examples/ChatExample.js +9 -34
  115. package/lib/examples/CopilotKitLexicalExample.js +2 -1
  116. package/lib/examples/CopilotKitNotebookExample.js +2 -1
  117. package/lib/examples/HomeExample.d.ts +15 -0
  118. package/lib/examples/HomeExample.js +77 -0
  119. package/lib/examples/Lexical2Example.js +4 -2
  120. package/lib/examples/{LexicalExample.d.ts → LexicalAgentExample.d.ts} +4 -4
  121. package/lib/examples/{LexicalExample.js → LexicalAgentExample.js} +65 -16
  122. package/lib/examples/{LexicalSidebarExample.d.ts → LexicalAgentSidebarExample.d.ts} +5 -5
  123. package/lib/examples/LexicalAgentSidebarExample.js +261 -0
  124. package/lib/examples/NotebookAgentExample.d.ts +9 -0
  125. package/lib/examples/NotebookAgentExample.js +192 -0
  126. package/lib/examples/{NotebookSidebarExample.d.ts → NotebookAgentSidebarExample.d.ts} +2 -2
  127. package/lib/examples/NotebookAgentSidebarExample.js +221 -0
  128. package/lib/examples/{DatalayerNotebookExample.d.ts → NotebookCollaborationExample.d.ts} +4 -4
  129. package/lib/examples/{DatalayerNotebookExample.js → NotebookCollaborationExample.js} +3 -3
  130. package/lib/examples/NotebookExample.d.ts +4 -7
  131. package/lib/examples/NotebookExample.js +14 -146
  132. package/lib/examples/components/AuthRequiredView.d.ts +6 -0
  133. package/lib/examples/components/AuthRequiredView.js +33 -0
  134. package/lib/examples/components/ErrorView.d.ts +14 -0
  135. package/lib/examples/components/ErrorView.js +20 -0
  136. package/lib/examples/components/ExampleWrapper.d.ts +7 -0
  137. package/lib/examples/components/ExampleWrapper.js +25 -6
  138. package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.js +1 -1
  139. package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.js +1 -1
  140. package/lib/examples/{ag-ui → components}/haiku/index.d.ts +1 -1
  141. package/lib/examples/{ag-ui → components}/haiku/index.js +1 -1
  142. package/lib/examples/components/index.d.ts +5 -0
  143. package/lib/examples/components/index.js +5 -0
  144. package/lib/examples/{ag-ui → components}/weather/index.d.ts +1 -1
  145. package/lib/examples/{ag-ui → components}/weather/index.js +1 -1
  146. package/lib/examples/example-selector.d.ts +17 -4
  147. package/lib/examples/example-selector.js +107 -41
  148. package/lib/examples/index.d.ts +9 -6
  149. package/lib/examples/index.js +9 -6
  150. package/lib/examples/main.d.ts +1 -0
  151. package/lib/examples/main.js +218 -27
  152. package/lib/examples/utils/a2ui.d.ts +18 -0
  153. package/lib/examples/utils/a2ui.js +69 -0
  154. package/lib/examples/utils/a2uiMarkdownProvider.d.ts +7 -0
  155. package/lib/examples/utils/a2uiMarkdownProvider.js +9 -0
  156. package/lib/examples/utils/agentId.d.ts +18 -0
  157. package/lib/examples/utils/agentId.js +54 -0
  158. package/lib/examples/utils/agents/earthquake-detector.json +11 -11
  159. package/lib/examples/utils/agents/sales-forecaster.json +11 -11
  160. package/lib/examples/utils/agents/social-post-generator.json +11 -11
  161. package/lib/examples/utils/agents/stock-market.json +11 -11
  162. package/lib/examples/utils/examplesStore.js +82 -27
  163. package/lib/hooks/index.d.ts +8 -8
  164. package/lib/hooks/index.js +7 -7
  165. package/lib/hooks/useA2A.d.ts +2 -3
  166. package/lib/hooks/useAIAgentsWebSocket.d.ts +43 -4
  167. package/lib/hooks/useAIAgentsWebSocket.js +118 -12
  168. package/lib/hooks/useAcp.d.ts +1 -2
  169. package/lib/hooks/useAgUi.d.ts +1 -1
  170. package/lib/hooks/{useAgents.d.ts → useAgentRuntimes.d.ts} +39 -2
  171. package/lib/hooks/{useAgents.js → useAgentRuntimes.js} +125 -15
  172. package/lib/hooks/useAgentsCatalog.js +1 -1
  173. package/lib/hooks/useAgentsService.d.ts +2 -2
  174. package/lib/hooks/useAgentsService.js +7 -7
  175. package/lib/hooks/useCheckpoints.js +1 -1
  176. package/lib/hooks/useConfig.d.ts +4 -1
  177. package/lib/hooks/useConfig.js +10 -3
  178. package/lib/hooks/useContextSnapshot.d.ts +9 -4
  179. package/lib/hooks/useContextSnapshot.js +9 -37
  180. package/lib/hooks/useMonitoring.js +3 -0
  181. package/lib/hooks/useSandbox.d.ts +20 -8
  182. package/lib/hooks/useSandbox.js +105 -40
  183. package/lib/hooks/useSkills.d.ts +23 -5
  184. package/lib/hooks/useSkills.js +94 -39
  185. package/lib/hooks/useToolApprovals.d.ts +60 -36
  186. package/lib/hooks/useToolApprovals.js +318 -69
  187. package/lib/hooks/useVercelAI.d.ts +1 -1
  188. package/lib/index.d.ts +2 -1
  189. package/lib/index.js +1 -0
  190. package/lib/inference/index.d.ts +0 -1
  191. package/lib/middleware/index.d.ts +0 -1
  192. package/lib/protocols/AGUIAdapter.js +6 -0
  193. package/lib/protocols/VercelAIAdapter.d.ts +9 -0
  194. package/lib/protocols/VercelAIAdapter.js +144 -26
  195. package/lib/shims/json5.d.ts +4 -0
  196. package/lib/shims/json5.js +8 -0
  197. package/lib/specs/agents/agents.d.ts +10 -0
  198. package/lib/specs/agents/agents.js +752 -24
  199. package/lib/specs/envvars.d.ts +1 -0
  200. package/lib/specs/envvars.js +11 -0
  201. package/lib/specs/events.d.ts +1 -0
  202. package/lib/specs/events.js +1 -0
  203. package/lib/specs/index.d.ts +1 -0
  204. package/lib/specs/index.js +1 -0
  205. package/lib/specs/personas.d.ts +41 -0
  206. package/lib/specs/personas.js +168 -0
  207. package/lib/specs/skills.d.ts +2 -1
  208. package/lib/specs/skills.js +23 -5
  209. package/lib/specs/tools.js +3 -0
  210. package/lib/stores/agentRuntimeStore.d.ts +204 -0
  211. package/lib/stores/agentRuntimeStore.js +636 -0
  212. package/lib/stores/index.d.ts +1 -1
  213. package/lib/stores/index.js +1 -1
  214. package/lib/tools/adapters/copilotkit/lexicalHooks.d.ts +1 -2
  215. package/lib/tools/adapters/copilotkit/lexicalHooks.js +1 -3
  216. package/lib/tools/adapters/copilotkit/notebookHooks.d.ts +1 -2
  217. package/lib/tools/adapters/copilotkit/notebookHooks.js +1 -3
  218. package/lib/tools/index.d.ts +0 -2
  219. package/lib/tools/index.js +0 -1
  220. package/lib/types/agentspecs.d.ts +50 -1
  221. package/lib/types/chat.d.ts +309 -8
  222. package/lib/types/context.d.ts +27 -0
  223. package/lib/types/cost.d.ts +2 -2
  224. package/lib/types/index.d.ts +2 -0
  225. package/lib/types/index.js +2 -0
  226. package/lib/types/mcp.d.ts +8 -0
  227. package/lib/types/models.d.ts +2 -2
  228. package/lib/types/personas.d.ts +25 -0
  229. package/lib/types/personas.js +5 -0
  230. package/lib/types/skills.d.ts +43 -1
  231. package/lib/types/stream.d.ts +110 -0
  232. package/lib/types/stream.js +36 -0
  233. package/lib/types/tools.d.ts +2 -0
  234. package/lib/utils/utils.d.ts +9 -5
  235. package/lib/utils/utils.js +9 -5
  236. package/package.json +13 -9
  237. package/scripts/codegen/__pycache__/generate_agents.cpython-313.pyc +0 -0
  238. package/scripts/codegen/__pycache__/generate_events.cpython-313.pyc +0 -0
  239. package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
  240. package/scripts/codegen/generate_agents.py +106 -7
  241. package/scripts/codegen/generate_events.py +47 -17
  242. package/scripts/codegen/generate_personas.py +319 -0
  243. package/scripts/codegen/generate_skills.py +9 -9
  244. package/scripts/codegen/generate_tools.py +20 -0
  245. package/scripts/sync-jupyter.sh +26 -7
  246. package/style/primer-primitives.css +1 -6
  247. package/lib/api/tool-approvals.d.ts +0 -62
  248. package/lib/api/tool-approvals.js +0 -145
  249. package/lib/examples/LexicalSidebarExample.js +0 -163
  250. package/lib/examples/NotebookSidebarExample.js +0 -119
  251. package/lib/examples/NotebookSimpleExample.d.ts +0 -6
  252. package/lib/examples/NotebookSimpleExample.js +0 -22
  253. package/lib/examples/ag-ui/index.d.ts +0 -10
  254. package/lib/examples/ag-ui/index.js +0 -16
  255. package/lib/hooks/useAgentsRegistry.d.ts +0 -10
  256. package/lib/hooks/useAgentsRegistry.js +0 -20
  257. package/lib/stores/agentsStore.d.ts +0 -123
  258. package/lib/stores/agentsStore.js +0 -270
  259. package/scripts/codegen/__pycache__/generate_envvars.cpython-313.pyc +0 -0
  260. package/scripts/codegen/__pycache__/generate_evals.cpython-313.pyc +0 -0
  261. package/scripts/codegen/__pycache__/generate_guardrails.cpython-313.pyc +0 -0
  262. package/scripts/codegen/__pycache__/generate_mcp_servers.cpython-313.pyc +0 -0
  263. package/scripts/codegen/__pycache__/generate_memory.cpython-313.pyc +0 -0
  264. package/scripts/codegen/__pycache__/generate_models.cpython-313.pyc +0 -0
  265. package/scripts/codegen/__pycache__/generate_notifications.cpython-313.pyc +0 -0
  266. package/scripts/codegen/__pycache__/generate_outputs.cpython-313.pyc +0 -0
  267. package/scripts/codegen/__pycache__/generate_skills.cpython-313.pyc +0 -0
  268. package/scripts/codegen/__pycache__/generate_teams.cpython-313.pyc +0 -0
  269. package/scripts/codegen/__pycache__/generate_tools.cpython-313.pyc +0 -0
  270. package/scripts/codegen/__pycache__/generate_triggers.cpython-313.pyc +0 -0
  271. /package/lib/examples/{AgentspecExample.d.ts → AgentSpecsExample.d.ts} +0 -0
  272. /package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.d.ts +0 -0
  273. /package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.d.ts +0 -0
  274. /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.d.ts +0 -0
  275. /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,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 { AlertIcon, CodeIcon, SignOutIcon, StopIcon, TerminalIcon, } from '@primer/octicons-react';
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(AGENT_NAME);
71
+ const [agentId, setAgentId] = useState(agentName);
71
72
  const [isReconnectedAgent, setIsReconnectedAgent] = useState(false);
72
73
  // ── Sandbox variant toggle ──
73
- const [variant, setVariant] = useState('local-eval');
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/${AGENT_NAME}`, {
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: AGENT_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: 'local-eval',
133
+ sandbox_variant: 'eval',
132
134
  }),
133
135
  });
134
- let resolvedAgentId = AGENT_NAME;
136
+ let resolvedAgentId = agentName;
135
137
  if (response.ok) {
136
138
  const data = await response.json();
137
- resolvedAgentId = data?.id || AGENT_NAME;
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:local-eval}');
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: 'local-eval',
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 || 'local-eval'),
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 (_jsxs(Box, { sx: {
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 => 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: [
450
- {
451
- title: 'Run some Python',
452
- message: 'Write a Python script that computes the first 20 Fibonacci numbers and prints them.',
453
- },
454
- {
455
- title: 'Generate a plot',
456
- message: 'Write Python code to generate a matplotlib bar chart of the top 5 programming languages by popularity, and save it to chart.png.',
457
- },
458
- {
459
- title: 'Long-running task',
460
- message: 'Write Python code that counts from 1 to 30 with a 1-second sleep between each number, printing each one.',
461
- },
462
- ], 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] })] }));
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, setAuth, clearAuth } = useSimpleAuthStore();
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(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, {}) }));
493
515
  }
494
516
  return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ThemedProvider, { children: _jsx(AgentSandboxInner, { onLogout: handleLogout }) }) }));
495
517
  };