@mrrisega/dsh-remote 0.3.2 → 0.3.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.
Files changed (2) hide show
  1. package/dsh-setup.mjs +51 -9
  2. package/package.json +1 -1
package/dsh-setup.mjs CHANGED
@@ -469,6 +469,8 @@ async function setup(argv) {
469
469
  // ---------- plugin:安装/卸载 dsh web 远程控制插件 ----------
470
470
  const PLUGIN_MARKER_START = "# >>> dsh-remote-ui (managed by dsh-remote plugin; do not edit)";
471
471
  const PLUGIN_MARKER_END = "# <<< dsh-remote-ui";
472
+ /** 插件在 profile 内的固定本地目录(安装时整目录拷贝,file: 引用;不依赖 pnpm 的 link:)。 */
473
+ const PLUGIN_LOCAL_DIR = "dsh-remote-ui-plugin";
472
474
 
473
475
  function pluginBlock(relayDir) {
474
476
  return `${PLUGIN_MARKER_START}
@@ -512,13 +514,48 @@ function stripPluginEntries(patch) {
512
514
  return out.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd() + "\n";
513
515
  }
514
516
 
515
- /** 在 profile 目录执行依赖安装(pnpm 优先)。 */
517
+ /**
518
+ * 归一化 patch 基座:去掉 dsh 新 profile 默认的空文档占位行 `[]`。
519
+ * 默认 cordis.patch.yml 是「顶部注释 + []」,若保留 [] 再往下拼 `- insert:`,
520
+ * YAML 会报 “end of the stream or a document separator is expected”(dsh web 启动即崩)。
521
+ * 返回内容不含结尾换行;[] 行只在独立成行时视为占位,不影响真正的条目。
522
+ */
523
+ function normalizePatchBase(patch) {
524
+ return String(patch ?? "")
525
+ .split("\n")
526
+ .filter((l) => !/^\[\s*\]\s*$/.test(l))
527
+ .join("\n")
528
+ .replace(/\n{3,}/g, "\n\n")
529
+ .trimEnd();
530
+ }
531
+
532
+ /** 在 profile 目录执行依赖安装(pnpm 优先,npm 兜底)。 */
516
533
  function installProfileDeps(profileDir) {
517
534
  const pm = sh("command -v pnpm >/dev/null 2>&1 && echo pnpm || echo npm").stdout.trim() || "npm";
518
535
  const cmd = pm === "pnpm" ? "pnpm install" : "npm install";
519
536
  return sh(cmd, 120000, profileDir);
520
537
  }
521
538
 
539
+ /**
540
+ * 把插件整目录拷贝进 profile 的固定子目录并返回该目录。
541
+ * 之所以拷贝而不是 link: 引用 npx 缓存目录:
542
+ * - link: 协议只有 pnpm 支持,npm 会报 EUNSUPPORTEDPROTOCOL(很多用户机器没装 pnpm);
543
+ * - npx 缓存目录是临时的,link 目标迟早失效。
544
+ * 拷贝后用 file: 相对依赖即可,npm/pnpm 都能解析。
545
+ */
546
+ function copyPluginIntoProfile(profileDir, pluginDir) {
547
+ const dest = path.join(profileDir, PLUGIN_LOCAL_DIR);
548
+ fs.rmSync(dest, { recursive: true, force: true });
549
+ fs.cpSync(pluginDir, dest, {
550
+ recursive: true,
551
+ filter: (src) =>
552
+ !src.includes(`${path.sep}node_modules${path.sep}`) &&
553
+ !src.includes(`${path.sep}.git${path.sep}`) &&
554
+ !src.endsWith(".DS_Store")
555
+ });
556
+ return dest;
557
+ }
558
+
522
559
  async function pluginCmd(argv) {
523
560
  const uninstall = hasFlag(argv, "--uninstall");
524
561
  const profileIdx = argv.indexOf("--profile");
@@ -554,28 +591,33 @@ async function pluginCmd(argv) {
554
591
  if (pkg.dependencies && pkg.dependencies["dsh-remote-ui"]) {
555
592
  delete pkg.dependencies["dsh-remote-ui"];
556
593
  fs.writeFileSync(pkgFile, JSON.stringify(pkg, null, 2) + "\n");
557
- console.log(`✅ 已从 ${pkgFile} 移除 dsh-remote-ui 依赖`);
594
+ fs.rmSync(path.join(profileDir, PLUGIN_LOCAL_DIR), { recursive: true, force: true });
595
+ console.log(`✅ 已从 ${pkgFile} 移除 dsh-remote-ui 依赖与本地插件目录`);
558
596
  }
559
597
  console.log(" 执行依赖更新...");
560
598
  const r = installProfileDeps(profileDir);
561
- if (!r.ok) console.warn(`⚠️ 依赖更新失败:${r.stderr.trim() || r.stdout.trim()}(请手动在 ${profileDir} 执行 pnpm install)`);
599
+ if (!r.ok) console.warn(`⚠️ 依赖更新失败:${r.stderr.trim() || r.stdout.trim()}(请手动在 ${profileDir} 执行 pnpm/npm install)`);
562
600
  console.log("✅ 卸载完成。重启 dsh web 生效。");
563
601
  return;
564
602
  }
565
603
 
566
- // 安装:写依赖 + patch
604
+ // 安装:插件整目录拷贝进 profile,以 file: 相对依赖安装(npm/pnpm 均支持;不再用 link:)。
567
605
  pkg.dependencies = pkg.dependencies || {};
568
- pkg.dependencies["dsh-remote-ui"] = `link:${pluginDir}`;
606
+ const pluginLocalDir = copyPluginIntoProfile(profileDir, pluginDir);
607
+ pkg.dependencies["dsh-remote-ui"] = `file:./${PLUGIN_LOCAL_DIR}`;
569
608
  fs.writeFileSync(pkgFile, JSON.stringify(pkg, null, 2) + "\n");
609
+ console.log(`✅ 插件已拷贝到 ${pluginLocalDir}(file: 依赖,npm/pnpm 均可安装)`);
570
610
 
571
- // 先清掉旧条目(含旧版无标记条目),再写入带标记的新块,保证不重复
611
+ // 先清掉旧条目(含旧版无标记条目),再写入带标记的新块,保证不重复。
612
+ // 关键:先清除默认的 [] 空文档占位行,否则拼接出的 YAML 非法,dsh web 启动即崩。
572
613
  const stripped = stripPluginEntries(patch);
614
+ const base = normalizePatchBase(stripped);
573
615
  const block = pluginBlock(CONFIG_DIR);
574
- fs.writeFileSync(patchFile, stripped + block + "\n");
616
+ fs.writeFileSync(patchFile, (base ? base + "\n" : "") + block + "\n");
575
617
  console.log(`✅ 已写入 ${patchFile}`);
576
- console.log(" 执行依赖更新(pnpm install)...");
618
+ console.log(" 执行依赖更新(pnpm 优先,未装 pnpm 自动用 npm)...");
577
619
  const r = installProfileDeps(profileDir);
578
- if (!r.ok) console.warn(`⚠️ 依赖更新失败:${r.stderr.trim() || r.stdout.trim()}(请手动在 ${profileDir} 执行 pnpm install)`);
620
+ if (!r.ok) console.warn(`⚠️ 依赖更新失败:${r.stderr.trim() || r.stdout.trim()}(请手动在 ${profileDir} 执行 pnpm install 或 npm install)`);
579
621
  console.log(`✅ 插件安装完成。配置目录: ${CONFIG_DIR}`);
580
622
  console.log(" 重启 dsh web(或重开 profile)后,在「设置 → 远程控制」查看面板。");
581
623
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrrisega/dsh-remote",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "手机远程控制 DeepSeek Harness · Remote control DeepSeek Harness (dsh web) from any phone browser — 100% 全功能 App 级体验:发消息、看工具执行、审批权限、改设置、管凭据,含特权操作,免内网穿透。一条命令安装 npx @mrrisega/dsh-remote。Mobile remote control for DSH, self-host or SaaS, no server needed on LAN.",
5
5
  "keywords": [
6
6
  "deepseek-harness",