source-code-mgmt 1.8.0 → 1.10.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/README.en.md ADDED
@@ -0,0 +1,219 @@
1
+ # source-code-mgmt — DSH Source Code Management Plugin
2
+
3
+ > Version: **v1.10.1** | 中文版见 [README.md](README.md)
4
+
5
+ > A source-code management plugin for the DSH Web GUI: it bundles「environment check → SSH setup → commit/push/upload code」into one「Code Management」panel with GitHub / Gitee dual-platform support.
6
+
7
+ > **Bilingual UI, live**: the panel and host-side messages follow DSH's language setting (Settings → General → Language) — switching between 中文 and English takes effect instantly, no refresh or restart needed.
8
+
9
+ > The entry point adapts automatically: when [dsh-better-sidebar](https://github.com/omdsh-dev/DSH-better-sidebar) is installed,「Code Management」appears as a new sidebar **Tab** of that sidebar; otherwise a「Code Management」button is registered in the **right-aligned header list beside "Session log"** (same pill style, 8px gap), opening a right-side integrated panel that pushes the main content. Both forms share the same panel UI and no longer use a left-rail bottom button.
10
+
11
+ > **UI language:** the panel follows DSH's language setting (Settings → General → Language), live — Chinese (中文) or English, including all host-side messages. No restart needed when you switch.
12
+
13
+ ## Features
14
+
15
+ Entry points (auto-detected, no manual switching):
16
+
17
+ - **dsh-better-sidebar installed:**「Code Management」registers as a new **Tab page** of its sidebar;
18
+ - **dsh-better-sidebar not installed:** a「Code Management」button in the **right-aligned header list beside "Session log"** (registered through DSH's `conversation.session.header.utilities` slot), opening a right-side integrated panel that pushes the main content left.
19
+
20
+ > Detection is a single in-memory read at activation time (`ctx.get('betterSidebar')`) — zero I/O, zero network, no impact on DSH startup.
21
+
22
+ The panel has three steps:
23
+
24
+ ### ① Environment Check
25
+ - Shows the **OS** (friendly names `Windows` / `macOS` / `Linux`, from the underlying `win32` / `darwin` / `linux` platform ids)
26
+ - Detects **Git** and **GitHub CLI** presence and versions (e.g. `git version 2.55.0`, `gh version 2.97.0`)
27
+ - Detects whether an **SSH** client is available
28
+ - **Missing tools → install guidance + one-click install**: when a tool is missing, the row shows「❌ 未安装」+「复制安装命令」(copy install command) +「安装」(install) — install picks the package manager automatically (winget / built-in features on Windows, brew on macOS, apt/dnf/pacman on Linux, may need admin rights) and re-detects afterwards
29
+
30
+ ### ② SSH Key & Connectivity
31
+ - **Platform selector**: GitHub (default) / Gitee — decides the SSH config target and connectivity test below
32
+ - **Auto-detect ed25519 key**: scans `~/.ssh/*.pub` for existing ed25519 public keys — prefers `id_ed25519`, otherwise the first found (any name, e.g. `github_ed25519`); falls back to `id_ed25519` when none exist. The status line shows the actual key filename, and the SSH config `IdentityFile` uses it too
33
+ - One-click **generate ed25519 key** (no passphrase; reuses an existing ed25519 key instead of duplicating)
34
+ - One-click **write SSH config** (GitHub: `github.com → ssh.github.com:443`; Gitee: `gitee.com` port 443) — see [Do I need the 443 config?](#do-i-need-the-443-config) below
35
+ - **Test connection** `ssh -T git@github.com` (GitHub) or `ssh -T git@gitee.com` (Gitee)
36
+ - Shows the public key content for easy copy-upload to the platform
37
+ - Detects whether `gh` is logged in and which account
38
+
39
+ ### ③ Code Management
40
+ - **Follows ②'s platform**: all「detect / create / visibility」logic switches with the platform selector (GitHub via `gh` CLI, Gitee via Gitee OpenAPI)
41
+ - **Gitee token** (Gitee mode only): enter a Gitee personal access token (needs `projects` permission) → stored at `~/.dsh/storages/source-code-mgmt-gitee.json` on the machine (0600, **not inside the plugin dir**, never echoed to the browser/logs); one-click clear; invalid tokens are removed automatically
42
+ - **Workspace selector**: dropdown of DSH-registered workspace folders
43
+ - **Select folder →**: paste an absolute path or click「Browse…」for a native folder picker; confirmed folders are **persisted into a custom folder list** (`~/.dsh/storages/source-code-mgmt-dirs.json`, separate from the plugin dir — no personal paths leak), shown with a custom-folder badge and a ✕ to remove the entry (record only, never deletes the actual folder)
44
+ - Shows repo status: platform source, branch, remote, pending change count, ahead/behind remote, >100MB files
45
+ - **View details**: when there are changes, a「查看」(view) button opens a dialog listing changed/added/deleted/renamed **files or folders**; tracked changes can be expanded to show an inline **side-by-side diff** (old left / new right, deletions red, additions green); untracked files are listed by name only. When local and remote diverge, a view button on the sync row lists the concrete commits you're ahead/behind
46
+ - **Local Git workflow** (does not change the remote-sync logic):
47
+ - **Stage / unstage** per file in the changes dialog (distinguishing staged/unstaged by `git status` XY codes), with「已暂存 / 未暂存」markers
48
+ - **Commit message input + Commit button** above the repo name (git repos with changes only) — custom message, or auto-generated when left empty
49
+ - **Branch「Switch」** button — dialog listing branches, click to `checkout`
50
+ - **History button** — dialog listing commits (hash + subject + author + date), each with view (side-by-side diff), **revert**, **cherry-pick** (both with confirmation, as they rewrite history)
51
+ - **Remote matching by platform + current account**: ③'s「remote / sync」only counts remotes of the current platform **whose owner equals the currently logged-in account** (GitHub platform = `gh` account, Gitee platform = Gitee token account). So switching to Gitee never reads the GitHub origin; someone else's / another org's repos (e.g. `deepseek-ai/deepseek-harness`) are never treated as "your own remote", and ahead/behind is not computed for them. With no account-owned remote, the panel shows「(无)」and offers the same-name repo check + create-and-push flow
52
+ - **Init Git**: shown when the folder is **not** a git repo but a same-name repo already exists remotely — runs `git init` only (+ default identity), **no pull, no push**, you choose the next step
53
+ - **Create repo & push**: repo name defaults to the **folder name** (read-only), optional private/public; the button is disabled with a hint when a same-name repo already exists. For a brand-new directory with no commits, it auto-stages an initial commit before creating the repo to avoid "no commits found"
54
+ - GitHub: `gh repo create --private|--public --source=. --push`
55
+ - Gitee: Gitee OpenAPI `POST /user/repos` to create, then sets the SSH remote `git@gitee.com:<owner>/<name>.git` and `git push` (through ②'s SSH key)
56
+
57
+ ### Data loading timing (fetch on open, "refreshing…" indicator)
58
+ DSH does **not** sync repos on startup — it only prefetches static env/SSH/workspace lists. Opening the plugin, switching workspace/folder, refreshing, and any push/pull/stage/commit operation fetch the latest repo status over the network and show a「⟳ 刷新中…」indicator — no stale data (like an old "no changes") when opening/reopening/switching.
59
+
60
+ ## Do I need the 443 config?
61
+
62
+ Short answer for users outside mainland China / port-22-blocked networks: **usually no.**
63
+
64
+ - GitHub's standard SSH endpoint is `git@github.com` on **port 22**, and it works out of the box on almost every network outside mainland China.
65
+ - The plugin's「write SSH config」step writes GitHub's **officially supported** port-443 fallback (`Host github.com → HostName ssh.github.com, Port 443`). It exists for networks that block port 22 (common in mainland China, plus some corporate/school/campus or otherwise firewalled networks).
66
+ - The step is **fully optional and user-initiated** — you can simply skip it: generate the key → add the public key to GitHub → test connection → push. Everything runs over port 22.
67
+ - Writing it anyway is harmless (GitHub officially supports SSH over 443; the only edge case is networks that block 443 as well). Gitee is a China-hosted platform, so it's only relevant if you actually use Gitee.
68
+
69
+ ## Installation
70
+
71
+ > This plugin ships as a **Profile Bundle**: its `package.json` declares `dsh.bundle` (carrying a `cordis.patch.yml` config layer), so `dsh plugin --profile web add` **installs and activates it in one step** — no manual config editing.
72
+
73
+ ### Option 1: npm package (recommended)
74
+
75
+ Run this from **any directory** (the command locates/initializes the `web` profile itself):
76
+
77
+ ```bash
78
+ dsh plugin --profile web add source-code-mgmt
79
+ ```
80
+
81
+ > The command runs `pnpm add` in the web profile directory, then reconciles the plugin layer: because this package declares `dsh.bundle`, it is automatically appended to `dsh.profile.bundles` (see `~/.dsh/profiles/web/package.json`) and registered into the Cordis loader tree — **one command, done**.
82
+
83
+ After installing, **fully restart dsh web** (stop the old process — not a page refresh), then **F5** in the browser. The「Code Management」entry appears (sidebar Tab with dsh-better-sidebar, otherwise the header button + right panel).
84
+
85
+ ### Option 2: local directory (development / testing)
86
+
87
+ **Windows (PowerShell):**
88
+ ```powershell
89
+ # install local source (link: protocol — a symlink, source edits take effect immediately)
90
+ dsh plugin --profile web add link:C:/path/to/source-code-mgmt
91
+ dsh web
92
+ ```
93
+
94
+ **Linux / macOS:**
95
+ ```bash
96
+ dsh plugin --profile web add link:/home/yourname/path/to/source-code-mgmt
97
+ dsh web
98
+ ```
99
+
100
+ ### Option 3: from GitHub (distribution)
101
+
102
+ ```bash
103
+ dsh plugin --profile web add git+https://github.com/Zhucy123/source-code-mgmt.git
104
+ dsh web
105
+ ```
106
+
107
+ > A git install **copies** the source into node_modules — to pick up source changes, re-run `dsh plugin --profile web add ...` (unlike `link:`, which is a symlink).
108
+
109
+ ### Verifying the install
110
+
111
+ After installing and restarting:
112
+
113
+ 1. **Dependency written**: `source-code-mgmt` is in `dependencies` of `~/.dsh/profiles/web/package.json`.
114
+ 2. **Added to the config layer**: `source-code-mgmt` is in the `dsh.profile.bundles` list of the same file (written automatically by `dsh plugin add` — no manual editing).
115
+ 3. **Symlink created (`link:` only)**: `~/.dsh/profiles/web/node_modules/source-code-mgmt` points at your source dir (a Junction on Windows).
116
+ 4. **Entry visible after restart**: sidebar「Code Management」Tab with dsh-better-sidebar, otherwise the header button beside "Session log" opening the right panel.
117
+
118
+ ### Troubleshooting
119
+
120
+ | Symptom | Cause / fix |
121
+ |---------|-------------|
122
+ | Installed with `dsh plugin add` and restarted, but no button | Most common: the process was **refreshed, not fully restarted**. Stop the old `dsh web` process (it may still hold port 3080) and start it again. |
123
+ | Install prints「declares no dsh.bundle」 | The installed version lacks the bundle declaration (old version or a package missing `cordis.patch.yml`). Reinstall/update with version ≥ 1.9.0. |
124
+ |「Failed to load plugins」 | The host-side `lib/index.js` failed to boot (usually a dependency resolution issue). Check the startup log and confirm `node_modules` dependencies are complete. |
125
+
126
+ ## Usage
127
+
128
+ 1. Restart dsh web and refresh the browser.
129
+ 2. Click the「**Code Management**」entry (sidebar Tab with dsh-better-sidebar, otherwise the header button beside "Session log").
130
+ 3. ① Confirm Git / GitHub CLI are installed → ② generate a key and test connectivity → ③ pick a workspace, then push or create a new repo.
131
+
132
+ ## Backend API routes
133
+
134
+ | Route | Method | Description |
135
+ |-------|--------|-------------|
136
+ | `/api/source-code-mgmt/env` | GET | Environment check (git/gh versions) |
137
+ | `/api/source-code-mgmt/install-tool` | POST | One-click install of a missing tool (body `tool`: `git`/`gh`/`ssh`, package manager picked per platform) |
138
+ | `/api/source-code-mgmt/ssh` | GET | SSH key / config / gh login status |
139
+ | `/api/source-code-mgmt/gen-key` | POST | Generate an ed25519 key |
140
+ | `/api/source-code-mgmt/write-config` | POST | Write SSH config (body `provider`: `github` default / `gitee`) |
141
+ | `/api/source-code-mgmt/ssh-test` | POST | Test SSH connectivity (body `provider`: `github` default / `gitee`) |
142
+ | `/api/source-code-mgmt/default-dir` | GET | Current workspace folder |
143
+ | `/api/source-code-mgmt/workspaces` | GET | List all workspace folders + custom folder set |
144
+ | `/api/source-code-mgmt/pick-dir` | POST | Native folder picker on the host; returns the chosen path |
145
+ | `/api/source-code-mgmt/add-workspace` | POST | Validate a folder and persist it to the custom list; returns the merged workspace list |
146
+ | `/api/source-code-mgmt/remove-workspace` | POST | Remove a custom-folder dropdown record only (never deletes the folder) |
147
+ | `/api/source-code-mgmt/align` | POST | Hard align: `git fetch` + `git reset --hard origin/<branch>` (full reset to remote) |
148
+ | `/api/source-code-mgmt/init-git` | POST | `git init` + default identity only — no pull/push |
149
+ | `/api/source-code-mgmt/repo-exists` | POST | Check whether a same-name repo exists (body `provider`: `github`/`gitee`) |
150
+ | `/api/source-code-mgmt/repo?dir=` | GET | Repo status (query `provider`: `github`/`gitee`) |
151
+ | `/api/source-code-mgmt/repo-diff?dir=&path=` | GET | Unified diff text for one changed file, on demand |
152
+ | `/api/source-code-mgmt/stage` | POST | Stage changes (body `dir`, `path`; empty `path` = all) |
153
+ | `/api/source-code-mgmt/unstage` | POST | Unstage changes (body `dir`, `path`; empty `path` = all) |
154
+ | `/api/source-code-mgmt/commit` | POST | Commit with a custom message (body `dir`, `message`, `paths?`) |
155
+ | `/api/source-code-mgmt/branches` | POST | List branches (current first) |
156
+ | `/api/source-code-mgmt/checkout` | POST | Switch branch (body `dir`, `branch`) |
157
+ | `/api/source-code-mgmt/log` | POST | Recent commit history (body `dir`, `count?`; returns hash/subject/author/date) |
158
+ | `/api/source-code-mgmt/revert` | POST | Revert a commit (body `dir`, `hash`) |
159
+ | `/api/source-code-mgmt/cherrypick` | POST | Cherry-pick a commit (body `dir`, `hash`) |
160
+ | `/api/source-code-mgmt/commit-diff` | POST | Full patch of a commit (body `dir`, `hash`) |
161
+ | `/api/source-code-mgmt/push` | POST | Commit and push (git operation, platform-agnostic) |
162
+ | `/api/source-code-mgmt/push-staged` | POST | Commit only staged content with your message, then push |
163
+ | `/api/source-code-mgmt/pull` | POST | `git pull --ff-only` (up-to-date / success / conflict feedback) |
164
+ | `/api/source-code-mgmt/merge-push` | POST | Pull and push (`git pull --rebase` + `git push`) |
165
+ | `/api/source-code-mgmt/force-push` | POST | Force push (`git push --force`) |
166
+ | `/api/source-code-mgmt/force-pull` | POST | Force pull (`git pull --force`) |
167
+ | `/api/source-code-mgmt/create` | POST | Create a repo and push (body `provider`; GitHub via `gh repo create`, Gitee via OpenAPI + SSH push) |
168
+ | `/api/source-code-mgmt/set-visibility` | POST | Change repo visibility (body `provider`; GitHub via `gh repo edit`, Gitee via `PATCH /repos/{owner}/{repo}`) |
169
+ | `/api/source-code-mgmt/gitee-token` | GET/POST | GET: token configured? + account; POST: save (`{token}`) or clear (`{clear:true}`) the Gitee token |
170
+
171
+ ## Security
172
+
173
+ All routes are **loopback-only** (`sec-fetch-site` + Origin checks) — only the local machine's browser can call them; LAN/mobile sources get a 403, same policy as the control panel.
174
+
175
+ ## Cross-platform
176
+
177
+ - **Windows / Linux / macOS**
178
+ - Platform detected via `process.platform`; `~/.ssh` resolved via `homedir()` (Windows: `C:\Users\<user>\.ssh`, Linux/macOS: `/home/<user>/.ssh` or `/Users/<user>/.ssh`)
179
+ - SSH config gets 0600 permissions on Linux/macOS
180
+ - **Automatic git / gh / ssh / ssh-keygen binary resolution** at startup: ① env overrides → ② PATH lookup (`.exe` added on Windows) → ③ (Windows only) Git's bundled dirs (`usr\bin` / `bin`), with the bare command name as a last resort. Git alone is enough even when `ssh` isn't on PATH — no per-machine config
181
+ - Optional explicit binary paths via env vars: `DSH_SCM_GIT` / `DSH_SCM_GH` / `DSH_SCM_SSH` / `DSH_SCM_SSH_KEYGEN`
182
+ - **SSH transport fix**: Git for Windows' bundled MSYS `ssh.exe` (`usr\bin\ssh.exe`) can fail with `couldn't create signal pipe, Win32 error 5` when spawned from a detached/agent process, breaking `git push`/`git pull`. The plugin injects `GIT_SSH` pointing at a working `ssh` (usually the system OpenSSH `C:\Windows\System32\OpenSSH\ssh.exe`) for git remote operations
183
+ - **One-click missing-tool install across platforms**: winget / built-in features (fallback choco/scoop) on Windows, brew on macOS, apt-get / dnf / pacman on Linux (auto `sudo -n`; skipped when already root). The native folder picker is Windows-only; on macOS/Linux paste the path into the input box instead
184
+
185
+ ## Development
186
+
187
+ ```bash
188
+ git clone https://github.com/Zhucy123/source-code-mgmt.git
189
+ cd source-code-mgmt
190
+ # test in your local DSH (installs to the web profile, auto-activated)
191
+ dsh plugin --profile web add link:$(pwd)
192
+ ```
193
+
194
+ - Changes to `lib/client.js` (browser side) → a page refresh is enough
195
+ - Changes to `lib/index.js` (host/Node side) → restart dsh web
196
+
197
+ ## Version history
198
+
199
+ ### v1.10.1 (current)
200
+ - **Fix: the top-right「代码管理」button lingered even after dsh-better-sidebar was installed.** For the fallback entry (better-sidebar absent) the teardown handler was only wired for the ReactDOM fallback path — the slots path never stored it, so switching to the sidebar-Tab form left the header entry behind. The `slots.inject` disposer is now captured into `entryUnmount`, so switching to a Tab tears the header entry down correctly.
201
+ - **Fix: when better-sidebar is absent, the entry only showed inside a conversation and vanished in the new-conversation / no-conversation empty state.** The old entry lived in `conversation.session.header.utilities` (`scope: 'session'`), and the whole session header is hidden via `hideChrome` in the empty state. It is now **always present at the top-right**: with an active session it sits beside「Session log」(the right-aligned session-header utilities); in the new/no-conversation empty state it becomes a fixed top-right button registered in the always-mounted `shell.overlay` slot (shown only when the session is blank or absent, so it never duplicates the header button).
202
+ - **Fix: on refresh the「代码管理」button overlapped「Session log」.** `captureSessions()` takes ~1.2s to populate the session list, and before that the button wrongly believed there was no session and lit up early. The overlap button now renders nothing until the session list is captured.
203
+ - **Corrected visibility signal:** the fixed button now keys off whether the current session is blank (`sessions.list.getSnapshot().byId[current].blank`) — show only for blank/no-session, hide for an active (non-blank) session — replacing the inaccurate `current === undefined` check.
204
+ - **Robustness:** better-sidebar detection now uses a **bounded multi-tick retry** (fast start then slowing, ~44s, stopping on success and cleared on teardown) instead of a single 1.5s retry, covering slow client cold-start so the Tab-switch race no longer misses.
205
+
206
+ > All changes are client-side (`lib/client.js`); refresh the page to pick them up. Host `/api` routes and the push/ignore logic are untouched.
207
+
208
+ ### v1.10.0 (history)
209
+ - **Bilingual UI, live (follows DSH's language setting)**: every piece of panel copy (steps ①②③, buttons, dialogs, status/result messages, confirm dialogs, the sidebar Tab title) plus host-side error/result messages is now driven by a bilingual dictionary. Language comes from DSH's Settings → General → Language and switches **instantly** — the panel re-renders via a `ctx.locale` subscription (the Tab title follows too), no refresh or restart. The host returns messages per-request based on `?lang=` (AsyncLocalStorage-scoped, so concurrent requests never cross languages). The Chinese UI is byte-identical to v1.9.0; English is a complete translation (including >100MB skip reasons, Gitee token hints, git command fallback messages). The `tools/` directory now holds the i18n extract/apply/test scripts for future maintenance.
210
+
211
+ ### v1.9.0 (history)
212
+ - **Profile Bundle distribution — install = activate**: `dsh.bundle` changed from the bare string `"./lib/index.js"` to the object form `{ "patch": "./cordis.patch.yml" }`, with a new `cordis.patch.yml` (inserts the `source-code-mgmt` row). `dsh plugin --profile web add source-code-mgmt` now appends the package to `dsh.profile.bundles` and registers it into the Cordis loader tree automatically — **no manual `cordis.patch.yml` editing**. The「install ≠ activate」warning and the PowerShell activation script were removed from the README. Behavior is otherwise unchanged (same `lib/index.js` host half + `lib/client.js` browser half).
213
+
214
+ ### v1.8.0 and earlier (history)
215
+ See the full Chinese changelog in [README.md](README.md#版本历史). Highlights of recent releases: push-staged button (v1.8.0), fetch-on-open with refreshing indicator (v1.7.0), header button + right panel when better-sidebar is absent (v1.6.0), one-click missing-tool install (v1.5.0), SSH key auto-detection (v1.4.0), local Git workflow — stage/unstage, custom commit message, branch switch, history with revert/cherry-pick, side-by-side diff (v1.3.0), adaptive entry + Gitee support (v1.1–1.2), first release (v1.0.0).
216
+
217
+ ## License
218
+
219
+ MIT
package/README.md CHANGED
@@ -1,19 +1,23 @@
1
1
  # source-code-mgmt — DSH 源代码管理插件
2
2
 
3
- > 版本:**v1.8.0** | 更新日志见文末「[版本历史](#版本历史)
3
+ > [English](README.en.md) | 中文
4
+
5
+ > 版本:**v1.10.1** | 更新日志见文末「[版本历史](#版本历史)」
6
+
7
+ > **界面语言跟随 DSH 设置实时切换**:面板与 host 端消息自动使用 DSH 的语言(设置 → 通用 → 语言),中文 ↔ 英文即时生效,无需重启。
4
8
 
5
9
  > DSH Web GUI 源代码管理插件:把「环境检查 → SSH 配置 → 代码上传推送」整合进「代码管理」面板,支持 GitHub / Gitee 双平台,一键管理代码仓库。
6
10
 
7
- > 入口位置自适应:**已安装 [dsh-better-sidebar](https://github.com/omdsh-dev/DSH-better-sidebar) 时**,「代码管理」作为它侧边栏的一个新 Tab 页面出现(全新侧边栏 Tab);**未安装时**,「代码管理」按钮出现在 DSH 页面**右上角 Session log 旁边**(同一右对齐列表、同款胶囊样式、间距 8px 不挤在一起),点击后打开一个 **dsh-better-sidebar 外观的右侧集成面板**(推挤主内容区)。两种形态都复用同一套面板 UI,且**不再占用左栏底部按钮**。
11
+ > 入口位置自适应:**已安装 [dsh-better-sidebar](https://github.com/omdsh-dev/DSH-better-sidebar) 时**,「代码管理」作为它侧边栏的一个新 Tab 页面出现(全新侧边栏 Tab);**未安装时**,「代码管理」按钮位于 DSH **右上角、常驻可见**——有会话时放在「Session 日志」旁边的右对齐列表里,无会话空态时改为一个固定在**右上角**的浮动按钮,点击后打开一个 **dsh-better-sidebar 外观的右侧集成面板**(推挤主内容区)。两种形态都复用同一套面板 UI
8
12
 
9
13
  ## 功能
10
14
 
11
15
  集成入口(二选一,自动检测,无需手动切换):
12
16
 
13
17
  - **已安装 dsh-better-sidebar**:「代码管理」注册为它侧边栏的一个**新 Tab 页面**,点击侧边栏 Tab 直接打开面板;
14
- - **未安装 dsh-better-sidebar**:「代码管理」按钮出现在 DSH 页面**右上角 Session log 旁边的右对齐列表**里(通过 DSH 的 `conversation.session.header.utilities` 槽位注册,与 Session log 同款胶囊样式、间距 8px 不挤在一起),点击后打开一个 **dsh-better-sidebar 外观的右侧集成面板**(内容放同一面板),并把主内容区往左推挤。
18
+ - **未安装 dsh-better-sidebar**:「代码管理」按钮常驻在 DSH **右上角**——有活跃(非空白)会话时通过 `conversation.session.header.utilities` 槽位放在「Session 日志」旁(同款胶囊、间距一致);空白(新对话)/无会话空态时通过常驻的 `shell.overlay` 槽注册一个固定在右上角的浮动按钮(仅空白或没有会话时显示,活跃会话时交给 header 内的按钮,避免重复)。点击都打开一个 **dsh-better-sidebar 外观的右侧集成面板**(内容放同一面板),并把主内容区往左推挤。
15
19
 
16
- > 检测只是激活时一次内存读取(`ctx.get('betterSidebar')`),零 I/O、零网络,不影响 DSH 启动速度;两种形态间自动切换,**不再占用左栏底部的按钮**。
20
+ > 检测只是激活时一次内存读取(`ctx.get('betterSidebar')`),零 I/O、零网络,不影响 DSH 启动速度;两种形态间自动切换。未安装 better-sidebar 时入口常驻右上角(有会话=Session 日志旁,空态=固定右上角浮动按钮),空态/新对话也可见。
17
21
 
18
22
  面板分三步:
19
23
 
@@ -32,6 +36,8 @@
32
36
  - 显示公钥内容,方便复制上传到对应平台
33
37
  - 检测 `gh` 是否已登录及账号
34
38
 
39
+ > **海外用户需要 443 吗?——不需要。** 「写 SSH config」是**可选的**(仅在你点按钮时才会写入 `~/.ssh/config`)。GitHub 官方标准端点就是 `git@github.com` 走 **22 端口**,海外正常网络开箱即用,直接跳过该按钮:生成密钥 → 把公钥贴到 GitHub → 测试连接 → 推送,全程 22 端口。443 配置(`Host github.com → HostName ssh.github.com, Port 443`)是 GitHub **官方支持的**端口 22 封锁兜底方案,典型场景是国内网络、部分公司/校园网;写了也无害(仅当 443 也被封锁时才反而不通,极少数网络)。Gitee 是国内平台,海外用户基本只会用到 GitHub。
40
+
35
41
  ### ③ 代码管理
36
42
  - **跟随 ② 平台**:本区所有「检测/新建/可见性」逻辑随 ② 的平台选择切换(GitHub 走 `gh` CLI,Gitee 走 Gitee OpenAPI)
37
43
  - **Gitee 令牌**(仅 Gitee 模式显示):输入 Gitee 私人访问令牌(需 `projects` 权限)→ 保存在本机 `~/.dsh/storages/source-code-mgmt-gitee.json`(0600,**不写入插件目录**、不回传到浏览器/日志);可一键清除;令牌无效会自动清掉
@@ -59,9 +65,7 @@ DSH 打开时**不联网同步仓库**,只预取静态的环境/SSH/工作区
59
65
 
60
66
  ## 安装
61
67
 
62
- ### 关键前提:安装 激活
63
-
64
- `pnpm add`(无论是 `link:`、`git+` 还是 npm)只会把插件写进 profile 的 `package.json` 依赖和 `node_modules`,**并不会自动把插件注册进 Cordis loader 树**。要让「代码管理」入口出现,**还必须激活它**(见下方「激活配置(安装后必做)」)+ **完全重启 dsh web**。这也是 dsh-update 等本地插件共用的激活方式。
68
+ > 本插件以 **Profile Bundle** 形态分发:`package.json` 声明了 `dsh.bundle`(携带 `cordis.patch.yml` 配置层),所以 `dsh plugin --profile web add` **一条命令装完即自动激活**——无需手动编辑任何配置文件。
65
69
 
66
70
  ### 方式一:从 npm 官方包安装(推荐)
67
71
 
@@ -73,106 +77,50 @@ DSH 打开时**不联网同步仓库**,只预取静态的环境/SSH/工作区
73
77
  dsh plugin --profile web add source-code-mgmt
74
78
  ```
75
79
 
76
- 或者等价地手动操作:
77
-
78
- ```bash
79
- cd ~/.dsh/profiles/web
80
- pnpm add source-code-mgmt
81
- dsh web
82
- ```
83
-
84
- > 说明:`dsh plugin --profile web add <包名>` 本质是「在 web profile 目录里执行 `pnpm add <包名>`」并顺带对账插件层,比手动 `cd` 更省心。但它**同样不会自动把插件激活**(不会替你写 `cordis.patch.yml` 的 insert 条目),所以装完后仍需下面「激活配置」里的步骤 + 完全重启。
85
-
86
- ### 激活配置(安装后必做)
87
-
88
- 插件**不会**因为 `pnpm add` 就自动出现在侧边栏。请在 `~/.dsh/profiles/web/cordis.patch.yml` 中添加 insert 条目(若文件已有其他插件的 insert,照格式并列添加即可):
89
-
90
- ```yaml
91
- - insert:
92
- - id: source-code-mgmt
93
- name: 'source-code-mgmt'
94
- ```
80
+ > 该命令在 web profile 目录里执行 `pnpm add`,成功后对账插件层:检测到本插件声明 `dsh.bundle`,会自动把它追加进 `dsh.profile.bundles`(见 `~/.dsh/profiles/web/package.json`)并注册进 Cordis loader 树,**一步装完即用**。
95
81
 
96
- 保存后**完全重启 dsh web**(不是刷新页面,而是要停掉旧进程后重新启动),然后浏览器 **F5 刷新**,「代码管理」入口即出现(已装 dsh-better-sidebar 时为侧边栏 Tab,未装时为右上角 Session log 旁的「代码管理」按钮 + 右侧集成面板)。
97
-
98
- > 用命令直接追加(幂等,已存在则跳过)——PowerShell:
99
- > ```powershell
100
- > $patch = "$HOME\.dsh\profiles\web\cordis.patch.yml"
101
- > $addLines = "`n# Activate the source-code-mgmt plugin (installed as a profile dependency).`n- insert:`n - id: source-code-mgmt`n name: 'source-code-mgmt'`n"
102
- > $utf8NoBom = [System.Text.UTF8Encoding]::new($false)
103
- > if (Test-Path $patch) {
104
- > $content = [System.IO.File]::ReadAllText($patch)
105
- > if ($content -notmatch 'source-code-mgmt') {
106
- > [System.IO.File]::AppendAllText($patch, $addLines, $utf8NoBom)
107
- > Write-Host "OK: 已追加 source-code-mgmt 激活条目" -ForegroundColor Green
108
- > } else {
109
- > Write-Host "SKIP: cordis.patch.yml 已包含 source-code-mgmt" -ForegroundColor Yellow
110
- > }
111
- > } else {
112
- > Write-Host "ERROR: 未找到 $patch" -ForegroundColor Red
113
- > }
114
- > ```
82
+ 装完**完全重启 dsh web**(不是刷新页面,而是要停掉旧进程后重新启动),然后浏览器 **F5 刷新**,「代码管理」入口即出现(已装 dsh-better-sidebar 时为侧边栏 Tab,未装时为右上角 Session log 旁的「代码管理」按钮 + 右侧集成面板)。
115
83
 
116
84
  ### 方式二:从本地目录安装(开发/测试)
117
85
 
118
86
  **Windows (PowerShell):**
119
-
120
87
  ```powershell
121
- # 1. 进入你的 DSH profile 目录
122
- cd ~/.dsh/profiles/web
123
-
124
- # 2. 用 link 协议添加插件(指向本地源码绝对路径),会建立符号链接
125
- pnpm add link:C:/path/to/source-code-mgmt
126
-
127
- # 3. 激活插件:同上(见上方「激活配置」;追加 insert 条目后完全重启)
88
+ # DSH 插件命令安装本地源码(link: 协议,符号链接,改源码即生效)
89
+ dsh plugin --profile web add link:C:/path/to/source-code-mgmt
128
90
  dsh web
129
91
  ```
130
92
 
131
93
  **Linux / macOS:**
132
-
133
94
  ```bash
134
- # 1. 进入你的 DSH profile 目录
135
- cd ~/.dsh/profiles/web
136
-
137
- # 2. 链接到插件源码目录(符号链接)
138
- pnpm add link:/home/yourname/path/to/source-code-mgmt
139
-
140
- # 3. 激活插件:同上(见上方「激活配置」;追加 insert 条目后完全重启)
95
+ dsh plugin --profile web add link:/home/yourname/path/to/source-code-mgmt
141
96
  dsh web
142
97
  ```
143
98
 
144
99
  ### 方式三:从 GitHub 安装(分发场景)
145
100
 
146
101
  **Windows / Linux / macOS 通用:**
147
-
148
102
  ```bash
149
- # 1. 进入你的 DSH profile 目录
150
- cd ~/.dsh/profiles/web
151
-
152
- # 2. 从 GitHub 安装插件(实际下载源码到 node_modules)
153
- pnpm add git+https://github.com/Zhucy123/source-code-mgmt.git
154
-
155
- # 3. 激活插件:同上(见上方「激活配置」;追加 insert 条目后完全重启)
103
+ dsh plugin --profile web add git+https://github.com/Zhucy123/source-code-mgmt.git
156
104
  dsh web
157
105
  ```
158
106
 
159
- > 方式三装完同样**不会自动激活**(激活方式同方式一);且它是**实际拷贝**到 node_modules,改动源码需重新 `pnpm add` 拉取(不像 `link:` 是符号链接、改源码即生效)。
107
+ > git 安装会把源码**实际拷贝**到 node_modules,改动源码需重新 `dsh plugin --profile web add ...` 拉取(不像 `link:` 是符号链接、改源码即生效)。
160
108
 
161
109
  ### 验证安装是否成功
162
110
 
163
- 安装 + 激活 + 重启后,可以核对以下几点:
111
+ 安装并重启后,可以核对以下几点:
164
112
 
165
113
  1. **依赖已写入**:`~/.dsh/profiles/web/package.json` 的 `dependencies` 里应有 `source-code-mgmt`。
166
- 2. **符号链接已建立(`link:` 方式)**:`~/.dsh/profiles/web/node_modules/source-code-mgmt` 指向源码目录(Windows 显示为 Junction)。
167
- 3. **激活条目已添加**:`~/.dsh/profiles/web/cordis.patch.yml` 里有 `source-code-mgmt` insert 条目。
114
+ 2. **已加入配置层**:`~/.dsh/profiles/web/package.json` 的 `dsh.profile.bundles` 列表里应有 `source-code-mgmt`(`dsh plugin add` 自动写入,无需手动编辑)。
115
+ 3. **符号链接已建立(`link:` 方式)**:`~/.dsh/profiles/web/node_modules/source-code-mgmt` 指向源码目录(Windows 显示为 Junction)。
168
116
  4. **重启后入口可见**:已装 dsh-better-sidebar 时侧边栏出现「代码管理」Tab;未装时右上角 Session log 旁出现「代码管理」按钮,点击展开右侧集成面板。
169
117
 
170
118
  ### 常见排障
171
119
 
172
120
  | 现象 | 原因 / 处理 |
173
121
  |------|------------|
174
- | 已 `pnpm add` 并重启,但按钮不出现 | 最常见:没在 `cordis.patch.yml` 里激活。补上 insert 条目后**完全重启**(不是刷新)。 |
175
- | 改了 `cordis.patch.yml` 但仍不出现 | 服务未真正重启——旧进程还占着 3080 端口。停掉旧 `dsh web` 进程再启动。 |
122
+ | 已 `dsh plugin add` 并重启,但按钮不出现 | 最常见:装完没有**完全重启**(不是刷新)。停掉旧 `dsh web` 进程再启动(旧进程还占着 3080 端口时,新实例起不来)。 |
123
+ | 安装时提示「declares no dsh.bundle」 | 装到的版本缺少 bundle 声明(旧版或打包遗漏 `cordis.patch.yml`)。确认版本 1.9.0 后重新安装/更新。 |
176
124
  | 出现「Failed to load plugins」 | 插件 host 端 `index.js` 启动报错(多为依赖解析问题)。查看启动日志,确认 `node_modules` 依赖已装齐。 |
177
125
 
178
126
  ## 使用步骤
@@ -240,9 +188,8 @@ dsh web
240
188
  ```bash
241
189
  git clone https://github.com/Zhucy123/source-code-mgmt.git
242
190
  cd source-code-mgmt
243
- # 在本地 DSH 测试
244
- cd ~/.dsh/profiles/web
245
- pnpm add link:$(pwd)
191
+ # 在本地 DSH 测试(安装到 web profile,自动激活)
192
+ dsh plugin --profile web add link:$(pwd)
246
193
  ```
247
194
 
248
195
  - 改动 `lib/client.js`(浏览器端)→ 刷新页面即生效
@@ -250,7 +197,28 @@ pnpm add link:$(pwd)
250
197
 
251
198
  ## 版本历史
252
199
 
253
- ### v1.8.0(当前)
200
+ ### v1.10.1(当前)
201
+ 本次更新(修复 better-sidebar 集成与「未安装 better-sidebar」时入口的若干问题):
202
+
203
+ - **修复:装了 dsh-better-sidebar 后,右上角「代码管理」按钮仍残留**。根因:未装 better-sidebar 时的降级入口此前只给 ReactDOM 降级路径赋了 `entryUnmount`,slots 路径漏了——导致切到「侧边栏 Tab」形态时 header 入口没被拆掉。现已把 `slots.inject` 返回的 disposer 记进 `entryUnmount`,切到 Tab 时正确拆除(顺带修正同类清理逻辑)。
204
+ - **修复:未安装 better-sidebar 时,入口只在对话内显示,新对话/无会话空态不显示**。根因:旧入口挂 `conversation.session.header.utilities`(`scope: 'session'`),而空态时整个会话 header 被 `hideChrome` 隐藏,按钮出不来。现在改为**右上角常驻**——有活跃会话时放在「Session 日志」旁(会话 header 的右对齐列表),新对话/无会话空态时改为 `shell.overlay` 常驻槽里 `position: fixed` 钉在右上角的按钮(仅空白/无会话时显示,避免与 header 按钮重复)。
205
+ - **修复:刷新瞬间「代码管理」按钮与「Session 日志」重叠**。根因:`captureSessions()` 延迟 1.2s 才捕获到 session 列表,捕获前误判为「无会话」而提前点亮常驻按钮。现在未捕获到 session 列表前不渲染常驻按钮,杜绝刷新闪叠。
206
+ - **判定信号修正**:常驻按钮的显隐改用「当前会话是否空白」判断(`sessions.list.getSnapshot().byId[current].blank`)——活跃(非空白)会话才隐藏常驻按钮(交给 header 内的按钮),空白/无会话则显示,替代原来不准确的「`current === undefined`」判断。
207
+ - **健壮性**:better-sidebar 服务的探测由「一次性 1.5s 重试」改为**有界多档重试**(快节奏起步再放慢,覆盖约 44s,拿到即停、卸载即清),兜底 better-sidebar 客户端冷启动较慢导致漏切 Tab 的竞态。
208
+
209
+ > 以上均为客户端(`lib/client.js`)改动,刷新页面即生效;host 端 `/api` 路由与推送/忽略逻辑未改动。
210
+
211
+ ### v1.10.0(历史)
212
+ 本次更新:
213
+
214
+ - **界面中英文实时切换(跟随 DSH 语言设置)**:面板全部文案(①②③ 三步、按钮、弹窗、状态/结果消息、确认框、Tab 标题)与 host 端错误/结果消息改为双语词典驱动——语言 = DSH 设置 → 通用 → 语言,切换**即时生效**(面板经 `ctx.locale` 订阅实时重渲染,Tab 标题随动),无需刷新/重启;host 端按请求的 `?lang=` 经 AsyncLocalStorage 按请求返回对应语言,并发不串扰。中文界面与 v1.9.0 完全一致,英文界面为完整翻译(含 >100MB 忽略原因、Gitee 令牌提示、git 命令失败回退等全部消息)。新增 `tools/` 下的 i18n 提取/应用/测试脚本便于后续维护
215
+
216
+ ### v1.9.0(历史)
217
+ 本次更新:
218
+
219
+ - **改为 Profile Bundle 分发,安装即激活**:`package.json` 的 `dsh.bundle` 从裸字符串 `"./lib/index.js"` 改为对象形态 `{ "patch": "./cordis.patch.yml" }`,并新增 `cordis.patch.yml`(insert `source-code-mgmt` 行)。现在 `dsh plugin --profile web add source-code-mgmt` 一步装完即被自动加入 `dsh.profile.bundles` 并注册进 Cordis loader 树,**不再需要手动编辑 `cordis.patch.yml` 激活**;README 中「安装 ≠ 激活」说明与 PowerShell 激活脚本已删除。功能行为零变化(仍是同一份 `lib/index.js` host 端 + `lib/client.js` 浏览器端)
220
+
221
+ ### v1.8.0(历史)
254
222
  本次更新:
255
223
 
256
224
  - **新增「推送暂存」按钮**(③面板「同步」行):当**本地领先有提交**或**有已暂存的改动**时,「同步」行「本地领先 N 提交」后面出现「**推送暂存**」按钮——点击后**只把已暂存的内容**用**你填写的提交信息**(没填则自动生成 `chore: update <文件夹名>`)提交,然后**推送到远程**;不会像「推送更改」那样自动暂存所有未暂存的改动。推送成功后自动刷新状态并显示「⟳ 刷新中…」,界面显示本次提交的信息与 hash。host 端新增 `POST /push-staged` 路由(`pushStagedFlow`,沿用本插件 `run()`/GIT_SSH)
@@ -0,0 +1,15 @@
1
+ # Profile bundle: mount the「代码管理」plugin when a profile lists this bundle.
2
+ #
3
+ # One row covers both halves:
4
+ # - host half: `lib/index.js` (package main) injects webServer and registers
5
+ # the /api/source-code-mgmt/* routes;
6
+ # - browser half: the modules node half scans enabled Loader entries whose
7
+ # manifest declares `dsh.client` and serves `lib/client.js` under /plugins,
8
+ # so the same row enables the「代码管理」entry in the web UI.
9
+ #
10
+ # `dsh plugin --profile <name> add source-code-mgmt` appends this bundle to the
11
+ # profile's `dsh.profile.bundles` automatically; no manual cordis.patch.yml
12
+ # editing is needed.
13
+ - insert:
14
+ - id: source-code-mgmt
15
+ name: 'source-code-mgmt'