@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
@@ -7,60 +7,17 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
7
  import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
8
8
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
9
9
  import { Box } from '@datalayer/primer-addons';
10
- import { ErrorView } from './components';
11
- import { Button, Heading, SegmentedControl, Spinner, Text, } from '@primer/react';
12
- import { SignOutIcon, ToolsIcon } from '@primer/octicons-react';
13
- import { useCoreStore } from '@datalayer/core';
14
- import { DEFAULT_SERVICE_URLS } from '@datalayer/core/lib/api/constants';
10
+ import { AuthRequiredView, ErrorView } from './components';
11
+ import { Spinner, Text } from '@primer/react';
15
12
  import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel';
16
- import { SignInSimple } from '@datalayer/core/lib/views/iam';
17
- import { UserBadge } from '@datalayer/core/lib/views/profile';
18
13
  import { ThemedProvider } from './utils/themedProvider';
14
+ import { uniqueAgentId } from './utils/agentId';
19
15
  import { Chat } from '../chat';
20
- import { ToolCallDisplay, ToolApprovalBanner, ToolApprovalDialog, } from '../chat/tools';
21
- const normalizeToolName = (value) => value.replace(/[-_]/g, '').toLowerCase();
22
- const AI_AGENTS_API_PREFIX = '/api/ai-agents/v1';
23
- const stableStringify = (value) => {
24
- if (value === null || typeof value !== 'object') {
25
- return JSON.stringify(value);
26
- }
27
- if (Array.isArray(value)) {
28
- return `[${value.map(item => stableStringify(item)).join(',')}]`;
29
- }
30
- const entries = Object.entries(value)
31
- .sort(([a], [b]) => a.localeCompare(b))
32
- .map(([key, itemValue]) => `${JSON.stringify(key)}:${stableStringify(itemValue)}`);
33
- return `{${entries.join(',')}}`;
34
- };
35
- const toWsUrl = (baseUrl, path, token) => {
36
- try {
37
- const url = new URL(baseUrl);
38
- url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
39
- url.pathname = path;
40
- if (token) {
41
- url.searchParams.set('token', token);
42
- }
43
- else {
44
- url.search = '';
45
- }
46
- return url.toString();
47
- }
48
- catch {
49
- return null;
50
- }
51
- };
52
- const normalizeAiAgentsBaseUrl = (rawBaseUrl) => {
53
- const trimmed = rawBaseUrl.replace(/\/$/, '');
54
- if (trimmed.endsWith(AI_AGENTS_API_PREFIX)) {
55
- return trimmed.slice(0, -AI_AGENTS_API_PREFIX.length);
56
- }
57
- return trimmed;
58
- };
16
+ import { useAgentRuntimePendingCount } from '../stores/agentRuntimeStore';
59
17
  const queryClient = new QueryClient();
60
18
  const AGENT_NAME_PREFIX = 'tool-approval-demo-agent';
61
19
  const DEFAULT_AGENT_SPEC_ID = 'demo-full';
62
20
  const DEFAULT_LOCAL_BASE_URL = import.meta.env.VITE_BASE_URL || 'http://localhost:8765';
63
- const FALLBACK_AI_AGENTS_BASE_URL = import.meta.env.VITE_AI_AGENTS_URL || DEFAULT_SERVICE_URLS.AI_AGENTS;
64
21
  const getSelectedAgentSpecIdFromUi = () => {
65
22
  const params = new URLSearchParams(window.location.search);
66
23
  const directKeys = [
@@ -91,36 +48,23 @@ const buildAgentNameForSpec = (specId) => {
91
48
  .replace(/[^a-z0-9]+/g, '-')
92
49
  .replace(/^-+|-+$/g, '')
93
50
  .slice(0, 48);
94
- return slug ? `${AGENT_NAME_PREFIX}-${slug}` : AGENT_NAME_PREFIX;
51
+ const base = slug ? `${AGENT_NAME_PREFIX}-${slug}` : AGENT_NAME_PREFIX;
52
+ return uniqueAgentId(base);
95
53
  };
96
- const approvalSignature = (toolName, args) => `${normalizeToolName(toolName)}::${stableStringify(args ?? {})}`;
97
54
  const AgentToolApprovalsInner = ({ onLogout, }) => {
98
55
  const { token } = useSimpleAuthStore();
99
56
  const [selectedSpecId] = useState(() => getSelectedAgentSpecIdFromUi());
100
57
  const agentName = useMemo(() => buildAgentNameForSpec(selectedSpecId), [selectedSpecId]);
101
- const [mode, setMode] = useState('local');
102
58
  const [runtimeStatus, setRuntimeStatus] = useState('launching');
103
59
  const [isReady, setIsReady] = useState(false);
104
60
  const [hookError, setHookError] = useState(null);
105
61
  const [agentId, setAgentId] = useState(agentName);
106
62
  const [isReconnectedAgent, setIsReconnectedAgent] = useState(false);
107
- const [approvals, setApprovals] = useState([]);
108
- const [localApprovals, setLocalApprovals] = useState([]);
109
- const [activeApproval, setActiveApproval] = useState(null);
110
- const [approvalLoading, setApprovalLoading] = useState(null);
111
- const [approvalError, setApprovalError] = useState(null);
112
- const [toolApprovalState, setToolApprovalState] = useState({});
113
- const [wsState, setWsState] = useState('closed');
114
- const createdApprovalSignatures = useRef(new Set());
115
- const toolRespondersRef = useRef(new Map());
116
- const respondedToolCallsRef = useRef(new Set());
117
- const resolveLocalRef = useRef(async () => null);
118
- const authFetchRef = useRef((url, opts) => fetch(url, opts));
119
63
  const chatAuthToken = token === null ? undefined : token;
120
- const configuredAiAgentsBaseUrl = useCoreStore((s) => s.configuration?.aiagentsRunUrl);
121
64
  const agentBaseUrl = DEFAULT_LOCAL_BASE_URL;
122
- const aiAgentsBaseUrl = normalizeAiAgentsBaseUrl(configuredAiAgentsBaseUrl || FALLBACK_AI_AGENTS_BASE_URL);
123
65
  const podName = 'localhost';
66
+ const pendingApprovalCount = useAgentRuntimePendingCount();
67
+ const createAttemptedRef = useRef(false);
124
68
  const authFetch = useCallback((url, opts = {}) => fetch(url, {
125
69
  ...opts,
126
70
  headers: {
@@ -129,30 +73,11 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
129
73
  ...(opts.headers ?? {}),
130
74
  },
131
75
  }), [token]);
132
- const emitServerToolDecision = useCallback((toolName, toolArgs, approved, approvalId, message) => {
133
- const signature = approvalSignature(toolName, toolArgs);
134
- const responder = toolRespondersRef.current.get(signature);
135
- if (!responder?.respond) {
136
- return false;
137
- }
138
- if (respondedToolCallsRef.current.has(responder.toolCallId)) {
139
- return false;
140
- }
141
- setToolApprovalState(prev => ({
142
- ...prev,
143
- [responder.toolCallId]: approved ? 'approved' : 'denied',
144
- }));
145
- respondedToolCallsRef.current.add(responder.toolCallId);
146
- responder.respond({
147
- type: 'tool-approval-decision',
148
- approved,
149
- approvalId,
150
- toolName: responder.toolName || toolName,
151
- ...(message ? { message } : {}),
152
- });
153
- return true;
154
- }, []);
155
76
  useEffect(() => {
77
+ if (createAttemptedRef.current) {
78
+ return;
79
+ }
80
+ createAttemptedRef.current = true;
156
81
  let isCancelled = false;
157
82
  const createLocalAgent = async () => {
158
83
  setRuntimeStatus('launching');
@@ -218,412 +143,6 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
218
143
  isCancelled = true;
219
144
  };
220
145
  }, [agentBaseUrl, authFetch, agentName, selectedSpecId]);
221
- const pollApprovals = useCallback(async () => {
222
- if (!isReady) {
223
- return;
224
- }
225
- const fetchPendingApprovals = async (baseUrl, apiPrefix) => {
226
- const res = await authFetch(`${baseUrl}${apiPrefix}`);
227
- if (!res.ok) {
228
- return [];
229
- }
230
- const data = await res.json();
231
- const allApprovals = Array.isArray(data)
232
- ? data
233
- : (data.approvals ?? data.requests ?? []);
234
- return allApprovals
235
- .filter((approval) => approval.status === 'pending' &&
236
- (approval.agent_id === agentId || !approval.agent_id))
237
- .map((approval) => ({
238
- ...approval,
239
- backendBaseUrl: baseUrl,
240
- apiPrefix,
241
- }));
242
- };
243
- const source = mode === 'server'
244
- ? {
245
- baseUrl: aiAgentsBaseUrl,
246
- apiPrefix: `${AI_AGENTS_API_PREFIX}/tool-approvals`,
247
- }
248
- : { baseUrl: agentBaseUrl, apiPrefix: '/api/v1/tool-approvals' };
249
- try {
250
- const localPending = await fetchPendingApprovals(agentBaseUrl, '/api/v1/tool-approvals');
251
- setLocalApprovals(localPending);
252
- const pendingForAgent = await fetchPendingApprovals(source.baseUrl, source.apiPrefix);
253
- setApprovals(pendingForAgent);
254
- }
255
- catch (error) {
256
- if (mode === 'server') {
257
- setApprovalError(error instanceof Error
258
- ? error.message
259
- : 'Failed to fetch server approvals');
260
- }
261
- }
262
- }, [isReady, mode, aiAgentsBaseUrl, agentBaseUrl, agentId, authFetch]);
263
- const resolveLocalApprovalForTool = useCallback(async (toolName, toolArgs) => {
264
- const signature = approvalSignature(toolName, toolArgs);
265
- const matchFromState = localApprovals.find(approval => approvalSignature(approval.tool_name, approval.tool_args ?? {}) ===
266
- signature);
267
- if (matchFromState) {
268
- return matchFromState;
269
- }
270
- const res = await authFetch(`${agentBaseUrl}/api/v1/tool-approvals`);
271
- if (!res.ok) {
272
- return null;
273
- }
274
- const data = await res.json();
275
- const allApprovals = Array.isArray(data)
276
- ? data
277
- : (data.approvals ?? data.requests ?? []);
278
- const pendingLocal = allApprovals
279
- .filter((approval) => approval.status === 'pending' &&
280
- (approval.agent_id === agentId || !approval.agent_id))
281
- .map((approval) => ({
282
- ...approval,
283
- backendBaseUrl: agentBaseUrl,
284
- apiPrefix: '/api/v1/tool-approvals',
285
- }));
286
- setLocalApprovals(pendingLocal);
287
- return (pendingLocal.find(approval => approvalSignature(approval.tool_name, approval.tool_args ?? {}) ===
288
- signature) || null);
289
- }, [localApprovals, authFetch, agentBaseUrl, agentId]);
290
- useEffect(() => {
291
- void pollApprovals();
292
- const interval = setInterval(pollApprovals, 5000);
293
- return () => clearInterval(interval);
294
- }, [pollApprovals]);
295
- useEffect(() => {
296
- if (!isReady || mode !== 'server') {
297
- setWsState('closed');
298
- return;
299
- }
300
- const wsUrl = toWsUrl(aiAgentsBaseUrl, `${AI_AGENTS_API_PREFIX}/ws`, chatAuthToken);
301
- if (!wsUrl) {
302
- setWsState('closed');
303
- return;
304
- }
305
- let closedByCleanup = false;
306
- setWsState('connecting');
307
- const ws = new WebSocket(wsUrl);
308
- ws.onopen = () => {
309
- setWsState('connected');
310
- void pollApprovals();
311
- };
312
- ws.onmessage = event => {
313
- try {
314
- const payload = JSON.parse(String(event.data));
315
- const wsEvent = payload?.event;
316
- const approval = payload?.data;
317
- if (!wsEvent || !approval) {
318
- return;
319
- }
320
- if (wsEvent === 'tool_approval_created') {
321
- if (approval.status !== 'pending' ||
322
- (approval.agent_id && approval.agent_id !== agentId)) {
323
- return;
324
- }
325
- setApprovals(prev => {
326
- const next = prev.filter(item => item.id !== approval.id);
327
- next.unshift({
328
- ...approval,
329
- backendBaseUrl: aiAgentsBaseUrl,
330
- apiPrefix: `${AI_AGENTS_API_PREFIX}/tool-approvals`,
331
- });
332
- return next;
333
- });
334
- return;
335
- }
336
- if (wsEvent === 'tool_approval_approved' ||
337
- wsEvent === 'tool_approval_rejected') {
338
- // Remove from the server approval queue.
339
- setApprovals(prev => prev.filter(item => item.id !== approval.id));
340
- // Bridge the decision to the local agent-runtimes approval.
341
- const action = wsEvent === 'tool_approval_approved' ? 'approve' : 'reject';
342
- void (async () => {
343
- try {
344
- const approved = wsEvent === 'tool_approval_approved';
345
- emitServerToolDecision(approval.tool_name, approval.tool_args ?? {}, approved, approval.id, approval.note);
346
- const localMatch = await resolveLocalRef.current(approval.tool_name, approval.tool_args ?? {});
347
- if (localMatch) {
348
- const localBaseUrl = `${agentBaseUrl}/api/v1/tool-approvals/${localMatch.id}/${action}`;
349
- await authFetchRef.current(localBaseUrl, {
350
- method: 'POST',
351
- body: JSON.stringify(approval.note ? { note: approval.note } : {}),
352
- });
353
- }
354
- }
355
- catch {
356
- // Local bridge errors are non-fatal; poll will reconcile.
357
- }
358
- })();
359
- return;
360
- }
361
- }
362
- catch {
363
- // Ignore malformed WS payloads.
364
- }
365
- };
366
- ws.onclose = () => {
367
- if (!closedByCleanup) {
368
- setWsState('closed');
369
- }
370
- };
371
- ws.onerror = () => {
372
- setWsState('closed');
373
- };
374
- return () => {
375
- closedByCleanup = true;
376
- ws.close();
377
- setWsState('closed');
378
- };
379
- }, [
380
- isReady,
381
- mode,
382
- aiAgentsBaseUrl,
383
- agentBaseUrl,
384
- chatAuthToken,
385
- agentId,
386
- pollApprovals,
387
- emitServerToolDecision,
388
- ]);
389
- // Keep refs in sync so the WS handler always has the latest functions.
390
- useEffect(() => {
391
- resolveLocalRef.current = resolveLocalApprovalForTool;
392
- }, [resolveLocalApprovalForTool]);
393
- useEffect(() => {
394
- authFetchRef.current = authFetch;
395
- }, [authFetch]);
396
- const approve = useCallback(async (requestId, note) => {
397
- setApprovalLoading(requestId);
398
- setApprovalError(null);
399
- try {
400
- const approval = approvals.find(item => item.id === requestId);
401
- const baseUrl = approval?.backendBaseUrl ||
402
- (mode === 'server' ? aiAgentsBaseUrl : agentBaseUrl);
403
- const apiPrefix = approval?.apiPrefix ||
404
- (mode === 'server'
405
- ? `${AI_AGENTS_API_PREFIX}/tool-approvals`
406
- : '/api/v1/tool-approvals');
407
- const response = await authFetch(`${baseUrl}${apiPrefix}/${requestId}/approve`, {
408
- method: 'POST',
409
- body: JSON.stringify(note ? { note } : {}),
410
- });
411
- if (!response.ok) {
412
- const errorText = await response.text().catch(() => '');
413
- throw new Error(errorText ||
414
- `Failed to approve request (${response.status} ${response.statusText})`);
415
- }
416
- // In server mode, UI/continuation updates are websocket-driven only.
417
- // The click only sends approve to the server; local chat reacts when
418
- // tool_approval_approved is received.
419
- if (mode !== 'server') {
420
- setApprovals(prev => prev.filter(a => a.id !== requestId));
421
- void pollApprovals();
422
- }
423
- return true;
424
- }
425
- catch (error) {
426
- const message = error instanceof Error
427
- ? error.message
428
- : 'Failed to approve tool request';
429
- setApprovalError(message);
430
- return false;
431
- }
432
- finally {
433
- setApprovalLoading(null);
434
- }
435
- }, [
436
- approvals,
437
- mode,
438
- aiAgentsBaseUrl,
439
- agentBaseUrl,
440
- authFetch,
441
- pollApprovals,
442
- ]);
443
- const reject = useCallback(async (requestId, note) => {
444
- setApprovalLoading(requestId);
445
- setApprovalError(null);
446
- try {
447
- const approval = approvals.find(item => item.id === requestId);
448
- const baseUrl = approval?.backendBaseUrl ||
449
- (mode === 'server' ? aiAgentsBaseUrl : agentBaseUrl);
450
- const apiPrefix = approval?.apiPrefix ||
451
- (mode === 'server'
452
- ? `${AI_AGENTS_API_PREFIX}/tool-approvals`
453
- : '/api/v1/tool-approvals');
454
- const response = await authFetch(`${baseUrl}${apiPrefix}/${requestId}/reject`, {
455
- method: 'POST',
456
- body: JSON.stringify(note ? { note } : {}),
457
- });
458
- if (!response.ok) {
459
- const errorText = await response.text().catch(() => '');
460
- throw new Error(errorText ||
461
- `Failed to reject request (${response.status} ${response.statusText})`);
462
- }
463
- // In server mode, UI/continuation updates are websocket-driven only.
464
- // The click only sends reject to the server; local chat reacts when
465
- // tool_approval_rejected is received.
466
- if (mode !== 'server') {
467
- setApprovals(prev => prev.filter(a => a.id !== requestId));
468
- void pollApprovals();
469
- }
470
- return true;
471
- }
472
- catch (error) {
473
- const message = error instanceof Error
474
- ? error.message
475
- : 'Failed to reject tool request';
476
- setApprovalError(message);
477
- return false;
478
- }
479
- finally {
480
- setApprovalLoading(null);
481
- }
482
- }, [
483
- approvals,
484
- mode,
485
- aiAgentsBaseUrl,
486
- agentBaseUrl,
487
- authFetch,
488
- pollApprovals,
489
- ]);
490
- const ensureServerApproval = useCallback(async (toolName, args) => {
491
- if (mode !== 'server' || !aiAgentsBaseUrl || !isReady) {
492
- return;
493
- }
494
- const signature = approvalSignature(toolName, args);
495
- if (createdApprovalSignatures.current.has(signature)) {
496
- return;
497
- }
498
- const alreadyTracked = approvals.some(approval => approvalSignature(approval.tool_name, approval.tool_args ?? {}) ===
499
- signature);
500
- if (alreadyTracked) {
501
- createdApprovalSignatures.current.add(signature);
502
- return;
503
- }
504
- createdApprovalSignatures.current.add(signature);
505
- try {
506
- const response = await authFetch(`${aiAgentsBaseUrl}${AI_AGENTS_API_PREFIX}/tool-approvals`, {
507
- method: 'POST',
508
- body: JSON.stringify({
509
- agent_id: agentId,
510
- pod_name: podName,
511
- tool_name: toolName,
512
- tool_args: args,
513
- }),
514
- });
515
- if (!response.ok) {
516
- const text = await response.text().catch(() => '');
517
- throw new Error(text ||
518
- `Failed creating server approval (${response.status} ${response.statusText})`);
519
- }
520
- const created = (await response.json());
521
- setApprovals(prev => {
522
- const next = prev.filter(item => item.id !== created.id);
523
- next.unshift({
524
- ...created,
525
- backendBaseUrl: aiAgentsBaseUrl,
526
- apiPrefix: `${AI_AGENTS_API_PREFIX}/tool-approvals`,
527
- });
528
- return next;
529
- });
530
- }
531
- catch (error) {
532
- createdApprovalSignatures.current.delete(signature);
533
- setApprovalError(error instanceof Error
534
- ? error.message
535
- : 'Failed to create server approval request');
536
- }
537
- }, [mode, aiAgentsBaseUrl, isReady, approvals, authFetch, agentId, podName]);
538
- const pendingApprovals = useMemo(() => approvals.map(req => ({
539
- id: req.id,
540
- toolName: req.tool_name,
541
- toolDescription: req.note,
542
- args: req.tool_args ?? {},
543
- agentId,
544
- requestedAt: req.created_at ?? new Date().toISOString(),
545
- })), [approvals, agentId]);
546
- const findMatchingApproval = useCallback((toolName, args) => {
547
- const normalizedToolName = normalizeToolName(toolName);
548
- const argsSig = stableStringify(args ?? {});
549
- return (approvals.find(approval => {
550
- if (normalizeToolName(approval.tool_name) !== normalizedToolName) {
551
- return false;
552
- }
553
- return stableStringify(approval.tool_args ?? {}) === argsSig;
554
- }) || null);
555
- }, [approvals]);
556
- const handleToolLevelApprove = useCallback(async (toolCallId, requestId, toolName, respond) => {
557
- const ok = await approve(requestId, 'Approved from tool message card');
558
- if (ok) {
559
- if (mode !== 'server') {
560
- setToolApprovalState(prev => ({ ...prev, [toolCallId]: 'approved' }));
561
- respond?.({
562
- type: 'tool-approval-decision',
563
- approved: true,
564
- approvalId: requestId,
565
- toolName,
566
- });
567
- }
568
- }
569
- }, [approve, mode]);
570
- const handleToolLevelDeny = useCallback(async (toolCallId, requestId, toolName, respond) => {
571
- const ok = await reject(requestId, 'Rejected from tool message card');
572
- if (ok) {
573
- if (mode !== 'server') {
574
- setToolApprovalState(prev => ({ ...prev, [toolCallId]: 'denied' }));
575
- respond?.({
576
- type: 'tool-approval-decision',
577
- approved: false,
578
- approvalId: requestId,
579
- toolName,
580
- });
581
- }
582
- }
583
- }, [reject, mode]);
584
- const renderToolResult = useCallback(({ toolCallId, toolName, args, result, status, error, respond }) => {
585
- const signature = approvalSignature(toolName, args);
586
- if (respond && status === 'inProgress') {
587
- toolRespondersRef.current.set(signature, {
588
- toolCallId,
589
- toolName,
590
- respond,
591
- });
592
- }
593
- else if (status === 'complete' || status === 'error') {
594
- toolRespondersRef.current.delete(signature);
595
- }
596
- const matchedApproval = findMatchingApproval(toolName, args);
597
- const resultObject = result && typeof result === 'object'
598
- ? result
599
- : undefined;
600
- const pendingByResult = status === 'inProgress' && resultObject?.pending_approval === true;
601
- const requiresServerApproval = mode === 'server' &&
602
- normalizeToolName(toolName) ===
603
- normalizeToolName('runtime_sensitive_echo');
604
- if (requiresServerApproval && !matchedApproval) {
605
- void ensureServerApproval(toolName, args);
606
- }
607
- const toolDecision = toolApprovalState[toolCallId];
608
- const loadingThisApproval = !!matchedApproval && approvalLoading === matchedApproval.id;
609
- const approvalState = toolDecision ||
610
- (pendingByResult || requiresServerApproval || !!matchedApproval
611
- ? 'pending'
612
- : undefined);
613
- return (_jsx(ToolCallDisplay, { toolCallId: toolCallId, toolName: toolName, args: args, result: result, status: status, error: error, approvalRequired: !!approvalState, approvalState: approvalState, approvalLoading: loadingThisApproval, onApprove: matchedApproval
614
- ? () => void handleToolLevelApprove(toolCallId, matchedApproval.id, toolName, respond)
615
- : undefined, onDeny: matchedApproval
616
- ? () => void handleToolLevelDeny(toolCallId, matchedApproval.id, toolName, respond)
617
- : undefined }));
618
- }, [
619
- mode,
620
- findMatchingApproval,
621
- ensureServerApproval,
622
- toolApprovalState,
623
- approvalLoading,
624
- handleToolLevelApprove,
625
- handleToolLevelDeny,
626
- ]);
627
146
  if (!isReady && runtimeStatus !== 'error') {
628
147
  return (_jsxs(Box, { sx: {
629
148
  display: 'flex',
@@ -632,32 +151,11 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
632
151
  justifyContent: 'center',
633
152
  height: '100vh',
634
153
  gap: 3,
635
- }, children: [_jsx(Spinner, { size: "large" }), _jsx(Text, { sx: { color: 'fg.muted' }, children: "Launching tool approval demo..." })] }));
154
+ }, children: [_jsx(Spinner, { size: "large" }), _jsx(Text, { sx: { color: 'fg.muted' }, children: "Launching tool approvals demo..." })] }));
636
155
  }
637
156
  if (runtimeStatus === 'error' || hookError) {
638
157
  return _jsx(ErrorView, { error: hookError, onLogout: onLogout });
639
158
  }
640
- const serverPanel = mode === 'server' ? (_jsxs(Box, { sx: {
641
- width: 320,
642
- minWidth: 280,
643
- borderLeft: '1px solid',
644
- borderColor: 'border.default',
645
- display: 'flex',
646
- flexDirection: 'column',
647
- minHeight: 0,
648
- bg: 'canvas.subtle',
649
- }, children: [_jsxs(Box, { sx: {
650
- p: 2,
651
- borderBottom: '1px solid',
652
- borderColor: 'border.default',
653
- }, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1, mb: 1 }, children: "Server Approval Queue" }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["WebSocket: ", wsState, " \u2022 Pending: ", approvals.length] })] }), _jsx(Box, { sx: { p: 2, overflow: 'auto', flex: 1 }, children: approvals.length === 0 ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "No pending approvals." })) : (approvals.map(approval => (_jsxs(Box, { sx: {
654
- border: '1px solid',
655
- borderColor: 'border.default',
656
- borderRadius: 2,
657
- p: 2,
658
- mb: 2,
659
- bg: 'canvas.default',
660
- }, children: [_jsx(Text, { sx: { fontWeight: 600, fontSize: 1 }, children: approval.tool_name }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', mb: 2 }, children: approval.id }), _jsxs(Box, { sx: { display: 'flex', gap: 1 }, children: [_jsx(Button, { size: "small", variant: "primary", onClick: () => void approve(approval.id), children: "Approve" }), _jsx(Button, { size: "small", variant: "danger", onClick: () => void reject(approval.id, 'Rejected from queue'), children: "Reject" })] })] }, approval.id)))) })] })) : null;
661
159
  return (_jsxs(Box, { sx: {
662
160
  height: 'calc(100vh - 60px)',
663
161
  display: 'flex',
@@ -667,41 +165,20 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
667
165
  py: 1,
668
166
  borderBottom: '1px solid',
669
167
  borderColor: 'border.default',
670
- }, children: _jsx(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: "Agent already running - reconnected." }) })), _jsx(ToolApprovalBanner, { pendingApprovals: pendingApprovals, onReview: approval => {
671
- const req = approvals.find(a => a.id === approval.id) || null;
672
- setActiveApproval(req);
673
- }, onApproveAll: async () => {
674
- for (const approval of approvals) {
675
- await approve(approval.id);
676
- }
677
- } }), _jsx(ToolApprovalDialog, { isOpen: !!activeApproval, toolName: activeApproval?.tool_name ?? '', toolDescription: activeApproval?.note, args: activeApproval?.tool_args ?? {}, onApprove: async () => {
678
- if (activeApproval) {
679
- const ok = await approve(activeApproval.id);
680
- if (ok) {
681
- setActiveApproval(null);
682
- }
683
- }
684
- }, onDeny: async () => {
685
- if (activeApproval) {
686
- const ok = await reject(activeApproval.id, 'Rejected from tool approval dialog');
687
- if (ok) {
688
- setActiveApproval(null);
689
- }
690
- }
691
- }, onClose: () => setActiveApproval(null) }), approvalError && (_jsx(Box, { sx: { px: 3, py: 1 }, children: _jsx(Text, { sx: { color: 'danger.fg', fontSize: 0 }, children: approvalError }) })), approvalLoading && (_jsx(Box, { sx: { px: 3, py: 1 }, children: _jsx(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: "Processing approval request..." }) })), _jsxs(Box, { sx: { flex: 1, minHeight: 0, display: 'flex' }, children: [_jsx(Box, { sx: { flex: 1, minWidth: 0 }, children: _jsx(Chat, { protocol: "vercel-ai", baseUrl: agentBaseUrl, agentId: agentId, authToken: chatAuthToken, title: `Tool Approval Agent - ${podName}`, placeholder: "Ask for actions that require approval...", showHeader: true, showNewChatButton: true, showClearButton: false, showTokenUsage: true, autoFocus: true, height: "100%", runtimeId: agentId, historyEndpoint: `${agentBaseUrl}/api/v1/history`, headerActions: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsxs(SegmentedControl, { "aria-label": "Approval mode", size: "small", onChange: index => setMode(index === 0 ? 'local' : 'server'), children: [_jsx(SegmentedControl.Button, { selected: mode === 'local', children: "Local" }), _jsx(SegmentedControl.Button, { selected: mode === 'server', children: "Server" })] }), _jsxs(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: ["Pending: ", pendingApprovals.length] }), token && _jsx(UserBadge, { token: token, variant: "small" }), _jsx(Button, { size: "small", variant: "invisible", onClick: onLogout, leadingVisual: SignOutIcon, sx: { color: 'fg.muted' }, children: "Sign out" })] }), suggestions: [
692
- {
693
- title: 'List your tools',
694
- message: 'list your tools',
695
- },
696
- {
697
- title: 'Run tool with approval',
698
- message: "Call the runtime_sensitive_echo tool with text 'hello' and reason 'audit', then reply with the tool result.",
699
- },
700
- {
701
- title: 'Run tool without approval',
702
- message: "Call the runtime_echo tool with text 'hello world', then reply with the tool result.",
703
- },
704
- ], renderToolResult: renderToolResult, submitOnSuggestionClick: true }) }), serverPanel] })] }));
168
+ }, children: _jsx(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: "Agent already running - reconnected." }) })), _jsx(Box, { sx: { flex: 1, minHeight: 0, display: 'flex' }, children: _jsx(Box, { sx: { flex: 1, minWidth: 0 }, children: _jsx(Chat, { protocol: "vercel-ai", baseUrl: agentBaseUrl, agentId: agentId, authToken: chatAuthToken, title: `Tool Approval Agent - ${podName}`, placeholder: "Ask for actions that require approval...", showHeader: true, showNewChatButton: true, showClearButton: false, showTokenUsage: true, autoFocus: true, height: "100%", runtimeId: agentId, historyEndpoint: `${agentBaseUrl}/api/v1/history`, headerActions: _jsx(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: _jsxs(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: ["Pending: ", pendingApprovalCount] }) }), suggestions: [
169
+ {
170
+ title: 'List your tools',
171
+ message: 'list your tools',
172
+ },
173
+ {
174
+ title: 'Run tool with approval',
175
+ message: "Call the runtime_sensitive_echo tool with text 'hello' and reason 'audit', then reply with the tool result.",
176
+ },
177
+ {
178
+ title: 'Run tool without approval',
179
+ message: "Call the runtime_echo tool with text 'hello world', then reply with the tool result.",
180
+ },
181
+ ], submitOnSuggestionClick: true }) }) })] }));
705
182
  };
706
183
  const syncTokenToIamStore = (token) => {
707
184
  import('@datalayer/core/lib/state').then(({ iamStore }) => {
@@ -709,7 +186,7 @@ const syncTokenToIamStore = (token) => {
709
186
  });
710
187
  };
711
188
  const AgentToolApprovalsExample = () => {
712
- const { token, setAuth, clearAuth } = useSimpleAuthStore();
189
+ const { token, clearAuth } = useSimpleAuthStore();
713
190
  const hasSynced = useRef(false);
714
191
  useEffect(() => {
715
192
  if (token && !hasSynced.current) {
@@ -717,11 +194,6 @@ const AgentToolApprovalsExample = () => {
717
194
  syncTokenToIamStore(token);
718
195
  }
719
196
  }, [token]);
720
- const handleSignIn = useCallback((newToken, handle) => {
721
- setAuth(newToken, handle);
722
- hasSynced.current = true;
723
- syncTokenToIamStore(newToken);
724
- }, [setAuth]);
725
197
  const handleLogout = useCallback(() => {
726
198
  clearAuth();
727
199
  hasSynced.current = false;
@@ -730,7 +202,7 @@ const AgentToolApprovalsExample = () => {
730
202
  });
731
203
  }, [clearAuth]);
732
204
  if (!token) {
733
- return (_jsx(ThemedProvider, { children: _jsx(SignInSimple, { onSignIn: handleSignIn, onApiKeySignIn: apiKey => handleSignIn(apiKey, 'api-key-user'), title: "Tool Approval Agent", description: "Sign in to test local and server-backed tool approvals.", leadingIcon: _jsx(ToolsIcon, { size: 24 }) }) }));
205
+ return (_jsx(ThemedProvider, { children: _jsx(AuthRequiredView, {}) }));
734
206
  }
735
207
  return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ThemedProvider, { children: _jsx(AgentToolApprovalsInner, { onLogout: handleLogout }) }) }));
736
208
  };