Skip to content

feat(macos): Agent 对话显示工具图片缩略图、点击放大,并将后台任务通知显示为状态行 (#1462) - #1472

Merged
xiaoyumuxi merged 9 commits into
previewfrom
feat/1462-agent-display-images
Oct 24, 2026
Merged

xiaoyumuxi merged 9 commits into
previewfrom
feat/1462-agent-display-images

Conversation

@xiaoyumuxi

@xiaoyumuxi xiaoyumuxi commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

Refs #1462

改动点

  • 工具图片缩略图:ACP 工具结果里的 image 内容块不再丢弃。工具行和工具组标题右侧显示缩略图,最多 3 张,其余以 +N 表示(最新的在右)。只给出路径的 read 工具调用(图片文件)直接显示该文件。折叠的“思考过程”标题行右侧也显示缩略图,否则默认折叠时看不到。
  • 悬停预览:复用 workbenchHoverCard,显示大图、标题和“第 i 项,共 n 项”。
  • 点击放大:转录区域内的覆盖层查看器,支持双指捏合缩放(相对适应窗口 25%–800%)、拖动平移、双击切换、百分比显示与复位、⌘+/⌘−/⌘0、左右方向键切换、Esc 和点击遮罩关闭。
  • 用户消息图片:📎 路径、[@名字](file:///路径)、裸 file:// 地址和 Claude Code 的 [Image: source: …] 指向图片文件时显示为缩略图并可放大;[Image: original …] 尺寸说明去掉;其余文字保持不变。
  • Claude Code 特殊消息格式(整条消息都是这些标记时才替换,用户自己输入的文字不受影响):
    • 后台任务通知 <task-notification>、斜杠命令、本地命令输出、Shell 转义、中断提示:状态行或输出块
    • 压缩续接摘要、技能展开、宿主上下文:折叠块
    • <system-reminder>、<local-command-caveat> 等只给模型看的块:不显示(接在用户文字后面时只去掉该块)
  • 后台任务通知换了显示方式:成功的通知不再单独成行,并入随后一轮的折叠“思考过程”,展开后按原顺序显示;失败、被终止或后面没有任何过程的通知仍保持可见。Claude 的英文 shell 任务摘要按界面语言显示(后台命令已完成:…),新增翻译在 shared/i18n。
  • 恢复 Claude 会话时显示压缩前的完整历史:SDK 回放只走最后一个压缩点之后的链,更早的记录在磁盘上却不会到达客户端。Rust 宿主在 session/load 前只读取会话文件中最后一个压缩点之前的记录,转成与回放一致的更新,每次压缩处显示“对话已从摘要继续”。这是对“宿主不读转录文件”约定的有限例外:只读 projects/*/<会话 id>.jsonl(按所选账号目录解析),不碰登录信息、不写入、不缓存;超过 128 MiB 的文件跳过,最多 30000 条更新,工具输入输出截断;解析失败只是不显示更早历史。边界与理由写进 Agent Note。
  • 新增翻译:放在 shared/i18n 并重新生成。
  • 图片数据有上限(单张 10 MB、每条消息 24 张),缩略图在后台线程用 ImageIO 解码并缓存,历史回放不解码。
  • 更新功能矩阵 agent-tool-activity-timeline 与 Agent Note(Windows 待对齐)。

关于 issue 第 2 项(多余复制按钮)

当前 preview 上 #1464 已把过程说明收进默认折叠的过程区,空白回复也不再生成行,截图场景不再出现,所以本 PR 没有改复制按钮规则。

验证

  • 新增 Rust 测试 claude_earlier_history(4 项)和 Swift 测试(后台通知分组、失败/孤立通知保持可见、摘要改写);lithe-agent-host 全部 238 项通过,聚焦的 78 项 Swift 测试通过
  • 压缩前历史尚未在真实 Claude 会话里手动验证,需要评审者用经历过多次压缩的会话确认
  • 相关测试套件(含新增 AgentImageTests 14 项)通过
  • verify-agent-notes.sh、verify-platform-feature-matrix.sh、矩阵变更门禁、verify-service-boundaries.sh、测试稳定性静态检查、i18n 检查均通过
  • 用 package-app.sh 打包并启动过本地实例,真实 Agent 会话中的悬停、缩放和格式显示仍需评审者手动确认;Windows 未实现

兼容 Claude Desktop 开始的会话(00f503dca)

Desktop 会话里模型几乎不直接输出文字,压缩前的段落在 Lithe 里只剩折叠的“思考过程”。本次改动:

  • wrap_up 显示为回复:宿主新增 claude_desktop.rs,把 mcp__ccd_turn__wrap_up 的 recap/ask 改写成 Agent 回复,并吞掉该调用后续的 tool_call_update
  • update_plan 显示为计划清单:整表(items)和增量(done/start/advance)调用都改写成完整的 ACP plan 更新;增量调用之前没有整表时保持原样。适配器回放和压缩前文回放都走这条路径,Windows 共用同一个宿主
  • 回放排队消息:压缩前文回放补上对话中途排队的用户消息(queued_command attachment),工具调用带上 name
  • macOS 转录:历史回放时计划快照作为清单显示在两段折叠过程之间;导出 Markdown 时写成任务列表;不计入历史消息数
  • 过程标题摘要:折叠的“思考过程”后面显示工具摘要(如“运行了 3 条命令,编辑了 2 个文件”)
  • Agent Note 已同步更新

验证:cargo test -p lithe-agent-host(242 通过)、AgentImageTests 和 AgentHistoryTests(58 通过)、verify-agent-notes.sh、verify-test-stability.sh

@ghfind-review ghfind-review Bot added the review: medium ghfind author score; see https://ghfind.com label Oct 24, 2026
@xiaoyumuxi
xiaoyumuxi marked this pull request as ready for review October 24, 2026 13:21
@lithe-code-review

lithe-code-review Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Lithe Review

结论: ⚠️ 有建议
范围: preview ← feat/1462-agent-display-images · head: 308080b

Findings

  1. [P2] 按消息上限截断后再解码图片
    macos/Sources/LitheAgentConversationModule/Application/AgentSessionConfiguration.swift:113

    • 实际影响:工具更新最多可包含 100 个内容块;当前先为其中每个有效图片块解码并构造 AgentImage,最后才截到 24 张。若更新包含 100 张接近 10 MB 上限的图片,可能产生约 1 GB 的额外解码数据和哈希计算,造成明显内存峰值甚至进程退出,超过了声明的每消息图片预算。
    • 触发条件:ACP 工具更新携带超过 24 张、且每张都接近单张大小上限的内联图片。
    • 复现步骤:向工具更新提供 100 个合法、各自解码后接近 10 MB 的 image 内容块;compactMap 会在 prefix(24) 之前解析全部内容。
    • 来源:本次引入
  2. [P2] 文件图片缓存键应包含文件版本
    macos/Sources/Lithe/Views/Agent/AgentImageViews.swift:67

    • 实际影响:文件图片的 AgentImage.id 只由路径构成(AgentImage.swift:30),缓存键又只由该 ID 和像素尺寸构成。图片文件被原位覆盖后,后续读取同一路径仍会命中旧的缩略图、预览或放大图,显示内容与 Agent 最新读取结果不符。
    • 触发条件:Agent 读取某个图片文件后,该文件被替换或修改,再次读取相同路径。
    • 复现步骤:打开路径为 /workspace/diagram.png 的图片,再覆盖该文件并让 Agent 再读一次;新视图会从 NSCache 取得旧路径对应的 rendition。
    • 来源:本次引入
  3. [P2] 矩阵不能把 macOS 新能力显示为 Windows 已实现
    shared/platform-feature-matrix/features/agent-tool-activity-timeline.json:5

    • 实际影响:新增的图片展示和放大能力没有 Windows 实现,但该能力被加入原有跨平台能力描述,Windows 的 implementationStatus 仍是 implemented(第 32 行)。矩阵会因此把 Windows 图片支持显示为已实现;同一变更中的验证说明和 Note 却写明 Windows 尚未实现。
    • 触发条件:查看或生成该能力的 Windows 平台矩阵视图。
    • 复现步骤:读取该矩阵记录;它同时描述图片查看能力、标记 Windows 已实现,并注明 Windows 对应能力尚未实现。
    • 来源:本次引入

Scope Check

  • 关联 Issue 或需求是否完成:Issue [Feature] Agent 显示逻辑补充 #1462 的图片缩略图、预览/放大及后台任务通知已接入实现;重复复制按钮规则未在本 PR 修改,PR 上下文称其由 fix(agent): 合并每轮思考与工具过程,默认折叠展示 #1464 处理。真实 Agent 运行验收尚未完成。
  • 已完成范围:工具结果和用户消息图片展示、图片查看器、后台任务通知状态行及对应本地化与说明。
  • 未完成范围:Windows 图片/通知能力未实现;视觉验收未提供截图;Issue 中复制按钮项不属于本 PR 的实现范围。
  • 是否复用了已有上游能力,或对自研边界给出充分证据:这是 macOS 展示层与 ACP 内容解析,未发现本次新增 IDE 领域引擎或重复实现问题。
  • 每个 Finding 是否由本次变更引入或加剧:是,三项均由新增解析/缓存行为或扩展矩阵描述引入。
  • 是否属于本次变更职责范围:是,涉及图片资源预算、图片展示正确性和同 PR 更新的平台能力矩阵。

Suggestions

  1. 在解析前限制实际接受的图片数量;遍历内容块时达到 24 张后停止解码,而不是先 compactMap 全部图片再截断。
  2. 为文件来源使用包含文件版本信息的缓存身份,或在图片更新时使对应路径的缓存失效。
  3. 将新图片能力拆成单独矩阵记录,并把 Windows 标为 platform-specific(若只属于 macOS)或 partial;保留既有时间线能力的状态。
  4. 按仓库审查要求,请 PR 作者补充受影响界面的截图;现有 Issue 截图是需求参考,不能验证本 PR 的视觉效果。

Summary

实现把图片解析、惰性解码和转录层展示分开放置,并增加了针对解析与通知文本的单元测试。仍需收紧图片计数上限的实际执行时机、避免文件路径缓存产生过期图像,并修正矩阵对 Windows 覆盖范围的表达。没有发现 P0/P1 阻塞问题。

Verification

  • 实际检查的文件、提交和调用链:按指定 53f7052a...308080b26 范围检查 15 个文件;追踪 AgentToolDetails.merge、用户消息 ACP 更新、转录行/工具行、ImageIO 解码缓存、Agent Note 和平台矩阵。
  • 已提供的测试或 CI 结果:PR 上下文报告 macOS 相关套件 59 项通过及若干静态检查通过;这些结果未在本次独立验证。所列 head Checks 中 Swift tests 为 skipped,macOS CI gate 为 success。
  • 本次未运行的测试:所有测试、构建、应用运行和矩阵生成/验证均未运行,遵守只读要求。
  • 仍存在的非阻塞风险或平台验证缺口:未提供本 PR 新界面的截图,视觉效果尚未验证;PR 上下文称未进行真实 Agent 运行验收;Windows 新能力尚未实现。

@xiaoyumuxi

Copy link
Copy Markdown
Collaborator Author
image

@xiaoyumuxi

Copy link
Copy Markdown
Collaborator Author
image image image

xiaoyumuxi added a commit that referenced this pull request Oct 24, 2026
- 图片 id 去重,避免 ForEach 重复 id
- 指纹改用 SHA-256,避免主线程逐字节循环
- 用户消息解析结果按消息缓存
- 查看器 ←/→ 仅在持有焦点时翻页,拖动限制在画面边缘内
- 只移除消息首尾的模型专用块,不吞用户中间引用的标签
- 图片按原文位置排序,超出上限的引用显示 +N
- read 只对存在的文件生成缩略图,解码失败显示占位
- 缓存限制成本,键含修改时间,解码任务随行取消
- 内联数据须能被 ImageIO 识别,否则退回文字条目

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- 图片 id 去重,避免 ForEach 重复 id
- 指纹改用 SHA-256,避免主线程逐字节循环
- 用户消息解析结果按消息缓存
- 查看器 ←/→ 仅在持有焦点时翻页,拖动限制在画面边缘内
- 只移除消息首尾的模型专用块,不吞用户中间引用的标签
- 图片按原文位置排序,超出上限的引用显示 +N
- read 只对存在的文件生成缩略图,解码失败显示占位
- 缓存限制成本,键含修改时间,解码任务随行取消
- 内联数据须能被 ImageIO 识别,否则退回文字条目
@xiaoyumuxi
xiaoyumuxi force-pushed the feat/1462-agent-display-images branch from 3ce110b to 6451723 Compare October 24, 2026 14:58
xiaoyumuxi and others added 4 commits October 24, 2026 23:06
- 成功的后台任务通知不再单独成行,进入随后一轮的折叠“思考过程”;失败、被终止或后面没有过程的通知仍显示
- Claude 的英文 shell 任务摘要按界面语言显示(后台命令已完成:…)
- Rust 宿主在 session/load 前只读取会话文件中最后一个压缩点之前的记录,转成回放更新,压缩前的用户消息、回复、思考和工具调用都能查看
- 读取范围:只读 projects/*/<会话 id>.jsonl,按所选账号目录解析,大小和条数有上限
- 新增翻译放在 shared/i18n,更新功能矩阵与 Agent Note

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
连续的用户消息(例如后台通知后紧跟用户输入)在回放时被拼成一个气泡,导致通知标记无法识别而显示原文。
按上游 messageId 区分用户消息;压缩前的历史也带上记录 uuid。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- 宿主把 mcp__ccd_turn__wrap_up 改写成 Agent 回复,吞掉其后续 tool_call_update
- 宿主把 mcp__ccd_turn__update_plan(整表/增量)改写成完整 ACP plan 更新
- 压缩前文回放补上对话中途排队的用户消息(queued_command),工具调用带上 name
- 历史回放时计划快照作为清单显示在折叠过程之间,导出为任务列表,不计入消息数
- 折叠的过程标题附工具摘要(如运行了 N 条命令)
@xiaoyumuxi
xiaoyumuxi merged commit 83017af into preview Oct 24, 2026
13 of 18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review: medium ghfind author score; see https://ghfind.com

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant