dsh-git
DeepSeek Harness Web GUI 的完整 Git 管理插件:分支切换/fetch/pull/commit/push,可折叠悬浮面板 + 输入框胶囊
- Stars
- 0
- Language
- JavaScript
- Created
- Sep 3, 2026
- Updated
- Sep 3, 2026
Introduction
@dsh-plugins/dsh-git
English | 中文
DeepSeek Harness Web GUI 的完整 Git 管理插件,形态为一个可折叠的悬浮面板, 实时跟随当前会话的工作区——在侧边栏点击不同的会话/工作区,面板会瞬间 重新绑定到对应仓库。
支持的工作流: 分支切换 · 拉取更新(fetch) · 拉取合并(pull,仅快进) · 提交(commit) · 推送(push) · 状态(status) · 最近提交 · 未提交文件列表 · 基于某分支新建分支。
界面
- 悬浮面板(
shell.overlay):折叠时不渲染任何元素(不会遮挡输入框); 展开后是完整的 Git 工作台(状态行、带 脏树预检 的分支切换器——在有 未提交修改时选择分支,会先显示受影响文件列表警告而不是直接切换,并提供 "仍要切换"按钮;fetch/pull/commit/push 操作;可折叠的变更列表与最近提交 列表;上次操作输出)。面板可通过顶栏拖动(按住带 Git 标题的那一行, 拖到哪里就停在哪里,不会拖出视口;顶栏上的按钮/输入框不会触发拖动; 双击顶栏回到居中位置)。 分支切换器旁边的"+ 新建分支"按钮会展开一个内联表单:新分支名 + 基分支 选择器(本地分支或origin/feature/x这样的完整远端引用)——确认后从 该基分支创建新分支并切换过去。 - 输入框胶囊(
conversation.input.dock):输入框左上角的紧凑型左对齐 状态胶囊(分支摘要,或"当前工作区不是 Git 仓库");点击它展开/收起悬浮面板。 - 两处界面共享同一个 store,状态永远一致,并都会随当前会话(及其 cwd) 切换而重新绑定。
架构
一个双面 npm 包:
| 半边 | 文件 | 职责 |
|---|---|---|
| 宿主 | lib/index.js | Cordis 插件(bundle 行 dsh-git),通过 ctx.connection.rpc.handle 挂载 /dsh-git-rpc 通道(authority: "trusted-host")。端点:status、branches、checkout、createBranch、fetch、pull、commit、push、log。所有 git 调用都走 execFile(无 shell)、带超时(本地 30s / 网络 120s)、严格入参校验。 |
| 浏览器 | lib/client.js | dsh.client bundle(服务于 /plugins/@dsh-plugins/dsh-git/client.js):悬浮面板 + dock 行 + 共享 store,对照模块表手写(仅依赖 react)。 |
安装
dsh plugin --profile web add https://github.com/xia-sc/dsh-git
然后重启 dsh web(bundle 行与浏览器 roster 在启动时组合)。刷新后,
当前会话工作区是 git 仓库时,输入框下方会出现 dock 行。
卸载:
dsh plugin --profile web remove @dsh-plugins/dsh-git
RPC 约定(/dsh-git-rpc)
载荷使用 { args } 约定。cwd 必须是绝对路径;branch 匹配
^[A-Za-z0-9][A-Za-z0-9._/-]*$(不允许前导 -、..、@{、\、空白、
控制字符);remote 为普通单段;提交信息以 --message=<msg> 形式传递
(含控制字符会被拒绝)。
| 端点 | 参数 | 结果(value) |
|---|---|---|
status | { cwd } | { repo, branch, detached, oid, upstream, ahead, behind, dirty, changes: [{status, path}] } |
branches | { cwd } | { repo, current, local: [{name, current, upstream, sha}], remote: [{name, short}] } |
checkout | { cwd, branch } | { branch, detached, oid, message? },经 git switch --guess;浏览器会预检脏树并提前警告;因"本地修改会被覆盖"被拒绝时会带上可读前缀。 |
createBranch | { cwd, branch, base? } | { branch, detached, oid, message? },经 git switch --create <branch> <base>(缺省 base 即 HEAD);从基分支创建新分支并切换过去。 |
fetch | { cwd, remote? } | { message }(120s 超时) |
pull | { cwd } | { message },经 git pull --ff-only(绝不隐式合并) |
commit | { cwd, message } | { message };未配置 user.name/email 时报 missing-author 错误 |
push | { cwd } | { message }(120s 超时) |
log | { cwd, count? } | { repo, commits: [{sha, author, subject, refs}] }(钳制 1..50) |
设计决策与边界
- pull 固定
--ff-only:不产生意外的合并提交;冲突以错误形式呈现, 由用户在自己的工具里解决。 - commit 不暂存:只提交已暂存的内容(
git add请在自己的工具里完成)。 - push/pull 凭据来自系统(Git Credential Manager / SSH agent);插件 绝不碰凭据存储。
- 插件绝不修改 git config;缺 author 时给出明确错误而不是悄悄补写。
- 面板操作是普通 UI 行为(和 Cordis 面板一样),不会写入会话日志 / 模型提示词。
开发说明
- 浏览器 bundle 为手写(无构建步骤);改
lib/client.js刷新即生效 (no-cache),改宿主半需要重启dsh web。 - 测试:
node test/smoke.mjs(校验/接线,不 spawn git——会话沙箱拦截 子进程管道 stdio)与node test/render.mjs(双界面真实 React SSR 渲染)。 git 命令集对照运行中的服务端做端到端验证。