@noob-stupid/dsh-plugin-console 0.3.56 → 0.3.57
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.md +2 -2
- package/README.zh.md +2 -2
- package/lib/client.js +1 -1
- package/lib/index.js +90 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -308,7 +308,7 @@ MIT
|
|
|
308
308
|
|
|
309
309
|
The layered-refactor preview lives in its **own repository**: [**`Noob-stupid/dsh-plugin-hub-refactor`**](https://github.com/Noob-stupid/dsh-plugin-hub-refactor)
|
|
310
310
|
|
|
311
|
-
- **What it is**: the monolithic `lib/index.js` (8547 lines) split into layers — `lib/index.js` **141 lines** + `lib/server/**` **38 modules**; **feature-equivalent to `0.3.
|
|
311
|
+
- **What it is**: the monolithic `lib/index.js` (8547 lines) split into layers — `lib/index.js` **141 lines** + `lib/server/**` **38 modules**; **feature-equivalent to `0.3.57`**, maintainability only;
|
|
312
312
|
- **Verified**: 19 test suites green · 8 architecture-guard assertions · **route inventory identical** (`status` + response fields) against the stable build;
|
|
313
313
|
- **Not yet exercised**: real framework upgrade / rollback, restart guardian, component start/stop, real AI run, Gitee OAuth (~10–25% long-tail risk, subjective);
|
|
314
|
-
- **For everyday use** stick to npm `@noob-stupid/dsh-plugin-console@0.3.
|
|
314
|
+
- **For everyday use** stick to npm `@noob-stupid/dsh-plugin-console@0.3.57`, or `main` of this repo.
|
package/README.zh.md
CHANGED
|
@@ -275,9 +275,9 @@ MIT
|
|
|
275
275
|
|
|
276
276
|
分层重构预览线在**独立仓库**:[**`Noob-stupid/dsh-plugin-hub-refactor`**](https://github.com/Noob-stupid/dsh-plugin-hub-refactor)
|
|
277
277
|
|
|
278
|
-
- **它是什么**:把单体 `lib/index.js`(8547 行)拆成分层结构 —— `lib/index.js` **141 行** + `lib/server/**` **38 个模块**,**功能与 `0.3.
|
|
278
|
+
- **它是什么**:把单体 `lib/index.js`(8547 行)拆成分层结构 —— `lib/index.js` **141 行** + `lib/server/**` **38 个模块**,**功能与 `0.3.57` 等价**,只为可维护性;
|
|
279
279
|
- **已验证**:19 套测试全绿 · 8 条架构守卫断言 · 与稳定版逐条对打**路由清单一致**(`status` + 响应字段);
|
|
280
280
|
- **已实测**(2026-09-20 真装真卸演练):普通插件 / bundle 插件 / 无 npm 仓库 / 套装 / 技能 / 聚合仓库子包 / 仓库落地 / 服务器组件启停;
|
|
281
281
|
- **尚未实测**:真框架升级 / 真回滚、重启守护链路、AI 真跑、Gitee OAuth 回调(长尾风险主观估计 **10%~25%**);
|
|
282
|
-
- **日常使用请继续用**:npm `@noob-stupid/dsh-plugin-console@0.3.
|
|
282
|
+
- **日常使用请继续用**:npm `@noob-stupid/dsh-plugin-console@0.3.57`,或本仓库 `main`。
|
|
283
283
|
- 请多反馈问题
|
package/lib/client.js
CHANGED
|
@@ -2519,7 +2519,7 @@ window.__ModuleLoader__.load({
|
|
|
2519
2519
|
} else if (data.ai === true) {
|
|
2520
2520
|
setMessage(t("installed") + ":" + data.packageName + "。" + (data.aiNote ?? t("aiRepaired")));
|
|
2521
2521
|
} else {
|
|
2522
|
-
setMessage(t("installed") + ":" + data.packageName + "(" + (data.entryId ?? "") + ")。" + (data.curlNote ?? (data.bundle ? t("bundleNote") : t("installNote"))) + (data.bundleNote ? "。" + data.bundleNote : ""));
|
|
2522
|
+
setMessage(t("installed") + ":" + data.packageName + "(" + (data.entryId ?? "") + ")。" + (data.curlNote ?? (data.bundle ? t("bundleNote") : t("installNote"))) + (data.bundleNote ? "。" + data.bundleNote : "") + (data.lockNote ? "。⚠️ " + data.lockNote : ""));
|
|
2523
2523
|
}
|
|
2524
2524
|
if (data.kind === "skill") {
|
|
2525
2525
|
// 技能无需页面刷新
|
package/lib/index.js
CHANGED
|
@@ -3211,7 +3211,10 @@ function installJobView(job) {
|
|
|
3211
3211
|
subpackages: job.subpackages ?? null,
|
|
3212
3212
|
source: job.source ?? 'github',
|
|
3213
3213
|
curlNote: job.curlNote ?? null,
|
|
3214
|
-
bundleNote: job.bundleNote ?? null,
|
|
3214
|
+
bundleNote: job.bundleNote ?? null,
|
|
3215
|
+
lockUpdated: job.lockUpdated ?? null,
|
|
3216
|
+
lockVersion: job.lockVersion ?? null,
|
|
3217
|
+
lockNote: job.lockNote ?? null,
|
|
3215
3218
|
compatNote: job.compatNote ?? null,
|
|
3216
3219
|
kind: job.kind ?? 'plugin',
|
|
3217
3220
|
skillName: job.skillName ?? null,
|
|
@@ -3636,7 +3639,10 @@ export async function runSuiteInstallJob(job, ctx) {
|
|
|
3636
3639
|
copyTree(subDir, target)
|
|
3637
3640
|
const taken = new Set(listEntries(ctx).map((e) => e.rowId))
|
|
3638
3641
|
const entryId = deriveEntryId(pkg.name, taken)
|
|
3639
|
-
await appendInsert(patchPath, entryId, pkg.name)
|
|
3642
|
+
await appendInsert(patchPath, entryId, pkg.name)
|
|
3643
|
+
// 记下套装装配出的包名:它们是 copyTree 铺进去的、不在 pnpm-lock.yaml 里,交给调用方统一对账
|
|
3644
|
+
if (!Array.isArray(job.suiteInstalled)) job.suiteInstalled = []
|
|
3645
|
+
if (!job.suiteInstalled.includes(pkg.name)) job.suiteInstalled.push(pkg.name)
|
|
3640
3646
|
report.push({ component: sub.name, type: 'plugin', ok: true, note: `已安装 ${pkg.name}(HMR 生效)` })
|
|
3641
3647
|
handled = true
|
|
3642
3648
|
}
|
|
@@ -5199,6 +5205,17 @@ async function runInstallJob(job, ctx) {
|
|
|
5199
5205
|
if (resolveInstallKind(job.kind, await probeGitmodules(job.repo)) === 'suite') {
|
|
5200
5206
|
job.kind = 'suite'
|
|
5201
5207
|
const suiteResult = await runSuiteInstallJob(job, ctx)
|
|
5208
|
+
// 套装装配出的普通插件同样对账,避免之后被 pnpm 还原/清理
|
|
5209
|
+
if (Array.isArray(job.suiteInstalled) && job.suiteInstalled.length > 0) {
|
|
5210
|
+
try {
|
|
5211
|
+
const lock = await reconcileLockfile({ profileDir, packages: job.suiteInstalled.map((name) => ({ name })), registries })
|
|
5212
|
+
job.lockUpdated = lock.lockUpdated
|
|
5213
|
+
job.lockVersion = lock.lockVersion
|
|
5214
|
+
job.lockMethod = lock.method
|
|
5215
|
+
job.lockPackages = lock.packages
|
|
5216
|
+
if (lock.lockNote !== null) job.lockNote = lock.lockNote
|
|
5217
|
+
} catch {}
|
|
5218
|
+
}
|
|
5202
5219
|
// clone 后才发现没有 .gitmodules(探测假阳性 / 仓库已重构)→ 回落普通安装,不给用户一个失败
|
|
5203
5220
|
if (suiteResult?.notASuite !== true) return
|
|
5204
5221
|
job.kind = 'plugin'
|
|
@@ -5492,6 +5509,20 @@ async function runInstallJob(job, ctx) {
|
|
|
5492
5509
|
const adapt = await maybeAutoAdaptCompat({ profileDir, packageName: installedName, syncedNames, patchPath, ctx })
|
|
5493
5510
|
if (adapt !== null && adapt.ran === true) job.compatNote = adapt.note
|
|
5494
5511
|
} catch {}
|
|
5512
|
+
// lock 对账(2026-09-21,用户报告的自更新缺陷同源):主包 + 本次被补装/对齐的聚合子包一起核对,
|
|
5513
|
+
// 一次 pnpm add 把漂移的包全写进 lock;对不上就留 lockNote,让面板如实告知(不假装成功)。
|
|
5514
|
+
try {
|
|
5515
|
+
const lock = await reconcileLockfile({
|
|
5516
|
+
profileDir,
|
|
5517
|
+
packages: [installedName, ...syncedNames].map((name) => ({ name })),
|
|
5518
|
+
registries,
|
|
5519
|
+
})
|
|
5520
|
+
job.lockUpdated = lock.lockUpdated
|
|
5521
|
+
job.lockVersion = lock.lockVersion
|
|
5522
|
+
job.lockMethod = lock.method
|
|
5523
|
+
job.lockPackages = lock.packages
|
|
5524
|
+
if (lock.lockNote !== null) job.lockNote = lock.lockNote
|
|
5525
|
+
} catch {}
|
|
5495
5526
|
job.stage = 'configuring'
|
|
5496
5527
|
// 2026-09-06 事故(i18n 更新变重复行):@linxin666/dsh-i18n 声明了 dsh.bundle.patch,
|
|
5497
5528
|
// 更新流程按「bundle 安装规则」把它追加进 bundles → 与全家桶内的 web-ui-i18n 行(同包)重复。
|
|
@@ -5694,6 +5725,63 @@ export async function selfUpdateToLatest({ profileDir, latest, registries, curlM
|
|
|
5694
5725
|
return { method, spec, installedVersion: installed, lockVersion: lock, lockUpdated, lockNote, command, note: noteParts.join(';'), errors }
|
|
5695
5726
|
}
|
|
5696
5727
|
|
|
5728
|
+
|
|
5729
|
+
/**
|
|
5730
|
+
* 通用 lock 对账(**任何**安装通道装完都该调用,支持一次对账多个包)。
|
|
5731
|
+
* 走非 pnpm 通道(并行 curl / curl tarball / GitHub Release / git 装配 / 套装 copyTree / 聚合子包补装)装的包,
|
|
5732
|
+
* node_modules 里的版本与 `pnpm-lock.yaml` 记的版本可能不一致——之后任何 pnpm 操作(开关插件改
|
|
5733
|
+
* `dsh.profile.bundles`、`dsh plugin add/remove`)都可能按 lock 把它还原或当外来物处理。这里:
|
|
5734
|
+
* ① 全部一致 → 直接返回(不跑 pnpm,零成本);
|
|
5735
|
+
* ② 有漂移 → **一次** `pnpm add <pkg1>@<v1> <pkg2>@<v2> …` 把漂移包精确写进 lock;
|
|
5736
|
+
* ③ 仍对不上 → 返回 lockNote(逐包列出)+ 可复制命令,由调用方如实展示,绝不假装成功。
|
|
5737
|
+
*/
|
|
5738
|
+
export async function reconcileLockfile({ profileDir, packageName = null, packages = null, registries = [], pnpmAdd = pnpmInstall, execOpts = {} }) {
|
|
5739
|
+
const targets = Array.isArray(packages)
|
|
5740
|
+
? packages.filter((p) => p && typeof p.name === 'string' && p.name !== '')
|
|
5741
|
+
: (packageName === null ? [] : [{ name: packageName, version: null }])
|
|
5742
|
+
const unique = []
|
|
5743
|
+
for (const t of targets) if (!unique.some((u) => u.name === t.name)) unique.push(t)
|
|
5744
|
+
const command = (name, version) => `dsh plugin --profile <你的profile> add ${name}@${version ?? '<版本>'}`
|
|
5745
|
+
const snap = () => unique.map((t) => ({
|
|
5746
|
+
name: t.name,
|
|
5747
|
+
spec: profileSpecOf(profileDir, t.name),
|
|
5748
|
+
installed: readInstalledVersion(profileDir, t.name),
|
|
5749
|
+
lock: lockVersionOf(profileDir, t.name),
|
|
5750
|
+
}))
|
|
5751
|
+
const drift = (rows) => rows.filter((r) => r.installed === null || r.installed !== r.lock)
|
|
5752
|
+
let rows = snap()
|
|
5753
|
+
let drifted = drift(rows)
|
|
5754
|
+
const errors = []
|
|
5755
|
+
let method = null
|
|
5756
|
+
if (drifted.length > 0) {
|
|
5757
|
+
const specs = drifted.filter((r) => r.installed !== null).map((r) => `${r.name}@${r.installed}`)
|
|
5758
|
+
if (specs.length > 0) {
|
|
5759
|
+
try {
|
|
5760
|
+
await pnpmAdd(profileDir, specs.length === 1 ? specs[0] : specs, registries?.[0])
|
|
5761
|
+
method = 'pnpm-add'
|
|
5762
|
+
} catch (error) {
|
|
5763
|
+
errors.push(`pnpm add 对齐失败:${error instanceof Error ? error.message : String(error)}`)
|
|
5764
|
+
}
|
|
5765
|
+
}
|
|
5766
|
+
rows = snap()
|
|
5767
|
+
drifted = drift(rows)
|
|
5768
|
+
}
|
|
5769
|
+
const lockUpdated = drifted.length === 0
|
|
5770
|
+
return {
|
|
5771
|
+
method,
|
|
5772
|
+
packages: rows.map((r) => ({ name: r.name, installedVersion: r.installed, lockVersion: r.lock, aligned: r.installed !== null && r.installed === r.lock })),
|
|
5773
|
+
spec: rows.length === 1 ? rows[0].spec : null,
|
|
5774
|
+
installedVersion: rows.length === 1 ? rows[0].installed : null,
|
|
5775
|
+
lockVersion: rows.length === 1 ? rows[0].lock : null,
|
|
5776
|
+
lockUpdated,
|
|
5777
|
+
lockNote: lockUpdated
|
|
5778
|
+
? null
|
|
5779
|
+
: `${drifted.length} 个包没写进 pnpm-lock.yaml(${drifted.map((r) => `${r.name}:装了 ${r.installed ?? '未知'}/lock 里是 ${r.lock ?? '未记录'}`).join(';')}):之后任何 pnpm 操作(开关插件、dsh plugin add/remove)都可能把它们还原。要钉住请执行:${command(drifted[0].name, drifted[0].installed)}`,
|
|
5780
|
+
command: drifted.length > 0 ? command(drifted[0].name, drifted[0].installed) : command(rows[0]?.name ?? '', rows[0]?.installed ?? null),
|
|
5781
|
+
errors,
|
|
5782
|
+
}
|
|
5783
|
+
}
|
|
5784
|
+
|
|
5697
5785
|
export function apply(ctx) {
|
|
5698
5786
|
// 恢复 AI 赋能任务(restart 后 running 置失败,plan-ready/结果保留)
|
|
5699
5787
|
loadAiJobs()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noob-stupid/dsh-plugin-console",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.57",
|
|
4
4
|
"description": "DSH plugin management panel & marketplace: one-click enable/disable, multi-source market (GitHub/Gitee/custom), static-index market (500+ plugins / 300 skills), skills, suites, and one-click framework upgrade.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|