dsh-plugin-rea 2.0.6 → 2.0.8
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/CHANGELOG.md +86 -0
- package/README.md +30 -4
- package/README.zh-CN.md +28 -4
- package/bin/rea-shim.mjs +666 -31
- package/check-updates.ps1 +33 -5
- package/package.json +2 -2
- package/scripts/host-compat.mjs +29 -4
- package/scripts/rea-bundle-bootstrap.ps1 +5 -0
- package/scripts/setup.mjs +30 -1
- package/scripts/setup.test.mjs +509 -8
- package/scripts/verify-branch.ps1 +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,92 @@
|
|
|
2
2
|
|
|
3
3
|
本插件遵循语义化版本。版本号变化说明「配置组合」这层的变化,与 REA 自身的版本无关。
|
|
4
4
|
|
|
5
|
+
## 2.0.8 — 2026-10-18
|
|
6
|
+
|
|
7
|
+
**2.0.7 的启动检测在两种边界上会失控:一个包着本 shim 的 `rea` 会让探针递归成进程链;超时探针会漏掉一个孙进程。两条都已修,并补了复现测试。**
|
|
8
|
+
|
|
9
|
+
### 修复
|
|
10
|
+
|
|
11
|
+
- **重复注册检测在自定义 `DSH_HOME` 下失效**:harness 会从 MCP 子进程里抹掉所有 `DSH_*`,镜像副本因此读
|
|
12
|
+
`~/.dsh` —— 那是错的文件,上游写进真实 home 的第二条 `serverName: rea` 永远报不出来。`setup.mjs` 现在把运行时
|
|
13
|
+
的 home 记进 `mirror.json` 的 `dshHome`,shim 优先读环境、其次读这条记录。`check-updates.ps1` 的 profile 段也
|
|
14
|
+
改用同一条 home 规则(此前硬编码 `$env:USERPROFILE`,自定义 home 时报「找不到 profile」)。
|
|
15
|
+
- **镜像启动器不会自己更新**:行执行的是 `<DSH_HOME>/plugins/rea-bundle/bin/rea-shim.mjs` 这份**副本**,而市场升级
|
|
16
|
+
只换包、不跑 setup —— 副本会一直跑它被复制时的代码,于是新版本里的修复对老用户静默失效(旧副本照常工作,最难发现)。
|
|
17
|
+
现在镜像启动时会与 `mirror.json` 记录的插件目录比对哈希,不同就转发执行插件里的那一份(一跳,带
|
|
18
|
+
`REA_BUNDLE_SHIM_REEXEC` 守卫,且只从镜像指向插件,不会反向)。`--shim-status` 新增 `mirror.stale`,
|
|
19
|
+
`check-updates.ps1` 也会报「镜像落后,重跑 setup」;`mirror.json` 增加 `shimSha256` 与 `pluginVersion` 便于追溯。
|
|
20
|
+
**2.0.8 之前的版本自身无法完成这一步**(副本里没有这段代码),从那些版本升级仍需手动跑一次 setup。
|
|
21
|
+
- **探针递归**:`probeRea` 派生候选时没带 `REA_BUNDLE_DELEGATED=1`,而防自委派的守卫只在**委派**前生效。若 PATH 上是「调用本 shim 的 wrapper」,
|
|
22
|
+
探针 → wrapper → 新 shim → 再探针……实测并发 node 峰值 83+、杀掉后仍自我再生。现在探针环境同时带 `REA_BUNDLE_DELEGATED=1` 与
|
|
23
|
+
`REA_BUNDLE_AUTO_PROVISION=0`:嵌套运行直接走 bundle 并返回,实测 0.2 秒、零额外进程。
|
|
24
|
+
- **超时探针泄漏孙进程**:`spawnSync` 的超时只杀它自己启动的 cmd.exe,而 `taskkill /T` 在 `spawnSync` 回收之后调用已找不到父进程 ——
|
|
25
|
+
每次超时留一个 REA/ping 在跑。探针改为异步 `spawn` + 自己的计时器:超时发生在父进程仍存活时,`taskkill /T /F` 能真正清掉整棵树。
|
|
26
|
+
实测 8.3 秒放弃、`rejected=["timeout"]`、无残留进程。
|
|
27
|
+
- **Windows 信号处理器是死代码**:`child.kill("SIGTERM")` 在 Windows 上是 TerminateProcess,不可捕获;控制台的 Ctrl+C 又直达子进程。
|
|
28
|
+
该分支已删除,并如实写明限制:**在 Windows 上强制结束 shim 不会带走被委派的 REA**(Node 没有 job object 可用)。
|
|
29
|
+
- **`comspec()` 不校验**:`ComSpec` 指向不存在的文件时,正常的 `.cmd` REA 被判 `spawn-failed`(`auto` 静默退回 bundle,`system` 直接 78)。
|
|
30
|
+
现在校验为常规文件,否则回落到 `%SystemRoot%\System32\cmd.exe`;实测 `ComSpec` 指向不存在路径仍能识别 6.9.0。
|
|
31
|
+
- **文案**:显式路径是目录时报「does not exist」,改为「is not a file」。
|
|
32
|
+
|
|
33
|
+
### 验证
|
|
34
|
+
|
|
35
|
+
- 单测 **67 条**(2.0.7 是 60 条,本轮 +7:wrapper 递归必须被判为 `exit 78` 且 20 秒内收敛;`ComSpec` 失效仍识别 `.cmd` REA;
|
|
36
|
+
镜像自愈的转发/守卫/`stale` 上报/同内容不转发;`DSH_HOME` 被抹时从 `mirror.json` 找到真实 home 并报出重复注册):
|
|
37
|
+
Windows 64 过 + 3 平台跳过。
|
|
38
|
+
- `verify-branch.ps1` 全绿(39 项),含「两份 README 必须写出 package.json 里的 `engines.dsh` 原文」;`audit-manifest` clean;
|
|
39
|
+
`host-compat` 10 covered / 5 correctly outside。
|
|
40
|
+
- 手工复现三例:wrapper 递归 0.2 秒收敛、0 残留进程;挂起候选 8.3 秒放弃且无 `PING` 残留;`ComSpec` 指向空路径仍识别系统 REA。
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
## 2.0.7 — 2026-10-18
|
|
44
|
+
|
|
45
|
+
**机器上已有可用的 REA 时,2.x 直接按 1.x 的方式跑它(环境检测 + 委派),不再供给;同时把 2.0.6 的宿主声明收紧到真的能证明的范围。**
|
|
46
|
+
|
|
47
|
+
### 新增:环境检测 → 跑 1.x 的那条路
|
|
48
|
+
|
|
49
|
+
- **启动时判断该跑谁**:`rea` 在 PATH 上且能应答 `--version`,就用它(`rea mcp`,用户自己的 Node 与 PATH);否则走供给的
|
|
50
|
+
bundle。这正是 1.x 的契约,现在从 2.x 的行里也能到。
|
|
51
|
+
- **版本优先级**:系统 REA 比供给的旧就不抢(6.4.0 是 170 个工具、6.5.0 是 207 个,静默回退工具数是真回归)。相等或更新
|
|
52
|
+
才切;预发布/无法比较时保守留 bundle。
|
|
53
|
+
- **覆盖**:`REA_BUNDLE_LAUNCH=auto|system|bundle`(默认 auto)、`REA_BUNDLE_SYSTEM_REA=<path>` 点名不在 PATH 上的二进制。
|
|
54
|
+
`system` 在找不到时**报错退出**,而不是替用户去下 800 MB。
|
|
55
|
+
- **`--shim-status` 报告决定**:`launch.{preference,mode,reason,unusable,systemRea,rejected}`;`--shim-print-env` 在 system
|
|
56
|
+
模式下打印 `{launch,rea,version}`。
|
|
57
|
+
- **防自委派**:被委派的子进程带 `REA_BUNDLE_DELEGATED=1`,一个调用本 shim 的 wrapper 不会让委派无限递归。
|
|
58
|
+
|
|
59
|
+
### 修复(两轮独立复核,逐条可复现)
|
|
60
|
+
|
|
61
|
+
- **委派参数被加引号**:`cmd /c` 下 `.cmd` 的 `%*` 收到的是 `"mcp"` 而不是 `mcp` —— 探针能过、委派是坏的。现在只给路径加
|
|
62
|
+
引号,参数原样传(行固定传 `mcp`;需要 shell 引号的参数本就不在这条路上)。
|
|
63
|
+
- **探测预算 3s 与真机同量级**:实测经 `.cmd` 的 `rea --version` 为 2.4s(并发 2.8–3.0s),3s 预算等于掷硬币。改为 8s;超时
|
|
64
|
+
用 `taskkill /T /F` 杀进程树,不再只杀 cmd.exe 而留下一个占着管道的 REA。
|
|
65
|
+
- **Windows 信号转发是错的**:`child.kill("SIGINT")` 只 TerminateProcess(cmd.exe),里面的 REA 继续跑;现在 Windows 走
|
|
66
|
+
`taskkill /T`,POSIX 不重复转发(stdio inherit 已由进程组投递)。
|
|
67
|
+
- **`--shim-status` 退出码**:`system` 被点名但不可用时曾返回 0(bundle 恰好已供给),实际启动却 78;现在按「这一行能不能
|
|
68
|
+
起来」返回,并新增 `launch.unusable` 字段。
|
|
69
|
+
- **候选判定**:`existsSync` 换成 `statSync().isFile()`(名为 `rea.cmd` 的目录曾被当成坏安装);PATH 项去引号、跳过相对项;
|
|
70
|
+
显式路径被拒时理由如实报告。
|
|
71
|
+
- **`fail()` 的补救命令补上 `--root`**:shim 用 `REA_BUNDLE_ROOT` 解析出的根与 setup 的默认根可以不同,照着旧提示执行会供给
|
|
72
|
+
到另一个根。
|
|
73
|
+
- **`engine.dsh` 上限收紧**:`<0.3.0` 在 includePrerelease 语义下会放行 `0.3.0-alpha.1`/`0.3.0-rc.1`;改为 `<0.3.0-0`,并用
|
|
74
|
+
市场自己的 `satisfiesRange` 逐版本核对。
|
|
75
|
+
- **`host-compat.mjs` 的测试加固**:发布清单逐项钉住;新增「低地板必须被判为泄漏」的反向对照(原实现把 `leaked` 改成 `[]`
|
|
76
|
+
仍然全绿);`+build` 元数据按 semver 接受、`v` 前缀与零填充预发布按 semver 拒绝。
|
|
77
|
+
- **环境独立性**:`setup.mjs` 自检的 shim 步骤钉 `bundle` 模式(否则机器上更新的 REA 会冒充本次供给的产物);CI 两个 job
|
|
78
|
+
各加 job 级 `REA_BUNDLE_LAUNCH=bundle`;测试里的每个 shim 调用点都钉住模式,测试不再随机器变。
|
|
79
|
+
- **`rea-bundle-bootstrap.ps1` 认 `REA_BUNDLE_ROOT`**:四份代码里只有它忽略这个覆盖,导致 bootstrap 把 800 MB 装到
|
|
80
|
+
`<DSH_HOME>/plugins/rea-bundle`,而 shim/setup/check-updates 去 `REA_BUNDLE_ROOT` 找,看到空 bundle 再起一次。
|
|
81
|
+
- 中文 README 的「更新到 2.0.4」措辞改正为「更新到 2.0.5」。
|
|
82
|
+
|
|
83
|
+
### 验证
|
|
84
|
+
|
|
85
|
+
- 单测 **60 条**(新增 12 条:6 条启动模式 + 1 条清单钉住 + 1 条泄漏反向对照 + 1 条 semver 容差 + 3 条 PATH/空格路径/委派退出码),
|
|
86
|
+
Windows 57 过 + 3 平台跳过。
|
|
87
|
+
- `verify-branch.ps1` 全绿;`audit-manifest.mjs` clean;`host-compat.mjs` 10 covered / 5 correctly outside。
|
|
88
|
+
- 真机:全局 `rea` 6.4.0 与供给的 6.5.0 并存时 `auto` 留 bundle(不降工具数),`REA_BUNDLE_LAUNCH=system` 才切过去。
|
|
89
|
+
|
|
90
|
+
|
|
5
91
|
## 2.0.6 — 2026-10-18
|
|
6
92
|
|
|
7
93
|
**声明宿主版本:`engines.dsh` 覆盖 `0.1.7-rc.2` … `0.2.1-rc.2` 全部发布版本,市场卡片因此显示「兼容」而不是「未声明」。**
|
package/README.md
CHANGED
|
@@ -127,7 +127,7 @@ by the shim itself, which provisions in the background.
|
|
|
127
127
|
|
|
128
128
|
### Which DSH versions
|
|
129
129
|
|
|
130
|
-
`package.json` declares `engines.dsh: ">=0.1.7-rc.2 <0.3.0"`, and that declaration is the answer the plugin market
|
|
130
|
+
`package.json` declares `engines.dsh: ">=0.1.7-rc.2 <0.3.0-0"`, and that declaration is the answer the plugin market
|
|
131
131
|
reads: with it the card says **compatible**; without it the market can only say *unknown*. The range is not a guess —
|
|
132
132
|
it is the dsh release list this plugin is checked against, and `node scripts/host-compat.mjs` fails the build when the
|
|
133
133
|
two disagree:
|
|
@@ -142,6 +142,26 @@ What was actually compared across that range is the row provider: `packages/mcp/
|
|
|
142
142
|
`env`, `failOnStartupError`), and `dsh.bundle.patch` exists at both tags. A host outside the range can still work; it is
|
|
143
143
|
simply not claimed.
|
|
144
144
|
|
|
145
|
+
### A REA you already have is used as-is
|
|
146
|
+
|
|
147
|
+
2.x exists to supply what a machine is missing. If REA is already installed — `rea` on PATH, the 1.x setup — the row
|
|
148
|
+
runs **that**, exactly as the 1.x line did, and nothing is provisioned:
|
|
149
|
+
|
|
150
|
+
| What the machine has | What the row runs |
|
|
151
|
+
|---|---|
|
|
152
|
+
| `rea` on PATH, at least as new as the provisioned build | your REA (`rea mcp`), with your Node and your PATH |
|
|
153
|
+
| `rea` on PATH but older than the provisioned build | the provisioned bundle — a stale global CLI would take the tool count backwards (6.4.0 ships 170 tools, 6.5.0 ships 207) |
|
|
154
|
+
| no `rea` on PATH | the provisioned bundle, provisioning itself on first use |
|
|
155
|
+
|
|
156
|
+
- `REA_BUNDLE_LAUNCH=auto|system|bundle` overrides the decision (`auto` is the default); `REA_BUNDLE_SYSTEM_REA=<path>`
|
|
157
|
+
names a binary that is not on PATH.
|
|
158
|
+
- The probe is the CLI's own `--version`, bounded at 8 s: a `.cmd` shim on Windows takes ~2.4 s to answer, so the check
|
|
159
|
+
runs once per start and only when a `rea` actually exists.
|
|
160
|
+
- `--shim-status` prints the decision — `launch.mode`, `launch.reason`, `launch.systemRea` — and its `launch.rejected`
|
|
161
|
+
list says why a candidate was skipped (`"exit 7"`, `"inside the bundle"`, `"timeout"`).
|
|
162
|
+
- A delegated child carries `REA_BUNDLE_DELEGATED=1`, so a wrapper that calls this shim cannot make it delegate to
|
|
163
|
+
itself forever.
|
|
164
|
+
|
|
145
165
|
## Configure — nothing
|
|
146
166
|
|
|
147
167
|
The shipped row carries **no machine path**:
|
|
@@ -210,9 +230,9 @@ Which one? Upstream's is the configuration-only route: it expects Node on REA's
|
|
|
210
230
|
zero-dependency route: it fetches Node, REA, JDK and Ghidra on first run. The patch shape and the
|
|
211
231
|
`mcp__rea__*` surface are the same either way.
|
|
212
232
|
|
|
213
|
-
The shim reports the conflict on startup
|
|
214
|
-
|
|
215
|
-
lists it under `duplicateRegistration`.
|
|
233
|
+
The shim reports the conflict on startup — `setup.mjs` records the DSH home it ran under in
|
|
234
|
+
`mirror.json`, and the mirrored copy reads that when the harness has stripped `DSH_*` from its
|
|
235
|
+
environment; `node bin/rea-shim.mjs --shim-status` lists it under `duplicateRegistration`.
|
|
216
236
|
|
|
217
237
|
## Verify
|
|
218
238
|
|
|
@@ -317,6 +337,12 @@ back on the next start.
|
|
|
317
337
|
|
|
318
338
|
- **This plugin** never updates itself. Installed from a market? Update it there. Installed from a `file:`
|
|
319
339
|
checkout? Overwrite the directory and reinstall.
|
|
340
|
+
- **The row runs a COPY of this plugin's launcher.** `<DSH_HOME>/plugins/rea-bundle/bin/rea-shim.mjs` is a mirror
|
|
341
|
+
made by setup, so a market upgrade replaces the package but not the file the row executes — until setup runs
|
|
342
|
+
again. From **2.0.8** the mirror notices that the installed plugin ships a different launcher and re-execs it
|
|
343
|
+
(one hop, guarded by `REA_BUNDLE_SHIM_REEXEC`), so upgrades carry. On an older version the mirror stays behind
|
|
344
|
+
silently; `--shim-status` now reports `mirror.stale`, and `check-updates.ps1` says to re-run setup. If you are
|
|
345
|
+
upgrading from 2.0.0–2.0.7, run `node scripts/setup.mjs` once after the upgrade.
|
|
320
346
|
- **Upgrading from `2.0.0-bundle.1`**: that release mirrored the shim and `setup.mjs` but not the manifest,
|
|
321
347
|
and recorded nothing about the plugin checkout, so a bundle it provisioned cannot repair itself — its
|
|
322
348
|
background provisioning dies on the missing manifest, invisibly, and its own lock suppresses retries for
|
package/README.zh-CN.md
CHANGED
|
@@ -118,7 +118,7 @@ node scripts/setup.mjs --reuse # 或先 --dry-run 看计划
|
|
|
118
118
|
|
|
119
119
|
### 支持哪些 DSH 版本
|
|
120
120
|
|
|
121
|
-
`package.json` 里声明了 `engines.dsh: ">=0.1.7-rc.2 <0.3.0"`,这就是插件市场读的那句话:有它,卡片显示
|
|
121
|
+
`package.json` 里声明了 `engines.dsh: ">=0.1.7-rc.2 <0.3.0-0"`,这就是插件市场读的那句话:有它,卡片显示
|
|
122
122
|
**兼容**;没有它,市场只能说*未声明*。这个范围不是猜的——它对应本插件实际核对过的 dsh 发布列表,
|
|
123
123
|
`node scripts/host-compat.mjs` 会在两者不一致时让构建失败:
|
|
124
124
|
|
|
@@ -131,6 +131,25 @@ node scripts/setup.mjs --reuse # 或先 --dry-run 看计划
|
|
|
131
131
|
暴露的配置面与发布的行完全一致(`serverName`、`transport`、`command`、`args`、`env`、`failOnStartupError`),
|
|
132
132
|
并且两个 tag 都有 `dsh.bundle.patch`。范围之外的宿主可能照样能用,只是没有替它声明。
|
|
133
133
|
|
|
134
|
+
### 机器上已有 REA 就直接用它
|
|
135
|
+
|
|
136
|
+
2.x 存在的意义是补上机器缺的东西。如果 REA 已经装好——`rea` 在 PATH 上,也就是 1.x 的形态——这一行就**直接跑它**,
|
|
137
|
+
和 1.x 一模一样,不再做任何供给:
|
|
138
|
+
|
|
139
|
+
| 机器上的情况 | 这一行跑什么 |
|
|
140
|
+
|---|---|
|
|
141
|
+
| `rea` 在 PATH 上,且不比供给的版本旧 | 你自己那份(`rea mcp`),用你的 Node 和你的 PATH |
|
|
142
|
+
| `rea` 在 PATH 上,但比供给的版本旧 | 供给出来的 bundle —— 旧的全局 CLI 会把工具数往回退(6.4.0 是 170 个,6.5.0 是 207 个) |
|
|
143
|
+
| PATH 上没有 `rea` | 供给出来的 bundle,首次使用时自行供给 |
|
|
144
|
+
|
|
145
|
+
- `REA_BUNDLE_LAUNCH=auto|system|bundle` 覆盖这个判断(默认 `auto`);`REA_BUNDLE_SYSTEM_REA=<path>` 用来点名一个
|
|
146
|
+
不在 PATH 上的可执行文件。
|
|
147
|
+
- 探测用的是 CLI 自己的 `--version`,上限 8 秒:Windows 上的 `.cmd` 垫片要 ~2.4 秒才答得出来,所以这个检查每次启动
|
|
148
|
+
只做一次,而且只在真的存在 `rea` 时才做。
|
|
149
|
+
- `--shim-status` 会把判断结果打出来 —— `launch.mode`、`launch.reason`、`launch.systemRea`,`launch.rejected` 里
|
|
150
|
+
写的是每个候选被跳过的原因(`"exit 7"`、`"inside the bundle"`、`"timeout"`)。
|
|
151
|
+
- 被委派的子进程带着 `REA_BUNDLE_DELEGATED=1`,所以一个调用本 shim 的 wrapper 不会让它无限委派给自己。
|
|
152
|
+
|
|
134
153
|
## 配置 —— 不需要
|
|
135
154
|
|
|
136
155
|
发布的那一行**不含任何机器路径**:
|
|
@@ -197,8 +216,8 @@ duplicate server name 报错并加载失败,最终留下哪一行取决于加
|
|
|
197
216
|
自己准备。本包是零依赖路线:首次运行自动取 Node、REA、JDK、Ghidra。两者的 patch 形态与
|
|
198
217
|
`mcp__rea__*` 工具面相同。
|
|
199
218
|
|
|
200
|
-
shim
|
|
201
|
-
|
|
219
|
+
shim 会在启动时提示冲突 —— `setup.mjs` 会把运行时的 DSH home 记进 `mirror.json`,镜像副本在 harness 抹掉
|
|
220
|
+
`DSH_*` 之后就用这条记录去找那份文件;`node bin/rea-shim.mjs --shim-status` 会把冲突列在 `duplicateRegistration` 下。
|
|
202
221
|
|
|
203
222
|
## 验证
|
|
204
223
|
|
|
@@ -264,7 +283,7 @@ shim** 的 MCP `initialize` 握手返回 `serverInfo {name: rea, version: 6.5.0}
|
|
|
264
283
|
### 在市场里更新
|
|
265
284
|
|
|
266
285
|
在哪儿装的就在哪儿更新。更新到 **2.0.5 及以上**是常规操作;而把已装的 2.0.1–2.0.4 通过应用内市场**更新到
|
|
267
|
-
2.0.
|
|
286
|
+
2.0.5**,在健康的 profile 上连续失败了三次:
|
|
268
287
|
|
|
269
288
|
> dsh-plugin-rea 更新后缺少入口文件(package.json 的 main/exports 指向的文件不存在),且未能验证恢复原版本文件
|
|
270
289
|
|
|
@@ -295,6 +314,11 @@ node scripts/setup.mjs # 或:powershell -File scripts\rea-bundle-boot
|
|
|
295
314
|
工具就回来了。
|
|
296
315
|
|
|
297
316
|
- **本插件**从不自更新。从市场装的就在市场更新;从 `file:` 检出的就覆盖目录重装。
|
|
317
|
+
- **行跑的是本插件启动器的「镜像副本」**:`<DSH_HOME>/plugins/rea-bundle/bin/rea-shim.mjs` 是 setup 复制过去的,
|
|
318
|
+
所以市场升级只换包、不换行执行的那个文件 —— 直到再跑一次 setup。从 **2.0.8** 起,镜像会发现自己落后于已安装的
|
|
319
|
+
插件,并转发执行插件里的那一份(一跳,带 `REA_BUNDLE_SHIM_REEXEC` 守卫),升级因此能生效。更早的版本里镜像会
|
|
320
|
+
静默地停在旧代码;`--shim-status` 现在会报 `mirror.stale`,`check-updates.ps1` 也会提示重跑 setup。**从
|
|
321
|
+
2.0.0–2.0.7 升级的话,升级后跑一次 `node scripts/setup.mjs`。**
|
|
298
322
|
- **从 `2.0.0-bundle.1` 升级**:那一版镜像了 shim 与 `setup.mjs`,却漏了 manifest,也没有留下插件 checkout
|
|
299
323
|
的记录,所以它供给出来的 bundle **无法自愈** —— 后台供给会因缺 manifest 而崩溃且完全不可见,而它自己写下的
|
|
300
324
|
lock 又会让重试被抑制六小时。请**从插件目录**重跑一次 `node scripts/setup.mjs`:它会重新镜像三个文件,
|