--- description: "面向 DeepSeek Harness Desktop 与标准 DSH Web profile 的 portable Git repository 操作及 Client UI。" kind: "package-bundle" --- # dsh-plugin-git [English](README.md) | 中文 ## 概述 标准 DSH/Cordis Git 插件,包含一项 portable Host service、一份 Client bundle 与 optional Desktop enhancement。同一 package 可在 DeepSeek Harness Desktop 与标准 DSH Web host 中原样运行;npm scope `@dsh-electron/` 标识发布者,不是运行时要求。 **依赖上游右侧边栏。** 本包要求 DeepSeek Harness ≥ v0.1.5-rc.2:其 Client UI 自带右侧边栏 `@deepseek-ai/dsh-client-ui-sidebar-right`。Git 以标准两阶段方式注册三个 sidebar tab type,并通过 `ctx.sidebarRight` 导航;宿主没有右侧边栏时 Client 半无法加载。旧的第三方 Details Host 插件已废弃,不再被依赖。 [DeepSeek Harness Desktop](https://github.com/cherrchen/deepseek-harness-electron) 预装本插件,并通过 git subtree 镜像本仓库。用户可在**设置 → 插件**中禁用 Git;右侧边栏是上游内置项。 ## 目录 - [DSH 兼容性](#dsh-compatibility) - [安装](#installation) - [与上游右侧边栏配对](#pairing-with-sidebar-right) - [用户体验](#user-experience) - [组合](#composition) - [配置](#configuration) - [Git 操作](#git-operations) - [npm 发布](#npm-publication) - [开发](#development) - [贡献](#contributing) - [Model Experience](#model-experience) - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work) - [开发备注](#dev-note) ## DSH 兼容性 本仓库的面向 **DeepSeek Harness `v0.1.5-rc.2`**。 ## 安装 本包已发布到 npm:`@dsh-electron/dsh-plugin-git`(当前 `0.2.1`,MIT,带构建 provenance)。仍处于试验开发阶段:API 与版本保持 pre-1.0,minor 版本之间可能变化。 **DeepSeek Harness Desktop** — Git 默认预装并启用。不需要仓库 UI 时,可在**设置 → 插件**中禁用。 **DSH Web** — 右侧边栏随 DeepSeek Harness ≥ v0.1.5-rc.2 一起提供,因此只装 Git 即可。最短路径是两条命令: ```sh dsh plugin --profile web add @dsh-electron/dsh-plugin-git dsh --profile web ``` `dsh plugin` 在 profile 目录内转发给 pnpm:安装 package,并激活包内 `cordis.patch.yml` 层,把插件挂进组合。它支持四种安装来源,下表以 `web` profile 为例: | 来源 | 命令 | 说明 | | --- | --- | --- | | npm 注册表(推荐) | `dsh plugin --profile web add @dsh-electron/dsh-plugin-git` | 预构建产物;无需构建授权 | | tarball | `dsh plugin --profile web add ./dsh-electron-dsh-plugin-git-.tgz` | 预构建离线包;无需构建授权 | | 本地路径 | `dsh plugin --profile web add /path/to/dsh-plugin-git` | pnpm 链接该 checkout;适合开发 | | GitHub / git | `dsh plugin --profile web add github:cherrchen/dsh-plugin-git` | 拉取源码并在安装时经 `prepare` 现场构建;需 `allowBuilds`,建议锁定 tag | 无论用哪种来源,Git client 加载时都要求宿主已提供 `ctx.sidebarRight` 与 `ctx.sidebarRightTabs` 两个 service;DeepSeek Harness ≥ v0.1.5-rc.2 两者皆有。 ### 从 npm 注册表安装(推荐) ```sh dsh plugin --profile web add @dsh-electron/dsh-plugin-git ``` 注册表里是预构建产物,安装时不会有任何 package 代码在你的机器上执行。 ### 从 tarball 安装 ```sh pnpm pack --pack-destination dist dsh plugin --profile web add ./dist/dsh-electron-dsh-plugin-git-0.2.1.tgz ``` `pnpm pack` 产出上述单一 tarball,每个 tag 的 GitHub Release 都附同一个文件 —— `0.2.1` 对应 `https://github.com/cherrchen/dsh-plugin-git/releases/download/v0.2.1/dsh-electron-dsh-plugin-git-0.2.1.tgz`。它同样是预构建产物,因此适合内网或离线 profile。 ### 从 GitHub 安装 ```sh dsh plugin --profile web add github:cherrchen/dsh-plugin-git ``` git 安装拉取的是**源码而非构建产物**,因此由本包自带的 `prepare` 脚本在安装方机器上构建发布入口:`pnpm run build` 先用 `tsc` 产出声明,再用 `tsdown` 打包两个面,只使用本包自带的 standalone tsconfig —— 不假设任何 sibling checkout。pnpm ≥ 10 会先拦下该脚本,首次 `add` 以 `ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED` 失败。把 pnpm 打印出的**原样包键**写入该 profile 的 `pnpm-workspace.yaml` —— 对 git 依赖而言,该键是包名加上解析后的 git spec 与 commit,裸包名并不匹配: ```yaml allowBuilds: # 此处填 pnpm 打印出的键 '@dsh-electron/dsh-plugin-git@git+/#': true ``` 然后重新执行 `add` 即可;换 pin 会换 commit,键也随之变化。请把该授权视为**允许该 package 在安装时于你的机器上执行代码**(且不在 agent 运行的任何沙箱之内)。建议锁定 tag,让后续推送无法悄悄改变实际运行的内容: ```sh dsh plugin --profile web add github:cherrchen/dsh-plugin-git#v0.2.1 ``` ### 从本地 checkout 安装(开发调试) ```sh git clone https://github.com/cherrchen/dsh-plugin-git.git cd dsh-plugin-git pnpm install pnpm build # 生成 lib/;它未纳入 Git,但安装读的就是它 dsh plugin --profile web add "$PWD" ``` pnpm 以链接方式接入该 checkout,之后的 `pnpm build` 无需重装即被采用。 > **提示**:如果你的 DSH 是 clone 源码方式使用(而非全局安装),`dsh` 不在 `PATH` 里,请把上述命令中的 `dsh` 换成 `pnpm dsh`,例如 `pnpm dsh plugin --profile web add …`。 ## 与上游右侧边栏配对 Git 通过上游右侧边栏的标准两阶段注册接入 tab-type 体系。Client manifest 只声明 service 依赖: ```json { "dsh": { "client": { "inject": [ "@deepseek-ai/dsh-client-ui-sidebar-right" ] } } } ``` 动态 client plugin 不允许 import 其他 plugin 包的运行时值,只允许 `import type`;因此类型引用在 bundle 中被完全擦除,`external` 不再需要。 **阶段一**——`ctx.sidebarRightTabs.register(definition)` 注册三个 tab type:`git.changes` 与 `git.graph` 是 page type(按 kind 打开,每个 pane 单例),并各贡献一个 guide 条目(Changes `order: 10`、Graph `order: 11`),在 guide 页替代旧 Details Launcher 卡片;`git.diff` 是 resource type,pattern `dsh-resource://git/diff/**`,`canOpen` 校验地址可解码,tab 标题取解码出的文件名。 **阶段二**——每个 tab type 的 body 组件注入 `sidebar.right.pane.tab` 座(key 即 definition 的 `id`),body 通过 `useTabInfo().tab.navigation` 读取 `{ address, params, revision }`。 统一导航收敛到 `ctx.sidebarRight`: ```text ctx.sidebarRight.openTab('git.changes') ctx.sidebarRight.openResource('dsh-resource://git/diff//', { params: { path, staged } }) ctx.sidebarRight.openTab('git.graph') ``` diff 标签页以精确地址为身份:同一文件同一比较侧重复打开会 reveal 既有标签页并递增 `revision`(body 据此重新拉取),而同一文件的 staged 与 working-tree diff 是两个不同地址,可并排共存。changes 与 graph 由侧栏按 kind 在每个 pane 去重。changed-files indicator、分支芯片与 guide 条目打开 `git.changes`;点击文件行打开该路径的 `git.diff`。 参数类型通过 augmentation 挂到右侧边栏: ```ts declare module '@deepseek-ai/dsh-client-ui-sidebar-right/client' { interface SidebarRightResourceParamsMap { git: GitDiffPayload } } ``` 仓库操作按钮(refresh / reveal)由本包以本地组件渲染在各 Git 面板内部。标签栏、guide 页、停靠几何与面板宽度由右侧边栏(基于 ui-dockkit)拥有,不属于本 package。 ## 用户体验 在会话输入区左侧,Git 贡献 branch selector 与 changed-files indicator。点击任一控件会在右侧边栏打开 `git.changes` 标签页。创建分支会打开共享的 conversation Modal;在仅有 `git init`、尚无提交(unborn HEAD)时,菜单以禁用态展示符号默认分支,说明需要先完成首次提交,并在 HEAD 存在前禁用创建。 **Changes** surface 顶部展示当前 branch 与 refresh,其下是默认一行、随内容增高的 commit message 输入框,带魔法棒 **Generate** 控件,以及分裂式 **Commit** 按钮(Commit、Amend、Commit & Push、Commit & Sync)。Staged、unstaged 与 untracked 路径以图标操作分区列出:plus/minus 切换 index,undo 在两步确认后 discard,porcelain 字母标记行状态。点击路径打开对应 diff。**Diff** surface 在右上角展示 refresh,并在每个标签页渲染一个文件的 working-tree 或 staged diff。**Graph** surface 顶部在同一行展示自动/全部/首父链与 refresh,其下以 canvas 绘制的 lane graph 展示提交历史——整页共享一个连续坐标系,rail 与 merge 边不会在行边界断裂——包含 subject、author、date、hash 与 HEAD/branch/tag 装饰徽标,并通过 load-more 控件增量分页。当 host 暴露 LLM runtime 时,staged diff 会发送到会话模型——或发送到 **设置 → 插件 → 插件配置 → Git** 里配置的自定义 provider/model——流式生成的建议写入可编辑输入框。同一张卡片也可以编辑生成所用的 system message。生成绝不 stage、commit 或 push 任何内容。在 Electron 上,optional Desktop enhancement 在 Desktop provider 存在时提供 reveal-in-folder 与 open-path 操作。 ## 组合 Host plugin 要求 `ctx.subprocess`,提供 `ctx.git`,并使用 executable 与独立 argv values 启动 Git。它绝不调用 shell。DSH Web Host 存在时,optional Connection child 注册 loopback `/git` RPC channel。 Client plugin 要求 Connection、locale、renderer、conversation UI、primitives、session UI 与上游右侧边栏(`ctx.sidebarRight` / `ctx.sidebarRightTabs`,仅类型级 import)。Business components 通过 slot injection 接收 controller 与 `openDetails()`,不访问 Cordis context。 当 `ctx.settingsScope` 存在时,Client 还会把一张卡片注册进 **设置 → 插件 → 插件配置**,命名空间为 `git-commit-message`。Host 不提供该命名空间时,卡片不会出现。 Client main fiber 不要求 `desktop`。Child `ctx.inject(['desktop'], ...)` fiber 只接受 `shell.showItemInFolder`、`shell.openPath` 与 `notification.show`;缺少这些能力时,repository、status、diff、stage、commit 与 branch operations 仍可用,native actions 不显示。 本 package 不发布 runtime invariant companion,因为 Cordis 负责它所使用的 service、RPC registration 与 child-fiber lifetimes。 ## 配置 | 字段 | 默认值 | 含义 | |---|---:|---| | `executable` | `git` | 由 `ctx.subprocess` 解析的 Git executable name 或 absolute path。 | | `maxOutputBytes` | 8 MiB | 单条 Git command 每个 stream 的 collection cap。 | | `graceMs` | 3000 | Managed subprocess termination grace period。 | | `commitMessage.provider` | — | 注册到 DSH LLM runtime 的 provider route。`commitMessage.mode` 为 `custom` 时必填。 | | `commitMessage.model` | — | 由 provider route 解析的 model id。`commitMessage.mode` 为 `custom` 时必填。 | | `commitMessage.mode` | inherit | `inherit` 使用宿主会话模型;`custom` 固定 `provider`/`model`。 | | `commitMessage.systemPrompt` | 内置 | 提交信息生成的 system prompt。空或缺省使用 package 默认值。 | | `commitMessage.maxDiffBytes` | 48 KiB | 生成 prompt 构建前对 staged diff 施加的字节上限(validated 最小值 1024)。 | 整个 `commitMessage` 节是 optional,同时也是 `git-commit-message` 设置命名空间。可在 **设置 → 插件 → 插件配置 → Git** 中编辑,或作为 composition entry。Host 未暴露 LLM runtime,或既没有会话模型也没有可解析的自定义路由时,commit message 生成不可用,Client 报告 `git/generation-unavailable`。 ## Git 操作 首个版本支持 repository discovery、Git version、current branch 与 HEAD、staged/unstaged/untracked status、local branches、working 与 staged diffs、stage/unstage、commit、amend、向 `origin` push、rebase-then-push sync、branch creation 与 branch switching。Status 使用带 NUL path separators 的 porcelain v2;branches 使用 `for-each-ref`;每个 caller-supplied path、branch 与 message 始终作为一个 argv value。 Discard 通过明确的 index、working tree 与 clean 操作还原一条 staged、unstaged 或 untracked 变更,包括暂存后再次编辑的新增和重命名,属于破坏性操作:Client 在发送 RPC 前总是要求第二次显式确认,确认正文会点名该路径。 提交历史以分页 `git log` 读取(`GIT_LOG_FORMAT`,每行一条 commit、固定字段数),Graph surface 通过 load-more 控件增量追加更早的提交,而不是一次性物化整个历史。 Commit message 生成在宿主侧按需启用:需要 LLM runtime 与可解析的模型(会话默认,或自定义 `provider`/`model`)。staged diff(受 `commitMessage.maxDiffBytes` 上限约束)会发送到该路由,流式生成的建议写入可编辑的 commit message 输入框。System prompt 默认为 Conventional Commit 说明,可在插件配置中覆盖。生成只提供建议 —— 它绝不 stage、commit 或 push 任何内容。 GitHub authentication、hosting-provider workflows、credential prompts、issues、pull requests、stash、cherry-pick 与 merge-conflict editing 不属于本 package。Push 与 sync 以独立 argv values 调用 `git push`/`git pull --rebase`,在缺少 remote 或 credentials 时展示 Git 自身的错误。 ## npm 发布 本包已发布到 npm:`@dsh-electron/dsh-plugin-git`(MIT;最新 `0.2.1`)。发布方式为推送 `vX.Y.Z` tag:工作流跑测试与构建、打包 tarball、带构建 provenance 发布到 npm,并把同一个 tarball 附到 GitHub Release。API 与版本保持 pre-1.0。UI 宿主是上游内置的右侧边栏,无需独立安装的第三方配对包。发布步骤与凭据见 [`docs/development/README.md`](docs/development/README.md#发布流程)。 ## 开发 使用 Node.js `^22.19` 或 `>=24` 与 pnpm 11。 ```sh pnpm install --frozen-lockfile pnpm test pnpm build pnpm pack ``` ## Model Experience 无,因为本 package 不注册 model tools、prompt sections 或 request context。 #### KV Cache effect 无。Commit message 生成是独立的 Host LLM 请求,不增加、替换或保留会话 token。 ## Known Limitations and Deferred Work - **无 credential UI** — push 与 sync 调用 Git 时不提示 remote 或 credentials;缺少 `origin` 或认证被拒时以 Git command error 失败。 - **Command output 有界** — 大于 `maxOutputBytes` 的 diff 只保留 subprocess collector tail;处理超大 diff 的 deployment 必须提高这一 validated setting。 - **生成依赖 host 与模型** — commit message 生成需要 host LLM runtime 与可解析的模型(会话默认或插件配置中的自定义路由);两者缺其一时,Generate 动作保持禁用或报告 `git/generation-unavailable`。 ### 开发备注 无。 ## 贡献 环境搭建、质量门禁与文档义务见 [`CONTRIBUTING.md`](CONTRIBUTING.md)。每个已发布版本的用户可见变更见 [`CHANGELOG.md`](CHANGELOG.md)。本包以 MIT 许可发布,见 [`LICENSE`](LICENSE)。