dsh-remote-web 0.7.0-beta.7 → 0.7.0-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-remote-web",
3
- "version": "0.7.0-beta.7",
3
+ "version": "0.7.0-beta.8",
4
4
  "description": "公网远程控制 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",
@@ -194,7 +194,7 @@ function printHelp() {
194
194
  // 认识的参数(只给 flag 也要能装上去,所以不认识时才拦)。
195
195
  const KNOWN_FLAGS = new Set([
196
196
  "--api", "--server", "--key", "--profile",
197
- "--no-autostart", "--no-plugin", "--no-restart", "--uninstall"
197
+ "--no-autostart", "--no-plugin", "--no-restart", "--uninstall", "--force"
198
198
  ]);
199
199
 
200
200
  // ⚠️ 这一整块必须挡在 ensureRuntimeCopy() **之前**:它会往 ~/.dsh-remote 同步运行时脚本。
@@ -1139,6 +1139,30 @@ function resolveProfileDir(argv = []) {
1139
1139
  * `pluginCmd()` 时原本传的是空数组 —— 于是"指定 desktop profile"会被静默忽略、
1140
1140
  * 插件仍然装进 Web 版 profile(桌面端用户装了却看不到面板,且极难自查)。
1141
1141
  */
1142
+ /**
1143
+ * DeepSeek Harness **桌面应用**是否正在运行。
1144
+ *
1145
+ * 🔴 2026-10-11 事故:我在应用运行中改写了 `~/.dsh/profiles/desktop/` 里的插件文件,
1146
+ * 应用随即**自己退出/重启**(业主:"怎么又触发了 dsh 的关闭")。安装器自己的提示早就写着
1147
+ * 「请先**完全退出** DeepSeek Harness 应用再安装(应用独占该 profile)」—— 这条必须由程序强制,
1148
+ * 不能靠"我记得"。
1149
+ * 检测方式:macOS 上桌面应用的进程名就是 `DeepSeek`(lsof/pgrep 实测),另加 App 包路径兜底。
1150
+ */
1151
+ function dshDesktopAppRunning() {
1152
+ // 显式覆盖(测试隔离 / 探测误报时的逃生口):DSH_DESKTOP_APP_RUNNING=0|1
1153
+ const override = String(process.env.DSH_DESKTOP_APP_RUNNING || "").trim();
1154
+ if (override === "0" || override === "1") return override === "1";
1155
+ if (process.platform !== "darwin") return false;
1156
+ try {
1157
+ // 实测(2026-10-11):`pgrep -x DeepSeek` 与 `pgrep -f "...app/Contents/MacOS"` 都匹配不到,
1158
+ // 必须用下面的写法(`Contents/MacOS/DeepSeek` 或短名 `DeepSeek Harness.app` 均可命中)。
1159
+ const a = sh("pgrep -f 'Contents/MacOS/DeepSeek'");
1160
+ if (a.ok && String(a.stdout || "").trim()) return true;
1161
+ const b = sh("lsof -nP -iTCP:19387 -sTCP:LISTEN");
1162
+ return Boolean(b.ok && /LISTEN/.test(String(b.stdout || "")));
1163
+ } catch { return false; }
1164
+ }
1165
+
1142
1166
  /**
1143
1167
  * 探测本机**已存在**的 profile(可装载 = 同时有 package.json 与 cordis.patch.yml)。
1144
1168
  * desktop 排在前面:业主主用的是桌面应用,多个 profile 一起装时它是"首选/权威"那个。
@@ -2787,14 +2811,27 @@ async function pluginCmd(argv) {
2787
2811
  }
2788
2812
  let last = null;
2789
2813
  let ok = 0;
2814
+ let skippedRunning = 0;
2815
+ const force = hasFlag(argv, "--force");
2790
2816
  for (const t of targets) {
2817
+ // ⚠️ 桌面应用在运行时**绝不改写它的 profile**:应用会因此退出/重启(2026-10-11 实测事故)
2818
+ if (t.name === "desktop" && !force && dshDesktopAppRunning()) {
2819
+ console.log(`⚠️ 跳过 desktop:DeepSeek Harness 应用正在运行。`);
2820
+ console.log(` 应用独占该 profile,运行中改写会让应用自己退出/重启。请任选其一:`);
2821
+ console.log(` · 完全退出应用后重跑本命令;或`);
2822
+ console.log(` · 在应用内「插件」页安装/更新 dsh-remote-web(官方路径,装完即热加载)。`);
2823
+ console.log(` (确实要强行写入:加 --force)`);
2824
+ skippedRunning += 1;
2825
+ continue;
2826
+ }
2791
2827
  if (multi) console.log(`\n── profile: ${t.name}(${t.dir})`);
2792
2828
  const r = await pluginApplyTo(t.dir, uninstall, multi);
2793
2829
  if (r === "skip") continue;
2794
2830
  ok += 1;
2795
2831
  if (r !== undefined && r !== null) last = r;
2796
2832
  }
2797
- if (ok === 0) process.exit(1);
2833
+ if (ok === 0 && skippedRunning === 0) process.exit(1);
2834
+ if (skippedRunning > 0) console.log(`ℹ 本次跳过了 ${skippedRunning} 个 profile(应用在运行);桥与运行环境不受影响。`);
2798
2835
  return last;
2799
2836
  }
2800
2837