feat(agent): update image message display to compact thumbnails with click-to-zoom preview

This commit is contained in:
HouYunFei
2026-07-29 15:26:26 +08:00
parent 5a607bea6c
commit fa58ec4715
3 changed files with 25 additions and 7 deletions
+2
View File
@@ -2,6 +2,8 @@
## Unreleased
+ [优化] Agent 用户图片消息改为紧凑缩略图展示,并支持单击放大预览。
+ [修复] 修复 Agent 图片预览打开后在对话区域产生额外空行的问题。
+ [优化] Canvas Agent 内置 Codex CLI 升级至 0.145.0。
+ [修复] Canvas Agent 停止任务改为中断当前 Codex turn,避免终止整个 App Server 进程。
+ [新增] Canvas Agent 支持通过 `--debug` 输出详细日志并按日期保存到本地日志文件。
+1 -1
View File
@@ -15,7 +15,7 @@ description: 当前版本已实现但仍需人工验证的变更项
- Agent 历史记录:点击记录卡片应直接进入对应对话,不再显示「进入」按钮;可勾选单条或全选多条记录并批量删除,删除当前对话后聊天内容应清空。
- Agent 默认新对话:每次进入任一画布并连接 Agent 后,对话区应保持空白且不自动恢复上一次会话;第一次发送消息时才创建新线程,不应产生未发送消息的空历史记录;需要继续旧对话时可在「历史」中主动选择恢复。
- Agent 当前画布优先:在已打开某个画布时要求 Agent 创建、修改、整理或生成内容,Agent 应直接读取并操作当前画布,不应先调用 `canvas_list_projects` 或使用 `site_navigate` 重复进入画布;只有明确要求查看或切换其他画布时才允许查询画布列表并导航。
- Agent 图片消息:发送一张或多张图片附件后,图片应紧跟用户文字并在消息右侧按原比例展示;任务运行中、完成同步历史、切换页面及重新进入历史对话后都应显示浏览器本地保存的图片缩略图,不应消失或把 attachmentId、附件使用说明等内部上下文回显到用户消息中;删除历史会话后应同步清理对应缩略图。
- Agent 图片消息:发送一张或多张图片附件后,图片应紧跟用户文字并在消息右侧显示为约 40px 的紧凑缩略图,不再撑大消息区域,单击缩略图应打开大图预览,打开或关闭预览不应改变消息间距或产生额外空行;任务运行中、完成同步历史、切换页面及重新进入历史对话后都应显示浏览器本地保存的图片缩略图,不应消失或把 attachmentId、附件使用说明等内部上下文回显到用户消息中;删除历史会话后应同步清理对应缩略图。
- 画布文本复制:在 Agent 对话或节点信息详情中用鼠标选中文字后,按 `Ctrl/Cmd + C` 应复制所选文本,不应触发画布节点复制;未选中文字且焦点位于画布时,原有节点复制快捷键应保持可用。
- Agent 工作目录指令:`canvas-agent/agent-instructions.md` 应作为独立维护源;重启 Canvas Agent 后,当前工作目录应自动生成 `AGENTS.md`;新建对话发送消息时,Codex 日志中的用户消息只包含本轮请求和必要的附件上下文,不再重复整段 Infinite Canvas 前置提示词,画布及工作台工具仍可正常调用。
- 画布文本设置:文本节点和生成配置节点切换到文本模式后应显示推理强度设置,可选择自动、低、中、高、极高;选择自动时默认 OpenAI Responses 请求不应携带 `reasoning`,选择其他档位时应携带所选强度,刷新画布后节点设置应保留;文本模型自定义调用脚本应能读取 `reasoningEffort`OpenAI 模板应按自动或指定档位正确组装请求。
@@ -1,5 +1,5 @@
import { useEffect, useState, type ReactNode } from "react";
import { Button } from "antd";
import { Button, Image } from "antd";
import { Brain, CheckCircle2, ChevronDown, Circle, CircleAlert, FilePenLine, FileText, ListChecks, LoaderCircle, Search, TerminalSquare, UserRound, Wrench, XCircle } from "lucide-react";
import { Streamdown } from "streamdown";
@@ -240,12 +240,28 @@ function AgentUserAvatar({ user, theme }: { user: LocalUser | null; theme: (type
}
function AgentMessageAttachments({ attachments, alignRight }: { attachments: AgentChatAttachment[]; alignRight?: boolean }) {
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
return (
<div className={`mt-2 flex flex-wrap gap-2 ${alignRight ? "justify-end" : "justify-start"}`}>
{attachments.map((item) => (
<img key={item.id} src={item.url} alt={item.name} className="max-h-72 max-w-[280px] rounded-xl object-contain" />
))}
</div>
<>
<div className={`mt-1.5 flex flex-wrap gap-1.5 ${alignRight ? "justify-end" : "justify-start"}`}>
{attachments.map((item) => (
<img
key={item.id}
src={item.url}
alt={item.name}
title="点击查看大图"
className="size-10 cursor-zoom-in rounded-lg object-cover"
draggable={false}
onClick={() => setPreviewUrl(item.url)}
/>
))}
</div>
{previewUrl ? (
<div className="hidden">
<Image src={previewUrl} alt="图片附件预览" preview={{ visible: true, src: previewUrl, onVisibleChange: (visible) => !visible && setPreviewUrl(null) }} />
</div>
) : null}
</>
);
}