diff --git a/README.md b/README.md
index 123df62..c8c1ede 100644
--- a/README.md
+++ b/README.md
@@ -35,42 +35,40 @@ https://github.com/user-attachments/assets/23187822-047e-45cc-b480-fe997bd55b86
## 🚀 安装
-前置:已安装 DSH(`dsh web` 可运行),Node.js ≥ 20、pnpm ≥ 10。插件已发布到 npm:**`dsh-better-sidebar@0.10.1`**(`@deepseek-ai/*` peer 依赖对齐宿主实际版本 `^0.1.0-rc.6` / `@deepseek-ai/cordis@^4.0.1`,同版本单实例)。挂载仍走 profile + `cordis.patch.yml`,不修改 DSH 源码。
+前置:已安装 DSH(`dsh web` 可运行,含 `dsh plugin` 命令),Node.js ≥ 20、pnpm ≥ 10。插件已发布到 npm:**`dsh-better-sidebar@0.10.2`**(`@deepseek-ai/*` peer 依赖对齐宿主实际版本 `^0.1.0-rc.6` / `@deepseek-ai/cordis@^4.0.1`,同版本单实例)。包内声明了 `dsh.bundle.patch`(随包发布的 `cordis.patch.yml`),官方 CLI **一条命令完成安装 + 挂载**,不修改 DSH 源码。
-### 一键安装(推荐)
+### 官方 CLI 安装(推荐)
+
+```sh
+dsh plugin --profile web add dsh-better-sidebar@0.10.2
+# 或(本机无 dsh 命令时)
+npx -y --package @deepseek-ai/dsh dsh plugin --profile web add dsh-better-sidebar@0.10.2
+# 或安装最新发布版
+dsh plugin --profile web add dsh-better-sidebar
+```
+
+命令自动完成:`pnpm add` 登记依赖到 `~/.dsh/profiles/web/package.json` → 识别包内 `dsh.bundle.patch`,把插件自动加进 `dsh.profile.bundles` → 下次启动自动挂载(无需手写 `cordis.patch.yml` 挂载行)。更新同理:`dsh plugin --profile web add dsh-better-sidebar@<新版>`。
+
+> ⚠️ 首次在新 profile 上执行时,pnpm 11 的 `strict-dep-builds` 会拦截 node-pty/protobufjs 的构建脚本,命令会报 `Ignored build scripts`(包仍已安装、node-pty 预编译产物可直接用)。此时在 `~/.dsh/profiles/web` 执行 `pnpm approve-builds --all` 再重跑一次即可;`scripts/install.sh` 会自动处理(预写 allowBuilds + 清理旧挂载行)。
+
+### 一键脚本(自动处理 allowBuilds / 旧挂载行)
```sh
curl -fsSL https://raw.githubusercontent.com/omdsh-dev/DSH-better-sidebar/main/scripts/install.sh | bash
-# 指定版本: curl -fsSL <同上> | bash -s 0.10.1
+# 指定版本: curl -fsSL <同上> | bash -s 0.10.2
# 装完自动重启 DSH: curl -fsSL <同上> | bash -s -- --restart
```
-脚本自动完成:登记 npm 依赖到 `~/.dsh/profiles/web/package.json`、幂等追加 `cordis.patch.yml` 挂载行、执行 `pnpm install`(版本默认 latest,可传参;`--dry-run` 只预览不落盘)。
-
-### 手动安装(npm 包方式)
-
-```text
-1. 在 ~/.dsh/profiles/web/package.json 的 dependencies 加 "dsh-better-sidebar": "^0.10.1"
-2. 在 ~/.dsh/profiles/web/cordis.patch.yml 追加挂载行:
- - insert:
- - id: better-sidebar
- name: 'dsh-better-sidebar'
-3. 在 ~/.dsh/profiles/web 执行 pnpm install
-4. 重启 DSH 并硬刷新(Cmd/Ctrl+Shift+R)验证
-```
-
-> 安装 = 依赖登记 + 一行挂载行。**DSH 以 npm 包启动(如 `npx -p @deepseek-ai/dsh@0.1.0-rc.6 dsh web`)同样可用**(v0.4.3 起实测验证)。
-
-> 提示:若 profile 的 pnpm 因 `minimumReleaseAge`(发布 <24h 的新版本)拒绝安装,会自动向 `~/.dsh/profiles/web/pnpm-workspace.yaml` 追加 `minimumReleaseAgeExclude` 条目;也可手动补一行 `dsh-better-sidebar@<版本>`。
-
### 更新
-```text
-1. 把 ~/.dsh/profiles/web/package.json 里版本号改到新版(如 "^0.10.1")
-2. 在 ~/.dsh/profiles/web 执行 pnpm install
-3. 重启 DSH 并硬刷新(Cmd/Ctrl+Shift+R)
+```sh
+dsh plugin --profile web add dsh-better-sidebar@<新版>
```
+或手动把 `~/.dsh/profiles/web/package.json` 里版本号改到新版(如 `"^0.10.2"`)后 `pnpm install`。随后重启 DSH 并硬刷新(Cmd/Ctrl+Shift+R)。
+
+> 提示:若 pnpm 因 `minimumReleaseAge`(发布 <24h 的新版本)拒绝安装,会自动向 `~/.dsh/profiles/web/pnpm-workspace.yaml` 追加 `minimumReleaseAgeExclude` 条目;也可手动补一行 `dsh-better-sidebar@<版本>`。
+
从源码安装 / 开发(可选,替代 npm 方式)
@@ -85,7 +83,7 @@ curl -fsSL https://raw.githubusercontent.com/omdsh-dev/DSH-better-sidebar/main/s
5. 重启 DSH 并硬刷新
```
-更新:`git pull && pnpm install && pnpm build` → 重启 DSH(仅 client 改动可硬刷新)。切回 npm 通道时,把依赖改回 `"dsh-better-sidebar": "^0.10.1"` 再 `pnpm install`。
+更新:`git pull && pnpm install && pnpm build` → 重启 DSH(仅 client 改动可硬刷新)。切回 npm 通道时,把依赖改回 `"dsh-better-sidebar": "^0.10.2"` 再 `pnpm install`。
diff --git a/README_EN.md b/README_EN.md
index 18240f0..487a436 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -35,42 +35,40 @@ https://github.com/user-attachments/assets/23187822-047e-45cc-b480-fe997bd55b86
## 🚀 Installation
-Prerequisites: DSH installed (`dsh web` works), Node.js ≥ 20, pnpm ≥ 10. The plugin is published to npm as **`dsh-better-sidebar@0.10.1`** (`@deepseek-ai/*` peers aligned with the host's actual versions `^0.1.0-rc.6` / `@deepseek-ai/cordis@^4.0.1`, single instance). Mounting still goes through the profile + `cordis.patch.yml`; the DSH source is never modified.
+Prerequisites: DSH installed (`dsh web` works, including the `dsh plugin` command), Node.js ≥ 20, pnpm ≥ 10. The plugin is published to npm as **`dsh-better-sidebar@0.10.2`** (`@deepseek-ai/*` peers aligned with the host's actual versions `^0.1.0-rc.6` / `@deepseek-ai/cordis@^4.0.1`, single instance). The package declares `dsh.bundle.patch` (the shipped `cordis.patch.yml`), so the official CLI installs **and mounts in one command** — the DSH source is never modified.
-### One-click install (recommended)
+### Official CLI install (recommended)
+
+```sh
+dsh plugin --profile web add dsh-better-sidebar@0.10.2
+# or (no local dsh command):
+npx -y --package @deepseek-ai/dsh dsh plugin --profile web add dsh-better-sidebar@0.10.2
+# or install the latest published version:
+dsh plugin --profile web add dsh-better-sidebar
+```
+
+The command: runs `pnpm add` to register the dependency in `~/.dsh/profiles/web/package.json`, detects the package's `dsh.bundle.patch`, auto-appends the plugin to `dsh.profile.bundles`, and the next boot mounts it — no hand-written `cordis.patch.yml` mount line. Update the same way: `dsh plugin --profile web add dsh-better-sidebar@`.
+
+> ⚠️ On a fresh profile, pnpm 11's `strict-dep-builds` blocks node-pty/protobufjs build scripts and the command reports `Ignored build scripts` (the package is still installed; node-pty's prebuilds work as-is). Fix: run `pnpm approve-builds --all` in `~/.dsh/profiles/web` and re-run. `scripts/install.sh` handles this automatically (pre-writes allowBuilds + cleans up the old mount line).
+
+### One-click script (handles allowBuilds / old mount line)
```sh
curl -fsSL https://raw.githubusercontent.com/omdsh-dev/DSH-better-sidebar/main/scripts/install.sh | bash
-# Pick a version: curl -fsSL | bash -s 0.10.1
+# Pick a version: curl -fsSL | bash -s 0.10.2
# Auto-restart DSH: curl -fsSL | bash -s -- --restart
```
-The script registers the npm dependency in `~/.dsh/profiles/web/package.json`, idempotently appends the `cordis.patch.yml` mount line, and runs `pnpm install` (version defaults to latest, pass one as an argument; `--dry-run` previews without writing anything).
-
-### Manual install (npm package)
-
-```text
-1. In ~/.dsh/profiles/web/package.json dependencies add "dsh-better-sidebar": "^0.10.1"
-2. Append the mount line to ~/.dsh/profiles/web/cordis.patch.yml:
- - insert:
- - id: better-sidebar
- name: 'dsh-better-sidebar'
-3. Run pnpm install in ~/.dsh/profiles/web
-4. Restart DSH and hard-refresh (Cmd/Ctrl+Shift+R) to verify
-```
-
-> Installation = dependency registration + one mount line. **It also works when DSH is started as an npm package (e.g. `npx -p @deepseek-ai/dsh@0.1.0-rc.6 dsh web`)** (verified since v0.4.3).
-
-> Note: if the profile's pnpm rejects a too-fresh release via `minimumReleaseAge` (<24h old), it auto-appends a `minimumReleaseAgeExclude` entry to `~/.dsh/profiles/web/pnpm-workspace.yaml` — or add `dsh-better-sidebar@` there manually.
-
### Updating
-```text
-1. Bump the version range in ~/.dsh/profiles/web/package.json (e.g. "^0.10.1")
-2. Run pnpm install in ~/.dsh/profiles/web
-3. Restart DSH and hard-refresh (Cmd/Ctrl+Shift+R)
+```sh
+dsh plugin --profile web add dsh-better-sidebar@
```
+or bump the version range in `~/.dsh/profiles/web/package.json` (e.g. `"^0.10.2"`) and run `pnpm install`. Then restart DSH and hard-refresh (Cmd/Ctrl+Shift+R).
+
+> Note: if pnpm rejects a too-fresh release via `minimumReleaseAge` (<24h old), it auto-appends a `minimumReleaseAgeExclude` entry to `~/.dsh/profiles/web/pnpm-workspace.yaml` — or add `dsh-better-sidebar@` there manually.
+
Install from source / develop (optional — alternative to the npm flow)
@@ -85,7 +83,7 @@ To debug local changes or track the dev branch, point the dependency at a local
5. Restart DSH and hard-refresh
```
-Update: `git pull && pnpm install && pnpm build` → restart DSH (client-only changes can just hard-refresh). To switch back to the npm channel, restore `"dsh-better-sidebar": "^0.10.1"` and re-run `pnpm install`.
+Update: `git pull && pnpm install && pnpm build` → restart DSH (client-only changes can just hard-refresh). To switch back to the npm channel, restore `"dsh-better-sidebar": "^0.10.2"` and re-run `pnpm install`.
diff --git a/cordis.patch.yml b/cordis.patch.yml
new file mode 100644
index 0000000..d071766
--- /dev/null
+++ b/cordis.patch.yml
@@ -0,0 +1,19 @@
+# dsh-better-sidebar bundle patch
+#
+# This file is the `dsh.bundle.patch` layer of the published npm package: when
+# the plugin is installed through the official CLI —
+#
+# dsh plugin --profile add dsh-better-sidebar@
+#
+# — the command reconciles `dsh.profile.bundles` against installed packages
+# and, seeing this declaration, appends `dsh-better-sidebar` to the bundle
+# stack. The profile boot then merges THIS patch (a single `insert` of the
+# plugin row) exactly like the manual cordis.patch.yml mount line used
+# before. No profile file edits needed — one command installs and mounts.
+#
+# If the profile still carries the old manual mount line in its own
+# cordis.patch.yml, remove it before switching to the bundle channel to
+# avoid double-mounting (two Node halves, two sidebars).
+- insert:
+ - id: better-sidebar
+ name: 'dsh-better-sidebar'
diff --git a/package.json b/package.json
index d304c05..1b99b02 100644
--- a/package.json
+++ b/package.json
@@ -40,6 +40,9 @@
"node": ">=20"
},
"dsh": {
+ "bundle": {
+ "patch": "./cordis.patch.yml"
+ },
"client": {
"inject": [
"@deepseek-ai/dsh-client-runtime",
@@ -63,6 +66,7 @@
"lib/types/**/*.d.ts",
"src",
"scripts/install.sh",
+ "cordis.patch.yml",
"README.md",
"README_EN.md",
"LICENSE"
diff --git a/scripts/install.sh b/scripts/install.sh
index 79977e5..ec27d9a 100755
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -1,15 +1,20 @@
#!/usr/bin/env bash
# =============================================================================
-# dsh-better-sidebar 一键安装脚本(npm 包方式)
+# dsh-better-sidebar 一键安装脚本(官方 CLI 方式)
#
-# 把插件以 npm 包形式装进 DSH 的 web profile(挂载仍走 cordis.patch.yml,
-# 符合仓库硬约束:不修改 DSH 源码,插件永远作为独立包被 profile 引用)。
+# 通过 DSH 官方插件命令安装 npm 包并自动挂载:
+# dsh plugin --profile web add dsh-better-sidebar@
+#
+# 包内声明了 dsh.bundle.patch(cordis.patch.yml):CLI 的 bundle 协调会把它
+# 自动加进 profile 的 dsh.profile.bundles,下次启动即挂载——无需手动写
+# cordis.patch.yml 挂载行。符合仓库硬约束:不修改 DSH 源码,插件永远作为
+# 独立包被 profile 引用。
#
# 用法:
# bash scripts/install.sh [版本] [--restart] [--dry-run]
#
# 版本 npm 版本号/范围,缺省为 latest(自动解析为 ^<最新>)。
-# 示例:0.10.1、^0.10.1、~0.10.1、latest
+# 示例:0.10.2、^0.10.2、~0.10.2、latest
# --restart 装完后尝试 `pm2 restart dsh-web`(无 pm2 时仅打印提示)。
# 注意:重启会断开当前 DSH 页面会话,默认不自动重启。
# --dry-run 只打印将要执行的操作,不写任何文件。
@@ -17,18 +22,26 @@
# 环境:
# DSH_HOME 默认 ~/.dsh
# REGISTRY 默认 https://registry.npmjs.org(发布源;装依赖仍走 pnpm 配置)
+# DSH_CMD 默认优先用 PATH 上的 `dsh`,缺省回退 npx -y --package @deepseek-ai/dsh
#
-# 幂等:依赖已存在且版本满足 → 跳过写入;cordis.patch.yml 已含挂载行 → 不重复追加。
-# 回滚:把 profile package.json 的依赖改回 "dsh-better-sidebar": "link:<路径>" 再 pnpm install。
+# 说明:
+# - pnpm 11 的 strict-dep-builds 会拦截 node-pty/protobufjs 的构建脚本并使
+# `dsh plugin add` 非零退出(bundle 协调因此被跳过)。脚本会先把这两个
+# 构建许可写进 profile 的 pnpm-workspace.yaml(幂等),保证 CLI 一步成功。
+# - 老版本(<0.10.2)用手动挂载行,bundle 通道激活后需移除,否则双挂载
+# (Node 半挂两次、页面两个侧边栏)。脚本会幂等移除 better-sidebar 挂载行。
+# - 回滚:dsh plugin --profile web remove dsh-better-sidebar,或把 profile 依赖
+# 改回 "dsh-better-sidebar": "link:<路径>" 再 pnpm install。
# =============================================================================
set -euo pipefail
DSH_HOME="${DSH_HOME:-$HOME/.dsh}"
PROFILE_DIR="$DSH_HOME/profiles/web"
-PKG_JSON="$PROFILE_DIR/package.json"
+WS_YML="$PROFILE_DIR/pnpm-workspace.yaml"
PATCH_YML="$PROFILE_DIR/cordis.patch.yml"
REGISTRY="${REGISTRY:-https://registry.npmjs.org}"
PKG="dsh-better-sidebar"
+DSH_CMD="${DSH_CMD:-dsh}"
RESTART=false
DRY_RUN=false
@@ -46,77 +59,99 @@ say() { printf '\033[32m[install]\033[0m %s\n' "$*"; }
warn() { printf '\033[33m[warn]\033[0m %s\n' "$*" >&2; }
die() { printf '\033[31m[error]\033[0m %s\n' "$*" >&2; exit 1; }
-# 解析用户给的版本 -> package.json 里要写的 spec("^x.y.z")
+# 解析用户给的版本 -> CLI 要用的 npm spec("x.y.z" / "^x.y.z")
resolve_spec() {
local given="${1:-latest}"
case "$given" in
latest)
local v
v="$(npm view "$PKG" version --registry="$REGISTRY" 2>/dev/null)" \
- || die "无法从 $REGISTRY 解析 $PKG 的最新版本(请检查网络/登录)。可显式传版本号:bash scripts/install.sh 0.10.1"
- printf '^%s' "$v"
+ || die "无法从 $REGISTRY 解析 $PKG 的最新版本(请检查网络/登录)。可显式传版本号:bash scripts/install.sh 0.10.2"
+ printf '%s' "$v"
;;
- ^*|~*) printf '%s' "$given" ;;
- *) printf '^%s' "$given" ;;
+ *) printf '%s' "$given" ;;
esac
}
+# 组装 dsh CLI 调用:优先 PATH 上的 dsh,缺省 npx 拉官方包
+dsh_cli() {
+ if command -v "$DSH_CMD" >/dev/null 2>&1; then
+ printf '%s' "$DSH_CMD"
+ else
+ printf 'npx -y --package @deepseek-ai/dsh dsh'
+ fi
+}
+
[ -d "$PROFILE_DIR" ] || die "找不到 profile 目录:${PROFILE_DIR}(请先安装并运行过一次 dsh web)"
-[ -f "$PKG_JSON" ] || die "找不到 $PKG_JSON"
-[ -f "$PATCH_YML" ] || die "找不到 ${PATCH_YML}(请先初始化 web profile)"
+[ -f "$WS_YML" ] || die "找不到 ${WS_YML}(请先初始化 web profile)"
SPEC="$(resolve_spec "$VERSION_SPEC")"
-say "目标依赖:\"$PKG\": \"$SPEC\"(profile: ${PROFILE_DIR})"
+CLI="$(dsh_cli)"
+say "目标:$CLI plugin --profile web add $PKG@${SPEC}(profile: ${PROFILE_DIR})"
if [ "$DRY_RUN" = true ]; then
- say "[dry-run] 步骤 1:更新 $PKG_JSON 的 dependencies[\"$PKG\"] = \"$SPEC\""
- say "[dry-run] 步骤 2:确保 $PATCH_YML 含挂载行(- insert: - id: better-sidebar)"
- say "[dry-run] 步骤 3:在 $PROFILE_DIR 执行 pnpm install"
+ say "[dry-run] 步骤 1:确保 $WS_YML 含 allowBuilds(node-pty/protobufjs: true)"
+ say "[dry-run] 步骤 2:执行 $CLI plugin --profile web add $PKG@${SPEC}(安装 + bundle 自动注册)"
+ say "[dry-run] 步骤 3:幂等移除 $PATCH_YML 里旧的 better-sidebar 手动挂载行(避免双挂载)"
if [ "$RESTART" = true ]; then say "[dry-run] 步骤 4:pm2 restart dsh-web"; else say "[dry-run] 步骤 4:提示用户手动重启 DSH"; fi
exit 0
fi
-# 步骤 1:写依赖(用 node 安全改 JSON,保留其余字段;替换已存在的 link:/旧版本条目)
-node -e '
- const fs = require("fs");
- const pkgJson = process.argv[1];
- const name = process.argv[2];
- const spec = process.argv[3];
- const p = JSON.parse(fs.readFileSync(pkgJson, "utf8"));
- p.dependencies = p.dependencies || {};
- const old = p.dependencies[name];
- if (old === spec) {
- console.log("unchanged");
- } else {
- p.dependencies[name] = spec;
- fs.writeFileSync(pkgJson, JSON.stringify(p, null, 2) + "\n");
- console.log(old === undefined ? `added ${name}@${spec}` : `replaced ${name}@${old} -> ${name}@${spec}`);
- }
-' "$PKG_JSON" "$PKG" "$SPEC"
-
-# 步骤 2:确保 cordis.patch.yml 挂载行存在(幂等追加)
-if grep -qE '^\s*- id: better-sidebar\b' "$PATCH_YML"; then
- say "挂载行已存在,跳过 cordis.patch.yml"
+# 步骤 1:预写 allowBuilds(幂等),保证 pnpm 不为 node-pty/protobufjs 拦截构建
+if ! grep -qE '^\s*node-pty: true\s*$' "$WS_YML"; then
+ # 清除 pnpm 自动写入的占位值("set this to true or false")后写入 true
+ node -e '
+ const fs = require("fs");
+ const p = process.argv[1];
+ let t = fs.readFileSync(p, "utf8");
+ t = t.replace(/node-pty:.*/g, "node-pty: true");
+ t = t.replace(/protobufjs:.*/g, "protobufjs: true");
+ if (!t.includes("allowBuilds:")) t += "\nallowBuilds:\n node-pty: true\n protobufjs: true\n";
+ fs.writeFileSync(p, t);
+ ' "$WS_YML"
+ say "已确保 $WS_YML 的 allowBuilds(node-pty/protobufjs: true)"
else
- # 确保文件末尾有换行
- [ -n "$(tail -c1 "$PATCH_YML" 2>/dev/null)" ] && printf '\n' >> "$PATCH_YML"
- cat >> "$PATCH_YML" <<'YAML'
-
-# dsh-better-sidebar mount (added by scripts/install.sh)
-- insert:
- - id: better-sidebar
- name: 'dsh-better-sidebar'
-YAML
- say "已追加挂载行到 cordis.patch.yml"
+ say "allowBuilds 已就绪,跳过"
fi
-# 步骤 3:安装
-say "执行 pnpm install(${PROFILE_DIR})..."
-if ! (cd "$PROFILE_DIR" && pnpm install); then
- warn "pnpm install 失败。若提示 minimumReleaseAge(新版本发布 <24h),pnpm 通常会自动写入 minimumReleaseAgeExclude 并重试;"
- warn "仍失败可尝试:cd $PROFILE_DIR && pnpm clean --lockfile && pnpm install"
+# 步骤 2:官方 CLI 安装 + bundle 自动注册(含挂载)
+say "执行 $CLI plugin --profile web add $PKG@$SPEC ..."
+if ! $CLI plugin --profile web add "$PKG@$SPEC" 2>&1 | tail -n +1; then
+ warn "dsh plugin add 失败。可能原因:minimumReleaseAge(发布 <24h,pnpm 通常自动写入排除并重试)"
+ warn "或 allowBuilds 未生效。可手动重试:cd $PROFILE_DIR && pnpm install"
exit 1
fi
+
+# 校验 bundle 已注册(挂载生效的判据)
+if ! node -e '
+ const fs = require("fs");
+ const p = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
+ const bundles = p.dsh?.profile?.bundles ?? [];
+ process.exit(bundles.includes(process.argv[2]) ? 0 : 1);
+' "$PROFILE_DIR/package.json" "$PKG"; then
+ warn "dsh-better-sidebar 未出现在 dsh.profile.bundles 中——挂载未注册。"
+ warn "若上面的 pnpm 输出提示 ignored build scripts,请确认 $WS_YML 的 allowBuilds 后重跑本脚本。"
+ exit 1
+fi
+say "bundle 已注册:dsh.profile.bundles 包含 $PKG(下次启动自动挂载)"
+
+# 步骤 3:幂等移除旧的 manual 挂载行(避免与 bundle 双挂载)
+if grep -qE '^\s*- id: better-sidebar\b' "$PATCH_YML"; then
+ node -e '
+ const fs = require("fs");
+ const p = process.argv[1];
+ let t = fs.readFileSync(p, "utf8");
+ // 移除 better-sidebar 的 insert 块(含其前的注释行)
+ t = t.replace(/(?:^[ \t]*#[^\n]*\n)*[ \t]*- insert:\n[ \t]+- id: better-sidebar\n[ \t]+name: '"'"'dsh-better-sidebar'"'"'\n?/g, "");
+ // 清理可能留下的空行堆积
+ t = t.replace(/\n{3,}/g, "\n\n");
+ fs.writeFileSync(p, t);
+ ' "$PATCH_YML"
+ say "已从 $PATCH_YML 移除旧的 better-sidebar 手动挂载行(bundle 通道接管挂载)"
+else
+ say "无旧手动挂载行,跳过"
+fi
+
say "安装完成:$PKG@$SPEC"
# 步骤 4:重启提示