@dsh-sup/dsh-core-linux-x64 0.1.5-BETA.2 → 0.1.5-BETA.3

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/core.cjs +287 -150
  2. package/package.json +1 -1
package/core.cjs CHANGED
@@ -225,7 +225,7 @@ var require_version = __commonJS({
225
225
  var fs2 = require("node:fs");
226
226
  var path2 = require("node:path");
227
227
  function guardVersion() {
228
- if (true) return String("0.1.5-BETA.2");
228
+ if (true) return String("0.1.5-BETA.3");
229
229
  try {
230
230
  return JSON.parse(fs2.readFileSync(path2.join(__dirname, "..", "..", "package.json"), "utf8")).version || "unknown";
231
231
  } catch {
@@ -236,6 +236,64 @@ var require_version = __commonJS({
236
236
  }
237
237
  });
238
238
 
239
+ // src/platform/matrix.js
240
+ var require_matrix = __commonJS({
241
+ "src/platform/matrix.js"(exports2, module2) {
242
+ "use strict";
243
+ var SUPPORTED = [
244
+ { platform: "linux", arch: "x64", osTag: "linux", npmTag: "linux-x64" },
245
+ { platform: "darwin", arch: "arm64", osTag: "darwin", npmTag: "darwin-arm64" },
246
+ { platform: "darwin", arch: "x64", osTag: "darwin", npmTag: "darwin-x64" },
247
+ { platform: "win32", arch: "x64", osTag: "win", npmTag: "win-x64" }
248
+ ];
249
+ var OS_TAG = { linux: "linux", darwin: "darwin", win32: "win" };
250
+ var FRP_OS = { linux: "linux", darwin: "darwin", win32: "windows" };
251
+ var FRP_ARCH = { x64: "amd64", arm64: "arm64" };
252
+ function osTag(platform) {
253
+ return OS_TAG[platform || process.platform] || null;
254
+ }
255
+ function current(platform, arch) {
256
+ const p = platform || process.platform;
257
+ const a = arch || process.arch;
258
+ return { platform: p, arch: a, osTag: OS_TAG[p] || null, npmTag: npmTag(p, a) };
259
+ }
260
+ function npmTag(platform, arch) {
261
+ const p = platform || process.platform;
262
+ const a = arch || process.arch;
263
+ const os2 = OS_TAG[p];
264
+ if (!os2 || a !== "x64" && a !== "arm64") {
265
+ throw new Error("\u4E0D\u652F\u6301\u7684\u5E73\u53F0\u7EC4\u5408: " + p + "/" + a + "\uFF08\u4EC5 linux/darwin/win32 \xD7 x64/arm64\uFF09");
266
+ }
267
+ return os2 + "-" + a;
268
+ }
269
+ function isSupported(platform, arch) {
270
+ const p = platform || process.platform;
271
+ const a = arch || process.arch;
272
+ return !!(OS_TAG[p] && (a === "x64" || a === "arm64"));
273
+ }
274
+ function frpTag(platform, arch) {
275
+ const p = platform || process.platform;
276
+ const a = arch || process.arch;
277
+ const os2 = FRP_OS[p];
278
+ const am = FRP_ARCH[a];
279
+ if (!os2 || !am) return null;
280
+ return { os: os2, arch: am, tag: os2 + "_" + am, exe: p === "win32" };
281
+ }
282
+ function supportsProcessGroup(platform) {
283
+ return (platform || process.platform) !== "win32";
284
+ }
285
+ module2.exports = {
286
+ SUPPORTED,
287
+ osTag,
288
+ current,
289
+ npmTag,
290
+ isSupported,
291
+ frpTag,
292
+ supportsProcessGroup
293
+ };
294
+ }
295
+ });
296
+
239
297
  // src/platform/os/pidlookup.js
240
298
  var require_pidlookup = __commonJS({
241
299
  "src/platform/os/pidlookup.js"(exports2, module2) {
@@ -245,6 +303,56 @@ var require_pidlookup = __commonJS({
245
303
  var isLinux = process.platform === "linux";
246
304
  var isMac = process.platform === "darwin";
247
305
  var isWindows = process.platform === "win32";
306
+ function parseProcNetTcpInodes(txt, port) {
307
+ const inodes = /* @__PURE__ */ new Set();
308
+ for (const lineRaw of String(txt || "").split("\n")) {
309
+ const cols = lineRaw.trim().split(/\s+/);
310
+ if (cols.length < 10) continue;
311
+ const local = cols[1];
312
+ const st = cols[3];
313
+ const inode = cols[9];
314
+ if (!local || !inode) continue;
315
+ const p = local.split(":")[1];
316
+ if (st === "0A" && p && parseInt(p, 16) === port) inodes.add("socket:[" + inode + "]");
317
+ }
318
+ return inodes;
319
+ }
320
+ function parseLsofPid(out) {
321
+ for (const line of String(out || "").split("\n")) {
322
+ const m = line.trim().split(/\s+/);
323
+ if (m.length >= 2 && /^\d+$/.test(m[1])) return Number(m[1]);
324
+ }
325
+ return null;
326
+ }
327
+ function parseNetstatPid(out, port) {
328
+ const want = String(port);
329
+ for (const line of String(out || "").split("\n")) {
330
+ const parts = line.trim().split(/\s+/);
331
+ if (parts.length >= 5 && (parts[0] === "TCP" || parts[0] === "TCPv6") && parts[3] === "LISTENING") {
332
+ const lp = parts[1];
333
+ const p = lp.slice(lp.lastIndexOf(":") + 1);
334
+ if (p === want) {
335
+ const pid = Number(parts[4]);
336
+ if (Number.isInteger(pid) && pid > 0) return pid;
337
+ }
338
+ }
339
+ }
340
+ return null;
341
+ }
342
+ function parseSsPid(out) {
343
+ const m = out && /pid=(\d+)/.exec(String(out));
344
+ return m ? Number(m[1]) : null;
345
+ }
346
+ function parseWmicCommandLine(out) {
347
+ if (!out) return null;
348
+ const m = /CommandLine=([\s\S]*)/.exec(String(out));
349
+ const v = m ? m[1].trim() : "";
350
+ return v || null;
351
+ }
352
+ function parsePowerShellCommandLine(out) {
353
+ const v = out ? String(out).trim() : "";
354
+ return v || null;
355
+ }
248
356
  function linuxListeningInodes(port) {
249
357
  const inodes = /* @__PURE__ */ new Set();
250
358
  for (const f of ["/proc/net/tcp", "/proc/net/tcp6"]) {
@@ -254,16 +362,7 @@ var require_pidlookup = __commonJS({
254
362
  } catch {
255
363
  continue;
256
364
  }
257
- for (const lineRaw of txt.split("\n")) {
258
- const cols = lineRaw.trim().split(/\s+/);
259
- if (cols.length < 10) continue;
260
- const local = cols[1];
261
- const st = cols[3];
262
- const inode = cols[9];
263
- if (!local || !inode) continue;
264
- const p = local.split(":")[1];
265
- if (st === "0A" && p && parseInt(p, 16) === port) inodes.add("socket:[" + inode + "]");
266
- }
365
+ for (const x of parseProcNetTcpInodes(txt, port)) inodes.add(x);
267
366
  }
268
367
  return inodes;
269
368
  }
@@ -297,10 +396,7 @@ var require_pidlookup = __commonJS({
297
396
  try {
298
397
  const out = ex2.runOut("lsof", ["-nP", "-iTCP:" + port, "-sTCP:LISTEN"], { timeoutMs: 3e3 });
299
398
  if (!out) return null;
300
- for (const line of out.split("\n")) {
301
- const m = line.trim().split(/\s+/);
302
- if (m.length >= 2 && /^\d+$/.test(m[1])) return Number(m[1]);
303
- }
399
+ return parseLsofPid(out);
304
400
  } catch {
305
401
  }
306
402
  return null;
@@ -309,18 +405,7 @@ var require_pidlookup = __commonJS({
309
405
  try {
310
406
  const out = ex2.runOut("netstat", ["-ano"], { timeoutMs: 3e3 });
311
407
  if (!out) return null;
312
- const want = String(port);
313
- for (const line of out.split("\n")) {
314
- const parts = line.trim().split(/\s+/);
315
- if (parts.length >= 5 && (parts[0] === "TCP" || parts[0] === "TCPv6") && parts[3] === "LISTENING") {
316
- const lp = parts[1];
317
- const p = lp.slice(lp.lastIndexOf(":") + 1);
318
- if (p === want) {
319
- const pid = Number(parts[4]);
320
- if (Number.isInteger(pid) && pid > 0) return pid;
321
- }
322
- }
323
- }
408
+ return parseNetstatPid(out, port);
324
409
  } catch {
325
410
  }
326
411
  return null;
@@ -330,8 +415,8 @@ var require_pidlookup = __commonJS({
330
415
  for (const ssBin of candidates) {
331
416
  try {
332
417
  const out = ex2.runOut(ssBin, ["-tlnHp", "sport = :" + port], { timeoutMs: 3e3 });
333
- const m = out && /pid=(\d+)/.exec(out);
334
- if (m) return Number(m[1]);
418
+ const pid = parseSsPid(out);
419
+ if (pid !== null) return pid;
335
420
  } catch {
336
421
  }
337
422
  }
@@ -375,15 +460,12 @@ var require_pidlookup = __commonJS({
375
460
  }
376
461
  if (isWindows) {
377
462
  const out = ex2.runOut("wmic", ["process", "where", "ProcessId=" + pid, "get", "CommandLine", "/value"], { timeoutMs: 5e3 });
378
- if (out) {
379
- const m = /CommandLine=([\s\S]*)/.exec(out);
380
- const viaWmic = m ? m[1].trim() : "";
381
- if (viaWmic) return viaWmic;
382
- }
463
+ const viaWmic = parseWmicCommandLine(out);
464
+ if (viaWmic) return viaWmic;
383
465
  {
384
466
  const ps = "(Get-CimInstance Win32_Process -Filter 'ProcessId=" + pid + "').CommandLine";
385
467
  const o = ex2.runOut("powershell", ["-NoProfile", "-NonInteractive", "-Command", ps], { timeoutMs: 5e3 });
386
- return o ? o.trim() || null : null;
468
+ return parsePowerShellCommandLine(o);
387
469
  }
388
470
  }
389
471
  return null;
@@ -436,7 +518,24 @@ var require_pidlookup = __commonJS({
436
518
  }
437
519
  return out;
438
520
  }
439
- module2.exports = { findListeningPid, isAlive, readCmdline, isDshCmdline, pgrepList };
521
+ function normCmdline(s) {
522
+ return String(s || "").replace(/\\/g, "/");
523
+ }
524
+ module2.exports = {
525
+ findListeningPid,
526
+ isAlive,
527
+ readCmdline,
528
+ normCmdline,
529
+ isDshCmdline,
530
+ pgrepList,
531
+ // 平台输出纯解析器(2026-09-13 抽出:使其可在任意宿主上穷举;生产代码直接调用,非平行实现)
532
+ parseProcNetTcpInodes,
533
+ parseLsofPid,
534
+ parseNetstatPid,
535
+ parseSsPid,
536
+ parseWmicCommandLine,
537
+ parsePowerShellCommandLine
538
+ };
440
539
  }
441
540
  });
442
541
 
@@ -565,7 +664,7 @@ var require_daemon_lifecycle = __commonJS({
565
664
  try {
566
665
  const pid = pidlook.findListeningPid(this.ctlPort);
567
666
  if (!pid) return null;
568
- const cmd2 = pidlook.readCmdline(pid) || "";
667
+ const cmd2 = pidlook.normCmdline(pidlook.readCmdline(pid) || "");
569
668
  return this._cmdMarks.some((mk) => mk && cmd2.indexOf(mk) >= 0) ? pid : null;
570
669
  } catch {
571
670
  return null;
@@ -865,13 +964,14 @@ var require_exec_path = __commonJS({
865
964
  }
866
965
  return null;
867
966
  }
868
- function standardDirs(platform, home) {
967
+ function standardDirs(platform, home, env) {
869
968
  const pl = platform || process.platform;
870
969
  const h = home || os2.homedir();
970
+ const e = env || process.env;
871
971
  const dirs = [];
872
972
  if (pl === "win32") {
873
- if (process.env.APPDATA) dirs.push(path2.join(process.env.APPDATA, "npm"));
874
- if (process.env.LOCALAPPDATA) dirs.push(path2.join(process.env.LOCALAPPDATA, "Programs", "dsh-supervisor"));
973
+ if (e.APPDATA) dirs.push(path2.join(e.APPDATA, "npm"));
974
+ if (e.LOCALAPPDATA) dirs.push(path2.join(e.LOCALAPPDATA, "Programs", "dsh-supervisor"));
875
975
  dirs.push(path2.join(h, ".local", "bin"));
876
976
  } else {
877
977
  dirs.push(path2.join(h, ".local", "bin"));
@@ -883,8 +983,9 @@ var require_exec_path = __commonJS({
883
983
  }
884
984
  return dirs;
885
985
  }
886
- function inPath(base, platform) {
887
- const raw = process.env.PATH || process.env.Path || "";
986
+ function inPath(base, platform, env) {
987
+ const e = env || process.env;
988
+ const raw = e.PATH || e.Path || "";
888
989
  for (const d of raw.split(path2.delimiter)) {
889
990
  if (!d) continue;
890
991
  const hit = firstExecutable(d, base, platform);
@@ -894,35 +995,42 @@ var require_exec_path = __commonJS({
894
995
  }
895
996
  function resolveExecutable(base, opts) {
896
997
  const o = opts || {};
897
- if (o.envVar && process.env[o.envVar]) {
898
- const v = process.env[o.envVar];
998
+ const pl = o.platform;
999
+ const env = o.env;
1000
+ const E = env || process.env;
1001
+ if (o.envVar && E[o.envVar]) {
1002
+ const v = E[o.envVar];
899
1003
  try {
900
1004
  if (fs2.statSync(v).isFile()) return v;
901
1005
  } catch {
902
1006
  }
903
1007
  }
904
- const inPathHit = inPath(base);
1008
+ const inPathHit = inPath(base, pl, env);
905
1009
  if (inPathHit) return inPathHit;
906
- for (const d of [...o.extraDirs || [], ...standardDirs()]) {
907
- const hit = firstExecutable(d, base);
1010
+ for (const d of [...o.extraDirs || [], ...standardDirs(pl, void 0, env)]) {
1011
+ const hit = firstExecutable(d, base, pl);
908
1012
  if (hit) return hit;
909
1013
  }
910
1014
  return null;
911
1015
  }
912
1016
  function npxBin(opts) {
913
- const pl = opts && opts.platform || process.platform;
1017
+ const o = opts || {};
1018
+ const pl = o.platform || process.platform;
1019
+ const env = o.env || process.env;
914
1020
  if (pl !== "win32") return "npx";
915
- const resolved = resolveExecutable("npx", { extraDirs: [
916
- process.env.APPDATA ? path2.join(process.env.APPDATA, "npm") : null
1021
+ const resolved = resolveExecutable("npx", { platform: pl, env, extraDirs: [
1022
+ env.APPDATA ? path2.join(env.APPDATA, "npm") : null
917
1023
  ].filter(Boolean) });
918
1024
  if (resolved) return resolved;
919
1025
  return "npx.cmd";
920
1026
  }
921
1027
  function npmBin(opts) {
922
- const pl = opts && opts.platform || process.platform;
1028
+ const o = opts || {};
1029
+ const pl = o.platform || process.platform;
1030
+ const env = o.env || process.env;
923
1031
  if (pl !== "win32") return "npm";
924
- const resolved = resolveExecutable("npm", { extraDirs: [
925
- process.env.APPDATA ? path2.join(process.env.APPDATA, "npm") : null
1032
+ const resolved = resolveExecutable("npm", { platform: pl, env, extraDirs: [
1033
+ env.APPDATA ? path2.join(env.APPDATA, "npm") : null
926
1034
  ].filter(Boolean) });
927
1035
  if (resolved) return resolved;
928
1036
  return "npm.cmd";
@@ -1171,53 +1279,54 @@ var require_notify = __commonJS({
1171
1279
  "src/platform/os/notify.js"(exports2, module2) {
1172
1280
  "use strict";
1173
1281
  var { spawn } = require("node:child_process");
1174
- var isLinux = process.platform === "linux";
1175
- var isMac = process.platform === "darwin";
1176
- var isWindows = process.platform === "win32";
1282
+ function appleScriptString(s) {
1283
+ return JSON.stringify(String(s));
1284
+ }
1285
+ function powerShellString(s) {
1286
+ return '"' + String(s).replace(/"/g, '""') + '"';
1287
+ }
1288
+ function notifyCommand(platform, title, body) {
1289
+ const pl = platform || process.platform;
1290
+ const t = String(title == null ? "" : title);
1291
+ const b = String(body == null ? "" : body);
1292
+ if (pl === "linux") {
1293
+ return { cmd: "notify-send", args: ["-a", "dsh-supervisor", t, b] };
1294
+ }
1295
+ if (pl === "darwin") {
1296
+ const script = "display notification " + appleScriptString(b) + " with title " + appleScriptString(t);
1297
+ return { cmd: "osascript", args: ["-e", script] };
1298
+ }
1299
+ if (pl === "win32") {
1300
+ const ps = [
1301
+ '[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null',
1302
+ '[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null',
1303
+ "$n = New-Object System.Windows.Forms.NotifyIcon",
1304
+ "$n.Icon = [System.Drawing.SystemIcons]::Information",
1305
+ "$n.Visible = $true",
1306
+ "$n.ShowBalloonTip(4000, " + powerShellString(t) + ", " + powerShellString(b) + ", [System.Windows.Forms.ToolTipIcon]::None)",
1307
+ "Start-Sleep -Milliseconds 4200",
1308
+ "$n.Dispose(); $n.Visible = $false"
1309
+ ].join("; ");
1310
+ return { cmd: "powershell", args: ["-NoProfile", "-NonInteractive", "-Command", ps] };
1311
+ }
1312
+ return null;
1313
+ }
1177
1314
  function notify(title, body, onError) {
1178
1315
  try {
1179
- if (isLinux) {
1180
- const c = spawn("notify-send", ["-a", "dsh-supervisor", String(title), String(body)], { stdio: "ignore", detached: true });
1181
- c.on("error", () => {
1182
- if (onError) onError();
1183
- });
1184
- c.unref();
1185
- return true;
1186
- }
1187
- if (isMac) {
1188
- const script = "display notification " + JSON.stringify(String(body)) + " with title " + JSON.stringify(String(title));
1189
- const c = spawn("osascript", ["-e", script], { stdio: "ignore" });
1190
- c.on("error", () => {
1191
- if (onError) onError();
1192
- });
1193
- c.unref();
1194
- return true;
1195
- }
1196
- if (isWindows) {
1197
- const ps = [
1198
- '[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null',
1199
- '[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null',
1200
- "$n = New-Object System.Windows.Forms.NotifyIcon",
1201
- "$n.Icon = [System.Drawing.SystemIcons]::Information",
1202
- "$n.Visible = $true",
1203
- "$n.ShowBalloonTip(4000, " + JSON.stringify(String(title)) + ", " + JSON.stringify(String(body)) + ", [System.Windows.Forms.ToolTipIcon]::None)",
1204
- "Start-Sleep -Milliseconds 4200",
1205
- "$n.Dispose(); $n.Visible = $false"
1206
- ].join("; ");
1207
- const c = spawn("powershell", ["-NoProfile", "-NonInteractive", "-Command", ps], { stdio: "ignore" });
1208
- c.on("error", () => {
1209
- if (onError) onError();
1210
- });
1211
- c.unref();
1212
- return true;
1213
- }
1214
- return false;
1316
+ const plan = notifyCommand(process.platform, title, body);
1317
+ if (!plan) return false;
1318
+ const c = spawn(plan.cmd, plan.args, { stdio: "ignore", detached: process.platform === "linux" });
1319
+ c.on("error", () => {
1320
+ if (onError) onError();
1321
+ });
1322
+ c.unref();
1323
+ return true;
1215
1324
  } catch {
1216
1325
  if (onError) onError();
1217
1326
  return false;
1218
1327
  }
1219
1328
  }
1220
- module2.exports = { notify };
1329
+ module2.exports = { notify, notifyCommand, appleScriptString, powerShellString };
1221
1330
  }
1222
1331
  });
1223
1332
 
@@ -1226,9 +1335,16 @@ var require_browser = __commonJS({
1226
1335
  "src/platform/os/browser.js"(exports2, module2) {
1227
1336
  "use strict";
1228
1337
  var { spawn } = require("node:child_process");
1338
+ function openCommand(platform, url) {
1339
+ const pl = platform || process.platform;
1340
+ if (pl === "darwin") return { cmd: "open", args: [url] };
1341
+ if (pl === "win32") return { cmd: "cmd", args: ["/c", "start", "", url] };
1342
+ return { cmd: "xdg-open", args: [url] };
1343
+ }
1229
1344
  function open(url) {
1230
1345
  try {
1231
- const p = process.platform === "darwin" ? spawn("open", [url], { detached: true, stdio: "ignore" }) : process.platform === "win32" ? spawn("cmd", ["/c", "start", "", url], { detached: true, stdio: "ignore" }) : spawn("xdg-open", [url], { detached: true, stdio: "ignore" });
1346
+ const c = openCommand(process.platform, url);
1347
+ const p = spawn(c.cmd, c.args, { detached: true, stdio: "ignore" });
1232
1348
  p.on("error", () => {
1233
1349
  });
1234
1350
  p.unref();
@@ -1255,6 +1371,37 @@ var require_browser = __commonJS({
1255
1371
  child.unref();
1256
1372
  return child;
1257
1373
  }
1374
+ function isolatedPlan(platform, url, opts) {
1375
+ const o = opts || {};
1376
+ const antiArgs = o.antiArgs || [];
1377
+ const profileDir = o.profileDir;
1378
+ const pl = platform || process.platform;
1379
+ if (pl === "darwin") {
1380
+ return { kind: "single", bin: "open", args: ["-na", "Google Chrome", "--args", ...antiArgs], isolated: true, label: "Google Chrome" };
1381
+ }
1382
+ if (pl === "win32") {
1383
+ return {
1384
+ kind: "single",
1385
+ bin: "cmd",
1386
+ args: ["/c", "start", "", "chrome", "--incognito", "--user-data-dir=" + profileDir, url],
1387
+ isolated: true,
1388
+ label: "chrome"
1389
+ };
1390
+ }
1391
+ return {
1392
+ kind: "chain",
1393
+ candidates: [
1394
+ { bin: "microsoft-edge", args: antiArgs, isolated: true, watch: true, envKind: "anti" },
1395
+ { bin: "microsoft-edge-stable", args: antiArgs, isolated: true, watch: true, envKind: "anti" },
1396
+ { bin: "google-chrome", args: antiArgs, isolated: true, watch: true, envKind: "anti" },
1397
+ { bin: "chromium", args: antiArgs, isolated: true, watch: true, envKind: "anti" },
1398
+ { bin: "chromium-browser", args: antiArgs, isolated: true, watch: true, envKind: "anti" },
1399
+ { bin: "firefox", args: ["--private-window", url], isolated: false, watch: true, envKind: "sys" },
1400
+ { bin: "xdg-open", args: [url], isolated: false, watch: false, envKind: "sys" }
1401
+ // 兜底:无隔离
1402
+ ]
1403
+ };
1404
+ }
1258
1405
  function launchIsolated(url, o) {
1259
1406
  const opts = o || {};
1260
1407
  const profileDir = opts.profileDir;
@@ -1263,31 +1410,20 @@ var require_browser = __commonJS({
1263
1410
  const sysEnv = opts.sysEnv || process.env;
1264
1411
  const onExit = opts.onExit;
1265
1412
  try {
1266
- if (process.platform === "darwin") {
1267
- const p = _spawnDetached("open", ["-na", "Google Chrome", "--args", ...antiArgs], antiEnv, onExit);
1268
- return { ok: !!p, bin: p ? "Google Chrome" : null, isolated: true };
1269
- }
1270
- if (process.platform === "win32") {
1271
- const p = _spawnDetached("cmd", ["/c", "start", "", "chrome", "--incognito", "--user-data-dir=" + profileDir, url], sysEnv, onExit);
1272
- return { ok: !!p, bin: p ? "chrome" : null, isolated: true };
1273
- }
1274
- const candidates = [
1275
- { bin: "microsoft-edge", args: antiArgs, env: antiEnv, isolated: true, watch: true },
1276
- { bin: "microsoft-edge-stable", args: antiArgs, env: antiEnv, isolated: true, watch: true },
1277
- { bin: "google-chrome", args: antiArgs, env: antiEnv, isolated: true, watch: true },
1278
- { bin: "chromium", args: antiArgs, env: antiEnv, isolated: true, watch: true },
1279
- { bin: "chromium-browser", args: antiArgs, env: antiEnv, isolated: true, watch: true },
1280
- { bin: "firefox", args: ["--private-window", url], env: sysEnv, isolated: false, watch: true },
1281
- { bin: "xdg-open", args: [url], env: sysEnv, isolated: false, watch: false }
1282
- // 兜底:无隔离
1283
- ];
1413
+ const plan = isolatedPlan(process.platform, url, { profileDir, antiArgs });
1414
+ if (plan.kind === "single") {
1415
+ const env = plan.bin === "open" ? antiEnv : sysEnv;
1416
+ const p = _spawnDetached(plan.bin, plan.args, env, onExit);
1417
+ return { ok: !!p, bin: p ? plan.label : null, isolated: plan.isolated };
1418
+ }
1284
1419
  let idx = 0;
1285
1420
  const tryNext = () => {
1286
- if (idx >= candidates.length) return { ok: false, bin: null, isolated: false };
1287
- const c = candidates[idx++];
1421
+ if (idx >= plan.candidates.length) return { ok: false, bin: null, isolated: false };
1422
+ const c = plan.candidates[idx++];
1423
+ const env = c.envKind === "anti" ? antiEnv : sysEnv;
1288
1424
  let child;
1289
1425
  try {
1290
- child = spawn(c.bin, c.args, { detached: true, stdio: "ignore", env: c.env || sysEnv });
1426
+ child = spawn(c.bin, c.args, { detached: true, stdio: "ignore", env: env || sysEnv });
1291
1427
  } catch {
1292
1428
  return tryNext();
1293
1429
  }
@@ -1308,7 +1444,7 @@ var require_browser = __commonJS({
1308
1444
  return { ok: false, bin: null, isolated: false };
1309
1445
  }
1310
1446
  }
1311
- module2.exports = { open, launchIsolated };
1447
+ module2.exports = { open, launchIsolated, openCommand, isolatedPlan };
1312
1448
  }
1313
1449
  });
1314
1450
 
@@ -1356,7 +1492,7 @@ var require_desktop = __commonJS({
1356
1492
  }
1357
1493
  return {
1358
1494
  platform: PLATFORM,
1359
- available: PLATFORM === "darwin" || PLATFORM === "win32",
1495
+ available: sessionAvailable(),
1360
1496
  reason: "session-scoped-by-launcher"
1361
1497
  };
1362
1498
  }
@@ -1459,6 +1595,9 @@ var require_autostart = __commonJS({
1459
1595
  guiLabel: GUI_LABEL
1460
1596
  };
1461
1597
  }
1598
+ if (!isLinux && !isMac && !isWindows) {
1599
+ return { kind: "none", unit: "unsupported", on: false, gui: false };
1600
+ }
1462
1601
  let unit = "unknown";
1463
1602
  const en = ex2.runDetail("systemctl", ["--user", "is-enabled", "dsh-supervisor.service"]);
1464
1603
  unit = String(en.stdout || en.stderr || "disabled").trim() || "disabled";
@@ -4690,6 +4829,7 @@ var require_dist = __commonJS({
4690
4829
  var fs2 = require("node:fs");
4691
4830
  var path2 = require("node:path");
4692
4831
  var net = require("node:net");
4832
+ var matrix = require_matrix();
4693
4833
  var { spawn } = require("node:child_process");
4694
4834
  var { npmBin } = require_exec_path();
4695
4835
  var registryContract = require_registry_contract();
@@ -4869,14 +5009,7 @@ var require_dist = __commonJS({
4869
5009
  * 并如实上报(见该函数的 try/catch),不会让守卫崩溃。
4870
5010
  */
4871
5011
  _platformTag() {
4872
- const osMap = { darwin: "darwin", win32: "win", linux: "linux" };
4873
- const archMap = { arm64: "arm64", x64: "x64" };
4874
- const os2 = osMap[process.platform];
4875
- const arch = archMap[process.arch];
4876
- if (!os2 || !arch) {
4877
- throw new Error("\u4E0D\u652F\u6301\u7684\u5E73\u53F0\u7EC4\u5408: " + process.platform + "/" + process.arch + "\uFF08\u4EC5 linux/darwin/win32 \xD7 x64/arm64\uFF09");
4878
- }
4879
- return os2 + "-" + arch;
5012
+ return matrix.npmTag();
4880
5013
  }
4881
5014
  /**
4882
5015
  * 探测单个 registry 的可达性 + 延迟。
@@ -7355,20 +7488,14 @@ var require_frpmgr = __commonJS({
7355
7488
  "use strict";
7356
7489
  var fs2 = require("node:fs");
7357
7490
  var path2 = require("node:path");
7491
+ var matrix = require_matrix();
7358
7492
  var http2 = require("node:http");
7359
7493
  var https = require("node:https");
7360
7494
  var { spawn } = require("node:child_process");
7361
7495
  var crypto = require("node:crypto");
7362
7496
  var FRP_VERSION = "0.61.1";
7363
7497
  function frpPlatformTag(platform, arch) {
7364
- const pl = platform || process.platform;
7365
- const ar = arch || process.arch;
7366
- const osMap = { linux: "linux", darwin: "darwin", win32: "windows" };
7367
- const archMap = { x64: "amd64", arm64: "arm64" };
7368
- const os2 = osMap[pl];
7369
- const am = archMap[ar];
7370
- if (!os2 || !am) return null;
7371
- return { os: os2, arch: am, tag: os2 + "_" + am, exe: pl === "win32" };
7498
+ return matrix.frpTag(platform, arch);
7372
7499
  }
7373
7500
  var MIRROR_PREFIXES = [
7374
7501
  "https://ghfast.top/",
@@ -7640,8 +7767,9 @@ var require_frpmgr = __commonJS({
7640
7767
  }
7641
7768
  };
7642
7769
  if (!this.frpTag) {
7643
- if (this.events) this.events.append("frpc_install_failed", { detail: "\u5F53\u524D\u5E73\u53F0\u65E0 frpc \u5B98\u65B9\u4EA7\u7269: " + process.platform + "/" + process.arch });
7644
- return { ok: false, error: "\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301 FRP\uFF08" + process.platform + "/" + process.arch + "\uFF09\uFF0C\u4EC5 linux/darwin/win32 \xD7 x64/arm64" };
7770
+ const cur = matrix.current();
7771
+ if (this.events) this.events.append("frpc_install_failed", { detail: "\u5F53\u524D\u5E73\u53F0\u65E0 frpc \u5B98\u65B9\u4EA7\u7269: " + cur.platform + "/" + cur.arch });
7772
+ return { ok: false, error: "\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301 FRP\uFF08" + cur.platform + "/" + cur.arch + "\uFF09\uFF0C\u4EC5 linux/darwin/win32 \xD7 x64/arm64" };
7645
7773
  }
7646
7774
  const asset = "frp_" + FRP_VERSION + "_" + this.frpTag.tag + ".tar.gz";
7647
7775
  const urls = downloadUrls(asset);
@@ -9139,6 +9267,7 @@ var require_instance = __commonJS({
9139
9267
  this.events = opts.events || null;
9140
9268
  this.dist = opts.dist || null;
9141
9269
  this.dshBin = opts.dshBin || "dsh";
9270
+ this.service = opts.service || service;
9142
9271
  this.instancesFile = path2.join(this.dir, "instances.json");
9143
9272
  this.instancesRoot = path2.join(path2.dirname(this.instancesFile), "instances");
9144
9273
  this.systemdDir = path2.join(os2.homedir(), ".config", "systemd", "user");
@@ -9314,7 +9443,7 @@ var require_instance = __commonJS({
9314
9443
  this.logger.info && this.logger.info("\u5DF2\u5C06\u963B\u6321 systemd-run \u7684\u6A21\u677F\u8BA9\u4F4D\uFF08\u6539\u540D\u4FDD\u7559\uFF0C\u672A\u5220\u9664\uFF09\uFF1A" + aside);
9315
9444
  if (this.events) this.events.append("systemd_template_moved_aside", { from: this.systemdTemplatePath, to: aside });
9316
9445
  }
9317
- const reloaded = service.daemonReload();
9446
+ const reloaded = this.service.daemonReload();
9318
9447
  if (reloaded === false) this.logger.warn && this.logger.warn("systemd daemon-reload \u5931\u8D25\uFF08\u4E0D\u963B\u65AD\u5B9E\u4F8B\u521B\u5EFA\uFF09");
9319
9448
  return true;
9320
9449
  } catch (e) {
@@ -9571,10 +9700,13 @@ var require_instance = __commonJS({
9571
9700
  }
9572
9701
  }
9573
9702
  const unit = "dsh-web@" + id;
9574
- service.stopUnit(unit);
9703
+ try {
9704
+ this.service.stopUnit(unit);
9705
+ } catch {
9706
+ }
9575
9707
  let stillActive = false;
9576
9708
  try {
9577
- stillActive = service.isUnitActive(unit) === true;
9709
+ stillActive = this.service.isUnitActive(unit) === true;
9578
9710
  } catch {
9579
9711
  stillActive = true;
9580
9712
  }
@@ -9992,7 +10124,7 @@ var require_instance = __commonJS({
9992
10124
  * 关键(日志实证 21:21:25):删除文件后 systemd 内存仍缓存该单元为 loaded,
9993
10125
  * 必须 daemon-reload 让 systemd 卸载其加载状态,否则 systemd-run 依然拒绝。 */
9994
10126
  _cleanStaleUnit(unit) {
9995
- service.cleanTransient(unit);
10127
+ this.service.cleanTransient(unit);
9996
10128
  this.logger.info && this.logger.info("cleaned stale transient unit: " + unit);
9997
10129
  }
9998
10130
  /** 用 systemd 启动实例(独立 transient unit/隔离环境)。沙箱注入独立 HOME/XDG/PATH/NODE_PATH。
@@ -10026,7 +10158,7 @@ var require_instance = __commonJS({
10026
10158
  }
10027
10159
  this._cleanStaleUnit("dsh-web@" + inst.id);
10028
10160
  try {
10029
- service.startTransient({ unit: "dsh-web@" + inst.id, cmd: cmdArr, env, props, workingDir });
10161
+ this.service.startTransient({ unit: "dsh-web@" + inst.id, cmd: cmdArr, env, props, workingDir });
10030
10162
  } catch (e) {
10031
10163
  const msg = "systemd \u542F\u52A8\u5931\u8D25: " + (e.message || e);
10032
10164
  inst.state.lastError = msg;
@@ -10073,7 +10205,7 @@ var require_instance = __commonJS({
10073
10205
  const inst = this.instances.find((i) => i.id === id);
10074
10206
  if (!inst) return { ok: false, error: "\u5B9E\u4F8B\u4E0D\u5B58\u5728" };
10075
10207
  if (!this.sandboxSupported) return { ok: false, error: "\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301\u6C99\u7BB1\u5B9E\u4F8B\uFF08\u9700 Linux + systemd-run\uFF1B\u80FD\u529B\u77E9\u9635\u89C1 GET /env/status \u7684 capabilities.multiInstance\uFF09" };
10076
- service.stopUnit("dsh-web@" + inst.id, { timeoutMs: 2e4 });
10208
+ this.service.stopUnit("dsh-web@" + inst.id, { timeoutMs: 2e4 });
10077
10209
  inst.state.phase = "STOPPED";
10078
10210
  this.save();
10079
10211
  this._stopLanForInstance(inst);
@@ -10354,6 +10486,7 @@ var require_plugins = __commonJS({
10354
10486
  var fs2 = require("node:fs");
10355
10487
  var path2 = require("node:path");
10356
10488
  var os2 = require("node:os");
10489
+ var matrix = require_matrix();
10357
10490
  var { semverCompare } = require_dist();
10358
10491
  var { dirSizeBytes } = require_fs_utils();
10359
10492
  var PROTECTED = /* @__PURE__ */ new Set(["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app"]);
@@ -10721,7 +10854,7 @@ var require_plugins = __commonJS({
10721
10854
  const killTree = (sig) => {
10722
10855
  if (!child) return;
10723
10856
  try {
10724
- if (process.platform !== "win32" && child.pid) process.kill(-child.pid, sig);
10857
+ if (matrix.supportsProcessGroup() && child.pid) process.kill(-child.pid, sig);
10725
10858
  else child.kill(sig);
10726
10859
  } catch {
10727
10860
  try {
@@ -12266,6 +12399,9 @@ var require_manager2 = __commonJS({
12266
12399
  function npmExe(self) {
12267
12400
  return self && self._npmBin || execPath.npmBin();
12268
12401
  }
12402
+ function npmExeArgs(self) {
12403
+ return self && Array.isArray(self._npmBinArgs) ? self._npmBinArgs.slice() : [];
12404
+ }
12269
12405
  var { semverCompare, VERSION_RE } = require_dist();
12270
12406
  var NativeManager = class {
12271
12407
  constructor(opts) {
@@ -12411,7 +12547,7 @@ var require_manager2 = __commonJS({
12411
12547
  const errors = [];
12412
12548
  const nv = ex2.runOut("node", ["--version"]);
12413
12549
  if (!nv || !nv.trim()) errors.push("node \u672A\u5B89\u88C5\u6216\u4E0D\u53EF\u6267\u884C");
12414
- const npmv = ex2.runOut(npmExe(this), ["--version"]);
12550
+ const npmv = ex2.runOut(npmExe(this), npmExeArgs(this).concat(["--version"]));
12415
12551
  if (!npmv || !npmv.trim()) errors.push("npm \u672A\u5B89\u88C5\u6216\u4E0D\u53EF\u6267\u884C");
12416
12552
  let npmRoot = this.npmRoot;
12417
12553
  if (!npmRoot) {
@@ -12463,7 +12599,7 @@ var require_manager2 = __commonJS({
12463
12599
  let pkgDir = null;
12464
12600
  try {
12465
12601
  if (!npmRoot) {
12466
- const r = ex2.runOut(npmExe(this), ["root", "-g"]);
12602
+ const r = ex2.runOut(npmExe(this), npmExeArgs(this).concat(["root", "-g"]));
12467
12603
  if (r) npmRoot = r.trim();
12468
12604
  }
12469
12605
  pkgDir = path2.join(npmRoot, this.config.packageName || "@deepseek-ai/dsh");
@@ -12942,7 +13078,7 @@ var require_manager2 = __commonJS({
12942
13078
  const exitCode = await new Promise((resolve) => {
12943
13079
  let child;
12944
13080
  try {
12945
- child = spawn(npmExe(this), uninstallArgs, { stdio: ["ignore", "pipe", "pipe"] });
13081
+ child = spawn(npmExe(this), npmExeArgs(this).concat(uninstallArgs), { stdio: ["ignore", "pipe", "pipe"] });
12946
13082
  } catch (e) {
12947
13083
  return resolve(-1);
12948
13084
  }
@@ -16612,7 +16748,7 @@ var require_supervise_view = __commonJS({
16612
16748
  try {
16613
16749
  const pid = pidlook.findListeningPid(this._routerCtlPort());
16614
16750
  if (!pid) return false;
16615
- const cmd2 = pidlook.readCmdline(pid) || "";
16751
+ const cmd2 = pidlook.normCmdline(pidlook.readCmdline(pid) || "");
16616
16752
  return cmd2.indexOf("router-daemon") >= 0 || cmd2.indexOf("service-daemon") >= 0 || cmd2.indexOf("/domains/router/daemon.js") >= 0;
16617
16753
  } catch {
16618
16754
  return false;
@@ -17644,6 +17780,7 @@ var require_settings_view = __commonJS({
17644
17780
  var { spawn } = require("node:child_process");
17645
17781
  var { execFile } = require("node:child_process");
17646
17782
  var ex2 = require_exec();
17783
+ var matrix = require_matrix();
17647
17784
  var netInfo = require_netinfo();
17648
17785
  var { EnvCatalog } = require_env_catalog();
17649
17786
  var { semverCompare } = require_dist();
@@ -17783,8 +17920,7 @@ var require_settings_view = __commonJS({
17783
17920
  guardCorePkg() {
17784
17921
  const raw = this.config.corePackageName;
17785
17922
  if (!raw) return null;
17786
- const map = { win32: "win", linux: "linux", darwin: "darwin" };
17787
- return String(raw).replace(/{os}/g, map[process.platform] || process.platform).replace(/{arch}/g, String(process.arch)) || null;
17923
+ return String(raw).replace(/{os}/g, matrix.osTag()).replace(/{arch}/g, matrix.current().arch) || null;
17788
17924
  }
17789
17925
  /** 守卫自更新(2026-09 收敛:npm 通道)——查 @dsh-sup/dsh-core-<os>-<arch> 全 tag 最高版本(全更新:
17790
17926
  * BETA/RC/正式都算更新,任一更高即提示可更新),对本机 guardVersion 比较。 */
@@ -18264,7 +18400,7 @@ var require_control_view = __commonJS({
18264
18400
  try {
18265
18401
  const pid = pidlook.findListeningPid(this._lanCtlPort());
18266
18402
  if (!pid) return false;
18267
- const cmd2 = pidlook.readCmdline(pid) || "";
18403
+ const cmd2 = pidlook.normCmdline(pidlook.readCmdline(pid) || "");
18268
18404
  return cmd2.indexOf("lan-daemon") >= 0 || cmd2.indexOf("/domains/relay/daemon.js") >= 0;
18269
18405
  } catch {
18270
18406
  return false;
@@ -19477,6 +19613,7 @@ var require_supervisor = __commonJS({
19477
19613
  var fs2 = require("node:fs");
19478
19614
  var path2 = require("node:path");
19479
19615
  var os2 = require("node:os");
19616
+ var matrix = require_matrix();
19480
19617
  var pidlook = require_pidlookup();
19481
19618
  var { DaemonLifecycle } = require_daemon_lifecycle();
19482
19619
  var platform = require_os();
@@ -20389,7 +20526,7 @@ var require_supervisor = __commonJS({
20389
20526
  if (!this.notifyEnabled) return;
20390
20527
  platform.notify(title, body, () => {
20391
20528
  this.notifyEnabled = false;
20392
- this.logger.warn("\u684C\u9762\u901A\u77E5\u4E0D\u53EF\u7528\uFF08" + process.platform + "\uFF09\uFF0C\u5DF2\u505C\u7528");
20529
+ this.logger.warn("\u684C\u9762\u901A\u77E5\u4E0D\u53EF\u7528\uFF08" + matrix.osTag() + "\uFF09\uFF0C\u5DF2\u505C\u7528");
20393
20530
  });
20394
20531
  }
20395
20532
  // ---- 升级流程挂钩(先停后装,消除运行中替换文件的混合版本窗口)----
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-sup/dsh-core-linux-x64",
3
- "version": "0.1.5-BETA.2",
3
+ "version": "0.1.5-BETA.3",
4
4
  "description": "DSH lifecycle guard core (Node launcher) for linux-x64 — requires Node >=18.",
5
5
  "license": "UNLICENSED",
6
6
  "os": [