@mrrisega/dsh-remote 0.3.7 → 0.3.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/dsh-setup.mjs +54 -42
- package/package.json +1 -1
package/dsh-setup.mjs
CHANGED
|
@@ -469,22 +469,23 @@ 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 内的固定本地目录(
|
|
472
|
+
/** 插件在 profile 内的固定本地目录(安装时整目录拷贝)。 */
|
|
473
473
|
const PLUGIN_LOCAL_DIR = "dsh-remote-ui-plugin";
|
|
474
|
-
/** 插件 node 半入口(相对 profile 目录;加载器按 '.' 开头在配置文件旁解析)。 */
|
|
475
|
-
const PLUGIN_ENTRY_REL = `./${PLUGIN_LOCAL_DIR}/lib/index.js`;
|
|
476
474
|
|
|
477
475
|
/**
|
|
478
|
-
* include 块。
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
*
|
|
476
|
+
* include 块。name 必须是【裸包名】'dsh-remote-ui':
|
|
477
|
+
* - 加载器据此 import 节点半(dsh-remote-ui 由 node_modules 链接解析);
|
|
478
|
+
* - dsh 客户端模块系统(@deepseek-ai/dsh-client-modules)用 require.resolve(
|
|
479
|
+
* '<name>/package.json') 从 profile 解析该包并读取 package.json 的
|
|
480
|
+
* dsh.client 声明 → 注入浏览器半(设置面板 UI)。相对文件路径入口只会加载
|
|
481
|
+
* 节点半、不会注入 UI —— 0.3.7/0.3.8 曾因此丢设置页。
|
|
482
|
+
* 链接由安装器自建(node_modules/dsh-remote-ui → 拷贝出的目录),不依赖 pnpm/npm。
|
|
482
483
|
*/
|
|
483
484
|
function pluginBlock(relayDir) {
|
|
484
485
|
return `${PLUGIN_MARKER_START}
|
|
485
486
|
- insert:
|
|
486
487
|
- id: dsh-remote-ui
|
|
487
|
-
name: '
|
|
488
|
+
name: 'dsh-remote-ui'
|
|
488
489
|
config:
|
|
489
490
|
relayDir: '${relayDir}'
|
|
490
491
|
${PLUGIN_MARKER_END}`;
|
|
@@ -547,35 +548,41 @@ function copyPluginIntoProfile(profileDir, pluginDir) {
|
|
|
547
548
|
fs.rmSync(dest, { recursive: true, force: true });
|
|
548
549
|
fs.cpSync(pluginDir, dest, {
|
|
549
550
|
recursive: true,
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
551
|
+
// 注意:插件源(npx 缓存 / npm 全局)本身就位于某个 node_modules 之下,
|
|
552
|
+
// 过滤必须基于“相对插件目录”的路径片段,绝不能整条 src 路径包含判断,
|
|
553
|
+
// 否则会把插件文件全过滤掉、拷出空目录(此前反复“插件入口缺失”的总根因)。
|
|
554
|
+
filter: (src) => {
|
|
555
|
+
if (src === pluginDir) return true;
|
|
556
|
+
const rel = path.relative(pluginDir, src);
|
|
557
|
+
return !String(rel).split(path.sep).some((seg) => seg === "node_modules" || seg === ".git" || seg === ".DS_Store");
|
|
558
|
+
}
|
|
554
559
|
});
|
|
555
560
|
return dest;
|
|
556
561
|
}
|
|
557
562
|
|
|
558
|
-
/**
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
function cleanupLegacyPluginState(profileDir, pkgFile) {
|
|
564
|
-
let changed = false;
|
|
563
|
+
/** 把插件挂到 <profile>/node_modules/dsh-remote-ui(裸包名解析需要),指向拷贝目录;缺失/指错时重建。 */
|
|
564
|
+
function ensurePluginLinked(profileDir, pluginLocalDir) {
|
|
565
|
+
const nmDir = path.join(profileDir, "node_modules");
|
|
566
|
+
const nmPlugin = path.join(nmDir, "dsh-remote-ui");
|
|
567
|
+
fs.mkdirSync(nmDir, { recursive: true });
|
|
565
568
|
try {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
fs.writeFileSync(pkgFile, JSON.stringify(pkg, null, 2) + "\n");
|
|
570
|
-
changed = true;
|
|
571
|
-
}
|
|
572
|
-
} catch { /* 无 package.json 或损坏则跳过 */ }
|
|
569
|
+
if (fs.realpathSync(nmPlugin) === pluginLocalDir) return false;
|
|
570
|
+
} catch { /* 缺失/悬空 → 重建 */ }
|
|
571
|
+
try { fs.rmSync(nmPlugin, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
573
572
|
try {
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
}
|
|
578
|
-
return
|
|
573
|
+
fs.symlinkSync(pluginLocalDir, nmPlugin, "dir");
|
|
574
|
+
} catch {
|
|
575
|
+
fs.cpSync(pluginLocalDir, nmPlugin, { recursive: true });
|
|
576
|
+
}
|
|
577
|
+
try { return fs.realpathSync(nmPlugin) === pluginLocalDir; } catch { return false; }
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/** package.json 写入 file: 依赖(让后续任何 pnpm/npm install 也认可该插件,不会删链接)。 */
|
|
581
|
+
function declarePluginDep(pkgFile) {
|
|
582
|
+
const pkg = JSON.parse(fs.readFileSync(pkgFile, "utf8"));
|
|
583
|
+
pkg.dependencies = pkg.dependencies || {};
|
|
584
|
+
pkg.dependencies["dsh-remote-ui"] = `file:./${PLUGIN_LOCAL_DIR}`;
|
|
585
|
+
fs.writeFileSync(pkgFile, JSON.stringify(pkg, null, 2) + "\n");
|
|
579
586
|
}
|
|
580
587
|
|
|
581
588
|
async function pluginCmd(argv) {
|
|
@@ -610,21 +617,25 @@ async function pluginCmd(argv) {
|
|
|
610
617
|
console.log("ℹ patch 中未发现 dsh-remote-ui 条目。");
|
|
611
618
|
}
|
|
612
619
|
fs.rmSync(path.join(profileDir, PLUGIN_LOCAL_DIR), { recursive: true, force: true });
|
|
613
|
-
|
|
614
|
-
|
|
620
|
+
fs.rmSync(path.join(profileDir, "node_modules", "dsh-remote-ui"), { recursive: true, force: true });
|
|
621
|
+
try {
|
|
622
|
+
const pkg = JSON.parse(fs.readFileSync(pkgFile, "utf8"));
|
|
623
|
+
if (pkg.dependencies) delete pkg.dependencies["dsh-remote-ui"];
|
|
624
|
+
fs.writeFileSync(pkgFile, JSON.stringify(pkg, null, 2) + "\n");
|
|
625
|
+
} catch { /* ignore */ }
|
|
615
626
|
console.log("✅ 卸载完成。重启 dsh web 生效。");
|
|
616
627
|
return;
|
|
617
628
|
}
|
|
618
629
|
|
|
619
|
-
//
|
|
620
|
-
//
|
|
630
|
+
// 安装 = 拷贝完整插件目录 + 写裸名 include + 自建 node_modules 链接 + 声明 file: 依赖。
|
|
631
|
+
// 全程不跑 pnpm/npm;但链接与依赖双保险,任何包管理器之后 install 也不会破坏它。
|
|
621
632
|
const pluginLocalDir = copyPluginIntoProfile(profileDir, pluginDir);
|
|
622
633
|
const entryFile = path.join(pluginLocalDir, "lib", "index.js");
|
|
623
634
|
if (!fs.existsSync(entryFile)) {
|
|
624
|
-
console.error(`❌ 插件入口缺失:${entryFile}
|
|
635
|
+
console.error(`❌ 插件入口缺失:${entryFile}(本包不完整?请用官方源重装:npx --registry=https://registry.npmjs.org @mrrisega/dsh-remote@latest)`);
|
|
625
636
|
process.exit(1);
|
|
626
637
|
}
|
|
627
|
-
console.log(`✅ 插件已拷贝到 ${pluginLocalDir}
|
|
638
|
+
console.log(`✅ 插件已拷贝到 ${pluginLocalDir}`);
|
|
628
639
|
|
|
629
640
|
// 先清掉旧条目(含旧版无标记条目),再写入带标记的新块,保证不重复。
|
|
630
641
|
// 关键:先清除默认的 [] 空文档占位行,否则拼接出的 YAML 非法,dsh web 启动即崩。
|
|
@@ -632,12 +643,13 @@ async function pluginCmd(argv) {
|
|
|
632
643
|
const base = normalizePatchBase(stripped);
|
|
633
644
|
const block = pluginBlock(CONFIG_DIR);
|
|
634
645
|
fs.writeFileSync(patchFile, (base ? base + "\n" : "") + block + "\n");
|
|
635
|
-
console.log(`✅ 已写入 ${patchFile}
|
|
646
|
+
console.log(`✅ 已写入 ${patchFile}(裸名 include:dsh-remote-ui → 节点半 + 浏览器半均生效)`);
|
|
636
647
|
|
|
637
|
-
//
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
648
|
+
declarePluginDep(pkgFile); // package.json 声明 file: 依赖(后端各类 install 不误删)
|
|
649
|
+
const linked = ensurePluginLinked(profileDir, pluginLocalDir); // 自建 node_modules 链接
|
|
650
|
+
console.log(linked
|
|
651
|
+
? `✅ 已建立 node_modules/dsh-remote-ui → ${pluginLocalDir}(免包管理器即可解析)`
|
|
652
|
+
: "✅ node_modules/dsh-remote-ui 已就绪");
|
|
641
653
|
|
|
642
654
|
console.log(`✅ 插件安装完成。配置目录: ${CONFIG_DIR}`);
|
|
643
655
|
console.log(" 重启 dsh web(或重开 profile)后,在「设置 → 远程控制」查看面板。");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrrisega/dsh-remote",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
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",
|