main
mula.liu 2026-03-11 22:25:31 +08:00
parent 753e1053c2
commit 590eae9f0c
4 changed files with 44 additions and 12 deletions

View File

@ -141,7 +141,7 @@ export const dashboardEn = {
toolsLoadFail: 'Failed to load tool skills.',
toolsAddFail: 'Failed to add tool.',
toolsRemoveFail: 'Failed to remove tool.',
toolsRemoveConfirm: (name: string) => `Remove skill ${name}?`,
toolsRemoveConfirm: (name: string) => `Remove skill ${name}? This action cannot be undone.`,
agent: 'Agent',
container: 'Container',
current: 'Current',

View File

@ -141,7 +141,7 @@ export const dashboardZhCn = {
toolsLoadFail: '读取工具技能失败。',
toolsAddFail: '新增工具失败。',
toolsRemoveFail: '移除工具失败。',
toolsRemoveConfirm: (name: string) => `确认移除技能 ${name}`,
toolsRemoveConfirm: (name: string) => `确认移除技能 ${name}该操作不可撤销。`,
agent: '代理',
container: '容器状态',
current: '当前状态',

View File

@ -818,6 +818,12 @@
position: relative;
}
.ops-chat-text.is-collapsed-user {
max-height: calc(1.58em * 5);
overflow: hidden;
position: relative;
}
.ops-chat-text.is-collapsed::after {
content: '';
position: absolute;
@ -829,6 +835,17 @@
background: linear-gradient(to bottom, transparent, color-mix(in oklab, var(--panel-soft) 88%, var(--panel) 12%));
}
.ops-chat-text.is-collapsed-user::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 42px;
pointer-events: none;
background: linear-gradient(to bottom, transparent, color-mix(in oklab, var(--panel-soft) 88%, var(--panel) 12%));
}
.ops-chat-text > *:first-child {
margin-top: 0;
}

View File

@ -1,6 +1,6 @@
import { useCallback, useEffect, useMemo, useRef, useState, type AnchorHTMLAttributes, type ChangeEvent, type KeyboardEvent, type ReactNode } from 'react';
import axios from 'axios';
import { Activity, ArrowUp, Boxes, Check, ChevronLeft, ChevronRight, Clock3, Copy, Download, EllipsisVertical, ExternalLink, Eye, EyeOff, FileText, FolderOpen, Gauge, Hammer, Lock, Maximize2, MessageSquareText, Mic, Minimize2, Paperclip, Pencil, Plus, Power, PowerOff, RefreshCw, Repeat2, Reply, Save, Search, Settings2, SlidersHorizontal, Square, ThumbsDown, ThumbsUp, TriangleAlert, Trash2, UserRound, Waypoints, X } from 'lucide-react';
import { Activity, ArrowUp, Boxes, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Clock3, Copy, Download, EllipsisVertical, ExternalLink, Eye, EyeOff, FileText, FolderOpen, Gauge, Hammer, Lock, Maximize2, MessageSquareText, Mic, Minimize2, Paperclip, Pencil, Plus, Power, PowerOff, RefreshCw, Repeat2, Reply, Save, Search, Settings2, SlidersHorizontal, Square, ThumbsDown, ThumbsUp, TriangleAlert, Trash2, UserRound, Waypoints, X } from 'lucide-react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeRaw from 'rehype-raw';
@ -794,6 +794,7 @@ export function BotDashboardModule({
const [botListQuery, setBotListQuery] = useState('');
const [botListPage, setBotListPage] = useState(1);
const [expandedProgressByKey, setExpandedProgressByKey] = useState<Record<string, boolean>>({});
const [expandedUserByKey, setExpandedUserByKey] = useState<Record<string, boolean>>({});
const [feedbackSavingByMessageId, setFeedbackSavingByMessageId] = useState<Record<number, boolean>>({});
const [showRuntimeActionModal, setShowRuntimeActionModal] = useState(false);
const [workspaceHoverCard, setWorkspaceHoverCard] = useState<WorkspaceHoverCardState | null>(null);
@ -1304,11 +1305,16 @@ export function BotDashboardModule({
conversation.map((item, idx) => {
const itemKey = `${item.id || item.ts}-${idx}`;
const isProgressBubble = item.role !== 'user' && (item.kind || 'final') === 'progress';
const isUserBubble = item.role === 'user';
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 progressCollapsible = isProgressBubble && (hasSummary || shouldCollapseProgress(fullText));
const normalizedUserText = isUserBubble ? normalizeUserMessageText(fullText) : '';
const userLineCount = isUserBubble ? normalizedUserText.split('\n').length : 0;
const userCollapsible = isUserBubble && userLineCount > 5;
const collapsible = isProgressBubble ? progressCollapsible : userCollapsible;
const expanded = isProgressBubble ? Boolean(expandedProgressByKey[itemKey]) : Boolean(expandedUserByKey[itemKey]);
const displayText = isProgressBubble && !expanded ? summaryText : fullText;
const currentDayKey = new Date(item.ts).toDateString();
const prevDayKey = idx > 0 ? new Date(conversation[idx - 1].ts).toDateString() : '';
@ -1356,21 +1362,28 @@ export function BotDashboardModule({
{collapsible ? (
<LucentIconButton
className="ops-chat-expand-icon-btn"
onClick={() =>
setExpandedProgressByKey((prev) => ({
onClick={() => {
if (isProgressBubble) {
setExpandedProgressByKey((prev) => ({
...prev,
[itemKey]: !prev[itemKey],
}));
return;
}
setExpandedUserByKey((prev) => ({
...prev,
[itemKey]: !prev[itemKey],
}))
}
}));
}}
tooltip={expanded ? (isZh ? '收起' : 'Collapse') : (isZh ? '展开' : 'Expand')}
aria-label={expanded ? (isZh ? '收起' : 'Collapse') : (isZh ? '展开' : 'Expand')}
>
{expanded ? '×' : '…'}
{expanded ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
</LucentIconButton>
) : null}
</div>
</div>
<div className={`ops-chat-text ${collapsible && !expanded ? 'is-collapsed' : ''}`}>
<div className={`ops-chat-text ${collapsible && !expanded ? (isUserBubble ? 'is-collapsed-user' : 'is-collapsed') : ''}`}>
{item.text ? (
item.role === 'user' ? (
<>
@ -1380,7 +1393,7 @@ export function BotDashboardModule({
<div className="ops-user-quoted-text">{normalizeAssistantMessageText(item.quoted_reply)}</div>
</div>
) : null}
<div className="whitespace-pre-wrap">{normalizeUserMessageText(item.text)}</div>
<div className="whitespace-pre-wrap">{normalizeUserMessageText(displayText)}</div>
</>
) : (
<ReactMarkdown
@ -1475,6 +1488,7 @@ export function BotDashboardModule({
[
conversation,
expandedProgressByKey,
expandedUserByKey,
feedbackSavingByMessageId,
isZh,
selectedBotId,
@ -1585,6 +1599,7 @@ export function BotDashboardModule({
useEffect(() => {
setExpandedProgressByKey({});
setExpandedUserByKey({});
setShowRuntimeActionModal(false);
setWorkspaceHoverCard(null);
}, [selectedBotId]);