@xbzbing/dsh-git-panel 0.1.0

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xbzbing
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,90 @@
1
+ # dsh-git-panel
2
+
3
+ [English](README_EN.md) | 简体中文
4
+
5
+ `dsh-git-panel` 是一个 DSH Web GUI 插件,在对话工作区里提供 IDE 风格的 Git 面板。它把分支列表、提交历史图、未提交变更的提交与 amend、语法高亮的差异对照集中到一个常驻标签页,并在输入框左侧放一个 zsh 风格的分支标记,让你在对话过程中随手查看仓库状态、提交改动,不必切到终端或另开 IDE。
6
+
7
+ 面板只读取当前会话工作目录所在的 Git 仓库,所有 git 命令都以 argv 数组经宿主的 subprocess 服务执行,不拼接 shell 字符串,工作目录锁定在仓库根,并带超时与输出上限。插件不改动 git 配置,写操作(提交、amend、暂存、丢弃)都有明确入口。
8
+
9
+ ## 安装
10
+
11
+ ```bash
12
+ # npm(默认)
13
+ dsh plugin add @xbzbing/dsh-git-panel
14
+
15
+ # 或从 GitHub 仓库安装(仓库已提交构建产物,无需本地构建)
16
+ dsh plugin add github:xbzbing/dsh-git-panel
17
+ ```
18
+
19
+ 安装后重启或刷新 Web GUI,工作区标签栏(「对话」「轨迹」之后)就会出现 **Git** 面板。
20
+
21
+ ## 功能
22
+
23
+ - **Git 总览**:三栏布局。左栏是分支 / 标签列表,点击某个引用即按它过滤历史;中栏是提交历史图,支持按提交信息、commit 哈希、作者、日期搜索,悬停某条提交弹出卡片显示完整提交信息(comment);右栏是选中提交的变更文件树与提交信息,点击文件在弹出的 modal 里查看该文件在此提交中的差异。
24
+ - **变更记录**:面向本地工作区。左栏是统计条(文件数 / 增删行数 / 最近变更时间)、带复选框的未提交变更列表、以及含 **Amend** 复选框的提交框,支持逐文件暂存 / 取消暂存 / 丢弃与手动提交;右栏是选中文件的 side-by-side 差异对照。
25
+ - **语法高亮差异**:两处差异视图(总览 modal 与变更记录)都带懒加载的 highlight.js 语法高亮,按文件扩展名选择语法,高亮首次查看 diff 时才动态加载。
26
+ - **展开未变更行**:差异工具栏提供「展开全部 / 折叠未变更」切换,展开后显示整个文件而不只是变更附近的上下文。
27
+ - **对照模式**:差异支持「对照 / 变更前 / 变更后」三种视图切换。
28
+ - **图片对照**:png、jpg 等图片文件的差异不显示二进制占位,改为「变更前 / 变更后」新旧双图并排对照(总览 modal 与变更记录同样生效);新增或删除的图片在另一侧显示「不存在」。
29
+ - **显示输入框标记开关**:插件详情页可切换输入框标记;关闭后输入框不再显示分支标记,改为在「Git」标签旁显示状态圆点(绿=已同步、橙色=有变更),两者互斥,保存后立即生效。
30
+ - **输入框 Git 标记**:一个 zsh 主题风格的 `<仓库名> (<分支>)` 标记,仓库名青色,`(分支)` 在已同步时为绿色、有未提交变更时为橙色;悬停显示完整仓库路径,点击跳转面板(有未提交变更进入变更记录,否则进入 Git 总览);当前目录不是 Git 仓库时只显示目录名,不报错。
31
+ - **版本与仓库入口**:子标签行右侧显示插件版本号,旁边有「检查新版本」按钮(用户主动点击才比对 GitHub 最新发布)和一个跳转到 GitHub 仓库的图标。
32
+ - UI 跟随 DSH 系统语言设置,支持简体中文和英文。
33
+
34
+ ## 界面
35
+
36
+ | Git 总览 | 文件差异 modal |
37
+ | :---: | :---: |
38
+ | ![Git 总览:分支、提交历史图、提交详情与 hover 卡片](docs/assets/screenshots/1-git-panel-overview.png) | ![文件差异 modal:语法高亮的 side-by-side 对照](docs/assets/screenshots/2-overview-tab.png) |
39
+ | 变更记录 | 插件详情 |
40
+ | ![变更记录:统计条、未提交变更列表、提交框与差异对照](docs/assets/screenshots/3-changes.png) | ![DSH 插件页中的 Git 面板](docs/assets/screenshots/4-plugin-detail.png) |
41
+
42
+ ## 架构
43
+
44
+ 插件分 host / client 两半,通过 typert Remote 网关通信。
45
+
46
+ - **Host**(`lib/host/`):`gitPanel` 命名空间上的 Cordis + typert `GitPanelService`,暴露 `snapshot` / `run` / `query` / `version` 四个端点,仅做端点委托与生命周期接线;git 命令经宿主 `subprocess` 服务执行(argv 数组、无 shell、cwd 锁仓库根、超时 + 输出上限)。
47
+ - **Client**(`lib/client.js`):一个 React 包,注册 `conversation.view` 面板和 `conversation.input.left` 标记。每会话一个快照控制器(轮询 + turn 完成后刷新 + 连接重置重拉),标记、变更记录页和统计条共用同一份快照,避免重复 git 命令。
48
+
49
+ ## 开发
50
+
51
+ ```bash
52
+ node build.mjs # tsc(host d.ts)+ esbuild(host bundle + client bundle + testkit)
53
+ npm run typecheck # 类型检查
54
+ npm run test:unit # 纯算法与 host 端点单测(node --test)
55
+ npm run test:e2e # 隔离的 file:// 无头浏览器 e2e(不碰任何运行中的实例)
56
+ npm test # 单测 + e2e
57
+ ```
58
+
59
+ host bundle 不做压缩:typert 网关靠方法参数名做参数校验,压缩会改名并破坏 wire 契约。client 改动没有热重载,需重新构建并刷新页面。`lib/` 作为构建产物随 git 提交入库,改动 `src/` 后必须重新构建并提交,否则从 GitHub 安装会加载到过期入口;测试期生成的 `lib/testkit.mjs` 不入库。本地联调:把插件加入 dsh web profile 的 `dsh.profile.bundles`,用 `file:` 依赖指向本目录,构建后即生效。
60
+
61
+ ## 项目结构
62
+
63
+ ```text
64
+ src/
65
+ host/
66
+ types.ts wire 数据模型的唯一权威源(client 直接复用)
67
+ index.ts GitPanelService:端点委托与生命周期接线
68
+ git.ts subprocess → 带超时的 GitRunner
69
+ core.ts workspace 解析 + snapshotForSession
70
+ actions.ts GitAction → git 命令序列(commit / amend / stage 等)
71
+ queries.ts history / diff / image-diff / show / branches / tags / worktree-stats
72
+ parser.ts git 输出解析为结构化数据
73
+ version.ts 本包版本 + GitHub release 更新检查
74
+ client/
75
+ rpc.ts gitPanel 端点的 client 面
76
+ controller.ts 每会话快照控制器
77
+ Panel.tsx 主面板壳:子 tab 路由 + 版本条
78
+ OverviewTab.tsx Git 总览三栏 + hover 卡片
79
+ ChangesTab.tsx 变更记录页
80
+ DiffView.tsx 并排差异视图
81
+ GitPill.tsx 输入框标记
82
+ highlight.ts diff 语法高亮的懒加载门面
83
+ git-graph.ts 提交图车道布局
84
+ file-tree.ts 路径折树
85
+ diff.ts unified diff → 并排行 + 统计
86
+ ```
87
+
88
+ ## 许可证
89
+
90
+ 本项目采用 [MIT License](LICENSE)。
package/README_EN.md ADDED
@@ -0,0 +1,90 @@
1
+ # dsh-git-panel
2
+
3
+ English | [简体中文](README.md)
4
+
5
+ `dsh-git-panel` is a DSH Web GUI plugin that brings an IDE-style Git panel into the conversation workspace. It gathers the branch list, commit history graph, uncommitted-change commit & amend, and syntax-highlighted diffs into one resident tab, and puts a zsh-style branch marker at the left of the input bar — so you can check repo status and commit changes mid-conversation without switching to a terminal or a separate IDE.
6
+
7
+ The panel only reads the Git repository at the current session's working directory. Every git command runs through the host subprocess service as an argv array — no shell string concatenation — with the working directory locked to the repository root and per-command timeout and output caps. The plugin never touches your git config, and every write (commit, amend, stage, discard) has an explicit entry point.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ # npm (default)
13
+ dsh plugin add @xbzbing/dsh-git-panel
14
+
15
+ # or from the GitHub repository (the built tree is committed, no local build needed)
16
+ dsh plugin add github:xbzbing/dsh-git-panel
17
+ ```
18
+
19
+ Restart or refresh the Web GUI afterwards and the **Git** panel appears in the workspace tab bar (after Chat and Trajectory).
20
+
21
+ ## Features
22
+
23
+ - **Overview** — three columns. The left column is the branch / tag list; clicking a ref filters history by it. The middle column is the commit history graph, searchable by commit message, commit hash, author, or date; hovering a commit shows a card with its full commit message (comment). The right column is the selected commit's changed-file tree and commit message; click a file to see its diff within that commit in a modal.
24
+ - **Changes** — the local working tree. The left column has a statistics bar (file count / added·deleted lines / last-change time), the uncommitted change list with per-file checkboxes, and a commit box with an **Amend** checkbox; per-file stage / unstage / discard and manual commit are supported. The right column is the selected file's side-by-side diff.
25
+ - **Syntax-highlighted diffs** — both diff views (the overview modal and the changes page) render lazy-loaded highlight.js syntax highlighting, picking a grammar by file extension; the highlighter is dynamically imported only the first time a diff is viewed.
26
+ - **Expand unchanged lines** — the diff toolbar offers an "expand all / collapse unchanged" toggle; expanded, it shows the whole file instead of just the context around each change.
27
+ - **Diff modes** — split / before / after views.
28
+ - **Image compare** — diffs of image files (png, jpg, …) skip the binary placeholder and render "before / after" panes side by side (in both the overview modal and the changes page); an added or deleted image shows "Does not exist" on the other pane.
29
+ - **Show input-bar marker toggle** — the plugin detail page can toggle the input-bar marker; when off, the input bar stays clean and the Git tab shows a status dot instead (green = synced, orange = dirty). The two are mutually exclusive and changes apply immediately.
30
+ - **Input-bar Git marker** — a zsh-theme `<repo> (<branch>)` marker: the repo name is cyan, `(branch)` is green when in sync and orange when there are uncommitted changes; hover shows the full repository path, and clicking jumps to the panel (to Changes when dirty, otherwise to Overview); when the current directory is not a Git repository, it shows only the directory name, with no error text.
31
+ - **Version & repo entry** — the sub-tab row shows the plugin version on the right, next to a "Check for updates" button (queries GitHub for the latest release only when clicked) and an icon linking to the GitHub repository.
32
+ - The UI follows the DSH system language, in Simplified Chinese and English.
33
+
34
+ ## Screenshots
35
+
36
+ | Overview | File-diff modal |
37
+ | :---: | :---: |
38
+ | ![Overview: branches, commit graph, commit detail, hover card](docs/assets/screenshots/1-git-panel-overview.png) | ![File-diff modal: syntax-highlighted side-by-side diff](docs/assets/screenshots/2-overview-tab.png) |
39
+ | Changes | Plugin detail |
40
+ | ![Changes: stats bar, uncommitted list, commit box, diff](docs/assets/screenshots/3-changes.png) | ![The Git panel in the DSH plugins page](docs/assets/screenshots/4-plugin-detail.png) |
41
+
42
+ ## Architecture
43
+
44
+ Two halves communicating over the typert Remote gateway.
45
+
46
+ - **Host** (`lib/host/`) — a Cordis + typert `GitPanelService` on the `gitPanel` namespace, exposing `snapshot` / `run` / `query` / `version` and doing only endpoint delegation and lifecycle wiring; git runs through the host `subprocess` service (argv arrays, no shell, cwd locked to the repository root, timeout + output caps).
47
+ - **Client** (`lib/client.js`) — a React bundle that registers the `conversation.view` panel and the `conversation.input.left` marker. One snapshot controller per session (polling + a refresh after each turn + a reload on connection reset) feeds the marker, the changes page, and the stats bar from a single snapshot, avoiding duplicate git commands.
48
+
49
+ ## Development
50
+
51
+ ```bash
52
+ node build.mjs # tsc (host d.ts) + esbuild (host bundle + client bundle + testkit)
53
+ npm run typecheck # type check
54
+ npm run test:unit # pure-algorithm and host-endpoint unit tests (node --test)
55
+ npm run test:e2e # isolated file:// headless-browser e2e (never touches a running instance)
56
+ npm test # unit + e2e
57
+ ```
58
+
59
+ The host bundle is not minified: the typert gateway validates arguments by method parameter name, and minification would rename them and break the wire contract. Client changes are not hot-reloaded — rebuild and refresh the page. `lib/` is committed as a build artifact so `dsh plugin add github:…` installs the built tree directly; after editing `src/` you must rebuild and commit, or a GitHub install loads a stale entry. The test-time `lib/testkit.mjs` is not committed. For local development, add the plugin to a dsh web profile's `dsh.profile.bundles` with a `file:` dependency pointing at this directory; a rebuild makes it effective.
60
+
61
+ ## Project structure
62
+
63
+ ```text
64
+ src/
65
+ host/
66
+ types.ts the single source of truth for the wire data model (reused by the client)
67
+ index.ts GitPanelService: endpoint delegation + lifecycle wiring
68
+ git.ts subprocess → a GitRunner with timeouts
69
+ core.ts workspace resolution + snapshotForSession
70
+ actions.ts GitAction → git command sequences (commit / amend / stage …)
71
+ queries.ts history / diff / image-diff / show / branches / tags / worktree-stats
72
+ parser.ts git output parsed into structured data
73
+ version.ts package version + GitHub release update check
74
+ client/
75
+ rpc.ts the client face of the gitPanel endpoints
76
+ controller.ts per-session snapshot controller
77
+ Panel.tsx panel shell: sub-tab routing + version bar
78
+ OverviewTab.tsx Overview three columns + hover card
79
+ ChangesTab.tsx changes page
80
+ DiffView.tsx side-by-side diff view
81
+ GitPill.tsx input-bar marker
82
+ highlight.ts lazy-loading facade for diff syntax highlighting
83
+ git-graph.ts commit-graph lane layout
84
+ file-tree.ts file paths folded into a tree
85
+ diff.ts unified diff → side-by-side rows + stats
86
+ ```
87
+
88
+ ## License
89
+
90
+ [MIT License](LICENSE).
@@ -0,0 +1,12 @@
1
+ # dsh-git-panel bundle patch: insert the host half as one cordis row.
2
+ # The package's dsh.bundle.patch points here; the row's host half
3
+ # (lib/host/index.js) loads as a plain cordis plugin, and the dsh.client
4
+ # metadata composes the browser half (lib/client.js).
5
+ - insert:
6
+ - id: git-panel
7
+ name: dsh-git-panel
8
+ config:
9
+ timeoutMs: 8000
10
+ maxBytes: 4194304
11
+ maxChanges: 1000
12
+ refreshIntervalMs: 30000
package/icon.svg ADDED
@@ -0,0 +1,15 @@
1
+ <svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <linearGradient id="gpNode" x1="7" y1="5" x2="29" y2="31" gradientUnits="userSpaceOnUse">
4
+ <stop stop-color="#4E9BFF"/>
5
+ <stop offset="1" stop-color="#2F80ED"/>
6
+ </linearGradient>
7
+ </defs>
8
+ <!-- git graph: a trunk with one branch that merges back -->
9
+ <path d="M11 8 V28" stroke="#4E9BFF" stroke-width="2.4" stroke-linecap="round"/>
10
+ <path d="M11 13 C11 18 25 15 25 20" stroke="#2F9C80" stroke-width="2.4" stroke-linecap="round" fill="none"/>
11
+ <path d="M25 20 C25 24 11 22 11 26" stroke="#2F9C80" stroke-width="2.4" stroke-linecap="round" fill="none"/>
12
+ <circle cx="11" cy="8" r="3.4" fill="url(#gpNode)" stroke="#1F4B8F" stroke-width="1"/>
13
+ <circle cx="25" cy="20" r="3.4" fill="#2F9C80" stroke="#1C6B57" stroke-width="1"/>
14
+ <circle cx="11" cy="28" r="3.4" fill="url(#gpNode)" stroke="#1F4B8F" stroke-width="1"/>
15
+ </svg>