Problem / 问题
会话窗口底部的输入区(composer)目前看不到任何 Git 状态,而 agent 恰恰是在这个位置直接改工作区文件的,存在两个具体问题:
容易在错误的分支上操作。 提交 prompt 前无法在输入区确认当前分支;改完、提交时才发现分支不对。([Feature] 项目会话页面没有展示当前分支信息 #679 已提出"至少显示分支",PR feat(chat): 在会话顶栏显示当前 Git 分支 #727 目前把它做在会话顶栏 。)
改动规模不透明,且没有分支切换入口。 想知道"工作区现在一共改了多少行"必须打开右侧 Review 面板逐文件看。现有的 +N −N 只出现在 Review 标签页(apps/desktop/src/components/workpanel/ReviewTab.tsx:30-33),而且数据源是 agent 消息自带的编辑证据(apps/desktop/src/lib/workspace-review.ts),不是 git 工作区的真实未提交状态——用户手工改的文件、以及上一个会话遗留的改动都不计入。切换分支则完全没有入口,只能回终端。
值得一提的是,diff 统计能力其实已经存在:packages/host-runtime/src/workspace-diff.ts 已经用 git status --porcelain=v1 -z + diff 算出每个文件的 additions/deletions,并通过 pi-desktop/workspace/diff(apps/desktop/electron/main/ipc/workspace-ipc.ts:623)暴露,但渲染层的 api.workspaceDiff()(apps/desktop/src/lib/api.ts:1248)至今没有任何调用点 。也就是说这不是从零造轮子,而是把已有能力接到界面上。
Proposed change / 期望改动
在 composer 底部工具栏 apps/desktop/src/features/chat/composer/ComposerToolbar.tsx:106(即 .composer-left / .composer-right,与权限模式、上下文用量、模型选择器同一行)增加两个轻量 chip:
1. 分支 chip(可交互)
显示当前分支;detached HEAD、非 git 目录、worktree 需要有明确降级文案,不能空白。
点击弹出分支列表(本地分支,可选远端分支),支持 switch / checkout。
切换前如果工作区有未提交改动,需要二次确认,避免静默丢改动;切换成功后刷新 chip 和 diff 统计。
2. diff stat chip(实时)
显示工作区未提交改动总量 +N −N,视觉沿用 ReviewTab 已有的 +{additions} −{deletions} 表达。
hover 展开按文件明细,点击直接打开 Review 面板。
无改动时显示 +0 −0 或隐藏,但需要与"非 git 目录 / git 命令失败"区分开(后者应可诊断,不能和干净工作区同样显示)。
实现建议(复用现有路径,避免第二套口径)
行数统计直接复用 collectWorkspaceDiff(cwd) / workspaceDiff,不要再引一个 simple-git/git2 依赖做同类计算。
分支列表与切换按 workspaceDiff 的既有先例新增窄通道:packages/shared/src/protocol.ts 的 IPC 表 + IPC_WHITELIST、apps/desktop/electron/main/ipc/workspace-ipc.ts handler、apps/desktop/src/lib/api.ts wrapper。读(列出分支)与写(切换分支)分成两个通道,便于权限区分。
"实时"不必轮询到 keystroke 级:在 agent turn 结束 / 文件写入后重算,加防抖(现有轮询先例 apps/desktop/src/pages/ScheduledPage.tsx:44)。仓库目前还没有面向渲染层的工作区 fs watcher(只有 plugin-watcher.ts 服务于开发期插件热重载),如果要做真正的 push 式更新,需要新增 watcher + event channel(参考 protocol.ts:339-357 的 sessionsChanged 等)。
顺手修一个既有缺陷:withGitBranch()(apps/desktop/electron/main/index.ts:1062-1078)直接读 <workspace.path>/.git/HEAD 文本正则匹配,不解析 gitdir: 文件,因此 linked git worktree 场景拿不到分支 ,只会落到 detached。既然本功能要把分支信息变成用户可操作的对象,建议改为 git rev-parse --abbrev-ref HEAD 并做缓存。
新增用户可见文案需要覆盖 packages/i18n/src/locales/*/index.ts 八个语言的 chat 命名空间。
Alternatives / 其他方案
Additional context / 补充信息
相关:[Feature] 项目会话页面没有展示当前分支信息 #679 (会话中展示当前分支)、PR feat(chat): 在会话顶栏显示当前 Git 分支 #727 (顶栏分支展示)。本 issue 的差异点是底部位置 + 可交互切换 + 实时 diff 规模 ,不重复请求纯展示。
安全/权限边界:切换分支是会改动工作区的写操作,应走权限确认,不能静默执行;detached HEAD、脏工作区、linked worktree、非 git 目录四种状态都需要显式处理与可诊断报错。
建议顺带明确统计口径:+N −N 是相对 HEAD 的工作区总量(含未跟踪文件,workspace-diff.ts 已用 --untracked-files=all 处理),并在 UI 上说明,避免与 Review 面板中"仅本次 agent 编辑"的数字产生歧义——这是两处数字将来最容易引起用户困惑的地方。
Problem / 问题
会话窗口底部的输入区(composer)目前看不到任何 Git 状态,而 agent 恰恰是在这个位置直接改工作区文件的,存在两个具体问题:
+N −N只出现在 Review 标签页(apps/desktop/src/components/workpanel/ReviewTab.tsx:30-33),而且数据源是 agent 消息自带的编辑证据(apps/desktop/src/lib/workspace-review.ts),不是 git 工作区的真实未提交状态——用户手工改的文件、以及上一个会话遗留的改动都不计入。切换分支则完全没有入口,只能回终端。值得一提的是,diff 统计能力其实已经存在:
packages/host-runtime/src/workspace-diff.ts已经用git status --porcelain=v1 -z+diff算出每个文件的additions/deletions,并通过pi-desktop/workspace/diff(apps/desktop/electron/main/ipc/workspace-ipc.ts:623)暴露,但渲染层的api.workspaceDiff()(apps/desktop/src/lib/api.ts:1248)至今没有任何调用点。也就是说这不是从零造轮子,而是把已有能力接到界面上。Proposed change / 期望改动
在 composer 底部工具栏
apps/desktop/src/features/chat/composer/ComposerToolbar.tsx:106(即.composer-left/.composer-right,与权限模式、上下文用量、模型选择器同一行)增加两个轻量 chip:1. 分支 chip(可交互)
detached HEAD、非 git 目录、worktree 需要有明确降级文案,不能空白。switch/checkout。2. diff stat chip(实时)
+N −N,视觉沿用ReviewTab已有的+{additions} −{deletions}表达。+0 −0或隐藏,但需要与"非 git 目录 / git 命令失败"区分开(后者应可诊断,不能和干净工作区同样显示)。实现建议(复用现有路径,避免第二套口径)
collectWorkspaceDiff(cwd)/workspaceDiff,不要再引一个simple-git/git2依赖做同类计算。workspaceDiff的既有先例新增窄通道:packages/shared/src/protocol.ts的 IPC 表 +IPC_WHITELIST、apps/desktop/electron/main/ipc/workspace-ipc.tshandler、apps/desktop/src/lib/api.tswrapper。读(列出分支)与写(切换分支)分成两个通道,便于权限区分。apps/desktop/src/pages/ScheduledPage.tsx:44)。仓库目前还没有面向渲染层的工作区 fs watcher(只有plugin-watcher.ts服务于开发期插件热重载),如果要做真正的 push 式更新,需要新增 watcher + event channel(参考protocol.ts:339-357的sessionsChanged等)。withGitBranch()(apps/desktop/electron/main/index.ts:1062-1078)直接读<workspace.path>/.git/HEAD文本正则匹配,不解析gitdir:文件,因此 linkedgit worktree场景拿不到分支,只会落到detached。既然本功能要把分支信息变成用户可操作的对象,建议改为git rev-parse --abbrev-ref HEAD并做缓存。packages/i18n/src/locales/*/index.ts八个语言的chat命名空间。Alternatives / 其他方案
Additional context / 补充信息
detached HEAD、脏工作区、linked worktree、非 git 目录四种状态都需要显式处理与可诊断报错。+N −N是相对HEAD的工作区总量(含未跟踪文件,workspace-diff.ts已用--untracked-files=all处理),并在 UI 上说明,避免与 Review 面板中"仅本次 agent 编辑"的数字产生歧义——这是两处数字将来最容易引起用户困惑的地方。