feat: 升级至 v0.3.16 — 工单修复 51 项 + 审查修复 30 项(安全加固/适配器/工具系统/数据层/前端)

This commit is contained in:
2026-07-22 10:31:13 +08:00
parent 516d8a728f
commit 2c2ca4a692
43 changed files with 1454 additions and 301 deletions
+6 -54
View File
@@ -9,13 +9,10 @@
*/
import { memo } from 'react';
import { Box, Typography, Stack } from '@mui/material';
import { Terminal } from 'lucide-react';
import type { ChatMessage } from '@renderer/stores/agent-store';
import { UserMessage } from './UserMessage';
import { AssistantMessage } from './AssistantMessage';
import { SystemMessage } from './SystemMessage';
import { formatTime } from '@renderer/lib/formatters';
interface MessageItemProps {
message: ChatMessage;
@@ -23,7 +20,7 @@ interface MessageItemProps {
isStreaming?: boolean;
}
function MessageItemImpl({ message, isLast, isStreaming }: MessageItemProps): React.JSX.Element {
function MessageItemImpl({ message, isLast, isStreaming }: MessageItemProps): React.JSX.Element | null {
switch (message.role) {
case 'user':
return <UserMessage message={message} />;
@@ -37,8 +34,11 @@ function MessageItemImpl({ message, isLast, isStreaming }: MessageItemProps): Re
);
case 'tool':
// 工具消息渲染为独立的结果块
return <ToolMessage message={message} />;
// #38 修复: 与 AgentStore.setCurrentSession 的过滤逻辑保持一致,
// 不在 UI 中渲染独立的 tool 消息卡片。
// tool 结果已包含在 assistant 消息的 toolCalls 中(见 AssistantMessage),
// 独立的 tool 消息仅用于 LLM API 上下文,不需要在前端显示为独立卡片。
return null;
case 'system':
default:
@@ -53,51 +53,3 @@ function MessageItemImpl({ message, isLast, isStreaming }: MessageItemProps): Re
* - isLast 是 boolean,仅在最后一条切换时变化
*/
export const MessageItem = memo(MessageItemImpl);
/** ToolMessage — 独立的工具结果消息(role=tool) */
function ToolMessage({ message }: { message: ChatMessage }): React.JSX.Element {
return (
<Box
sx={{
borderRadius: 1.5,
border: '1px solid',
borderColor: 'divider',
borderLeft: '3px solid',
borderLeftColor: '#22d3ee',
bgcolor: 'secondary.main',
px: 1.5,
py: 1,
mb: 2,
animation: 'fadeInUp 300ms ease-out',
}}
>
<Stack direction="row" spacing={1} sx={{ mb: 0.5, alignItems: 'center' }}>
<Terminal size={12} style={{ color: '#22d3ee' }} />
<Typography variant="caption" sx={{ fontWeight: 500, color: 'text.primary' }}>
</Typography>
<Typography variant="caption" sx={{ ml: 'auto', color: 'text.disabled' }}>
{formatTime(message.timestamp)}
</Typography>
</Stack>
<Box
component="pre"
sx={{
fontSize: 11,
borderRadius: 1,
px: 1,
py: 0.75,
overflowX: 'auto',
bgcolor: 'background.default',
color: 'text.secondary',
fontFamily: "'SF Mono',monospace",
maxHeight: 120,
m: 0,
whiteSpace: 'pre-wrap',
}}
>
{message.content.length > 500 ? message.content.slice(0, 500) + '\n... [截断]' : message.content}
</Box>
</Box>
);
}