@shiqyka/dsh-git-graph 0.0.0-stage → 0.26.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.
- package/LICENSE +21 -0
- package/README.md +139 -2
- package/README_EN.md +140 -0
- package/client.js +64 -0
- package/cordis.patch.yml +21 -0
- package/index.js +1545 -0
- package/package.json +64 -4
- package/web/app.css +1194 -0
- package/web/app.js +4374 -0
- package/web/index.html +258 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-git-graph contributors
|
|
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
CHANGED
|
@@ -1,3 +1,140 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-git-graph
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**DSH 里开箱即用的 Git 可视化。** 在 DeepSeek Harness 的对话界面内直接看提交历史图、管分支、读 Diff、处理未提交改动——AI 开发时不用再切到别的 Git 客户端。
|
|
4
|
+
|
|
5
|
+
[中文](./README.md) · [English](./README_EN.md) · 
|
|
6
|
+
|
|
7
|
+
<img src="assets/git-graph-demo.png" alt="Git 图谱" width="760">
|
|
8
|
+
|
|
9
|
+
## 为什么用它
|
|
10
|
+
|
|
11
|
+
- **不离开对话**:图谱是会话页里的一个标签,和「轨迹」并排。切换工作区,图谱自动跟着切到对应仓库。
|
|
12
|
+
- **不用等**:首屏 50 条、下滑续拉;分支列表与自动刷新里的 ref 探测直接读 `.git` 下的 refs 文件,**不启动 git 进程**。在装了实时防护、`git` 每次启动要几百毫秒的机器上,这一项直接决定「读历史快不快」。
|
|
13
|
+
- **不止能看**:暂存、提交、还原、打标签、切分支、拉取推送都在页面里完成,破坏性操作一律先弹确认。
|
|
14
|
+
|
|
15
|
+
## 安装
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# 从 GitHub
|
|
19
|
+
dsh plugin --profile web add github:siqyka/dsh-git-graph
|
|
20
|
+
|
|
21
|
+
# 或从 npm
|
|
22
|
+
dsh plugin --profile web add @shiqyka/dsh-git-graph
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
装完**重启 `dsh web`**,回到浏览器打开 dsh web 输出的地址,在任意会话页点「Git 图谱」标签(在「轨迹」旁边)即可查看。
|
|
26
|
+
|
|
27
|
+
**开发者 / 离线**:`dsh plugin --profile web add link:<本仓库路径>` 直挂仓库目录,改完代码重启 `dsh web` 即生效,无需复制文件。
|
|
28
|
+
|
|
29
|
+
### 可选:固定仓库白名单
|
|
30
|
+
|
|
31
|
+
默认**无需任何配置**——自动发现当前会话工作区的 git 仓库,「打开文件夹」添加的仓库也会记住。需要固定白名单时,在 profile 的 `cordis.patch.yml` 里给插件行加 `config`:
|
|
32
|
+
|
|
33
|
+
```yaml
|
|
34
|
+
- insert:
|
|
35
|
+
- id: git-graph
|
|
36
|
+
name: '@shiqyka/dsh-git-graph'
|
|
37
|
+
config:
|
|
38
|
+
repo: "C:/path/to/your/repo" # 或 repos: [ ... ] 数组
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 功能
|
|
42
|
+
|
|
43
|
+
### 📜 看提交历史
|
|
44
|
+
|
|
45
|
+
- **提交图**:GitHub 风格列表,本地 / 远程分支各自成组、各有配色,组头可点击折叠。
|
|
46
|
+
- **泳道图**:平铺模式下左侧绘制真正的分叉与合并曲线(与 VS Code Git Graph 同款「预留点」算法)。分组模式不画——组头会切断泳道。
|
|
47
|
+
- **提交详情**:修改文件列表、单文件 diff、完整补丁;📜 可查单个文件的历史提交。详情面板可拖动调宽、双击复位、宽度自动记忆。
|
|
48
|
+
- **三种过滤**:分支过滤(不勾 = 完全隐藏)、日期区间(应用内日历,允许只填一端)、搜索(消息 / 作者 / 哈希 / 邮箱)。命中不到时有「恢复全选」/「清除筛选」出口。
|
|
49
|
+
- **键盘导航**:`↑` `↓` / `j` `k` 逐条切换并同步打开详情。鼠标与方向键共用**同一个游标**——点第 6 行再按 `↓` 就是第 7 行。
|
|
50
|
+
|
|
51
|
+
### 📝 改工作区
|
|
52
|
+
|
|
53
|
+
- **未提交改动**常驻图谱顶部:已暂存 / 更改 / 未跟踪三组,状态徽标 `A/M/D/R/U/?` 与每文件 `+/−` 行数。
|
|
54
|
+
- 点击行展开单文件 diff(语法高亮);重命名显示 `新 ← 旧`,未跟踪文件直接显示内容。☑ 分组菜单可单独隐藏某组。
|
|
55
|
+
- 行内 **暂存 / 取消暂存 / 还原**;顶栏 **全部暂存 / 提交**;勾选复选框批量 **暂存 / 取消暂存 / 还原 / 忽略 / 提交选中**(只提交选中文件,其余改动不受影响)。
|
|
56
|
+
- 提交对话框可 **✨ AI 生成提交信息**:按 diff 统计启发式生成候选,可编辑。无外部 AI 调用。
|
|
57
|
+
- 文件超过 10 行时列表内部滚动,顶栏按钮与批量条保持钉住。
|
|
58
|
+
|
|
59
|
+
### 🌿 管分支
|
|
60
|
+
|
|
61
|
+
- **顶栏图标**:打开文件夹 / 拉取(`fetch --all --prune`)/ 推送当前分支 / 刷新。
|
|
62
|
+
- **分支组头右键**:本地分支可切换 / 推送 / 删除(`-d` 拒绝未合并,HEAD 受保护);远程分支可拉取 / 复制分支名。远程组头始终显示,并标注「已同步」/「已包含」。
|
|
63
|
+
- **提交行右键**:复制哈希 / 消息、打标签(可改名、删除)、从提交新建分支、打开 GitHub 提交页、复制仓库路径、在文件管理器中打开。
|
|
64
|
+
- **多仓库**:「打开文件夹」可浏览磁盘添加任意仓库,持久记住,顶部下拉随时切换。
|
|
65
|
+
|
|
66
|
+
### 🎨 用起来
|
|
67
|
+
|
|
68
|
+
- **主题**:自动 / 深色 / 浅色,外加 8 种风格方案(🌸 樱花 · 🌊 海洋 · 🌲 森林 · 🌙 夜空 · 🍬 糖果 · 💼 商务 · ✨ 星河 · 🤖 科技),每种带专属动态背景。
|
|
69
|
+
- **⚙ 设置**(齿轮,二级页面):视图(按分支分组 / 平铺)、主题(带颜色圆点的网格)、快捷键入口。任一选项非默认时齿轮右上角有小圆点。
|
|
70
|
+
- **状态记忆**:过滤、折叠、主题、日期区间落盘到插件目录的 `.state/prefs.json`——换端口、重启 dsh web 都不会丢(localStorage 按 origin 隔离,端口一变就清空)。
|
|
71
|
+
- **自动刷新**:页面可见时每 5 秒探测改动,自动更新统计与列表;切工作区每 3 秒跟随一次。
|
|
72
|
+
- **自动更新**:静默检查 GitHub 最新 tag,一键下载并替换(自动备份、失败回滚),重启生效。以 `link:` 挂载时隐藏该按钮,改为提示 `git pull`,绝不改写 git 管理的文件。
|
|
73
|
+
|
|
74
|
+
## 使用速查
|
|
75
|
+
|
|
76
|
+
| 操作 | 说明 |
|
|
77
|
+
| --- | --- |
|
|
78
|
+
| 会话页「Git 图谱」标签 | 打开当前会话工作区的仓库 |
|
|
79
|
+
| 顶部仓库下拉 | 切换仓库,左侧小字显示完整路径 |
|
|
80
|
+
| 分支组标题 | 点击折叠 / 展开该分支 |
|
|
81
|
+
| 「分支过滤」(顶栏中部) | 勾选 = 显示,不勾 = 完全隐藏 |
|
|
82
|
+
| 「日期」(顶栏中部) | 应用内日历:点一天写「从」,再点一天写「到」,区间高亮;「从 / 到」标签可点,决定日历写入哪一端;近 7 / 30 / 90 天与近一年预设、「今天」、年月跳转;只填一端 = 单侧边界,起止选反自动交换 |
|
|
83
|
+
| 搜索框(顶栏中部) | 按消息 / 作者 / 哈希 / 邮箱过滤 |
|
|
84
|
+
| 图谱顶部「未提交改动」区块 | 见上方「改工作区」;点击状态栏的改动计数可滚回该区块 |
|
|
85
|
+
| 提交行 | 点击查看详情 |
|
|
86
|
+
| 提交行右键 | 复制 / 打标签 / 建分支 / 打开 GitHub / 打开文件夹 |
|
|
87
|
+
| 提交详情里的 📜 | 查看该文件的历史提交 |
|
|
88
|
+
| 详情面板左侧分界线 | 拖动调整宽度;双击恢复默认(最小 260px) |
|
|
89
|
+
| 顶栏图标 | 打开文件夹 / 拉取 / 推送 / 刷新 |
|
|
90
|
+
| ⚙ 设置(最右) | 视图、主题、快捷键 |
|
|
91
|
+
|
|
92
|
+
**快捷键**:`Ctrl+F` 搜索 · `Ctrl+/` 快捷键面板 · `Ctrl+B` 折叠 / 展开全部分支组 · `↑` `↓` / `j` `k` 切换提交 · `Enter` 重开当前详情 · `Esc` 关闭面板。
|
|
93
|
+
|
|
94
|
+
## 开发
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
dsh-git-graph/
|
|
98
|
+
├── index.js # 服务端(Host 半):/git-graph 前缀路由 + git API
|
|
99
|
+
├── client.js # 客户端(浏览器半):注册 conversation.view 标签
|
|
100
|
+
├── web/index.html # 图谱页面骨架(iframe 独立页,只含 markup)
|
|
101
|
+
├── web/app.css # 页面样式(外部样式表)
|
|
102
|
+
├── web/app.js # 页面逻辑(外部脚本)
|
|
103
|
+
├── package.json # 插件清单(dsh.client + dsh.bundle.patch + engines.dsh)
|
|
104
|
+
├── cordis.patch.yml # profile 挂载点
|
|
105
|
+
├── scripts/ # check-compat.mjs / publish.mjs / compat-isolated-test.ps1
|
|
106
|
+
└── docs/ # 兼容性与安全审计证据
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# 首次挂载(此后改代码无需重复)
|
|
111
|
+
dsh plugin --profile web add link:<本仓库路径>
|
|
112
|
+
|
|
113
|
+
# 改动后
|
|
114
|
+
node --check index.js client.js && node --check web/app.js
|
|
115
|
+
# index.js / client.js 改动需重启 dsh web;web/ 下三个文件刷新即生效
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
发版流程:`npm run check:compat` → `pwsh -File scripts/compat-isolated-test.ps1`(锚点版本隔离实测)→ 版本号 +1 → `git commit` → `git tag vX.Y` → `git push --follow-tags` → `npm run publish:npm`。完整约定见 [AGENTS.md](AGENTS.md)。
|
|
119
|
+
|
|
120
|
+
## 兼容与安全
|
|
121
|
+
|
|
122
|
+
- **兼容范围**:`engines.dsh` 与 `peerDependencies["@deepseek-ai/dsh"]` 均为 `>=0.1.0-rc.6 <0.3.0`。隔离实测(独立 `DSH_HOME`,add → dump-config → remove 全链路)通过 **0.1.7-rc.2**(latest)与 **0.2.0-rc.1**(next),证据见 [docs/compatibility.md](docs/compatibility.md)。
|
|
123
|
+
- **默认只读**:服务端一律用 `execFile` + 固定参数数组调用 git,从不经 shell;文件路径做 `resolve` + 前缀校验防穿越;长输出截断。
|
|
124
|
+
- **写操作必须 POST**,并校验 Origin / Referer 同源;页面带严格 CSP(`script-src 'self'`、`style-src 'self'`,无任何内联许可)。
|
|
125
|
+
- **权限与来源**:只在你授权的目录内执行 git,网络仅用于自更新与 `fetch`/`pull`/`push`,无生命周期脚本、不触碰 DSH 核心。
|
|
126
|
+
|
|
127
|
+
## 发布渠道
|
|
128
|
+
|
|
129
|
+
- **GitHub**:本仓库带 `dsh-plugin` topic,`dsh plugin add github:…` 直装。
|
|
130
|
+
- **npm**:[`@shiqyka/dsh-git-graph`](https://www.npmjs.com/package/@shiqyka/dsh-git-graph)。
|
|
131
|
+
包名必须带 scope:npm 上不带 scope 的 `dsh-git-graph` 属于另一个项目,本插件无法沿用。
|
|
132
|
+
|
|
133
|
+
## 开源协议
|
|
134
|
+
|
|
135
|
+
[MIT](./LICENSE)
|
|
136
|
+
|
|
137
|
+
## 致谢
|
|
138
|
+
|
|
139
|
+
- [DeepSeek Harness](https://github.com/deepseek-ai/) —— 插件运行平台
|
|
140
|
+
- [quansheng](https://github.com/1841220388zzzcccxxx-star) —— 本项目原作者,v0.22.0 之前的全部代码与文档均由他完成;本仓库是他的 [dsh-git-graph](https://github.com/1841220388zzzcccxxx-star/dsh-git-graph) 的 fork
|
package/README_EN.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# dsh-git-graph
|
|
2
|
+
|
|
3
|
+
**Ready-to-use git visualization inside DSH.** Commit history graph, branch management, diffs and working-tree changes, embedded in the DeepSeek Harness conversation pane — no switching to another git client while you work with AI.
|
|
4
|
+
|
|
5
|
+
[中文](./README.md) · [English](./README_EN.md) · 
|
|
6
|
+
|
|
7
|
+
<img src="assets/git-graph-demo.png" alt="Git graph" width="760">
|
|
8
|
+
|
|
9
|
+
## Why it exists
|
|
10
|
+
|
|
11
|
+
- **Never leave the session**: the graph is a tab next to the trajectory tab. Switch workspaces and the graph follows to that repo automatically.
|
|
12
|
+
- **No waiting**: the first screen paints 50 commits and pulls more as you scroll. The branch list and the ref probe in the auto-refresh tick read ref files under `.git` directly — **no git process at all**. On machines where real-time AV makes each `git` launch cost hundreds of milliseconds, this is what "reading history feels fast" comes down to.
|
|
13
|
+
- **Not read-only**: stage, commit, restore, tag, switch branches, fetch and push from the page. Destructive actions always ask first.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# From GitHub
|
|
19
|
+
dsh plugin --profile web add github:siqyka/dsh-git-graph
|
|
20
|
+
|
|
21
|
+
# Or from npm
|
|
22
|
+
dsh plugin --profile web add @shiqyka/dsh-git-graph
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Restart `dsh web`** afterwards, open the address it prints, then pick the **Git 图谱** tab in any session (next to the trajectory tab).
|
|
26
|
+
|
|
27
|
+
**Developers / offline**: `dsh plugin --profile web add link:<path to this repo>` mounts the directory directly — edit code, restart `dsh web`, no file copying.
|
|
28
|
+
|
|
29
|
+
### Optional: fixed repo allowlist
|
|
30
|
+
|
|
31
|
+
**No configuration is required.** The graph discovers git repos in the current session workspace, and repos added through "Open folder" are remembered. To pin an allowlist, add `config` to the plugin row in your profile's `cordis.patch.yml`:
|
|
32
|
+
|
|
33
|
+
```yaml
|
|
34
|
+
- insert:
|
|
35
|
+
- id: git-graph
|
|
36
|
+
name: '@shiqyka/dsh-git-graph'
|
|
37
|
+
config:
|
|
38
|
+
repo: "C:/path/to/your/repo" # or repos: [ ... ]
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Features
|
|
42
|
+
|
|
43
|
+
### 📜 Reading history
|
|
44
|
+
|
|
45
|
+
- **Commit graph**: GitHub-style list with local and remote branches grouped and colour-coded separately; group headers fold on click.
|
|
46
|
+
- **Lane graph**: in flat mode the left gutter draws real fork and merge curves using the same "reserved point" layout as VS Code Git Graph. Grouped mode draws none — group headers would break the lanes.
|
|
47
|
+
- **Commit details**: changed files, per-file diffs, full patch, and 📜 file history for any single file. The detail panel resizes by dragging, double-click resets, and the width is remembered.
|
|
48
|
+
- **Three filters**: branch (unchecked = fully hidden), date range (in-app calendar, either end may be empty), and search across message / author / hash / email. Empty results offer a "show all branches" or "clear filters" way out.
|
|
49
|
+
- **Keyboard navigation**: `↑` `↓` / `j` `k` step through commits and open each detail. The mouse and the arrows share **one cursor** — click row 6, press `↓`, land on row 7.
|
|
50
|
+
|
|
51
|
+
### 📝 Working tree
|
|
52
|
+
|
|
53
|
+
- **Uncommitted changes** sit permanently at the top of the graph: staged / changes / untracked groups, status badges `A/M/D/R/U/?` and per-file `+/−` counts.
|
|
54
|
+
- Click a row to expand its diff (syntax highlighted); renames show `new ← old` and untracked files show their contents. The ☑ groups menu hides any group.
|
|
55
|
+
- Per-row **stage / unstage / restore**; top-bar **stage all / commit**; checkboxes for batch **stage / unstage / restore / ignore / commit selected** (commits only the selected files, leaving the rest alone).
|
|
56
|
+
- The commit dialog offers **✨ AI-generate a commit message**: heuristic candidates from the diff stats, editable. No external AI call.
|
|
57
|
+
- Past 10 files the list scrolls internally, keeping the top-bar buttons and the batch bar pinned.
|
|
58
|
+
|
|
59
|
+
### 🌿 Branches
|
|
60
|
+
|
|
61
|
+
- **Top-bar icons**: open folder / fetch (`fetch --all --prune`) / push current branch / refresh.
|
|
62
|
+
- **Branch group right-click**: local branches switch / push / delete (`-d` refuses unmerged, HEAD protected); remote branches fetch / copy name. Remote group headers always render, labelled "synced" or "contained".
|
|
63
|
+
- **Commit row right-click**: copy hash / message, tag (rename, delete), create a branch from this commit, open the GitHub commit page, copy repo path, reveal in file manager.
|
|
64
|
+
- **Multiple repos**: "Open folder" browses the disk to add any repo, remembers it, and the top dropdown switches between them.
|
|
65
|
+
|
|
66
|
+
### 🎨 Living with it
|
|
67
|
+
|
|
68
|
+
- **Themes**: auto / dark / light plus 8 style presets (🌸 sakura · 🌊 ocean · 🌲 forest · 🌙 night · 🍬 candy · 💼 business · ✨ starry · 🤖 tech), each with its own animated background.
|
|
69
|
+
- **⚙ Settings** (gear, second-level page): view (grouped / flat), theme (a grid of colour chips), and a shortcut-panel entry. A small dot on the gear marks any non-default choice.
|
|
70
|
+
- **State memory**: filters, fold states, theme and date range persist to `.state/prefs.json` next to the plugin — surviving a port change or a `dsh web` restart (localStorage is origin-scoped and silently resets when the port moves).
|
|
71
|
+
- **Auto refresh**: while visible, a 5-second probe updates the stats and list; workspace changes are followed every 3 seconds.
|
|
72
|
+
- **Auto-update**: silently checks the latest GitHub tag and swaps the files in one click (backup first, automatic rollback on failure), applied on restart. When mounted via `link:` the button hides and suggests `git pull` instead — files owned by git are never rewritten.
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
| Action | Description |
|
|
77
|
+
| --- | --- |
|
|
78
|
+
| "Git 图谱" tab in a session | Open the graph for the current session's workspace |
|
|
79
|
+
| Repo dropdown at the top | Switch repositories; the label to its left shows the full path |
|
|
80
|
+
| Branch group header | Click to fold / unfold that branch |
|
|
81
|
+
| "分支过滤" (top bar, centre) | Checked = visible, unchecked = fully hidden |
|
|
82
|
+
| "日期" (top bar, centre) | In-app calendar: click a day to set the start, another for the end, with the span tinted. The 从 / 到 chips are clickable and decide which end the calendar writes to. Presets for 7 / 30 / 90 days and a year, plus 今天 and year/month stepping. One end alone is a single-sided limit; a reversed range is swapped silently |
|
|
83
|
+
| Search box (top bar, centre) | Filter by message / author / hash / email |
|
|
84
|
+
| "未提交改动" block at the top of the graph | See "Working tree" above; clicking the change count in the status line scrolls back to it |
|
|
85
|
+
| Commit row | Click for details |
|
|
86
|
+
| Commit row right-click | Copy / tag / branch / open GitHub / open folder |
|
|
87
|
+
| 📜 in the commit details | File history for that path |
|
|
88
|
+
| Splitter left of the detail panel | Drag to resize; double-click to reset (min 260px) |
|
|
89
|
+
| Top-bar icons | Open folder / fetch / push / refresh |
|
|
90
|
+
| ⚙ Settings (far right) | View, theme, shortcuts |
|
|
91
|
+
|
|
92
|
+
**Shortcuts**: `Ctrl+F` search · `Ctrl+/` shortcut panel · `Ctrl+B` fold / unfold all branch groups · `↑` `↓` / `j` `k` step through commits · `Enter` reopen the current detail · `Esc` close panels.
|
|
93
|
+
|
|
94
|
+
## Development
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
dsh-git-graph/
|
|
98
|
+
├── index.js # Server half: /git-graph prefix routes + git API
|
|
99
|
+
├── client.js # Client half: registers the conversation.view tab
|
|
100
|
+
├── web/index.html # Page shell (standalone page inside an iframe, markup only)
|
|
101
|
+
├── web/app.css # Page styles (external stylesheet)
|
|
102
|
+
├── web/app.js # Page logic (external script)
|
|
103
|
+
├── package.json # Plugin manifest (dsh.client + dsh.bundle.patch + engines.dsh)
|
|
104
|
+
├── cordis.patch.yml # Profile mount point
|
|
105
|
+
├── scripts/ # check-compat.mjs / publish.mjs / compat-isolated-test.ps1
|
|
106
|
+
└── docs/ # Compatibility and security-audit evidence
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# One-time mount (no need to repeat after code changes)
|
|
111
|
+
dsh plugin --profile web add link:<path to this repository>
|
|
112
|
+
|
|
113
|
+
# After editing
|
|
114
|
+
node --check index.js client.js && node --check web/app.js
|
|
115
|
+
# index.js / client.js changes need a dsh web restart; the three web/ files only need a refresh
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Release flow: `npm run check:compat` → `pwsh -File scripts/compat-isolated-test.ps1` (isolated tests on anchor versions) → bump version → `git commit` → `git tag vX.Y` → `git push --follow-tags` → `npm run publish:npm`. Full conventions live in [AGENTS.md](AGENTS.md).
|
|
119
|
+
|
|
120
|
+
## Compatibility & security
|
|
121
|
+
|
|
122
|
+
- **Compatibility range**: both `engines.dsh` and `peerDependencies["@deepseek-ai/dsh"]` are `>=0.1.0-rc.6 <0.3.0`. Isolated tests (separate `DSH_HOME`, full add → dump-config → remove cycle) pass on **0.1.7-rc.2** (latest) and **0.2.0-rc.1** (next); evidence in [docs/compatibility.md](docs/compatibility.md).
|
|
123
|
+
- **Read-only by default**: git is always invoked through `execFile` with fixed argument arrays, never a shell; file paths are `resolve`d and prefix-checked against traversal; long output is truncated.
|
|
124
|
+
- **Write operations must be POST** and are validated for same-origin Origin / Referer. The page ships a strict CSP (`script-src 'self'`, `style-src 'self'`, no inline allowance at all).
|
|
125
|
+
- **Permissions & provenance**: git runs only inside directories you authorize; network access is limited to self-update and `fetch`/`pull`/`push`; no lifecycle scripts, and DSH core is never touched.
|
|
126
|
+
|
|
127
|
+
## Distribution
|
|
128
|
+
|
|
129
|
+
- **GitHub**: this repository carries the `dsh-plugin` topic, so `dsh plugin add github:…` installs directly.
|
|
130
|
+
- **npm**: [`@shiqyka/dsh-git-graph`](https://www.npmjs.com/package/@shiqyka/dsh-git-graph).
|
|
131
|
+
The scope is mandatory: the unscoped `dsh-git-graph` name belongs to a different project on npm.
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
[MIT](./LICENSE)
|
|
136
|
+
|
|
137
|
+
## Acknowledgements
|
|
138
|
+
|
|
139
|
+
- [DeepSeek Harness](https://github.com/deepseek-ai/) — the plugin platform
|
|
140
|
+
- [quansheng](https://github.com/1841220388zzzcccxxx-star) — original author of this project; every line of code and documentation before v0.22.0 is his work. This repository is a fork of his [dsh-git-graph](https://github.com/1841220388zzzcccxxx-star/dsh-git-graph)
|
package/client.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "@shiqyka/dsh-git-graph",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let react = require("react");
|
|
8
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
|
+
|
|
10
|
+
//#region styles
|
|
11
|
+
const css = [
|
|
12
|
+
/* frame shared by the conversation view */
|
|
13
|
+
".gg-frame{flex:1;width:100%;border:0;display:block;background:#0d1117;min-height:0}",
|
|
14
|
+
/* conversation view (tab next to 轨迹) */
|
|
15
|
+
".gg-view{height:100%;display:flex;flex-direction:column;background:var(--dsw-alias-bg-base, #0d1117)}",
|
|
16
|
+
".gg-view .gg-frame{flex:1}"
|
|
17
|
+
].join("");
|
|
18
|
+
/* Style ownership keys off the module id: core's claimStyles() looks up
|
|
19
|
+
* `style[data-plugin="<entry id>"]`, so both the id and the lookup key must
|
|
20
|
+
* be the full package name — a bare "dsh-git-graph" would leave this tag
|
|
21
|
+
* unclaimed and it would survive plugin unload / HMR. */
|
|
22
|
+
const tagId = "@shiqyka/dsh-git-graph/style";
|
|
23
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
24
|
+
const tag = document.createElement("style");
|
|
25
|
+
tag.dataset.plugin = "@shiqyka/dsh-git-graph";
|
|
26
|
+
tag.dataset.pluginCss = tagId;
|
|
27
|
+
tag.textContent = css;
|
|
28
|
+
document.head.appendChild(tag);
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
|
|
32
|
+
const graphSrc = (sid) => "/git-graph/index.html" + (sid ? "?sid=" + encodeURIComponent(sid) : "");
|
|
33
|
+
|
|
34
|
+
/** Conversation view tab: the graph embedded in the session pane (next to 轨迹). */
|
|
35
|
+
function GitGraphView(props) {
|
|
36
|
+
const sid = props.sessionId || "";
|
|
37
|
+
return react_jsx_runtime.jsx("div", {
|
|
38
|
+
className: "gg-view",
|
|
39
|
+
children: react_jsx_runtime.jsx("iframe", {
|
|
40
|
+
className: "gg-frame",
|
|
41
|
+
src: graphSrc(sid),
|
|
42
|
+
title: "Git 图谱"
|
|
43
|
+
})
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Required service: the slot registry. */
|
|
48
|
+
const inject = ["slots"];
|
|
49
|
+
|
|
50
|
+
/** Client plugin body: the "Git 图谱" conversation tab only. */
|
|
51
|
+
function apply(ctx) {
|
|
52
|
+
ctx.slots.inject("conversation.view", () => ctx.slots.register({
|
|
53
|
+
name: "conversation.view",
|
|
54
|
+
id: "git-graph",
|
|
55
|
+
order: 20,
|
|
56
|
+
label: () => "Git 图谱"
|
|
57
|
+
}, GitGraphView));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
exports.apply = apply;
|
|
61
|
+
exports.inject = inject;
|
|
62
|
+
return module.exports;
|
|
63
|
+
}
|
|
64
|
+
});
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# dsh bundle layer: mount the git-graph plugin (server half: index.js;
|
|
2
|
+
# client half: client.js served by dsh-client-modules under /plugins).
|
|
3
|
+
#
|
|
4
|
+
# 仓库白名单(可选):不配置时插件仍可用 —— 会话工作区自动发现 +
|
|
5
|
+
# 图谱页面「📂 打开文件夹」添加的仓库都可直接访问。
|
|
6
|
+
# 如需固定白名单,取消注释并改成你自己的仓库路径:
|
|
7
|
+
#
|
|
8
|
+
# config:
|
|
9
|
+
# repo: "C:/path/to/your/repo" # 单个仓库
|
|
10
|
+
# # repos: # 或多个仓库
|
|
11
|
+
# # - "C:/path/to/repo-a"
|
|
12
|
+
# # - "C:/path/to/repo-b"
|
|
13
|
+
#
|
|
14
|
+
# `name` MUST be the full npm package name (scoped). The loader resolves the row
|
|
15
|
+
# through Node (`exactPackageSpecifier` + require.resolve) to locate the package
|
|
16
|
+
# manifest, and only then reads `dsh.client` to bring in the browser half. A bare
|
|
17
|
+
# "dsh-git-graph" resolves to nothing here — the published package is scoped — so
|
|
18
|
+
# the row never mounts and the tab silently never appears.
|
|
19
|
+
- insert:
|
|
20
|
+
- id: git-graph
|
|
21
|
+
name: '@shiqyka/dsh-git-graph'
|