@datalayer/agent-runtimes 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -119
- 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 -104
- 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 +1118 -141
- 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 +110 -102
- 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 +48 -19
- package/lib/client/AgentsMixin.js +115 -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 +55 -26
- package/lib/components/OutputCard.js +21 -7
- package/lib/components/ToolApprovalCard.js +20 -2
- 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 +14 -34
- package/lib/examples/AgentCodemodeExample.d.ts +4 -6
- package/lib/examples/AgentCodemodeExample.js +591 -175
- package/lib/examples/AgentEvalsExample.js +13 -23
- package/lib/examples/AgentGuardrailsExample.js +371 -71
- 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 +14 -24
- package/lib/examples/AgentMonitoringExample.js +261 -206
- package/lib/examples/AgentNotificationsExample.js +50 -24
- package/lib/examples/AgentOtelExample.js +2 -3
- package/lib/examples/AgentOutputsExample.d.ts +11 -6
- package/lib/examples/AgentOutputsExample.js +383 -88
- 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 +69 -47
- package/lib/examples/AgentSkillsExample.js +92 -106
- 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 +30 -493
- package/lib/examples/AgentTriggersExample.js +1067 -246
- package/lib/examples/ChatCustomExample.js +11 -24
- package/lib/examples/ChatExample.js +9 -34
- 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/ErrorView.d.ts +14 -0
- package/lib/examples/components/ErrorView.js +20 -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 +5 -0
- package/lib/examples/components/index.js +5 -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.d.ts +1 -0
- package/lib/examples/main.js +218 -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 +9 -0
- package/lib/protocols/VercelAIAdapter.js +144 -26
- package/lib/shims/json5.d.ts +4 -0
- package/lib/shims/json5.js +8 -0
- package/lib/specs/agents/agents.d.ts +10 -0
- package/lib/specs/agents/agents.js +752 -24
- package/lib/specs/envvars.d.ts +1 -0
- package/lib/specs/envvars.js +11 -0
- package/lib/specs/events.d.ts +1 -0
- package/lib/specs/events.js +1 -0
- package/lib/specs/index.d.ts +1 -0
- package/lib/specs/index.js +1 -0
- 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 +23 -5
- package/lib/specs/tools.js +3 -0
- 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/types/tools.d.ts +2 -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 +106 -7
- package/scripts/codegen/generate_events.py +47 -17
- package/scripts/codegen/generate_personas.py +319 -0
- package/scripts/codegen/generate_skills.py +9 -9
- package/scripts/codegen/generate_tools.py +20 -0
- package/scripts/sync-jupyter.sh +26 -7
- package/style/primer-primitives.css +1 -6
- 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/scripts/codegen/__pycache__/generate_envvars.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_evals.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_guardrails.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_mcp_servers.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_memory.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_models.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_notifications.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_outputs.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_skills.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_teams.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_tools.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_triggers.cpython-313.pyc +0 -0
- /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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
/*
|
|
3
3
|
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
@@ -6,48 +6,241 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
/**
|
|
7
7
|
* AgentOutputsExample
|
|
8
8
|
*
|
|
9
|
-
* Demonstrates rich output rendering for agent responses
|
|
10
|
-
*
|
|
9
|
+
* Demonstrates rich output rendering for agent responses. The agent (spec
|
|
10
|
+
* `demo-outputs`) is prompted to return exactly one of four output types per
|
|
11
|
+
* response:
|
|
12
|
+
* - TABLE → GitHub-flavored Markdown table
|
|
13
|
+
* - JSON → ```json fenced block
|
|
14
|
+
* - CHART → ```json fenced block whose first line is `// chart` (ECharts)
|
|
15
|
+
* - FILE → fenced block whose info string is a file extension and
|
|
16
|
+
* whose first line is `# filename: <name.ext>`
|
|
11
17
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* output formats (table, JSON, chart, file)
|
|
18
|
+
* We subscribe to the chat store, detect the output type of the latest
|
|
19
|
+
* assistant message, auto-switch the sidebar tab, and render the payload
|
|
20
|
+
* inline in the sidebar.
|
|
16
21
|
*/
|
|
17
22
|
/// <reference types="vite/client" />
|
|
18
|
-
import { useEffect, useState, useCallback, useRef } from 'react';
|
|
23
|
+
import { useEffect, useState, useCallback, useRef, useMemo, } from 'react';
|
|
19
24
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
20
25
|
import { Text, Button, Spinner, Heading, Label } from '@primer/react';
|
|
21
|
-
import {
|
|
26
|
+
import { TableIcon, FileIcon, CodeIcon, GraphIcon, DownloadIcon, } from '@primer/octicons-react';
|
|
22
27
|
import { Box } from '@datalayer/primer-addons';
|
|
28
|
+
import { AuthRequiredView, ErrorView } from './components';
|
|
23
29
|
import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel';
|
|
24
|
-
import { SignInSimple } from '@datalayer/core/lib/views/iam';
|
|
25
|
-
import { UserBadge } from '@datalayer/core/lib/views/profile';
|
|
26
30
|
import { ThemedProvider } from './utils/themedProvider';
|
|
27
|
-
import {
|
|
31
|
+
import { uniqueAgentId } from './utils/agentId';
|
|
28
32
|
import { Chat } from '../chat';
|
|
33
|
+
import { useChatStore } from '../stores/chatStore';
|
|
29
34
|
const queryClient = new QueryClient();
|
|
30
35
|
// ─── Constants ─────────────────────────────────────────────────────────────
|
|
31
|
-
const AGENT_NAME = '
|
|
32
|
-
const AGENT_SPEC_ID = '
|
|
36
|
+
const AGENT_NAME = 'outputs-demo-agent';
|
|
37
|
+
const AGENT_SPEC_ID = 'demo-outputs';
|
|
38
|
+
const DEFAULT_LOCAL_BASE_URL = import.meta.env.VITE_BASE_URL || 'http://localhost:8765';
|
|
39
|
+
// ─── Output detection ──────────────────────────────────────────────────────
|
|
40
|
+
const FENCE_RE = /```([a-zA-Z0-9_+-]*)\n([\s\S]*?)```/g;
|
|
41
|
+
const MD_TABLE_RE = /(^|\n)\s*\|[^\n]+\|\s*\n\s*\|[\s:|-]+\|\s*\n(\s*\|[^\n]+\|\s*\n?)+/;
|
|
42
|
+
const EXT_LIKE_INFOS = new Set([
|
|
43
|
+
'csv',
|
|
44
|
+
'tsv',
|
|
45
|
+
'txt',
|
|
46
|
+
'md',
|
|
47
|
+
'markdown',
|
|
48
|
+
'yaml',
|
|
49
|
+
'yml',
|
|
50
|
+
'xml',
|
|
51
|
+
'html',
|
|
52
|
+
'log',
|
|
53
|
+
'ini',
|
|
54
|
+
'toml',
|
|
55
|
+
]);
|
|
56
|
+
const messageText = (m) => {
|
|
57
|
+
if (typeof m.content === 'string')
|
|
58
|
+
return m.content;
|
|
59
|
+
return m.content
|
|
60
|
+
.filter(p => p.type === 'text')
|
|
61
|
+
.map(p => p.text)
|
|
62
|
+
.join('\n');
|
|
63
|
+
};
|
|
64
|
+
const detectOutput = (m) => {
|
|
65
|
+
const text = messageText(m);
|
|
66
|
+
if (!text)
|
|
67
|
+
return null;
|
|
68
|
+
// 1) Fenced code blocks (first one wins).
|
|
69
|
+
FENCE_RE.lastIndex = 0;
|
|
70
|
+
const match = FENCE_RE.exec(text);
|
|
71
|
+
if (match) {
|
|
72
|
+
const info = (match[1] || '').toLowerCase();
|
|
73
|
+
const body = match[2] ?? '';
|
|
74
|
+
const firstLine = body.split('\n', 1)[0]?.trim() ?? '';
|
|
75
|
+
// Chart: ```json with `// chart` marker on first line.
|
|
76
|
+
if (info === 'json' && /^\/\/\s*chart\b/i.test(firstLine)) {
|
|
77
|
+
return {
|
|
78
|
+
tab: 'chart',
|
|
79
|
+
payload: body.replace(/^\/\/\s*chart.*\n?/i, ''),
|
|
80
|
+
messageId: m.id,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// File: info string is a known extension OR first line declares a filename.
|
|
84
|
+
const filenameMatch = firstLine.match(/^#\s*filename:\s*([\w.-]+)/i);
|
|
85
|
+
if (filenameMatch || EXT_LIKE_INFOS.has(info)) {
|
|
86
|
+
const filename = filenameMatch?.[1] ?? (info ? `output.${info}` : 'output.txt');
|
|
87
|
+
return {
|
|
88
|
+
tab: 'files',
|
|
89
|
+
payload: filenameMatch
|
|
90
|
+
? body.replace(/^#\s*filename:.*\n?/i, '')
|
|
91
|
+
: body,
|
|
92
|
+
filename,
|
|
93
|
+
extension: filename.split('.').pop(),
|
|
94
|
+
messageId: m.id,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// JSON (explicit language tag).
|
|
98
|
+
if (info === 'json' || info === 'json5') {
|
|
99
|
+
return { tab: 'json', payload: body, messageId: m.id };
|
|
100
|
+
}
|
|
101
|
+
// JSON fallback: bare ``` fence whose body parses as JSON.
|
|
102
|
+
if (!info || info === 'text' || info === 'plain') {
|
|
103
|
+
const trimmed = body.trim();
|
|
104
|
+
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
|
|
105
|
+
try {
|
|
106
|
+
JSON.parse(trimmed);
|
|
107
|
+
return { tab: 'json', payload: trimmed, messageId: m.id };
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
/* not JSON — ignore */
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// 1b) No fences — try to detect a bare JSON object/array in the message.
|
|
116
|
+
{
|
|
117
|
+
const stripped = text.trim();
|
|
118
|
+
if (stripped.startsWith('{') || stripped.startsWith('[')) {
|
|
119
|
+
try {
|
|
120
|
+
JSON.parse(stripped);
|
|
121
|
+
return { tab: 'json', payload: stripped, messageId: m.id };
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
/* not JSON — ignore */
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Or: find the first {...} / [...] block and try parsing it.
|
|
128
|
+
const blockMatch = stripped.match(/(\{[\s\S]*\}|\[[\s\S]*\])/);
|
|
129
|
+
if (blockMatch) {
|
|
130
|
+
try {
|
|
131
|
+
JSON.parse(blockMatch[1]);
|
|
132
|
+
return { tab: 'json', payload: blockMatch[1], messageId: m.id };
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
/* not JSON — ignore */
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// 2) Markdown table (no fences).
|
|
140
|
+
if (MD_TABLE_RE.test(text)) {
|
|
141
|
+
const tableMatch = text.match(MD_TABLE_RE);
|
|
142
|
+
return {
|
|
143
|
+
tab: 'table',
|
|
144
|
+
payload: tableMatch ? tableMatch[0].trim() : text,
|
|
145
|
+
messageId: m.id,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
};
|
|
150
|
+
// ─── Table renderer (parses the Markdown pipe syntax) ──────────────────────
|
|
151
|
+
const MarkdownTable = ({ source }) => {
|
|
152
|
+
const { headers, rows } = useMemo(() => {
|
|
153
|
+
const lines = source
|
|
154
|
+
.split('\n')
|
|
155
|
+
.map(l => l.trim())
|
|
156
|
+
.filter(l => l.startsWith('|'));
|
|
157
|
+
if (lines.length < 2)
|
|
158
|
+
return { headers: [], rows: [] };
|
|
159
|
+
const split = (line) => line
|
|
160
|
+
.replace(/^\|/, '')
|
|
161
|
+
.replace(/\|$/, '')
|
|
162
|
+
.split('|')
|
|
163
|
+
.map(c => c.trim());
|
|
164
|
+
const headers = split(lines[0]);
|
|
165
|
+
const rows = lines.slice(2).map(split);
|
|
166
|
+
return { headers, rows };
|
|
167
|
+
}, [source]);
|
|
168
|
+
if (headers.length === 0) {
|
|
169
|
+
return (_jsx(Box, { as: "pre", sx: {
|
|
170
|
+
fontFamily: 'mono',
|
|
171
|
+
fontSize: 0,
|
|
172
|
+
whiteSpace: 'pre-wrap',
|
|
173
|
+
m: 0,
|
|
174
|
+
}, children: source }));
|
|
175
|
+
}
|
|
176
|
+
return (_jsx(Box, { sx: { overflowX: 'auto' }, children: _jsxs(Box, { as: "table", sx: {
|
|
177
|
+
width: '100%',
|
|
178
|
+
borderCollapse: 'collapse',
|
|
179
|
+
fontSize: 0,
|
|
180
|
+
'th, td': {
|
|
181
|
+
border: '1px solid',
|
|
182
|
+
borderColor: 'border.muted',
|
|
183
|
+
px: 2,
|
|
184
|
+
py: 1,
|
|
185
|
+
textAlign: 'left',
|
|
186
|
+
verticalAlign: 'top',
|
|
187
|
+
},
|
|
188
|
+
th: { bg: 'canvas.subtle', fontWeight: 'bold' },
|
|
189
|
+
}, children: [_jsx("thead", { children: _jsx("tr", { children: headers.map((h, i) => (_jsx("th", { children: h }, i))) }) }), _jsx("tbody", { children: rows.map((r, i) => (_jsx("tr", { children: r.map((c, j) => (_jsx("td", { children: c }, j))) }, i))) })] }) }));
|
|
190
|
+
};
|
|
191
|
+
// ─── Chart renderer (lazy ECharts) ─────────────────────────────────────────
|
|
192
|
+
const ChartView = ({ source }) => {
|
|
193
|
+
const [ReactECharts, setReactECharts] = useState(null);
|
|
194
|
+
useEffect(() => {
|
|
195
|
+
let cancelled = false;
|
|
196
|
+
import('echarts-for-react')
|
|
197
|
+
.then(m => {
|
|
198
|
+
if (!cancelled) {
|
|
199
|
+
setReactECharts(() => m.default);
|
|
200
|
+
}
|
|
201
|
+
})
|
|
202
|
+
.catch(() => {
|
|
203
|
+
/* echarts-for-react not installed — fall back to raw JSON */
|
|
204
|
+
});
|
|
205
|
+
return () => {
|
|
206
|
+
cancelled = true;
|
|
207
|
+
};
|
|
208
|
+
}, []);
|
|
209
|
+
const option = useMemo(() => {
|
|
210
|
+
try {
|
|
211
|
+
return JSON.parse(source);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
}, [source]);
|
|
217
|
+
if (!option) {
|
|
218
|
+
return (_jsx(Text, { sx: { color: 'danger.fg', fontSize: 0 }, children: "Could not parse chart spec as JSON." }));
|
|
219
|
+
}
|
|
220
|
+
if (!ReactECharts) {
|
|
221
|
+
return (_jsx(Box, { as: "pre", sx: {
|
|
222
|
+
fontFamily: 'mono',
|
|
223
|
+
fontSize: 0,
|
|
224
|
+
whiteSpace: 'pre-wrap',
|
|
225
|
+
bg: 'canvas.subtle',
|
|
226
|
+
p: 2,
|
|
227
|
+
borderRadius: 2,
|
|
228
|
+
m: 0,
|
|
229
|
+
}, children: source }));
|
|
230
|
+
}
|
|
231
|
+
return (_jsx(ReactECharts, { option: option, style: { height: 280, width: '100%' } }));
|
|
232
|
+
};
|
|
33
233
|
// ─── Inner component (rendered after auth) ─────────────────────────────────
|
|
34
234
|
const AgentOutputsInner = ({ onLogout, }) => {
|
|
35
235
|
const { token } = useSimpleAuthStore();
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
});
|
|
45
|
-
const [activeTab, setActiveTab] = useState('table');
|
|
46
|
-
const [artifacts, setArtifacts] = useState([]);
|
|
47
|
-
const agentBaseUrl = runtime?.agentBaseUrl || '';
|
|
48
|
-
const agentId = runtime?.agentId || AGENT_NAME;
|
|
49
|
-
const podName = runtime?.podName || '(launching…)';
|
|
50
|
-
// Authenticated fetch helper
|
|
236
|
+
const agentName = useRef(uniqueAgentId(AGENT_NAME)).current;
|
|
237
|
+
const [runtimeStatus, setRuntimeStatus] = useState('launching');
|
|
238
|
+
const [isReady, setIsReady] = useState(false);
|
|
239
|
+
const [hookError, setHookError] = useState(null);
|
|
240
|
+
const [agentId, setAgentId] = useState(agentName);
|
|
241
|
+
const [isReconnectedAgent, setIsReconnectedAgent] = useState(false);
|
|
242
|
+
const agentBaseUrl = DEFAULT_LOCAL_BASE_URL;
|
|
243
|
+
const chatAuthToken = token === null ? undefined : token;
|
|
51
244
|
const authFetch = useCallback((url, opts = {}) => fetch(url, {
|
|
52
245
|
...opts,
|
|
53
246
|
headers: {
|
|
@@ -56,26 +249,98 @@ const AgentOutputsInner = ({ onLogout, }) => {
|
|
|
56
249
|
...(opts.headers ?? {}),
|
|
57
250
|
},
|
|
58
251
|
}), [token]);
|
|
59
|
-
// ── Poll output artifacts ─────────────────────────────────────────────
|
|
60
252
|
useEffect(() => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
253
|
+
let isCancelled = false;
|
|
254
|
+
const createAgent = async () => {
|
|
255
|
+
setRuntimeStatus('launching');
|
|
256
|
+
setIsReady(false);
|
|
257
|
+
setHookError(null);
|
|
258
|
+
setIsReconnectedAgent(false);
|
|
64
259
|
try {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
260
|
+
const response = await authFetch(`${agentBaseUrl}/api/v1/agents`, {
|
|
261
|
+
method: 'POST',
|
|
262
|
+
body: JSON.stringify({
|
|
263
|
+
name: agentName,
|
|
264
|
+
description: 'Agent with rich output rendering (table/JSON/chart/file)',
|
|
265
|
+
agent_library: 'pydantic-ai',
|
|
266
|
+
transport: 'vercel-ai',
|
|
267
|
+
agent_spec_id: AGENT_SPEC_ID,
|
|
268
|
+
enable_skills: true,
|
|
269
|
+
tools: [],
|
|
270
|
+
}),
|
|
271
|
+
});
|
|
272
|
+
let resolvedAgentId = agentName;
|
|
273
|
+
let isAlreadyRunning = false;
|
|
274
|
+
if (response.ok) {
|
|
275
|
+
const data = await response.json();
|
|
276
|
+
resolvedAgentId = data?.id || agentName;
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
const contentType = response.headers.get('content-type') || '';
|
|
280
|
+
let detail = '';
|
|
281
|
+
if (contentType.includes('application/json')) {
|
|
282
|
+
const data = await response.json().catch(() => null);
|
|
283
|
+
detail =
|
|
284
|
+
(typeof data?.detail === 'string' && data.detail) ||
|
|
285
|
+
(typeof data?.message === 'string' && data.message) ||
|
|
286
|
+
'';
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
detail = await response.text();
|
|
290
|
+
}
|
|
291
|
+
if (response.status === 409 || /already exists/i.test(detail || '')) {
|
|
292
|
+
isAlreadyRunning = true;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
throw new Error(detail || `Failed to create agent: ${response.status}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (!isCancelled) {
|
|
299
|
+
setAgentId(resolvedAgentId);
|
|
300
|
+
setIsReconnectedAgent(isAlreadyRunning);
|
|
301
|
+
setIsReady(true);
|
|
302
|
+
setRuntimeStatus('ready');
|
|
69
303
|
}
|
|
70
304
|
}
|
|
71
|
-
catch {
|
|
72
|
-
|
|
305
|
+
catch (error) {
|
|
306
|
+
if (!isCancelled) {
|
|
307
|
+
setHookError(error instanceof Error ? error.message : 'Agent failed to start');
|
|
308
|
+
setRuntimeStatus('error');
|
|
309
|
+
}
|
|
73
310
|
}
|
|
74
311
|
};
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
312
|
+
void createAgent();
|
|
313
|
+
return () => {
|
|
314
|
+
isCancelled = true;
|
|
315
|
+
};
|
|
316
|
+
}, [agentBaseUrl, agentName, authFetch]);
|
|
317
|
+
const [activeTab, setActiveTab] = useState('table');
|
|
318
|
+
const [detected, setDetected] = useState([]);
|
|
319
|
+
const lastProcessedIdRef = useRef(null);
|
|
320
|
+
// Subscribe to chat store messages and detect outputs in assistant replies.
|
|
321
|
+
useEffect(() => {
|
|
322
|
+
const process = (messages) => {
|
|
323
|
+
const assistants = messages.filter(m => m.role === 'assistant');
|
|
324
|
+
if (assistants.length === 0)
|
|
325
|
+
return;
|
|
326
|
+
const last = assistants[assistants.length - 1];
|
|
327
|
+
if (last.id === lastProcessedIdRef.current)
|
|
328
|
+
return;
|
|
329
|
+
const out = detectOutput(last);
|
|
330
|
+
if (!out)
|
|
331
|
+
return;
|
|
332
|
+
lastProcessedIdRef.current = last.id;
|
|
333
|
+
setDetected(prev => {
|
|
334
|
+
if (prev.some(d => d.messageId === out.messageId))
|
|
335
|
+
return prev;
|
|
336
|
+
return [out, ...prev].slice(0, 20);
|
|
337
|
+
});
|
|
338
|
+
setActiveTab(out.tab);
|
|
339
|
+
};
|
|
340
|
+
process(useChatStore.getState().messages);
|
|
341
|
+
const unsub = useChatStore.subscribe(state => state.messages, process);
|
|
342
|
+
return unsub;
|
|
343
|
+
}, []);
|
|
79
344
|
// ── Loading / Error ───────────────────────────────────────────────────
|
|
80
345
|
if (!isReady && runtimeStatus !== 'error') {
|
|
81
346
|
return (_jsxs(Box, { sx: {
|
|
@@ -86,25 +351,35 @@ const AgentOutputsInner = ({ onLogout, }) => {
|
|
|
86
351
|
height: '100vh',
|
|
87
352
|
gap: 3,
|
|
88
353
|
}, children: [_jsx(Spinner, { size: "large" }), _jsx(Text, { sx: { color: 'fg.muted' }, children: runtimeStatus === 'launching'
|
|
89
|
-
? 'Launching
|
|
90
|
-
: 'Creating
|
|
354
|
+
? 'Launching outputs demo agent...'
|
|
355
|
+
: 'Creating outputs demo agent...' })] }));
|
|
91
356
|
}
|
|
92
357
|
if (runtimeStatus === 'error' || hookError) {
|
|
93
|
-
return (
|
|
94
|
-
display: 'flex',
|
|
95
|
-
flexDirection: 'column',
|
|
96
|
-
alignItems: 'center',
|
|
97
|
-
justifyContent: 'center',
|
|
98
|
-
height: '100vh',
|
|
99
|
-
gap: 3,
|
|
100
|
-
}, children: [_jsx(AlertIcon, { size: 48 }), _jsx(Text, { sx: { color: 'danger.fg' }, children: hookError || 'Agent failed to start' })] }));
|
|
358
|
+
return _jsx(ErrorView, { error: hookError, onLogout: onLogout });
|
|
101
359
|
}
|
|
102
|
-
const filtered =
|
|
360
|
+
const filtered = detected.filter(d => d.tab === activeTab);
|
|
361
|
+
const countByTab = (tab) => detected.filter(d => d.tab === tab).length;
|
|
362
|
+
const download = (d) => {
|
|
363
|
+
const blob = new Blob([d.payload], { type: 'text/plain;charset=utf-8' });
|
|
364
|
+
const url = URL.createObjectURL(blob);
|
|
365
|
+
const a = document.createElement('a');
|
|
366
|
+
a.href = url;
|
|
367
|
+
a.download = d.filename ?? `output.${d.extension ?? 'txt'}`;
|
|
368
|
+
document.body.appendChild(a);
|
|
369
|
+
a.click();
|
|
370
|
+
document.body.removeChild(a);
|
|
371
|
+
URL.revokeObjectURL(url);
|
|
372
|
+
};
|
|
103
373
|
return (_jsxs(Box, { sx: {
|
|
104
374
|
height: 'calc(100vh - 60px)',
|
|
105
375
|
display: 'flex',
|
|
106
376
|
flexDirection: 'column',
|
|
107
|
-
}, children: [
|
|
377
|
+
}, children: [isReconnectedAgent && (_jsx(Box, { sx: {
|
|
378
|
+
px: 3,
|
|
379
|
+
py: 1,
|
|
380
|
+
borderBottom: '1px solid',
|
|
381
|
+
borderColor: 'border.default',
|
|
382
|
+
}, children: _jsx(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: "Agent already running - reconnected." }) })), _jsxs(Box, { sx: {
|
|
108
383
|
display: 'flex',
|
|
109
384
|
alignItems: 'center',
|
|
110
385
|
gap: 2,
|
|
@@ -113,22 +388,30 @@ const AgentOutputsInner = ({ onLogout, }) => {
|
|
|
113
388
|
borderBottom: '1px solid',
|
|
114
389
|
borderColor: 'border.default',
|
|
115
390
|
flexShrink: 0,
|
|
116
|
-
}, children: [_jsx(TableIcon, { size: 16 }),
|
|
391
|
+
}, children: [_jsx(TableIcon, { size: 16 }), _jsx(Heading, { as: "h3", sx: { fontSize: 2, flex: 1 }, children: "Agent Outputs \u2014 Local Runtime" })] }), _jsxs(Box, { sx: { flex: 1, minHeight: 0, display: 'flex' }, children: [_jsx(Box, { sx: { flex: 1, minWidth: 0 }, children: _jsx(Chat, { protocol: "vercel-ai", baseUrl: agentBaseUrl, agentId: agentId, authToken: chatAuthToken, title: "Outputs Demo Agent", placeholder: "Ask for a Table, JSON, Chart, or File\u2026", description: `${detected.length} detected output${detected.length !== 1 ? 's' : ''}`, showHeader: true, showToolsMenu: true, showSkillsMenu: true, autoFocus: true, height: "100%", runtimeId: agentId, historyEndpoint: `${agentBaseUrl}/api/v1/history`, suggestions: [
|
|
117
392
|
{
|
|
118
|
-
title: '
|
|
119
|
-
message: 'Generate a
|
|
393
|
+
title: 'Table',
|
|
394
|
+
message: 'Generate a Markdown table of the top 5 US cities by population, with columns City, State, Population.',
|
|
120
395
|
},
|
|
121
396
|
{
|
|
122
|
-
title: '
|
|
123
|
-
message: '
|
|
397
|
+
title: 'JSON',
|
|
398
|
+
message: 'Return a JSON object describing a fictitious product catalog with 3 items (id, name, price, tags).',
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
title: 'Chart',
|
|
402
|
+
message: 'Produce a bar chart ECharts spec (valid JSON, with `// chart` on the first line of the fenced block) showing monthly sales for Jan–Jun.',
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
title: 'File',
|
|
406
|
+
message: 'Create a downloadable CSV file with sample sales data for the last 7 days. Output it inside a ```csv fenced block whose first line is `# filename: sales.csv`.',
|
|
124
407
|
},
|
|
125
408
|
], submitOnSuggestionClick: true }) }), _jsxs(Box, { sx: {
|
|
126
|
-
width:
|
|
409
|
+
width: 420,
|
|
127
410
|
borderLeft: '1px solid',
|
|
128
411
|
borderColor: 'border.default',
|
|
129
412
|
display: 'flex',
|
|
130
413
|
flexDirection: 'column',
|
|
131
|
-
overflow: '
|
|
414
|
+
overflow: 'hidden',
|
|
132
415
|
}, children: [_jsx(Box, { sx: {
|
|
133
416
|
display: 'flex',
|
|
134
417
|
borderBottom: '1px solid',
|
|
@@ -139,13 +422,18 @@ const AgentOutputsInner = ({ onLogout, }) => {
|
|
|
139
422
|
{ key: 'json', icon: CodeIcon, label: 'JSON' },
|
|
140
423
|
{ key: 'chart', icon: GraphIcon, label: 'Chart' },
|
|
141
424
|
{ key: 'files', icon: FileIcon, label: 'Files' },
|
|
142
|
-
].map(t =>
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
425
|
+
].map(t => {
|
|
426
|
+
const n = countByTab(t.key);
|
|
427
|
+
return (_jsxs(Button, { size: "small", variant: "invisible", leadingVisual: t.icon, onClick: () => setActiveTab(t.key), sx: {
|
|
428
|
+
flex: 1,
|
|
429
|
+
borderRadius: 0,
|
|
430
|
+
borderBottom: activeTab === t.key
|
|
431
|
+
? '2px solid'
|
|
432
|
+
: '2px solid transparent',
|
|
433
|
+
borderColor: activeTab === t.key ? 'accent.fg' : 'transparent',
|
|
434
|
+
fontWeight: activeTab === t.key ? 'bold' : 'normal',
|
|
435
|
+
}, children: [t.label, n > 0 ? ` (${n})` : ''] }, t.key));
|
|
436
|
+
}) }), _jsxs(Box, { sx: { p: 3, flex: 1, overflow: 'auto' }, children: [_jsxs(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: [activeTab.charAt(0).toUpperCase() + activeTab.slice(1), " outputs"] }), filtered.length === 0 ? (_jsxs(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: ["No ", activeTab, " outputs yet. Use one of the suggestion buttons in the chat to produce one \u2014 the side panel will switch to the matching tab automatically."] })) : (filtered.map((d, idx) => (_jsxs(Box, { sx: {
|
|
149
437
|
p: 2,
|
|
150
438
|
mb: 2,
|
|
151
439
|
border: '1px solid',
|
|
@@ -155,25 +443,37 @@ const AgentOutputsInner = ({ onLogout, }) => {
|
|
|
155
443
|
display: 'flex',
|
|
156
444
|
justifyContent: 'space-between',
|
|
157
445
|
alignItems: 'center',
|
|
158
|
-
mb:
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
: activeTab })] }), art.preview && (_jsx(Box, { sx: {
|
|
446
|
+
mb: 2,
|
|
447
|
+
gap: 2,
|
|
448
|
+
}, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold' }, children: d.filename ?? `${d.tab} output` }), _jsx(Label, { size: "small", variant: "secondary", children: d.tab })] }), d.tab === 'table' && _jsx(MarkdownTable, { source: d.payload }), d.tab === 'json' && (_jsx(Box, { as: "pre", sx: {
|
|
162
449
|
bg: 'canvas.subtle',
|
|
163
450
|
p: 2,
|
|
164
451
|
borderRadius: 2,
|
|
165
452
|
fontFamily: 'mono',
|
|
166
453
|
fontSize: 0,
|
|
167
|
-
|
|
168
|
-
maxHeight: 120,
|
|
454
|
+
maxHeight: 320,
|
|
169
455
|
overflow: 'auto',
|
|
170
456
|
whiteSpace: 'pre-wrap',
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
457
|
+
m: 0,
|
|
458
|
+
}, children: (() => {
|
|
459
|
+
try {
|
|
460
|
+
return JSON.stringify(JSON.parse(d.payload), null, 2);
|
|
461
|
+
}
|
|
462
|
+
catch {
|
|
463
|
+
return d.payload;
|
|
464
|
+
}
|
|
465
|
+
})() })), d.tab === 'chart' && _jsx(ChartView, { source: d.payload }), d.tab === 'files' && (_jsxs(_Fragment, { children: [_jsx(Box, { as: "pre", sx: {
|
|
466
|
+
bg: 'canvas.subtle',
|
|
467
|
+
p: 2,
|
|
468
|
+
borderRadius: 2,
|
|
469
|
+
fontFamily: 'mono',
|
|
470
|
+
fontSize: 0,
|
|
471
|
+
maxHeight: 200,
|
|
472
|
+
overflow: 'auto',
|
|
473
|
+
whiteSpace: 'pre-wrap',
|
|
474
|
+
m: 0,
|
|
475
|
+
mb: 2,
|
|
476
|
+
}, children: d.payload }), _jsxs(Button, { size: "small", leadingVisual: DownloadIcon, onClick: () => download(d), children: ["Download ", d.filename ?? 'file'] })] }))] }, d.messageId + ':' + idx))))] })] })] })] }));
|
|
177
477
|
};
|
|
178
478
|
// ─── Sync token to core IAM store ──────────────────────────────────────────
|
|
179
479
|
const syncTokenToIamStore = (token) => {
|
|
@@ -183,7 +483,7 @@ const syncTokenToIamStore = (token) => {
|
|
|
183
483
|
};
|
|
184
484
|
// ─── Main component with auth gate ─────────────────────────────────────────
|
|
185
485
|
const AgentOutputsExample = () => {
|
|
186
|
-
const { token,
|
|
486
|
+
const { token, clearAuth } = useSimpleAuthStore();
|
|
187
487
|
const hasSynced = useRef(false);
|
|
188
488
|
useEffect(() => {
|
|
189
489
|
if (token && !hasSynced.current) {
|
|
@@ -191,11 +491,6 @@ const AgentOutputsExample = () => {
|
|
|
191
491
|
syncTokenToIamStore(token);
|
|
192
492
|
}
|
|
193
493
|
}, [token]);
|
|
194
|
-
const handleSignIn = useCallback((newToken, handle) => {
|
|
195
|
-
setAuth(newToken, handle);
|
|
196
|
-
hasSynced.current = true;
|
|
197
|
-
syncTokenToIamStore(newToken);
|
|
198
|
-
}, [setAuth]);
|
|
199
494
|
const handleLogout = useCallback(() => {
|
|
200
495
|
clearAuth();
|
|
201
496
|
hasSynced.current = false;
|
|
@@ -204,7 +499,7 @@ const AgentOutputsExample = () => {
|
|
|
204
499
|
});
|
|
205
500
|
}, [clearAuth]);
|
|
206
501
|
if (!token) {
|
|
207
|
-
return (_jsx(ThemedProvider, { children: _jsx(
|
|
502
|
+
return (_jsx(ThemedProvider, { children: _jsx(AuthRequiredView, {}) }));
|
|
208
503
|
}
|
|
209
504
|
return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ThemedProvider, { children: _jsx(AgentOutputsInner, { onLogout: handleLogout }) }) }));
|
|
210
505
|
};
|