@datalayer/agent-runtimes 1.0.8 → 1.0.10

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 (49) hide show
  1. package/lib/chat/Chat.js +24 -12
  2. package/lib/chat/base/ChatBase.js +39 -1
  3. package/lib/client/AgentsMixin.d.ts +4 -4
  4. package/lib/client/AgentsMixin.js +7 -7
  5. package/lib/components/ToolApprovalCard.js +13 -3
  6. package/lib/config/AgentConfiguration.d.ts +2 -2
  7. package/lib/config/index.d.ts +1 -1
  8. package/lib/examples/AgentCheckpointsExample.js +12 -12
  9. package/lib/examples/AgentEvalsExample.js +3 -3
  10. package/lib/examples/AgentGuardrailsExample.js +5 -5
  11. package/lib/examples/AgentHooksExample.js +3 -3
  12. package/lib/examples/AgentInferenceProviderExample.js +5 -5
  13. package/lib/examples/AgentMCPExample.js +2 -2
  14. package/lib/examples/AgentMemoryExample.js +2 -2
  15. package/lib/examples/AgentMonitoringExample.js +2 -2
  16. package/lib/examples/AgentNotificationsExample.js +2 -2
  17. package/lib/examples/AgentOtelExample.js +5 -5
  18. package/lib/examples/AgentOutputsExample.js +2 -2
  19. package/lib/examples/AgentParametersExample.js +4 -4
  20. package/lib/examples/AgentSandboxExample.js +2 -2
  21. package/lib/examples/AgentSkillsExample.js +2 -2
  22. package/lib/examples/AgentSubagentsExample.js +2 -2
  23. package/lib/examples/AgentToolApprovalsExample.js +33 -7
  24. package/lib/examples/AgentTriggersExample.js +4 -4
  25. package/lib/examples/ChatExample.js +3 -3
  26. package/lib/hooks/useAgentRuntimes.js +2 -2
  27. package/lib/hooks/useAgentsCatalog.d.ts +3 -3
  28. package/lib/hooks/useAgentsCatalog.js +4 -4
  29. package/lib/hooks/useCheckpoints.js +2 -2
  30. package/lib/hooks/useToolApprovals.d.ts +8 -0
  31. package/lib/hooks/useToolApprovals.js +20 -1
  32. package/lib/identity/identityStore.js +4 -4
  33. package/lib/index.d.ts +1 -1
  34. package/lib/specs/agents/agents.d.ts +51 -50
  35. package/lib/specs/agents/agents.js +154 -141
  36. package/lib/specs/agents/index.d.ts +5 -5
  37. package/lib/specs/agents/index.js +9 -9
  38. package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.js +0 -10
  39. package/lib/types/agents.d.ts +3 -3
  40. package/lib/types/agentspecs.d.ts +5 -3
  41. package/lib/types/teams.d.ts +2 -2
  42. package/package.json +7 -7
  43. package/scripts/codegen/generate_agents.py +75 -57
  44. package/scripts/codegen/generate_teams.py +4 -4
  45. package/scripts/codegen/__pycache__/generate_agents.cpython-313.pyc +0 -0
  46. package/scripts/codegen/__pycache__/generate_benchmarks.cpython-313.pyc +0 -0
  47. package/scripts/codegen/__pycache__/generate_evals.cpython-313.pyc +0 -0
  48. package/scripts/codegen/__pycache__/generate_events.cpython-313.pyc +0 -0
  49. package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
package/lib/chat/Chat.js CHANGED
@@ -18,7 +18,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
18
  *
19
19
  * @module chat/Chat
20
20
  */
21
- import { useEffect, useMemo, useState, useRef } from 'react';
21
+ import { useEffect, useMemo, useState, useRef, useCallback } from 'react';
22
22
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
23
23
  import { Text, Button, Spinner } from '@primer/react';
24
24
  import { AlertIcon, SyncIcon } from '@primer/octicons-react';
@@ -145,9 +145,7 @@ export function Chat({ protocol: transport, extensions: _extensions, baseUrl = '
145
145
  const [showDetails, setShowDetails] = useState(false);
146
146
  const [messageCount, setMessageCount] = useState(0);
147
147
  const [focusTrigger, setFocusTrigger] = useState(0);
148
- const renderCountRef = useRef(0);
149
- renderCountRef.current += 1;
150
- console.log(`[AgentRuntimes][Chat] render count: ${renderCountRef.current}`);
148
+ const lastMessageCountRef = useRef(null);
151
149
  // Get connected identities to pass to backend for skill execution
152
150
  const connectedIdentities = useConnectedIdentities();
153
151
  // Map identities to the format expected by ChatBase
@@ -272,6 +270,26 @@ export function Chat({ protocol: transport, extensions: _extensions, baseUrl = '
272
270
  const handleNewChat = () => {
273
271
  onDisconnect?.();
274
272
  };
273
+ const handleInformationClick = useCallback(() => {
274
+ setShowDetails(true);
275
+ }, []);
276
+ const handleBackFromDetails = useCallback(() => {
277
+ setShowDetails(false);
278
+ }, []);
279
+ const handleMessagesChange = useCallback((messages) => {
280
+ const nextCount = messages.length;
281
+ if (lastMessageCountRef.current === nextCount) {
282
+ return;
283
+ }
284
+ lastMessageCountRef.current = nextCount;
285
+ setMessageCount(nextCount);
286
+ }, []);
287
+ const headerButtons = useMemo(() => ({
288
+ showNewChat: showNewChatButton,
289
+ showClear: showClearButton,
290
+ onNewChat: handleNewChat,
291
+ }), [showNewChatButton, showClearButton]);
292
+ const avatarConfig = useMemo(() => ({ showAvatars: true }), []);
275
293
  // Render error state
276
294
  if (error) {
277
295
  return (_jsx(QueryClientProvider, { client: queryClient, children: _jsxs(Box, { className: className, sx: {
@@ -306,7 +324,7 @@ export function Chat({ protocol: transport, extensions: _extensions, baseUrl = '
306
324
  display: showDetails ? 'flex' : 'none',
307
325
  flexDirection: 'column',
308
326
  height: '100%',
309
- }, children: _jsx(AgentDetails, { name: title || 'AI Agent', icon: brandIcon, protocol: transport, url: protocolConfig?.endpoint || baseUrl, messageCount: messageCount, agentId: agentId, apiBase: baseUrl, identityProviders: identityProviders, onIdentityConnect: onIdentityConnect, onIdentityDisconnect: onIdentityDisconnect, onBack: () => setShowDetails(false), mcpStatusData: mcpStatusData, codemodeStatusData: codemodeStatusData }) }), _jsxs(Box, { sx: {
327
+ }, children: _jsx(AgentDetails, { name: title || 'AI Agent', icon: brandIcon, protocol: transport, url: protocolConfig?.endpoint || baseUrl, messageCount: messageCount, agentId: agentId, apiBase: baseUrl, identityProviders: identityProviders, onIdentityConnect: onIdentityConnect, onIdentityDisconnect: onIdentityDisconnect, onBack: handleBackFromDetails, mcpStatusData: mcpStatusData, codemodeStatusData: codemodeStatusData }) }), _jsxs(Box, { sx: {
310
328
  display: showDetails ? 'none' : 'flex',
311
329
  flexDirection: 'column',
312
330
  height: '100%',
@@ -331,12 +349,6 @@ export function Chat({ protocol: transport, extensions: _extensions, baseUrl = '
331
349
  ? 'attention.fg'
332
350
  : 'danger.fg',
333
351
  flex: 1,
334
- }, children: errorBanner.message })] })), _jsx(ChatBase, { title: title, subtitle: subtitle, brandIcon: brandIcon, showHeader: showHeader, protocol: protocolConfig, placeholder: placeholder, description: description, suggestions: suggestions, submitOnSuggestionClick: submitOnSuggestionClick, autoFocus: autoFocus, runtimeId: runtimeId, historyEndpoint: historyEndpoint, pendingPrompt: pendingPrompt, showInformation: showInformation, onInformationClick: () => setShowDetails(true), headerContent: headerContent, headerActions: headerActions, showModelSelector: showModelSelector, showToolsMenu: showToolsMenu, showInput: showInput, disableInputPrompt: disableInputPrompt, showSkillsMenu: showSkillsMenu, showTokenUsage: showTokenUsage, codemodeEnabled: codemodeEnabled, onToggleCodemode: onToggleCodemode, initialModel: initialModel, availableModels: availableModels, mcpServers: mcpServers, initialSkills: initialSkills, connectedIdentities: identitiesForChat, onNewChat: handleNewChat, onMessagesChange: messages => setMessageCount(messages.length), headerButtons: {
335
- showNewChat: showNewChatButton,
336
- showClear: showClearButton,
337
- onNewChat: handleNewChat,
338
- }, avatarConfig: {
339
- showAvatars: true,
340
- }, backgroundColor: "canvas.default", focusTrigger: focusTrigger, chatViewMode: chatViewMode, onChatViewModeChange: onChatViewModeChange, frontendTools: frontendTools, onToolCallStart: onToolCallStart, onToolCallComplete: onToolCallComplete, renderToolResult: renderToolResult, hideMessagesAfterToolUI: hideMessagesAfterToolUI, contextSnapshot: contextSnapshot, mcpStatusData: mcpStatusData, sandboxStatusData: sandboxStatusData, showToolApprovalBanner: showToolApprovalBanner, pendingApprovals: pendingApprovals, onApproveApproval: onApproveApproval, onRejectApproval: onRejectApproval })] })] }) }));
352
+ }, children: errorBanner.message })] })), _jsx(ChatBase, { title: title, subtitle: subtitle, brandIcon: brandIcon, showHeader: showHeader, protocol: protocolConfig, placeholder: placeholder, description: description, suggestions: suggestions, submitOnSuggestionClick: submitOnSuggestionClick, autoFocus: autoFocus, runtimeId: runtimeId, historyEndpoint: historyEndpoint, pendingPrompt: pendingPrompt, showInformation: showInformation, onInformationClick: handleInformationClick, headerContent: headerContent, headerActions: headerActions, showModelSelector: showModelSelector, showToolsMenu: showToolsMenu, showInput: showInput, disableInputPrompt: disableInputPrompt, showSkillsMenu: showSkillsMenu, showTokenUsage: showTokenUsage, codemodeEnabled: codemodeEnabled, onToggleCodemode: onToggleCodemode, initialModel: initialModel, availableModels: availableModels, mcpServers: mcpServers, initialSkills: initialSkills, connectedIdentities: identitiesForChat, onNewChat: handleNewChat, onMessagesChange: handleMessagesChange, headerButtons: headerButtons, avatarConfig: avatarConfig, backgroundColor: "canvas.default", focusTrigger: focusTrigger, chatViewMode: chatViewMode, onChatViewModeChange: onChatViewModeChange, frontendTools: frontendTools, onToolCallStart: onToolCallStart, onToolCallComplete: onToolCallComplete, renderToolResult: renderToolResult, hideMessagesAfterToolUI: hideMessagesAfterToolUI, contextSnapshot: contextSnapshot, mcpStatusData: mcpStatusData, sandboxStatusData: sandboxStatusData, showToolApprovalBanner: showToolApprovalBanner, pendingApprovals: pendingApprovals, onApproveApproval: onApproveApproval, onRejectApproval: onRejectApproval })] })] }) }));
341
353
  }
342
354
  export default Chat;
@@ -604,6 +604,42 @@ showToolApprovalBanner = true, pendingApprovals: pendingApprovalsProp, onApprove
604
604
  requestAiAgentsApprovalHistory,
605
605
  sendAiAgentsApprovalDecision,
606
606
  ]);
607
+ const reconcileResolvedApprovalInStore = useCallback((approval) => {
608
+ const state = agentRuntimeStore.getState();
609
+ const removalIds = new Set([approval.id]);
610
+ const hasResolvedToolName = Boolean(approval.tool_name);
611
+ const resolvedSignature = hasResolvedToolName
612
+ ? approvalSignature(approval.tool_name, approval.tool_args ?? {})
613
+ : null;
614
+ for (const existing of state.approvals) {
615
+ if (existing.status !== 'pending') {
616
+ continue;
617
+ }
618
+ if (!isApprovalForAgent(existing, activeAgentId)) {
619
+ continue;
620
+ }
621
+ if (existing.id === approval.id) {
622
+ removalIds.add(existing.id);
623
+ continue;
624
+ }
625
+ if (approval.tool_call_id &&
626
+ existing.tool_call_id &&
627
+ existing.tool_call_id === approval.tool_call_id) {
628
+ removalIds.add(existing.id);
629
+ continue;
630
+ }
631
+ if (!resolvedSignature || !existing.tool_name) {
632
+ continue;
633
+ }
634
+ const existingSignature = approvalSignature(existing.tool_name, existing.tool_args ?? {});
635
+ if (existingSignature === resolvedSignature) {
636
+ removalIds.add(existing.id);
637
+ }
638
+ }
639
+ for (const id of removalIds) {
640
+ state.removeApproval(id);
641
+ }
642
+ }, [activeAgentId]);
607
643
  // Optional ai-agents bridge for server-mode visibility.
608
644
  // This keeps approval synchronization in ChatBase so examples do not need
609
645
  // their own approval websocket plumbing.
@@ -702,7 +738,7 @@ showToolApprovalBanner = true, pendingApprovals: pendingApprovalsProp, onApprove
702
738
  state.upsertApproval(scopedApproval);
703
739
  }
704
740
  else {
705
- state.removeApproval(scopedApproval.id);
741
+ reconcileResolvedApprovalInStore(scopedApproval);
706
742
  }
707
743
  }
708
744
  }
@@ -730,6 +766,7 @@ showToolApprovalBanner = true, pendingApprovals: pendingApprovalsProp, onApprove
730
766
  aiAgentsAuthToken,
731
767
  activeAgentId,
732
768
  isSuppressedPending,
769
+ reconcileResolvedApprovalInStore,
733
770
  ]);
734
771
  // The outer ChatBase wrapper always resolves a string Protocol to a full
735
772
  // ProtocolConfig (or undefined). Narrow the type for internal use.
@@ -964,6 +1001,7 @@ showToolApprovalBanner = true, pendingApprovals: pendingApprovalsProp, onApprove
964
1001
  }
965
1002
  return;
966
1003
  }
1004
+ reconcileResolvedApprovalInStore(payload);
967
1005
  applyServerApprovalDecision(payload, msg.type === 'tool_approval_approved', payload.note ?? undefined);
968
1006
  },
969
1007
  });
@@ -11,7 +11,7 @@
11
11
  * @module client/AgentsMixin
12
12
  */
13
13
  import type { Constructor } from '@datalayer/core/lib/client/utils/mixins';
14
- import type { AgentEvent, CreateAgentEventRequest, GetAgentEventResponse, ListAgentEventsParams, ListAgentEventsResponse, UpdateAgentEventRequest, RunningAgent, AgentUsageSummary, ConversationCheckpoint, AgentNotification, NotificationFilters, OutputArtifact, EvalReport, RunEvalsRequest, ContextUsage, CostUsage, AgentSpec } from '../types';
14
+ import type { AgentEvent, CreateAgentEventRequest, GetAgentEventResponse, ListAgentEventsParams, ListAgentEventsResponse, UpdateAgentEventRequest, RunningAgent, AgentUsageSummary, ConversationCheckpoint, AgentNotification, NotificationFilters, OutputArtifact, EvalReport, RunEvalsRequest, ContextUsage, CostUsage, Agentspec } from '../types';
15
15
  import type { CreateAgentRuntimeRequest, CreateRuntimeApiResponse } from '../types/agents-lifecycle';
16
16
  /** Agents mixin providing durable agent management. */
17
17
  export declare function AgentsMixin<TBase extends Constructor>(Base: TBase): {
@@ -153,19 +153,19 @@ export declare function AgentsMixin<TBase extends Constructor>(Base: TBase): {
153
153
  * @param agentSpecId - Agent spec identifier.
154
154
  * @returns The agent spec, or undefined if not found.
155
155
  */
156
- getAgentSpec(agentSpecId: string): AgentSpec | undefined;
156
+ getAgentspec(agentSpecId: string): Agentspec | undefined;
157
157
  /**
158
158
  * List all available agent specifications.
159
159
  * @param prefix - If provided, only return specs whose ID starts with this prefix.
160
160
  * @returns Array of agent specifications.
161
161
  */
162
- listAgentSpecs(prefix?: string): AgentSpec[];
162
+ listAgentspecs(prefix?: string): Agentspec[];
163
163
  /**
164
164
  * Get required environment variables for an agent spec.
165
165
  * @param spec - The agent specification.
166
166
  * @returns Deduplicated array of required environment variable names.
167
167
  */
168
- getAgentSpecRequiredEnvVars(spec: AgentSpec): string[];
168
+ getAgentspecRequiredEnvVars(spec: Agentspec): string[];
169
169
  /**
170
170
  * Assign an agent runtime to a project.
171
171
  * @param projectUid - Project UID.
@@ -8,7 +8,7 @@ import * as events from '../api/events';
8
8
  import * as output from '../api/output';
9
9
  import * as evals from '../api/evals';
10
10
  import * as context from '../api/context';
11
- import * as agentSpecs from '../specs/agents';
11
+ import * as agentspecs from '../specs/agents';
12
12
  import { requestDatalayerAPI } from '@datalayer/core/lib/api/DatalayerApi';
13
13
  /** Agents mixin providing durable agent management. */
14
14
  export function AgentsMixin(Base) {
@@ -261,24 +261,24 @@ export function AgentsMixin(Base) {
261
261
  * @param agentSpecId - Agent spec identifier.
262
262
  * @returns The agent spec, or undefined if not found.
263
263
  */
264
- getAgentSpec(agentSpecId) {
265
- return agentSpecs.getAgentSpecs(agentSpecId);
264
+ getAgentspec(agentSpecId) {
265
+ return agentspecs.getAgentspecs(agentSpecId);
266
266
  }
267
267
  /**
268
268
  * List all available agent specifications.
269
269
  * @param prefix - If provided, only return specs whose ID starts with this prefix.
270
270
  * @returns Array of agent specifications.
271
271
  */
272
- listAgentSpecs(prefix) {
273
- return agentSpecs.listAgentSpecs(prefix);
272
+ listAgentspecs(prefix) {
273
+ return agentspecs.listAgentspecs(prefix);
274
274
  }
275
275
  /**
276
276
  * Get required environment variables for an agent spec.
277
277
  * @param spec - The agent specification.
278
278
  * @returns Deduplicated array of required environment variable names.
279
279
  */
280
- getAgentSpecRequiredEnvVars(spec) {
281
- return agentSpecs.getAgentSpecRequiredEnvVars(spec);
280
+ getAgentspecRequiredEnvVars(spec) {
281
+ return agentspecs.getAgentspecRequiredEnvVars(spec);
282
282
  }
283
283
  // ========================================================================
284
284
  // Project Agent Assignment
@@ -30,6 +30,18 @@ export function ToolApprovalCard({ approval, onApprove, onReject, onToggleRead,
30
30
  const detailLabelSx = { color: 'fg.muted' };
31
31
  const detailValueSx = { color: 'fg.default' };
32
32
  const isRead = approval.isRead ?? false;
33
+ const statusDescriptor = approval.status === 'approved_with_changes'
34
+ ? 'approved with changes'
35
+ : approval.status;
36
+ // Review text must follow status, not only reviewedAt.
37
+ // Some websocket flows can have an already-decided status before reviewer
38
+ // metadata is hydrated; rendering "review pending" in that window is
39
+ // misleading, so non-pending statuses get a status-based summary.
40
+ const reviewSummary = approval.reviewedAt
41
+ ? `, reviewed by ${approval.reviewedBy || 'reviewer'} ${formatRelativeTime(approval.reviewedAt)}`
42
+ : approval.status === 'pending'
43
+ ? ', review pending'
44
+ : `, ${statusDescriptor}`;
33
45
  return (_jsx(Box, { sx: {
34
46
  p: 3,
35
47
  borderRadius: 2,
@@ -47,9 +59,7 @@ export function ToolApprovalCard({ approval, onApprove, onReject, onToggleRead,
47
59
  gap: 2,
48
60
  mb: 1,
49
61
  flexWrap: 'wrap',
50
- }, children: [_jsx(Text, { sx: { fontWeight: 'bold', fontSize: 2 }, children: approval.toolName }), _jsx(Label, { variant: statusConfig.variant, children: statusConfig.label }), _jsx(Label, { variant: riskConfig.variant, children: riskConfig.label }), !isRead && _jsx(Label, { variant: "accent", children: "Unread" })] }), _jsxs(Text, { sx: { color: 'fg.muted', fontSize: 0, display: 'block' }, children: ["Requested by ", approval.requestedBy, ' ', formatRelativeTime(approval.requestedAt), approval.reviewedAt
51
- ? `, reviewed by ${approval.reviewedBy || 'reviewer'} ${formatRelativeTime(approval.reviewedAt)}`
52
- : ', review pending'] }), _jsx(Box, { sx: {
62
+ }, children: [_jsx(Text, { sx: { fontWeight: 'bold', fontSize: 2 }, children: approval.toolName }), _jsx(Label, { variant: statusConfig.variant, children: statusConfig.label }), _jsx(Label, { variant: riskConfig.variant, children: riskConfig.label }), !isRead && _jsx(Label, { variant: "accent", children: "Unread" })] }), _jsxs(Text, { sx: { color: 'fg.muted', fontSize: 0, display: 'block' }, children: ["Requested by ", approval.requestedBy, ' ', formatRelativeTime(approval.requestedAt), reviewSummary] }), _jsx(Box, { sx: {
53
63
  mt: 2,
54
64
  width: '100%',
55
65
  p: 2,
@@ -5,7 +5,7 @@ import type { AgentLibrary, Extension, McpServerSelection, Protocol } from '../t
5
5
  /**
6
6
  * Agent spec entry from the library endpoint.
7
7
  */
8
- export interface LibraryAgentSpec {
8
+ export interface LibraryAgentspec {
9
9
  [key: string]: unknown;
10
10
  id: string;
11
11
  version?: string;
@@ -121,7 +121,7 @@ export interface AgentConfigurationProps {
121
121
  /** Selected MCP servers */
122
122
  selectedMcpServers?: McpServerSelection[];
123
123
  /** Cloud-discovered specs fetched from a remote runtime catalog. */
124
- cloudLibrarySpecs?: LibraryAgentSpec[];
124
+ cloudLibrarySpecs?: LibraryAgentspec[];
125
125
  /** Loading state for cloud library specs. */
126
126
  cloudLibraryLoading?: boolean;
127
127
  /** Optional cloud library fetch error message. */
@@ -1,3 +1,3 @@
1
1
  export * from './utils';
2
2
  export { AgentConfiguration, AGENT_LIBRARIES, TRANSPORTS, EXTENSIONS, isSpecSelection, getSpecId, } from './AgentConfiguration';
3
- export type { AgentConfigurationProps, SkillOption, LibraryAgentSpec, } from './AgentConfiguration';
3
+ export type { AgentConfigurationProps, SkillOption, LibraryAgentspec, } from './AgentConfiguration';
@@ -35,8 +35,8 @@ import { useDeletePausedAgentRuntime } from '../hooks/useCheckpoints';
35
35
  import { AGENT_STATUS_COLORS } from '../types/agents';
36
36
  const queryClient = new QueryClient();
37
37
  // ─── Defaults ──────────────────────────────────────────────────────────────
38
- const AGENT_SPEC_ID = 'monitor-sales-kpis';
39
- const DEMO_AGENT_NAME = AGENT_SPEC_ID;
38
+ const AGENTSPEC_ID = 'monitor-sales-kpis';
39
+ const DEMO_AGENT_NAME = AGENTSPEC_ID;
40
40
  const LIGHT_CHECKPOINT_MESSAGES = [
41
41
  '[Checkpoint] Captured message history snapshot',
42
42
  '[Checkpoint] Saved conversational context for lightweight resume',
@@ -45,7 +45,7 @@ const LIGHT_CHECKPOINT_MESSAGES = [
45
45
  * Agent spec attributes displayed in the sidebar.
46
46
  * In production this would be fetched from the agentspecs service.
47
47
  */
48
- const AGENT_SPEC = {
48
+ const AGENTSPEC = {
49
49
  id: 'monitor-sales-kpis',
50
50
  name: 'Monitor Sales KPIs',
51
51
  description: 'Monitor and analyze sales KPIs from the CRM system. Generate daily reports, identify trends, and flag anomalies.',
@@ -86,9 +86,9 @@ const SpecRow = ({ icon: Icon, label, value }) => (_jsxs(Box, { sx: {
86
86
  // ─── Inner component (rendered after auth) ─────────────────────────────────
87
87
  const AgentCheckpointsInner = ({ onLogout, }) => {
88
88
  const { runtime, status: runtimeStatus, endpoint: _agentEndpoint, isReady, error: hookError, launchRuntime, connectToRuntime, disconnect, } = useAgentRuntimes({
89
- agentSpecId: AGENT_SPEC_ID,
89
+ agentSpecId: AGENTSPEC_ID,
90
90
  autoStart: false,
91
- agentSpec: AGENT_SPEC,
91
+ agentSpec: AGENTSPEC,
92
92
  agentConfig: {
93
93
  name: DEMO_AGENT_NAME,
94
94
  model: 'bedrock:us.anthropic.claude-sonnet-4-5-20250929-v1:0',
@@ -97,8 +97,8 @@ const AgentCheckpointsInner = ({ onLogout, }) => {
97
97
  },
98
98
  });
99
99
  const { pause, resume, terminate, refreshCheckpoints, checkpoints } = useAgentLifecycle({
100
- agentSpecId: AGENT_SPEC_ID,
101
- agentSpec: AGENT_SPEC,
100
+ agentSpecId: AGENTSPEC_ID,
101
+ agentSpec: AGENTSPEC,
102
102
  runtime,
103
103
  connectToRuntime,
104
104
  disconnect,
@@ -120,7 +120,7 @@ const AgentCheckpointsInner = ({ onLogout, }) => {
120
120
  const autoConnectAttemptRef = useRef(null);
121
121
  const displayError = hookError || actionError;
122
122
  const podName = runtime?.podName || '(launching…)';
123
- const agentId = runtime?.agentId || AGENT_SPEC_ID;
123
+ const agentId = runtime?.agentId || AGENTSPEC_ID;
124
124
  const agentBaseUrl = runtime?.agentBaseUrl || '';
125
125
  const handleLaunch = useCallback(async () => {
126
126
  setIsStarting(true);
@@ -319,7 +319,7 @@ const AgentCheckpointsInner = ({ onLogout, }) => {
319
319
  p: 3,
320
320
  borderBottom: '1px solid',
321
321
  borderColor: 'border.default',
322
- }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2, mb: 2 }, children: [_jsx(Text, { sx: { fontSize: '20px' }, children: AGENT_SPEC.emoji }), _jsx(Heading, { as: "h4", sx: { fontSize: 2, m: 0 }, children: AGENT_SPEC.name })] }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block', mb: 3 }, children: AGENT_SPEC.description }), _jsx(SpecRow, { icon: AiModelIcon, label: "Model", value: AGENT_SPEC.model }), _jsx(SpecRow, { icon: GlobeIcon, label: "Protocol", value: AGENT_SPEC.protocol }), _jsx(SpecRow, { icon: ZapIcon, label: "Memory", value: AGENT_SPEC.memory }), _jsx(SpecRow, { icon: GraphIcon, label: "Environment", value: AGENT_SPEC.environment_name }), _jsx(SpecRow, { icon: ClockIcon, label: "Trigger", value: AGENT_SPEC.trigger.description }), _jsx(SpecRow, { icon: TagIcon, label: "Tags", value: AGENT_SPEC.tags.join(', ') }), _jsxs(Box, { sx: {
322
+ }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2, mb: 2 }, children: [_jsx(Text, { sx: { fontSize: '20px' }, children: AGENTSPEC.emoji }), _jsx(Heading, { as: "h4", sx: { fontSize: 2, m: 0 }, children: AGENTSPEC.name })] }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block', mb: 3 }, children: AGENTSPEC.description }), _jsx(SpecRow, { icon: AiModelIcon, label: "Model", value: AGENTSPEC.model }), _jsx(SpecRow, { icon: GlobeIcon, label: "Protocol", value: AGENTSPEC.protocol }), _jsx(SpecRow, { icon: ZapIcon, label: "Memory", value: AGENTSPEC.memory }), _jsx(SpecRow, { icon: GraphIcon, label: "Environment", value: AGENTSPEC.environment_name }), _jsx(SpecRow, { icon: ClockIcon, label: "Trigger", value: AGENTSPEC.trigger.description }), _jsx(SpecRow, { icon: TagIcon, label: "Tags", value: AGENTSPEC.tags.join(', ') }), _jsxs(Box, { sx: {
323
323
  mt: 2,
324
324
  pt: 2,
325
325
  borderTop: '1px solid',
@@ -329,7 +329,7 @@ const AgentCheckpointsInner = ({ onLogout, }) => {
329
329
  fontSize: 0,
330
330
  display: 'block',
331
331
  mb: 1,
332
- }, children: "Advanced" }), _jsx(SpecRow, { label: "Cost limit", value: AGENT_SPEC.advanced.cost_limit }), _jsx(SpecRow, { label: "Time limit", value: AGENT_SPEC.advanced.time_limit }), _jsx(SpecRow, { label: "Max iterations", value: String(AGENT_SPEC.advanced.max_iterations) }), _jsx(SpecRow, { label: "Checkpoint interval", value: `${AGENT_SPEC.advanced.checkpoint_interval}s` }), _jsx(SpecRow, { label: "Temperature", value: String(AGENT_SPEC.model_config.temperature) }), _jsx(SpecRow, { label: "Max tokens", value: String(AGENT_SPEC.model_config.max_tokens) })] })] }), _jsxs(Box, { sx: {
332
+ }, children: "Advanced" }), _jsx(SpecRow, { label: "Cost limit", value: AGENTSPEC.advanced.cost_limit }), _jsx(SpecRow, { label: "Time limit", value: AGENTSPEC.advanced.time_limit }), _jsx(SpecRow, { label: "Max iterations", value: String(AGENTSPEC.advanced.max_iterations) }), _jsx(SpecRow, { label: "Checkpoint interval", value: `${AGENTSPEC.advanced.checkpoint_interval}s` }), _jsx(SpecRow, { label: "Temperature", value: String(AGENTSPEC.model_config.temperature) }), _jsx(SpecRow, { label: "Max tokens", value: String(AGENTSPEC.model_config.max_tokens) })] })] }), _jsxs(Box, { sx: {
333
333
  order: 2,
334
334
  p: 3,
335
335
  borderBottom: '1px solid',
@@ -426,7 +426,7 @@ const AgentCheckpointsInner = ({ onLogout, }) => {
426
426
  height: '100%',
427
427
  gap: 3,
428
428
  }, children: [_jsx(Spinner, { size: "large" }), _jsx(Text, { sx: { color: 'fg.muted' }, children: runtimeStatus === 'launching'
429
- ? `Launching runtime for ${AGENT_SPEC_ID}…`
429
+ ? `Launching runtime for ${AGENTSPEC_ID}…`
430
430
  : 'Creating agent on runtime…' })] })) : showNoAgentRunningView ? (_jsxs(Box, { sx: {
431
431
  display: 'flex',
432
432
  flexDirection: 'column',
@@ -435,7 +435,7 @@ const AgentCheckpointsInner = ({ onLogout, }) => {
435
435
  height: '100%',
436
436
  gap: 3,
437
437
  px: 3,
438
- }, children: [_jsx(AgentIcon, { size: 48 }), _jsx(Heading, { as: "h2", sx: { fontSize: 3 }, children: "Checkpoint Agent" }), _jsxs(Text, { sx: { color: 'fg.muted', textAlign: 'center', maxWidth: 560 }, children: ["Launch a cloud agent runtime with pause/resume checkpointing. The agent will be deployed from the", ' ', _jsx("strong", { children: AGENT_SPEC_ID }), " spec."] }), displayError && (_jsx(Flash, { variant: "danger", sx: { maxWidth: 560, width: '100%' }, children: displayError })), _jsx(Button, { variant: "primary", size: "large", leadingVisual: PlayIcon, onClick: handleLaunch, children: "Launch Agent" })] })) : (isReady || runtimeStatus === 'resumed') &&
438
+ }, children: [_jsx(AgentIcon, { size: 48 }), _jsx(Heading, { as: "h2", sx: { fontSize: 3 }, children: "Checkpoint Agent" }), _jsxs(Text, { sx: { color: 'fg.muted', textAlign: 'center', maxWidth: 560 }, children: ["Launch a cloud agent runtime with pause/resume checkpointing. The agent will be deployed from the", ' ', _jsx("strong", { children: AGENTSPEC_ID }), " spec."] }), displayError && (_jsx(Flash, { variant: "danger", sx: { maxWidth: 560, width: '100%' }, children: displayError })), _jsx(Button, { variant: "primary", size: "large", leadingVisual: PlayIcon, onClick: handleLaunch, children: "Launch Agent" })] })) : (isReady || runtimeStatus === 'resumed') &&
439
439
  runtimeStatus !== 'paused' ? (_jsx(Chat, { protocol: "vercel-ai", baseUrl: agentBaseUrl, agentId: agentId, title: "Monitor Sales KPI Agent", brandIcon: _jsx(AgentIcon, { size: 16 }), placeholder: "Ask about sales KPIs\u2026", description: "Monitor Sales KPI agent with pause/resume checkpointing", showHeader: false, showTokenUsage: true, autoFocus: true, height: "100%", runtimeId: podName, historyEndpoint: `${agentBaseUrl}/api/v1/history`, suggestions: [
440
440
  {
441
441
  title: 'KPIs',
@@ -31,7 +31,7 @@ import { useAgentRuntimes } from '../hooks/useAgentRuntimes';
31
31
  const queryClient = new QueryClient();
32
32
  // ─── Constants ─────────────────────────────────────────────────────────────
33
33
  const AGENT_NAME = 'eval-example-agent';
34
- const AGENT_SPEC_ID = 'example-evals';
34
+ const AGENTSPEC_ID = 'example-evals';
35
35
  const DEFAULT_EXECUTION_TARGET = (import.meta.env.VITE_AGENT_EVALS_TARGET || 'cloud').toLowerCase() === 'local'
36
36
  ? 'local'
37
37
  : 'cloud';
@@ -93,7 +93,7 @@ const AgentEvalsInner = ({ onLogout, executionTarget, onExecutionTargetChange })
93
93
  return 'https://r1.datalayer.run';
94
94
  }, [configuration?.runtimesRunUrl]);
95
95
  const { runtime, status: runtimeStatus, isReady, error: hookError, runtimeCreationBaseUrl, } = useAgentRuntimes({
96
- agentSpecId: AGENT_SPEC_ID,
96
+ agentSpecId: AGENTSPEC_ID,
97
97
  autoStart: executionTarget === 'cloud',
98
98
  runtimeCreationTarget: executionTarget === 'local' ? 'local-agent-runtimes' : 'backend-services',
99
99
  runtimeCreationBaseUrl: executionTarget === 'local' ? localRuntimeBaseUrl : cloudRuntimeBaseUrl,
@@ -182,7 +182,7 @@ const AgentEvalsInner = ({ onLogout, executionTarget, onExecutionTargetChange })
182
182
  description: 'Agent with evaluation and quality scoring',
183
183
  agent_library: 'pydantic-ai',
184
184
  transport: 'vercel-ai',
185
- agent_spec_id: AGENT_SPEC_ID,
185
+ agent_spec_id: AGENTSPEC_ID,
186
186
  enable_skills: true,
187
187
  tools: [],
188
188
  }),
@@ -26,7 +26,7 @@ import { AuthRequiredView, ErrorView } from './components';
26
26
  import { ThemedProvider } from './utils/themedProvider';
27
27
  import { uniqueAgentId } from './utils/agentId';
28
28
  import { parseAgentStreamMessage } from '../types/stream';
29
- import { getAgentSpecs } from '../specs/agents';
29
+ import { getAgentspecs } from '../specs/agents';
30
30
  import { subscribeOtelWs } from '../context/otelWsPool';
31
31
  import { toMetricValue } from '../hooks/useMonitoring';
32
32
  import { useAIAgentsWebSocket } from '../hooks';
@@ -35,7 +35,7 @@ import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel';
35
35
  import { Chat } from '../chat';
36
36
  // ─── Constants ─────────────────────────────────────────────────────────────
37
37
  const AGENT_NAME = 'guardrails-example-agent';
38
- const AGENT_SPEC_ID = 'example-guardrails';
38
+ const AGENTSPEC_ID = 'example-guardrails';
39
39
  const DEFAULT_LOCAL_BASE_URL = import.meta.env.VITE_BASE_URL || 'http://localhost:8765';
40
40
  const OTEL_BASE_URL_ENV = import.meta.env.VITE_OTEL_BASE_URL;
41
41
  const DATALAYER_RUN_URL_ENV = import.meta.env.DATALAYER_RUN_URL;
@@ -55,7 +55,7 @@ const toNumberOrNull = (value) => {
55
55
  return null;
56
56
  };
57
57
  const resolvePerRunBudgetFromSpec = (agentSpecId) => {
58
- const spec = getAgentSpecs(agentSpecId);
58
+ const spec = getAgentspecs(agentSpecId);
59
59
  if (!spec?.guardrails?.length) {
60
60
  return null;
61
61
  }
@@ -74,7 +74,7 @@ const resolvePerRunBudgetFromSpec = (agentSpecId) => {
74
74
  }
75
75
  return null;
76
76
  };
77
- const DEFAULT_RUN_BUDGET_USD = resolvePerRunBudgetFromSpec(AGENT_SPEC_ID);
77
+ const DEFAULT_RUN_BUDGET_USD = resolvePerRunBudgetFromSpec(AGENTSPEC_ID);
78
78
  const toApprovalRequest = (payload) => ({
79
79
  id: payload.id,
80
80
  tool_name: payload.tool_name,
@@ -249,7 +249,7 @@ const AgentGuardrailsInner = ({ onLogout, }) => {
249
249
  description: 'Agent with cost budget and tool approval guardrails',
250
250
  agent_library: 'pydantic-ai',
251
251
  transport: 'vercel-ai',
252
- agent_spec_id: AGENT_SPEC_ID,
252
+ agent_spec_id: AGENTSPEC_ID,
253
253
  enable_skills: true,
254
254
  tools: [],
255
255
  }),
@@ -13,7 +13,7 @@ import { useExampleAgentRuntimesUrl } from './utils/useExampleAgentRuntimesUrl';
13
13
  import { ErrorView } from './components';
14
14
  import { Chat } from '../chat';
15
15
  setupPrimerPortals();
16
- const AGENT_SPEC_ID = 'example-hooks';
16
+ const AGENTSPEC_ID = 'example-hooks';
17
17
  const AGENT_NAME = 'hooks-example-agent';
18
18
  const AgentHooksExample = () => {
19
19
  const baseUrl = useExampleAgentRuntimesUrl();
@@ -30,7 +30,7 @@ const AgentHooksExample = () => {
30
30
  headers: { 'Content-Type': 'application/json' },
31
31
  body: JSON.stringify({
32
32
  name,
33
- agent_spec_id: AGENT_SPEC_ID,
33
+ agent_spec_id: AGENTSPEC_ID,
34
34
  transport: 'vercel-ai',
35
35
  }),
36
36
  });
@@ -79,7 +79,7 @@ const AgentHooksExample = () => {
79
79
  height: '100vh',
80
80
  gap: 3,
81
81
  bg: 'canvas.default',
82
- }, children: [_jsx(Spinner, { size: "large" }), _jsxs(Text, { sx: { color: 'fg.muted' }, children: ["Creating agent from ", AGENT_SPEC_ID, "..."] })] }) }));
82
+ }, children: [_jsx(Spinner, { size: "large" }), _jsxs(Text, { sx: { color: 'fg.muted' }, children: ["Creating agent from ", AGENTSPEC_ID, "..."] })] }) }));
83
83
  }
84
84
  if (error || !agentId) {
85
85
  return (_jsx(ThemedProvider, { children: _jsx(ErrorView, { error: "Failed to start hooks agent", detail: error || 'No agent ID returned' }) }));
@@ -12,7 +12,7 @@ import { uniqueAgentId } from './utils/agentId';
12
12
  import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel';
13
13
  import { Chat } from '../chat';
14
14
  import { useAIAgentsWebSocket } from '../hooks';
15
- const AGENT_SPEC_ID = 'example-inference';
15
+ const AGENTSPEC_ID = 'example-inference';
16
16
  const AGENT_NAME = 'inference-provider-example-agent';
17
17
  const DEFAULT_LOCAL_BASE_URL = import.meta.env.VITE_BASE_URL || 'http://localhost:8765';
18
18
  const queryClient = new QueryClient();
@@ -114,7 +114,7 @@ const AgentInferenceProviderExampleInner = () => {
114
114
  body: JSON.stringify({
115
115
  name,
116
116
  transport: 'vercel-ai',
117
- agent_spec_id: AGENT_SPEC_ID,
117
+ agent_spec_id: AGENTSPEC_ID,
118
118
  inferenceProvider: nextProvider,
119
119
  }),
120
120
  });
@@ -131,7 +131,7 @@ const AgentInferenceProviderExampleInner = () => {
131
131
  setAgentId(nextAgentId);
132
132
  appendProviderEvent('agent.created', 'Launched local agent runtime', {
133
133
  agentId: nextAgentId,
134
- agentSpecId: AGENT_SPEC_ID,
134
+ agentSpecId: AGENTSPEC_ID,
135
135
  inferenceProvider: nextProvider,
136
136
  baseUrl,
137
137
  });
@@ -225,7 +225,7 @@ const AgentInferenceProviderExampleInner = () => {
225
225
  alignItems: 'center',
226
226
  flexWrap: 'wrap',
227
227
  gap: 2,
228
- }, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 4, mb: 1 }, children: "Agent Inference Provider Example" }), _jsxs(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: ["Launches a local agent runtime from ", AGENT_SPEC_ID, " and lets you switch between local and datalayer inference."] })] }), _jsx(ProviderBadge, { provider: provider })] }), _jsxs(SegmentedControl, { "aria-label": "Inference provider", fullWidth: true, children: [_jsx(SegmentedControl.Button, { selected: provider === 'local', onClick: () => onProviderChange('local'), children: "local" }), _jsx(SegmentedControl.Button, { selected: provider === 'datalayer', onClick: () => onProviderChange('datalayer'), children: "datalayer" })] }), _jsxs(Box, { sx: {
228
+ }, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 4, mb: 1 }, children: "Agent Inference Provider Example" }), _jsxs(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: ["Launches a local agent runtime from ", AGENTSPEC_ID, " and lets you switch between local and datalayer inference."] })] }), _jsx(ProviderBadge, { provider: provider })] }), _jsxs(SegmentedControl, { "aria-label": "Inference provider", fullWidth: true, children: [_jsx(SegmentedControl.Button, { selected: provider === 'local', onClick: () => onProviderChange('local'), children: "local" }), _jsx(SegmentedControl.Button, { selected: provider === 'datalayer', onClick: () => onProviderChange('datalayer'), children: "datalayer" })] }), _jsxs(Box, { sx: {
229
229
  display: 'flex',
230
230
  gap: 2,
231
231
  alignItems: 'center',
@@ -248,7 +248,7 @@ const AgentInferenceProviderExampleInner = () => {
248
248
  borderRadius: 2,
249
249
  overflow: 'hidden',
250
250
  bg: 'canvas.default',
251
- }, children: agentId && !isLaunching ? (_jsx(Chat, { protocol: "vercel-ai", baseUrl: baseUrl, agentId: agentId, authToken: token ?? undefined, title: "Agent Inference Provider Example", subtitle: `Spec: ${AGENT_SPEC_ID}`, placeholder: "Ask the inference provider something...", showHeader: true, showNewChatButton: true, showClearButton: false, showModelSelector: true, showToolsMenu: true, showSkillsMenu: true, showTokenUsage: true, autoFocus: true, height: "100%", runtimeId: agentId, historyEndpoint: `${baseUrl}/api/v1/history`, onMessageSent: content => {
251
+ }, children: agentId && !isLaunching ? (_jsx(Chat, { protocol: "vercel-ai", baseUrl: baseUrl, agentId: agentId, authToken: token ?? undefined, title: "Agent Inference Provider Example", subtitle: `Spec: ${AGENTSPEC_ID}`, placeholder: "Ask the inference provider something...", showHeader: true, showNewChatButton: true, showClearButton: false, showModelSelector: true, showToolsMenu: true, showSkillsMenu: true, showTokenUsage: true, autoFocus: true, height: "100%", runtimeId: agentId, historyEndpoint: `${baseUrl}/api/v1/history`, onMessageSent: content => {
252
252
  appendProviderEvent('provider.request', `Sent message via ${provider}`, {
253
253
  provider,
254
254
  agentId,
@@ -21,7 +21,7 @@ import { MCP_SERVER_LIBRARY } from '../specs/mcpServers';
21
21
  const queryClient = new QueryClient();
22
22
  const AGENT_NAME = 'mcp-example-agent';
23
23
  // Must match agentspecs/agentspecs/agents/example-mcp.yaml `id`.
24
- const AGENT_SPEC_ID = 'example-mcp';
24
+ const AGENTSPEC_ID = 'example-mcp';
25
25
  const DEFAULT_LOCAL_BASE_URL = import.meta.env.VITE_BASE_URL || 'http://localhost:8765';
26
26
  /* ── Aggregate MCP status helpers ─────────────────────── */
27
27
  function deriveAggregate(servers) {
@@ -153,7 +153,7 @@ const AgentMCPInner = ({ onLogout }) => {
153
153
  description: 'MCP example agent – web crawling and research via Tavily',
154
154
  agent_library: 'pydantic-ai',
155
155
  transport: 'vercel-ai',
156
- agent_spec_id: AGENT_SPEC_ID,
156
+ agent_spec_id: AGENTSPEC_ID,
157
157
  enable_codemode: false,
158
158
  enable_skills: true,
159
159
  tools: [],
@@ -28,7 +28,7 @@ import { Chat } from '../chat';
28
28
  import { useExampleAgentRuntimesUrl } from './utils/useExampleAgentRuntimesUrl';
29
29
  // ─── Constants ─────────────────────────────────────────────────────────────
30
30
  const AGENT_NAME = 'memory-example-agent';
31
- const AGENT_SPEC_ID = 'example-memory';
31
+ const AGENTSPEC_ID = 'example-memory';
32
32
  // ─── Inner component (rendered after auth) ─────────────────────────────────
33
33
  const AgentMemoryInner = ({ onLogout }) => {
34
34
  const { token } = useSimpleAuthStore();
@@ -66,7 +66,7 @@ const AgentMemoryInner = ({ onLogout }) => {
66
66
  description: 'Agent with Mem0 persistent memory',
67
67
  agent_library: 'pydantic-ai',
68
68
  transport: 'vercel-ai',
69
- agent_spec_id: AGENT_SPEC_ID,
69
+ agent_spec_id: AGENTSPEC_ID,
70
70
  enable_skills: true,
71
71
  tools: [],
72
72
  }),
@@ -35,7 +35,7 @@ const queryClient = new QueryClient();
35
35
  import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel';
36
36
  import { Chat } from '../chat';
37
37
  const AGENT_NAME = 'monitoring-example-agent';
38
- const AGENT_SPEC_ID = 'example-monitoring';
38
+ const AGENTSPEC_ID = 'example-monitoring';
39
39
  const DEFAULT_LOCAL_BASE_URL = import.meta.env.VITE_BASE_URL || 'http://localhost:8765';
40
40
  const OTEL_BASE_URL_ENV = import.meta.env.VITE_OTEL_BASE_URL;
41
41
  const DATALAYER_RUN_URL_ENV = import.meta.env.DATALAYER_RUN_URL;
@@ -90,7 +90,7 @@ const AgentMonitoringInner = ({ onLogout, }) => {
90
90
  description: 'MCP monitoring example – web crawling via Tavily with live cost/token metrics',
91
91
  agent_library: 'pydantic-ai',
92
92
  transport: 'vercel-ai',
93
- agent_spec_id: AGENT_SPEC_ID,
93
+ agent_spec_id: AGENTSPEC_ID,
94
94
  enable_skills: true,
95
95
  tools: [],
96
96
  }),
@@ -28,7 +28,7 @@ import { Chat } from '../chat';
28
28
  const queryClient = new QueryClient();
29
29
  // ─── Constants ─────────────────────────────────────────────────────────────
30
30
  const AGENT_NAME = 'notification-example-agent';
31
- const AGENT_SPEC_ID = 'example-notifications';
31
+ const AGENTSPEC_ID = 'example-notifications';
32
32
  const alertVariant = (severity) => {
33
33
  if (severity === 'critical')
34
34
  return 'danger';
@@ -78,7 +78,7 @@ const AgentNotificationsInner = ({ onLogout, }) => {
78
78
  description: 'Agent with multi-channel notification support',
79
79
  agent_library: 'pydantic-ai',
80
80
  transport: 'vercel-ai',
81
- agent_spec_id: AGENT_SPEC_ID,
81
+ agent_spec_id: AGENTSPEC_ID,
82
82
  enable_skills: true,
83
83
  tools: [],
84
84
  }),