v0.1.4
parent
753e1053c2
commit
590eae9f0c
|
|
@ -141,7 +141,7 @@ export const dashboardEn = {
|
||||||
toolsLoadFail: 'Failed to load tool skills.',
|
toolsLoadFail: 'Failed to load tool skills.',
|
||||||
toolsAddFail: 'Failed to add tool.',
|
toolsAddFail: 'Failed to add tool.',
|
||||||
toolsRemoveFail: 'Failed to remove 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',
|
agent: 'Agent',
|
||||||
container: 'Container',
|
container: 'Container',
|
||||||
current: 'Current',
|
current: 'Current',
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ export const dashboardZhCn = {
|
||||||
toolsLoadFail: '读取工具技能失败。',
|
toolsLoadFail: '读取工具技能失败。',
|
||||||
toolsAddFail: '新增工具失败。',
|
toolsAddFail: '新增工具失败。',
|
||||||
toolsRemoveFail: '移除工具失败。',
|
toolsRemoveFail: '移除工具失败。',
|
||||||
toolsRemoveConfirm: (name: string) => `确认移除技能 ${name}?`,
|
toolsRemoveConfirm: (name: string) => `确认移除技能 ${name}?该操作不可撤销。`,
|
||||||
agent: '代理',
|
agent: '代理',
|
||||||
container: '容器状态',
|
container: '容器状态',
|
||||||
current: '当前状态',
|
current: '当前状态',
|
||||||
|
|
|
||||||
|
|
@ -818,6 +818,12 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ops-chat-text.is-collapsed-user {
|
||||||
|
max-height: calc(1.58em * 5);
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
.ops-chat-text.is-collapsed::after {
|
.ops-chat-text.is-collapsed::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
@ -829,6 +835,17 @@
|
||||||
background: linear-gradient(to bottom, transparent, color-mix(in oklab, var(--panel-soft) 88%, var(--panel) 12%));
|
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 {
|
.ops-chat-text > *:first-child {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState, type AnchorHTMLAttributes, type ChangeEvent, type KeyboardEvent, type ReactNode } from 'react';
|
import { useCallback, useEffect, useMemo, useRef, useState, type AnchorHTMLAttributes, type ChangeEvent, type KeyboardEvent, type ReactNode } from 'react';
|
||||||
import axios from 'axios';
|
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 ReactMarkdown from 'react-markdown';
|
||||||
import remarkGfm from 'remark-gfm';
|
import remarkGfm from 'remark-gfm';
|
||||||
import rehypeRaw from 'rehype-raw';
|
import rehypeRaw from 'rehype-raw';
|
||||||
|
|
@ -794,6 +794,7 @@ export function BotDashboardModule({
|
||||||
const [botListQuery, setBotListQuery] = useState('');
|
const [botListQuery, setBotListQuery] = useState('');
|
||||||
const [botListPage, setBotListPage] = useState(1);
|
const [botListPage, setBotListPage] = useState(1);
|
||||||
const [expandedProgressByKey, setExpandedProgressByKey] = useState<Record<string, boolean>>({});
|
const [expandedProgressByKey, setExpandedProgressByKey] = useState<Record<string, boolean>>({});
|
||||||
|
const [expandedUserByKey, setExpandedUserByKey] = useState<Record<string, boolean>>({});
|
||||||
const [feedbackSavingByMessageId, setFeedbackSavingByMessageId] = useState<Record<number, boolean>>({});
|
const [feedbackSavingByMessageId, setFeedbackSavingByMessageId] = useState<Record<number, boolean>>({});
|
||||||
const [showRuntimeActionModal, setShowRuntimeActionModal] = useState(false);
|
const [showRuntimeActionModal, setShowRuntimeActionModal] = useState(false);
|
||||||
const [workspaceHoverCard, setWorkspaceHoverCard] = useState<WorkspaceHoverCardState | null>(null);
|
const [workspaceHoverCard, setWorkspaceHoverCard] = useState<WorkspaceHoverCardState | null>(null);
|
||||||
|
|
@ -1304,11 +1305,16 @@ export function BotDashboardModule({
|
||||||
conversation.map((item, idx) => {
|
conversation.map((item, idx) => {
|
||||||
const itemKey = `${item.id || item.ts}-${idx}`;
|
const itemKey = `${item.id || item.ts}-${idx}`;
|
||||||
const isProgressBubble = item.role !== 'user' && (item.kind || 'final') === 'progress';
|
const isProgressBubble = item.role !== 'user' && (item.kind || 'final') === 'progress';
|
||||||
|
const isUserBubble = item.role === 'user';
|
||||||
const fullText = String(item.text || '');
|
const fullText = String(item.text || '');
|
||||||
const summaryText = isProgressBubble ? summarizeProgressText(fullText, isZh) : fullText;
|
const summaryText = isProgressBubble ? summarizeProgressText(fullText, isZh) : fullText;
|
||||||
const hasSummary = isProgressBubble && summaryText.trim().length > 0 && summaryText.trim() !== fullText.trim();
|
const hasSummary = isProgressBubble && summaryText.trim().length > 0 && summaryText.trim() !== fullText.trim();
|
||||||
const collapsible = isProgressBubble && (hasSummary || shouldCollapseProgress(fullText));
|
const progressCollapsible = isProgressBubble && (hasSummary || shouldCollapseProgress(fullText));
|
||||||
const expanded = Boolean(expandedProgressByKey[itemKey]);
|
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 displayText = isProgressBubble && !expanded ? summaryText : fullText;
|
||||||
const currentDayKey = new Date(item.ts).toDateString();
|
const currentDayKey = new Date(item.ts).toDateString();
|
||||||
const prevDayKey = idx > 0 ? new Date(conversation[idx - 1].ts).toDateString() : '';
|
const prevDayKey = idx > 0 ? new Date(conversation[idx - 1].ts).toDateString() : '';
|
||||||
|
|
@ -1356,21 +1362,28 @@ export function BotDashboardModule({
|
||||||
{collapsible ? (
|
{collapsible ? (
|
||||||
<LucentIconButton
|
<LucentIconButton
|
||||||
className="ops-chat-expand-icon-btn"
|
className="ops-chat-expand-icon-btn"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
setExpandedProgressByKey((prev) => ({
|
if (isProgressBubble) {
|
||||||
|
setExpandedProgressByKey((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[itemKey]: !prev[itemKey],
|
||||||
|
}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setExpandedUserByKey((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[itemKey]: !prev[itemKey],
|
[itemKey]: !prev[itemKey],
|
||||||
}))
|
}));
|
||||||
}
|
}}
|
||||||
tooltip={expanded ? (isZh ? '收起' : 'Collapse') : (isZh ? '展开' : 'Expand')}
|
tooltip={expanded ? (isZh ? '收起' : 'Collapse') : (isZh ? '展开' : 'Expand')}
|
||||||
aria-label={expanded ? (isZh ? '收起' : 'Collapse') : (isZh ? '展开' : 'Expand')}
|
aria-label={expanded ? (isZh ? '收起' : 'Collapse') : (isZh ? '展开' : 'Expand')}
|
||||||
>
|
>
|
||||||
{expanded ? '×' : '…'}
|
{expanded ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
|
||||||
</LucentIconButton>
|
</LucentIconButton>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</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.text ? (
|
||||||
item.role === 'user' ? (
|
item.role === 'user' ? (
|
||||||
<>
|
<>
|
||||||
|
|
@ -1380,7 +1393,7 @@ export function BotDashboardModule({
|
||||||
<div className="ops-user-quoted-text">{normalizeAssistantMessageText(item.quoted_reply)}</div>
|
<div className="ops-user-quoted-text">{normalizeAssistantMessageText(item.quoted_reply)}</div>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<div className="whitespace-pre-wrap">{normalizeUserMessageText(item.text)}</div>
|
<div className="whitespace-pre-wrap">{normalizeUserMessageText(displayText)}</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
|
|
@ -1475,6 +1488,7 @@ export function BotDashboardModule({
|
||||||
[
|
[
|
||||||
conversation,
|
conversation,
|
||||||
expandedProgressByKey,
|
expandedProgressByKey,
|
||||||
|
expandedUserByKey,
|
||||||
feedbackSavingByMessageId,
|
feedbackSavingByMessageId,
|
||||||
isZh,
|
isZh,
|
||||||
selectedBotId,
|
selectedBotId,
|
||||||
|
|
@ -1585,6 +1599,7 @@ export function BotDashboardModule({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setExpandedProgressByKey({});
|
setExpandedProgressByKey({});
|
||||||
|
setExpandedUserByKey({});
|
||||||
setShowRuntimeActionModal(false);
|
setShowRuntimeActionModal(false);
|
||||||
setWorkspaceHoverCard(null);
|
setWorkspaceHoverCard(null);
|
||||||
}, [selectedBotId]);
|
}, [selectedBotId]);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue