@datalayer/agent-runtimes 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. package/README.md +34 -0
  2. package/lib/App.js +1 -1
  3. package/lib/agents/AgentDetails.d.ts +22 -1
  4. package/lib/agents/AgentDetails.js +34 -47
  5. package/lib/api/index.d.ts +0 -1
  6. package/lib/api/index.js +4 -2
  7. package/lib/chat/Chat.d.ts +5 -106
  8. package/lib/chat/Chat.js +4 -4
  9. package/lib/chat/ChatFloating.d.ts +7 -140
  10. package/lib/chat/ChatFloating.js +2 -2
  11. package/lib/chat/ChatPopupStandalone.d.ts +8 -47
  12. package/lib/chat/ChatPopupStandalone.js +3 -3
  13. package/lib/chat/ChatSidebar.d.ts +4 -69
  14. package/lib/chat/ChatSidebar.js +2 -2
  15. package/lib/chat/ChatStandalone.d.ts +4 -54
  16. package/lib/chat/ChatStandalone.js +3 -3
  17. package/lib/chat/base/ChatBase.js +1083 -157
  18. package/lib/chat/header/ChatHeaderBase.d.ts +11 -6
  19. package/lib/chat/header/ChatHeaderBase.js +18 -16
  20. package/lib/chat/indicators/McpStatusIndicator.d.ts +7 -4
  21. package/lib/chat/indicators/McpStatusIndicator.js +7 -32
  22. package/lib/chat/indicators/SandboxStatusIndicator.d.ts +4 -1
  23. package/lib/chat/indicators/SandboxStatusIndicator.js +9 -9
  24. package/lib/chat/indicators/SkillsStatusIndicator.d.ts +7 -0
  25. package/lib/chat/indicators/SkillsStatusIndicator.js +88 -0
  26. package/lib/chat/indicators/index.d.ts +1 -0
  27. package/lib/chat/indicators/index.js +1 -0
  28. package/lib/chat/messages/ChatMessageList.d.ts +1 -1
  29. package/lib/chat/messages/ChatMessageList.js +108 -113
  30. package/lib/chat/prompt/InputFooter.d.ts +19 -6
  31. package/lib/chat/prompt/InputFooter.js +71 -18
  32. package/lib/chat/prompt/InputPrompt.d.ts +3 -1
  33. package/lib/chat/prompt/InputPrompt.js +4 -4
  34. package/lib/chat/prompt/InputPromptFooter.js +1 -1
  35. package/lib/chat/prompt/InputPromptLexical.d.ts +3 -1
  36. package/lib/chat/prompt/InputPromptLexical.js +12 -5
  37. package/lib/chat/prompt/InputPromptText.d.ts +3 -1
  38. package/lib/chat/prompt/InputPromptText.js +2 -2
  39. package/lib/chat/tools/ToolApprovalBanner.js +1 -1
  40. package/lib/chat/tools/ToolCallDisplay.d.ts +3 -1
  41. package/lib/chat/tools/ToolCallDisplay.js +2 -2
  42. package/lib/chat/usage/TokenUsageBar.js +20 -2
  43. package/lib/client/AgentRuntimesClientContext.d.ts +53 -0
  44. package/lib/client/AgentRuntimesClientContext.js +55 -0
  45. package/lib/client/AgentsMixin.d.ts +0 -18
  46. package/lib/client/AgentsMixin.js +6 -30
  47. package/lib/client/IAgentRuntimesClient.d.ts +215 -0
  48. package/lib/client/IAgentRuntimesClient.js +5 -0
  49. package/lib/client/SdkAgentRuntimesClient.d.ts +151 -0
  50. package/lib/client/SdkAgentRuntimesClient.js +134 -0
  51. package/lib/client/index.d.ts +4 -1
  52. package/lib/client/index.js +3 -1
  53. package/lib/components/NotificationEventCard.js +5 -1
  54. package/lib/config/AgentConfiguration.js +3 -3
  55. package/lib/context/ContextDistribution.d.ts +3 -1
  56. package/lib/context/ContextDistribution.js +8 -27
  57. package/lib/context/ContextInspector.d.ts +3 -1
  58. package/lib/context/ContextInspector.js +19 -67
  59. package/lib/context/ContextPanel.d.ts +3 -1
  60. package/lib/context/ContextPanel.js +104 -64
  61. package/lib/context/ContextUsage.d.ts +3 -1
  62. package/lib/context/ContextUsage.js +3 -3
  63. package/lib/context/CostTracker.d.ts +9 -3
  64. package/lib/context/CostTracker.js +26 -47
  65. package/lib/context/CostUsageChart.d.ts +12 -0
  66. package/lib/context/CostUsageChart.js +378 -0
  67. package/lib/context/GraphFlowChart.d.ts +16 -0
  68. package/lib/context/GraphFlowChart.js +182 -0
  69. package/lib/context/TokenUsageChart.d.ts +8 -1
  70. package/lib/context/TokenUsageChart.js +349 -211
  71. package/lib/context/TurnGraphChart.d.ts +39 -0
  72. package/lib/context/TurnGraphChart.js +538 -0
  73. package/lib/context/otelWsPool.d.ts +20 -0
  74. package/lib/context/otelWsPool.js +69 -0
  75. package/lib/examples/A2UiComponentGalleryExample.d.ts +0 -17
  76. package/lib/examples/A2UiComponentGalleryExample.js +315 -522
  77. package/lib/examples/A2UiContactCardExample.d.ts +0 -18
  78. package/lib/examples/A2UiContactCardExample.js +154 -411
  79. package/lib/examples/A2UiRestaurantExample.d.ts +0 -30
  80. package/lib/examples/A2UiRestaurantExample.js +114 -212
  81. package/lib/examples/A2UiViewerExample.d.ts +0 -18
  82. package/lib/examples/A2UiViewerExample.js +283 -532
  83. package/lib/examples/AgUiBackendToolRenderingExample.js +1 -1
  84. package/lib/examples/AgUiHaikuGenUiExample.d.ts +1 -1
  85. package/lib/examples/AgUiHaikuGenUiExample.js +1 -1
  86. package/lib/examples/AgentCheckpointsExample.js +13 -27
  87. package/lib/examples/AgentCodemodeExample.d.ts +4 -6
  88. package/lib/examples/AgentCodemodeExample.js +591 -169
  89. package/lib/examples/AgentEvalsExample.js +12 -16
  90. package/lib/examples/AgentGuardrailsExample.js +370 -64
  91. package/lib/examples/AgentHooksExample.d.ts +3 -0
  92. package/lib/examples/AgentHooksExample.js +104 -0
  93. package/lib/examples/AgentMCPExample.d.ts +3 -0
  94. package/lib/examples/AgentMCPExample.js +480 -0
  95. package/lib/examples/AgentMemoryExample.js +13 -17
  96. package/lib/examples/AgentMonitoringExample.js +260 -199
  97. package/lib/examples/AgentNotificationsExample.js +49 -17
  98. package/lib/examples/AgentOtelExample.js +2 -3
  99. package/lib/examples/AgentOutputsExample.d.ts +11 -6
  100. package/lib/examples/AgentOutputsExample.js +382 -81
  101. package/lib/examples/AgentParametersExample.d.ts +3 -0
  102. package/lib/examples/AgentParametersExample.js +246 -0
  103. package/lib/examples/AgentSandboxExample.d.ts +2 -2
  104. package/lib/examples/AgentSandboxExample.js +68 -40
  105. package/lib/examples/AgentSkillsExample.js +91 -99
  106. package/lib/examples/{AgentspecExample.js → AgentSpecsExample.js} +10 -21
  107. package/lib/examples/AgentSubagentsExample.d.ts +14 -0
  108. package/lib/examples/AgentSubagentsExample.js +228 -0
  109. package/lib/examples/AgentToolApprovalsExample.js +29 -557
  110. package/lib/examples/AgentTriggersExample.js +819 -565
  111. package/lib/examples/ChatCustomExample.js +11 -24
  112. package/lib/examples/ChatExample.js +7 -24
  113. package/lib/examples/CopilotKitLexicalExample.js +2 -1
  114. package/lib/examples/CopilotKitNotebookExample.js +2 -1
  115. package/lib/examples/HomeExample.d.ts +15 -0
  116. package/lib/examples/HomeExample.js +77 -0
  117. package/lib/examples/Lexical2Example.js +4 -2
  118. package/lib/examples/{LexicalExample.d.ts → LexicalAgentExample.d.ts} +4 -4
  119. package/lib/examples/{LexicalExample.js → LexicalAgentExample.js} +65 -16
  120. package/lib/examples/{LexicalSidebarExample.d.ts → LexicalAgentSidebarExample.d.ts} +5 -5
  121. package/lib/examples/LexicalAgentSidebarExample.js +261 -0
  122. package/lib/examples/NotebookAgentExample.d.ts +9 -0
  123. package/lib/examples/NotebookAgentExample.js +192 -0
  124. package/lib/examples/{NotebookSidebarExample.d.ts → NotebookAgentSidebarExample.d.ts} +2 -2
  125. package/lib/examples/NotebookAgentSidebarExample.js +221 -0
  126. package/lib/examples/{DatalayerNotebookExample.d.ts → NotebookCollaborationExample.d.ts} +4 -4
  127. package/lib/examples/{DatalayerNotebookExample.js → NotebookCollaborationExample.js} +3 -3
  128. package/lib/examples/NotebookExample.d.ts +4 -7
  129. package/lib/examples/NotebookExample.js +14 -146
  130. package/lib/examples/components/AuthRequiredView.d.ts +6 -0
  131. package/lib/examples/components/AuthRequiredView.js +33 -0
  132. package/lib/examples/components/ExampleWrapper.d.ts +7 -0
  133. package/lib/examples/components/ExampleWrapper.js +25 -6
  134. package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.js +1 -1
  135. package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.js +1 -1
  136. package/lib/examples/{ag-ui → components}/haiku/index.d.ts +1 -1
  137. package/lib/examples/{ag-ui → components}/haiku/index.js +1 -1
  138. package/lib/examples/components/index.d.ts +3 -0
  139. package/lib/examples/components/index.js +4 -0
  140. package/lib/examples/{ag-ui → components}/weather/index.d.ts +1 -1
  141. package/lib/examples/{ag-ui → components}/weather/index.js +1 -1
  142. package/lib/examples/example-selector.d.ts +17 -4
  143. package/lib/examples/example-selector.js +107 -41
  144. package/lib/examples/index.d.ts +9 -6
  145. package/lib/examples/index.js +9 -6
  146. package/lib/examples/main.js +217 -27
  147. package/lib/examples/utils/a2ui.d.ts +18 -0
  148. package/lib/examples/utils/a2ui.js +69 -0
  149. package/lib/examples/utils/a2uiMarkdownProvider.d.ts +7 -0
  150. package/lib/examples/utils/a2uiMarkdownProvider.js +9 -0
  151. package/lib/examples/utils/agentId.d.ts +18 -0
  152. package/lib/examples/utils/agentId.js +54 -0
  153. package/lib/examples/utils/agents/earthquake-detector.json +11 -11
  154. package/lib/examples/utils/agents/sales-forecaster.json +11 -11
  155. package/lib/examples/utils/agents/social-post-generator.json +11 -11
  156. package/lib/examples/utils/agents/stock-market.json +11 -11
  157. package/lib/examples/utils/examplesStore.js +82 -27
  158. package/lib/hooks/index.d.ts +8 -8
  159. package/lib/hooks/index.js +7 -7
  160. package/lib/hooks/useA2A.d.ts +2 -3
  161. package/lib/hooks/useAIAgentsWebSocket.d.ts +43 -4
  162. package/lib/hooks/useAIAgentsWebSocket.js +118 -12
  163. package/lib/hooks/useAcp.d.ts +1 -2
  164. package/lib/hooks/useAgUi.d.ts +1 -1
  165. package/lib/hooks/{useAgents.d.ts → useAgentRuntimes.d.ts} +39 -2
  166. package/lib/hooks/{useAgents.js → useAgentRuntimes.js} +125 -15
  167. package/lib/hooks/useAgentsCatalog.js +1 -1
  168. package/lib/hooks/useAgentsService.d.ts +2 -2
  169. package/lib/hooks/useAgentsService.js +7 -7
  170. package/lib/hooks/useCheckpoints.js +1 -1
  171. package/lib/hooks/useConfig.d.ts +4 -1
  172. package/lib/hooks/useConfig.js +10 -3
  173. package/lib/hooks/useContextSnapshot.d.ts +9 -4
  174. package/lib/hooks/useContextSnapshot.js +9 -37
  175. package/lib/hooks/useMonitoring.js +3 -0
  176. package/lib/hooks/useSandbox.d.ts +20 -8
  177. package/lib/hooks/useSandbox.js +105 -40
  178. package/lib/hooks/useSkills.d.ts +23 -5
  179. package/lib/hooks/useSkills.js +94 -39
  180. package/lib/hooks/useToolApprovals.d.ts +60 -36
  181. package/lib/hooks/useToolApprovals.js +318 -69
  182. package/lib/hooks/useVercelAI.d.ts +1 -1
  183. package/lib/index.d.ts +2 -1
  184. package/lib/index.js +1 -0
  185. package/lib/inference/index.d.ts +0 -1
  186. package/lib/middleware/index.d.ts +0 -1
  187. package/lib/protocols/AGUIAdapter.js +6 -0
  188. package/lib/protocols/VercelAIAdapter.d.ts +7 -0
  189. package/lib/protocols/VercelAIAdapter.js +59 -7
  190. package/lib/specs/agents/agents.d.ts +10 -0
  191. package/lib/specs/agents/agents.js +2139 -262
  192. package/lib/specs/agents/index.js +3 -1
  193. package/lib/specs/envvars.d.ts +1 -0
  194. package/lib/specs/envvars.js +38 -20
  195. package/lib/specs/evals.js +6 -6
  196. package/lib/specs/events.d.ts +3 -10
  197. package/lib/specs/events.js +127 -84
  198. package/lib/specs/frontendTools.js +2 -2
  199. package/lib/specs/guardrails.d.ts +0 -7
  200. package/lib/specs/guardrails.js +240 -159
  201. package/lib/specs/index.d.ts +1 -0
  202. package/lib/specs/index.js +1 -0
  203. package/lib/specs/mcpServers.js +35 -6
  204. package/lib/specs/memory.d.ts +0 -2
  205. package/lib/specs/memory.js +4 -17
  206. package/lib/specs/models.js +25 -5
  207. package/lib/specs/notifications.js +102 -18
  208. package/lib/specs/outputs.js +15 -9
  209. package/lib/specs/personas.d.ts +41 -0
  210. package/lib/specs/personas.js +168 -0
  211. package/lib/specs/skills.d.ts +2 -1
  212. package/lib/specs/skills.js +41 -23
  213. package/lib/specs/teams/index.js +3 -1
  214. package/lib/specs/teams/teams.js +468 -348
  215. package/lib/specs/tools.js +4 -4
  216. package/lib/specs/triggers.js +61 -11
  217. package/lib/stores/agentRuntimeStore.d.ts +204 -0
  218. package/lib/stores/agentRuntimeStore.js +636 -0
  219. package/lib/stores/index.d.ts +1 -1
  220. package/lib/stores/index.js +1 -1
  221. package/lib/tools/adapters/copilotkit/lexicalHooks.d.ts +1 -2
  222. package/lib/tools/adapters/copilotkit/lexicalHooks.js +1 -3
  223. package/lib/tools/adapters/copilotkit/notebookHooks.d.ts +1 -2
  224. package/lib/tools/adapters/copilotkit/notebookHooks.js +1 -3
  225. package/lib/tools/index.d.ts +0 -2
  226. package/lib/tools/index.js +0 -1
  227. package/lib/types/agentspecs.d.ts +50 -1
  228. package/lib/types/chat.d.ts +309 -8
  229. package/lib/types/context.d.ts +27 -0
  230. package/lib/types/cost.d.ts +2 -2
  231. package/lib/types/index.d.ts +2 -0
  232. package/lib/types/index.js +2 -0
  233. package/lib/types/mcp.d.ts +8 -0
  234. package/lib/types/models.d.ts +2 -2
  235. package/lib/types/personas.d.ts +25 -0
  236. package/lib/types/personas.js +5 -0
  237. package/lib/types/skills.d.ts +43 -1
  238. package/lib/types/stream.d.ts +110 -0
  239. package/lib/types/stream.js +36 -0
  240. package/lib/utils/utils.d.ts +9 -5
  241. package/lib/utils/utils.js +9 -5
  242. package/package.json +13 -9
  243. package/scripts/codegen/__pycache__/generate_agents.cpython-313.pyc +0 -0
  244. package/scripts/codegen/__pycache__/generate_events.cpython-313.pyc +0 -0
  245. package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
  246. package/scripts/codegen/generate_agents.py +102 -6
  247. package/scripts/codegen/generate_events.py +35 -13
  248. package/scripts/codegen/generate_personas.py +319 -0
  249. package/scripts/codegen/generate_skills.py +9 -9
  250. package/scripts/sync-jupyter.sh +26 -7
  251. package/lib/api/tool-approvals.d.ts +0 -62
  252. package/lib/api/tool-approvals.js +0 -145
  253. package/lib/examples/LexicalSidebarExample.js +0 -163
  254. package/lib/examples/NotebookSidebarExample.js +0 -119
  255. package/lib/examples/NotebookSimpleExample.d.ts +0 -6
  256. package/lib/examples/NotebookSimpleExample.js +0 -22
  257. package/lib/examples/ag-ui/index.d.ts +0 -10
  258. package/lib/examples/ag-ui/index.js +0 -16
  259. package/lib/hooks/useAgentsRegistry.d.ts +0 -10
  260. package/lib/hooks/useAgentsRegistry.js +0 -20
  261. package/lib/stores/agentsStore.d.ts +0 -123
  262. package/lib/stores/agentsStore.js +0 -270
  263. /package/lib/examples/{AgentspecExample.d.ts → AgentSpecsExample.d.ts} +0 -0
  264. /package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.d.ts +0 -0
  265. /package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.d.ts +0 -0
  266. /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.d.ts +0 -0
  267. /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.js +0 -0
@@ -18,15 +18,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
18
  import { useEffect, useState, useCallback, useRef } from 'react';
19
19
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
20
20
  import { Text, Button, Spinner, Heading, Label, Flash, ProgressBar, } from '@primer/react';
21
- import { BeakerIcon, CheckCircleIcon, XCircleIcon, PlayIcon, SignOutIcon, } from '@primer/octicons-react';
21
+ import { BeakerIcon, CheckCircleIcon, XCircleIcon, PlayIcon, } from '@primer/octicons-react';
22
22
  import { Box } from '@datalayer/primer-addons';
23
- import { ErrorView } from './components';
23
+ import { AuthRequiredView, ErrorView } from './components';
24
24
  import { ThemedProvider } from './utils/themedProvider';
25
+ import { uniqueAgentId } from './utils/agentId';
25
26
  import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel';
26
- import { SignInSimple } from '@datalayer/core/lib/views/iam';
27
- import { UserBadge } from '@datalayer/core/lib/views/profile';
28
27
  import { Chat } from '../chat';
29
- import { useAgents } from '../hooks/useAgents';
28
+ import { useAgentRuntimes } from '../hooks/useAgentRuntimes';
30
29
  const queryClient = new QueryClient();
31
30
  // ─── Constants ─────────────────────────────────────────────────────────────
32
31
  const AGENT_NAME = 'eval-demo-agent';
@@ -34,12 +33,14 @@ const AGENT_SPEC_ID = 'monitor-sales-kpis';
34
33
  // ─── Inner component (rendered after auth) ─────────────────────────────────
35
34
  const AgentEvalsInner = ({ onLogout }) => {
36
35
  const { token } = useSimpleAuthStore();
37
- const { runtime, status: runtimeStatus, isReady, error: hookError, } = useAgents({
36
+ const agentName = useRef(uniqueAgentId(AGENT_NAME)).current;
37
+ const { runtime, status: runtimeStatus, isReady, error: hookError, } = useAgentRuntimes({
38
38
  agentSpecId: AGENT_SPEC_ID,
39
39
  autoStart: true,
40
40
  agentConfig: {
41
- name: AGENT_NAME,
42
- protocol: 'ag-ui',
41
+ name: agentName,
42
+ model: 'bedrock:us.anthropic.claude-3-5-haiku-20241022-v1:0',
43
+ protocol: 'vercel-ai',
43
44
  description: 'Agent with evaluation and quality scoring',
44
45
  },
45
46
  });
@@ -130,7 +131,7 @@ const AgentEvalsInner = ({ onLogout }) => {
130
131
  borderBottom: '1px solid',
131
132
  borderColor: 'border.default',
132
133
  flexShrink: 0,
133
- }, children: [_jsx(BeakerIcon, { size: 16 }), _jsxs(Heading, { as: "h3", sx: { fontSize: 2, flex: 1 }, children: ["Evaluation \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: "Eval Agent", placeholder: "Chat with the agent, then run evaluations\u2026", description: latestScore != null
134
+ }, children: [_jsx(BeakerIcon, { size: 16 }), _jsxs(Heading, { as: "h3", sx: { fontSize: 2, flex: 1 }, children: ["Evaluation \u2014 ", podName] })] }), _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, title: "Eval Agent", placeholder: "Chat with the agent, then run evaluations\u2026", description: latestScore != null
134
135
  ? `Last score: ${(latestScore * 100).toFixed(0)}%`
135
136
  : 'No evaluations run yet', showHeader: true, autoFocus: true, height: "100%", runtimeId: podName, historyEndpoint: `${agentBaseUrl}/api/v1/history`, suggestions: [
136
137
  {
@@ -182,7 +183,7 @@ const syncTokenToIamStore = (token) => {
182
183
  };
183
184
  // ─── Main component with auth gate ─────────────────────────────────────────
184
185
  const AgentEvalsExample = () => {
185
- const { token, setAuth, clearAuth } = useSimpleAuthStore();
186
+ const { token, clearAuth } = useSimpleAuthStore();
186
187
  const hasSynced = useRef(false);
187
188
  useEffect(() => {
188
189
  if (token && !hasSynced.current) {
@@ -190,11 +191,6 @@ const AgentEvalsExample = () => {
190
191
  syncTokenToIamStore(token);
191
192
  }
192
193
  }, [token]);
193
- const handleSignIn = useCallback((newToken, handle) => {
194
- setAuth(newToken, handle);
195
- hasSynced.current = true;
196
- syncTokenToIamStore(newToken);
197
- }, [setAuth]);
198
194
  const handleLogout = useCallback(() => {
199
195
  clearAuth();
200
196
  hasSynced.current = false;
@@ -203,7 +199,7 @@ const AgentEvalsExample = () => {
203
199
  });
204
200
  }, [clearAuth]);
205
201
  if (!token) {
206
- return (_jsx(ThemedProvider, { children: _jsx(SignInSimple, { onSignIn: handleSignIn, onApiKeySignIn: apiKey => handleSignIn(apiKey, 'api-key-user'), title: "Agent Evaluation", description: "Sign in to evaluate agent quality and review scores.", leadingIcon: _jsx(BeakerIcon, { size: 24 }) }) }));
202
+ return (_jsx(ThemedProvider, { children: _jsx(AuthRequiredView, {}) }));
207
203
  }
208
204
  return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ThemedProvider, { children: _jsx(AgentEvalsInner, { onLogout: handleLogout }) }) }));
209
205
  };
@@ -18,41 +18,213 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
18
  import { useEffect, useState, useCallback, useRef } from 'react';
19
19
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
20
20
  import { Text, Button, Spinner, Heading, Label, Flash, ProgressBar, } from '@primer/react';
21
- import { ShieldCheckIcon, CheckIcon, XIcon, SignOutIcon, } from '@primer/octicons-react';
21
+ import { ShieldCheckIcon, CheckIcon, XIcon, DotFillIcon, } from '@primer/octicons-react';
22
22
  import { Box } from '@datalayer/primer-addons';
23
- import { ErrorView } from './components';
23
+ import { buildOtelWebSocketUrl } from '@datalayer/core/lib/otel';
24
+ import { useCoreStore } from '@datalayer/core/lib/state';
25
+ import { AuthRequiredView, ErrorView } from './components';
24
26
  import { ThemedProvider } from './utils/themedProvider';
27
+ import { uniqueAgentId } from './utils/agentId';
28
+ import { parseAgentStreamMessage } from '../types/stream';
29
+ import { getAgentSpecs } from '../specs/agents';
30
+ import { subscribeOtelWs } from '../context/otelWsPool';
31
+ import { toMetricValue } from '../hooks/useMonitoring';
32
+ import { useAIAgentsWebSocket } from '../hooks';
25
33
  const queryClient = new QueryClient();
26
34
  import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel';
27
- import { SignInSimple } from '@datalayer/core/lib/views/iam';
28
- import { UserBadge } from '@datalayer/core/lib/views/profile';
29
35
  import { Chat } from '../chat';
30
- import { useAgents } from '../hooks/useAgents';
31
36
  // ─── Constants ─────────────────────────────────────────────────────────────
32
37
  const AGENT_NAME = 'guardrails-demo-agent';
33
- const AGENT_SPEC_ID = 'monitor-sales-kpis';
34
- const COST_LIMIT_USD = 5.0;
38
+ const AGENT_SPEC_ID = 'demo-guardrails';
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;
42
+ const OTEL_SERVICE_NAME = 'agent-runtimes';
43
+ const COST_RUN_METRIC = 'agent_runtimes.capability.cost.run.usd';
44
+ const COST_CUMULATIVE_METRIC = 'agent_runtimes.capability.cost.cumulative.usd';
45
+ const toNumberOrNull = (value) => {
46
+ if (typeof value === 'number' && Number.isFinite(value)) {
47
+ return value;
48
+ }
49
+ if (typeof value === 'string' && value.trim().length > 0) {
50
+ const parsed = Number(value);
51
+ if (Number.isFinite(parsed)) {
52
+ return parsed;
53
+ }
54
+ }
55
+ return null;
56
+ };
57
+ const resolvePerRunBudgetFromSpec = (agentSpecId) => {
58
+ const spec = getAgentSpecs(agentSpecId);
59
+ if (!spec?.guardrails?.length) {
60
+ return null;
61
+ }
62
+ for (const guardrail of spec.guardrails) {
63
+ if (!guardrail || typeof guardrail !== 'object') {
64
+ continue;
65
+ }
66
+ const costBudget = guardrail.cost_budget;
67
+ if (!costBudget || typeof costBudget !== 'object') {
68
+ continue;
69
+ }
70
+ const perRunUsd = toNumberOrNull(costBudget.per_run_usd);
71
+ if (perRunUsd != null) {
72
+ return perRunUsd;
73
+ }
74
+ }
75
+ return null;
76
+ };
77
+ const DEFAULT_RUN_BUDGET_USD = resolvePerRunBudgetFromSpec(AGENT_SPEC_ID);
78
+ const toApprovalRequest = (payload) => ({
79
+ id: payload.id,
80
+ tool_name: payload.tool_name,
81
+ tool_args: payload.tool_args ?? {},
82
+ created_at: payload.created_at ?? new Date().toISOString(),
83
+ });
84
+ const normalizeBaseUrl = (rawBaseUrl) => {
85
+ if (rawBaseUrl.startsWith('http://') ||
86
+ rawBaseUrl.startsWith('https://') ||
87
+ rawBaseUrl.startsWith('ws://') ||
88
+ rawBaseUrl.startsWith('wss://')) {
89
+ return rawBaseUrl;
90
+ }
91
+ const protocol = typeof window !== 'undefined' && window.location.protocol === 'https:'
92
+ ? 'https:'
93
+ : 'http:';
94
+ const host = typeof window !== 'undefined' ? window.location.host : '';
95
+ return `${protocol}//${host}${rawBaseUrl}`;
96
+ };
97
+ const parseAttributes = (attrs) => {
98
+ if (attrs && typeof attrs === 'object' && !Array.isArray(attrs)) {
99
+ return attrs;
100
+ }
101
+ if (typeof attrs === 'string') {
102
+ try {
103
+ return JSON.parse(attrs);
104
+ }
105
+ catch {
106
+ return {};
107
+ }
108
+ }
109
+ return {};
110
+ };
111
+ const extractServiceName = (row) => {
112
+ const directCandidates = [row.service_name, row.service, row.serviceName];
113
+ for (const candidate of directCandidates) {
114
+ if (typeof candidate === 'string' && candidate.length > 0) {
115
+ return candidate;
116
+ }
117
+ }
118
+ const resourceAttributes = row.resource_attributes;
119
+ if (resourceAttributes && typeof resourceAttributes === 'object') {
120
+ const nested = resourceAttributes['service.name'];
121
+ if (typeof nested === 'string' && nested.length > 0) {
122
+ return nested;
123
+ }
124
+ }
125
+ return undefined;
126
+ };
127
+ const extractAgentId = (row) => {
128
+ const attrs = parseAttributes(row.attributes);
129
+ const aid = attrs['agent.id'];
130
+ return typeof aid === 'string' ? aid : undefined;
131
+ };
132
+ const rowTimestampMs = (row) => {
133
+ const nanoTs = row.timestamp_unix_nano ?? row.observed_timestamp_unix_nano;
134
+ if (typeof nanoTs === 'number' && nanoTs > 0) {
135
+ return nanoTs / 1_000_000;
136
+ }
137
+ if (typeof nanoTs === 'string' && nanoTs.length > 0) {
138
+ const parsed = Number(nanoTs);
139
+ if (Number.isFinite(parsed) && parsed > 0) {
140
+ return parsed / 1_000_000;
141
+ }
142
+ }
143
+ const isoTs = row.timestamp;
144
+ if (typeof isoTs === 'string' && isoTs.length > 0) {
145
+ const ms = new Date(isoTs).getTime();
146
+ if (Number.isFinite(ms) && ms > 0) {
147
+ return ms;
148
+ }
149
+ }
150
+ return 0;
151
+ };
152
+ const selectLatestOtelCost = (rows, agentId) => {
153
+ const filtered = rows.filter(row => {
154
+ const metricName = row.metric_name;
155
+ if (metricName !== COST_RUN_METRIC &&
156
+ metricName !== COST_CUMULATIVE_METRIC) {
157
+ return false;
158
+ }
159
+ if (extractServiceName(row) !== OTEL_SERVICE_NAME) {
160
+ return false;
161
+ }
162
+ return extractAgentId(row) === agentId;
163
+ });
164
+ if (filtered.length === 0) {
165
+ return null;
166
+ }
167
+ let latestTimestampMs = 0;
168
+ let runUsd = 0;
169
+ let cumulativeUsd = 0;
170
+ for (const row of filtered) {
171
+ const ts = rowTimestampMs(row);
172
+ if (!Number.isFinite(ts) || ts <= 0) {
173
+ continue;
174
+ }
175
+ if (ts > latestTimestampMs) {
176
+ latestTimestampMs = ts;
177
+ runUsd = 0;
178
+ cumulativeUsd = 0;
179
+ }
180
+ if (ts !== latestTimestampMs) {
181
+ continue;
182
+ }
183
+ const value = Math.max(0, toMetricValue(row));
184
+ if (row.metric_name === COST_RUN_METRIC) {
185
+ runUsd += value;
186
+ }
187
+ else if (row.metric_name === COST_CUMULATIVE_METRIC) {
188
+ cumulativeUsd = Math.max(cumulativeUsd, value);
189
+ }
190
+ }
191
+ if (latestTimestampMs <= 0) {
192
+ return null;
193
+ }
194
+ return {
195
+ timestampMs: latestTimestampMs,
196
+ runUsd,
197
+ cumulativeUsd,
198
+ };
199
+ };
35
200
  // ─── Inner component (rendered after auth) ─────────────────────────────────
36
201
  const AgentGuardrailsInner = ({ onLogout, }) => {
37
202
  const { token } = useSimpleAuthStore();
38
- const { runtime, status: runtimeStatus, isReady, error: hookError, } = useAgents({
39
- agentSpecId: AGENT_SPEC_ID,
40
- autoStart: true,
41
- agentConfig: {
42
- name: AGENT_NAME,
43
- protocol: 'ag-ui',
44
- description: 'Agent with cost budget and tool approval guardrails',
45
- },
46
- });
203
+ const { configuration } = useCoreStore();
204
+ const agentName = useRef(uniqueAgentId(AGENT_NAME)).current;
205
+ const [runtimeStatus, setRuntimeStatus] = useState('launching');
206
+ const [isReady, setIsReady] = useState(false);
207
+ const [hookError, setHookError] = useState(null);
208
+ const [agentId, setAgentId] = useState(agentName);
209
+ const [isReconnectedAgent, setIsReconnectedAgent] = useState(false);
47
210
  // Cost tracking
48
- const [costUsd, setCostUsd] = useState(0);
211
+ const [snapshotRunCostUsd, setSnapshotRunCostUsd] = useState(0);
212
+ const [runBudgetUsd, setRunBudgetUsd] = useState(DEFAULT_RUN_BUDGET_USD);
49
213
  const [totalTokens, setTotalTokens] = useState(0);
214
+ const [otelRunCostUsd, setOtelRunCostUsd] = useState(null);
215
+ const [otelCumulativeCostUsd, setOtelCumulativeCostUsd] = useState(null);
216
+ const [otelSampleTimestamp, setOtelSampleTimestamp] = useState(null);
50
217
  // Tool approval queue
51
218
  const [approvals, setApprovals] = useState([]);
52
219
  const [approvalLoading, setApprovalLoading] = useState(null);
53
- const agentBaseUrl = runtime?.agentBaseUrl || '';
54
- const agentId = runtime?.agentId || AGENT_NAME;
55
- const podName = runtime?.podName || '(launching…)';
220
+ const agentBaseUrl = DEFAULT_LOCAL_BASE_URL;
221
+ const otelBaseUrl = configuration?.otelRunUrl ||
222
+ configuration?.runUrl ||
223
+ OTEL_BASE_URL_ENV ||
224
+ DATALAYER_RUN_URL_ENV ||
225
+ 'https://prod1.datalayer.run';
226
+ const podName = agentId;
227
+ const chatAuthToken = token === null ? undefined : token;
56
228
  // Authenticated fetch helper (for sidecar endpoints)
57
229
  const authFetch = useCallback((url, opts = {}) => fetch(url, {
58
230
  ...opts,
@@ -62,46 +234,158 @@ const AgentGuardrailsInner = ({ onLogout, }) => {
62
234
  ...(opts.headers ?? {}),
63
235
  },
64
236
  }), [token]);
65
- // ── Poll cost + tool approvals ───────────────────────────────────────────
66
237
  useEffect(() => {
67
- if (!isReady || !agentBaseUrl)
68
- return;
69
- const poll = async () => {
238
+ let isCancelled = false;
239
+ const createLocalAgent = async () => {
240
+ setRuntimeStatus('launching');
241
+ setIsReady(false);
242
+ setHookError(null);
243
+ setIsReconnectedAgent(false);
70
244
  try {
71
- // Cost usage
72
- const costRes = await authFetch(`${agentBaseUrl}/api/v1/agents/${agentId}/cost`);
73
- if (costRes.ok) {
74
- const d = await costRes.json();
75
- setCostUsd(d.total_cost_usd ?? d.cost ?? 0);
76
- setTotalTokens(d.total_tokens ?? 0);
245
+ const response = await authFetch(`${agentBaseUrl}/api/v1/agents`, {
246
+ method: 'POST',
247
+ body: JSON.stringify({
248
+ name: agentName,
249
+ description: 'Agent with cost budget and tool approval guardrails',
250
+ agent_library: 'pydantic-ai',
251
+ transport: 'vercel-ai',
252
+ agent_spec_id: AGENT_SPEC_ID,
253
+ enable_skills: true,
254
+ tools: [],
255
+ }),
256
+ });
257
+ let resolvedAgentId = agentName;
258
+ let isAlreadyRunning = false;
259
+ if (response.ok) {
260
+ const data = await response.json();
261
+ resolvedAgentId = data?.id || agentName;
262
+ }
263
+ else {
264
+ const contentType = response.headers.get('content-type') || '';
265
+ let detail = '';
266
+ if (contentType.includes('application/json')) {
267
+ const data = await response.json().catch(() => null);
268
+ detail =
269
+ (typeof data?.detail === 'string' && data.detail) ||
270
+ (typeof data?.message === 'string' && data.message) ||
271
+ '';
272
+ }
273
+ else {
274
+ detail = await response.text();
275
+ }
276
+ if (response.status === 409 || /already exists/i.test(detail || '')) {
277
+ isAlreadyRunning = true;
278
+ }
279
+ else {
280
+ throw new Error(detail || `Failed to create local agent: ${response.status}`);
281
+ }
282
+ }
283
+ if (!isCancelled) {
284
+ setAgentId(resolvedAgentId);
285
+ setIsReconnectedAgent(isAlreadyRunning);
286
+ setIsReady(true);
287
+ setRuntimeStatus('ready');
77
288
  }
78
289
  }
79
- catch {
80
- /* endpoint may not be wired */
290
+ catch (error) {
291
+ if (!isCancelled) {
292
+ setHookError(error instanceof Error ? error.message : 'Agent failed to start');
293
+ setRuntimeStatus('error');
294
+ }
81
295
  }
82
- try {
83
- // Tool approvals
84
- const apprRes = await authFetch(`${agentBaseUrl}/api/v1/agents/${agentId}/tool-approvals?status=pending`);
85
- if (apprRes.ok) {
86
- const d = await apprRes.json();
87
- setApprovals(Array.isArray(d) ? d : (d.requests ?? []));
296
+ };
297
+ void createLocalAgent();
298
+ return () => {
299
+ isCancelled = true;
300
+ };
301
+ }, [agentBaseUrl, agentName, authFetch]);
302
+ const handleGuardrailsStreamMessage = useCallback((message) => {
303
+ try {
304
+ const stream = parseAgentStreamMessage(message?.raw ?? message);
305
+ if (!stream) {
306
+ return;
307
+ }
308
+ if (stream.type === 'agent.snapshot') {
309
+ const payload = stream.payload;
310
+ setApprovals((payload.approvals ?? []).map(toApprovalRequest));
311
+ const snapshotCost = payload.contextSnapshot?.costUsage ?? payload.costUsage;
312
+ if (snapshotCost) {
313
+ setSnapshotRunCostUsd(Number(snapshotCost.cumulativeCostUsd ??
314
+ snapshotCost.lastTurnCostUsd ??
315
+ 0));
316
+ setRunBudgetUsd(prev => snapshotCost.perRunBudgetUsd == null
317
+ ? (prev ?? DEFAULT_RUN_BUDGET_USD)
318
+ : Number(snapshotCost.perRunBudgetUsd));
319
+ setTotalTokens(Number(snapshotCost.totalTokensUsed ?? 0));
88
320
  }
321
+ return;
89
322
  }
90
- catch {
91
- /* ok */
323
+ if (stream.type === 'tool_approval_created') {
324
+ const approval = toApprovalRequest(stream.payload);
325
+ setApprovals(prev => {
326
+ const next = prev.filter(item => item.id !== approval.id);
327
+ next.unshift(approval);
328
+ return next;
329
+ });
330
+ return;
92
331
  }
93
- };
94
- poll();
95
- const interval = setInterval(poll, 5_000);
96
- return () => clearInterval(interval);
97
- }, [isReady, agentBaseUrl, agentId, authFetch]);
332
+ if (stream.type === 'tool_approval_approved' ||
333
+ stream.type === 'tool_approval_rejected') {
334
+ const approval = stream.payload;
335
+ setApprovals(prev => prev.filter(item => item.id !== approval.id));
336
+ }
337
+ }
338
+ catch {
339
+ // Ignore malformed stream payloads.
340
+ }
341
+ }, []);
342
+ const approvalSocket = useAIAgentsWebSocket({
343
+ enabled: isReady && Boolean(agentBaseUrl),
344
+ baseUrl: agentBaseUrl,
345
+ path: '/api/v1/tool-approvals/ws',
346
+ queryParams: { agent_id: agentId },
347
+ onMessage: handleGuardrailsStreamMessage,
348
+ reconnectDelayMs: attempt => Math.min(1000 * 2 ** Math.max(0, attempt - 1), 10000),
349
+ });
350
+ const wsState = approvalSocket.connectionState;
351
+ useEffect(() => {
352
+ setOtelRunCostUsd(null);
353
+ setOtelCumulativeCostUsd(null);
354
+ setOtelSampleTimestamp(null);
355
+ if (!isReady || !token) {
356
+ return;
357
+ }
358
+ let wsUrl;
359
+ try {
360
+ wsUrl = buildOtelWebSocketUrl({
361
+ baseUrl: normalizeBaseUrl(otelBaseUrl),
362
+ token,
363
+ });
364
+ }
365
+ catch {
366
+ return;
367
+ }
368
+ const unsubscribe = subscribeOtelWs(wsUrl, msg => {
369
+ if (msg.signal !== 'metrics' || !Array.isArray(msg.data)) {
370
+ return;
371
+ }
372
+ const sample = selectLatestOtelCost(msg.data, agentId);
373
+ if (!sample) {
374
+ return;
375
+ }
376
+ setOtelRunCostUsd(sample.runUsd);
377
+ setOtelCumulativeCostUsd(sample.cumulativeUsd);
378
+ setOtelSampleTimestamp(sample.timestampMs);
379
+ });
380
+ return unsubscribe;
381
+ }, [agentId, isReady, otelBaseUrl, token]);
98
382
  // ── Approve / Reject ─────────────────────────────────────────────────────
99
383
  const handleApprove = useCallback(async (requestId) => {
100
384
  if (!agentBaseUrl)
101
385
  return;
102
386
  setApprovalLoading(requestId);
103
387
  try {
104
- await authFetch(`${agentBaseUrl}/api/v1/agents/${agentId}/tool-approvals/${requestId}/approve`, { method: 'POST' });
388
+ await authFetch(`${agentBaseUrl}/api/v1/tool-approvals/${requestId}/approve`, { method: 'POST' });
105
389
  setApprovals(prev => prev.filter(a => a.id !== requestId));
106
390
  }
107
391
  catch {
@@ -110,13 +394,13 @@ const AgentGuardrailsInner = ({ onLogout, }) => {
110
394
  finally {
111
395
  setApprovalLoading(null);
112
396
  }
113
- }, [agentBaseUrl, agentId, authFetch]);
397
+ }, [agentBaseUrl, authFetch]);
114
398
  const handleReject = useCallback(async (requestId) => {
115
399
  if (!agentBaseUrl)
116
400
  return;
117
401
  setApprovalLoading(requestId);
118
402
  try {
119
- await authFetch(`${agentBaseUrl}/api/v1/agents/${agentId}/tool-approvals/${requestId}/reject`, {
403
+ await authFetch(`${agentBaseUrl}/api/v1/tool-approvals/${requestId}/reject`, {
120
404
  method: 'POST',
121
405
  body: JSON.stringify({ reason: 'User rejected' }),
122
406
  });
@@ -128,7 +412,7 @@ const AgentGuardrailsInner = ({ onLogout, }) => {
128
412
  finally {
129
413
  setApprovalLoading(null);
130
414
  }
131
- }, [agentBaseUrl, agentId, authFetch]);
415
+ }, [agentBaseUrl, authFetch]);
132
416
  // ── Loading / Error ──────────────────────────────────────────────────────
133
417
  if (!isReady && runtimeStatus !== 'error') {
134
418
  return (_jsxs(Box, { sx: {
@@ -138,14 +422,31 @@ const AgentGuardrailsInner = ({ onLogout, }) => {
138
422
  justifyContent: 'center',
139
423
  height: '100vh',
140
424
  gap: 3,
141
- }, children: [_jsx(Spinner, { size: "large" }), _jsx(Text, { sx: { color: 'fg.muted' }, children: runtimeStatus === 'launching'
142
- ? 'Launching runtime for guardrails agent…'
143
- : 'Creating guardrails demo agent…' })] }));
425
+ }, children: [_jsx(Spinner, { size: "large" }), _jsx(Text, { sx: { color: 'fg.muted' }, children: "Launching guardrails demo agent..." })] }));
144
426
  }
145
427
  if (runtimeStatus === 'error' || hookError) {
146
428
  return _jsx(ErrorView, { error: hookError, onLogout: onLogout });
147
429
  }
148
- const costPercent = Math.min((costUsd / COST_LIMIT_USD) * 100, 100);
430
+ const runCostUsd = Math.max(snapshotRunCostUsd, otelRunCostUsd ?? 0);
431
+ const cumulativeCostUsd = otelCumulativeCostUsd;
432
+ const isOverRunBudget = runBudgetUsd != null && runBudgetUsd > 0 && runCostUsd > runBudgetUsd;
433
+ const runBudgetDisplayUsd = runBudgetUsd != null ? runBudgetUsd.toFixed(2) : '0.00';
434
+ const overBudgetBanner = isOverRunBudget
435
+ ? {
436
+ variant: 'danger',
437
+ message: `Run budget exceeded: $${runCostUsd.toFixed(4)} / $${runBudgetDisplayUsd}. Start a new run or adjust the budget before sending more messages.`,
438
+ }
439
+ : undefined;
440
+ const budgetForProgress = runBudgetUsd && runBudgetUsd > 0 ? runBudgetUsd : 1;
441
+ const usagePercentRaw = (runCostUsd / budgetForProgress) * 100;
442
+ const costPercent = Math.min(usagePercentRaw, 100);
443
+ const usageSafePercent = Math.min(costPercent, 50);
444
+ const usageWatchPercent = Math.min(Math.max(costPercent - 50, 0), 30);
445
+ const usageDangerPercent = Math.min(Math.max(costPercent - 80, 0), 20);
446
+ const overBudgetPercent = Math.max(usagePercentRaw - 100, 0);
447
+ const overBudgetAmountUsd = runBudgetUsd != null && runBudgetUsd > 0
448
+ ? Math.max(runCostUsd - runBudgetUsd, 0)
449
+ : 0;
149
450
  const costColor = costPercent > 80
150
451
  ? 'danger.fg'
151
452
  : costPercent > 50
@@ -164,14 +465,24 @@ const AgentGuardrailsInner = ({ onLogout, }) => {
164
465
  borderBottom: '1px solid',
165
466
  borderColor: 'border.default',
166
467
  flexShrink: 0,
167
- }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [_jsx(ShieldCheckIcon, { size: 16 }), _jsxs(Heading, { as: "h3", sx: { fontSize: 2 }, children: ["Guardrails Demo \u2014 ", podName] })] }), _jsxs(Box, { sx: { flex: 1, maxWidth: 300 }, children: [_jsxs(Box, { sx: {
468
+ }, children: [isReconnectedAgent && (_jsx(Label, { variant: "secondary", size: "small", children: "Reconnected" })), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [_jsx(ShieldCheckIcon, { size: 16 }), _jsxs(Heading, { as: "h3", sx: { fontSize: 2 }, children: ["Guardrails Demo \u2014 ", podName] })] }), _jsx(Label, { variant: wsState === 'connected' ? 'success' : 'secondary', children: wsState }), _jsxs(Box, { sx: { flex: 1, maxWidth: 300 }, children: [_jsxs(Box, { sx: {
168
469
  display: 'flex',
169
470
  justifyContent: 'space-between',
170
471
  fontSize: 0,
171
472
  mb: 1,
172
- }, children: [_jsxs(Text, { sx: { color: costColor, fontWeight: 'semibold' }, children: ["$", costUsd.toFixed(4)] }), _jsxs(Text, { sx: { color: 'fg.muted' }, children: ["/ $", COST_LIMIT_USD.toFixed(2), " limit"] })] }), _jsx(ProgressBar, { progress: costPercent, sx: { height: 6 } })] }), _jsxs(Label, { variant: "secondary", children: [totalTokens.toLocaleString(), " tokens"] }), token && _jsx(UserBadge, { token: token, variant: "small" }), _jsx(Button, { size: "small", variant: "invisible", onClick: onLogout, leadingVisual: SignOutIcon, sx: { color: 'fg.muted' }, children: "Sign out" })] }), approvals.map(req => (_jsx(Flash, { variant: "warning", sx: { mx: 3, mt: 2 }, children: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsxs(Text, { sx: { flex: 1, fontSize: 1 }, children: [_jsx("strong", { children: req.tool_name }), " requests approval", req.arguments
173
- ? ` ${JSON.stringify(req.arguments).slice(0, 120)}`
174
- : ''] }), _jsx(Button, { size: "small", variant: "primary", leadingVisual: CheckIcon, onClick: () => handleApprove(req.id), disabled: approvalLoading === req.id, children: "Approve" }), _jsx(Button, { size: "small", variant: "danger", leadingVisual: XIcon, onClick: () => handleReject(req.id), disabled: approvalLoading === req.id, children: "Reject" })] }) }, req.id))), _jsx(Box, { sx: { flex: 1, minHeight: 0 }, children: _jsx(Chat, { protocol: "ag-ui", baseUrl: agentBaseUrl, agentId: agentId, title: "Guardrails Agent", placeholder: "Ask something that triggers tools\u2026", description: "Agent with $5 cost limit and tool approval gates", showHeader: false, showTokenUsage: true, autoFocus: true, height: "100%", runtimeId: podName, historyEndpoint: `${agentBaseUrl}/api/v1/history`, suggestions: [
473
+ }, children: [_jsxs(Text, { sx: { color: costColor, fontWeight: 'semibold' }, children: ["$", runCostUsd.toFixed(4)] }), _jsx(Text, { sx: { color: 'fg.muted' }, children: runBudgetUsd != null
474
+ ? ` / $${runBudgetUsd.toFixed(2)} run budget`
475
+ : ' / no run budget' })] }), _jsxs(ProgressBar, { "aria-label": "Run budget usage", "aria-valuenow": Math.max(0, costPercent), sx: { height: 6 }, children: [_jsx(ProgressBar.Item, { progress: usageSafePercent, style: { backgroundColor: 'var(--bgColor-success-emphasis)' }, "aria-label": `Healthy usage ${usageSafePercent.toFixed(1)}%` }), _jsx(ProgressBar.Item, { progress: usageWatchPercent, style: { backgroundColor: 'var(--bgColor-accent-emphasis)' }, "aria-label": `Watch usage ${usageWatchPercent.toFixed(1)}%` }), _jsx(ProgressBar.Item, { progress: usageDangerPercent, style: { backgroundColor: 'var(--bgColor-danger-emphasis)' }, "aria-label": `Critical usage ${usageDangerPercent.toFixed(1)}%` })] }), _jsxs(Box, { sx: {
476
+ display: 'flex',
477
+ alignItems: 'center',
478
+ gap: 2,
479
+ flexWrap: 'wrap',
480
+ mt: 1,
481
+ }, role: "presentation", children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [_jsx(DotFillIcon, { size: 12, fill: "var(--bgColor-success-emphasis)" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "0-50%" })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [_jsx(DotFillIcon, { size: 12, fill: "var(--bgColor-accent-emphasis)" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "50-80%" })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [_jsx(DotFillIcon, { size: 12, fill: "var(--bgColor-danger-emphasis)" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "80-100%" })] }), overBudgetPercent > 0 && (_jsxs(Label, { variant: "danger", size: "small", children: ["+", overBudgetPercent.toFixed(1), "% over"] }))] })] }), _jsxs(Label, { variant: otelSampleTimestamp == null ? 'secondary' : 'success', children: ["OTEL ", otelSampleTimestamp == null ? 'waiting' : 'live'] }), cumulativeCostUsd != null && (_jsxs(Label, { variant: "secondary", children: ["Total $", cumulativeCostUsd.toFixed(4)] })), _jsxs(Label, { variant: "secondary", children: [totalTokens.toLocaleString(), " tokens"] })] }), isOverRunBudget && (_jsx(Flash, { variant: "danger", sx: { mx: 3, mt: 2 }, children: _jsxs(Text, { sx: { fontSize: 1 }, children: [_jsx("strong", { children: "Run budget exceeded." }), " Current run cost is $", runCostUsd.toFixed(4), " against a budget of $", runBudgetDisplayUsd, overBudgetAmountUsd > 0
482
+ ? ` (over by $${overBudgetAmountUsd.toFixed(4)}).`
483
+ : '.', ' ', "Start a new run or increase the run budget before continuing."] }) })), approvals.map(req => (_jsx(Flash, { variant: "warning", sx: { mx: 3, mt: 2 }, children: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsxs(Text, { sx: { flex: 1, fontSize: 1 }, children: [_jsx("strong", { children: req.tool_name }), " requests approval", req.tool_args
484
+ ? ` — ${JSON.stringify(req.tool_args).slice(0, 120)}`
485
+ : ''] }), _jsx(Button, { size: "small", variant: "primary", leadingVisual: CheckIcon, onClick: () => handleApprove(req.id), disabled: approvalLoading === req.id, children: "Approve" }), _jsx(Button, { size: "small", variant: "danger", leadingVisual: XIcon, onClick: () => handleReject(req.id), disabled: approvalLoading === req.id, children: "Reject" })] }) }, req.id))), _jsx(Box, { sx: { flex: 1, minHeight: 0 }, children: _jsx(Chat, { protocol: "vercel-ai", baseUrl: agentBaseUrl, agentId: agentId, authToken: chatAuthToken, title: "Guardrails Agent", placeholder: "Ask something that triggers tools\u2026", description: "Cost guardrail with OTEL-backed gauge and manual tool approval gates", showHeader: false, showTokenUsage: true, errorBanner: overBudgetBanner, disableInputPrompt: isOverRunBudget, autoFocus: true, height: "100%", runtimeId: agentId, historyEndpoint: `${agentBaseUrl}/api/v1/history`, suggestions: [
175
486
  { title: 'Update CRM', message: 'Update the CRM records for Q3' },
176
487
  { title: 'Report', message: 'Generate the weekly KPI report' },
177
488
  ], submitOnSuggestionClick: true }) })] }));
@@ -184,7 +495,7 @@ const syncTokenToIamStore = (token) => {
184
495
  };
185
496
  // ─── Main component with auth gate ─────────────────────────────────────────
186
497
  const AgentGuardrailsExample = () => {
187
- const { token, setAuth, clearAuth } = useSimpleAuthStore();
498
+ const { token, clearAuth } = useSimpleAuthStore();
188
499
  const hasSynced = useRef(false);
189
500
  useEffect(() => {
190
501
  if (token && !hasSynced.current) {
@@ -192,11 +503,6 @@ const AgentGuardrailsExample = () => {
192
503
  syncTokenToIamStore(token);
193
504
  }
194
505
  }, [token]);
195
- const handleSignIn = useCallback((newToken, handle) => {
196
- setAuth(newToken, handle);
197
- hasSynced.current = true;
198
- syncTokenToIamStore(newToken);
199
- }, [setAuth]);
200
506
  const handleLogout = useCallback(() => {
201
507
  clearAuth();
202
508
  hasSynced.current = false;
@@ -205,7 +511,7 @@ const AgentGuardrailsExample = () => {
205
511
  });
206
512
  }, [clearAuth]);
207
513
  if (!token) {
208
- return (_jsx(ThemedProvider, { children: _jsx(SignInSimple, { onSignIn: handleSignIn, onApiKeySignIn: apiKey => handleSignIn(apiKey, 'api-key-user'), title: "Guardrails Agent", description: "Sign in to use agents with cost and tool guardrails.", leadingIcon: _jsx(ShieldCheckIcon, { size: 24 }) }) }));
514
+ return (_jsx(ThemedProvider, { children: _jsx(AuthRequiredView, {}) }));
209
515
  }
210
516
  return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ThemedProvider, { children: _jsx(AgentGuardrailsInner, { onLogout: handleLogout }) }) }));
211
517
  };
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const AgentHooksExample: React.FC;
3
+ export default AgentHooksExample;