Skip to content

feat!: 文件变动统一 tab——Git 面板 + 文件追踪(PR #471)二为一,统一 diff 渲染栈 - #475

Merged
Menghuan1918 merged 4 commits into
mainfrom
feat/unified-file-changes
Aug 31, 2026
Merged

feat!: 文件变动统一 tab——Git 面板 + 文件追踪(PR #471)二为一,统一 diff 渲染栈#475
Menghuan1918 merged 4 commits into
mainfrom
feat/unified-file-changes

Conversation

@Menghuan1918

Copy link
Copy Markdown
Collaborator

摘要

#471(file-trace tab)基础上的演进:将「源代码管理」面板与「文件追踪」合并为一个「文件变动」tab,一个 tab、双视角回答"改了什么"——Git 视角(仓库真相)与本轮文件视角(agent 真相)。同时把仓库里的两套 diff 渲染(DiffView 无高亮 vs filetrace 自带引擎)统一为一套共享渲染栈,git diff 从此也获得语法着色、改写配对与行内字符级高亮。

本 PR 包含 #471 的全部提交并在其上重构;合并本 PR 即可,#471 可关闭feat!: 8→7 tab,file-trace id 从未发布,无迁移负担;git tab id 保留,持久化布局不受影响)。

双视角设计

┌──────────────────────────────────┐
│ [ Git | 本轮文件 ]  ← 分段切换器   │
├──────────────────────────────────┤
│  Git 视角:worktree/分支选择、     │
│  staged/unstaged、提交框、历史     │
│  (或)本轮文件:筛选 chips、       │
│   按文件分组的操作时间线            │
├──────────────────────────────────┤
│ ▁▁ 拖拽把手 ▁▁                    │
│ 路径/to/文件.ts  +12 −3  ⟳ ↗ ✕   │  ← 共享预览面板
│  12 - const old = 1              │
│  13 + const next = 2   (高亮)     │
└──────────────────────────────────┘
  • Git 视角 = 原 GitView 全量能力(staged/unstaged、stage/unstage、提交 Ctrl+Enter、checkout、历史分页、右键菜单全部保留:打开编辑器/暂存/放弃/复制路径、还原/捡取提交 + 确认弹窗;worktree 原子性/竞态防护原样迁移并有测试钉住)。
  • 本轮文件视角 = 原 file-trace(会话事件日志实时折叠、最新在前、按文件分组),新增:类型筛选 chips(全部/写入/编辑/读取,带计数)、相对时间、选中行高亮。
  • 交互升级:点击文件/提交/操作 → 底部可拖拽预览面板就地查看(不再直接开 diff tab,扫读不换上下文);面板头部 +n −m 统计、git 目标带刷新与**「展开为独立 diff tab」**(,保留原 VSCode 式 diff tab 流程,同一渲染栈);面板高度可拖拽/方向键调节并持久化;视角选择与面板高度存 tab.meta,重开还原。
  • 角标(badge)= 本会话文件操作数(事件日志实时推导);git 行 XY 徽章按状态字母着色(A 绿/D 红/M·R 蓝/C·U 橙)。

统一 diff 栈(src/client/diff/

  • rows.ts(引擎,纯函数):共享 DiffRow 模型(context/del/add/mod/meta);行级 LCS diffLines + pairMods 改写配对;buildDiffSegments hunk/折叠分段;前缀后缀行内 diff;parseUnifiedDiff(形状不变,原测试原样通过)+ 新 unifiedSegments 转换器——git hunk 行映射为共享行模型并在 hunk 内做 mod 配对,hunk 之间 git 未输出的上下文按行号范围生成不可展开的折叠标记;diffStats 统计。
  • DiffRows(单文件渲染器):折叠 chips、长行折叠、语法着色(跨行块注释状态按侧线程推导)、mod 行内字符级高亮——修复了 feat: 新增内置 tab「文件追踪」——会话文件操作记录与逐行 diff(移植 dsh-file-trace) #471 移植中旧侧行内高亮失配的问题(字符串键 "old|" 永远查不到 "old|new",改为行对象身份键);巨 diff 行数上限 + 展开按钮。
  • DiffFiles(多文件文档):原 DiffView 的文件级折叠语义保留(源码默认展开、测试/文档/生成物默认折叠,行为有测试钉住),文件头新增 +n −m 统计 chips;未跟踪文件全文新增回退保留。
  • DiffTab 改用该栈——独立 diff tab 与预览面板渲染完全一致。
  • 视觉:行底色 8% tint(对齐原 git diff 的 tint 语言)+ 文字色 + 语法色(color-mix 落位 diff 三色空档);仅 --dsw-alias-* / --ds-* 令牌(皮肤契约)。

结构与约束

  • 新目录:src/client/changes/(ChangesTab 壳 / GitLens / SessionLens / DiffPane / ops)+ src/client/diff/;删除 GitView.tsx / DiffView.tsx / filetrace/;git 样式从 sidebar.module.css 迁至 changes.module.css(DiffTab 壳样式留守)。
  • i18n:fileTrace* 十键重命名 changes*git 键值更新为「文件变动 / Changes」,新增 7 键(视角/筛选/面板操作),全部 21 个词典同步(locales key-set 测试通过)。
  • 文档:README ×2 功能矩阵合并、external-plugin-guide §4.4 内置表与清单(7 tab)、mount e2e + 菜单标题同步。

验证

  • pnpm typecheck ✅;pnpm build ✅(纯度门通过)
  • 全量 pnpm test106 文件 / 1122 用例全部通过(9 skipped 为环境条件跳过)
  • 新增/迁移测试:diff-rows.spec.ts(unified 转换/mod 配对/间隙折叠/统计 7 例)、changes-tab.spec.tsx(壳交互 jsdom 2 例:git 行点击→面板预览、视角切换)、diff-files-collapse.spec.tsx(原折叠行为钉住)、changes-ops.spec.ts(原 filetrace 数据层 9 例)、git-view-worktree.spec.tsx(GitLens 迁移)、builtins.spec.ts(7 tab + git badge pin)
  • mount e2e(plugin-mount lane)将在 CI 验证真实挂载

lhh010 and others added 3 commits August 30, 2026 20:59
- 数据层:直接折叠会话事件日志(tool/call + tool/result 对)提取文件操作,
  与仓库「读事件日志而非动注册表」的取向一致;含错误文本捕获与
  running 态实时更新(ctx.on('session/event'),不可见时暂停、恢复时追平)
- 视图:操作列表 + 底部可拖拽 diff 面板;行级 diff(删红/增绿/改蓝)+
  行内字符级高亮;读取视图带真实行号;失败操作统一展示真实错误文本
- 语法着色:轻量分词器(关键字/字符串/数字/类型/函数/注释/预处理),
  色相经 color-mix 落在 diff 三色之间的空档;跨行块注释状态按行序推导
- 单实例 tab,+ 菜单 order 55,角标显示操作数;设置页可整体关闭
  (与独立维护的 dsh-file-trace 插件共存)
- i18n:10 个新 key 同步全部 21 个词典;builtins 测试 7→8;
  README/指南内置清单同步
…uide version line (keep 8-tab count, adopt v0.18.0-alpha.0 alpha-track wording)
在 PR #471(file-trace)基础上的演进:

- 合并 tab:git tab(id 保留,兼容持久化布局)升级为「文件变动」双视角
  tab——Git 视角(原 GitView 全部能力:staged/unstaged/提交/历史/worktree·
  子仓库选择/右键菜单/确认弹窗)+ 本轮文件视角(原 file-trace:会话事件
  日志实时折叠的模型读写编辑记录,按文件分组、新增类型筛选 chips、相对
  时间);file-trace tab 移除(未随任何版本发布)。
- 统一 diff 组件:新 src/client/diff/ 模块(rows.ts 引擎 + DiffRows/
  DiffFiles 渲染器 + highlight.ts 语法着色)——git diff 与会话操作 diff
  共用一套渲染:mod 改写配对(del-run/add-run 对半标蓝)、行内字符级
  高亮(修复了旧实现旧侧失配不高亮的问题,改为行对象身份键)、上下文
  hunk 折叠、git hunk 间未输出区间按行号范围生成不可展开折叠、语法着色
  色相落位 diff 三色空档、+n −m 统计 chips、行底色 tint;DiffTab 改用
  该栈(git diff tab 从此也有高亮)。
- 交互:两视角共用底部可拖拽预览面板(点击文件/提交/操作即预览,不再
  直接开 diff tab;面板可刷新、可键盘/拖拽调高、git 目标可一键展开为
  独立 diff tab);视角选择与面板高度持久化在 tab.meta;git 行 XY 徽章
  按状态字母着色;选中行高亮。
- i18n:fileTrace* 十键重命名为 changes* 前缀,git 键值更新为「文件
  变动」,新增 7 键(视角/筛选/面板操作),全部 21 个词典同步。
- 结构:src/client/changes/(ChangesTab/GitLens/SessionLens/DiffPane/
  ops)+ src/client/diff/;GitView/DiffView/filetrace/ 删除;git 样式
  从 sidebar.module.css 迁至 changes.module.css。
- 测试:builtins 8→7(git tab 承接 badge pin)、diff-rows(unified
  转换/mod 配对/间隙折叠/统计)、changes-tab(壳交互 jsdom)、
  diff-files-collapse(原 DiffView 折叠行为钉住)、changes-ops(原
  filetrace 数据层)、git-view-worktree 迁移至 GitLens;全量 1122 通过。
- 文档:README ×2 功能矩阵合并、external-plugin-guide §4.4 与内置清单
  7 tab、mount e2e 菜单标题同步。
@lhh010

lhh010 commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

感谢修复!关于「旧侧行内高亮失配(字符串键 "old|" 永远查不到 "old|new")」这条,我核验了一下 #471 移植版与独立插件 dsh-file-trace(https://github.com/lhh010/dsh-file-trace)的同源实现,供参考:

  • 两边的建键与查键都从同一批行对象、同一表达式派生(diffLines 产出的 del 行只带 oldLine、add 行只带 newLine,pairMods 仅改 kind 不动字段),所以行级键是半键——del 侧 "old|"、add 侧 "|new",两侧必然一致。刚在独立插件侧用一次性测试实证:真实 diff 的每个 mod 行 inline 查找全部命中。
  • 因此 "old|" vs "old|new" 的失配应该是本 PR 把渲染迁入 DiffPane/DiffRows 时引入的(配对级 old|new 键 vs 行级半键),在你们分支上修正当其时——feat: 新增内置 tab「文件追踪」——会话文件操作记录与逐行 diff(移植 dsh-file-trace) #471 / 独立插件无需回改
  • 认同改用行对象身份键:比字符串键更抗未来的行对象重构,也顺带消除了理论上同号行撞键的边角。

双视角 + 统一 diff 栈的设计很赞,期待合并 🎉

CI 修复(plugin-mount 的 ctx.sessions.get TypeError ×1003):
- 客户端 runtime 无事件日志面——badge/SessionLens 原在客户端直读
  ctx.sessions.get(id).events / ctx.on('session/event'),全部不可达。
- 新增宿主路由 changes.ops:live 会话日志优先,冷会话回放
  sessionPersistence.inspect;afterSeq 增量(缺省游标含 seq 0,
  显式游标为 seq > afterSeq,同 sidechat.events 约定),窗口上限
  4000 与客户端累加器一致。
- ChangesTab 轮询(mount 一拉 + visible 2.5s 增量)折入 ops,写
  模块级 opCounts 缓存供 badge 同步读取;SessionLens 改纯展示。

diff 展开二级设置(changesDiffFloat,默认浮窗):
- prefs 四处接线 + git tab settings select(浮窗/面板,图标选项卡)
- 预览面板「展开为 diff tab」按设置落点:浮窗居中弹出或源 pane
  下方 split;i18n 全 21 词典同步。

视觉迭代(真机挂载截图审查后调整):
- Session 视角:kind 徽章为左轨,大小+相对时间右对齐元列;失败
  操作行红色内嵌条;文件组头降为三级标签并加组间距。
- Git 视角:untracked '?' 徽章与新增同绿色;stage 按钮改 plus 图标。
- diff 折叠行:可展开折叠带 › 箭头 + 次级对比度,静态 gap 不再
  显示 pointer/hover;预览头路径改尾部截断(RTL 技巧,保文件名)。

验证:typecheck ✓ / vitest 1123 ✓ / pnpm test:mount(钉 alpha.2 CLI)
14/14 ✓;真机挂载截图(badge=5、双视角、浮窗展开)0 console error。
@Menghuan1918

Copy link
Copy Markdown
Collaborator Author

三项后续已完成(f024fbf):

1. CI 修复(plugin-mount 失败根因)

  • 报错 ctx.sessions.get is not a function ×1003 的根因:客户端 runtime 的 sessions 面没有 .get,也不广播 session/event——feat: 新增内置 tab「文件追踪」——会话文件操作记录与逐行 diff(移植 dsh-file-trace) #471 的 badge/文件追踪在客户端直读这两者,挂到默认布局的 git tab 上后每个渲染 tick 都抛错。
  • 修法与 sidechat 同策:新增宿主路由 changes.ops(live 会话日志优先、冷会话回放 sessionPersistence.inspectafterSeq 增量,缺省游标含 seq 0),ChangesTab 轮询折入 ops 并写同步缓存供 badge 读取;SessionLens 改纯展示。
  • 验证:pnpm test:mount(钉 @deepseek-ai/dsh@0.1.2-alpha.2)14/14 ✓。

2. diff 展开二级设置(默认浮窗)

  • 「文件变动」tab 设置新增 select:自由浮窗(默认,居中弹出可拖拽)/ 面板(源 pane 下方 VSCode 式 split),图标选项卡样式同 editorExplorer。
  • prefs 四处接线 + 全 21 词典同步。

3. 视觉/UX 迭代(真机挂载逐张截图审查)

  • 搭了真机截图环境(scratch profile + demo 仓库多状态 + 伪造带 tool 事件的持久化会话),逐张审查 Git 视角 / Session 视角 / 预览面板 / 浮窗展开 / 错误态后迭代:
    • Session 视角操作行改为「kind 徽章左轨 + 大小/时间右对齐元列」,失败操作加红色内嵌条,文件组头降级并加间距;
    • Git 视角 untracked ? 徽章改绿色(与新增一致)、stage 按钮 branch→plus 图标;
    • diff 折叠行加 箭头与更强对比,静态 gap 不再伪装可点击;
    • 预览头路径改尾部截断(长路径保文件名)。
  • 复拍验证 + 全程 0 console error;badge(本轮操作数)、双视角、浮窗展开均实拍确认。

全量验证:typecheck ✓ / vitest 1123 ✓ / mount e2e 14/14 ✓。

@Menghuan1918
Menghuan1918 merged commit d70db8f into main Aug 31, 2026
2 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