@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,378 @@
1
+ import { jsx as _jsx } 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, useRef, useState } from 'react';
7
+ import ReactECharts from 'echarts-for-react';
8
+ import { buildOtelWebSocketUrl } from '@datalayer/core/lib/otel';
9
+ import { toMetricValue } from '../hooks/useMonitoring';
10
+ import { subscribeOtelWs } from './otelWsPool';
11
+ import { agentRuntimeStore, getMonitoringCacheKey, useAgentRuntimeStore, } from '../stores/agentRuntimeStore';
12
+ const COST_RUN_METRIC = 'agent_runtimes.capability.cost.run.usd';
13
+ const COST_CUMULATIVE_METRIC = 'agent_runtimes.capability.cost.cumulative.usd';
14
+ function resolveMonitoringEntry(monitoringCache, serviceName, agentId) {
15
+ const direct = monitoringCache[getMonitoringCacheKey(serviceName, agentId)];
16
+ if (direct)
17
+ return direct;
18
+ if (agentId) {
19
+ const byAgent = Object.entries(monitoringCache).find(([key, entry]) => {
20
+ return key.endsWith(`::${agentId}`) && entry.costPoints.length > 0;
21
+ });
22
+ if (byAgent)
23
+ return byAgent[1];
24
+ }
25
+ if (serviceName) {
26
+ const byService = Object.entries(monitoringCache).find(([key, entry]) => {
27
+ return key.startsWith(`${serviceName}::`) && entry.costPoints.length > 0;
28
+ });
29
+ if (byService)
30
+ return byService[1];
31
+ }
32
+ return undefined;
33
+ }
34
+ function localPointToCostPoint(point) {
35
+ return {
36
+ timestampKey: String(point.timestampMs),
37
+ timestampMs: point.timestampMs,
38
+ costUsd: 0,
39
+ cumulativeUsd: point.cumulativeUsd,
40
+ };
41
+ }
42
+ /** Parse attributes that may arrive as a JSON string (WS) or object (HTTP). */
43
+ function parseAttributes(attrs) {
44
+ if (attrs && typeof attrs === 'object' && !Array.isArray(attrs)) {
45
+ return attrs;
46
+ }
47
+ if (typeof attrs === 'string') {
48
+ try {
49
+ return JSON.parse(attrs);
50
+ }
51
+ catch {
52
+ return {};
53
+ }
54
+ }
55
+ return {};
56
+ }
57
+ /** Convert metric row timestamp to milliseconds. */
58
+ function rowTimestampMs(row) {
59
+ const nanoTs = row.timestamp_unix_nano ?? row.observed_timestamp_unix_nano;
60
+ if (typeof nanoTs === 'number' && nanoTs > 0)
61
+ return nanoTs / 1_000_000;
62
+ if (typeof nanoTs === 'string' && nanoTs.length > 0) {
63
+ const parsed = Number(nanoTs);
64
+ if (Number.isFinite(parsed) && parsed > 0)
65
+ return parsed / 1_000_000;
66
+ }
67
+ const isoTs = row.timestamp;
68
+ if (typeof isoTs === 'string' && isoTs.length > 0) {
69
+ const ms = new Date(isoTs).getTime();
70
+ if (Number.isFinite(ms) && ms > 0)
71
+ return ms;
72
+ }
73
+ return Date.now();
74
+ }
75
+ function rowTimestampKey(row) {
76
+ const nano = row.timestamp_unix_nano;
77
+ if (typeof nano === 'number' && nano > 0)
78
+ return String(nano);
79
+ if (typeof nano === 'string' && nano.length > 0)
80
+ return nano;
81
+ const iso = row.timestamp;
82
+ if (typeof iso === 'string' && iso.length > 0)
83
+ return iso;
84
+ return '';
85
+ }
86
+ /** Extract cost points from cost metrics rows. */
87
+ function extractCostPoints(rows, agentId) {
88
+ let filtered = rows.filter(row => {
89
+ const metricName = row.metric_name;
90
+ return (metricName === COST_CUMULATIVE_METRIC || metricName === COST_RUN_METRIC);
91
+ });
92
+ if (agentId) {
93
+ filtered = filtered.filter(row => extractAgentId(row) === agentId);
94
+ }
95
+ const byTimestamp = new Map();
96
+ for (const row of filtered) {
97
+ const ts = rowTimestampKey(row);
98
+ if (!ts)
99
+ continue;
100
+ const group = byTimestamp.get(ts) ?? [];
101
+ group.push(row);
102
+ byTimestamp.set(ts, group);
103
+ }
104
+ const points = [];
105
+ const sorted = [...byTimestamp.entries()].sort((a, b) => {
106
+ const na = Number(a[0]);
107
+ const nb = Number(b[0]);
108
+ if (Number.isFinite(na) && Number.isFinite(nb))
109
+ return na - nb;
110
+ return a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0;
111
+ });
112
+ for (const [, groupRows] of sorted) {
113
+ const cumulativeRows = groupRows.filter(r => r.metric_name === COST_CUMULATIVE_METRIC);
114
+ if (cumulativeRows.length === 0)
115
+ continue;
116
+ const runRows = groupRows.filter(r => r.metric_name === COST_RUN_METRIC);
117
+ // Cumulative metric values represent the running total. Repeated snapshot
118
+ // rows for the same timestamp should not be summed; keep the highest value.
119
+ const cumulativeUsd = cumulativeRows.reduce((max, row) => Math.max(max, toMetricValue(row)), 0);
120
+ const costUsd = runRows.reduce((sum, row) => sum + toMetricValue(row), 0);
121
+ if (!Number.isFinite(cumulativeUsd) || !Number.isFinite(costUsd))
122
+ continue;
123
+ const timestampKey = rowTimestampKey(cumulativeRows[0]);
124
+ if (!timestampKey)
125
+ continue;
126
+ points.push({
127
+ timestampKey,
128
+ timestampMs: rowTimestampMs(cumulativeRows[0]),
129
+ costUsd,
130
+ cumulativeUsd,
131
+ });
132
+ }
133
+ points.sort((a, b) => a.timestampMs - b.timestampMs);
134
+ return points;
135
+ }
136
+ function extractServiceName(row) {
137
+ const directCandidates = [row.service_name, row.service, row.serviceName];
138
+ for (const candidate of directCandidates) {
139
+ if (typeof candidate === 'string' && candidate.length > 0) {
140
+ return candidate;
141
+ }
142
+ }
143
+ const resourceAttributes = row.resource_attributes;
144
+ if (resourceAttributes && typeof resourceAttributes === 'object') {
145
+ const nested = resourceAttributes['service.name'];
146
+ if (typeof nested === 'string' && nested.length > 0) {
147
+ return nested;
148
+ }
149
+ }
150
+ return undefined;
151
+ }
152
+ /** Extract `agent.id` from span/trace attributes. */
153
+ function extractAgentId(row) {
154
+ const attrs = parseAttributes(row.attributes);
155
+ const aid = attrs['agent.id'];
156
+ if (typeof aid === 'string')
157
+ return aid;
158
+ return undefined;
159
+ }
160
+ export function CostUsageChart({ serviceName, agentId, apiKey, runUrl, wsRunUrl, liveCumulativeUsd, liveTimestampMs, height = 160, }) {
161
+ const monitoringCache = useAgentRuntimeStore(s => s.monitoringCache);
162
+ const mergeCostPoints = useAgentRuntimeStore(s => s.mergeCostPoints);
163
+ const upsertLocalCostPoint = useAgentRuntimeStore(s => s.upsertLocalCostPoint);
164
+ const cachedEntry = useMemo(() => resolveMonitoringEntry(monitoringCache, serviceName, agentId), [agentId, monitoringCache, serviceName]);
165
+ const [points, setPoints] = useState([]);
166
+ const initialTimestampMsRef = useRef(Date.now());
167
+ const mergePoints = (existing, incoming) => {
168
+ const byTimestamp = new Map();
169
+ for (const point of existing) {
170
+ byTimestamp.set(point.timestampKey, point);
171
+ }
172
+ for (const point of incoming) {
173
+ const prev = byTimestamp.get(point.timestampKey);
174
+ if (!prev) {
175
+ byTimestamp.set(point.timestampKey, point);
176
+ continue;
177
+ }
178
+ byTimestamp.set(point.timestampKey, {
179
+ ...prev,
180
+ timestampMs: Math.max(prev.timestampMs, point.timestampMs),
181
+ costUsd: Math.max(prev.costUsd, point.costUsd),
182
+ cumulativeUsd: Math.max(prev.cumulativeUsd, point.cumulativeUsd),
183
+ });
184
+ }
185
+ const merged = Array.from(byTimestamp.values()).sort((a, b) => a.timestampMs - b.timestampMs);
186
+ // Cumulative cost should never decrease; guard against out-of-order or
187
+ // duplicate snapshots by enforcing a monotonic series.
188
+ let runningMax = 0;
189
+ return merged.map(point => {
190
+ runningMax = Math.max(runningMax, point.cumulativeUsd);
191
+ return {
192
+ ...point,
193
+ cumulativeUsd: runningMax,
194
+ };
195
+ });
196
+ };
197
+ // ── Reset state on source switch ──────────────────────────────
198
+ useEffect(() => {
199
+ if (!serviceName) {
200
+ setPoints([]);
201
+ return;
202
+ }
203
+ setPoints((cachedEntry?.costPoints ?? []).map(localPointToCostPoint));
204
+ initialTimestampMsRef.current = Date.now();
205
+ }, [agentId, cachedEntry, serviceName]);
206
+ // Apply immediate post-turn updates from the monitoring websocket snapshot.
207
+ useEffect(() => {
208
+ if (!serviceName)
209
+ return;
210
+ if (typeof liveCumulativeUsd !== 'number' ||
211
+ !Number.isFinite(liveCumulativeUsd)) {
212
+ return;
213
+ }
214
+ const timestampMs = typeof liveTimestampMs === 'number' && Number.isFinite(liveTimestampMs)
215
+ ? liveTimestampMs
216
+ : Date.now();
217
+ const livePoint = {
218
+ timestampKey: `live-${timestampMs}`,
219
+ timestampMs,
220
+ costUsd: 0,
221
+ cumulativeUsd: Math.max(0, liveCumulativeUsd),
222
+ };
223
+ upsertLocalCostPoint({
224
+ serviceName,
225
+ agentId,
226
+ timestampMs,
227
+ cumulativeUsd: livePoint.cumulativeUsd,
228
+ });
229
+ const mergedEntry = resolveMonitoringEntry(agentRuntimeStore.getState().monitoringCache, serviceName, agentId);
230
+ if (mergedEntry) {
231
+ setPoints(mergedEntry.costPoints.map(localPointToCostPoint));
232
+ }
233
+ else {
234
+ setPoints(prev => mergePoints(prev, [livePoint]));
235
+ }
236
+ }, [
237
+ agentId,
238
+ liveCumulativeUsd,
239
+ liveTimestampMs,
240
+ serviceName,
241
+ upsertLocalCostPoint,
242
+ ]);
243
+ // ── WebSocket subscription (shared connection pool) ─────────
244
+ useEffect(() => {
245
+ if (!serviceName || !apiKey)
246
+ return;
247
+ const rawBaseUrl = wsRunUrl ||
248
+ runUrl ||
249
+ (typeof window !== 'undefined' ? window.location.origin : '');
250
+ if (!rawBaseUrl)
251
+ return;
252
+ const baseWithProtocol = rawBaseUrl.startsWith('http://') ||
253
+ rawBaseUrl.startsWith('https://') ||
254
+ rawBaseUrl.startsWith('ws://') ||
255
+ rawBaseUrl.startsWith('wss://')
256
+ ? rawBaseUrl
257
+ : `${typeof window !== 'undefined' &&
258
+ window.location.protocol === 'https:'
259
+ ? 'https:'
260
+ : 'http:'}//${typeof window !== 'undefined' ? window.location.host : ''}${rawBaseUrl}`;
261
+ let wsUrl;
262
+ try {
263
+ wsUrl = buildOtelWebSocketUrl({
264
+ baseUrl: baseWithProtocol,
265
+ token: apiKey,
266
+ });
267
+ }
268
+ catch {
269
+ return;
270
+ }
271
+ const unsubscribe = subscribeOtelWs(wsUrl, msg => {
272
+ if (msg.signal !== 'metrics')
273
+ return;
274
+ const rows = Array.isArray(msg.data) ? msg.data : [];
275
+ let matchingRows = rows.filter(row => extractServiceName(row) === serviceName);
276
+ // Filter by agent.id when specified.
277
+ if (agentId) {
278
+ matchingRows = matchingRows.filter(row => extractAgentId(row) === agentId);
279
+ }
280
+ if (matchingRows.length === 0)
281
+ return;
282
+ const newPoints = extractCostPoints(matchingRows, agentId);
283
+ if (newPoints.length > 0) {
284
+ mergeCostPoints({
285
+ serviceName,
286
+ agentId,
287
+ points: newPoints.map(point => ({
288
+ timestampMs: point.timestampMs,
289
+ cumulativeUsd: point.cumulativeUsd,
290
+ })),
291
+ });
292
+ const mergedEntry = resolveMonitoringEntry(agentRuntimeStore.getState().monitoringCache, serviceName, agentId);
293
+ if (mergedEntry) {
294
+ setPoints(mergedEntry.costPoints.map(localPointToCostPoint));
295
+ }
296
+ else {
297
+ setPoints(prev => mergePoints(prev, newPoints));
298
+ }
299
+ }
300
+ });
301
+ return unsubscribe;
302
+ }, [agentId, apiKey, mergeCostPoints, runUrl, serviceName, wsRunUrl]);
303
+ // ── Chart options ─────────────────────────────────────────────
304
+ const option = useMemo(() => {
305
+ const chartData = points.length > 0
306
+ ? [
307
+ [points[0].timestampMs, 0],
308
+ ...points.map(p => [p.timestampMs, p.cumulativeUsd]),
309
+ ]
310
+ : [[initialTimestampMsRef.current, 0]];
311
+ return {
312
+ animation: false,
313
+ animationDuration: 0,
314
+ animationDurationUpdate: 0,
315
+ tooltip: {
316
+ trigger: 'axis',
317
+ textStyle: { fontSize: 10 },
318
+ confine: true,
319
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
320
+ formatter: (params) => {
321
+ if (!Array.isArray(params) || params.length === 0)
322
+ return '';
323
+ const lines = params.map((p) => `${p.marker} ${p.seriesName}: $${p.value[1].toFixed(6)}`);
324
+ return lines.join('<br/>');
325
+ },
326
+ },
327
+ legend: {
328
+ data: ['Cumulative cost'],
329
+ top: 0,
330
+ textStyle: { fontSize: 9 },
331
+ itemWidth: 10,
332
+ itemHeight: 8,
333
+ itemGap: 6,
334
+ },
335
+ grid: {
336
+ left: 50,
337
+ right: 15,
338
+ top: 24,
339
+ bottom: 20,
340
+ },
341
+ xAxis: {
342
+ type: 'time',
343
+ min: 'dataMin',
344
+ max: 'dataMax',
345
+ axisLabel: { fontSize: 9 },
346
+ axisLine: { lineStyle: { color: '#d0d7de' } },
347
+ },
348
+ yAxis: {
349
+ type: 'value',
350
+ min: 0,
351
+ axisLabel: {
352
+ fontSize: 9,
353
+ formatter: (v) => `$${v.toFixed(4)}`,
354
+ },
355
+ splitLine: {
356
+ show: true,
357
+ lineStyle: { color: '#f0f0f0' },
358
+ },
359
+ },
360
+ series: [
361
+ {
362
+ name: 'Cumulative cost',
363
+ type: 'line',
364
+ smooth: false,
365
+ lineStyle: { width: 2 },
366
+ areaStyle: { opacity: 0.15 },
367
+ symbol: 'circle',
368
+ symbolSize: 4,
369
+ itemStyle: { color: '#cf222e' },
370
+ data: chartData,
371
+ animation: false,
372
+ },
373
+ ],
374
+ };
375
+ }, [points]);
376
+ return (_jsx(ReactECharts, { option: option, style: { height, width: '100%' }, opts: { renderer: 'canvas' }, notMerge: true, lazyUpdate: true }));
377
+ }
378
+ export default CostUsageChart;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * GraphFlowChart — ECharts graph visualisation of pydantic-graph execution.
3
+ *
4
+ * Renders a force-directed graph showing:
5
+ * - Static topology (nodes + edges from the graph definition)
6
+ * - Dynamic execution trace (which nodes were visited, with timing)
7
+ */
8
+ import { type CSSProperties } from 'react';
9
+ import type { GraphTelemetryData } from '../types/stream';
10
+ export interface GraphFlowChartProps {
11
+ data: GraphTelemetryData;
12
+ height?: number | string;
13
+ style?: CSSProperties;
14
+ }
15
+ export declare const GraphFlowChart: React.FC<GraphFlowChartProps>;
16
+ export default GraphFlowChart;
@@ -0,0 +1,182 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2025-2026 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ /**
7
+ * GraphFlowChart — ECharts graph visualisation of pydantic-graph execution.
8
+ *
9
+ * Renders a force-directed graph showing:
10
+ * - Static topology (nodes + edges from the graph definition)
11
+ * - Dynamic execution trace (which nodes were visited, with timing)
12
+ */
13
+ import { useMemo } from 'react';
14
+ import ReactECharts from 'echarts-for-react';
15
+ /** Category definitions for ECharts graph. */
16
+ const CATEGORIES = [
17
+ { name: 'start', itemStyle: { color: '#58a6ff' } },
18
+ { name: 'step', itemStyle: { color: '#3fb950' } },
19
+ { name: 'end', itemStyle: { color: '#f85149' } },
20
+ { name: 'end_or_continue', itemStyle: { color: '#d29922' } },
21
+ { name: 'join', itemStyle: { color: '#bc8cff' } },
22
+ { name: 'decision', itemStyle: { color: '#f0883e' } },
23
+ { name: 'error', itemStyle: { color: '#da3633' } },
24
+ { name: 'parallel', itemStyle: { color: '#79c0ff' } },
25
+ ];
26
+ const CATEGORY_INDEX = {};
27
+ CATEGORIES.forEach((c, i) => {
28
+ CATEGORY_INDEX[c.name] = i;
29
+ });
30
+ function getCategoryIndex(category) {
31
+ return CATEGORY_INDEX[category] ?? CATEGORY_INDEX['step'];
32
+ }
33
+ /** Map node events to a lookup for fast access. */
34
+ function buildEventLookup(events) {
35
+ const map = new Map();
36
+ for (const evt of events) {
37
+ const existing = map.get(evt.nodeId);
38
+ if (existing) {
39
+ existing.push(evt);
40
+ }
41
+ else {
42
+ map.set(evt.nodeId, [evt]);
43
+ }
44
+ }
45
+ return map;
46
+ }
47
+ function formatDuration(ms) {
48
+ if (ms == null)
49
+ return '—';
50
+ if (ms < 1)
51
+ return '<1ms';
52
+ if (ms < 1000)
53
+ return `${ms.toFixed(1)}ms`;
54
+ return `${(ms / 1000).toFixed(2)}s`;
55
+ }
56
+ export const GraphFlowChart = ({ data, height = 320, style, }) => {
57
+ const option = useMemo(() => {
58
+ const eventLookup = buildEventLookup(data.events);
59
+ // Build ECharts nodes
60
+ const echartsNodes = data.nodes.map((node) => {
61
+ const nodeEvents = eventLookup.get(node.id) || [];
62
+ const lastEvent = nodeEvents[nodeEvents.length - 1];
63
+ const hitCount = nodeEvents.filter(e => e.status === 'completed').length;
64
+ const hasError = nodeEvents.some(e => e.status === 'error');
65
+ const totalDuration = nodeEvents.reduce((sum, e) => sum + (e.durationMs ?? 0), 0);
66
+ // Size based on hit count (bigger = more visits)
67
+ const baseSize = 30;
68
+ const symbolSize = baseSize + Math.min(hitCount * 8, 40);
69
+ // Determine visual category
70
+ let visualCategory = node.category;
71
+ if (hasError)
72
+ visualCategory = 'error';
73
+ return {
74
+ id: node.id,
75
+ name: node.name === '__start__'
76
+ ? 'Start'
77
+ : node.name === '__end__'
78
+ ? 'End'
79
+ : node.name,
80
+ symbolSize,
81
+ category: getCategoryIndex(visualCategory),
82
+ value: hitCount,
83
+ itemStyle: hitCount > 0 ? { borderWidth: 3, borderColor: '#e3b341' } : undefined,
84
+ label: {
85
+ show: true,
86
+ fontSize: 11,
87
+ color: '#c9d1d9',
88
+ },
89
+ tooltip: {
90
+ formatter: () => {
91
+ const lines = [
92
+ `<b>${node.name}</b>`,
93
+ `Category: ${node.category}`,
94
+ `Executions: ${hitCount}`,
95
+ ];
96
+ if (totalDuration > 0) {
97
+ lines.push(`Total duration: ${formatDuration(totalDuration)}`);
98
+ }
99
+ if (lastEvent?.status === 'error' && lastEvent.error) {
100
+ lines.push(`<span style="color:#f85149">Error: ${lastEvent.error}</span>`);
101
+ }
102
+ return lines.join('<br/>');
103
+ },
104
+ },
105
+ };
106
+ });
107
+ // Build ECharts edges (links)
108
+ const echartsLinks = data.edges.map((edge) => {
109
+ // Check if this edge was traversed in the execution trace
110
+ const wasTraversed = data.events.some(e => e.nodeId === edge.target && e.parentNodeId === edge.source);
111
+ return {
112
+ source: edge.source,
113
+ target: edge.target,
114
+ label: edge.label
115
+ ? {
116
+ show: true,
117
+ formatter: edge.label,
118
+ fontSize: 9,
119
+ color: '#8b949e',
120
+ }
121
+ : undefined,
122
+ lineStyle: {
123
+ color: wasTraversed ? '#e3b341' : '#484f58',
124
+ width: wasTraversed ? 3 : 1.5,
125
+ curveness: 0.2,
126
+ type: edge.edgeType === 'parallel'
127
+ ? 'dashed'
128
+ : 'solid',
129
+ },
130
+ };
131
+ });
132
+ return {
133
+ tooltip: {
134
+ trigger: 'item',
135
+ backgroundColor: '#161b22',
136
+ borderColor: '#30363d',
137
+ textStyle: { color: '#c9d1d9', fontSize: 12 },
138
+ },
139
+ legend: {
140
+ data: CATEGORIES.map(c => c.name),
141
+ top: 4,
142
+ textStyle: { color: '#8b949e', fontSize: 10 },
143
+ itemWidth: 12,
144
+ itemHeight: 12,
145
+ },
146
+ series: [
147
+ {
148
+ type: 'graph',
149
+ layout: 'force',
150
+ roam: true,
151
+ draggable: true,
152
+ categories: CATEGORIES,
153
+ data: echartsNodes,
154
+ links: echartsLinks,
155
+ force: {
156
+ repulsion: 200,
157
+ edgeLength: [80, 160],
158
+ gravity: 0.1,
159
+ },
160
+ edgeSymbol: ['none', 'arrow'],
161
+ edgeSymbolSize: [0, 8],
162
+ emphasis: {
163
+ focus: 'adjacency',
164
+ lineStyle: { width: 4 },
165
+ },
166
+ label: {
167
+ show: true,
168
+ position: 'bottom',
169
+ fontSize: 10,
170
+ },
171
+ lineStyle: {
172
+ opacity: 0.7,
173
+ },
174
+ animation: true,
175
+ animationDuration: 500,
176
+ },
177
+ ],
178
+ };
179
+ }, [data]);
180
+ return (_jsx(ReactECharts, { option: option, style: { height, width: '100%', ...style }, opts: { renderer: 'canvas' }, notMerge: true }));
181
+ };
182
+ export default GraphFlowChart;
@@ -1,10 +1,17 @@
1
1
  export interface TokenUsageChartProps {
2
2
  serviceName?: string;
3
+ agentId?: string;
3
4
  apiKey?: string;
4
5
  runUrl?: string;
5
6
  wsRunUrl?: string;
7
+ liveSystemPromptTokens?: number;
8
+ liveToolsDescriptionTokens?: number;
9
+ liveUserMessageTokens?: number;
10
+ liveAgentMessageTokens?: number;
11
+ liveToolsUsageTokens?: number;
12
+ liveTimestampMs?: number | null;
6
13
  height?: number;
7
14
  days?: number;
8
15
  }
9
- export declare function TokenUsageChart({ serviceName, apiKey, runUrl, wsRunUrl, height, days, }: TokenUsageChartProps): import("react/jsx-runtime").JSX.Element;
16
+ export declare function TokenUsageChart({ serviceName, agentId, apiKey, runUrl, wsRunUrl, liveSystemPromptTokens, liveToolsDescriptionTokens, liveUserMessageTokens, liveAgentMessageTokens, liveToolsUsageTokens, liveTimestampMs, height, }: TokenUsageChartProps): import("react/jsx-runtime").JSX.Element;
10
17
  export default TokenUsageChart;