@mrrisega/dsh-remote 0.3.3 → 0.3.5
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/dsh-setup.mjs +63 -7
- 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}
|
|
@@ -527,13 +529,56 @@ function normalizePatchBase(patch) {
|
|
|
527
529
|
.trimEnd();
|
|
528
530
|
}
|
|
529
531
|
|
|
530
|
-
/** 在 profile 目录执行依赖安装(pnpm
|
|
532
|
+
/** 在 profile 目录执行依赖安装(pnpm 优先,npm 兜底)。 */
|
|
531
533
|
function installProfileDeps(profileDir) {
|
|
532
534
|
const pm = sh("command -v pnpm >/dev/null 2>&1 && echo pnpm || echo npm").stdout.trim() || "npm";
|
|
533
535
|
const cmd = pm === "pnpm" ? "pnpm install" : "npm install";
|
|
534
536
|
return sh(cmd, 120000, profileDir);
|
|
535
537
|
}
|
|
536
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
|
+
|
|
559
|
+
/**
|
|
560
|
+
* 兜底:确保 dsh 能从 profile 的 node_modules 解析到 dsh-remote-ui。
|
|
561
|
+
* 部分机器上 pnpm/npm 可能因网络、锁文件或旧 node_modules 布局没真正放下链接,
|
|
562
|
+
* 导致 dsh web 启动报 "Cannot find package 'dsh-remote-ui'"。这里直接自建链接/拷贝,
|
|
563
|
+
* 保证“装完就能用”,不依赖包管理器的成败。返回 true 表示本次补建了链接。
|
|
564
|
+
*/
|
|
565
|
+
function ensurePluginLinked(profileDir, pluginLocalDir) {
|
|
566
|
+
const nmPlugin = path.join(profileDir, "node_modules", "dsh-remote-ui");
|
|
567
|
+
if (fs.existsSync(nmPlugin)) return false; // 已可解析(含目标仍有效的软链)
|
|
568
|
+
try {
|
|
569
|
+
fs.mkdirSync(path.join(profileDir, "node_modules"), { recursive: true });
|
|
570
|
+
fs.symlinkSync(pluginLocalDir, nmPlugin, "dir");
|
|
571
|
+
return true;
|
|
572
|
+
} catch {
|
|
573
|
+
try {
|
|
574
|
+
fs.cpSync(pluginLocalDir, nmPlugin, { recursive: true });
|
|
575
|
+
return true;
|
|
576
|
+
} catch {
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
537
582
|
async function pluginCmd(argv) {
|
|
538
583
|
const uninstall = hasFlag(argv, "--uninstall");
|
|
539
584
|
const profileIdx = argv.indexOf("--profile");
|
|
@@ -569,19 +614,22 @@ async function pluginCmd(argv) {
|
|
|
569
614
|
if (pkg.dependencies && pkg.dependencies["dsh-remote-ui"]) {
|
|
570
615
|
delete pkg.dependencies["dsh-remote-ui"];
|
|
571
616
|
fs.writeFileSync(pkgFile, JSON.stringify(pkg, null, 2) + "\n");
|
|
572
|
-
|
|
617
|
+
fs.rmSync(path.join(profileDir, PLUGIN_LOCAL_DIR), { recursive: true, force: true });
|
|
618
|
+
console.log(`✅ 已从 ${pkgFile} 移除 dsh-remote-ui 依赖与本地插件目录`);
|
|
573
619
|
}
|
|
574
620
|
console.log(" 执行依赖更新...");
|
|
575
621
|
const r = installProfileDeps(profileDir);
|
|
576
|
-
if (!r.ok) console.warn(`⚠️ 依赖更新失败:${r.stderr.trim() || r.stdout.trim()}(请手动在 ${profileDir} 执行 pnpm install)`);
|
|
622
|
+
if (!r.ok) console.warn(`⚠️ 依赖更新失败:${r.stderr.trim() || r.stdout.trim()}(请手动在 ${profileDir} 执行 pnpm/npm install)`);
|
|
577
623
|
console.log("✅ 卸载完成。重启 dsh web 生效。");
|
|
578
624
|
return;
|
|
579
625
|
}
|
|
580
626
|
|
|
581
|
-
//
|
|
627
|
+
// 安装:插件整目录拷贝进 profile,以 file: 相对依赖安装(npm/pnpm 均支持;不再用 link:)。
|
|
582
628
|
pkg.dependencies = pkg.dependencies || {};
|
|
583
|
-
|
|
629
|
+
const pluginLocalDir = copyPluginIntoProfile(profileDir, pluginDir);
|
|
630
|
+
pkg.dependencies["dsh-remote-ui"] = `file:./${PLUGIN_LOCAL_DIR}`;
|
|
584
631
|
fs.writeFileSync(pkgFile, JSON.stringify(pkg, null, 2) + "\n");
|
|
632
|
+
console.log(`✅ 插件已拷贝到 ${pluginLocalDir}(file: 依赖,npm/pnpm 均可安装)`);
|
|
585
633
|
|
|
586
634
|
// 先清掉旧条目(含旧版无标记条目),再写入带标记的新块,保证不重复。
|
|
587
635
|
// 关键:先清除默认的 [] 空文档占位行,否则拼接出的 YAML 非法,dsh web 启动即崩。
|
|
@@ -590,9 +638,17 @@ async function pluginCmd(argv) {
|
|
|
590
638
|
const block = pluginBlock(CONFIG_DIR);
|
|
591
639
|
fs.writeFileSync(patchFile, (base ? base + "\n" : "") + block + "\n");
|
|
592
640
|
console.log(`✅ 已写入 ${patchFile}`);
|
|
593
|
-
console.log(" 执行依赖更新(pnpm
|
|
641
|
+
console.log(" 执行依赖更新(pnpm 优先,未装 pnpm 自动用 npm)...");
|
|
594
642
|
const r = installProfileDeps(profileDir);
|
|
595
|
-
if (!r.ok)
|
|
643
|
+
if (!r.ok) {
|
|
644
|
+
console.warn(`⚠️ 包管理器依赖更新未完全成功(${(r.stderr || r.stdout || "").trim().slice(0, 300) || "未知错误"})`);
|
|
645
|
+
console.warn(" 将直接建立插件链接,不依赖包管理器,dsh web 仍可正常加载插件。");
|
|
646
|
+
}
|
|
647
|
+
// 兜底:不依赖 pnpm/npm 的成败,确保 node_modules 里能解析到 dsh-remote-ui
|
|
648
|
+
const linked = ensurePluginLinked(profileDir, pluginLocalDir);
|
|
649
|
+
console.log(linked
|
|
650
|
+
? `✅ 插件链接已就绪:${path.join(profileDir, "node_modules", "dsh-remote-ui")} → ${pluginLocalDir}`
|
|
651
|
+
: "✅ 插件依赖已就绪");
|
|
596
652
|
console.log(`✅ 插件安装完成。配置目录: ${CONFIG_DIR}`);
|
|
597
653
|
console.log(" 重启 dsh web(或重开 profile)后,在「设置 → 远程控制」查看面板。");
|
|
598
654
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrrisega/dsh-remote",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
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",
|