v0.1.2
parent
3cb25ba795
commit
a2ac5c4fb5
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
import os
|
||||
from typing import Any, Dict, List
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -391,6 +391,7 @@ export function BotDashboardModule({
|
|||
const [compactPanelTab, setCompactPanelTab] = useState<CompactPanelTab>('chat');
|
||||
const [isCompactMobile, setIsCompactMobile] = useState(false);
|
||||
const [expandedProgressByKey, setExpandedProgressByKey] = useState<Record<string, boolean>>({});
|
||||
const [runtimeActionExpanded, setRuntimeActionExpanded] = useState(false);
|
||||
const runtimeMenuRef = useRef<HTMLDivElement | null>(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 (
|
||||
<div key={itemKey} className={`ops-chat-row ${item.role === 'user' ? 'is-user' : 'is-assistant'}`}>
|
||||
<div className={`ops-chat-item ${item.role === 'user' ? 'is-user' : 'is-assistant'}`}>
|
||||
|
|
@ -648,7 +664,7 @@ export function BotDashboardModule({
|
|||
<div className="whitespace-pre-wrap">{normalizeUserMessageText(item.text)}</div>
|
||||
) : (
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]} components={markdownComponents}>
|
||||
{decorateWorkspacePathsForMarkdown(item.text)}
|
||||
{decorateWorkspacePathsForMarkdown(displayText)}
|
||||
</ReactMarkdown>
|
||||
)
|
||||
) : null}
|
||||
|
|
@ -736,6 +752,7 @@ export function BotDashboardModule({
|
|||
|
||||
useEffect(() => {
|
||||
setExpandedProgressByKey({});
|
||||
setRuntimeActionExpanded(false);
|
||||
}, [selectedBotId]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -1932,7 +1949,20 @@ export function BotDashboardModule({
|
|||
<>
|
||||
<div className="ops-runtime-row"><span>{t.container}</span><strong className="mono">{selectedBot.docker_status}</strong></div>
|
||||
<div className="ops-runtime-row"><span>{t.current}</span><strong className="mono">{displayState}</strong></div>
|
||||
<div className="ops-runtime-row"><span>{t.lastAction}</span><strong>{runtimeAction}</strong></div>
|
||||
<div className="ops-runtime-row">
|
||||
<span>{t.lastAction}</span>
|
||||
<div className="ops-runtime-action">
|
||||
<strong className={`ops-runtime-action-text ${runtimeActionExpanded ? 'expanded' : ''}`}>{runtimeActionDisplay}</strong>
|
||||
{runtimeActionHasMore ? (
|
||||
<button
|
||||
className="ops-chat-more-btn"
|
||||
onClick={() => setRuntimeActionExpanded((prev) => !prev)}
|
||||
>
|
||||
{runtimeActionExpanded ? (isZh ? '收起' : 'Less') : (isZh ? '更多' : 'More')}
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="ops-runtime-row"><span>Provider</span><strong className="mono">{selectedBot.llm_provider || '-'}</strong></div>
|
||||
<div className="ops-runtime-row"><span>Model</span><strong className="mono">{selectedBot.llm_model || '-'}</strong></div>
|
||||
</>
|
||||
|
|
|
|||
Loading…
Reference in New Issue