Skip to content

feat(chat): 回复末尾「已编辑文件」卡片——文件引用富渲染,支持打开文件 / 文件树定位 / 查看 Diff#200

Merged
su-fen merged 3 commits into
Stack-Cairn:mainfrom
Bsyy95:feat/changed-files-card
Jul 21, 2026
Merged

feat(chat): 回复末尾「已编辑文件」卡片——文件引用富渲染,支持打开文件 / 文件树定位 / 查看 Diff#200
su-fen merged 3 commits into
Stack-Cairn:mainfrom
Bsyy95:feat/changed-files-card

Conversation

@Bsyy95

@Bsyy95 Bsyy95 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

背景

Agent 一轮回复里改了哪些文件,目前只能逐个展开 Write/Edit 工具卡片查看。这个 PR 为消息渲染补上"文件引用"这层富交互:在 Agent 回复末尾展示一张可交互的「已编辑 N 个文件」卡片(类似 Cursor 的 Changed Files 卡),并让工具卡片里的文件路径变为可点击的文件引用。

功能

回复末尾的 Changed Files 卡片(GUI + WebUI 双端):

  • 聚合整条回复所有 round 的 Write / Edit / Delete 成功结果:按路径去重(跨 round 合并、忽略正反斜杠与大小写漂移),每个文件复用与工具栏折叠徽标同一 diff 引擎的 +增/−删行数,头部显示总计;Delete 标记「已删除」,其后再 Write 视为重建
  • 流式回复实时更新:工具结果每落一个,卡片同步增长;失败/未完成的操作不计入
  • 卡片可折叠;头部提供「审核」按钮直接打开 Git Review 面板
  • 每行三个动作:点击行打开文件(工作区编辑器/预览)、在文件树中定位(展开祖先目录 + 高亮 + 滚动到可见)、查看 Diff(打开 Git Review 并聚焦该文件的工作区 diff)
  • 分享页只读视图不受影响:redactToolContent 时不渲染卡片;无动作上下文时降级为纯数据列表

文件引用可点击:Write/Edit 工具卡片展开后的 path 字段变为可点击引用,点击直接打开工作区编辑器(与卡片同一动作通道)。

实现方式

  • 新增 lib/chat/.../changedFiles.ts(双端同内容):纯函数 collectChangedFiles(rounds),路径取 toolResult.details.displayPath → relativePath → path → arguments.path;行数复用现有 deriveFileChangeStats(真 diff + 截断回退),并用 WeakMap 缓存每个 toolCall 的 diff,流式期间零重复计算
  • 新增 components/chat/ChangedFilesCard.tsx(双端同内容):卡片 + ChangedFilesActionsContext——动作经 React context 注入而非 props 下钻,转录行的 memo 边界零改动
  • Git Review 聚焦通道(三个镜像文件,字节级一致):RightDockContext 新增 git.focusRequest { path, nonce } / onFocusRequestHandledRightDockPanel 透传新 props;useGitReviewData 在面板激活且仓库状态就绪后切到 changes 视图并 selectPath(path) 加载该文件 diff,用 handled 回调 retire 请求,保证换项目/重挂载后绝不重放
  • 文件树定位复用现有 reveal 语义:openRightDockSingletonTab("fileTree") + updateRightDockFileTreeState({ selectedPath, expandedPaths: 现有∪祖先, bumpRevision }),与 Git Review 面板里的 "Reveal in File Tree" 行为一致
  • ChatPage / GatewayApp 各自注入三个动作(打开文件走既有 handleOpenWorkspaceFile),并挂载 Provider 包住转录组件

变更清单

  • 新增 crates/{agent-gui/src/lib/chat/messages,agent-gateway/web/src/lib/chat}/changedFiles.ts
  • 新增 crates/{agent-gui,agent-gateway/web}/src/components/chat/ChangedFilesCard.tsx
  • AssistantBubble(双端):回复末尾挂载卡片;FileToolArgs(双端):路径可点击
  • 镜像三件:RightDockContext.tsx / RightDockPanel.tsx / git-review/useGitReviewData.ts(聚焦通道,字节级同步)
  • ChatPage.tsx / GatewayApp.tsx:动作接线 + Provider + gitReview 聚焦状态
  • i18n 双端中英文各 10 条(chat.changedFiles.*
  • 测试:GUI changed-files.test.mjs(5 例:跨 round 聚合与合计、失败/未完成剔除、Delete 标记与重建、参数回退、displayPath 优先与去重)+ WebUI changed-files.test.mjs(双端契约一致性)

验证

  • GUI:pnpm build / pnpm lint(0 错误)/ pnpm test:frontend(1071 全过,含新增 5 例)
  • WebUI:pnpm build / pnpm lint(0 错误)/ pnpm test(368 全过,含新增 1 例)
  • node scripts/check-mirror.mjs(87 个镜像文件一致);git diff --check 干净;未改动 Rust / Go

基点说明

分支基于 #178 合并点切出(提交用的 PAT 无 workflow scope,无法把上游后续含 CI 工作流的提交推到 fork)。git merge-tree 与最新 main 预演:与 #190(stream-retry details)在 crates/agent-gui/.../AssistantBubble.tsxcrates/agent-gateway/web/src/app/GatewayApp.tsx 各有一处相邻插入的轻微文本冲突(import/props 追加,均 <10 行),其余文件干净。fork 的 main 同步后我可以随时 rebase 重推消除冲突,也欢迎在合并时顺手解决。

已知边界

  • +N/−N 是按操作累计的行数(与折叠工具栏徽标同源),同一文件多次编辑时为各次之和而非净 diff;「查看 Diff」里的 Git 工作区 diff 才是权威净变更
  • Git Review 聚焦按 Git 仓库根路径匹配文件;子目录仓库场景下若工具路径相对会话工作区而非仓库根,会打开 changes 视图但不预选该文件(与现有面板行为一致)

…e actions

Co-authored-by: Cursor <cursoragent@cursor.com>
@Bsyy95
Bsyy95 force-pushed the feat/changed-files-card branch from eb39c05 to b82d1f1 Compare July 21, 2026 10:17
Bsyy95 and others added 2 commits July 21, 2026 19:27
…-type icons, two-line header, scrollable list

Co-authored-by: Cursor <cursoragent@cursor.com>
…e transcript

Add overscroll-contain to the card's inner scroll container in both
frontends; also restore the web copy's comment that had been
mojibake-corrupted in the previous commit.
@su-fen
su-fen merged commit 94f6675 into Stack-Cairn:main Jul 21, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants