@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.
- package/README.md +34 -0
- package/lib/App.js +1 -1
- package/lib/agents/AgentDetails.d.ts +22 -1
- package/lib/agents/AgentDetails.js +34 -47
- package/lib/api/index.d.ts +0 -1
- package/lib/api/index.js +4 -2
- package/lib/chat/Chat.d.ts +5 -106
- package/lib/chat/Chat.js +4 -4
- package/lib/chat/ChatFloating.d.ts +7 -140
- package/lib/chat/ChatFloating.js +2 -2
- package/lib/chat/ChatPopupStandalone.d.ts +8 -47
- package/lib/chat/ChatPopupStandalone.js +3 -3
- package/lib/chat/ChatSidebar.d.ts +4 -69
- package/lib/chat/ChatSidebar.js +2 -2
- package/lib/chat/ChatStandalone.d.ts +4 -54
- package/lib/chat/ChatStandalone.js +3 -3
- package/lib/chat/base/ChatBase.js +1083 -157
- package/lib/chat/header/ChatHeaderBase.d.ts +11 -6
- package/lib/chat/header/ChatHeaderBase.js +18 -16
- package/lib/chat/indicators/McpStatusIndicator.d.ts +7 -4
- package/lib/chat/indicators/McpStatusIndicator.js +7 -32
- package/lib/chat/indicators/SandboxStatusIndicator.d.ts +4 -1
- package/lib/chat/indicators/SandboxStatusIndicator.js +9 -9
- package/lib/chat/indicators/SkillsStatusIndicator.d.ts +7 -0
- package/lib/chat/indicators/SkillsStatusIndicator.js +88 -0
- package/lib/chat/indicators/index.d.ts +1 -0
- package/lib/chat/indicators/index.js +1 -0
- package/lib/chat/messages/ChatMessageList.d.ts +1 -1
- package/lib/chat/messages/ChatMessageList.js +108 -113
- package/lib/chat/prompt/InputFooter.d.ts +19 -6
- package/lib/chat/prompt/InputFooter.js +71 -18
- package/lib/chat/prompt/InputPrompt.d.ts +3 -1
- package/lib/chat/prompt/InputPrompt.js +4 -4
- package/lib/chat/prompt/InputPromptFooter.js +1 -1
- package/lib/chat/prompt/InputPromptLexical.d.ts +3 -1
- package/lib/chat/prompt/InputPromptLexical.js +12 -5
- package/lib/chat/prompt/InputPromptText.d.ts +3 -1
- package/lib/chat/prompt/InputPromptText.js +2 -2
- package/lib/chat/tools/ToolApprovalBanner.js +1 -1
- package/lib/chat/tools/ToolCallDisplay.d.ts +3 -1
- package/lib/chat/tools/ToolCallDisplay.js +2 -2
- package/lib/chat/usage/TokenUsageBar.js +20 -2
- package/lib/client/AgentRuntimesClientContext.d.ts +53 -0
- package/lib/client/AgentRuntimesClientContext.js +55 -0
- package/lib/client/AgentsMixin.d.ts +0 -18
- package/lib/client/AgentsMixin.js +6 -30
- package/lib/client/IAgentRuntimesClient.d.ts +215 -0
- package/lib/client/IAgentRuntimesClient.js +5 -0
- package/lib/client/SdkAgentRuntimesClient.d.ts +151 -0
- package/lib/client/SdkAgentRuntimesClient.js +134 -0
- package/lib/client/index.d.ts +4 -1
- package/lib/client/index.js +3 -1
- package/lib/components/NotificationEventCard.js +5 -1
- package/lib/config/AgentConfiguration.js +3 -3
- package/lib/context/ContextDistribution.d.ts +3 -1
- package/lib/context/ContextDistribution.js +8 -27
- package/lib/context/ContextInspector.d.ts +3 -1
- package/lib/context/ContextInspector.js +19 -67
- package/lib/context/ContextPanel.d.ts +3 -1
- package/lib/context/ContextPanel.js +104 -64
- package/lib/context/ContextUsage.d.ts +3 -1
- package/lib/context/ContextUsage.js +3 -3
- package/lib/context/CostTracker.d.ts +9 -3
- package/lib/context/CostTracker.js +26 -47
- package/lib/context/CostUsageChart.d.ts +12 -0
- package/lib/context/CostUsageChart.js +378 -0
- package/lib/context/GraphFlowChart.d.ts +16 -0
- package/lib/context/GraphFlowChart.js +182 -0
- package/lib/context/TokenUsageChart.d.ts +8 -1
- package/lib/context/TokenUsageChart.js +349 -211
- package/lib/context/TurnGraphChart.d.ts +39 -0
- package/lib/context/TurnGraphChart.js +538 -0
- package/lib/context/otelWsPool.d.ts +20 -0
- package/lib/context/otelWsPool.js +69 -0
- package/lib/examples/A2UiComponentGalleryExample.d.ts +0 -17
- package/lib/examples/A2UiComponentGalleryExample.js +315 -522
- package/lib/examples/A2UiContactCardExample.d.ts +0 -18
- package/lib/examples/A2UiContactCardExample.js +154 -411
- package/lib/examples/A2UiRestaurantExample.d.ts +0 -30
- package/lib/examples/A2UiRestaurantExample.js +114 -212
- package/lib/examples/A2UiViewerExample.d.ts +0 -18
- package/lib/examples/A2UiViewerExample.js +283 -532
- package/lib/examples/AgUiBackendToolRenderingExample.js +1 -1
- package/lib/examples/AgUiHaikuGenUiExample.d.ts +1 -1
- package/lib/examples/AgUiHaikuGenUiExample.js +1 -1
- package/lib/examples/AgentCheckpointsExample.js +13 -27
- package/lib/examples/AgentCodemodeExample.d.ts +4 -6
- package/lib/examples/AgentCodemodeExample.js +591 -169
- package/lib/examples/AgentEvalsExample.js +12 -16
- package/lib/examples/AgentGuardrailsExample.js +370 -64
- package/lib/examples/AgentHooksExample.d.ts +3 -0
- package/lib/examples/AgentHooksExample.js +104 -0
- package/lib/examples/AgentMCPExample.d.ts +3 -0
- package/lib/examples/AgentMCPExample.js +480 -0
- package/lib/examples/AgentMemoryExample.js +13 -17
- package/lib/examples/AgentMonitoringExample.js +260 -199
- package/lib/examples/AgentNotificationsExample.js +49 -17
- package/lib/examples/AgentOtelExample.js +2 -3
- package/lib/examples/AgentOutputsExample.d.ts +11 -6
- package/lib/examples/AgentOutputsExample.js +382 -81
- package/lib/examples/AgentParametersExample.d.ts +3 -0
- package/lib/examples/AgentParametersExample.js +246 -0
- package/lib/examples/AgentSandboxExample.d.ts +2 -2
- package/lib/examples/AgentSandboxExample.js +68 -40
- package/lib/examples/AgentSkillsExample.js +91 -99
- package/lib/examples/{AgentspecExample.js → AgentSpecsExample.js} +10 -21
- package/lib/examples/AgentSubagentsExample.d.ts +14 -0
- package/lib/examples/AgentSubagentsExample.js +228 -0
- package/lib/examples/AgentToolApprovalsExample.js +29 -557
- package/lib/examples/AgentTriggersExample.js +819 -565
- package/lib/examples/ChatCustomExample.js +11 -24
- package/lib/examples/ChatExample.js +7 -24
- package/lib/examples/CopilotKitLexicalExample.js +2 -1
- package/lib/examples/CopilotKitNotebookExample.js +2 -1
- package/lib/examples/HomeExample.d.ts +15 -0
- package/lib/examples/HomeExample.js +77 -0
- package/lib/examples/Lexical2Example.js +4 -2
- package/lib/examples/{LexicalExample.d.ts → LexicalAgentExample.d.ts} +4 -4
- package/lib/examples/{LexicalExample.js → LexicalAgentExample.js} +65 -16
- package/lib/examples/{LexicalSidebarExample.d.ts → LexicalAgentSidebarExample.d.ts} +5 -5
- package/lib/examples/LexicalAgentSidebarExample.js +261 -0
- package/lib/examples/NotebookAgentExample.d.ts +9 -0
- package/lib/examples/NotebookAgentExample.js +192 -0
- package/lib/examples/{NotebookSidebarExample.d.ts → NotebookAgentSidebarExample.d.ts} +2 -2
- package/lib/examples/NotebookAgentSidebarExample.js +221 -0
- package/lib/examples/{DatalayerNotebookExample.d.ts → NotebookCollaborationExample.d.ts} +4 -4
- package/lib/examples/{DatalayerNotebookExample.js → NotebookCollaborationExample.js} +3 -3
- package/lib/examples/NotebookExample.d.ts +4 -7
- package/lib/examples/NotebookExample.js +14 -146
- package/lib/examples/components/AuthRequiredView.d.ts +6 -0
- package/lib/examples/components/AuthRequiredView.js +33 -0
- package/lib/examples/components/ExampleWrapper.d.ts +7 -0
- package/lib/examples/components/ExampleWrapper.js +25 -6
- package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.js +1 -1
- package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.js +1 -1
- package/lib/examples/{ag-ui → components}/haiku/index.d.ts +1 -1
- package/lib/examples/{ag-ui → components}/haiku/index.js +1 -1
- package/lib/examples/components/index.d.ts +3 -0
- package/lib/examples/components/index.js +4 -0
- package/lib/examples/{ag-ui → components}/weather/index.d.ts +1 -1
- package/lib/examples/{ag-ui → components}/weather/index.js +1 -1
- package/lib/examples/example-selector.d.ts +17 -4
- package/lib/examples/example-selector.js +107 -41
- package/lib/examples/index.d.ts +9 -6
- package/lib/examples/index.js +9 -6
- package/lib/examples/main.js +217 -27
- package/lib/examples/utils/a2ui.d.ts +18 -0
- package/lib/examples/utils/a2ui.js +69 -0
- package/lib/examples/utils/a2uiMarkdownProvider.d.ts +7 -0
- package/lib/examples/utils/a2uiMarkdownProvider.js +9 -0
- package/lib/examples/utils/agentId.d.ts +18 -0
- package/lib/examples/utils/agentId.js +54 -0
- package/lib/examples/utils/agents/earthquake-detector.json +11 -11
- package/lib/examples/utils/agents/sales-forecaster.json +11 -11
- package/lib/examples/utils/agents/social-post-generator.json +11 -11
- package/lib/examples/utils/agents/stock-market.json +11 -11
- package/lib/examples/utils/examplesStore.js +82 -27
- package/lib/hooks/index.d.ts +8 -8
- package/lib/hooks/index.js +7 -7
- package/lib/hooks/useA2A.d.ts +2 -3
- package/lib/hooks/useAIAgentsWebSocket.d.ts +43 -4
- package/lib/hooks/useAIAgentsWebSocket.js +118 -12
- package/lib/hooks/useAcp.d.ts +1 -2
- package/lib/hooks/useAgUi.d.ts +1 -1
- package/lib/hooks/{useAgents.d.ts → useAgentRuntimes.d.ts} +39 -2
- package/lib/hooks/{useAgents.js → useAgentRuntimes.js} +125 -15
- package/lib/hooks/useAgentsCatalog.js +1 -1
- package/lib/hooks/useAgentsService.d.ts +2 -2
- package/lib/hooks/useAgentsService.js +7 -7
- package/lib/hooks/useCheckpoints.js +1 -1
- package/lib/hooks/useConfig.d.ts +4 -1
- package/lib/hooks/useConfig.js +10 -3
- package/lib/hooks/useContextSnapshot.d.ts +9 -4
- package/lib/hooks/useContextSnapshot.js +9 -37
- package/lib/hooks/useMonitoring.js +3 -0
- package/lib/hooks/useSandbox.d.ts +20 -8
- package/lib/hooks/useSandbox.js +105 -40
- package/lib/hooks/useSkills.d.ts +23 -5
- package/lib/hooks/useSkills.js +94 -39
- package/lib/hooks/useToolApprovals.d.ts +60 -36
- package/lib/hooks/useToolApprovals.js +318 -69
- package/lib/hooks/useVercelAI.d.ts +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +1 -0
- package/lib/inference/index.d.ts +0 -1
- package/lib/middleware/index.d.ts +0 -1
- package/lib/protocols/AGUIAdapter.js +6 -0
- package/lib/protocols/VercelAIAdapter.d.ts +7 -0
- package/lib/protocols/VercelAIAdapter.js +59 -7
- package/lib/specs/agents/agents.d.ts +10 -0
- package/lib/specs/agents/agents.js +2139 -262
- package/lib/specs/agents/index.js +3 -1
- package/lib/specs/envvars.d.ts +1 -0
- package/lib/specs/envvars.js +38 -20
- package/lib/specs/evals.js +6 -6
- package/lib/specs/events.d.ts +3 -10
- package/lib/specs/events.js +127 -84
- package/lib/specs/frontendTools.js +2 -2
- package/lib/specs/guardrails.d.ts +0 -7
- package/lib/specs/guardrails.js +240 -159
- package/lib/specs/index.d.ts +1 -0
- package/lib/specs/index.js +1 -0
- package/lib/specs/mcpServers.js +35 -6
- package/lib/specs/memory.d.ts +0 -2
- package/lib/specs/memory.js +4 -17
- package/lib/specs/models.js +25 -5
- package/lib/specs/notifications.js +102 -18
- package/lib/specs/outputs.js +15 -9
- package/lib/specs/personas.d.ts +41 -0
- package/lib/specs/personas.js +168 -0
- package/lib/specs/skills.d.ts +2 -1
- package/lib/specs/skills.js +41 -23
- package/lib/specs/teams/index.js +3 -1
- package/lib/specs/teams/teams.js +468 -348
- package/lib/specs/tools.js +4 -4
- package/lib/specs/triggers.js +61 -11
- package/lib/stores/agentRuntimeStore.d.ts +204 -0
- package/lib/stores/agentRuntimeStore.js +636 -0
- package/lib/stores/index.d.ts +1 -1
- package/lib/stores/index.js +1 -1
- package/lib/tools/adapters/copilotkit/lexicalHooks.d.ts +1 -2
- package/lib/tools/adapters/copilotkit/lexicalHooks.js +1 -3
- package/lib/tools/adapters/copilotkit/notebookHooks.d.ts +1 -2
- package/lib/tools/adapters/copilotkit/notebookHooks.js +1 -3
- package/lib/tools/index.d.ts +0 -2
- package/lib/tools/index.js +0 -1
- package/lib/types/agentspecs.d.ts +50 -1
- package/lib/types/chat.d.ts +309 -8
- package/lib/types/context.d.ts +27 -0
- package/lib/types/cost.d.ts +2 -2
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.js +2 -0
- package/lib/types/mcp.d.ts +8 -0
- package/lib/types/models.d.ts +2 -2
- package/lib/types/personas.d.ts +25 -0
- package/lib/types/personas.js +5 -0
- package/lib/types/skills.d.ts +43 -1
- package/lib/types/stream.d.ts +110 -0
- package/lib/types/stream.js +36 -0
- package/lib/utils/utils.d.ts +9 -5
- package/lib/utils/utils.js +9 -5
- package/package.json +13 -9
- package/scripts/codegen/__pycache__/generate_agents.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_events.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
- package/scripts/codegen/generate_agents.py +102 -6
- package/scripts/codegen/generate_events.py +35 -13
- package/scripts/codegen/generate_personas.py +319 -0
- package/scripts/codegen/generate_skills.py +9 -9
- package/scripts/sync-jupyter.sh +26 -7
- package/lib/api/tool-approvals.d.ts +0 -62
- package/lib/api/tool-approvals.js +0 -145
- package/lib/examples/LexicalSidebarExample.js +0 -163
- package/lib/examples/NotebookSidebarExample.js +0 -119
- package/lib/examples/NotebookSimpleExample.d.ts +0 -6
- package/lib/examples/NotebookSimpleExample.js +0 -22
- package/lib/examples/ag-ui/index.d.ts +0 -10
- package/lib/examples/ag-ui/index.js +0 -16
- package/lib/hooks/useAgentsRegistry.d.ts +0 -10
- package/lib/hooks/useAgentsRegistry.js +0 -20
- package/lib/stores/agentsStore.d.ts +0 -123
- package/lib/stores/agentsStore.js +0 -270
- /package/lib/examples/{AgentspecExample.d.ts → AgentSpecsExample.d.ts} +0 -0
- /package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.d.ts +0 -0
- /package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.d.ts +0 -0
- /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.d.ts +0 -0
- /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.js +0 -0
|
@@ -431,7 +431,7 @@ export const AgentConfiguration = ({ agentLibrary, protocol: transport, extensio
|
|
|
431
431
|
.map(spec => {
|
|
432
432
|
const pkg = spec.id.includes('/') ? spec.id.split('/')[0] : '';
|
|
433
433
|
return (_jsxs(Select.Option, { value: `spec:${spec.id}`, children: [spec.emoji ? `${spec.emoji} ` : '', pkg ? `[${pkg}] ` : '', spec.name] }, `spec:${spec.id}`));
|
|
434
|
-
}), agents.map(agent => (_jsxs(Select.Option, { value: agent.id, children: ["[
|
|
434
|
+
}), agents.map(agent => (_jsxs(Select.Option, { value: agent.id, children: ["[Persona] ", agent.status === 'running' && '● ', agent.name] }, agent.id)))] }), _jsx(FormControl.Caption, { children: isNewAgentMode
|
|
435
435
|
? selectedSpec
|
|
436
436
|
? `Creating from spec: ${selectedSpec.name} — capabilities are locked`
|
|
437
437
|
: 'Configure a new custom agent'
|
|
@@ -444,7 +444,7 @@ export const AgentConfiguration = ({ agentLibrary, protocol: transport, extensio
|
|
|
444
444
|
: 'The base URL of your agent-runtimes server' })] }), _jsxs(Box, { sx: { display: 'flex', gap: 3, marginBottom: 3 }, children: [_jsxs(FormControl, { sx: { flex: 1 }, disabled: isFormReadOnly, children: [_jsx(FormControl.Label, { children: "Agent Library" }), _jsx(Select, { value: agentLibrary, onChange: e => onAgentLibraryChange(e.target.value), sx: { width: '100%' }, children: AGENT_LIBRARIES.map(lib => (_jsxs(Select.Option, { value: lib.value, disabled: lib.disabled, children: [lib.label, lib.disabled && ' (Coming Soon)'] }, lib.value))) })] }), _jsxs(FormControl, { sx: { flex: 1 }, disabled: isFormReadOnly || models.length === 0, children: [_jsx(FormControl.Label, { children: "Model" }), _jsx(Select, { value: model, onChange: e => onModelChange(e.target.value), sx: { width: '100%' }, children: models.length === 0 ? (_jsx(Select.Option, { value: "", children: "Loading models..." })) : (models.map(m => (_jsxs(Select.Option, { value: m.id, disabled: !m.isAvailable, children: [m.name, !m.isAvailable && ' (API key required)'] }, m.id)))) })] }), _jsxs(FormControl, { sx: { flex: 1 }, disabled: isFormReadOnly, children: [_jsx(FormControl.Label, { children: "Transport" }), _jsx(Select, { value: transport, onChange: e => onTransportChange(e.target.value), sx: { width: '100%' }, children: TRANSPORTS.map(t => (_jsx(Select.Option, { value: t.value, children: t.label }, t.value))) })] }), _jsxs(FormControl, { sx: { flex: 1 }, children: [_jsx(FormControl.Label, { children: "Extensions" }), _jsx(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: EXTENSIONS.map(ext => (_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { value: ext.value, checked: extensions.includes(ext.value), disabled: isFormReadOnly || !isExtensionEnabled(ext.value), onChange: e => handleExtensionChange(ext.value, e.target.checked) }), _jsx(Text, { children: ext.label })] }, ext.value))) })] })] }), _jsxs(FormControl, { sx: { marginBottom: 3 }, disabled: isFormReadOnly, children: [_jsx(FormControl.Label, { children: "System Prompt" }), _jsx(TextInput, { value: systemPrompt, onChange: e => onSystemPromptChange(e.target.value), placeholder: "You are a helpful AI assistant.", sx: { width: '100%' } })] }), _jsxs(FormControl, { sx: { marginBottom: 3 }, disabled: isFormReadOnly, children: [_jsx(FormControl.Label, { children: "System Prompt Codemode Addons" }), _jsx(TextInput, { value: systemPromptCodemodeAddons, onChange: e => onSystemPromptCodemodeAddonsChange(e.target.value), placeholder: "Additional codemode instructions", sx: { width: '100%' } })] }), _jsxs(Box, { sx: { display: 'flex', gap: 3, marginBottom: 3 }, children: [_jsxs(FormControl, { sx: { flex: 1 }, disabled: isFormReadOnly, children: [_jsx(FormControl.Label, { children: "Tools (comma-separated)" }), _jsx(TextInput, { value: tools.join(', '), onChange: e => onToolsChange(e.target.value
|
|
445
445
|
.split(',')
|
|
446
446
|
.map(tool => tool.trim())
|
|
447
|
-
.filter(Boolean)), placeholder: "tool_a, tool_b", sx: { width: '100%' } })] }), _jsxs(FormControl, { sx: { flex: 1 }, disabled: isFormReadOnly, children: [_jsx(FormControl.Label, { children: "Sandbox Variant" }), _jsxs(Select, { value: sandboxVariant, onChange: e => onSandboxVariantChange(e.target.value), sx: { width: '100%' }, children: [_jsx(Select.Option, { value: "", children: "Default" }), _jsx(Select.Option, { value: "
|
|
447
|
+
.filter(Boolean)), placeholder: "tool_a, tool_b", sx: { width: '100%' } })] }), _jsxs(FormControl, { sx: { flex: 1 }, disabled: isFormReadOnly, children: [_jsx(FormControl.Label, { children: "Sandbox Variant" }), _jsxs(Select, { value: sandboxVariant, onChange: e => onSandboxVariantChange(e.target.value), sx: { width: '100%' }, children: [_jsx(Select.Option, { value: "", children: "Default" }), _jsx(Select.Option, { value: "eval", children: "eval" }), _jsx(Select.Option, { value: "jupyter", children: "jupyter" })] })] })] }), _jsxs(Box, { sx: {
|
|
448
448
|
marginBottom: 3,
|
|
449
449
|
padding: 3,
|
|
450
450
|
border: '1px solid',
|
|
@@ -470,7 +470,7 @@ export const AgentConfiguration = ({ agentLibrary, protocol: transport, extensio
|
|
|
470
470
|
color: 'fg.muted',
|
|
471
471
|
fontWeight: 'normal',
|
|
472
472
|
ml: 2,
|
|
473
|
-
}, children: "\u2014 defined by spec" }))] }), _jsx(Box, { sx: { display: 'flex', gap: 4, opacity: isSpecMode ? 0.6 : 1 }, children: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: enableCodemode, disabled: !isNewAgentMode || isSpecMode, onChange: e => onEnableCodemodeChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Codemode" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Execute code to compose tools" })] })] }) }), skillsEnabled && enableCodemode && (_jsx(Flash, { variant: "default", sx: { mt: 3 }, children: _jsx(Text, { sx: { fontSize: 0 }, children: "Skills provide curated capabilities; Codemode composes tools with Python for multi-step execution." }) })), skillsEnabled && !enableCodemode && (_jsx(Flash, { variant: "default", sx: { mt: 3 }, children: _jsx(Text, { sx: { fontSize: 0 }, children: "Skills will run with a standalone code sandbox for script execution. Enable Codemode to compose skills with other tools." }) })), enableCodemode && (_jsxs(Box, { sx: { mt: 3, display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: allowDirectToolCalls, disabled: !isNewAgentMode || isSpecMode, onChange: e => onAllowDirectToolCallsChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Allow direct tool calls" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Expose call_tool for simple, single-tool operations" })] })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: enableToolReranker, disabled: !isNewAgentMode || isSpecMode, onChange: e => onEnableToolRerankerChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Enable tool reranker" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Reorder search results using the configured reranker" })] })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: useJupyterSandbox, disabled: !isNewAgentMode || isSpecMode, onChange: e => onUseJupyterSandboxChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Use Jupyter Sandbox" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Execute code in a Jupyter Sandbox instead of
|
|
473
|
+
}, children: "\u2014 defined by spec" }))] }), _jsx(Box, { sx: { display: 'flex', gap: 4, opacity: isSpecMode ? 0.6 : 1 }, children: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: enableCodemode, disabled: !isNewAgentMode || isSpecMode, onChange: e => onEnableCodemodeChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Codemode" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Execute code to compose tools" })] })] }) }), skillsEnabled && enableCodemode && (_jsx(Flash, { variant: "default", sx: { mt: 3 }, children: _jsx(Text, { sx: { fontSize: 0 }, children: "Skills provide curated capabilities; Codemode composes tools with Python for multi-step execution." }) })), skillsEnabled && !enableCodemode && (_jsx(Flash, { variant: "default", sx: { mt: 3 }, children: _jsx(Text, { sx: { fontSize: 0 }, children: "Skills will run with a standalone code sandbox for script execution. Enable Codemode to compose skills with other tools." }) })), enableCodemode && (_jsxs(Box, { sx: { mt: 3, display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: allowDirectToolCalls, disabled: !isNewAgentMode || isSpecMode, onChange: e => onAllowDirectToolCallsChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Allow direct tool calls" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Expose call_tool for simple, single-tool operations" })] })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: enableToolReranker, disabled: !isNewAgentMode || isSpecMode, onChange: e => onEnableToolRerankerChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Enable tool reranker" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Reorder search results using the configured reranker" })] })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: useJupyterSandbox, disabled: !isNewAgentMode || isSpecMode, onChange: e => onUseJupyterSandboxChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Use Jupyter Sandbox" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Execute code in a Jupyter Sandbox instead of eval Sandbox" })] })] })] }))] }), _jsxs(Box, { sx: {
|
|
474
474
|
marginBottom: 3,
|
|
475
475
|
padding: 3,
|
|
476
476
|
border: '1px solid',
|
|
@@ -103,9 +103,11 @@ export interface ContextDistributionProps {
|
|
|
103
103
|
agentId: string;
|
|
104
104
|
/** Height of the chart */
|
|
105
105
|
height?: string;
|
|
106
|
+
/** Live snapshot data from WS — bypasses REST polling when provided */
|
|
107
|
+
liveData?: ContextSnapshotResponse | null;
|
|
106
108
|
}
|
|
107
109
|
/**
|
|
108
110
|
* ContextDistribution component displays context distribution as a treemap.
|
|
109
111
|
*/
|
|
110
|
-
export declare function ContextDistribution({ agentId, height, }: ContextDistributionProps): import("react/jsx-runtime").JSX.Element;
|
|
112
|
+
export declare function ContextDistribution({ agentId, height, liveData, }: ContextDistributionProps): import("react/jsx-runtime").JSX.Element;
|
|
111
113
|
export default ContextDistribution;
|
|
@@ -6,18 +6,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
6
6
|
*/
|
|
7
7
|
import { Box, Text, Spinner, Button } from '@primer/react';
|
|
8
8
|
import { ListUnorderedIcon } from '@primer/octicons-react';
|
|
9
|
-
import { useQuery } from '@tanstack/react-query';
|
|
10
9
|
import ReactECharts from 'echarts-for-react';
|
|
11
10
|
import { useState } from 'react';
|
|
12
|
-
function getLocalApiBase() {
|
|
13
|
-
if (typeof window === 'undefined') {
|
|
14
|
-
return '';
|
|
15
|
-
}
|
|
16
|
-
const host = window.location.hostname;
|
|
17
|
-
return host === 'localhost' || host === '127.0.0.1'
|
|
18
|
-
? 'http://127.0.0.1:8765'
|
|
19
|
-
: '';
|
|
20
|
-
}
|
|
21
11
|
/**
|
|
22
12
|
* Format token count for display
|
|
23
13
|
*/
|
|
@@ -33,23 +23,14 @@ function formatTokens(tokens) {
|
|
|
33
23
|
/**
|
|
34
24
|
* ContextDistribution component displays context distribution as a treemap.
|
|
35
25
|
*/
|
|
36
|
-
export function ContextDistribution({ agentId, height = '250px', }) {
|
|
26
|
+
export function ContextDistribution({ agentId, height = '250px', liveData, }) {
|
|
37
27
|
const [showDetails, setShowDetails] = useState(false);
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
throw new Error('Failed to fetch context snapshot');
|
|
45
|
-
}
|
|
46
|
-
return response.json();
|
|
47
|
-
},
|
|
48
|
-
refetchInterval: 10000, // Refresh every 10 seconds
|
|
49
|
-
refetchOnMount: 'always',
|
|
50
|
-
staleTime: 0,
|
|
51
|
-
});
|
|
52
|
-
if (isLoading) {
|
|
28
|
+
const hasLiveData = liveData !== undefined;
|
|
29
|
+
// REST polling removed — data comes exclusively via WS `agent.snapshot`.
|
|
30
|
+
const snapshotData = liveData;
|
|
31
|
+
const showLoading = !hasLiveData;
|
|
32
|
+
const hasError = false;
|
|
33
|
+
if (showLoading) {
|
|
53
34
|
return (_jsxs(Box, { sx: {
|
|
54
35
|
p: 3,
|
|
55
36
|
display: 'flex',
|
|
@@ -58,7 +39,7 @@ export function ContextDistribution({ agentId, height = '250px', }) {
|
|
|
58
39
|
height,
|
|
59
40
|
}, children: [_jsx(Spinner, { size: "small" }), _jsx(Text, { sx: { ml: 2, fontSize: 1, color: 'fg.muted' }, children: "Loading context distribution..." })] }));
|
|
60
41
|
}
|
|
61
|
-
if (
|
|
42
|
+
if (hasError || !snapshotData) {
|
|
62
43
|
return (_jsx(Box, { sx: {
|
|
63
44
|
p: 3,
|
|
64
45
|
bg: 'canvas.subtle',
|
|
@@ -73,9 +73,11 @@ export interface ContextInspectorProps {
|
|
|
73
73
|
agentId: string;
|
|
74
74
|
/** API base URL for fetching context data */
|
|
75
75
|
apiBase?: string;
|
|
76
|
+
/** Live full-context data from WS — bypasses REST polling when provided */
|
|
77
|
+
liveData?: FullContextResponse | null;
|
|
76
78
|
}
|
|
77
79
|
/**
|
|
78
80
|
* ContextInspector component displays full detailed context snapshot.
|
|
79
81
|
*/
|
|
80
|
-
export declare function ContextInspector({ agentId, apiBase }: ContextInspectorProps): import("react/jsx-runtime").JSX.Element;
|
|
82
|
+
export declare function ContextInspector({ agentId, apiBase, liveData, }: ContextInspectorProps): import("react/jsx-runtime").JSX.Element;
|
|
81
83
|
export default ContextInspector;
|
|
@@ -5,29 +5,15 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
5
5
|
* ContextInspector component - Shows detailed context snapshot with full tool schemas,
|
|
6
6
|
* message history with in_context flags, and model configuration.
|
|
7
7
|
*/
|
|
8
|
-
import { Text,
|
|
8
|
+
import { Text, Button, Label, ProgressBar } from '@primer/react';
|
|
9
9
|
import { Box } from '@datalayer/primer-addons';
|
|
10
10
|
import { AiModelIcon, TerminalIcon, CommentDiscussionIcon, DatabaseIcon, KeyIcon, CodeIcon, CheckCircleIcon, XCircleIcon, ChevronDownIcon, ChevronRightIcon, InfoIcon, } from '@primer/octicons-react';
|
|
11
|
-
import {
|
|
12
|
-
import React, { useState, useMemo, useEffect } from 'react';
|
|
13
|
-
const RETRY_INTERVAL_SECONDS = 5;
|
|
11
|
+
import React, { useState, useMemo } from 'react';
|
|
14
12
|
/**
|
|
15
13
|
* Get the API base URL for fetching context data.
|
|
16
14
|
* If apiBase prop is provided, use it.
|
|
17
15
|
* Otherwise, fall back to localhost for local development.
|
|
18
16
|
*/
|
|
19
|
-
function getApiBase(apiBase) {
|
|
20
|
-
if (apiBase) {
|
|
21
|
-
return apiBase;
|
|
22
|
-
}
|
|
23
|
-
if (typeof window === 'undefined') {
|
|
24
|
-
return '';
|
|
25
|
-
}
|
|
26
|
-
const host = window.location.hostname;
|
|
27
|
-
return host === 'localhost' || host === '127.0.0.1'
|
|
28
|
-
? 'http://127.0.0.1:8765'
|
|
29
|
-
: '';
|
|
30
|
-
}
|
|
31
17
|
/**
|
|
32
18
|
* Format token count for display
|
|
33
19
|
*/
|
|
@@ -143,34 +129,10 @@ function MessageDetailView({ message }) {
|
|
|
143
129
|
/**
|
|
144
130
|
* ContextInspector component displays full detailed context snapshot.
|
|
145
131
|
*/
|
|
146
|
-
export function ContextInspector({ agentId, apiBase }) {
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
queryFn: async () => {
|
|
151
|
-
const base = getApiBase(apiBase);
|
|
152
|
-
const response = await fetch(`${base}/api/v1/configure/agents/${encodeURIComponent(agentId)}/full-context`);
|
|
153
|
-
if (!response.ok) {
|
|
154
|
-
throw new Error('Failed to fetch full context');
|
|
155
|
-
}
|
|
156
|
-
return response.json();
|
|
157
|
-
},
|
|
158
|
-
refetchInterval: RETRY_INTERVAL_SECONDS * 1000,
|
|
159
|
-
refetchOnMount: 'always',
|
|
160
|
-
staleTime: 0,
|
|
161
|
-
});
|
|
162
|
-
const hasRetryError = Boolean(error) || Boolean(contextData?.error);
|
|
163
|
-
useEffect(() => {
|
|
164
|
-
if (!hasRetryError) {
|
|
165
|
-
setRetryCountdown(RETRY_INTERVAL_SECONDS);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
setRetryCountdown(RETRY_INTERVAL_SECONDS);
|
|
169
|
-
const timer = window.setInterval(() => {
|
|
170
|
-
setRetryCountdown(prev => prev <= 1 ? RETRY_INTERVAL_SECONDS : prev - 1);
|
|
171
|
-
}, 1000);
|
|
172
|
-
return () => window.clearInterval(timer);
|
|
173
|
-
}, [hasRetryError]);
|
|
132
|
+
export function ContextInspector({ agentId, apiBase, liveData, }) {
|
|
133
|
+
const hasLiveData = liveData !== undefined;
|
|
134
|
+
// REST polling removed — data comes exclusively via WS `agent.snapshot`.
|
|
135
|
+
const contextData = liveData;
|
|
174
136
|
// Separate messages by in_context status
|
|
175
137
|
const { inContextMessages, outOfContextMessages } = useMemo(() => {
|
|
176
138
|
if (!contextData?.messages) {
|
|
@@ -181,30 +143,28 @@ export function ContextInspector({ agentId, apiBase }) {
|
|
|
181
143
|
outOfContextMessages: contextData.messages.filter(m => !m.inContext),
|
|
182
144
|
};
|
|
183
145
|
}, [contextData?.messages]);
|
|
184
|
-
|
|
185
|
-
|
|
146
|
+
const messageHistoryTokens = useMemo(() => {
|
|
147
|
+
if (!contextData?.messages) {
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
return contextData.messages.reduce((sum, message) => sum + (message.estimatedTokens || 0), 0);
|
|
151
|
+
}, [contextData?.messages]);
|
|
152
|
+
if (!hasLiveData) {
|
|
153
|
+
return (_jsx(Box, { sx: {
|
|
186
154
|
p: 3,
|
|
187
155
|
display: 'flex',
|
|
188
156
|
alignItems: 'center',
|
|
189
157
|
justifyContent: 'center',
|
|
190
|
-
}, children:
|
|
158
|
+
}, children: _jsx(Text, { sx: { color: 'fg.muted' }, children: "Waiting for context data from WebSocket stream..." }) }));
|
|
191
159
|
}
|
|
192
|
-
if (
|
|
160
|
+
if (!contextData) {
|
|
193
161
|
return (_jsx(Box, { sx: {
|
|
194
162
|
p: 3,
|
|
195
163
|
bg: 'attention.subtle',
|
|
196
164
|
borderRadius: 2,
|
|
197
165
|
border: '1px solid',
|
|
198
166
|
borderColor: 'attention.muted',
|
|
199
|
-
}, children:
|
|
200
|
-
display: 'flex',
|
|
201
|
-
alignItems: 'center',
|
|
202
|
-
justifyContent: 'space-between',
|
|
203
|
-
gap: 2,
|
|
204
|
-
}, children: [_jsxs(Text, { sx: { color: 'attention.fg' }, children: ["Service not available for context snapshot. Retrying in", ' ', retryCountdown, " second", retryCountdown === 1 ? '' : 's', "..."] }), _jsx(Button, { size: "small", variant: "invisible", onClick: () => {
|
|
205
|
-
setRetryCountdown(RETRY_INTERVAL_SECONDS);
|
|
206
|
-
void refetch();
|
|
207
|
-
}, children: "Retry now" })] }) }));
|
|
167
|
+
}, children: _jsx(Text, { sx: { color: 'attention.fg' }, children: "No context data available." }) }));
|
|
208
168
|
}
|
|
209
169
|
if (contextData.error) {
|
|
210
170
|
return (_jsx(Box, { sx: {
|
|
@@ -213,15 +173,7 @@ export function ContextInspector({ agentId, apiBase }) {
|
|
|
213
173
|
borderRadius: 2,
|
|
214
174
|
border: '1px solid',
|
|
215
175
|
borderColor: 'attention.muted',
|
|
216
|
-
}, children:
|
|
217
|
-
display: 'flex',
|
|
218
|
-
alignItems: 'center',
|
|
219
|
-
justifyContent: 'space-between',
|
|
220
|
-
gap: 2,
|
|
221
|
-
}, children: [_jsx(Text, { sx: { color: 'attention.fg' }, children: `${contextData.error} Retrying in ${retryCountdown} second${retryCountdown === 1 ? '' : 's'}...` }), _jsx(Button, { size: "small", variant: "invisible", onClick: () => {
|
|
222
|
-
setRetryCountdown(RETRY_INTERVAL_SECONDS);
|
|
223
|
-
void refetch();
|
|
224
|
-
}, children: "Retry now" })] }) }));
|
|
176
|
+
}, children: _jsx(Text, { sx: { color: 'attention.fg' }, children: contextData.error }) }));
|
|
225
177
|
}
|
|
226
178
|
const { tokenSummary, modelConfiguration } = contextData;
|
|
227
179
|
return (_jsxs(Box, { children: [_jsxs(Box, { sx: { mb: 3 }, children: [_jsxs(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: ["Total usage: ", formatTokens(tokenSummary.total), " /", ' ', formatTokens(tokenSummary.contextWindow), " (", Math.round(tokenSummary.usagePercent), "%)"] }), _jsx(ProgressBar, { progress: Math.min(tokenSummary.usagePercent, 100), sx: { mt: 2, height: 8 }, bg: tokenSummary.usagePercent > 90
|
|
@@ -258,7 +210,7 @@ export function ContextInspector({ agentId, apiBase }) {
|
|
|
258
210
|
wordBreak: 'break-word',
|
|
259
211
|
maxHeight: 200,
|
|
260
212
|
overflow: 'auto',
|
|
261
|
-
}, children: prompt.content })] }, idx)))) }), _jsx(CollapsibleSection, { title: "
|
|
213
|
+
}, children: prompt.content })] }, idx)))) }), _jsx(CollapsibleSection, { title: "Tool Definitions", icon: TerminalIcon, count: contextData.tools.length, tokens: contextData.toolTokens, children: contextData.tools.length === 0 ? (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "No tools configured" })) : (contextData.tools.map((tool, idx) => (_jsx(ToolDetailView, { tool: tool }, idx)))) }), _jsx(CollapsibleSection, { title: "Message History", icon: CommentDiscussionIcon, count: contextData.messages.length, tokens: messageHistoryTokens, children: contextData.messages.length === 0 ? (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "No messages yet" })) : (_jsxs(_Fragment, { children: [outOfContextMessages.length > 0 && (_jsxs(Box, { sx: { mb: 3 }, children: [_jsxs(Text, { sx: {
|
|
262
214
|
fontWeight: 'semibold',
|
|
263
215
|
fontSize: 1,
|
|
264
216
|
color: 'fg.muted',
|
|
@@ -98,6 +98,8 @@ export interface ContextPanelProps {
|
|
|
98
98
|
agentId: string;
|
|
99
99
|
/** API base URL for fetching context data */
|
|
100
100
|
apiBase?: string;
|
|
101
|
+
/** Live context snapshot pushed by websocket; skips internal polling when provided */
|
|
102
|
+
liveData?: ContextSnapshotResponse | null;
|
|
101
103
|
/** Number of messages in conversation (from chat store) */
|
|
102
104
|
messageCount?: number;
|
|
103
105
|
/** Default view mode */
|
|
@@ -108,5 +110,5 @@ export interface ContextPanelProps {
|
|
|
108
110
|
/**
|
|
109
111
|
* ContextPanel component - unified context usage display.
|
|
110
112
|
*/
|
|
111
|
-
export declare function ContextPanel({ agentId, apiBase, messageCount, defaultView, chartHeight, }: ContextPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
113
|
+
export declare function ContextPanel({ agentId, apiBase, liveData, messageCount, defaultView, chartHeight, }: ContextPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
112
114
|
export default ContextPanel;
|
|
@@ -7,12 +7,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
7
7
|
* - Token distribution treemap
|
|
8
8
|
* - Historic usage time-series chart
|
|
9
9
|
*/
|
|
10
|
-
import { CommentDiscussionIcon, DatabaseIcon, FileIcon, ToolsIcon, ClockIcon, GraphIcon, ListUnorderedIcon, } from '@primer/octicons-react';
|
|
10
|
+
import { CommentDiscussionIcon, DatabaseIcon, FileIcon, ToolsIcon, ClockIcon, GraphIcon, AppsIcon, ListUnorderedIcon, DownloadIcon, } from '@primer/octicons-react';
|
|
11
11
|
import { Heading, Text, ProgressBar, Spinner, Button, SegmentedControl, } from '@primer/react';
|
|
12
12
|
import { Box } from '@datalayer/primer-addons';
|
|
13
|
-
import { useQuery } from '@tanstack/react-query';
|
|
14
13
|
import ReactECharts from 'echarts-for-react';
|
|
15
|
-
import { useState, useMemo
|
|
14
|
+
import { useState, useMemo } from 'react';
|
|
16
15
|
/**
|
|
17
16
|
* Format token count for display
|
|
18
17
|
*/
|
|
@@ -29,8 +28,11 @@ function formatTokens(tokens) {
|
|
|
29
28
|
* Format duration
|
|
30
29
|
*/
|
|
31
30
|
function formatDuration(seconds) {
|
|
31
|
+
if (!Number.isFinite(seconds) || Number.isNaN(seconds) || seconds < 0) {
|
|
32
|
+
return '0ms';
|
|
33
|
+
}
|
|
32
34
|
if (seconds < 1) {
|
|
33
|
-
return `${Math.round(seconds * 1000)}ms`;
|
|
35
|
+
return `${Math.max(0, Math.round(seconds * 1000))}ms`;
|
|
34
36
|
}
|
|
35
37
|
if (seconds < 60) {
|
|
36
38
|
return `${seconds.toFixed(1)}s`;
|
|
@@ -39,6 +41,89 @@ function formatDuration(seconds) {
|
|
|
39
41
|
const secs = Math.round(seconds % 60);
|
|
40
42
|
return `${minutes}m ${secs}s`;
|
|
41
43
|
}
|
|
44
|
+
function csvCell(value) {
|
|
45
|
+
const text = String(value ?? '');
|
|
46
|
+
if (/[",\n]/.test(text)) {
|
|
47
|
+
return `"${text.replace(/"/g, '""')}"`;
|
|
48
|
+
}
|
|
49
|
+
return text;
|
|
50
|
+
}
|
|
51
|
+
function downloadContextUsageAsCSV(data) {
|
|
52
|
+
const rows = [];
|
|
53
|
+
rows.push(['Context Usage Snapshot for Agent', data.agentId]);
|
|
54
|
+
rows.push(['Generated At', new Date().toISOString()]);
|
|
55
|
+
rows.push([]);
|
|
56
|
+
rows.push(['Summary']);
|
|
57
|
+
rows.push(['Total Tokens', data.totalTokens]);
|
|
58
|
+
rows.push(['Context Window', data.contextWindow]);
|
|
59
|
+
rows.push(['System Prompt Tokens', data.systemPromptTokens]);
|
|
60
|
+
rows.push(['Tool Tokens', data.toolTokens]);
|
|
61
|
+
rows.push(['History Tokens', data.historyTokens]);
|
|
62
|
+
rows.push(['Current Message Tokens', data.currentMessageTokens]);
|
|
63
|
+
rows.push(['User Message Tokens', data.userMessageTokens]);
|
|
64
|
+
rows.push(['Assistant Message Tokens', data.assistantMessageTokens]);
|
|
65
|
+
rows.push([]);
|
|
66
|
+
if (data.sessionUsage) {
|
|
67
|
+
rows.push(['Session Usage']);
|
|
68
|
+
rows.push(['Input Tokens', data.sessionUsage.inputTokens]);
|
|
69
|
+
rows.push(['Output Tokens', data.sessionUsage.outputTokens]);
|
|
70
|
+
rows.push(['Requests', data.sessionUsage.requests]);
|
|
71
|
+
rows.push(['Tool Calls', data.sessionUsage.toolCalls]);
|
|
72
|
+
rows.push(['Turns', data.sessionUsage.turns]);
|
|
73
|
+
rows.push(['Duration Seconds', data.sessionUsage.durationSeconds]);
|
|
74
|
+
rows.push([]);
|
|
75
|
+
}
|
|
76
|
+
if (data.turnUsage) {
|
|
77
|
+
rows.push(['Last Turn Usage']);
|
|
78
|
+
rows.push(['Input Tokens', data.turnUsage.inputTokens]);
|
|
79
|
+
rows.push(['Output Tokens', data.turnUsage.outputTokens]);
|
|
80
|
+
rows.push(['Requests', data.turnUsage.requests]);
|
|
81
|
+
rows.push(['Tool Calls', data.turnUsage.toolCalls]);
|
|
82
|
+
rows.push(['Duration Seconds', data.turnUsage.durationSeconds]);
|
|
83
|
+
rows.push([]);
|
|
84
|
+
}
|
|
85
|
+
rows.push(['Distribution']);
|
|
86
|
+
rows.push(['Category', 'Tokens']);
|
|
87
|
+
for (const category of data.distribution?.children ?? []) {
|
|
88
|
+
rows.push([category.name, category.value]);
|
|
89
|
+
}
|
|
90
|
+
rows.push([]);
|
|
91
|
+
if (data.perRequestUsage.length > 0) {
|
|
92
|
+
rows.push(['Per Request Usage']);
|
|
93
|
+
rows.push([
|
|
94
|
+
'Request #',
|
|
95
|
+
'Input Tokens',
|
|
96
|
+
'Output Tokens',
|
|
97
|
+
'Duration Ms',
|
|
98
|
+
'Tool Names',
|
|
99
|
+
'Timestamp',
|
|
100
|
+
'Turn ID',
|
|
101
|
+
]);
|
|
102
|
+
for (const request of data.perRequestUsage) {
|
|
103
|
+
rows.push([
|
|
104
|
+
request.requestNum,
|
|
105
|
+
request.inputTokens,
|
|
106
|
+
request.outputTokens,
|
|
107
|
+
request.durationMs,
|
|
108
|
+
request.toolNames.join('; '),
|
|
109
|
+
request.timestamp ?? '',
|
|
110
|
+
request.turnId ?? '',
|
|
111
|
+
]);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const csv = rows.map(row => row.map(csvCell).join(',')).join('\n');
|
|
115
|
+
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
|
|
116
|
+
const url = URL.createObjectURL(blob);
|
|
117
|
+
const link = document.createElement('a');
|
|
118
|
+
link.href = url;
|
|
119
|
+
const ts = new Date().toISOString().replace(/[:.]/g, '-');
|
|
120
|
+
link.download = `context-usage-${data.agentId}-${ts}.csv`;
|
|
121
|
+
link.style.display = 'none';
|
|
122
|
+
document.body.appendChild(link);
|
|
123
|
+
link.click();
|
|
124
|
+
document.body.removeChild(link);
|
|
125
|
+
URL.revokeObjectURL(url);
|
|
126
|
+
}
|
|
42
127
|
/**
|
|
43
128
|
* Get icon for context category
|
|
44
129
|
*/
|
|
@@ -59,56 +144,17 @@ function getCategoryIcon(name) {
|
|
|
59
144
|
return ClockIcon;
|
|
60
145
|
}
|
|
61
146
|
}
|
|
62
|
-
const RETRY_INTERVAL_SECONDS = 5;
|
|
63
|
-
/**
|
|
64
|
-
* Get the API base URL for fetching context data.
|
|
65
|
-
* If apiBase prop is provided, use it.
|
|
66
|
-
* Otherwise, fall back to localhost for local development.
|
|
67
|
-
*/
|
|
68
|
-
function getApiBase(apiBase) {
|
|
69
|
-
if (apiBase) {
|
|
70
|
-
return apiBase;
|
|
71
|
-
}
|
|
72
|
-
if (typeof window === 'undefined') {
|
|
73
|
-
return '';
|
|
74
|
-
}
|
|
75
|
-
const host = window.location.hostname;
|
|
76
|
-
return host === 'localhost' || host === '127.0.0.1'
|
|
77
|
-
? 'http://127.0.0.1:8765'
|
|
78
|
-
: '';
|
|
79
|
-
}
|
|
80
147
|
/**
|
|
81
148
|
* ContextPanel component - unified context usage display.
|
|
82
149
|
*/
|
|
83
|
-
export function ContextPanel({ agentId, apiBase, messageCount = 0, defaultView = 'overview', chartHeight = '200px', }) {
|
|
150
|
+
export function ContextPanel({ agentId, apiBase, liveData, messageCount = 0, defaultView = 'overview', chartHeight = '200px', }) {
|
|
84
151
|
const [viewMode, setViewMode] = useState(defaultView);
|
|
85
152
|
const [showDetails, setShowDetails] = useState(false);
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const response = await fetch(`${base}/api/v1/configure/agents/${encodeURIComponent(agentId)}/context-snapshot`);
|
|
92
|
-
if (!response.ok) {
|
|
93
|
-
throw new Error('Failed to fetch context snapshot');
|
|
94
|
-
}
|
|
95
|
-
return response.json();
|
|
96
|
-
},
|
|
97
|
-
refetchInterval: RETRY_INTERVAL_SECONDS * 1000,
|
|
98
|
-
refetchOnMount: 'always',
|
|
99
|
-
staleTime: 0,
|
|
100
|
-
});
|
|
101
|
-
useEffect(() => {
|
|
102
|
-
if (!error) {
|
|
103
|
-
setRetryCountdown(RETRY_INTERVAL_SECONDS);
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
setRetryCountdown(RETRY_INTERVAL_SECONDS);
|
|
107
|
-
const timer = window.setInterval(() => {
|
|
108
|
-
setRetryCountdown(prev => prev <= 1 ? RETRY_INTERVAL_SECONDS : prev - 1);
|
|
109
|
-
}, 1000);
|
|
110
|
-
return () => window.clearInterval(timer);
|
|
111
|
-
}, [error]);
|
|
153
|
+
const hasLiveData = liveData !== undefined;
|
|
154
|
+
// REST polling removed — data comes exclusively via WS `agent.snapshot`.
|
|
155
|
+
const snapshotData = liveData;
|
|
156
|
+
const showLoading = !hasLiveData;
|
|
157
|
+
const hasError = false;
|
|
112
158
|
// Build historic usage chart data from perRequestUsage
|
|
113
159
|
const historyChartOption = useMemo(() => {
|
|
114
160
|
if (!snapshotData?.perRequestUsage ||
|
|
@@ -251,7 +297,7 @@ export function ContextPanel({ agentId, apiBase, messageCount = 0, defaultView =
|
|
|
251
297
|
};
|
|
252
298
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
253
299
|
}, [snapshotData?.distribution]);
|
|
254
|
-
if (
|
|
300
|
+
if (showLoading) {
|
|
255
301
|
return (_jsxs(Box, { children: [_jsx(Heading, { as: "h4", sx: {
|
|
256
302
|
fontSize: 1,
|
|
257
303
|
fontWeight: 'semibold',
|
|
@@ -268,7 +314,7 @@ export function ContextPanel({ agentId, apiBase, messageCount = 0, defaultView =
|
|
|
268
314
|
gap: 2,
|
|
269
315
|
}, children: [_jsx(Spinner, { size: "small" }), _jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Loading context details..." })] })] }));
|
|
270
316
|
}
|
|
271
|
-
if (
|
|
317
|
+
if (hasError || !snapshotData) {
|
|
272
318
|
return (_jsxs(Box, { children: [_jsx(Heading, { as: "h4", sx: {
|
|
273
319
|
fontSize: 1,
|
|
274
320
|
fontWeight: 'semibold',
|
|
@@ -280,19 +326,13 @@ export function ContextPanel({ agentId, apiBase, messageCount = 0, defaultView =
|
|
|
280
326
|
borderRadius: 2,
|
|
281
327
|
border: '1px solid',
|
|
282
328
|
borderColor: 'attention.muted',
|
|
283
|
-
}, children:
|
|
284
|
-
display: 'flex',
|
|
285
|
-
alignItems: 'center',
|
|
286
|
-
justifyContent: 'space-between',
|
|
287
|
-
gap: 2,
|
|
288
|
-
}, children: [_jsxs(Text, { sx: { fontSize: 1, color: 'attention.fg' }, children: ["Service not available for context usage. Retrying in", ' ', retryCountdown, " second", retryCountdown === 1 ? '' : 's', "..."] }), _jsx(Button, { size: "small", variant: "invisible", onClick: () => {
|
|
289
|
-
setRetryCountdown(RETRY_INTERVAL_SECONDS);
|
|
290
|
-
void refetch();
|
|
291
|
-
}, children: "Retry now" })] }) })] }));
|
|
329
|
+
}, children: _jsx(Text, { sx: { fontSize: 1, color: 'attention.fg' }, children: "Waiting for context data from WebSocket stream..." }) })] }));
|
|
292
330
|
}
|
|
293
331
|
const { totalTokens, contextWindow, sessionUsage, turnUsage, distribution } = snapshotData;
|
|
332
|
+
const sentMessageCount = messageCount > 0
|
|
333
|
+
? messageCount
|
|
334
|
+
: Math.max(sessionUsage?.turns ?? 0, snapshotData.perRequestUsage?.length > 0 ? 1 : 0);
|
|
294
335
|
const hasDistributionData = distribution?.children && distribution.children.length > 0;
|
|
295
|
-
const hasHistoryData = snapshotData.perRequestUsage && snapshotData.perRequestUsage.length > 0;
|
|
296
336
|
return (_jsxs(Box, { children: [_jsxs(Box, { sx: {
|
|
297
337
|
display: 'flex',
|
|
298
338
|
justifyContent: 'space-between',
|
|
@@ -302,7 +342,7 @@ export function ContextPanel({ agentId, apiBase, messageCount = 0, defaultView =
|
|
|
302
342
|
fontSize: 1,
|
|
303
343
|
fontWeight: 'semibold',
|
|
304
344
|
color: 'fg.muted',
|
|
305
|
-
}, children: "Context Usage" }),
|
|
345
|
+
}, children: "Context Usage" }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [sentMessageCount > 0 && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: [sentMessageCount, ' ', sentMessageCount === 1 ? 'message sent' : 'messages sent'] })), _jsx(Button, { size: "small", variant: "invisible", leadingVisual: DownloadIcon, onClick: () => downloadContextUsageAsCSV(snapshotData), children: "Download" })] })] }), _jsxs(Box, { sx: {
|
|
306
346
|
p: 3,
|
|
307
347
|
bg: 'canvas.subtle',
|
|
308
348
|
borderRadius: 2,
|
|
@@ -337,7 +377,7 @@ export function ContextPanel({ agentId, apiBase, messageCount = 0, defaultView =
|
|
|
337
377
|
}, children: [_jsxs(SegmentedControl, { "aria-label": "View mode", size: "small", onChange: index => {
|
|
338
378
|
const modes = ['overview', 'distribution', 'history'];
|
|
339
379
|
setViewMode(modes[index]);
|
|
340
|
-
}, children: [_jsx(SegmentedControl.
|
|
380
|
+
}, children: [_jsx(SegmentedControl.IconButton, { "aria-label": "Overview", selected: viewMode === 'overview', icon: ListUnorderedIcon }), _jsx(SegmentedControl.IconButton, { "aria-label": "Distribution", selected: viewMode === 'distribution', icon: AppsIcon, disabled: !hasDistributionData }), _jsx(SegmentedControl.IconButton, { "aria-label": "History", selected: viewMode === 'history', icon: GraphIcon })] }), viewMode === 'overview' && (_jsx(Button, { size: "small", variant: "invisible", onClick: () => setShowDetails(!showDetails), children: showDetails ? 'Less' : 'More' }))] }), viewMode === 'overview' && (_jsxs(Box, { children: [_jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [hasDistributionData &&
|
|
341
381
|
distribution.children.map(category => {
|
|
342
382
|
const CategoryIcon = getCategoryIcon(category.name);
|
|
343
383
|
const categoryPercent = (category.value / contextWindow) * 100;
|
|
@@ -384,6 +424,6 @@ export function ContextPanel({ agentId, apiBase, messageCount = 0, defaultView =
|
|
|
384
424
|
py: 1,
|
|
385
425
|
borderBottom: idx < 9 ? '1px solid' : 'none',
|
|
386
426
|
borderColor: 'border.muted',
|
|
387
|
-
}, children: [_jsxs(Text, { sx: { fontWeight: 'semibold', minWidth: 30 }, children: ["#", req.requestNum] }), _jsxs(Text, { sx: { color: '#3B82F6' }, children: ["\u2193", formatTokens(req.inputTokens)] }), _jsxs(Text, { sx: { color: '#10B981' }, children: ["\u2191", formatTokens(req.outputTokens)] }), req.toolNames.length > 0 && (_jsxs(Text, { sx: { color: 'fg.muted' }, children: ["\uD83D\uDD27 ", req.toolNames.join(', ')] }))] }, req.requestNum))) }))] }))] })] }));
|
|
427
|
+
}, children: [_jsxs(Text, { sx: { fontWeight: 'semibold', minWidth: 30 }, children: ["#", req.requestNum] }), _jsxs(Text, { sx: { color: '#3B82F6' }, children: ["\u2193", formatTokens(req.inputTokens)] }), _jsxs(Text, { sx: { color: '#10B981' }, children: ["\u2191", formatTokens(req.outputTokens)] }), req.toolNames.length > 0 && (_jsxs(Text, { sx: { color: 'fg.muted' }, children: ["\uD83D\uDD27 ", req.toolNames.join(', ')] }))] }, req.requestNum))) }))] })), viewMode === 'history' && !historyChartOption && (_jsx(Box, { sx: { py: 3 }, children: _jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "No history" }) }))] })] }));
|
|
388
428
|
}
|
|
389
429
|
export default ContextPanel;
|
|
@@ -25,9 +25,11 @@ export interface ContextDetailsResponse {
|
|
|
25
25
|
export interface ContextUsageProps {
|
|
26
26
|
/** Agent ID for fetching context details (required) */
|
|
27
27
|
agentId: string;
|
|
28
|
+
/** Optional base URL override (defaults to local 8765 or same-origin) */
|
|
29
|
+
baseUrl?: string;
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
30
32
|
* ContextUsage component displays token usage breakdown by category.
|
|
31
33
|
*/
|
|
32
|
-
export declare function ContextUsage({ agentId }: ContextUsageProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
export declare function ContextUsage({ agentId, baseUrl }: ContextUsageProps): import("react/jsx-runtime").JSX.Element;
|
|
33
35
|
export default ContextUsage;
|
|
@@ -52,11 +52,11 @@ function getCategoryIcon(name) {
|
|
|
52
52
|
/**
|
|
53
53
|
* ContextUsage component displays token usage breakdown by category.
|
|
54
54
|
*/
|
|
55
|
-
export function ContextUsage({ agentId }) {
|
|
55
|
+
export function ContextUsage({ agentId, baseUrl }) {
|
|
56
56
|
const { data: contextData, isLoading, error, } = useQuery({
|
|
57
|
-
queryKey: ['context-details', agentId],
|
|
57
|
+
queryKey: ['context-details', agentId, baseUrl],
|
|
58
58
|
queryFn: async () => {
|
|
59
|
-
const apiBase = getLocalApiBase();
|
|
59
|
+
const apiBase = baseUrl || getLocalApiBase();
|
|
60
60
|
const response = await fetch(`${apiBase}/api/v1/configure/agents/${encodeURIComponent(agentId)}/context-details`);
|
|
61
61
|
if (!response.ok) {
|
|
62
62
|
throw new Error('Failed to fetch context details');
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export interface CostUsageResponse {
|
|
5
5
|
agentId: string;
|
|
6
|
-
/** Cost for the
|
|
7
|
-
|
|
6
|
+
/** Cost for the last completed turn in USD */
|
|
7
|
+
lastTurnCostUsd: number;
|
|
8
8
|
/** Total cumulative cost in USD */
|
|
9
9
|
cumulativeCostUsd: number;
|
|
10
10
|
/** Per-run budget limit (from guardrails) */
|
|
@@ -23,15 +23,21 @@ export interface CostUsageResponse {
|
|
|
23
23
|
costUsd: number;
|
|
24
24
|
requests: number;
|
|
25
25
|
}>;
|
|
26
|
+
/** Optional run traces with pricing resolution info */
|
|
27
|
+
runs?: Array<{
|
|
28
|
+
pricingResolved: boolean;
|
|
29
|
+
}>;
|
|
26
30
|
}
|
|
27
31
|
export interface CostTrackerProps {
|
|
28
32
|
/** Agent ID for fetching cost data */
|
|
29
33
|
agentId: string;
|
|
30
34
|
/** Compact mode — show only the summary bar */
|
|
31
35
|
compact?: boolean;
|
|
36
|
+
/** Live cost data pushed by websocket (single source of truth). */
|
|
37
|
+
liveData?: CostUsageResponse | null;
|
|
32
38
|
}
|
|
33
39
|
/**
|
|
34
40
|
* Displays running cost and budget utilization for an agent.
|
|
35
41
|
*/
|
|
36
|
-
export declare function CostTracker({ agentId, compact }: CostTrackerProps): import("react/jsx-runtime").JSX.Element;
|
|
42
|
+
export declare function CostTracker({ agentId: _agentId, compact, liveData, }: CostTrackerProps): import("react/jsx-runtime").JSX.Element;
|
|
37
43
|
export default CostTracker;
|