From a2ac5c4fb573237e87706abf21092e2a62423d75 Mon Sep 17 00:00:00 2001 From: "mula.liu" Date: Mon, 2 Mar 2026 04:04:42 +0800 Subject: [PATCH] v0.1.2 --- backend/core/config_manager.py | 1 + frontend/src/hooks/useBotsSync.ts | 26 +++++++++-- .../modules/dashboard/BotDashboardModule.css | 20 ++++++++ .../modules/dashboard/BotDashboardModule.tsx | 46 +++++++++++++++---- 4 files changed, 80 insertions(+), 13 deletions(-) diff --git a/backend/core/config_manager.py b/backend/core/config_manager.py index 18906c4..8c3367a 100644 --- a/backend/core/config_manager.py +++ b/backend/core/config_manager.py @@ -1,3 +1,4 @@ +import json import os from typing import Any, Dict, List diff --git a/frontend/src/hooks/useBotsSync.ts b/frontend/src/hooks/useBotsSync.ts index 2d78871..3bb5429 100644 --- a/frontend/src/hooks/useBotsSync.ts +++ b/frontend/src/hooks/useBotsSync.ts @@ -147,14 +147,30 @@ export function useBotsSync() { if (data.type === 'AGENT_STATE') { const state = String(payload.state || data.state || 'INFO'); const messageRaw = String(payload.action_msg || payload.msg || data.action_msg || data.msg || ''); - const message = summarizeProgressText(messageRaw, isZh); + const normalizedState = normalizeState(state); + const fullMessage = normalizeAssistantMessageText(messageRaw); + const message = fullMessage || summarizeProgressText(messageRaw, isZh) || t.stateUpdated; updateBotState(bot.id, state, message); addBotEvent(bot.id, { - state: normalizeState(state), + state: normalizedState, text: message || t.stateUpdated, ts: Date.now(), channel: sourceChannel || undefined, }); + if (isDashboardChannel && fullMessage && (normalizedState === 'THINKING' || normalizedState === 'TOOL_CALL')) { + const chatText = normalizedState === 'TOOL_CALL' ? `${isZh ? '工具调用' : 'Tool Call'}\n${fullMessage}` : fullMessage; + const now = Date.now(); + const prev = lastProgressRef.current[bot.id]; + if (!prev || prev.text !== chatText || now - prev.ts > 1200) { + addBotMessage(bot.id, { + role: 'assistant', + text: chatText, + ts: now, + kind: 'progress', + }); + lastProgressRef.current[bot.id] = { text: chatText, ts: now }; + } + } return; } if (data.type === 'ASSISTANT_MESSAGE') { @@ -178,10 +194,10 @@ export function useBotsSync() { if (isProgress) { const state = normalizeBusState(isTool); const progressText = summarizeProgressText(content, isZh); - updateBotState(bot.id, state, progressText); - addBotEvent(bot.id, { state, text: progressText || t.progress, ts: Date.now(), channel: sourceChannel || undefined }); + const fullProgress = content || progressText || (isZh ? '处理中...' : 'Processing...'); + updateBotState(bot.id, state, fullProgress); + addBotEvent(bot.id, { state, text: fullProgress || t.progress, ts: Date.now(), channel: sourceChannel || undefined }); if (isDashboardChannel) { - const fullProgress = content || progressText || (isZh ? '处理中...' : 'Processing...'); const chatText = isTool ? `${isZh ? '工具调用' : 'Tool Call'}\n${fullProgress}` : fullProgress; const now = Date.now(); const prev = lastProgressRef.current[bot.id]; diff --git a/frontend/src/modules/dashboard/BotDashboardModule.css b/frontend/src/modules/dashboard/BotDashboardModule.css index 54c41b9..409dbad 100644 --- a/frontend/src/modules/dashboard/BotDashboardModule.css +++ b/frontend/src/modules/dashboard/BotDashboardModule.css @@ -1074,6 +1074,26 @@ font-weight: 700; } +.ops-runtime-action { + min-width: 0; + display: grid; + gap: 6px; +} + +.ops-runtime-action-text { + display: block; + white-space: pre-wrap; + word-break: break-word; + overflow-wrap: anywhere; + line-height: 1.54; + max-height: 82px; + overflow: auto; +} + +.ops-runtime-action-text.expanded { + max-height: 180px; +} + .ops-preview { border: 1px solid var(--line); border-radius: 10px; diff --git a/frontend/src/modules/dashboard/BotDashboardModule.tsx b/frontend/src/modules/dashboard/BotDashboardModule.tsx index 93a5843..f80ab02 100644 --- a/frontend/src/modules/dashboard/BotDashboardModule.tsx +++ b/frontend/src/modules/dashboard/BotDashboardModule.tsx @@ -391,6 +391,7 @@ export function BotDashboardModule({ const [compactPanelTab, setCompactPanelTab] = useState('chat'); const [isCompactMobile, setIsCompactMobile] = useState(false); const [expandedProgressByKey, setExpandedProgressByKey] = useState>({}); + const [runtimeActionExpanded, setRuntimeActionExpanded] = useState(false); const runtimeMenuRef = useRef(null); const openWorkspacePathFromChat = (path: string) => { const normalized = String(path || '').trim(); @@ -607,12 +608,23 @@ export function BotDashboardModule({ return 'IDLE'; }, [selectedBot, isThinking, latestEvent]); const runtimeAction = useMemo(() => { - const action = summarizeProgressText(selectedBot?.last_action || '', isZh); - if (action && action !== t.processing) return action; - const eventText = summarizeProgressText(latestEvent?.text || '', isZh); - if (eventText && eventText !== t.processing) return eventText; + const action = normalizeAssistantMessageText(selectedBot?.last_action || '').trim(); + if (action) return action; + const eventText = normalizeAssistantMessageText(latestEvent?.text || '').trim(); + if (eventText) return eventText; return '-'; - }, [selectedBot, latestEvent, isZh, t.processing]); + }, [selectedBot, latestEvent]); + const runtimeActionSummary = useMemo(() => { + const full = String(runtimeAction || '').trim(); + if (!full || full === '-') return '-'; + return summarizeProgressText(full, isZh); + }, [runtimeAction, isZh]); + const runtimeActionHasMore = useMemo(() => { + const full = String(runtimeAction || '').trim(); + const summary = String(runtimeActionSummary || '').trim(); + return Boolean(full && full !== '-' && summary && full !== summary); + }, [runtimeAction, runtimeActionSummary]); + const runtimeActionDisplay = runtimeActionExpanded || !runtimeActionHasMore ? runtimeAction : runtimeActionSummary; const shouldCollapseProgress = (text: string) => { const normalized = String(text || '').trim(); @@ -626,8 +638,12 @@ export function BotDashboardModule({ conversation.map((item, idx) => { const itemKey = `${item.ts}-${idx}`; const isProgressBubble = item.role !== 'user' && (item.kind || 'final') === 'progress'; - const collapsible = isProgressBubble && shouldCollapseProgress(item.text); + const fullText = String(item.text || ''); + const summaryText = isProgressBubble ? summarizeProgressText(fullText, isZh) : fullText; + const hasSummary = isProgressBubble && summaryText.trim().length > 0 && summaryText.trim() !== fullText.trim(); + const collapsible = isProgressBubble && (hasSummary || shouldCollapseProgress(fullText)); const expanded = Boolean(expandedProgressByKey[itemKey]); + const displayText = isProgressBubble && !expanded ? summaryText : fullText; return (
@@ -648,7 +664,7 @@ export function BotDashboardModule({
{normalizeUserMessageText(item.text)}
) : ( - {decorateWorkspacePathsForMarkdown(item.text)} + {decorateWorkspacePathsForMarkdown(displayText)} ) ) : null} @@ -736,6 +752,7 @@ export function BotDashboardModule({ useEffect(() => { setExpandedProgressByKey({}); + setRuntimeActionExpanded(false); }, [selectedBotId]); useEffect(() => { @@ -1932,7 +1949,20 @@ export function BotDashboardModule({ <>
{t.container}{selectedBot.docker_status}
{t.current}{displayState}
-
{t.lastAction}{runtimeAction}
+
+ {t.lastAction} +
+ {runtimeActionDisplay} + {runtimeActionHasMore ? ( + + ) : null} +
+
Provider{selectedBot.llm_provider || '-'}
Model{selectedBot.llm_model || '-'}