feat(composer): replicate WorkBuddy branch label and context usage (TODO 21)

This commit is contained in:
xiaohan.yuan committed 2026-10-17 08:15:19 +08:00
1 parent cb8a7e6466
commit bde041c12d
21 files changed
+1350 -12

No files matched your search

+47 -6
View File
@@ -392,16 +392,57 @@
### 21. 对话框 Git 分支检测与会话上下文信息
- [ ] 通过 REA 拆解 WorkBuddy 对话框中 Git 分支和会话上下文信息的显示位置、图标、字体、间距、提示及交互。
- [ ] 根据当前任务绑定的工作目录检测 Git 仓库和实际分支;核对原版对非 Git 目录、未产生首次提交、detached HEAD、检测失败等状态的处理。
- [ ] 明确原版“上下文信息”的实际字段、数据来源、更新时机和展示方式,再接入 YCode 的真实会话数据;上下文用量等字段如存在,必须区分真实统计与估算。
- [ ] 验收:新建任务、已有会话、切换空间/任务、外部切换 Git 分支后的信息归属与刷新正确;无仓库时不显示虚构分支;浅色/深色及窄窗口布局与原版对齐。
- [x] 通过 REA 拆解 WorkBuddy 对话框中 Git 分支和会话上下文信息的显示位置、图标、字体、间距、提示及交互。
- [x] 根据当前任务绑定的工作目录检测 Git 仓库和实际分支;核对原版对非 Git 目录、未产生首次提交、detached HEAD、检测失败等状态的处理。
- [x] 明确原版“上下文信息”的实际字段、数据来源、更新时机和展示方式,再接入 YCode 的真实会话数据;上下文用量等字段如存在,必须区分真实统计与估算。
- [x] 验收:新建任务、已有会话、切换空间/任务、外部切换 Git 分支后的信息归属与刷新正确;无仓库时不显示虚构分支;浅色/深色及窄窗口布局与原版对齐。
状态:待 REA 拆解与现有能力盘点;本项仅加入 TODO,尚未实施。
状态:已按回收几何/样式/图标/文案实现,并通过真实隔离 App 端到端回归(47 项断言 + 6 项 Git 检测断言);分支为真实 git 结果,用量为上游真实 token(不估算)。
原版证据:
- 运行时几何/结构 REA Evidence `ev_2569313a7a0aa901c5a3b8dc1d7fd190109b9006c915830109b62195f312376a`(WorkBuddy 5.8.3 会话输入区,视口 1336×902,`.tmp/rea-debug-ready-20261017/layout.json`):
左组 `[.cr-add-menu 431,32]` → `[._branchLabel_jdvlk_244 471,82×32]` → `[.cr-permission-setting 561,107×32]` → `[.cr-status-chips 676]`;
右组 `[.cr-context-usage 903,32×32]` → `[.cr-model-selector 939,174×32]` → `[.cr-voice-trigger 1117]` → `[.cr-send-button 1157]`;两组 gap 分别为 8 / 4。
分支标签:radius 999、padding `5px 8px`、gap 8、max-width 188、字体 14/400/22、transition `background .15s`;图标按钮 16×16(`._branchLabelIconButton_jdvlk_279`),默认 SVG `viewBox 0 0 16 16` 分支字形、悬停 copy 字形(`lucide lucide-copy wb-icon`、`viewBox 0 0 24 24`、`stroke-width 1.5`、rect 14×14 + path),两个字形用 opacity 互换(1/0 → 0/1),`:hover`/`:focus-within` 背景 `var(--wb-bg-secondary)`;
用量环:32×32 / radius 16 / transition `background-color .2s`、hover `var(--cr-context-usage-hover-bg,#0000000d)`、`role="button"`、`cursor:pointer`;内含 16×16 SVG,track `circle r=7 stroke-width 2 stroke rgba(128,128,128,.2)`、progress `circle r=7 stroke-width 2 stroke-linecap round transform rotate(-90 8 8)` + `transition:stroke-dashoffset .3s`;截图像素采样确认该实例用的就是这两个回退色(`rgb(230,230,230)` / `rgb(158,162,176)`)。
浮层:`.cr-context-usage-popover` 280 宽 / padding 16 / radius 16 / font 12、标题行(`__title` 12/400/20 + `__close` 16×16)、百分比 20/700/28、`已使用` 12/20、进度条 8 高 radius 3、五类图例(每行 22 高、8×8 圆点、名称 13/22、值 12/20)、`__window-control` 分隔区;另有 `.__requesting-tip`(`bottom:calc(100% + 8px); right:0`)。
- 回收样式表:`contexts-BkjwYSZT.css`(`._branchLabel_*`、`._branchLabelCompact_jdvlk_274`)、`src-CyXHA0IC.css`(`.cr-context-usage*`);文案取自已回收 i18n 表 `chatInput.contextUsage.*`(title 上下文用量 / used 已使用 / tooltip `{percentage}% · {used} / {total} 上下文已使用` / requesting / needMessage / unavailable / 五个分类名)。
- 探针(可复跑):`scripts/rea/probe-todo21-discovery.json`(当前窗口基线)、`probe-todo21-home.json`、`probe-todo21-conversation.json`;本轮采集 `ev_f11473e2…`(首页基线,首页输入区只有工作空间/权限两个入口,没有分支标签与用量环)、`ev_c0dbb550…`、`ev_9796071b…`。
- 数据来源(原版):REA 只能拿到 DOM/样式/文案,浮层的定位与用量数值生成在 JS 内,本轮未取到;因此数值字段按已回收文案与类名结构对齐,YCode 侧只用自己能证明的真实值。
- 观察范围:桌面端 5.8.3、浅色运行时 + 深色按 `.cr-theme` token;未覆盖:原版 detached HEAD/无首次提交/非仓库时的标签表现、悬浮提示的实际锚定与延迟、用量环颜色的分段规则、`__window-control` 的内容。
实现:
- `src/main/git.ts`(新增):`readGitBranch(cwd)` 真实执行 `git -C <cwd> rev-parse --is-inside-work-tree` → `symbolic-ref --short -q HEAD` → 失败再 `rev-parse --short HEAD`;`windowsHide`、5s 超时、git 缺失/超时降级为 `unavailable:true`,全部异常都返回合法形状而不是抛出。
- `src/main/ipc.ts`:新增 `git:branch(sessionId)`,用会话 `cwd`(无则回退工作空间根目录)调用上面的检测。
- `src/renderer/src/workbuddy/composer/context-info/`(新增):`ComposerContextInfo.tsx`(`ComposerBranchLabel` / `ContextUsageRing`)、`icons.tsx`(分支字形 + lucide copy,路径逐字取自证据)、`source.css`(回收规则收敛在 `.cr-input-toolbar` 内)。
- `src/renderer/src/workbuddy/composer/ComposerControls.tsx`:新增 `branchLabelSlot`(左组「+」之后)与 `contextUsageSlot`(右组最前)两个槽位,与证据里的顺序一致。
- `src/renderer/src/components/ChatPane.tsx`:传入两个槽位;用量环的分母用所选模型真实的 `maxInputTokens`。
- 用量真实性:`ChatEvent` 新增 `usage`;OMP 通路在 `message_end` 读取助手消息上的真实 usage(`contextTokens ?? input + cacheRead + cacheWrite`,字段语义取自内核自身),网关通路在 Responses `response.completed.response.usage` 透传;渲染进程只保存最近一次真实值(`stores/chat.ts` 的 `sessionUsage`),拿不到就显示原版「正在会话中 / 暂无用量明细 / 暂时无法获取」文案。
- 原版浮层按五类拆分提示词构成,YCode 的提示词由内核拼装、拿不到该拆分,因此分类值显示「—」,不编造比例。
验证:
- `node scripts/verify-git-branch.cjs`(真实临时仓库 + esbuild 打包被测模块)6 项全 PASS:master 分支、`feature/x`、detached HEAD 短 SHA、空目录、包含不存在路径的非仓库目录、`git init` 无提交。
- `node scripts/verify-composer-context-info.cjs`(真实隔离 App + 真实 OMP 内核 + 受控本地 OpenAI 兼容上游 + 真实 Git 仓库)47 项全 PASS:
分支标签:文案等于真实分支名、32 高 / `5px 8px` / radius 999 / gap 8 / max-width 188 / 14-400-22 省略号、图标按钮 16×16、默认字形与 copy 字形几何与 class 逐项一致、默认可见 copy 隐藏、与「+」和权限入口各相距 8px;悬停后字形 opacity 互换且背景等于同作用域 `--wb-bg-secondary` 解析值;点击图标把真实分支名写入系统剪贴板。
用量环:32×32 / radius 16 / `role=button`、为右组第一个元素、与模型选择器相距 4px、内部 16×16 SVG 与 track/progress 圆的 r/描边/线帽/rotate/过渡逐项一致;无用量时 dashoffset 等于整周长。
浮层与提示:未拿到用量时显示「暂时无法获取用量明细,请稍后重试」且不显示百分比;真实回合(上游 `prompt_tokens 12800`、窗口 64000)后 dashoffset = 周长 ×0.8、悬浮提示 `20% · 12800 / 64000 上下文已使用`(底色/文字/圆角/内边距/字号与 `--wb-tooltip-*` 解析值一致)、浮层显示 `20%` 与 `12800 / 64000`、进度条填充 20%、五类图例名与 8×8 圆点齐全且值为「—」;关闭按钮可关闭浮层。
主题:通过原生设置窗口切深色后 `.chat-pane[data-cr-theme]` 变为 dark,浮层底色 `rgb(36,38,41)`、进度条 `rgba(255,255,255,.1)`、分支标签文字 `rgb(255,255,255)`;再切回浅色恢复 `rgb(255,255,255)`/`rgb(0,0,0)`。
- 回归(顺序执行,避免多进程 Electron 抢焦点):`npm run typecheck`、`npm run build`、`npm run test:chat`、`npm run test:conversation`、`npm run test:conversation-ipc`、`node scripts/verify-sidebar-footer.cjs`、`node scripts/verify-account-menu.cjs`、`node scripts/verify-new-task-switch.cjs` 全部通过。
- 报告:`.tmp/composer-context-lEIWRF/report.json`。
遗留:
1. 原版浮层/提示由 JS 定位(floating-ui),本轮只回收了 `.__requesting-tip{bottom:calc(100% + 8px);right:0}` 这一处锚定规则;YCode 按同向(上方 8px、右对齐到用量环)内联渲染,未逐像素比对原版浮层相对位置。
2. 原版五类上下文占比无法复刻(提示词由内核拼装,YCode 拿不到分类统计),分类值固定显示「—」;原版 `__window-control`(上下文窗口相关控件)内容未采集,未实现。
3. `._branchLabelCompact_jdvlk_274`(32 宽的紧凑形态)只回收了规则,未观察到运行时触发条件,尚未启用。
4. 原版对 detached HEAD、无首次提交、非 Git 目录、检测失败的标签表现未采集;YCode 在这些情况下不渲染标签(无提交但有分支时按 git 真实结果仍显示分支名)。
5. 用量环进度颜色:原版通过未回收的变量注入,本轮截图像素证明该实例用的是回退色 `#9ca3af`;是否随用量分段变色未验证。
6. 刷新时机未采集:YCode 在切换会话、窗口重新聚焦以及每 20s 轮询时重新读取分支;用量只在收到真实 `usage` 时更新。
7. 备用(非 OMP)内核走自建网关时用量来自 Responses `response.completed.usage`;Chat Completions 上游路径仍未解析 `usage`。
8. 用量环只在会话输入区渲染(本轮首页基线的 REA 证据里首页输入区确实没有该入口),首页/新建任务时不显示。
## 推进顺序
1. 对话与侧栏:01 → 02 → 03 → 04 → 05 → 06 → 07 → 08 → 09 → 21。
1. 对话与侧栏:01 → 02 → 03 → 04 → 05 → 06 → 07 → 08 → 09 → 21(均已实现并留下验收记录,未完成验收点在各条目内标注)。
2. 设置:先落实 16、17 的入口范围,再依次推进 10 → 11 → 12 → 13 → 15 → 19。
3. 14、18、20 保留为待拆解,后续单独展开。