DSH-EZ Commit Plugin
DSH(DeepSeek Harness)「一键 Commit」静态双面插件:安装并重启 profile 后,web 会话标题栏自动出现 一键 Commit 按钮,由当前会话模型按业务颗粒度把工作区 git 改动拆分为多个提交(Conventional Commits),经用户审查后分批执行;当模型判定改动为「环境噪音」时只提示、不执行任何 git 写操作。
English | 简体中文
目录
简介
DSH-EZ Commit 是一个 DSH 静态双面插件(与 dsh-skin-market 等第三方皮肤包同一机制):
- 一个包,双平面:Client 半(
exports "./client"+dsh.client声明,浏览器模块工厂)负责 UI(按钮 + 弹窗);Host 半(main入口)负责在webServer上挂载同源 HTTP API、git 采集、模型裁决与分批提交。 - 安装即生效:
dsh plugin --profile <name> add dsh-ezcommit-plugin安装/升级(dsh.bundle规范,见 docs/INSTALL.md),重启 profile 后会话标题栏自动出现按钮;无需 cordis preset,也无需cordis_define/cordis_run。 - 零运行时依赖:仅用 Node 内置模块与浏览器原生能力(
fetch/React.createElement),React由 web 外壳预置基线提供。 - 模型优先:拆分与噪音裁决完全由当前会话模型完成,插件本身不做任何猜测性的 git 写操作。
特性
| # | 需求 | 实现 |
|---|---|---|
| 1 | 非 git 仓库 → 按钮置灰 | Host shell 执行 git rev-parse --is-inside-work-tree |
| 2 | 按钮左侧展示分支名 | git symbolic-ref --short HEAD(detached 退化为短 hash) |
| 3 | 点击弹二次确认框 | Client shell.overlay 插槽自绘 modal |
| 4 | 模型按业务颗粒度拆分 commit | Host llm.stream() 分析改动事实,输出 JSON 计划 |
| 5 | 无改动 → 置灰 | git status --porcelain 计数为 0 时禁用 |
| 6 | 模型判定「环境噪音」→ 提示不 commit | 裁决 verdict: "noise",Host 零 git 写操作 |
快速开始
安装
安装用 DSH 官方 CLI 完成分发与版本管理(完整规范见 docs/INSTALL.md,English):
# 从 npm 安装(发布后)——登记为 profile bundle 层,由 pnpm 管理版本
dsh plugin --profile web add dsh-ezcommit-plugin
# 或从 git 仓库 / 本地 checkout 安装
dsh plugin --profile web add git+https://github.com/PenguinAndy/dsh-ezcommit-plugin.git
dsh plugin --profile web add link:/path/to/dsh-ezcommit-plugin
安装完成后重启 profile(如 dsh web):启动日志打印 [dsh-ezcommit-plugin] v<x.y.z> 已安装 与路由挂载结果;刷新页面后,每个 web 会话标题栏出现 [分支名] [一键 Commit],工作区非 git 仓库或无改动时按钮置灰。无需任何会话内操作(不需要 cordis preset / cordis_define)。
使用流程
- 点击「一键 Commit」→ 确认框展示分支与改动计数(二次确认)。
- 「开始分析」→ Host 采集
status / diff / 未跟踪采样(敏感路径自动过滤,不采样、不进入提示词),调用当前会话已路由的模型裁决:noise→ 黄色提示框展示原因,不执行任何 git 写操作;commit→ 计划审查框展示拆分批次(顺序、message、文件清单)、被过滤的敏感文件与未覆盖文件告警。
- 「执行 N 批提交」→ 逐批
git add --pathspec-from-file=- --(文件清单经 stdin,天然规避空格/特殊字符路径)+git commit -m title [-m body],返回每批短 hash。 - 完成后按钮立即刷新置灰;任一批失败即停止(不回滚),已成功批次照常报告。
工作原理
一个包、双平面:Client 半由 dsh-client-modules 打进 web 启动图(/plugins/dsh-ezcommit-plugin/client.js),按 window.__ModuleLoader__ 工厂格式在浏览器加载并挂载客户端插件;Host 半在本进程加载,向 webServer 注册 /ezcommit/api 前缀路由。Client 通过同源 HTTP 调用 Host。一次完整操作的时序如下:
sequenceDiagram
participant C as Client(浏览器)
participant H as Host(Node 进程)
participant M as 当前会话模型
Note over C: setInterval:每 5s 轮询
C->>H: POST /ezcommit/api/git.state {sessionId}
H-->>C: { inRepo, branch, hasChanges, changedCount }
Note over C: 非 git 仓库 / 无改动 → 按钮置灰
C->>C: 点击「一键 Commit」→ 二次确认框
C->>H: POST /ezcommit/api/commit.analyze {sessionId}
H->>H: 采集 status / diff / 未跟踪采样<br/>截断上限 + 敏感路径过滤
H->>M: llm.stream(改动事实 + 系统提示词)
M-->>H: JSON 计划 { verdict, commits }
alt verdict = "noise"
H-->>C: 环境噪音 → 提示弹窗(零 git 写操作)
else verdict = "commit"
H-->>C: 拆分批次 + 文件清单(用户审查)
C->>H: POST /ezcommit/api/commit.execute {sessionId, commits}
H->>H: 逐批 git add + git commit<br/>任一批失败即停止(不回滚)
H-->>C: { results: [{ title, hash }], leftoverCount }
end
API 契约
HTTP API 一览
Host 半在 webServer 上挂载三个同源 JSON API(仅 POST,同源校验;参数与返回值仅无损 JSON):
| 方法 | 路径 | 入参 | 出参要点 |
|---|---|---|---|
git.state |
POST /ezcommit/api/git.state |
{sessionId} |
{ok, inRepo, branch, hasChanges, changedCount, untrackedCount} |
commit.analyze |
POST /ezcommit/api/commit.analyze |
{sessionId} |
{ok, verdict:'noise'|'commit', reason, commits:[{title,body,files}], unplanned, problems, sensitive:[path], diffTruncated, target} |
commit.execute |
POST /ezcommit/api/commit.execute |
{sessionId, commits} |
{ok, results:[{title,hash}], leftoverCount} |
失败统一返回 {ok:false, error:{message, code}};非 POST → 405,未知方法 → 404,跨源 → 403。
模型输出契约
系统提示词要求模型仅输出如下 JSON(响应解析时自动剥离 markdown 代码围栏,解析失败自动重试一次):
{
"verdict": "noise",
"reason": "一句话说明(noise 时必填)",
"commits": [
{ "title": "feat(scope): ...", "body": "可选多行说明", "files": ["相对路径..."] }
]
}
files必须逐字取自改动清单;不存在/重复的文件归入unplanned并在 UI 告警。- 模型目标解析顺序:会话已路由配置(
session.requestHeader().config)→agent.options→ 默认模型(agentDefaultModel.currentSelection())。
安全与隐私
- 噪音裁决在
git add/commit之前完成,noise 路径零 git 写操作。 - 敏感路径过滤:
.env*、.npmrc、.pypirc、.netrc、.git-credentials、*.pem、*.key、id_rsa*、.ssh/、.aws/、.kube/、credentials*.json等文件的路径与内容不会发送给模型,也不会进入计划或被执行提交;计划/噪音弹窗会列出被过滤文件(仅本地展示)。 - 隐私边界:点击「开始分析」后,工作区
status、diff与未跟踪文本采样(每文件前 8KB、最多 32 个)会发送给当前会话模型服务商;敏感路径除外。请仅对允许发送给模型服务商的工作区使用。 - API 仅接受同源 POST(Origin 与 Host 一致),拒绝跨站调用。
commit.execute执行前用当前 porcelain 重建已知文件集合,陈旧/发明路径一律无效。- 不
git push、不--force、不修改历史;多批次中某批失败 → 停止、不回滚、如实报告。 - 同一 sessionId 的 analyze/execute 有进程内 in-flight 锁,重复点击直接拒绝。
- 所有副作用(路由、插槽、轮询、样式)均挂在插件生命周期上,bundle 层卸载时自动清理。
开发
目录结构
.
├── .github/workflows/
│ └── release.yml 发布工作流
├── docs/
│ ├── README.en.md 英文版 README
│ ├── INSTALL.md 插件安装规范(中文)
│ ├── INSTALL.en.md 插件安装规范(English)
│ ├── dsh-ez-commit-design.md 设计文档(需求→契约映射、决策点、风险)
│ └── VERIFICATION.md 真机验证走查(六条需求)
├── src/
│ ├── index.js Host 半:/ezcommit/api 路由 + git/模型逻辑 + 公告/自检
│ └── client.js Client 半:按钮 + 弹窗 + 样式(__ModuleLoader__ 工厂)
├── scripts/
│ ├── verify.mjs 离线冒烟校验(不依赖 DSH 运行时,真实 git 集成)
│ └── stage-fixture.mjs 场景制备:demo | noise | clean
├── cordis.patch.yml profile bundle 层补丁(ezcommit 安装锚点行)
├── package.json 版本与 dsh.bundle + dsh.client 双面契约;零运行时依赖
├── pnpm-lock.yaml
└── LICENSE MIT
本地验证
pnpm verify # 或 npm run verify:包契约 + HTTP 路由集成(真实 git)+ client 工厂冒烟
运行时验证:安装并重启 profile 后,按 docs/VERIFICATION.md 的走查矩阵逐项验证六条需求(配 node scripts/stage-fixture.mjs demo|noise|clean 场景制备工具);模型裁决路径可用包含 .DS_Store、锁文件等「噪音」的工作区验证。
相关文档
- 安装规范:docs/INSTALL.md / docs/INSTALL.en.md
- 设计文档:docs/dsh-ez-commit-design.md
- 验证走查:docs/VERIFICATION.md
贡献
欢迎 Issue 与 PR。提交 PR 时请:
- 提交信息遵循 Conventional Commits 规范;
- 修改
src/后运行pnpm verify确保离线冒烟校验通过; - 涉及行为变更时同步更新本 README 与
docs/文档。
No comments yet. Be the first to write one.