v0.1.4
parent
753e1053c2
commit
590eae9f0c
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ export const dashboardZhCn = {
|
|||
toolsLoadFail: '读取工具技能失败。',
|
||||
toolsAddFail: '新增工具失败。',
|
||||
toolsRemoveFail: '移除工具失败。',
|
||||
toolsRemoveConfirm: (name: string) => `确认移除技能 ${name}?`,
|
||||
toolsRemoveConfirm: (name: string) => `确认移除技能 ${name}?该操作不可撤销。`,
|
||||
agent: '代理',
|
||||
container: '容器状态',
|
||||
current: '当前状态',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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={() =>
|
||||
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]);
|
||||
|
|
|
|||
Loading…
Reference in New Issue