diff --git a/frontend/src/i18n/dashboard.en.ts b/frontend/src/i18n/dashboard.en.ts index f2e2bd8..a7fa71f 100644 --- a/frontend/src/i18n/dashboard.en.ts +++ b/frontend/src/i18n/dashboard.en.ts @@ -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', diff --git a/frontend/src/i18n/dashboard.zh-cn.ts b/frontend/src/i18n/dashboard.zh-cn.ts index 92c2bed..c219e6e 100644 --- a/frontend/src/i18n/dashboard.zh-cn.ts +++ b/frontend/src/i18n/dashboard.zh-cn.ts @@ -141,7 +141,7 @@ export const dashboardZhCn = { toolsLoadFail: '读取工具技能失败。', toolsAddFail: '新增工具失败。', toolsRemoveFail: '移除工具失败。', - toolsRemoveConfirm: (name: string) => `确认移除技能 ${name}?`, + toolsRemoveConfirm: (name: string) => `确认移除技能 ${name}?该操作不可撤销。`, agent: '代理', container: '容器状态', current: '当前状态', diff --git a/frontend/src/modules/dashboard/BotDashboardModule.css b/frontend/src/modules/dashboard/BotDashboardModule.css index 8ab837a..7dec514 100644 --- a/frontend/src/modules/dashboard/BotDashboardModule.css +++ b/frontend/src/modules/dashboard/BotDashboardModule.css @@ -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; } diff --git a/frontend/src/modules/dashboard/BotDashboardModule.tsx b/frontend/src/modules/dashboard/BotDashboardModule.tsx index 3e86f93..dab392c 100644 --- a/frontend/src/modules/dashboard/BotDashboardModule.tsx +++ b/frontend/src/modules/dashboard/BotDashboardModule.tsx @@ -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>({}); + const [expandedUserByKey, setExpandedUserByKey] = useState>({}); const [feedbackSavingByMessageId, setFeedbackSavingByMessageId] = useState>({}); const [showRuntimeActionModal, setShowRuntimeActionModal] = useState(false); const [workspaceHoverCard, setWorkspaceHoverCard] = useState(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 ? ( - 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 ? : } ) : null} -
+
{item.text ? ( item.role === 'user' ? ( <> @@ -1380,7 +1393,7 @@ export function BotDashboardModule({
{normalizeAssistantMessageText(item.quoted_reply)}
) : null} -
{normalizeUserMessageText(item.text)}
+
{normalizeUserMessageText(displayText)}
) : ( { setExpandedProgressByKey({}); + setExpandedUserByKey({}); setShowRuntimeActionModal(false); setWorkspaceHoverCard(null); }, [selectedBotId]);