dsh-remote-ui 0.6.4-beta.8 → 0.6.4-beta.9
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 +25 -9
- package/lib/index.js +22 -9
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -1243,6 +1243,9 @@ window.__ModuleLoader__.load({
|
|
|
1243
1243
|
// 是否需要重启 DeepSeek harness(首次安装/在线更新后置顶提醒 + 底部常驻按钮)
|
|
1244
1244
|
var restartInfo = (st && st.restart) || {};
|
|
1245
1245
|
var restartPending = !!restartInfo.pending;
|
|
1246
|
+
// kind === "refresh" = 插件文件在运行中被改写(装完/更新完),只需刷新页面;
|
|
1247
|
+
// 其余情况(极为罕见)才提重启 dsh web。
|
|
1248
|
+
var isRefreshOnly = restartPending && restartInfo.kind === "refresh";
|
|
1246
1249
|
// 连接阶段(node 半下发):轮询拿到的新鲜结果优先,其次用 /status 里带的那一份;
|
|
1247
1250
|
// 旧版 host(响应里没有 connect 字段)→ 回退到原来的 service.running 文案(行为不变)。
|
|
1248
1251
|
var connInfo = conn || (st && st.connect) || null;
|
|
@@ -2446,9 +2449,11 @@ window.__ModuleLoader__.load({
|
|
|
2446
2449
|
);
|
|
2447
2450
|
}
|
|
2448
2451
|
|
|
2449
|
-
// 【自动化】待重启时自动倒计时重启(见 autoRestartCancelled 说明)
|
|
2452
|
+
// 【自动化】待重启时自动倒计时重启(见 autoRestartCancelled 说明);倒计时只在面板可见且无其他操作时推进。
|
|
2453
|
+
// ⚠️ isRefreshOnly(插件更新后只需刷新)时**不**自动重启:刷新是零风险动作,重启 dsh web 会打断
|
|
2454
|
+
// 用户正在进行的会话,不能替他做这个决定 —— 让他点「刷新页面」即可。
|
|
2450
2455
|
useEffect(function () {
|
|
2451
|
-
if (!restartPending || busy !== "" || restartCancelled) { setRestartCountdown(null); return undefined; }
|
|
2456
|
+
if (!restartPending || isRefreshOnly || busy !== "" || restartCancelled) { setRestartCountdown(null); return undefined; }
|
|
2452
2457
|
var at = restartInfo.at || 0;
|
|
2453
2458
|
if (autoRestartCancelled(at)) { setRestartCountdown(null); return undefined; }
|
|
2454
2459
|
var left = Math.round(AUTO_RESTART_DELAY_MS / 1000);
|
|
@@ -2462,7 +2467,7 @@ window.__ModuleLoader__.load({
|
|
|
2462
2467
|
restartHarness(); // 已有实现:重启 + 轮询等它回来 + 自动刷新页面
|
|
2463
2468
|
}, 1000);
|
|
2464
2469
|
return function () { clearInterval(iv); };
|
|
2465
|
-
}, [restartPending, restartInfo.at, busy, restartCancelled]);
|
|
2470
|
+
}, [restartPending, isRefreshOnly, restartInfo.at, busy, restartCancelled]);
|
|
2466
2471
|
|
|
2467
2472
|
/** 取消本次自动重启(按事件持久化:同一 pending 事件不再自动重启)。 */
|
|
2468
2473
|
var cancelAutoRestart = function () {
|
|
@@ -2508,9 +2513,13 @@ window.__ModuleLoader__.load({
|
|
|
2508
2513
|
h("span", { className: "dru-restart-alert-icon" }, "🔔"),
|
|
2509
2514
|
h("div", { style: { flex: "1" } },
|
|
2510
2515
|
h("div", { className: "dru-restart-alert-title" },
|
|
2511
|
-
|
|
2516
|
+
// 插件已改为 patch 热加载:装插件/在线更新都不再需要重启 harness,
|
|
2517
|
+
// 唯一要用户动一下的情形是"插件文件在运行中被改写"→ 刷新页面即可。
|
|
2518
|
+
isRefreshOnly ? "插件已更新,刷新页面即可生效" : "需要重启 dsh web 才能载入新插件"),
|
|
2512
2519
|
h("div", { className: "dru-restart-alert-sub" },
|
|
2513
|
-
|
|
2520
|
+
isRefreshOnly
|
|
2521
|
+
? "刚装好/刚更新的插件已在磁盘上,浏览器里的面板还是旧版本。刷新一下这个页面即可(手机端连接与已登录状态都不受影响)。"
|
|
2522
|
+
: "当前运行中的 dsh web 里还没有载入这个插件。先刷新页面;如果刷新后仍然看不到面板,再重启一次 dsh web。"),
|
|
2514
2523
|
// 【自动化】待重启时自动倒计时重启(用户零操作);倒计时期间可一键取消
|
|
2515
2524
|
restartCountdown !== null && restartCountdown > 0
|
|
2516
2525
|
? h("div", { className: "dru-restart-auto", role: "status" },
|
|
@@ -2524,12 +2533,19 @@ window.__ModuleLoader__.load({
|
|
|
2524
2533
|
? h("div", { className: "dru-restart-auto muted" }, "已取消自动重启 —— 你也可以随时点下面的按钮完成安装")
|
|
2525
2534
|
: null,
|
|
2526
2535
|
h("div", { className: "dru-actions", style: { marginTop: 10 } },
|
|
2536
|
+
isRefreshOnly
|
|
2537
|
+
? h("button", {
|
|
2538
|
+
type: "button",
|
|
2539
|
+
className: "dru-btn dru-btn-primary",
|
|
2540
|
+
onClick: function () { try { location.reload(); } catch (e) { /* 忽略 */ } }
|
|
2541
|
+
}, "刷新页面")
|
|
2542
|
+
: null,
|
|
2527
2543
|
h("button", {
|
|
2528
2544
|
type: "button",
|
|
2529
|
-
className: "dru-btn dru-btn-primary",
|
|
2545
|
+
className: "dru-btn " + (isRefreshOnly ? "dru-btn-ghost" : "dru-btn-primary"),
|
|
2530
2546
|
disabled: busy !== "",
|
|
2531
2547
|
onClick: function () { restartHarness(); }
|
|
2532
|
-
}, busy === "restart" ? "重启中…" : (restartCountdown !== null && restartCountdown > 0 ? "立即重启(不用等)" : "重启
|
|
2548
|
+
}, busy === "restart" ? "重启中…" : (restartCountdown !== null && restartCountdown > 0 ? "立即重启(不用等)" : "重启 dsh web")),
|
|
2533
2549
|
restartCountdown !== null && restartCountdown > 0
|
|
2534
2550
|
? h("button", {
|
|
2535
2551
|
type: "button",
|
|
@@ -2545,13 +2561,13 @@ window.__ModuleLoader__.load({
|
|
|
2545
2561
|
),
|
|
2546
2562
|
// 常驻入口最底部:「重启 DeepSeek harness」按钮始终可达(首次安装/更新/排查都用它)
|
|
2547
2563
|
h("div", { className: "dru-restart-foot" },
|
|
2548
|
-
h("div", { className: "dru-hint" }, "重启
|
|
2564
|
+
h("div", { className: "dru-hint" }, "重启 dsh web:仅在「刷新页面后仍看不到面板」时才需要。日常安装/更新插件已自动热加载,装完刷新页面即可;重启只影响 dsh web 本身,不影响 bridge 与手机端连接。"),
|
|
2549
2565
|
h("button", {
|
|
2550
2566
|
type: "button",
|
|
2551
2567
|
className: "dru-btn " + (restartPending ? "dru-btn-primary" : "dru-btn-ghost"),
|
|
2552
2568
|
disabled: busy !== "",
|
|
2553
2569
|
onClick: function () { restartHarness(); }
|
|
2554
|
-
}, busy === "restart" ? "重启中…" : "🔄 重启
|
|
2570
|
+
}, busy === "restart" ? "重启中…" : "🔄 重启 dsh web")
|
|
2555
2571
|
),
|
|
2556
2572
|
renderCommunityModal()
|
|
2557
2573
|
);
|
package/lib/index.js
CHANGED
|
@@ -677,8 +677,11 @@ function scheduleRuntime(relayDir) {
|
|
|
677
677
|
telemetryRuntimeProbe(relayDir); // 匿名遥测:环境刚补齐 → runtime_ready(每进程一次)
|
|
678
678
|
if (awaitingRestartHint) {
|
|
679
679
|
awaitingRestartHint = false;
|
|
680
|
-
//
|
|
681
|
-
|
|
680
|
+
// 运行环境刚在本进程内补齐 —— **不需要重启 harness**:
|
|
681
|
+
// · bridge 是独立 launchd 进程,补齐后自愈调度会直接把它拉起;
|
|
682
|
+
// · 插件本体走 patch 热加载,装完即生效。
|
|
683
|
+
// 以前这里会 markRestartPending("first-install") 弹出"需要重启 DeepSeek harness"横幅,
|
|
684
|
+
// 在热加载落地后已经变成纯粹的误导(用户实测反馈),故移除。
|
|
682
685
|
}
|
|
683
686
|
const cfg = loadConfig(relayDir);
|
|
684
687
|
const hasAcct = Boolean((cfg.phone || cfg.email) && cfg.password) || Boolean(cfg.local_key);
|
|
@@ -849,7 +852,10 @@ function writeRestartState(relayDir, state) {
|
|
|
849
852
|
} catch { /* 写盘失败不致命:面板退化为不提示 */ }
|
|
850
853
|
}
|
|
851
854
|
|
|
852
|
-
/**
|
|
855
|
+
/**
|
|
856
|
+
* 标记「需要用户动一下」的状态。kind = refresh(插件被运行时改写,刷新页面即可)。
|
|
857
|
+
* 历史 kind(first-install / update)已废弃:热加载落地后,装插件与在线更新都不再需要重启 harness。
|
|
858
|
+
*/
|
|
853
859
|
function markRestartPending(relayDir, kind, reason) {
|
|
854
860
|
const cur = readRestartState(relayDir);
|
|
855
861
|
if (cur.pending && cur.kind === kind) return cur; // 幂等:同一原因不反复重写
|
|
@@ -1739,7 +1745,7 @@ const PLUGIN_ID = "dsh-remote-ui";
|
|
|
1739
1745
|
const PLUGIN_LEGACY_IDS = ["dsh-remote-web"];
|
|
1740
1746
|
const PLUGIN_ALL_IDS = [PLUGIN_ID, ...PLUGIN_LEGACY_IDS];
|
|
1741
1747
|
/** 插件自身发布版本(与 dsh-remote 根包同步递增)。 */
|
|
1742
|
-
const PLUGIN_VERSION = "0.6.4-beta.
|
|
1748
|
+
const PLUGIN_VERSION = "0.6.4-beta.9";
|
|
1743
1749
|
const UPDATE_LOG = ".dsh-update.log";
|
|
1744
1750
|
const UPDATE_MARKER = ".dsh-update-running";
|
|
1745
1751
|
|
|
@@ -1809,9 +1815,12 @@ function runOnlineUpdate(relayDir) {
|
|
|
1809
1815
|
}
|
|
1810
1816
|
appendLogLine(relayDir, UPDATE_LOG, `[update] npx 退出 code=${code ?? "?"}(${retried ? "默认源" : "官方源"})`);
|
|
1811
1817
|
clear();
|
|
1812
|
-
// 在线更新改写了插件/运行环境文件 →
|
|
1813
|
-
|
|
1814
|
-
|
|
1818
|
+
// 在线更新改写了插件/运行环境文件 → 版本对不上时由 pluginInstalledAfterBoot() 自动识别,
|
|
1819
|
+
// 面板会提示"刷新页面"。这里**不再**写"需要重启 DeepSeek harness"的待重启标记:
|
|
1820
|
+
// 插件走 patch 热加载、bridge 是独立进程,重启 harness 已无必要(用户实测反馈)。
|
|
1821
|
+
// 成功不发事件(update_started 已发过,失败才发 update_failed;白名单里没有 update_done,
|
|
1822
|
+
// 硬发只会被服务端静默丢弃)。
|
|
1823
|
+
if (code !== 0) telemetryRecord(relayDir, "update_failed", { fail_code: telemetryFailCodeFromText(readTail(join(relayDir, UPDATE_LOG))) });
|
|
1815
1824
|
});
|
|
1816
1825
|
child.on("error", (e) => {
|
|
1817
1826
|
appendLogLine(relayDir, UPDATE_LOG, `[update] 子进程启动失败: ${e.message}`);
|
|
@@ -3325,8 +3334,12 @@ export function apply(ctx, config = {}) {
|
|
|
3325
3334
|
ctx.logger?.info?.("dsh-remote-web: 检测到 DeepSeek harness 已重启,撤下「需要重启」提示");
|
|
3326
3335
|
}
|
|
3327
3336
|
if (!readRestartState(relayDir).pending && pluginInstalledAfterBoot()) {
|
|
3328
|
-
|
|
3329
|
-
|
|
3337
|
+
// 唯一还需要用户动一下的情形:插件文件晚于本进程启动才落盘(= 运行中被市场安装/在线更新改写),
|
|
3338
|
+
// 此时本进程里没有本插件的路由与面板。**先让用户刷新页面**(客户端半随之更新);
|
|
3339
|
+
// 只有刷新后仍无面板才需要重启(那时多半是 profile patch 行没被 HMR 读到)。
|
|
3340
|
+
// 不再对"首次安装/在线更新完成"提示重启:插件走 patch 热加载、bridge 是独立进程,重启 harness 无必要。
|
|
3341
|
+
markRestartPending(relayDir, "refresh", "插件已更新,刷新页面即可生效");
|
|
3342
|
+
ctx.logger?.info?.("dsh-remote-web: 插件文件晚于本次进程启动 → 提示刷新页面");
|
|
3330
3343
|
}
|
|
3331
3344
|
ctx.effect(() => registerRoutes(ctx, relayDir), "dsh-remote-web: /dsh-remote routes");
|
|
3332
3345
|
// 0.1.2-rc.1+ 浏览器会话代持:换取 Harness 会话 Cookie 供 bridge 上游携带(手机点设备不再 401 白页)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-remote-ui",
|
|
3
|
-
"version": "0.6.4-beta.
|
|
3
|
+
"version": "0.6.4-beta.9",
|
|
4
4
|
"description": "【兼容别名包】dsh-remote 旧名 dsh-remote-ui 的别名,功能与 dsh-remote-web 完全一致(同一份代码同步生成)。 Legacy alias of dsh-remote-web — identical build, kept installable while the renamed entry is pending review. 公网远程控制 DeepSeek Harness(dsh web):安装即得专属加密地址,人在外面也能用手机访问电脑上的 dsh——无需同一局域网/WiFi、无需公网 IP 与内网穿透,全程加密;手机端 100% 还原电脑体验(对话/工具/审批/设置)。技术用户可选自建服务,流量走自己的服务器。Remote control DeepSeek Harness (dsh web) from anywhere over the public internet — install, get an encrypted URL, use it from your phone on any network (dual-half cordis plugin: Settings panel + same-origin /dsh-remote routes). (2026-09 由 dsh-remote-ui 更名 / renamed from dsh-remote-ui; dsh-remote 的 dsh web 插件半,不是纯 UI/皮肤插件)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|