@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
@@ -16,141 +16,57 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
16
16
  /// <reference types="vite/client" />
17
17
  import { useEffect, useState, useCallback, useRef } from 'react';
18
18
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
19
- import { Text, Button, Spinner, Heading, Label } from '@primer/react';
20
- import { AlertIcon, CheckCircleIcon, GraphIcon, SignOutIcon, } from '@primer/octicons-react';
19
+ import { Text, Spinner, Heading, Label } from '@primer/react';
20
+ import { GraphIcon } from '@primer/octicons-react';
21
21
  import { Box } from '@datalayer/primer-addons';
22
+ import { AuthRequiredView, ErrorView } from './components';
22
23
  import { ThemedProvider } from './utils/themedProvider';
24
+ import { uniqueAgentId } from './utils/agentId';
25
+ import { ContextPanel, } from '../context/ContextPanel';
26
+ import { CostTracker } from '../context/CostTracker';
27
+ import { CostUsageChart } from '../context/CostUsageChart';
28
+ import { TokenUsageChart } from '../context/TokenUsageChart';
29
+ import { GraphFlowChart } from '../context/GraphFlowChart';
30
+ import { TurnGraphChart } from '../context/TurnGraphChart';
31
+ import { useAIAgentsWebSocket } from '../hooks';
32
+ import { parseAgentStreamMessage } from '../types/stream';
33
+ import { useCoreStore } from '@datalayer/core/lib/state';
23
34
  const queryClient = new QueryClient();
24
35
  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
36
  import { Chat } from '../chat';
28
- import { useAgents } from '../hooks/useAgents';
29
37
  const AGENT_NAME = 'monitoring-demo-agent';
30
- const AGENT_SPEC_ID = 'monitor-sales-kpis';
31
- const clampPercent = (value) => Math.max(0, Math.min(100, value));
32
- const toNumber = (value, fallback) => {
33
- const n = Number(value);
34
- return Number.isFinite(n) ? n : fallback;
35
- };
36
- const randomOffset = (range) => (Math.random() - 0.5) * range;
37
- const createSyntheticSnapshot = (previous) => {
38
- const baseCpu = previous?.cpuPercent ?? 42;
39
- const baseMemory = previous?.memoryPercent ?? 57;
40
- const baseLatency = previous?.latencyMs ?? 320;
41
- const baseErrorRate = previous?.errorRatePercent ?? 1.6;
42
- const baseQueueDepth = previous?.queueDepth ?? 12;
43
- const cpuPercent = clampPercent(baseCpu + randomOffset(10));
44
- const memoryPercent = clampPercent(baseMemory + randomOffset(8));
45
- const latencyMs = Math.max(30, baseLatency + randomOffset(120));
46
- const errorRatePercent = clampPercent(baseErrorRate + randomOffset(0.8));
47
- const queueDepth = Math.max(0, Math.round(baseQueueDepth + randomOffset(8)));
48
- let status = 'healthy';
49
- if (errorRatePercent > 4 || latencyMs > 1200 || cpuPercent > 90) {
50
- status = 'critical';
51
- }
52
- else if (errorRatePercent > 2 || latencyMs > 700 || cpuPercent > 80) {
53
- status = 'degraded';
54
- }
55
- return {
56
- timestamp: new Date().toISOString(),
57
- cpuPercent,
58
- memoryPercent,
59
- latencyMs,
60
- errorRatePercent,
61
- queueDepth,
62
- status,
63
- };
64
- };
65
- const normalizeSnapshot = (raw, previous) => {
66
- if (!raw || typeof raw !== 'object') {
67
- return createSyntheticSnapshot(previous);
68
- }
69
- const data = raw;
70
- const snapshot = createSyntheticSnapshot(previous);
71
- const statusValue = String(data.status ?? snapshot.status).toLowerCase();
72
- const status = statusValue === 'healthy' ||
73
- statusValue === 'degraded' ||
74
- statusValue === 'critical'
75
- ? statusValue
76
- : 'unknown';
77
- return {
78
- timestamp: String(data.timestamp ?? new Date().toISOString()),
79
- cpuPercent: clampPercent(toNumber(data.cpuPercent ?? data.cpu, snapshot.cpuPercent)),
80
- memoryPercent: clampPercent(toNumber(data.memoryPercent ?? data.memory, snapshot.memoryPercent)),
81
- latencyMs: Math.max(0, toNumber(data.latencyMs ?? data.latency, snapshot.latencyMs)),
82
- errorRatePercent: clampPercent(toNumber(data.errorRatePercent ?? data.errorRate, snapshot.errorRatePercent)),
83
- queueDepth: Math.max(0, Math.round(toNumber(data.queueDepth, snapshot.queueDepth))),
84
- status,
85
- };
86
- };
87
- const normalizeAlert = (raw, index) => {
88
- if (!raw || typeof raw !== 'object') {
89
- return null;
90
- }
91
- const data = raw;
92
- const severityValue = String(data.severity ?? 'info').toLowerCase();
93
- const severity = severityValue === 'warning' || severityValue === 'critical'
94
- ? severityValue
95
- : 'info';
96
- return {
97
- id: String(data.id ?? `alert-${Date.now()}-${index}`),
98
- title: String(data.title ?? 'Agent alert detected'),
99
- severity,
100
- timestamp: String(data.timestamp ?? new Date().toISOString()),
101
- };
102
- };
103
- const statusVariant = (status) => {
104
- if (status === 'healthy')
105
- return 'success';
106
- if (status === 'degraded')
107
- return 'attention';
108
- if (status === 'critical')
109
- return 'danger';
110
- return 'secondary';
111
- };
112
- const alertVariant = (severity) => {
113
- if (severity === 'critical')
114
- return 'danger';
115
- if (severity === 'warning')
116
- return 'attention';
117
- return 'secondary';
118
- };
119
- const MetricRow = ({ label, value, percent }) => {
120
- return (_jsxs(Box, { sx: { mb: 2 }, children: [_jsxs(Box, { sx: {
121
- display: 'flex',
122
- justifyContent: 'space-between',
123
- alignItems: 'center',
124
- mb: 1,
125
- }, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: label }), _jsx(Text, { sx: { fontSize: 0, fontWeight: 'bold' }, children: value })] }), _jsx(Box, { sx: {
126
- width: '100%',
127
- height: 8,
128
- bg: 'canvas.subtle',
129
- borderRadius: 6,
130
- overflow: 'hidden',
131
- }, children: _jsx(Box, { sx: {
132
- width: `${clampPercent(percent)}%`,
133
- height: '100%',
134
- bg: percent >= 85 ? 'danger.emphasis' : 'accent.emphasis',
135
- transition: 'width 300ms ease-out',
136
- } }) })] }));
137
- };
38
+ const AGENT_SPEC_ID = 'demo-monitoring';
39
+ const DEFAULT_LOCAL_BASE_URL = import.meta.env.VITE_BASE_URL || 'http://localhost:8765';
40
+ const OTEL_BASE_URL_ENV = import.meta.env.VITE_OTEL_BASE_URL;
41
+ const DATALAYER_RUN_URL_ENV = import.meta.env.DATALAYER_RUN_URL;
138
42
  const AgentMonitoringInner = ({ onLogout, }) => {
139
43
  const { token } = useSimpleAuthStore();
140
- const { runtime, status: runtimeStatus, isReady, error: hookError, } = useAgents({
141
- agentSpecId: AGENT_SPEC_ID,
142
- autoStart: true,
143
- agentConfig: {
144
- name: AGENT_NAME,
145
- protocol: 'ag-ui',
146
- description: 'Agent with runtime and alert monitoring signals',
147
- },
148
- });
149
- const [snapshots, setSnapshots] = useState([]);
44
+ const agentName = useRef(uniqueAgentId(AGENT_NAME)).current;
45
+ const { configuration } = useCoreStore();
46
+ const [runtimeStatus, setRuntimeStatus] = useState('launching');
47
+ const [isReady, setIsReady] = useState(false);
48
+ const [hookError, setHookError] = useState(null);
49
+ const [agentId, setAgentId] = useState(agentName);
50
+ const [isReconnectedAgent, setIsReconnectedAgent] = useState(false);
150
51
  const [alerts, setAlerts] = useState([]);
151
- const agentBaseUrl = runtime?.agentBaseUrl || '';
152
- const agentId = runtime?.agentId || AGENT_NAME;
153
- const podName = runtime?.podName || '(launching…)';
52
+ const [liveContext, setLiveContext] = useState(undefined);
53
+ const [liveContextSnapshot, setLiveContextSnapshot] = useState(undefined);
54
+ const [liveCost, setLiveCost] = useState(undefined);
55
+ const [liveMcpStatus, setLiveMcpStatus] = useState(undefined);
56
+ const [monitorLastSnapshotAt, setMonitorLastSnapshotAt] = useState(null);
57
+ const [liveGraphTelemetry, setLiveGraphTelemetry] = useState(undefined);
58
+ const agentBaseUrl = DEFAULT_LOCAL_BASE_URL;
59
+ const otelBaseUrl = configuration?.otelRunUrl ||
60
+ configuration?.runUrl ||
61
+ OTEL_BASE_URL_ENV ||
62
+ DATALAYER_RUN_URL_ENV ||
63
+ 'https://prod1.datalayer.run';
64
+ const podName = agentId;
65
+ // The OTEL service_name resource attribute is 'agent-runtimes' (the
66
+ // application name), NOT the individual agent ID. Use the correct value
67
+ // so the TokenUsageChart WS filter and HTTP query match actual rows.
68
+ const otelServiceName = 'agent-runtimes';
69
+ const chatAuthToken = token === null ? undefined : token;
154
70
  const authFetch = useCallback((url, opts = {}) => fetch(url, {
155
71
  ...opts,
156
72
  headers: {
@@ -160,46 +76,137 @@ const AgentMonitoringInner = ({ onLogout, }) => {
160
76
  },
161
77
  }), [token]);
162
78
  useEffect(() => {
163
- if (!isReady || !agentBaseUrl)
164
- return;
165
- const poll = async () => {
166
- let nextSnapshot = null;
167
- let nextAlerts = null;
79
+ let isCancelled = false;
80
+ const createLocalAgent = async () => {
81
+ setRuntimeStatus('launching');
82
+ setIsReady(false);
83
+ setHookError(null);
84
+ setIsReconnectedAgent(false);
168
85
  try {
169
- const res = await authFetch(`${agentBaseUrl}/api/v1/agents/${agentId}/monitoring`);
170
- if (res.ok) {
171
- const data = await res.json();
172
- const rawSnapshot = data?.snapshot ?? data?.metrics ?? data;
173
- nextAlerts = Array.isArray(data?.alerts)
174
- ? data.alerts
175
- .map((a, i) => normalizeAlert(a, i))
176
- .filter((a) => !!a)
177
- .slice(0, 25)
178
- : [];
179
- setSnapshots(prev => {
180
- nextSnapshot = normalizeSnapshot(rawSnapshot, prev[0]);
181
- return [nextSnapshot, ...prev].slice(0, 40);
182
- });
183
- if (nextAlerts) {
184
- setAlerts(nextAlerts);
86
+ const response = await authFetch(`${agentBaseUrl}/api/v1/agents`, {
87
+ method: 'POST',
88
+ body: JSON.stringify({
89
+ name: agentName,
90
+ description: 'MCP monitoring demo – web crawling via Tavily with live cost/token metrics',
91
+ agent_library: 'pydantic-ai',
92
+ transport: 'vercel-ai',
93
+ agent_spec_id: AGENT_SPEC_ID,
94
+ enable_skills: true,
95
+ tools: [],
96
+ }),
97
+ });
98
+ let resolvedAgentId = agentName;
99
+ let isAlreadyRunning = false;
100
+ if (response.ok) {
101
+ const data = await response.json();
102
+ resolvedAgentId = data?.id || agentName;
103
+ }
104
+ else {
105
+ const contentType = response.headers.get('content-type') || '';
106
+ let detail = '';
107
+ if (contentType.includes('application/json')) {
108
+ const data = await response.json().catch(() => null);
109
+ detail =
110
+ (typeof data?.detail === 'string' && data.detail) ||
111
+ (typeof data?.message === 'string' && data.message) ||
112
+ '';
113
+ }
114
+ else {
115
+ detail = await response.text();
116
+ }
117
+ if (response.status === 409 || /already exists/i.test(detail || '')) {
118
+ isAlreadyRunning = true;
119
+ }
120
+ else {
121
+ throw new Error(detail || `Failed to create local agent: ${response.status}`);
185
122
  }
186
- return;
123
+ }
124
+ if (!isCancelled) {
125
+ setAgentId(resolvedAgentId);
126
+ setIsReconnectedAgent(isAlreadyRunning);
127
+ setIsReady(true);
128
+ setRuntimeStatus('ready');
187
129
  }
188
130
  }
189
- catch {
190
- // Keep UI responsive with synthetic values when endpoint is unavailable.
191
- }
192
- setSnapshots(prev => {
193
- if (prev.length > 0) {
194
- return prev;
131
+ catch (error) {
132
+ if (!isCancelled) {
133
+ setHookError(error instanceof Error ? error.message : 'Agent failed to start');
134
+ setRuntimeStatus('error');
195
135
  }
196
- return [createSyntheticSnapshot()];
197
- });
136
+ }
137
+ };
138
+ void createLocalAgent();
139
+ return () => {
140
+ isCancelled = true;
198
141
  };
199
- poll();
200
- const interval = window.setInterval(poll, 10_000);
201
- return () => window.clearInterval(interval);
202
- }, [isReady, agentBaseUrl, agentId, authFetch]);
142
+ }, [agentBaseUrl, authFetch]);
143
+ const handleMonitoringStreamMessage = useCallback((message) => {
144
+ try {
145
+ const stream = parseAgentStreamMessage(message?.raw ?? message);
146
+ if (!stream || stream.type !== 'agent.snapshot') {
147
+ return;
148
+ }
149
+ const payload = stream.payload;
150
+ if (payload.contextSnapshot) {
151
+ setLiveContext(payload.contextSnapshot);
152
+ setLiveContextSnapshot(payload.contextSnapshot);
153
+ setMonitorLastSnapshotAt(Date.now());
154
+ }
155
+ if (payload.mcpStatus !== undefined) {
156
+ setLiveMcpStatus(payload.mcpStatus ?? undefined);
157
+ }
158
+ if (payload.graphTelemetry) {
159
+ setLiveGraphTelemetry(payload.graphTelemetry);
160
+ }
161
+ const snapshotCost = payload.contextSnapshot?.costUsage ?? payload.costUsage;
162
+ if (!snapshotCost) {
163
+ return;
164
+ }
165
+ setLiveCost({
166
+ agentId,
167
+ lastTurnCostUsd: Number(snapshotCost.lastTurnCostUsd ?? 0),
168
+ cumulativeCostUsd: Number(snapshotCost.cumulativeCostUsd ?? 0),
169
+ perRunBudgetUsd: snapshotCost.perRunBudgetUsd == null
170
+ ? null
171
+ : Number(snapshotCost.perRunBudgetUsd),
172
+ cumulativeBudgetUsd: snapshotCost.cumulativeBudgetUsd == null
173
+ ? null
174
+ : Number(snapshotCost.cumulativeBudgetUsd),
175
+ requestCount: Number(snapshotCost.requestCount ?? 0),
176
+ totalTokensUsed: Number(snapshotCost.totalTokensUsed ?? 0),
177
+ modelBreakdown: Array.isArray(snapshotCost.modelBreakdown)
178
+ ? snapshotCost.modelBreakdown.map(item => ({
179
+ model: String(item.model ?? 'unknown'),
180
+ inputTokens: Number(item.inputTokens ?? 0),
181
+ outputTokens: Number(item.outputTokens ?? 0),
182
+ costUsd: Number(item.costUsd ?? 0),
183
+ requests: Number(item.requests ?? 0),
184
+ }))
185
+ : [],
186
+ runs: Array.isArray(snapshotCost.runs)
187
+ ? snapshotCost.runs.map(item => ({
188
+ pricingResolved: Boolean(item.pricingResolved),
189
+ }))
190
+ : undefined,
191
+ });
192
+ }
193
+ catch {
194
+ // Ignore malformed stream payloads.
195
+ }
196
+ }, [agentId]);
197
+ const monitorSocket = useAIAgentsWebSocket({
198
+ enabled: isReady && Boolean(agentBaseUrl),
199
+ baseUrl: agentBaseUrl,
200
+ path: '/api/v1/tool-approvals/ws',
201
+ queryParams: { agent_id: agentId },
202
+ onMessage: handleMonitoringStreamMessage,
203
+ reconnectDelayMs: attempt => Math.min(1000 * 2 ** Math.max(0, attempt - 1), 10000),
204
+ });
205
+ useEffect(() => {
206
+ // Monitoring alerts endpoint is optional and may return 404 in local mode.
207
+ // Keep the UI quiet and rely on stream snapshots for now.
208
+ setAlerts([]);
209
+ }, [isReady, agentId]);
203
210
  if (!isReady && runtimeStatus !== 'error') {
204
211
  return (_jsxs(Box, { sx: {
205
212
  display: 'flex',
@@ -208,21 +215,11 @@ const AgentMonitoringInner = ({ onLogout, }) => {
208
215
  justifyContent: 'center',
209
216
  height: '100vh',
210
217
  gap: 3,
211
- }, children: [_jsx(Spinner, { size: "large" }), _jsx(Text, { sx: { color: 'fg.muted' }, children: runtimeStatus === 'launching'
212
- ? 'Launching runtime for monitoring agent…'
213
- : 'Creating monitoring demo agent…' })] }));
218
+ }, children: [_jsx(Spinner, { size: "large" }), _jsx(Text, { sx: { color: 'fg.muted' }, children: "Launching local monitoring demo agent..." })] }));
214
219
  }
215
220
  if (runtimeStatus === 'error' || hookError) {
216
- return (_jsxs(Box, { sx: {
217
- display: 'flex',
218
- flexDirection: 'column',
219
- alignItems: 'center',
220
- justifyContent: 'center',
221
- height: '100vh',
222
- gap: 3,
223
- }, children: [_jsx(AlertIcon, { size: 48 }), _jsx(Text, { sx: { color: 'danger.fg' }, children: hookError || 'Agent failed to start' })] }));
221
+ return _jsx(ErrorView, { error: hookError, onLogout: onLogout });
224
222
  }
225
- const latest = snapshots[0] ?? createSyntheticSnapshot();
226
223
  return (_jsxs(Box, { sx: {
227
224
  height: 'calc(100vh - 60px)',
228
225
  display: 'flex',
@@ -236,46 +233,109 @@ const AgentMonitoringInner = ({ onLogout, }) => {
236
233
  borderBottom: '1px solid',
237
234
  borderColor: 'border.default',
238
235
  flexShrink: 0,
239
- }, children: [_jsx(GraphIcon, { size: 16 }), _jsxs(Heading, { as: "h3", sx: { fontSize: 2, flex: 1 }, children: ["Monitoring \u2014 ", podName] }), _jsx(Label, { variant: statusVariant(latest.status), size: "small", children: latest.status }), 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: "Monitoring Agent", placeholder: "Ask about performance, latency, and alert trends\u2026", description: `${alerts.length} active alert${alerts.length !== 1 ? 's' : ''}`, showHeader: true, autoFocus: true, height: "100%", runtimeId: podName, historyEndpoint: `${agentBaseUrl}/api/v1/history`, suggestions: [
236
+ }, children: [_jsx(GraphIcon, { size: 16 }), _jsxs(Heading, { as: "h3", sx: { fontSize: 2, flex: 1 }, children: ["Monitoring \u2014 ", podName] }), isReconnectedAgent && (_jsx(Label, { variant: "secondary", size: "small", children: "Reconnected" })), _jsxs(Label, { variant: monitorSocket.connectionState === 'connected'
237
+ ? 'success'
238
+ : 'secondary', children: ["WS: ", monitorSocket.connectionState] })] }), _jsxs(Box, { sx: { flex: 1, minHeight: 0, display: 'flex' }, children: [_jsxs(Box, { sx: {
239
+ width: 320,
240
+ minWidth: 280,
241
+ borderRight: '1px solid',
242
+ borderColor: 'border.default',
243
+ display: 'flex',
244
+ flexDirection: 'column',
245
+ overflow: 'auto',
246
+ '@media (max-width: 1680px)': {
247
+ width: 300,
248
+ minWidth: 260,
249
+ },
250
+ '@media (max-width: 1400px)': {
251
+ display: 'none',
252
+ },
253
+ }, children: [_jsxs(Box, { sx: {
254
+ p: 3,
255
+ borderBottom: '1px solid',
256
+ borderColor: 'border.default',
257
+ }, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: "Token Usage" }), _jsx(TokenUsageChart, { serviceName: otelServiceName, agentId: agentId, apiKey: token ?? undefined, runUrl: otelBaseUrl, liveSystemPromptTokens: liveContextSnapshot?.systemPromptTokens, liveUserMessageTokens: liveContextSnapshot?.userMessageTokens, liveAgentMessageTokens: liveContextSnapshot?.assistantMessageTokens, liveToolsUsageTokens: liveContextSnapshot?.toolTokens, liveTimestampMs: monitorLastSnapshotAt, height: 180 })] }), _jsxs(Box, { sx: {
258
+ p: 3,
259
+ borderBottom: '1px solid',
260
+ borderColor: 'border.default',
261
+ }, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: "Cost" }), _jsx(CostUsageChart, { serviceName: otelServiceName, agentId: agentId, apiKey: token ?? undefined, runUrl: otelBaseUrl, liveCumulativeUsd: liveCost?.cumulativeCostUsd, liveTimestampMs: monitorLastSnapshotAt, height: 180 })] }), _jsxs(Box, { sx: {
262
+ p: 3,
263
+ borderBottom: '1px solid',
264
+ borderColor: 'border.default',
265
+ }, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: "LLM Cost Monitoring" }), liveCost ? (_jsx(CostTracker, { agentId: agentId, compact: false, liveData: liveCost })) : (_jsxs(Box, { children: [_jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "Waiting for first websocket snapshot..." }), monitorSocket.lastClose?.detail && (_jsxs(Text, { sx: {
266
+ color: 'danger.fg',
267
+ fontSize: 0,
268
+ mt: 1,
269
+ display: 'block',
270
+ }, children: ["Last close: ", monitorSocket.lastClose.detail] }))] }))] })] }), _jsx(Box, { sx: { flex: 1, minWidth: 0 }, children: _jsx(Chat, { protocol: "vercel-ai", baseUrl: agentBaseUrl, agentId: agentId, authToken: chatAuthToken, title: "Monitoring Agent", placeholder: "Ask for cost, token usage, and turn-level monitoring insights...", description: `${alerts.length} active alert${alerts.length !== 1 ? 's' : ''}`, showHeader: true, showTokenUsage: true, showToolsMenu: true, showSkillsMenu: true, autoFocus: true, height: "100%", runtimeId: agentId, historyEndpoint: `${agentBaseUrl}/api/v1/history`, suggestions: [
240
271
  {
241
- title: 'Health summary',
242
- message: 'Summarize current agent health and key bottlenecks',
272
+ title: ' No-tool turn',
273
+ message: 'Briefly introduce yourself without calling any tool or skill — produces a linear Start → Model → Decision → End graph.',
243
274
  },
244
275
  {
245
- title: 'Alert triage',
246
- message: 'List critical alerts first and suggest immediate mitigations',
276
+ title: '🔍 Single tool call',
277
+ message: 'Use the Tavily web search tool to find the latest news about pydantic-graph. Make a single search call.',
247
278
  },
248
- ], submitOnSuggestionClick: true }) }), _jsxs(Box, { sx: {
249
- width: 380,
279
+ {
280
+ title: '🌀 Parallel tool fan-out',
281
+ message: 'Use Tavily to search the web in parallel for these three topics in the same turn: (1) OpenTelemetry traces, (2) agent observability, (3) LLM cost monitoring. Issue all three searches together so the turn graph fans out (Broadcast → Spread → Join).',
282
+ },
283
+ {
284
+ title: '🧩 Skill call',
285
+ message: 'Use the datalayer-whoami skill to identify my profile, then summarize it.',
286
+ },
287
+ {
288
+ title: '😄 Joke skill',
289
+ message: 'Use the jokes skill to tell me a random dad joke, then wrap it in one-sentence commentary.',
290
+ },
291
+ {
292
+ title: '🧪 Mixed tools + skills',
293
+ message: 'In one turn: (a) use Tavily to search for "OTEL traces best practices", (b) call the datalayer-whoami skill, (c) call the jokes skill. Summarize all three results together. This should produce a Broadcast → three Spread nodes → Join in the Turn Execution Graph.',
294
+ },
295
+ {
296
+ title: 'Monitoring summary',
297
+ message: 'Summarize my current token usage, cost status, and recent turn activity.',
298
+ },
299
+ {
300
+ title: 'Turn usage analysis',
301
+ message: 'Analyze the last turn usage and explain which parts drove input and output tokens.',
302
+ },
303
+ ], submitOnSuggestionClick: true, contextSnapshot: liveContextSnapshot, mcpStatusData: liveMcpStatus }) }), _jsxs(Box, { sx: {
304
+ width: 360,
305
+ minWidth: 320,
250
306
  borderLeft: '1px solid',
251
307
  borderColor: 'border.default',
252
308
  display: 'flex',
253
309
  flexDirection: 'column',
254
310
  overflow: 'auto',
311
+ '@media (max-width: 1680px)': {
312
+ width: 340,
313
+ minWidth: 300,
314
+ },
315
+ '@media (max-width: 1100px)': {
316
+ width: 300,
317
+ minWidth: 260,
318
+ },
255
319
  }, children: [_jsxs(Box, { sx: {
256
320
  p: 3,
257
321
  borderBottom: '1px solid',
258
322
  borderColor: 'border.default',
259
- }, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: "Live Metrics" }), _jsx(MetricRow, { label: "CPU", value: `${latest.cpuPercent.toFixed(1)}%`, percent: latest.cpuPercent }), _jsx(MetricRow, { label: "Memory", value: `${latest.memoryPercent.toFixed(1)}%`, percent: latest.memoryPercent }), _jsx(MetricRow, { label: "Latency", value: `${Math.round(latest.latencyMs)} ms`, percent: (latest.latencyMs / 2000) * 100 }), _jsx(MetricRow, { label: "Error Rate", value: `${latest.errorRatePercent.toFixed(2)}%`, percent: latest.errorRatePercent * 20 }), _jsx(MetricRow, { label: "Queue Depth", value: `${latest.queueDepth}`, percent: latest.queueDepth })] }), _jsxs(Box, { sx: { p: 3, flex: 1, overflow: 'auto' }, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: "Recent Alerts" }), alerts.length === 0 ? (_jsxs(Box, { sx: {
260
- p: 2,
261
- border: '1px solid',
262
- borderColor: 'border.default',
263
- borderRadius: 2,
264
- display: 'flex',
265
- alignItems: 'center',
266
- gap: 2,
267
- }, children: [_jsx(CheckCircleIcon, { size: 16 }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "No active alerts." })] })) : (alerts.map(alert => (_jsxs(Box, { sx: {
268
- p: 2,
269
- mb: 2,
270
- border: '1px solid',
271
- borderColor: 'border.default',
272
- borderRadius: 2,
273
- }, children: [_jsxs(Box, { sx: {
274
- display: 'flex',
275
- justifyContent: 'space-between',
276
- alignItems: 'center',
277
- mb: 1,
278
- }, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold' }, children: alert.title }), _jsx(Label, { size: "small", variant: alertVariant(alert.severity), children: alert.severity })] }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: new Date(alert.timestamp).toLocaleString() })] }, alert.id))))] })] })] })] }));
323
+ }, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: "Turn and Session Usage" }), liveContext ? (_jsx(ContextPanel, { agentId: agentId, apiBase: agentBaseUrl, liveData: liveContext, defaultView: "overview", chartHeight: "160px" })) : (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "Waiting for first websocket snapshot..." })), _jsxs(Text, { sx: { mt: 2, color: 'fg.muted', fontSize: 0 }, children: ["Live monitoring uses websocket snapshots only.", monitorLastSnapshotAt
324
+ ? ` Last snapshot ${new Date(monitorLastSnapshotAt).toLocaleTimeString()}.`
325
+ : '', monitorSocket.connectionState !== 'connected' &&
326
+ monitorSocket.reconnectAttempt > 0
327
+ ? ` Reconnect attempt ${monitorSocket.reconnectAttempt}.`
328
+ : ''] })] }), liveGraphTelemetry && (_jsxs(Box, { sx: {
329
+ p: 3,
330
+ borderBottom: '1px solid',
331
+ borderColor: 'border.default',
332
+ }, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: "Graph Execution (live)" }), _jsx(GraphFlowChart, { data: liveGraphTelemetry, height: 240 }), _jsxs(Text, { sx: { mt: 1, color: 'fg.muted', fontSize: 0 }, children: [liveGraphTelemetry.totalNodesExecuted, " node(s) executed across", ' ', liveGraphTelemetry.runCount, " run(s)", liveGraphTelemetry.totalDurationMs
333
+ ? ` — ${(liveGraphTelemetry.totalDurationMs / 1000).toFixed(2)}s total`
334
+ : ''] })] })), _jsxs(Box, { sx: {
335
+ p: 3,
336
+ borderBottom: '1px solid',
337
+ borderColor: 'border.default',
338
+ }, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: "Turn Execution Graph (OTEL traces)" }), _jsx(TurnGraphChart, { serviceName: otelServiceName, agentId: agentId, runUrl: otelBaseUrl, apiKey: token ?? undefined, autoRefreshMs: 10_000, height: 280 })] })] })] })] }));
279
339
  };
280
340
  const syncTokenToIamStore = (token) => {
281
341
  import('@datalayer/core/lib/state').then(({ iamStore }) => {
@@ -283,7 +343,7 @@ const syncTokenToIamStore = (token) => {
283
343
  });
284
344
  };
285
345
  const AgentMonitoringExample = () => {
286
- const { token, setAuth, clearAuth } = useSimpleAuthStore();
346
+ const { token, clearAuth } = useSimpleAuthStore();
287
347
  const hasSynced = useRef(false);
288
348
  useEffect(() => {
289
349
  if (token && !hasSynced.current) {
@@ -291,11 +351,6 @@ const AgentMonitoringExample = () => {
291
351
  syncTokenToIamStore(token);
292
352
  }
293
353
  }, [token]);
294
- const handleSignIn = useCallback((newToken, handle) => {
295
- setAuth(newToken, handle);
296
- hasSynced.current = true;
297
- syncTokenToIamStore(newToken);
298
- }, [setAuth]);
299
354
  const handleLogout = useCallback(() => {
300
355
  clearAuth();
301
356
  hasSynced.current = false;
@@ -304,7 +359,7 @@ const AgentMonitoringExample = () => {
304
359
  });
305
360
  }, [clearAuth]);
306
361
  if (!token) {
307
- return (_jsx(ThemedProvider, { children: _jsx(SignInSimple, { onSignIn: handleSignIn, onApiKeySignIn: apiKey => handleSignIn(apiKey, 'api-key-user'), title: "Agent Monitoring", description: "Sign in to monitor runtime health and alerts.", leadingIcon: _jsx(GraphIcon, { size: 24 }) }) }));
362
+ return (_jsx(ThemedProvider, { children: _jsx(AuthRequiredView, {}) }));
308
363
  }
309
364
  return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ThemedProvider, { children: _jsx(AgentMonitoringInner, { onLogout: handleLogout }) }) }));
310
365
  };