dsh-git-ui 0.0.2 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +55 -20
  2. package/README.zh.md +55 -21
  3. package/cordis.patch.yml +1 -1
  4. package/lib/client.js +36 -35
  5. package/lib/client.js.map +4 -4
  6. package/lib/contracts/host-endpoints.d.ts +27 -0
  7. package/lib/host/actions.d.ts +22 -2
  8. package/lib/host/core.d.ts +7 -1
  9. package/lib/host/index.d.ts +25 -15
  10. package/lib/host/index.js +419 -53
  11. package/lib/host/index.js.map +4 -4
  12. package/lib/host/parser.d.ts +37 -1
  13. package/lib/host/queries.d.ts +17 -0
  14. package/lib/host/types.d.ts +131 -1
  15. package/package.json +1 -1
  16. package/src/adapters/dsh/client-adapter.ts +120 -0
  17. package/src/adapters/dsh/types/cordis.d.ts +48 -0
  18. package/src/adapters/dsh/types/typert-protocol.d.ts +81 -0
  19. package/src/adapters/dsh/types/ui-primitives.d.ts +45 -0
  20. package/src/adapters/dsh/ui-primitives.ts +16 -0
  21. package/src/client/GitCenter.tsx +1414 -149
  22. package/src/client/GitPill.tsx +282 -67
  23. package/src/client/changes-diff.ts +63 -0
  24. package/src/client/controller.ts +34 -31
  25. package/src/client/error-text.ts +21 -0
  26. package/src/client/file-tree.ts +101 -0
  27. package/src/client/git-graph.ts +188 -0
  28. package/src/client/icons.tsx +292 -0
  29. package/src/client/index.ts +38 -134
  30. package/src/client/locales.ts +124 -0
  31. package/src/client/popup-close.ts +19 -0
  32. package/src/client/remote.ts +85 -3
  33. package/src/client/select-menu.tsx +113 -0
  34. package/src/client/side-by-side.ts +150 -0
  35. package/src/client/styles.ts +1375 -86
  36. package/src/client/time-format.ts +32 -0
  37. package/src/contracts/client-platform.ts +147 -0
  38. package/src/contracts/host-endpoints.ts +58 -0
  39. package/src/contracts/plugin-activation.ts +129 -0
  40. package/src/contracts/ui-context.tsx +28 -0
  41. package/src/contracts/ui-primitives.ts +48 -0
  42. package/src/host/actions.ts +66 -15
  43. package/src/host/core.ts +9 -2
  44. package/src/host/index.ts +60 -54
  45. package/src/host/parser.ts +155 -12
  46. package/src/host/queries.ts +289 -0
  47. package/src/host/types.ts +104 -0
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![npm license](https://img.shields.io/npm/l/dsh-git-ui.svg)](https://www.npmjs.com/package/dsh-git-ui)
5
5
  [![npm downloads](https://img.shields.io/npm/dm/dsh-git-ui.svg)](https://www.npmjs.com/package/dsh-git-ui)
6
6
 
7
- A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (dsh) plugin that visualizes Git status in the Web UI: current branch, HEAD, dirty-state counts (staged / modified / untracked), ahead/behind, recent commits, and changed files right in the session header, no terminal needed.
7
+ A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (dsh) plugin that visualizes Git status in the Web UI — the session-header pill shows the current branch (or detached HEAD) and dirty-state counts (staged / modified / untracked) with ahead/behind at a glance. Click for recent commits and changed files, or open the Git center for full management. No terminal needed.
8
8
 
9
9
  > Read this in [简体中文](README.zh.md).
10
10
 
@@ -14,34 +14,41 @@ A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (dsh) plug
14
14
 
15
15
  ## Features
16
16
 
17
- - **Branch pill** in the session header (right-aligned, per-session): shows the current branch at a glance, with dirty-state and ahead/behind indicators:
17
+ - **Branch pill** in the session header (right-aligned, per-session): a status dot (green when clean, orange when dirty) followed by the branch name and dirty / ahead-behind badges — click to open the detail popover:
18
18
 
19
- <img src="docs/screenshots/pill.png" alt="Branch pill in the session header" width="720">
19
+ <img src="docs/screenshots/01-pill面板内容展示.png" alt="Branch pill and the detail popover it opens" width="720">
20
20
 
21
21
  | State | Pill |
22
22
  |---|---|
23
- | Clean | `⎇ main` |
24
- | Dirty | `⎇ main · +2 −1 ?3` (staged / modified / untracked) |
25
- | Ahead / behind | `⎇ main ↑1 ↓2` |
26
- | Detached HEAD | `⎇ (detached) · a1b2c3d` |
27
- | Unborn (no commits) | `⎇ main · 无提交` |
23
+ | Clean | `● main` |
24
+ | Dirty | `● main · +2 −1 ?3` |
25
+ | Ahead / behind | `● main · ↑1 ↓2` |
26
+ | Detached HEAD | `● (detached HEAD) · a1b2c3d` |
27
+ | Unborn (no commits) | `● main · 无提交` |
28
28
  | Not a git repo | Dimmed `无 Git 仓库` |
29
29
  | Git unavailable / error | Dimmed `Git 不可用` (reason in tooltip) |
30
30
 
31
- - **Detail popover** (click the pill): repository root, count grid (staged / modified / untracked / ahead / behind), recent commits (hash · subject · author · relative time), changed-file list with status chips, manual refresh button, and last-checked time:
31
+ `+N −N ?N` = staged / modified / untracked; `↑N ↓N` = ahead / behind. When both dirty and ahead/behind, the badges combine (e.g. `● main · +2 −1 ?3 · ↑1 ↓2`).
32
32
 
33
- <img src="docs/screenshots/popup.png" alt="Git status detail popup" width="720">
33
+ - **Detail popover** (click the pill): repository root, status counts (staged / modified / untracked) with dirty and ahead/behind badges, recent commits (hash · subject · author · relative time), a changed-file list with status chips and inline per-file actions (stage / unstage / discard), an inline branch switcher, a manual refresh button, and last-checked time:
34
34
 
35
- - **Git center** (management panel from the popup): IDE-style changes view — stage / unstage / discard per file or all, and commit with a message (selected files or everything staged). Every operation refreshes the status instantly:
35
+ <img src="docs/screenshots/02-面板选择切换分支.png" alt="Inline branch switching in the detail popover" width="720">
36
36
 
37
- <img src="docs/screenshots/center.png" alt="Git center changes view" width="720">
37
+ - **Git center** (management panel opened from the popover): two tabs — **Changes** and **History**.
38
+ - *Changes*: IDE-style grouped lists (staged / unstaged / untracked), per-file and bulk stage / unstage / discard (two-step confirm), a commit box (selected files or everything staged), and an inline side-by-side diff for the selected file with prev/next navigation.
39
+ - *History*: a paginated commit list with a rendered branch graph, per-commit details (subject · body · changed-file tree), and filters by branch / tag / author / date / text-or-hash, plus a fetch-remote button.
38
40
 
39
- - **Always-fresh data, zero interaction**: automatic fetch on session open, silent polling (host-configured interval, default 30s, no overlapping requests), **immediate refresh when an agent turn completes** (best-effort — the working tree most likely changed right then), resync after reconnect, and a manual refresh button.
40
- - **Deterministic degradation**: non-git directories, missing cwd, missing git, timeouts, and oversized repositories show stable fallback states — never crashes, never spams:
41
+ Every operation refreshes the status instantly:
41
42
 
42
- <img src="docs/screenshots/dirty.png" alt="Clean vs dirty vs non-repository states" width="720">
43
+ <img src="docs/screenshots/03-Git中心统一阅览文件变更.png" alt="Git center Changes tab (grouped file changes)" width="720">
43
44
 
44
- - **Pure read-only UI**: no new model tools, no session events, no impact on agent behavior.
45
+ <img src="docs/screenshots/04-Git中心查看分支历史.png" alt="Git center History tab (commit list with branch graph)" width="720">
46
+
47
+ <img src="docs/screenshots/04-Git中心查看提交详情.png" alt="Git center — commit details and changed-file tree" width="720">
48
+
49
+ - **Always-fresh data, zero interaction**: automatic status snapshot on session open, silent polling (host-configured interval, default 30s, no overlapping requests), **immediate refresh when an agent turn completes** (best-effort — the working tree most likely changed right then), resync after reconnect, and a manual refresh button.
50
+ - **Deterministic degradation**: non-git directories, missing cwd, missing git, timeouts, and oversized repositories show stable fallback states — never crashes, never spams.
51
+ - **Zero agent impact**: adds no model tools and writes no session events — it never changes agent behavior. Git operations in the center (stage / commit / branch / fetch) are user-initiated from the UI, never agent-driven.
45
52
 
46
53
  ## Installation
47
54
 
@@ -78,7 +85,7 @@ dsh plugin --profile web remove dsh-git-ui
78
85
 
79
86
  1. Open a session whose working directory is inside a git repository.
80
87
  2. Read the branch pill in the header at any time — no action needed.
81
- 3. Click the pill to inspect repository root, counts, recent commits, and changed files; use `刷新` (refresh) for an immediate re-check.
88
+ 3. Click the pill to inspect repository root, counts, recent commits, and changed files; use `刷新` (refresh) for an immediate re-check, or open the Git center for full change management and history.
82
89
 
83
90
  Each session shows the Git status of **its own working directory**. Non-repository sessions show a dimmed placeholder instead of the pill.
84
91
 
@@ -103,10 +110,10 @@ All defaults work out of the box. Advanced users may override the plugin config
103
110
 
104
111
  ## Known Limitations
105
112
 
106
- - Shows the Git state of the session's working directory only (no remote URL / push-branch names yet).
113
+ - Shows the Git state of the session's working directory only. The History filter tree lists remote branches with ahead/behind and a manual fetch, but push / pull / merge are not exposed.
107
114
  - Polling-based refresh (default 30s); file-watcher event push is a planned extension.
108
- - Changed-file list is capped (`maxChanges`); when status output overflows the in-memory cap (default 4 MiB) it is recovered from a private spill file so counts stay exact — only if the spill cap (64 MiB) also overflows does the snapshot fall back to approximate (`truncated: true`).
109
- - Browser never sends paths — only a `sessionId`; the host resolves the authoritative cwd and runs read-only git commands.
115
+ - Changed-file list is capped (`maxChanges`); untracked-directory contents are enumerated individually. When status output overflows the in-memory cap (default 4 MiB) it is recovered from a private spill file so counts stay exact — only if the spill cap (64 MiB) also overflows does the snapshot fall back to approximate (`truncated: true`).
116
+ - Browser never sends paths — only a `sessionId`; the host resolves the authoritative cwd and runs git commands (write operations use `--` path separation and reject absolute / `..` escapes).
110
117
 
111
118
  ## Development
112
119
 
@@ -126,6 +133,34 @@ pnpm run build # host (esbuild ESM, never minified) + client (ModuleLoade
126
133
  dsh plugin --profile web add ./ # local install; restart dsh web to verify
127
134
  ```
128
135
 
136
+ ### Architecture
137
+
138
+ The plugin is layered to isolate the dsh platform behind a narrow adapter seam,
139
+ so business logic stays untouched when dsh APIs evolve:
140
+
141
+ ```mermaid
142
+ flowchart TB
143
+ subgraph Biz["Business Layer — zero dsh imports"]
144
+ HostBiz["src/host/ · core / actions / queries / parser"]
145
+ ClientBiz["src/client/ · controller / GitPill / GitCenter"]
146
+ end
147
+ subgraph Contracts["Contracts Layer — stable interfaces"]
148
+ C["src/contracts/ · host-endpoints / client-platform / ui-primitives"]
149
+ end
150
+ subgraph Adapters["Adapters Layer — the only dsh-aware code"]
151
+ A["src/adapters/dsh/ · client-adapter / ui-primitives / types"]
152
+ end
153
+ HostBiz --> C
154
+ ClientBiz --> C
155
+ C --> A
156
+ A --> DSH["dsh platform · cordis / typert / ui-primitives"]
157
+ ```
158
+
159
+ - `src/contracts/` defines the plugin's own stable interfaces (no dsh imports).
160
+ - `src/host/` and `src/client/` implement business logic against those interfaces.
161
+ - `src/adapters/dsh/` is the **only** place that imports `@deepseek-ai/*`;
162
+ a dsh upgrade only requires changes here.
163
+
129
164
  ## License
130
165
 
131
166
  [MIT](LICENSE)
package/README.zh.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![npm license](https://img.shields.io/npm/l/dsh-git-ui.svg)](https://www.npmjs.com/package/dsh-git-ui)
5
5
  [![npm downloads](https://img.shields.io/npm/dm/dsh-git-ui.svg)](https://www.npmjs.com/package/dsh-git-ui)
6
6
 
7
- [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(dsh)Web UI 插件:在会话界面中可视化展示当前工程的 Git 状态——分支、HEAD、脏状态计数(已暂存/已修改/未跟踪)、领先/落后、最近提交与变更文件。无需切换终端,扫一眼即得。
7
+ [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(dsh)Web UI 插件:在会话界面中可视化展示 Git 状态——会话头部的 Pill 一眼呈现当前分支(或游离 HEAD)与脏状态计数(已暂存/已修改/未跟踪)及领先/落后。点击查看最近提交与变更文件,或打开 Git 中心进行完整管理。无需切换终端。
8
8
 
9
9
  > English version: [README.md](README.md)
10
10
 
@@ -14,34 +14,41 @@
14
14
 
15
15
  ## 功能特性
16
16
 
17
- - **会话头部分支 Pill**(右侧、每会话独立):常态只显示分支,脏状态与领先/落后以徽标呈现:
17
+ - **会话头部分支 Pill**(右侧、每会话独立):状态点(干净为绿、脏为橙)+ 分支名 + 脏/领先落后徽标——点击展开详情面板:
18
18
 
19
- <img src="docs/screenshots/pill.png" alt="会话头部分支 Pill" width="720">
19
+ <img src="docs/screenshots/01-pill面板内容展示.png" alt="会话头部分支 Pill 与展开的详情面板" width="720">
20
20
 
21
21
  | 状态 | Pill 显示 |
22
22
  |---|---|
23
- | 干净 | `⎇ main` |
24
- | 脏状态 | `⎇ main · +2 −1 ?3`(已暂存/已修改/未跟踪) |
25
- | 领先/落后 | `⎇ main ↑1 ↓2` |
26
- | 游离 HEAD | `⎇ (detached) · a1b2c3d` |
27
- | unborn(无提交) | `⎇ main · 无提交` |
23
+ | 干净 | `● main` |
24
+ | 脏状态 | `● main · +2 −1 ?3` |
25
+ | 领先/落后 | `● main · ↑1 ↓2` |
26
+ | 游离 HEAD | `● (游离 HEAD) · a1b2c3d` |
27
+ | unborn(无提交) | `● main · 无提交` |
28
28
  | 非 git 仓库 | 弱化显示 `无 Git 仓库` |
29
29
  | git 不可用/出错 | 弱化显示 `Git 不可用`(tooltip 显示原因) |
30
30
 
31
- - **详情面板**(点击 pill 展开):仓库根目录、计数格(已暂存/已修改/未跟踪/领先/落后)、最近提交(哈希·主题·作者·相对时间)、变更文件列表(状态 chip)、手动刷新按钮、上次检查时间:
31
+ `+N −N ?N` = 已暂存/已修改/未跟踪;`↑N ↓N` = 领先/落后。脏且领先落后时徽标合并(如 `● main · +2 −1 ?3 · ↑1 ↓2`)。
32
32
 
33
- <img src="docs/screenshots/popup.png" alt="Git 状态详情面板" width="720">
33
+ - **详情面板**(点击 pill 展开):仓库根目录、状态计数(已暂存/已修改/未跟踪)+ 脏与领先落后徽标、最近提交(哈希·主题·作者·相对时间)、变更文件列表(状态 chip + 行内暂存/取消/丢弃操作)、分支内联切换、手动刷新按钮、上次检查时间:
34
34
 
35
- - **Git 中心**(从面板进入的管理面板):IDE 式变更视图——单文件/全部暂存、取消暂存、丢弃,以及带提交信息的提交(勾选文件或全部已暂存)。每次操作即时刷新状态:
35
+ <img src="docs/screenshots/02-面板选择切换分支.png" alt="详情面板内的分支内联切换" width="720">
36
36
 
37
- <img src="docs/screenshots/center.png" alt="Git 中心变更视图" width="720">
37
+ - **Git 中心**(从面板进入的管理面板):双标签——**变更**与**历史**。
38
+ - *变更*:IDE 式三段分组(已暂存/更改/未跟踪),单文件与全部暂存/取消暂存/丢弃(两步确认)、提交框(勾选文件或全部已暂存),以及选中文件的并排差异对照(前后导航)。
39
+ - *历史*:分页提交列表 + 分支图渲染,每条提交详情(主题·正文·变更文件树),按分支/标签/作者/日期/文本或哈希过滤,以及拉取远程按钮。
38
40
 
39
- - **数据自动保鲜,零操作**:进入会话自动拉取、静默轮询(间隔由主机下发,默认 30s,不重叠请求)、**agent 完成一个回合后立即刷新**(尽力而为——此时工作区最可能已变化)、断线重连 resync、面板内手动刷新。
40
- - **确定性降级**:非 git 目录、无 cwd、git 缺失、超时、巨型仓库等边界显示稳定降级态——不崩溃、不刷屏:
41
+ 每次操作即时刷新状态:
41
42
 
42
- <img src="docs/screenshots/dirty.png" alt="干净 / 脏状态 / 非 git 仓库对照" width="720">
43
+ <img src="docs/screenshots/03-Git中心统一阅览文件变更.png" alt="Git 中心——变更标签(分组文件变更)" width="720">
43
44
 
44
- - **纯只读 UI**:不给模型新增工具、不写会话事件,不改变 agent 的任何行为。
45
+ <img src="docs/screenshots/04-Git中心查看分支历史.png" alt="Git 中心——历史标签(提交列表与分支图)" width="720">
46
+
47
+ <img src="docs/screenshots/04-Git中心查看提交详情.png" alt="Git 中心——提交详情与变更文件树" width="720">
48
+
49
+ - **数据自动保鲜,零操作**:进入会话自动加载状态快照、静默轮询(间隔由主机下发,默认 30s,不重叠请求)、**agent 完成一个回合后立即刷新**(尽力而为——此时工作区最可能已变化)、断线重连 resync、面板内手动刷新。
50
+ - **确定性降级**:非 git 目录、无 cwd、git 缺失、超时、巨型仓库等边界显示稳定降级态——不崩溃、不刷屏。
51
+ - **零 agent 影响**:不给模型新增工具、不写会话事件,从不改变 agent 行为。Git 中心的写操作(暂存/提交/分支/拉取)均由用户从 UI 主动发起,绝非 agent 驱动。
45
52
 
46
53
  ## 安装
47
54
 
@@ -76,7 +83,7 @@ dsh plugin --profile web remove dsh-git-ui
76
83
 
77
84
  1. 打开一个工作目录位于 git 仓库内的会话。
78
85
  2. 随时扫一眼头部 Pill——无需任何操作。
79
- 3. 点击 Pill 查看仓库根目录、计数、最近提交与变更文件;点 `刷新` 立即重新检查。
86
+ 3. 点击 Pill 查看仓库根目录、计数、最近提交与变更文件;点 `刷新` 立即重新检查,或打开 Git 中心进行完整变更管理与历史浏览。
80
87
 
81
88
  每个会话显示**自己工作目录**的 Git 状态;非仓库会话显示弱化占位而非 Pill。
82
89
 
@@ -97,14 +104,14 @@ dsh plugin --profile web remove dsh-git-ui
97
104
 
98
105
  - Node.js `^22.19.0 || >=24.0.0`
99
106
  - dsh `>= 0.1.0-rc`(开发者预览版)
100
- - 主机可执行 `git`(插件通过子进程调用只读 git 命令)
107
+ - 主机可执行 `git`(插件通过子进程调用 git 命令)
101
108
 
102
109
  ## 已知限制
103
110
 
104
- - 仅展示会话工作目录的 Git 状态(远程 URL、push 分支名暂未支持)。
111
+ - 仅展示会话工作目录的 Git 状态。历史页的过滤树列出远程分支、领先/落后与手动拉取,但不暴露 push / pull / merge。
105
112
  - 轮询式刷新(默认 30s);基于文件监听的事件推送为规划中的扩展。
106
- - 变更文件列表有上限(`maxChanges`);status 输出超过内存上限(默认 4 MiB)时会从私有 spill 文件恢复完整输出,**计数保持精确**——仅当 spill 上限(64 MiB)也被突破时才回退为近似(`truncated: true`)。
107
- - 浏览器只传 `sessionId`,不传路径;主机解析权威 cwd 并仅执行只读 git 命令。
113
+ - 变更文件列表有上限(`maxChanges`);未跟踪目录内部文件逐个枚举。status 输出超过内存上限(默认 4 MiB)时会从私有 spill 文件恢复完整输出,**计数保持精确**——仅当 spill 上限(64 MiB)也被突破时才回退为近似(`truncated: true`)。
114
+ - 浏览器只传 `sessionId`,不传路径;主机解析权威 cwd 并执行 git 命令(写操作用 `--` 路径分隔、拒绝绝对路径与 `..` 逃逸)。
108
115
 
109
116
  ## 开发
110
117
 
@@ -123,6 +130,33 @@ pnpm run build # host(esbuild ESM,禁止压缩)+ client(ModuleLoa
123
130
  dsh plugin --profile web add ./ # 本地安装;重启 dsh web 验证
124
131
  ```
125
132
 
133
+ ### 架构
134
+
135
+ 插件采用分层架构,将 dsh 平台隔离在窄适配层之后,dsh API 演进时业务逻辑零改动:
136
+
137
+ ```mermaid
138
+ flowchart TB
139
+ subgraph Biz["业务层 — 零 dsh import"]
140
+ HostBiz["src/host/ · core / actions / queries / parser"]
141
+ ClientBiz["src/client/ · controller / GitPill / GitCenter"]
142
+ end
143
+ subgraph Contracts["契约层 — 稳定接口"]
144
+ C["src/contracts/ · host-endpoints / client-platform / ui-primitives"]
145
+ end
146
+ subgraph Adapters["适配层 — 唯一感知 dsh 的代码"]
147
+ A["src/adapters/dsh/ · client-adapter / ui-primitives / types"]
148
+ end
149
+ HostBiz --> C
150
+ ClientBiz --> C
151
+ C --> A
152
+ A --> DSH["dsh 平台 · cordis / typert / ui-primitives"]
153
+ ```
154
+
155
+ - `src/contracts/` 定义插件自己的稳定接口(零 dsh import)。
156
+ - `src/host/` 与 `src/client/` 基于这些接口实现业务逻辑。
157
+ - `src/adapters/dsh/` 是**唯一** import `@deepseek-ai/*` 的地方;
158
+ dsh 升级只需修改此处。
159
+
126
160
  ## 许可证
127
161
 
128
162
  [MIT](LICENSE)
package/cordis.patch.yml CHANGED
@@ -10,5 +10,5 @@
10
10
  config:
11
11
  timeoutMs: 5000
12
12
  maxStatusBytes: 4194304
13
- maxChanges: 100
13
+ maxChanges: 500
14
14
  defaultRefreshIntervalMs: 30000