@noob-stupid/dsh-plugin-console 0.5.6 → 0.5.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/lib/client.js
CHANGED
|
@@ -201,6 +201,9 @@ window.__ModuleLoader__.load({
|
|
|
201
201
|
fwPanelChecking: "检查中…",
|
|
202
202
|
fwPanelRecheck: "重新检查版本",
|
|
203
203
|
fwPanelRefreshStatus: "刷新进度",
|
|
204
|
+
fwRecordClear: "关闭这条记录",
|
|
205
|
+
fwRecordClearTitle: "关掉后这里会显示「还没有升级记录」;日志仍保留在 ~/.dsh/plugin-console(fw-upgrade.log / fw-relaunch.log)",
|
|
206
|
+
fwRecordCleared: "已关闭这条升级记录",
|
|
204
207
|
fwPanelNoRecord: "还没有升级记录(这里会常驻显示最近一次升级/回滚的每一步)",
|
|
205
208
|
fwPanelConfirmBody: "确认升级到 {v}?脚本会自动:备份配置 → 预扫禁用不适配行 → 停服 → 装新版 → 拉起服务;起不来会先隔离重试,最后才整包回滚。",
|
|
206
209
|
fwRollbackDone: "已回滚到 {v}(当前就是快照版本,没有更早的可回)",
|
|
@@ -667,6 +670,9 @@ window.__ModuleLoader__.load({
|
|
|
667
670
|
fwPanelChecking: "checking…",
|
|
668
671
|
fwPanelRecheck: "Re-check version",
|
|
669
672
|
fwPanelRefreshStatus: "Refresh progress",
|
|
673
|
+
fwRecordClear: "Dismiss this record",
|
|
674
|
+
fwRecordClearTitle: "Hides the record here; logs stay in ~/.dsh/plugin-console (fw-upgrade.log / fw-relaunch.log)",
|
|
675
|
+
fwRecordCleared: "Upgrade record dismissed",
|
|
670
676
|
fwPanelNoRecord: "No upgrade record yet (the last upgrade/rollback steps will always be shown here)",
|
|
671
677
|
fwPanelConfirmBody: "Upgrade to {v}? The script will back up config, pre-disable incompatible rows, stop the service, install the new version and relaunch it; if it fails to start it quarantines and retries first, and only then rolls back the whole tree.",
|
|
672
678
|
fwRollbackDone: "Already rolled back to {v} (this is the snapshot version; nothing earlier to restore)",
|
|
@@ -1505,6 +1511,16 @@ window.__ModuleLoader__.load({
|
|
|
1505
1511
|
const [fwPreflightBusy, setFwPreflightBusy] = react.useState(false);
|
|
1506
1512
|
const [fwPreflight, setFwPreflight] = react.useState(null);
|
|
1507
1513
|
// 面板里的状态刷新:**无视**「终态已关闭」标记——卡片可以被永久关掉,面板必须永远能查到真相
|
|
1514
|
+
// 2026-09-25 用户要求:升级记录常驻是设计,但必须能一键关掉(否则每次打开都看到上次那条吓人的失败)
|
|
1515
|
+
const [fwClearing, setFwClearing] = react.useState(false);
|
|
1516
|
+
const clearFrameworkRecord = () => {
|
|
1517
|
+
if (fwClearing) return;
|
|
1518
|
+
setFwClearing(true);
|
|
1519
|
+
call("/plugin-console/framework-status-clear", {}).then(
|
|
1520
|
+
() => { setFrameworkStatus({ status: "idle", message: null }); setFwStatusDismissed(true); setMessage(t("fwRecordCleared")); },
|
|
1521
|
+
(error) => { setMessage(t("failed") + ":" + friendlyGithubError(error).message); },
|
|
1522
|
+
).finally(() => setFwClearing(false));
|
|
1523
|
+
};
|
|
1508
1524
|
const fwStatusRefresh = () => {
|
|
1509
1525
|
call("/plugin-console/framework-upgrade-status").then(
|
|
1510
1526
|
(data) => {
|
|
@@ -3813,7 +3829,10 @@ window.__ModuleLoader__.load({
|
|
|
3813
3829
|
frameworkStatus.stalled && frameworkStatus.note
|
|
3814
3830
|
? el("p", { className: styles.message, "data-warn": "true" }, "⚠ " + frameworkStatus.note)
|
|
3815
3831
|
: null,
|
|
3816
|
-
frameworkStatus.message ? el("p", { className: styles.status, "data-error": frameworkStatus.status === "failed" ? "true" : undefined }, frameworkStatus.message) : null
|
|
3832
|
+
frameworkStatus.message ? el("p", { className: styles.status, "data-error": frameworkStatus.status === "failed" ? "true" : undefined }, frameworkStatus.message) : null,
|
|
3833
|
+
// 2026-09-25 用户要求:记录常驻是设计,但得能一键关掉(否则每次打开都看到上次那条吓人的失败)
|
|
3834
|
+
el("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" } },
|
|
3835
|
+
el("button", { type: "button", className: styles.toggle, disabled: fwClearing, title: t("fwRecordClearTitle"), onClick: clearFrameworkRecord }, t("fwRecordClear"))))
|
|
3817
3836
|
: el("p", { className: styles.status }, t("fwPanelNoRecord")),
|
|
3818
3837
|
// ③.0 升级预检报告(只读结论 + 一键适配结果)——放在升级按钮之前,
|
|
3819
3838
|
// 让「先预检、再升级」成为默认路径
|
|
@@ -5029,12 +5048,22 @@ setMessage(t("failed") + ":" + (data?.reason ?? "未知"));
|
|
|
5029
5048
|
// 且仅当 configured = ledger.bundles.has(pkg.name) 为真 —— 我们是 profile bundle,天然满足。
|
|
5030
5049
|
// 所以入口长在那一页「已安装 → 我们的 bundle」详情里,用的是官方容器与官方风格,不是 DOM 注入。
|
|
5031
5050
|
// 之前那个独立的「升级安全」tab 已按用户要求关闭(错误落点不占位);原 tab(id=console) 一行未动。
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5051
|
+
//
|
|
5052
|
+
// 老框架兼容(2026-09-25 用户提问后加固):`plugins.bundle.config` 是**官方插件管理页声明的子插槽**,
|
|
5053
|
+
// 老版本框架里可能根本不存在这个插槽。此时绝不能让它把一个异常抛到 apply() 外面 —— 那样会连带
|
|
5054
|
+
// 把上面那个「插件」tab 一起拖没(前端半边整个 pending/异常)。这里包一层 try/catch:
|
|
5055
|
+
// 插槽不存在 → 只是这个新入口不显示,其余功能(含原 tab)照常。
|
|
5056
|
+
try {
|
|
5057
|
+
ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register({
|
|
5058
|
+
name: "plugins.bundle.config",
|
|
5059
|
+
key: "@noob-stupid/dsh-plugin-console",
|
|
5060
|
+
locale: NS,
|
|
5061
|
+
inject: () => ({}),
|
|
5062
|
+
}, PluginSafetyTab));
|
|
5063
|
+
} catch (error) {
|
|
5064
|
+
// 静默降级:老框架没有该子插槽属预期情况,不该在用户控制台里刷错误
|
|
5065
|
+
ctx.logger?.debug?.("plugin-console: plugins.bundle.config 插槽不可用,已跳过「升级安全」入口", error)
|
|
5066
|
+
}
|
|
5038
5067
|
}
|
|
5039
5068
|
exports.NS = NS;
|
|
5040
5069
|
exports.apply = apply;
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
function fwIntegrityCheck(params) {
|
|
11
11
|
const { target, nodePath, fwRoot } = params
|
|
12
12
|
return [
|
|
13
|
-
`
|
|
14
|
-
`
|
|
15
|
-
`
|
|
13
|
+
` # 安装后结构完整性校验:版本号对 ≠ 装完整。2026-09-24 事故:一次升级的 pnpm 安装被中断,`,
|
|
14
|
+
` # 顶层 @deepseek-ai\\dsh 目录整个消失、.pnpm 实体只剩 lib 里几个硬链接 —— 只对版本号的校验`,
|
|
15
|
+
` # 有可能被"package.json 写成功但 lib 没落全"骗过,等下次重启才发现服务起不来。`,
|
|
16
16
|
` if ($code -eq 0) {`,
|
|
17
17
|
` try {`,
|
|
18
18
|
` $fwDsh = Join-Path '${fwRoot}' '@deepseek-ai\\dsh'`,
|
|
@@ -541,4 +541,15 @@ async function routeRestart(req, res, rc) {
|
|
|
541
541
|
return
|
|
542
542
|
}
|
|
543
543
|
|
|
544
|
-
|
|
544
|
+
/** 清掉「最近一次升级/回滚记录」(2026-09-25 用户要求):记录常驻是设计,但用户要能一键关掉。
|
|
545
|
+
* 只删状态文件与心跳(不动日志,日志仍可在 ~/.dsh/plugin-console 里查)。 */
|
|
546
|
+
async function routeFrameworkStatusClear(req, res, rc) {
|
|
547
|
+
const dir = join(dshHome(), 'plugin-console')
|
|
548
|
+
const state = join(dir, 'fw-upgrade-state.txt')
|
|
549
|
+
const removed = []
|
|
550
|
+
for (const f of [state, `${state}.hb`]) {
|
|
551
|
+
try { if (existsSync(f)) { rmSync(f, { force: true }); removed.push(basename(f)) } } catch {}
|
|
552
|
+
}
|
|
553
|
+
sendJson(res, 200, { ok: true, removed, status: 'idle', message: null })
|
|
554
|
+
}
|
|
555
|
+
export { routeFrameworkStatusClear, routeFrameworkUpgradeStatusGet, routeFrameworkRelaunch, routeFrameworkCheck, routeCompatGate, routeCheckUpdate, routeFrameworkRollback, routeRestart }
|
|
@@ -17,7 +17,7 @@ import { routeComponentAutostart, routeComponentStart, routeComponentStatus, rou
|
|
|
17
17
|
import { routeCompatMode, routeCompatStamp, routeCompatStatusGet, routeDeclareInstalled } from './compat.js'
|
|
18
18
|
import { routeFrameworkUpgrade } from './framework-upgrade.js'
|
|
19
19
|
import { routeFrameworkPreflight, routeFrameworkPreflightPatch } from './framework-preflight.js'
|
|
20
|
-
import { routeCheckUpdate, routeCompatGate, routeFrameworkCheck, routeFrameworkRelaunch, routeFrameworkRollback, routeFrameworkUpgradeStatusGet, routeRestart } from './framework.js'
|
|
20
|
+
import { routeCheckUpdate, routeCompatGate, routeFrameworkCheck, routeFrameworkRelaunch, routeFrameworkRollback, routeFrameworkStatusClear, routeFrameworkUpgradeStatusGet, routeRestart } from './framework.js'
|
|
21
21
|
import { routeGithubLogin, routeGithubOpenLogin } from './github-login.js'
|
|
22
22
|
import { routeInstall, routeInstallStatus } from './install.js'
|
|
23
23
|
import { routeEnrich, routeMarketIndex, routeRepo, routeSearch, routeSubpackages } from './market.js'
|
|
@@ -93,6 +93,7 @@ const ROUTES = [
|
|
|
93
93
|
{ methods: ['POST'], path: `${ROUTE_PREFIX}/framework-upgrade`, handler: routeFrameworkUpgrade },
|
|
94
94
|
{ methods: ['POST'], path: `${ROUTE_PREFIX}/framework-preflight`, handler: routeFrameworkPreflight },
|
|
95
95
|
{ methods: ['POST'], path: `${ROUTE_PREFIX}/framework-preflight-patch`, handler: routeFrameworkPreflightPatch },
|
|
96
|
+
{ methods: ['POST'], path: `${ROUTE_PREFIX}/framework-status-clear`, handler: routeFrameworkStatusClear },
|
|
96
97
|
{ methods: ['POST'], path: `${ROUTE_PREFIX}/compat-mode`, handler: routeCompatMode },
|
|
97
98
|
{ methods: ['POST'], path: `${ROUTE_PREFIX}/compat-stamp`, handler: routeCompatStamp },
|
|
98
99
|
{ methods: ['POST'], path: `${ROUTE_PREFIX}/declare-installed`, handler: routeDeclareInstalled },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noob-stupid/dsh-plugin-console",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.8",
|
|
4
4
|
"description": "DSH 框架升级安全与插件升级门控:一键升级、失败自动回滚、升级后回滚上版、旧插件不适配自动禁用;内置多源插件市场为发现层,插件源全部可自定义,可指向公司内网私有源 / 私有索引 / 本地 Git 仓库,纯内网离线可用 | Framework upgrade safety & plugin version gating for DSH, with a customizable multi-source plugin market: point every source at internal mirrors or a local file:// repo for intranet-only, offline installs.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|