dsh-remote-ui 0.6.4-beta.9 → 0.6.4
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/index.js +54 -3
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -887,7 +887,15 @@ function pluginInstalledAfterBoot() {
|
|
|
887
887
|
const pkgFile = join(dirname(dirname(here)), "package.json");
|
|
888
888
|
const mtimeMs = statSync(pkgFile).mtimeMs;
|
|
889
889
|
const bootMs = Date.now() - process.uptime() * 1000;
|
|
890
|
-
|
|
890
|
+
if (!(mtimeMs > bootMs + 2000)) return false;
|
|
891
|
+
// ⚠️ 只看时间戳会**误报**:安装器补装/在线更新会把同样的文件重写一遍(哪怕是同一个版本),
|
|
892
|
+
// 时间戳变新 → 被当成"有新插件要装载" → 弹出"需要重启/刷新"横幅(用户实测踩到:
|
|
893
|
+
// 自愈补装把 profile 副本重写了一次,运行中的旧代码就写下了"需要重启")。
|
|
894
|
+
// 真正该提示用户的只有一件事:**磁盘上的插件版本与本进程装载的版本不同**。
|
|
895
|
+
// 版本相同 → 运行中的代码就是目标版本,什么都不用做。
|
|
896
|
+
const diskVersion = String(JSON.parse(readFileSync(pkgFile, "utf8")).version || "");
|
|
897
|
+
const runningVersion = String(PLUGIN_VERSION || "");
|
|
898
|
+
return Boolean(diskVersion && runningVersion && diskVersion !== runningVersion);
|
|
891
899
|
} catch { return false; }
|
|
892
900
|
}
|
|
893
901
|
|
|
@@ -1745,7 +1753,7 @@ const PLUGIN_ID = "dsh-remote-ui";
|
|
|
1745
1753
|
const PLUGIN_LEGACY_IDS = ["dsh-remote-web"];
|
|
1746
1754
|
const PLUGIN_ALL_IDS = [PLUGIN_ID, ...PLUGIN_LEGACY_IDS];
|
|
1747
1755
|
/** 插件自身发布版本(与 dsh-remote 根包同步递增)。 */
|
|
1748
|
-
const PLUGIN_VERSION = "0.6.4
|
|
1756
|
+
const PLUGIN_VERSION = "0.6.4";
|
|
1749
1757
|
const UPDATE_LOG = ".dsh-update.log";
|
|
1750
1758
|
const UPDATE_MARKER = ".dsh-update-running";
|
|
1751
1759
|
|
|
@@ -1770,6 +1778,44 @@ async function npmLatestVersion() {
|
|
|
1770
1778
|
return "";
|
|
1771
1779
|
}
|
|
1772
1780
|
|
|
1781
|
+
/**
|
|
1782
|
+
* 语义化版本比较(只处理本仓库用到的形态:`X.Y.Z` 与 `X.Y.Z-<pre>.<n>`)。
|
|
1783
|
+
* 为什么需要它:面板判断"有没有新版本"不能只用 `latest !== current` ——
|
|
1784
|
+
* 预设版之间(beta.10 → beta.11)无法比较大小,而且预设版在 semver 里**低于**同号正式版
|
|
1785
|
+
* (0.6.4 < 0.6.4),朴素不等判断会把"已经装了预设版"误判成落后。
|
|
1786
|
+
* @returns {number} a>b → 1;a<b → -1;相等 → 0
|
|
1787
|
+
*/
|
|
1788
|
+
function compareVersions(a, b) {
|
|
1789
|
+
const parse = (v) => {
|
|
1790
|
+
const m = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/.exec(String(v || "").trim());
|
|
1791
|
+
if (!m) return null;
|
|
1792
|
+
return { nums: [Number(m[1]), Number(m[2]), Number(m[3])], pre: m[4] ? m[4].split(".") : null };
|
|
1793
|
+
};
|
|
1794
|
+
const x = parse(a);
|
|
1795
|
+
const y = parse(b);
|
|
1796
|
+
if (!x || !y) return null; // 无法解析 → 交给调用方保守处理
|
|
1797
|
+
for (let i = 0; i < 3; i += 1) {
|
|
1798
|
+
if (x.nums[i] !== y.nums[i]) return x.nums[i] > y.nums[i] ? 1 : -1;
|
|
1799
|
+
}
|
|
1800
|
+
if (!x.pre && !y.pre) return 0;
|
|
1801
|
+
if (!x.pre) return 1; // 有预设版 < 无预设版(semver §11)
|
|
1802
|
+
if (!y.pre) return -1;
|
|
1803
|
+
const len = Math.max(x.pre.length, y.pre.length);
|
|
1804
|
+
for (let i = 0; i < len; i += 1) {
|
|
1805
|
+
const p1 = x.pre[i];
|
|
1806
|
+
const p2 = y.pre[i];
|
|
1807
|
+
if (p1 === undefined) return -1;
|
|
1808
|
+
if (p2 === undefined) return 1;
|
|
1809
|
+
const n1 = /^\d+$/.test(p1) ? Number(p1) : null;
|
|
1810
|
+
const n2 = /^\d+$/.test(p2) ? Number(p2) : null;
|
|
1811
|
+
if (n1 !== null && n2 !== null) { if (n1 !== n2) return n1 > n2 ? 1 : -1; continue; }
|
|
1812
|
+
if (n1 !== null) return -1; // 数字标识符 < 字母标识符
|
|
1813
|
+
if (n2 !== null) return 1;
|
|
1814
|
+
if (p1 !== p2) return p1 > p2 ? 1 : -1;
|
|
1815
|
+
}
|
|
1816
|
+
return 0;
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1773
1819
|
/** 以 detached 子进程执行 `npx --yes <UPDATE_SPEC>`(env 可覆盖 npm 源/更新通道)。 */
|
|
1774
1820
|
function spawnUpdater(relayDir, extraEnv) {
|
|
1775
1821
|
const log = join(relayDir, UPDATE_LOG);
|
|
@@ -2848,7 +2894,12 @@ function registerRoutes(ctx, relayDir) {
|
|
|
2848
2894
|
handler: async (_req, res) => {
|
|
2849
2895
|
const latest = await npmLatestVersion();
|
|
2850
2896
|
const current = PLUGIN_VERSION;
|
|
2851
|
-
|
|
2897
|
+
// 正规比较:注册表版本**严格大于**本地版本才算有更新。
|
|
2898
|
+
// 这样 0.6.4 < 0.6.4(正式版发布后预设版会正确提示升级),
|
|
2899
|
+
// 而 0.6.4-beta.10 < 0.6.4 也能正确判断;解析不了时退回朴素不等(保守提示)。
|
|
2900
|
+
const cmp = compareVersions(latest, current);
|
|
2901
|
+
const outdated = cmp === null ? Boolean(latest && latest !== current) : cmp > 0;
|
|
2902
|
+
sendJson(res, 200, { ok: true, current, latest, outdated });
|
|
2852
2903
|
},
|
|
2853
2904
|
},
|
|
2854
2905
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-remote-ui",
|
|
3
|
-
"version": "0.6.4
|
|
3
|
+
"version": "0.6.4",
|
|
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",
|