packages/dsh-git-graph
zhu1090093659/dsh-web输入框上方提供 Git 分支选择器,并把分支泳道与提交历史画成图谱,沿着时间线找到任意变更。
输入框工具行的 git 状态角标:模型选择器左侧一枚 14px 分支图标,悬停显示分支名、变更文件数与增删行数。统计含未跟踪文件;非 git 工作区不显示。
DSH 插件:在输入框(composer)工具行右端、模型选择器左侧显示一枚 git 状态角标。

+新增 -删除(绿/红)。git pull 别人的提交不计:范围是 @{upstream}..HEAD,已推送的内容落在范围外。git init、无远程、detached HEAD)时只算工作区。| 文件 | 作用 |
|---|---|
index.js | host 半:注册 RPC 通道 /dsh-git-change,status 端点解析会话 cwd 并返回 git 摘要 |
git.js | git 采集(spawn 系统 git,-z 分帧,固定 C locale,只读命令,带上限与截断标记) |
client.js | client 半:手写 bundle(无构建步骤),把角标注册进 conversation.input.right |
tools/verify-host.mjs | host 半离线验证(6 项) |
tools/verify-client.mjs | client bundle 离线验证(5 项:加载协议 / apply / 图标 / 悬停浮层 / 非仓库不渲染) |
tools/asar.mjs、tools/asar-grep.mjs | 读 DSH app.asar 的小工具(调研用) |
tools/make-preview.py | 生成上面那张效果图(PIL 合成,不含任何真实项目内容) |
tools/uninstall.sh | 一键从 desktop profile 卸载 |
无构建步骤:DSH 的浏览器模块系统只要求 client.js 调用一次
window.__ModuleLoader__.load({ id, factory }),且 factory 返回 module.exports。
id 必须等于包名。
# 1) 包放进 profile 能解析的位置(本地开发用 link 依赖)
# profile/package.json:
# "dependencies": { "dsh-git-change": "link:/absolute/path/to/dsh-git-change" }
# "dsh": { "profile": { "bundles": [ ..., "dsh-git-change" ] } }
# 2) 安装(建立软链 + 写入 lockfile)
cd ~/.dsh/profiles/desktop && pnpm install
包的 package.json 声明 dsh.bundle.patch: ./cordis.patch.yml,该 patch 里用
- insert: 把自己挂进配置树。
注意:不要用 profile cordis.patch.yml 的顶层条目挂本地插件。
用户层的顶层 - id: x / name: y 只能"覆盖已存在条目",新增会被
patch: entry "x" not found 静默忽略(insert: 才新增)。
改完代码要重启 DSH:一是 profile 的 bundle/patch 层只在启动时装配;
二是 Node 的 ESM 缓存会让运行中的 host 一直用第一次加载的模块
(改了 index.js 后重载仍报旧行号的错就是这个原因)。
# 1) 撤销 profile 侧的挂载
cd ~/.dsh/profiles/desktop
node -e "const fs=require('fs');const p='package.json';const j=JSON.parse(fs.readFileSync(p));delete j.dependencies['dsh-git-change'];j.dsh.profile.bundles=j.dsh.profile.bundles.filter(b=>b!=='dsh-git-change');fs.writeFileSync(p,JSON.stringify(j,null,2)+'\n')"
pnpm install
# 2) 重启 DSH
node tools/verify-client.mjs # 需要 react/react-dom/jsdom(默认从 /tmp/gc-render/node_modules 取)
node tools/verify-host.mjs # 可选参数:任意 git 工作区路径,默认 /tmp/gc-test
verify-client.mjs 复刻 DSH 的加载协议(classic script → __ModuleLoader__.load →
materialize),再用 jsdom + 真实 React 跑一遍挂载与悬停,因此 bundle 的语法/协议错误
不会走到线上 GUI(客户端插件加载失败会阻止整个 Web GUI 挂载)。
conversation.input.right,它渲染在模型选择器
左侧、间距恒为 12px(窄窗口 8px),而整组靠右对齐(margin-left:auto),所以模型名越
长、角标越靠左。模型选择器 max-width: 220px。GIT_OPTIONAL_LOCKS=0、GIT_TERMINAL_PROMPT=0、LC_ALL=C,4 秒超时。