@datalayer/agent-runtimes 1.0.4 → 1.0.6

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 (299) hide show
  1. package/README.md +182 -1
  2. package/lib/AgentNode.d.ts +3 -0
  3. package/lib/AgentNode.js +676 -0
  4. package/lib/App.js +1 -1
  5. package/lib/agent-node/themeStore.d.ts +3 -0
  6. package/lib/agent-node/themeStore.js +156 -0
  7. package/lib/agent-node-main.d.ts +1 -0
  8. package/lib/agent-node-main.js +14 -0
  9. package/lib/agents/AgentDetails.d.ts +22 -1
  10. package/lib/agents/AgentDetails.js +34 -47
  11. package/lib/api/index.d.ts +0 -1
  12. package/lib/api/index.js +4 -2
  13. package/lib/chat/Chat.d.ts +5 -106
  14. package/lib/chat/Chat.js +20 -14
  15. package/lib/chat/ChatFloating.d.ts +7 -140
  16. package/lib/chat/ChatFloating.js +3 -3
  17. package/lib/chat/ChatPopupStandalone.d.ts +8 -47
  18. package/lib/chat/ChatPopupStandalone.js +3 -3
  19. package/lib/chat/ChatSidebar.d.ts +4 -69
  20. package/lib/chat/ChatSidebar.js +83 -51
  21. package/lib/chat/ChatStandalone.d.ts +4 -54
  22. package/lib/chat/ChatStandalone.js +3 -3
  23. package/lib/chat/base/ChatBase.js +1414 -174
  24. package/lib/chat/display/FloatingBrandButton.js +8 -1
  25. package/lib/chat/header/ChatHeader.d.ts +3 -1
  26. package/lib/chat/header/ChatHeader.js +15 -12
  27. package/lib/chat/header/ChatHeaderBase.d.ts +30 -5
  28. package/lib/chat/header/ChatHeaderBase.js +41 -16
  29. package/lib/chat/indicators/McpStatusIndicator.d.ts +7 -4
  30. package/lib/chat/indicators/McpStatusIndicator.js +7 -32
  31. package/lib/chat/indicators/SandboxStatusIndicator.d.ts +4 -1
  32. package/lib/chat/indicators/SandboxStatusIndicator.js +91 -56
  33. package/lib/chat/indicators/SkillsStatusIndicator.d.ts +7 -0
  34. package/lib/chat/indicators/SkillsStatusIndicator.js +88 -0
  35. package/lib/chat/indicators/index.d.ts +1 -0
  36. package/lib/chat/indicators/index.js +1 -0
  37. package/lib/chat/messages/ChatMessageList.d.ts +1 -1
  38. package/lib/chat/messages/ChatMessageList.js +154 -114
  39. package/lib/chat/messages/ChatMessages.js +6 -2
  40. package/lib/chat/prompt/InputFooter.d.ts +21 -6
  41. package/lib/chat/prompt/InputFooter.js +76 -20
  42. package/lib/chat/prompt/InputPrompt.d.ts +5 -1
  43. package/lib/chat/prompt/InputPrompt.js +4 -4
  44. package/lib/chat/prompt/InputPromptFooter.d.ts +3 -1
  45. package/lib/chat/prompt/InputPromptFooter.js +3 -3
  46. package/lib/chat/prompt/InputPromptLexical.d.ts +3 -1
  47. package/lib/chat/prompt/InputPromptLexical.js +12 -5
  48. package/lib/chat/prompt/InputPromptText.d.ts +3 -1
  49. package/lib/chat/prompt/InputPromptText.js +2 -2
  50. package/lib/chat/tools/ToolApprovalBanner.js +1 -1
  51. package/lib/chat/tools/ToolCallDisplay.d.ts +3 -1
  52. package/lib/chat/tools/ToolCallDisplay.js +2 -2
  53. package/lib/chat/usage/TokenUsageBar.js +20 -2
  54. package/lib/client/AgentRuntimesClientContext.d.ts +53 -0
  55. package/lib/client/AgentRuntimesClientContext.js +55 -0
  56. package/lib/client/AgentsMixin.d.ts +0 -18
  57. package/lib/client/AgentsMixin.js +20 -30
  58. package/lib/client/IAgentRuntimesClient.d.ts +215 -0
  59. package/lib/client/IAgentRuntimesClient.js +5 -0
  60. package/lib/client/SdkAgentRuntimesClient.d.ts +151 -0
  61. package/lib/client/SdkAgentRuntimesClient.js +134 -0
  62. package/lib/client/index.d.ts +4 -1
  63. package/lib/client/index.js +3 -1
  64. package/lib/components/NotificationEventCard.js +5 -1
  65. package/lib/config/AgentConfiguration.d.ts +22 -0
  66. package/lib/config/AgentConfiguration.js +319 -64
  67. package/lib/context/ContextDistribution.d.ts +3 -1
  68. package/lib/context/ContextDistribution.js +8 -27
  69. package/lib/context/ContextInspector.d.ts +3 -1
  70. package/lib/context/ContextInspector.js +19 -67
  71. package/lib/context/ContextPanel.d.ts +3 -1
  72. package/lib/context/ContextPanel.js +104 -64
  73. package/lib/context/ContextUsage.d.ts +3 -1
  74. package/lib/context/ContextUsage.js +3 -3
  75. package/lib/context/CostTracker.d.ts +9 -3
  76. package/lib/context/CostTracker.js +26 -47
  77. package/lib/context/CostUsageChart.d.ts +12 -0
  78. package/lib/context/CostUsageChart.js +378 -0
  79. package/lib/context/GraphFlowChart.d.ts +16 -0
  80. package/lib/context/GraphFlowChart.js +182 -0
  81. package/lib/context/TokenUsageChart.d.ts +8 -1
  82. package/lib/context/TokenUsageChart.js +349 -211
  83. package/lib/context/TurnGraphChart.d.ts +39 -0
  84. package/lib/context/TurnGraphChart.js +538 -0
  85. package/lib/context/otelWsPool.d.ts +20 -0
  86. package/lib/context/otelWsPool.js +69 -0
  87. package/lib/examples/A2UiComponentGalleryExample.d.ts +0 -17
  88. package/lib/examples/A2UiComponentGalleryExample.js +315 -522
  89. package/lib/examples/A2UiContactCardExample.d.ts +0 -18
  90. package/lib/examples/A2UiContactCardExample.js +154 -411
  91. package/lib/examples/A2UiRestaurantExample.d.ts +0 -30
  92. package/lib/examples/A2UiRestaurantExample.js +114 -212
  93. package/lib/examples/A2UiViewerExample.d.ts +0 -18
  94. package/lib/examples/A2UiViewerExample.js +283 -532
  95. package/lib/examples/AgUiBackendToolRenderingExample.js +1 -1
  96. package/lib/examples/AgUiHaikuGenUiExample.d.ts +1 -1
  97. package/lib/examples/AgUiHaikuGenUiExample.js +1 -1
  98. package/lib/examples/AgUiSharedStateExample.js +2 -1
  99. package/lib/examples/AgentCheckpointsExample.js +14 -28
  100. package/lib/examples/AgentCodemodeExample.d.ts +4 -6
  101. package/lib/examples/AgentCodemodeExample.js +603 -169
  102. package/lib/examples/AgentEvalsExample.js +339 -53
  103. package/lib/examples/AgentGuardrailsExample.js +383 -66
  104. package/lib/examples/AgentHooksExample.d.ts +3 -0
  105. package/lib/examples/AgentHooksExample.js +122 -0
  106. package/lib/examples/AgentInferenceProviderExample.d.ts +3 -0
  107. package/lib/examples/AgentInferenceProviderExample.js +329 -0
  108. package/lib/examples/AgentMCPExample.d.ts +3 -0
  109. package/lib/examples/AgentMCPExample.js +481 -0
  110. package/lib/examples/AgentMemoryExample.d.ts +1 -2
  111. package/lib/examples/AgentMemoryExample.js +78 -33
  112. package/lib/examples/AgentMonitoringExample.js +261 -200
  113. package/lib/examples/AgentNotificationsExample.d.ts +1 -2
  114. package/lib/examples/AgentNotificationsExample.js +114 -33
  115. package/lib/examples/AgentOtelExample.js +32 -42
  116. package/lib/examples/AgentOutputsExample.d.ts +11 -6
  117. package/lib/examples/AgentOutputsExample.js +433 -81
  118. package/lib/examples/AgentParametersExample.d.ts +3 -0
  119. package/lib/examples/AgentParametersExample.js +248 -0
  120. package/lib/examples/AgentSandboxExample.d.ts +3 -3
  121. package/lib/examples/AgentSandboxExample.js +74 -45
  122. package/lib/examples/AgentSkillsExample.js +95 -103
  123. package/lib/examples/AgentSubagentsExample.d.ts +14 -0
  124. package/lib/examples/AgentSubagentsExample.js +228 -0
  125. package/lib/examples/AgentToolApprovalsExample.js +49 -561
  126. package/lib/examples/AgentTriggersExample.js +823 -569
  127. package/lib/examples/{AgentspecExample.d.ts → AgentspecsExample.d.ts} +2 -2
  128. package/lib/examples/AgentspecsExample.js +1096 -0
  129. package/lib/examples/ChatCustomExample.js +16 -28
  130. package/lib/examples/ChatExample.js +13 -29
  131. package/lib/examples/CopilotKitLexicalExample.js +2 -1
  132. package/lib/examples/CopilotKitNotebookExample.js +2 -1
  133. package/lib/examples/HomeExample.d.ts +15 -0
  134. package/lib/examples/HomeExample.js +77 -0
  135. package/lib/examples/Lexical2Example.js +4 -2
  136. package/lib/examples/{LexicalExample.d.ts → LexicalAgentExample.d.ts} +4 -4
  137. package/lib/examples/{LexicalExample.js → LexicalAgentExample.js} +66 -17
  138. package/lib/examples/{LexicalSidebarExample.d.ts → LexicalAgentSidebarExample.d.ts} +5 -5
  139. package/lib/examples/LexicalAgentSidebarExample.js +261 -0
  140. package/lib/examples/NotebookAgentExample.d.ts +9 -0
  141. package/lib/examples/NotebookAgentExample.js +192 -0
  142. package/lib/examples/{NotebookSidebarExample.d.ts → NotebookAgentSidebarExample.d.ts} +2 -2
  143. package/lib/examples/NotebookAgentSidebarExample.js +221 -0
  144. package/lib/examples/{DatalayerNotebookExample.d.ts → NotebookCollaborationExample.d.ts} +4 -4
  145. package/lib/examples/{DatalayerNotebookExample.js → NotebookCollaborationExample.js} +3 -3
  146. package/lib/examples/NotebookExample.d.ts +4 -7
  147. package/lib/examples/NotebookExample.js +14 -146
  148. package/lib/examples/components/AuthRequiredView.d.ts +6 -0
  149. package/lib/examples/components/AuthRequiredView.js +33 -0
  150. package/lib/examples/components/ExampleWrapper.d.ts +9 -3
  151. package/lib/examples/components/ExampleWrapper.js +45 -9
  152. package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.js +1 -1
  153. package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.js +1 -1
  154. package/lib/examples/{ag-ui → components}/haiku/index.d.ts +1 -1
  155. package/lib/examples/{ag-ui → components}/haiku/index.js +1 -1
  156. package/lib/examples/components/index.d.ts +3 -0
  157. package/lib/examples/components/index.js +4 -0
  158. package/lib/examples/{ag-ui → components}/weather/index.d.ts +1 -1
  159. package/lib/examples/{ag-ui → components}/weather/index.js +1 -1
  160. package/lib/examples/example-selector.d.ts +17 -4
  161. package/lib/examples/example-selector.js +108 -41
  162. package/lib/examples/index.d.ts +10 -6
  163. package/lib/examples/index.js +10 -6
  164. package/lib/examples/lexical/initial-content.json +6 -6
  165. package/lib/examples/main.js +257 -27
  166. package/lib/examples/utils/a2ui.d.ts +18 -0
  167. package/lib/examples/utils/a2ui.js +69 -0
  168. package/lib/examples/utils/a2uiMarkdownProvider.d.ts +7 -0
  169. package/lib/examples/utils/a2uiMarkdownProvider.js +9 -0
  170. package/lib/examples/utils/agentId.d.ts +18 -0
  171. package/lib/examples/utils/agentId.js +54 -0
  172. package/lib/examples/utils/agents/earthquake-detector.json +11 -11
  173. package/lib/examples/utils/agents/sales-forecaster.json +11 -11
  174. package/lib/examples/utils/agents/social-post-generator.json +11 -11
  175. package/lib/examples/utils/agents/stock-market.json +11 -11
  176. package/lib/examples/utils/examplesStore.js +82 -27
  177. package/lib/examples/utils/useExampleAgentRuntimesUrl.d.ts +5 -0
  178. package/lib/examples/utils/useExampleAgentRuntimesUrl.js +19 -0
  179. package/lib/hooks/index.d.ts +8 -8
  180. package/lib/hooks/index.js +7 -7
  181. package/lib/hooks/useA2A.d.ts +2 -3
  182. package/lib/hooks/useAIAgentsWebSocket.d.ts +43 -4
  183. package/lib/hooks/useAIAgentsWebSocket.js +153 -12
  184. package/lib/hooks/useAcp.d.ts +1 -2
  185. package/lib/hooks/useAgUi.d.ts +1 -1
  186. package/lib/hooks/{useAgents.d.ts → useAgentRuntimes.d.ts} +70 -4
  187. package/lib/hooks/{useAgents.js → useAgentRuntimes.js} +237 -32
  188. package/lib/hooks/useAgentsCatalog.js +1 -1
  189. package/lib/hooks/useAgentsService.d.ts +2 -2
  190. package/lib/hooks/useAgentsService.js +7 -7
  191. package/lib/hooks/useCheckpoints.js +1 -1
  192. package/lib/hooks/useConfig.d.ts +4 -1
  193. package/lib/hooks/useConfig.js +10 -3
  194. package/lib/hooks/useContextSnapshot.d.ts +9 -4
  195. package/lib/hooks/useContextSnapshot.js +9 -37
  196. package/lib/hooks/useMonitoring.js +3 -0
  197. package/lib/hooks/useSandbox.d.ts +20 -8
  198. package/lib/hooks/useSandbox.js +105 -40
  199. package/lib/hooks/useSkills.d.ts +23 -5
  200. package/lib/hooks/useSkills.js +94 -39
  201. package/lib/hooks/useToolApprovals.d.ts +60 -36
  202. package/lib/hooks/useToolApprovals.js +318 -69
  203. package/lib/hooks/useVercelAI.d.ts +1 -1
  204. package/lib/index.d.ts +2 -1
  205. package/lib/index.js +1 -0
  206. package/lib/inference/index.d.ts +0 -1
  207. package/lib/middleware/index.d.ts +0 -1
  208. package/lib/protocols/AGUIAdapter.js +6 -0
  209. package/lib/protocols/VercelAIAdapter.d.ts +7 -0
  210. package/lib/protocols/VercelAIAdapter.js +59 -7
  211. package/lib/specs/agents/agents.d.ts +21 -4
  212. package/lib/specs/agents/agents.js +2879 -316
  213. package/lib/specs/agents/index.js +3 -1
  214. package/lib/specs/benchmarks.d.ts +20 -0
  215. package/lib/specs/benchmarks.js +205 -0
  216. package/lib/specs/envvars.js +27 -20
  217. package/lib/specs/evals.d.ts +10 -9
  218. package/lib/specs/evals.js +128 -88
  219. package/lib/specs/events.d.ts +3 -10
  220. package/lib/specs/events.js +127 -84
  221. package/lib/specs/frontendTools.js +2 -2
  222. package/lib/specs/guardrails.d.ts +0 -7
  223. package/lib/specs/guardrails.js +240 -159
  224. package/lib/specs/mcpServers.js +35 -6
  225. package/lib/specs/memory.d.ts +0 -2
  226. package/lib/specs/memory.js +4 -17
  227. package/lib/specs/models.d.ts +0 -2
  228. package/lib/specs/models.js +20 -15
  229. package/lib/specs/notifications.js +102 -18
  230. package/lib/specs/outputs.js +15 -9
  231. package/lib/specs/personas.d.ts +41 -0
  232. package/lib/specs/personas.js +168 -0
  233. package/lib/specs/skills.d.ts +1 -1
  234. package/lib/specs/skills.js +23 -23
  235. package/lib/specs/teams/index.js +3 -1
  236. package/lib/specs/teams/teams.js +468 -348
  237. package/lib/specs/tools.js +4 -4
  238. package/lib/specs/triggers.js +61 -11
  239. package/lib/stores/agentRuntimeStore.d.ts +208 -0
  240. package/lib/stores/agentRuntimeStore.js +650 -0
  241. package/lib/stores/conversationStore.js +2 -2
  242. package/lib/stores/index.d.ts +1 -1
  243. package/lib/stores/index.js +1 -1
  244. package/lib/tools/adapters/copilotkit/lexicalHooks.d.ts +1 -2
  245. package/lib/tools/adapters/copilotkit/lexicalHooks.js +1 -3
  246. package/lib/tools/adapters/copilotkit/notebookHooks.d.ts +1 -2
  247. package/lib/tools/adapters/copilotkit/notebookHooks.js +1 -3
  248. package/lib/tools/index.d.ts +0 -2
  249. package/lib/tools/index.js +0 -1
  250. package/lib/types/agents-lifecycle.d.ts +18 -0
  251. package/lib/types/agents.d.ts +6 -0
  252. package/lib/types/agentspecs.d.ts +54 -1
  253. package/lib/types/benchmarks.d.ts +43 -0
  254. package/lib/types/benchmarks.js +5 -0
  255. package/lib/types/chat.d.ts +325 -8
  256. package/lib/types/context.d.ts +27 -0
  257. package/lib/types/cost.d.ts +2 -2
  258. package/lib/types/evals.d.ts +26 -17
  259. package/lib/types/index.d.ts +3 -0
  260. package/lib/types/index.js +3 -0
  261. package/lib/types/mcp.d.ts +8 -0
  262. package/lib/types/models.d.ts +2 -2
  263. package/lib/types/personas.d.ts +25 -0
  264. package/lib/types/personas.js +5 -0
  265. package/lib/types/skills.d.ts +43 -1
  266. package/lib/types/stream.d.ts +110 -0
  267. package/lib/types/stream.js +36 -0
  268. package/lib/utils/utils.d.ts +9 -5
  269. package/lib/utils/utils.js +9 -5
  270. package/package.json +19 -11
  271. package/scripts/codegen/__pycache__/generate_agents.cpython-313.pyc +0 -0
  272. package/scripts/codegen/__pycache__/generate_benchmarks.cpython-313.pyc +0 -0
  273. package/scripts/codegen/__pycache__/generate_evals.cpython-313.pyc +0 -0
  274. package/scripts/codegen/__pycache__/generate_events.cpython-313.pyc +0 -0
  275. package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
  276. package/scripts/codegen/generate_agents.py +187 -45
  277. package/scripts/codegen/generate_benchmarks.py +441 -0
  278. package/scripts/codegen/generate_evals.py +94 -16
  279. package/scripts/codegen/generate_events.py +35 -14
  280. package/scripts/codegen/generate_personas.py +319 -0
  281. package/scripts/codegen/generate_skills.py +9 -9
  282. package/scripts/sync-jupyter.sh +26 -7
  283. package/lib/api/tool-approvals.d.ts +0 -62
  284. package/lib/api/tool-approvals.js +0 -145
  285. package/lib/examples/AgentspecExample.js +0 -705
  286. package/lib/examples/LexicalSidebarExample.js +0 -163
  287. package/lib/examples/NotebookSidebarExample.js +0 -119
  288. package/lib/examples/NotebookSimpleExample.d.ts +0 -6
  289. package/lib/examples/NotebookSimpleExample.js +0 -22
  290. package/lib/examples/ag-ui/index.d.ts +0 -10
  291. package/lib/examples/ag-ui/index.js +0 -16
  292. package/lib/hooks/useAgentsRegistry.d.ts +0 -10
  293. package/lib/hooks/useAgentsRegistry.js +0 -20
  294. package/lib/stores/agentsStore.d.ts +0 -123
  295. package/lib/stores/agentsStore.js +0 -270
  296. /package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.d.ts +0 -0
  297. /package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.d.ts +0 -0
  298. /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.d.ts +0 -0
  299. /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.js +0 -0
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  /*
3
3
  * Copyright (c) 2025-2026 Datalayer, Inc.
4
4
  * Distributed under the terms of the Modified BSD License.
@@ -6,49 +6,283 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
6
  /**
7
7
  * AgentOutputsExample
8
8
  *
9
- * Demonstrates rich output rendering for agent responses: structured data
10
- * tables, charts, downloadable artifacts, and multi-format output panels.
9
+ * Demonstrates rich output rendering for agent responses. The agent (spec
10
+ * `example-outputs`) is prompted to return exactly one of four output types per
11
+ * response:
12
+ * - TABLE → GitHub-flavored Markdown table
13
+ * - JSON → ```json fenced block
14
+ * - CHART → ```json fenced block whose first line is `// chart` (ECharts)
15
+ * - FILE → fenced block whose info string is a file extension and
16
+ * whose first line is `# filename: <name.ext>`
11
17
  *
12
- * - Creates a cloud agent runtime (environment: 'ai-agents-env') via the Datalayer
13
- * Runtimes API and deploys an agent on its sidecar
14
- * - Shows an output gallery alongside the chat with tabs for different
15
- * output formats (table, JSON, chart, file)
18
+ * We subscribe to the chat store, detect the output type of the latest
19
+ * assistant message, auto-switch the sidebar tab, and render the payload
20
+ * inline in the sidebar.
16
21
  */
17
22
  /// <reference types="vite/client" />
18
- import { useEffect, useState, useCallback, useRef } from 'react';
23
+ import { useEffect, useState, useCallback, useRef, useMemo, } from 'react';
19
24
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
20
25
  import { Text, Button, Spinner, Heading, Label } from '@primer/react';
21
- import { TableIcon, FileIcon, CodeIcon, GraphIcon, DownloadIcon, SignOutIcon, } from '@primer/octicons-react';
26
+ import { TableIcon, FileIcon, CodeIcon, GraphIcon, DownloadIcon, } from '@primer/octicons-react';
22
27
  import { Box } from '@datalayer/primer-addons';
23
- import { ErrorView } from './components';
28
+ import { AuthRequiredView, ErrorView } from './components';
24
29
  import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel';
25
- import { SignInSimple } from '@datalayer/core/lib/views/iam';
26
- import { UserBadge } from '@datalayer/core/lib/views/profile';
27
30
  import { ThemedProvider } from './utils/themedProvider';
28
- import { useAgents } from '../hooks/useAgents';
31
+ import { uniqueAgentId } from './utils/agentId';
29
32
  import { Chat } from '../chat';
33
+ import { useChatStore } from '../stores/chatStore';
30
34
  const queryClient = new QueryClient();
31
35
  // ─── Constants ─────────────────────────────────────────────────────────────
32
- const AGENT_NAME = 'output-demo-agent';
33
- const AGENT_SPEC_ID = 'monitor-sales-kpis';
36
+ const AGENT_NAME = 'outputs-example-agent';
37
+ const AGENT_SPEC_ID = 'demo-outputs';
38
+ const DEFAULT_LOCAL_BASE_URL = import.meta.env.VITE_BASE_URL || 'http://localhost:8765';
39
+ // ─── Output detection ──────────────────────────────────────────────────────
40
+ const FENCE_RE = /```([a-zA-Z0-9_+-]*)\n([\s\S]*?)```/g;
41
+ const MD_TABLE_RE = /(^|\n)\s*\|[^\n]+\|\s*\n\s*\|[\s:|-]+\|\s*\n(\s*\|[^\n]+\|\s*\n?)+/;
42
+ /**
43
+ * Some agents emit a markdown table compressed onto a single logical line by
44
+ * joining row separators with `||`. Expand that form back to one row per line
45
+ * so the markdown table renderer can parse it. Idempotent: any pre-existing
46
+ * `|\n|` boundaries are unaffected.
47
+ */
48
+ const expandCompactMarkdownTable = (text) => {
49
+ if (!text)
50
+ return text;
51
+ if (!/\|\s*[-:| ]{3,}\|/.test(text))
52
+ return text;
53
+ if (!text.includes('||'))
54
+ return text;
55
+ return text.replace(/\|\|/g, '|\n|');
56
+ };
57
+ const EXT_LIKE_INFOS = new Set([
58
+ 'csv',
59
+ 'tsv',
60
+ 'txt',
61
+ 'md',
62
+ 'markdown',
63
+ 'yaml',
64
+ 'yml',
65
+ 'xml',
66
+ 'html',
67
+ 'log',
68
+ 'ini',
69
+ 'toml',
70
+ ]);
71
+ const messageText = (m) => {
72
+ if (typeof m.content === 'string')
73
+ return m.content;
74
+ return m.content
75
+ .filter(p => p.type === 'text')
76
+ .map(p => p.text)
77
+ .join('\n');
78
+ };
79
+ const detectOutput = (m) => {
80
+ const text = messageText(m);
81
+ if (!text)
82
+ return null;
83
+ // 1) Fenced code blocks (first one wins).
84
+ FENCE_RE.lastIndex = 0;
85
+ const match = FENCE_RE.exec(text);
86
+ if (match) {
87
+ const info = (match[1] || '').toLowerCase();
88
+ const rawBody = match[2] ?? '';
89
+ const body = expandCompactMarkdownTable(rawBody);
90
+ const firstLine = body.split('\n', 1)[0]?.trim() ?? '';
91
+ // Markdown fenced table should render in the table panel, not as a file.
92
+ if ((info === 'markdown' || info === 'md') && MD_TABLE_RE.test(body)) {
93
+ const tableMatch = body.match(MD_TABLE_RE);
94
+ return {
95
+ tab: 'table',
96
+ payload: tableMatch ? tableMatch[0].trim() : body.trim(),
97
+ messageId: m.id,
98
+ };
99
+ }
100
+ // Bare/unlabeled fence around a markdown table — route to Table tab too.
101
+ if ((!info || info === 'text' || info === 'plain') &&
102
+ MD_TABLE_RE.test(body)) {
103
+ const tableMatch = body.match(MD_TABLE_RE);
104
+ return {
105
+ tab: 'table',
106
+ payload: tableMatch ? tableMatch[0].trim() : body.trim(),
107
+ messageId: m.id,
108
+ };
109
+ }
110
+ // Chart: ```json with `// chart` marker on first line.
111
+ if (info === 'json' && /^\/\/\s*chart\b/i.test(firstLine)) {
112
+ return {
113
+ tab: 'chart',
114
+ payload: body.replace(/^\/\/\s*chart.*\n?/i, ''),
115
+ messageId: m.id,
116
+ };
117
+ }
118
+ // File: info string is a known extension OR first line declares a filename.
119
+ const filenameMatch = firstLine.match(/^#\s*filename:\s*([\w.-]+)/i);
120
+ if (filenameMatch || EXT_LIKE_INFOS.has(info)) {
121
+ const filename = filenameMatch?.[1] ?? (info ? `output.${info}` : 'output.txt');
122
+ return {
123
+ tab: 'files',
124
+ payload: filenameMatch
125
+ ? body.replace(/^#\s*filename:.*\n?/i, '')
126
+ : body,
127
+ filename,
128
+ extension: filename.split('.').pop(),
129
+ messageId: m.id,
130
+ };
131
+ }
132
+ // JSON (explicit language tag).
133
+ if (info === 'json' || info === 'json5') {
134
+ return { tab: 'json', payload: body, messageId: m.id };
135
+ }
136
+ // JSON fallback: bare ``` fence whose body parses as JSON.
137
+ if (!info || info === 'text' || info === 'plain') {
138
+ const trimmed = body.trim();
139
+ if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
140
+ try {
141
+ JSON.parse(trimmed);
142
+ return { tab: 'json', payload: trimmed, messageId: m.id };
143
+ }
144
+ catch {
145
+ /* not JSON — ignore */
146
+ }
147
+ }
148
+ }
149
+ }
150
+ // 1b) No fences — try to detect a bare JSON object/array in the message.
151
+ {
152
+ const stripped = text.trim();
153
+ if (stripped.startsWith('{') || stripped.startsWith('[')) {
154
+ try {
155
+ JSON.parse(stripped);
156
+ return { tab: 'json', payload: stripped, messageId: m.id };
157
+ }
158
+ catch {
159
+ /* not JSON — ignore */
160
+ }
161
+ }
162
+ // Or: find the first {...} / [...] block and try parsing it.
163
+ const blockMatch = stripped.match(/(\{[\s\S]*\}|\[[\s\S]*\])/);
164
+ if (blockMatch) {
165
+ try {
166
+ JSON.parse(blockMatch[1]);
167
+ return { tab: 'json', payload: blockMatch[1], messageId: m.id };
168
+ }
169
+ catch {
170
+ /* not JSON — ignore */
171
+ }
172
+ }
173
+ }
174
+ // 2) Markdown table (no fences).
175
+ const expandedText = expandCompactMarkdownTable(text.trim());
176
+ if (MD_TABLE_RE.test(expandedText)) {
177
+ const tableMatch = expandedText.match(MD_TABLE_RE);
178
+ return {
179
+ tab: 'table',
180
+ payload: tableMatch ? tableMatch[0].trim() : expandedText,
181
+ messageId: m.id,
182
+ };
183
+ }
184
+ return null;
185
+ };
186
+ // ─── Table renderer (parses the Markdown pipe syntax) ──────────────────────
187
+ const MarkdownTable = ({ source }) => {
188
+ const { headers, rows } = useMemo(() => {
189
+ // Some model responses compress table rows into one line using `||`.
190
+ // Normalize that form back to one table row per line.
191
+ const normalized = expandCompactMarkdownTable(source).trim();
192
+ const lines = normalized
193
+ .split('\n')
194
+ .map(l => l.trim())
195
+ .filter(l => l.startsWith('|'));
196
+ if (lines.length < 2)
197
+ return { headers: [], rows: [] };
198
+ const split = (line) => line
199
+ .replace(/^\|/, '')
200
+ .replace(/\|$/, '')
201
+ .split('|')
202
+ .map(c => c.trim());
203
+ const headers = split(lines[0]);
204
+ const rows = lines.slice(2).map(split);
205
+ return { headers, rows };
206
+ }, [source]);
207
+ if (headers.length === 0) {
208
+ return (_jsx(Box, { as: "pre", sx: {
209
+ fontFamily: 'mono',
210
+ fontSize: 0,
211
+ whiteSpace: 'pre-wrap',
212
+ m: 0,
213
+ }, children: source }));
214
+ }
215
+ return (_jsx(Box, { sx: { overflowX: 'auto' }, children: _jsxs(Box, { as: "table", sx: {
216
+ width: '100%',
217
+ tableLayout: 'auto',
218
+ borderCollapse: 'collapse',
219
+ fontSize: 0,
220
+ 'th, td': {
221
+ border: '1px solid',
222
+ borderColor: 'border.muted',
223
+ px: 2,
224
+ py: 1,
225
+ textAlign: 'left',
226
+ verticalAlign: 'top',
227
+ whiteSpace: 'normal',
228
+ wordBreak: 'break-word',
229
+ },
230
+ th: { bg: 'canvas.subtle', fontWeight: 'bold' },
231
+ }, children: [_jsx("thead", { children: _jsx("tr", { children: headers.map((h, i) => (_jsx("th", { children: h }, i))) }) }), _jsx("tbody", { children: rows.map((r, i) => (_jsx("tr", { children: r.map((c, j) => (_jsx("td", { children: c }, j))) }, i))) })] }) }));
232
+ };
233
+ // ─── Chart renderer (lazy ECharts) ─────────────────────────────────────────
234
+ const ChartView = ({ source }) => {
235
+ const [ReactECharts, setReactECharts] = useState(null);
236
+ useEffect(() => {
237
+ let cancelled = false;
238
+ import('echarts-for-react')
239
+ .then(m => {
240
+ if (!cancelled) {
241
+ setReactECharts(() => m.default);
242
+ }
243
+ })
244
+ .catch(() => {
245
+ /* echarts-for-react not installed — fall back to raw JSON */
246
+ });
247
+ return () => {
248
+ cancelled = true;
249
+ };
250
+ }, []);
251
+ const option = useMemo(() => {
252
+ try {
253
+ return JSON.parse(source);
254
+ }
255
+ catch {
256
+ return null;
257
+ }
258
+ }, [source]);
259
+ if (!option) {
260
+ return (_jsx(Text, { sx: { color: 'danger.fg', fontSize: 0 }, children: "Could not parse chart spec as JSON." }));
261
+ }
262
+ if (!ReactECharts) {
263
+ return (_jsx(Box, { as: "pre", sx: {
264
+ fontFamily: 'mono',
265
+ fontSize: 0,
266
+ whiteSpace: 'pre-wrap',
267
+ bg: 'canvas.subtle',
268
+ p: 2,
269
+ borderRadius: 2,
270
+ m: 0,
271
+ }, children: source }));
272
+ }
273
+ return (_jsx(ReactECharts, { option: option, style: { height: 280, width: '100%' } }));
274
+ };
34
275
  // ─── Inner component (rendered after auth) ─────────────────────────────────
35
276
  const AgentOutputsInner = ({ onLogout, }) => {
36
277
  const { token } = useSimpleAuthStore();
37
- const { runtime, status: runtimeStatus, isReady, error: hookError, } = useAgents({
38
- agentSpecId: AGENT_SPEC_ID,
39
- autoStart: true,
40
- agentConfig: {
41
- name: AGENT_NAME,
42
- protocol: 'ag-ui',
43
- description: 'Agent with rich output rendering and artifact management',
44
- },
45
- });
46
- const [activeTab, setActiveTab] = useState('table');
47
- const [artifacts, setArtifacts] = useState([]);
48
- const agentBaseUrl = runtime?.agentBaseUrl || '';
49
- const agentId = runtime?.agentId || AGENT_NAME;
50
- const podName = runtime?.podName || '(launching…)';
51
- // Authenticated fetch helper
278
+ const agentName = useRef(uniqueAgentId(AGENT_NAME)).current;
279
+ const [runtimeStatus, setRuntimeStatus] = useState('launching');
280
+ const [isReady, setIsReady] = useState(false);
281
+ const [hookError, setHookError] = useState(null);
282
+ const [agentId, setAgentId] = useState(agentName);
283
+ const [isReconnectedAgent, setIsReconnectedAgent] = useState(false);
284
+ const agentBaseUrl = DEFAULT_LOCAL_BASE_URL;
285
+ const chatAuthToken = token === null ? undefined : token;
52
286
  const authFetch = useCallback((url, opts = {}) => fetch(url, {
53
287
  ...opts,
54
288
  headers: {
@@ -57,26 +291,107 @@ const AgentOutputsInner = ({ onLogout, }) => {
57
291
  ...(opts.headers ?? {}),
58
292
  },
59
293
  }), [token]);
60
- // ── Poll output artifacts ─────────────────────────────────────────────
61
294
  useEffect(() => {
62
- if (!isReady || !agentBaseUrl)
63
- return;
64
- const poll = async () => {
295
+ let isCancelled = false;
296
+ const createAgent = async () => {
297
+ setRuntimeStatus('launching');
298
+ setIsReady(false);
299
+ setHookError(null);
300
+ setIsReconnectedAgent(false);
65
301
  try {
66
- const res = await authFetch(`${agentBaseUrl}/api/v1/agents/${agentId}/outputs`);
67
- if (res.ok) {
68
- const d = await res.json();
69
- setArtifacts(Array.isArray(d) ? d : (d.artifacts ?? []));
302
+ const response = await authFetch(`${agentBaseUrl}/api/v1/agents`, {
303
+ method: 'POST',
304
+ body: JSON.stringify({
305
+ name: agentName,
306
+ description: 'Agent with rich output rendering (table/JSON/chart/file)',
307
+ agent_library: 'pydantic-ai',
308
+ transport: 'vercel-ai',
309
+ agent_spec_id: AGENT_SPEC_ID,
310
+ enable_skills: true,
311
+ tools: [],
312
+ }),
313
+ });
314
+ let resolvedAgentId = agentName;
315
+ let isAlreadyRunning = false;
316
+ if (response.ok) {
317
+ const data = await response.json();
318
+ resolvedAgentId = data?.id || agentName;
319
+ }
320
+ else {
321
+ const contentType = response.headers.get('content-type') || '';
322
+ let detail = '';
323
+ if (contentType.includes('application/json')) {
324
+ const data = await response.json().catch(() => null);
325
+ detail =
326
+ (typeof data?.detail === 'string' && data.detail) ||
327
+ (typeof data?.message === 'string' && data.message) ||
328
+ '';
329
+ }
330
+ else {
331
+ detail = await response.text();
332
+ }
333
+ if (response.status === 409 || /already exists/i.test(detail || '')) {
334
+ isAlreadyRunning = true;
335
+ }
336
+ else {
337
+ throw new Error(detail || `Failed to create agent: ${response.status}`);
338
+ }
339
+ }
340
+ if (!isCancelled) {
341
+ setAgentId(resolvedAgentId);
342
+ setIsReconnectedAgent(isAlreadyRunning);
343
+ setIsReady(true);
344
+ setRuntimeStatus('ready');
70
345
  }
71
346
  }
72
- catch {
73
- /* ok */
347
+ catch (error) {
348
+ if (!isCancelled) {
349
+ setHookError(error instanceof Error ? error.message : 'Agent failed to start');
350
+ setRuntimeStatus('error');
351
+ }
74
352
  }
75
353
  };
76
- poll();
77
- const interval = setInterval(poll, 10_000);
78
- return () => clearInterval(interval);
79
- }, [isReady, agentBaseUrl, agentId, authFetch]);
354
+ void createAgent();
355
+ return () => {
356
+ isCancelled = true;
357
+ };
358
+ }, [agentBaseUrl, agentName, authFetch]);
359
+ const [activeTab, setActiveTab] = useState('table');
360
+ const [detected, setDetected] = useState([]);
361
+ const lastTextByIdRef = useRef(new Map());
362
+ // Subscribe to chat store messages and detect outputs in assistant replies.
363
+ // We re-detect on every change because messages stream incrementally — the
364
+ // first chunk may only contain a header + one row, and later chunks add the
365
+ // remaining rows; we always want to keep the latest, most complete output.
366
+ useEffect(() => {
367
+ const process = (messages) => {
368
+ const assistants = messages.filter(m => m.role === 'assistant');
369
+ if (assistants.length === 0)
370
+ return;
371
+ const last = assistants[assistants.length - 1];
372
+ const currentText = messageText(last);
373
+ if (lastTextByIdRef.current.get(last.id) === currentText)
374
+ return;
375
+ lastTextByIdRef.current.set(last.id, currentText);
376
+ const out = detectOutput(last);
377
+ if (!out)
378
+ return;
379
+ setDetected(prev => {
380
+ const idx = prev.findIndex(d => d.messageId === out.messageId);
381
+ if (idx === -1)
382
+ return [out, ...prev].slice(0, 20);
383
+ // Replace the existing detection in place so the panel keeps up with
384
+ // streaming content.
385
+ const next = prev.slice();
386
+ next[idx] = out;
387
+ return next;
388
+ });
389
+ setActiveTab(out.tab);
390
+ };
391
+ process(useChatStore.getState().messages);
392
+ const unsub = useChatStore.subscribe(state => state.messages, process);
393
+ return unsub;
394
+ }, []);
80
395
  // ── Loading / Error ───────────────────────────────────────────────────
81
396
  if (!isReady && runtimeStatus !== 'error') {
82
397
  return (_jsxs(Box, { sx: {
@@ -87,18 +402,35 @@ const AgentOutputsInner = ({ onLogout, }) => {
87
402
  height: '100vh',
88
403
  gap: 3,
89
404
  }, children: [_jsx(Spinner, { size: "large" }), _jsx(Text, { sx: { color: 'fg.muted' }, children: runtimeStatus === 'launching'
90
- ? 'Launching runtime for output agent'
91
- : 'Creating output demo agent' })] }));
405
+ ? 'Launching outputs example agent...'
406
+ : 'Creating outputs example agent...' })] }));
92
407
  }
93
408
  if (runtimeStatus === 'error' || hookError) {
94
409
  return _jsx(ErrorView, { error: hookError, onLogout: onLogout });
95
410
  }
96
- const filtered = artifacts.filter(a => a.type === activeTab);
411
+ const filtered = detected.filter(d => d.tab === activeTab);
412
+ const countByTab = (tab) => detected.filter(d => d.tab === tab).length;
413
+ const download = (d) => {
414
+ const blob = new Blob([d.payload], { type: 'text/plain;charset=utf-8' });
415
+ const url = URL.createObjectURL(blob);
416
+ const a = document.createElement('a');
417
+ a.href = url;
418
+ a.download = d.filename ?? `output.${d.extension ?? 'txt'}`;
419
+ document.body.appendChild(a);
420
+ a.click();
421
+ document.body.removeChild(a);
422
+ URL.revokeObjectURL(url);
423
+ };
97
424
  return (_jsxs(Box, { sx: {
98
425
  height: 'calc(100vh - 60px)',
99
426
  display: 'flex',
100
427
  flexDirection: 'column',
101
- }, children: [_jsxs(Box, { sx: {
428
+ }, children: [isReconnectedAgent && (_jsx(Box, { sx: {
429
+ px: 3,
430
+ py: 1,
431
+ borderBottom: '1px solid',
432
+ borderColor: 'border.default',
433
+ }, children: _jsx(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: "Agent already running - reconnected." }) })), _jsxs(Box, { sx: {
102
434
  display: 'flex',
103
435
  alignItems: 'center',
104
436
  gap: 2,
@@ -107,22 +439,30 @@ const AgentOutputsInner = ({ onLogout, }) => {
107
439
  borderBottom: '1px solid',
108
440
  borderColor: 'border.default',
109
441
  flexShrink: 0,
110
- }, children: [_jsx(TableIcon, { size: 16 }), _jsxs(Heading, { as: "h3", sx: { fontSize: 2, flex: 1 }, children: ["Agent Outputs \u2014 ", podName] }), token && _jsx(UserBadge, { token: token, variant: "small" }), _jsx(Button, { size: "small", variant: "invisible", onClick: onLogout, leadingVisual: SignOutIcon, sx: { color: 'fg.muted' }, children: "Sign out" })] }), _jsxs(Box, { sx: { flex: 1, minHeight: 0, display: 'flex' }, children: [_jsx(Box, { sx: { flex: 1, minWidth: 0 }, children: _jsx(Chat, { protocol: "ag-ui", baseUrl: agentBaseUrl, agentId: agentId, title: "Output Agent", placeholder: "Ask the agent to generate reports, data, or files\u2026", description: `${artifacts.length} artifact${artifacts.length !== 1 ? 's' : ''} produced`, showHeader: true, autoFocus: true, height: "100%", runtimeId: podName, historyEndpoint: `${agentBaseUrl}/api/v1/history`, suggestions: [
442
+ }, children: [_jsx(TableIcon, { size: 16 }), _jsx(Heading, { as: "h3", sx: { fontSize: 2, flex: 1 }, children: "Agent Outputs \u2014 Local Runtime" })] }), _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: "Outputs Demo Agent", brandIcon: _jsx(FileIcon, { size: 16 }), placeholder: "Ask for a Table, JSON, Chart, or File\u2026", description: `${detected.length} detected output${detected.length !== 1 ? 's' : ''}`, showHeader: true, showToolsMenu: true, showSkillsMenu: true, autoFocus: true, height: "100%", runtimeId: agentId, historyEndpoint: `${agentBaseUrl}/api/v1/history`, suggestions: [
111
443
  {
112
- title: 'Generate report',
113
- message: 'Generate a KPI summary report as a table',
444
+ title: 'Table',
445
+ message: 'Generate a Markdown table of the top 5 US cities by population, with columns City, State, Population.',
114
446
  },
115
447
  {
116
- title: 'Export JSON',
117
- message: 'Export the latest sales data as JSON',
448
+ title: 'JSON',
449
+ message: 'Return a JSON object describing a fictitious product catalog with 3 items (id, name, price, tags).',
450
+ },
451
+ {
452
+ title: 'Chart',
453
+ message: 'Produce a bar chart ECharts spec (valid JSON, with `// chart` on the first line of the fenced block) showing monthly sales for Jan–Jun.',
454
+ },
455
+ {
456
+ title: 'File',
457
+ message: 'Create a downloadable CSV file with sample sales data for the last 7 days. Output it inside a ```csv fenced block whose first line is `# filename: sales.csv`.',
118
458
  },
119
459
  ], submitOnSuggestionClick: true }) }), _jsxs(Box, { sx: {
120
- width: 380,
460
+ width: 420,
121
461
  borderLeft: '1px solid',
122
462
  borderColor: 'border.default',
123
463
  display: 'flex',
124
464
  flexDirection: 'column',
125
- overflow: 'auto',
465
+ overflow: 'hidden',
126
466
  }, children: [_jsx(Box, { sx: {
127
467
  display: 'flex',
128
468
  borderBottom: '1px solid',
@@ -133,13 +473,18 @@ const AgentOutputsInner = ({ onLogout, }) => {
133
473
  { key: 'json', icon: CodeIcon, label: 'JSON' },
134
474
  { key: 'chart', icon: GraphIcon, label: 'Chart' },
135
475
  { key: 'files', icon: FileIcon, label: 'Files' },
136
- ].map(t => (_jsx(Button, { size: "small", variant: "invisible", leadingVisual: t.icon, onClick: () => setActiveTab(t.key), sx: {
137
- flex: 1,
138
- borderRadius: 0,
139
- borderBottom: activeTab === t.key ? '2px solid' : '2px solid transparent',
140
- borderColor: activeTab === t.key ? 'accent.fg' : 'transparent',
141
- fontWeight: activeTab === t.key ? 'bold' : 'normal',
142
- }, children: t.label }, t.key))) }), _jsxs(Box, { sx: { p: 3, flex: 1, overflow: 'auto' }, children: [_jsxs(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: [activeTab.charAt(0).toUpperCase() + activeTab.slice(1), " Outputs"] }), filtered.length === 0 ? (_jsxs(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: ["No ", activeTab, " outputs yet. Ask the agent to generate some."] })) : (filtered.map(art => (_jsxs(Box, { sx: {
476
+ ].map(t => {
477
+ const n = countByTab(t.key);
478
+ return (_jsxs(Button, { size: "small", variant: "invisible", leadingVisual: t.icon, onClick: () => setActiveTab(t.key), sx: {
479
+ flex: 1,
480
+ borderRadius: 0,
481
+ borderBottom: activeTab === t.key
482
+ ? '2px solid'
483
+ : '2px solid transparent',
484
+ borderColor: activeTab === t.key ? 'accent.fg' : 'transparent',
485
+ fontWeight: activeTab === t.key ? 'bold' : 'normal',
486
+ }, children: [t.label, n > 0 ? ` (${n})` : ''] }, t.key));
487
+ }) }), _jsxs(Box, { sx: { p: 3, flex: 1, overflow: 'auto' }, children: [_jsxs(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: [activeTab.charAt(0).toUpperCase() + activeTab.slice(1), " outputs"] }), filtered.length === 0 ? (_jsxs(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: ["No ", activeTab, " outputs yet. Use one of the suggestion buttons in the chat to produce one \u2014 the side panel will switch to the matching tab automatically."] })) : (filtered.map((d, idx) => (_jsxs(Box, { sx: {
143
488
  p: 2,
144
489
  mb: 2,
145
490
  border: '1px solid',
@@ -149,25 +494,37 @@ const AgentOutputsInner = ({ onLogout, }) => {
149
494
  display: 'flex',
150
495
  justifyContent: 'space-between',
151
496
  alignItems: 'center',
152
- mb: 1,
153
- }, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold' }, children: art.name }), _jsx(Label, { size: "small", variant: "secondary", children: art.size != null
154
- ? `${(art.size / 1024).toFixed(1)} KB`
155
- : activeTab })] }), art.preview && (_jsx(Box, { sx: {
497
+ mb: 2,
498
+ gap: 2,
499
+ }, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold' }, children: d.filename ?? `${d.tab} output` }), _jsx(Label, { size: "small", variant: "secondary", children: d.tab })] }), d.tab === 'table' && _jsx(MarkdownTable, { source: d.payload }), d.tab === 'json' && (_jsx(Box, { as: "pre", sx: {
156
500
  bg: 'canvas.subtle',
157
501
  p: 2,
158
502
  borderRadius: 2,
159
503
  fontFamily: 'mono',
160
504
  fontSize: 0,
161
- mb: 1,
162
- maxHeight: 120,
505
+ maxHeight: 320,
163
506
  overflow: 'auto',
164
507
  whiteSpace: 'pre-wrap',
165
- }, children: art.preview })), _jsxs(Box, { sx: {
166
- display: 'flex',
167
- justifyContent: 'space-between',
168
- fontSize: 0,
169
- color: 'fg.muted',
170
- }, children: [_jsx(Text, { children: new Date(art.timestamp).toLocaleString() }), _jsx(Button, { size: "small", variant: "invisible", leadingVisual: DownloadIcon, onClick: () => window.open(`${agentBaseUrl}/api/v1/agents/${agentId}/outputs/${art.id}/download`), children: "Download" })] })] }, art.id))))] })] })] })] }));
508
+ m: 0,
509
+ }, children: (() => {
510
+ try {
511
+ return JSON.stringify(JSON.parse(d.payload), null, 2);
512
+ }
513
+ catch {
514
+ return d.payload;
515
+ }
516
+ })() })), d.tab === 'chart' && _jsx(ChartView, { source: d.payload }), d.tab === 'files' && (_jsxs(_Fragment, { children: [_jsx(Box, { as: "pre", sx: {
517
+ bg: 'canvas.subtle',
518
+ p: 2,
519
+ borderRadius: 2,
520
+ fontFamily: 'mono',
521
+ fontSize: 0,
522
+ maxHeight: 200,
523
+ overflow: 'auto',
524
+ whiteSpace: 'pre-wrap',
525
+ m: 0,
526
+ mb: 2,
527
+ }, children: d.payload }), _jsxs(Button, { size: "small", leadingVisual: DownloadIcon, onClick: () => download(d), children: ["Download ", d.filename ?? 'file'] })] }))] }, d.messageId + ':' + idx))))] })] })] })] }));
171
528
  };
172
529
  // ─── Sync token to core IAM store ──────────────────────────────────────────
173
530
  const syncTokenToIamStore = (token) => {
@@ -177,7 +534,7 @@ const syncTokenToIamStore = (token) => {
177
534
  };
178
535
  // ─── Main component with auth gate ─────────────────────────────────────────
179
536
  const AgentOutputsExample = () => {
180
- const { token, setAuth, clearAuth } = useSimpleAuthStore();
537
+ const { token, clearAuth } = useSimpleAuthStore();
181
538
  const hasSynced = useRef(false);
182
539
  useEffect(() => {
183
540
  if (token && !hasSynced.current) {
@@ -185,11 +542,6 @@ const AgentOutputsExample = () => {
185
542
  syncTokenToIamStore(token);
186
543
  }
187
544
  }, [token]);
188
- const handleSignIn = useCallback((newToken, handle) => {
189
- setAuth(newToken, handle);
190
- hasSynced.current = true;
191
- syncTokenToIamStore(newToken);
192
- }, [setAuth]);
193
545
  const handleLogout = useCallback(() => {
194
546
  clearAuth();
195
547
  hasSynced.current = false;
@@ -198,7 +550,7 @@ const AgentOutputsExample = () => {
198
550
  });
199
551
  }, [clearAuth]);
200
552
  if (!token) {
201
- return (_jsx(ThemedProvider, { children: _jsx(SignInSimple, { onSignIn: handleSignIn, onApiKeySignIn: apiKey => handleSignIn(apiKey, 'api-key-user'), title: "Agent Outputs", description: "Sign in to view and manage agent output artifacts.", leadingIcon: _jsx(TableIcon, { size: 24 }) }) }));
553
+ return (_jsx(ThemedProvider, { children: _jsx(AuthRequiredView, {}) }));
202
554
  }
203
555
  return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ThemedProvider, { children: _jsx(AgentOutputsInner, { onLogout: handleLogout }) }) }));
204
556
  };
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const AgentParametersExample: React.FC;
3
+ export default AgentParametersExample;