@web-auto/webauto 0.1.6 → 0.1.7
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.
|
@@ -270,6 +270,7 @@ async function importConfigFromFile(filePath) {
|
|
|
270
270
|
// src/main/core-daemon-manager.mts
|
|
271
271
|
import { spawn } from "child_process";
|
|
272
272
|
import path2 from "path";
|
|
273
|
+
import { existsSync as existsSync2 } from "fs";
|
|
273
274
|
import { fileURLToPath } from "url";
|
|
274
275
|
var REPO_ROOT = path2.resolve(path2.dirname(fileURLToPath(import.meta.url)), "../../../..");
|
|
275
276
|
var CORE_HEALTH_URLS = ["http://127.0.0.1:7701/health", "http://127.0.0.1:7704/health"];
|
|
@@ -283,11 +284,33 @@ function resolveNodeBin() {
|
|
|
283
284
|
if (explicit) return explicit;
|
|
284
285
|
const npmNode = String(process.env.npm_node_execpath || "").trim();
|
|
285
286
|
if (npmNode) return npmNode;
|
|
286
|
-
|
|
287
|
+
const fromPath = resolveOnPath(process.platform === "win32" ? ["node.exe", "node.cmd", "node"] : ["node"]);
|
|
288
|
+
if (fromPath) return fromPath;
|
|
289
|
+
return process.execPath;
|
|
287
290
|
}
|
|
288
291
|
function resolveNpxBin() {
|
|
292
|
+
const fromPath = resolveOnPath(
|
|
293
|
+
process.platform === "win32" ? ["npx.cmd", "npx.exe", "npx.bat", "npx.ps1"] : ["npx"]
|
|
294
|
+
);
|
|
295
|
+
if (fromPath) return fromPath;
|
|
289
296
|
return process.platform === "win32" ? "npx.cmd" : "npx";
|
|
290
297
|
}
|
|
298
|
+
function resolveOnPath(candidates) {
|
|
299
|
+
const pathEnv = process.env.PATH || process.env.Path || "";
|
|
300
|
+
const dirs = pathEnv.split(path2.delimiter).filter(Boolean);
|
|
301
|
+
for (const dir of dirs) {
|
|
302
|
+
for (const name of candidates) {
|
|
303
|
+
const full = path2.join(dir, name);
|
|
304
|
+
if (existsSync2(full)) return full;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
function quoteCmdArg(value) {
|
|
310
|
+
if (!value) return '""';
|
|
311
|
+
if (!/[\s"]/u.test(value)) return value;
|
|
312
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
313
|
+
}
|
|
291
314
|
async function checkHttpHealth(url) {
|
|
292
315
|
try {
|
|
293
316
|
const res = await fetch(url, { signal: AbortSignal.timeout(1e3) });
|
|
@@ -332,7 +355,18 @@ async function runNodeScript(scriptPath, timeoutMs) {
|
|
|
332
355
|
}
|
|
333
356
|
async function runCommand(command, args, timeoutMs) {
|
|
334
357
|
return new Promise((resolve) => {
|
|
335
|
-
const
|
|
358
|
+
const lower = String(command || "").toLowerCase();
|
|
359
|
+
let spawnCommand2 = command;
|
|
360
|
+
let spawnArgs = args;
|
|
361
|
+
if (process.platform === "win32" && (lower.endsWith(".cmd") || lower.endsWith(".bat"))) {
|
|
362
|
+
spawnCommand2 = "cmd.exe";
|
|
363
|
+
const cmdLine = [quoteCmdArg(command), ...args.map(quoteCmdArg)].join(" ");
|
|
364
|
+
spawnArgs = ["/d", "/s", "/c", cmdLine];
|
|
365
|
+
} else if (process.platform === "win32" && lower.endsWith(".ps1")) {
|
|
366
|
+
spawnCommand2 = "powershell.exe";
|
|
367
|
+
spawnArgs = ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", command, ...args];
|
|
368
|
+
}
|
|
369
|
+
const child = spawn(spawnCommand2, spawnArgs, {
|
|
336
370
|
cwd: REPO_ROOT,
|
|
337
371
|
stdio: "ignore",
|
|
338
372
|
windowsHide: true,
|
|
@@ -365,7 +399,11 @@ async function startCoreDaemon() {
|
|
|
365
399
|
console.error("[CoreDaemonManager] Failed to start unified API service");
|
|
366
400
|
return false;
|
|
367
401
|
}
|
|
368
|
-
const startedBrowser = await runCommand(
|
|
402
|
+
const startedBrowser = await runCommand(
|
|
403
|
+
resolveNpxBin(),
|
|
404
|
+
["--yes", "--package=@web-auto/camo", "camo", "init"],
|
|
405
|
+
4e4
|
|
406
|
+
);
|
|
369
407
|
if (!startedBrowser) {
|
|
370
408
|
console.error("[CoreDaemonManager] Failed to start camo browser backend");
|
|
371
409
|
return false;
|
|
@@ -691,28 +729,26 @@ var StateBridge = class {
|
|
|
691
729
|
var stateBridge = new StateBridge();
|
|
692
730
|
|
|
693
731
|
// src/main/env-check.mts
|
|
694
|
-
import {
|
|
695
|
-
import {
|
|
696
|
-
import { existsSync as existsSync2 } from "node:fs";
|
|
732
|
+
import { spawnSync } from "node:child_process";
|
|
733
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
697
734
|
import path4 from "node:path";
|
|
698
735
|
import os3 from "node:os";
|
|
699
|
-
var execAsync = promisify(exec);
|
|
700
736
|
function resolveWebautoRoot() {
|
|
701
737
|
const portableRoot = String(process.env.WEBAUTO_PORTABLE_ROOT || process.env.WEBAUTO_ROOT || "").trim();
|
|
702
738
|
return portableRoot ? path4.join(portableRoot, ".webauto") : path4.join(os3.homedir(), ".webauto");
|
|
703
739
|
}
|
|
704
740
|
function resolveNpxBin2() {
|
|
705
741
|
if (process.platform !== "win32") return "npx";
|
|
706
|
-
const resolved =
|
|
742
|
+
const resolved = resolveOnPath2(["npx.cmd", "npx.exe", "npx.bat", "npx.ps1"]);
|
|
707
743
|
return resolved || "npx.cmd";
|
|
708
744
|
}
|
|
709
|
-
function
|
|
745
|
+
function resolveOnPath2(candidates) {
|
|
710
746
|
const pathEnv = process.env.PATH || process.env.Path || "";
|
|
711
747
|
const dirs = pathEnv.split(path4.delimiter).filter(Boolean);
|
|
712
748
|
for (const dir of dirs) {
|
|
713
749
|
for (const name of candidates) {
|
|
714
750
|
const full = path4.join(dir, name);
|
|
715
|
-
if (
|
|
751
|
+
if (existsSync3(full)) return full;
|
|
716
752
|
}
|
|
717
753
|
}
|
|
718
754
|
return null;
|
|
@@ -729,7 +765,7 @@ ${String(stderr || "")}`.trim();
|
|
|
729
765
|
}
|
|
730
766
|
return "unknown";
|
|
731
767
|
}
|
|
732
|
-
function
|
|
768
|
+
function quoteCmdArg2(value) {
|
|
733
769
|
if (!value) return '""';
|
|
734
770
|
if (!/[\s"]/u.test(value)) return value;
|
|
735
771
|
return `"${value.replace(/"/g, '""')}"`;
|
|
@@ -739,7 +775,7 @@ function runVersionCheck(command, args, explicitPath) {
|
|
|
739
775
|
const lower = String(command || "").toLowerCase();
|
|
740
776
|
let ret;
|
|
741
777
|
if (process.platform === "win32" && (lower.endsWith(".cmd") || lower.endsWith(".bat"))) {
|
|
742
|
-
const cmdLine = [
|
|
778
|
+
const cmdLine = [quoteCmdArg2(command), ...args.map(quoteCmdArg2)].join(" ");
|
|
743
779
|
ret = spawnSync("cmd.exe", ["/d", "/s", "/c", cmdLine], {
|
|
744
780
|
encoding: "utf8",
|
|
745
781
|
timeout: 8e3,
|
|
@@ -773,6 +809,14 @@ function runVersionCheck(command, args, explicitPath) {
|
|
|
773
809
|
return { installed: false, error: String(err) };
|
|
774
810
|
}
|
|
775
811
|
}
|
|
812
|
+
function resolvePathFromOutput(stdout) {
|
|
813
|
+
const lines = String(stdout || "").split(/\r?\n/).map((x) => x.trim()).filter(Boolean);
|
|
814
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
815
|
+
const line = lines[i];
|
|
816
|
+
if (line.startsWith("/") || /^[A-Z]:\\/i.test(line)) return line;
|
|
817
|
+
}
|
|
818
|
+
return "";
|
|
819
|
+
}
|
|
776
820
|
async function checkCamoCli() {
|
|
777
821
|
const camoCandidates = process.platform === "win32" ? ["camo.cmd", "camo.exe", "camo.bat", "camo.ps1"] : ["camo"];
|
|
778
822
|
for (const candidate of camoCandidates) {
|
|
@@ -788,7 +832,7 @@ async function checkCamoCli() {
|
|
|
788
832
|
for (const localRoot of localRoots) {
|
|
789
833
|
for (const suffix of camoCandidates) {
|
|
790
834
|
const candidate = path4.resolve(localRoot, suffix);
|
|
791
|
-
if (!
|
|
835
|
+
if (!existsSync3(candidate)) continue;
|
|
792
836
|
const ret = runVersionCheck(candidate, ["help"], candidate);
|
|
793
837
|
if (ret.installed) return ret;
|
|
794
838
|
}
|
|
@@ -813,51 +857,32 @@ async function checkServices() {
|
|
|
813
857
|
return { unifiedApi, camoRuntime, searchGate };
|
|
814
858
|
}
|
|
815
859
|
async function checkFirefox() {
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
if (platform === "win32") {
|
|
836
|
-
const programFiles = process.env.PROGRAMFILES || "C:\\Program Files";
|
|
837
|
-
const programFilesX86 = process.env["PROGRAMFILES(X86)"] || "C:\\Program Files (x86)";
|
|
838
|
-
const localAppData = process.env.LOCALAPPDATA || path4.join(os3.homedir(), "AppData", "Local");
|
|
839
|
-
const possiblePaths = [
|
|
840
|
-
path4.join(programFiles, "Mozilla Firefox", "firefox.exe"),
|
|
841
|
-
path4.join(programFilesX86, "Mozilla Firefox", "firefox.exe"),
|
|
842
|
-
path4.join(localAppData, "Mozilla Firefox", "firefox.exe")
|
|
843
|
-
];
|
|
844
|
-
for (const firefoxPath2 of possiblePaths) {
|
|
845
|
-
if (existsSync2(firefoxPath2)) return { installed: true, path: firefoxPath2 };
|
|
846
|
-
}
|
|
847
|
-
return { installed: false };
|
|
860
|
+
const candidates = process.platform === "win32" ? [
|
|
861
|
+
{ command: "python", args: ["-m", "camoufox", "path"] },
|
|
862
|
+
{ command: "py", args: ["-3", "-m", "camoufox", "path"] },
|
|
863
|
+
{ command: resolveNpxBin2(), args: ["--yes", "--package=camoufox", "camoufox", "path"] }
|
|
864
|
+
] : [
|
|
865
|
+
{ command: "python3", args: ["-m", "camoufox", "path"] },
|
|
866
|
+
{ command: resolveNpxBin2(), args: ["--yes", "--package=camoufox", "camoufox", "path"] }
|
|
867
|
+
];
|
|
868
|
+
for (const candidate of candidates) {
|
|
869
|
+
try {
|
|
870
|
+
const ret = spawnSync(candidate.command, candidate.args, {
|
|
871
|
+
encoding: "utf8",
|
|
872
|
+
timeout: 8e3,
|
|
873
|
+
windowsHide: true
|
|
874
|
+
});
|
|
875
|
+
if (ret.status !== 0) continue;
|
|
876
|
+
const resolvedPath = resolvePathFromOutput(String(ret.stdout || ""));
|
|
877
|
+
return resolvedPath ? { installed: true, path: resolvedPath } : { installed: true };
|
|
878
|
+
} catch {
|
|
848
879
|
}
|
|
849
|
-
const macBundle = "/Applications/Firefox.app/Contents/MacOS/firefox";
|
|
850
|
-
if (platform === "darwin" && existsSync2(macBundle)) return { installed: true, path: macBundle };
|
|
851
|
-
const { stdout } = await execAsync("which firefox", { timeout: 3e3 });
|
|
852
|
-
const firefoxPath = String(stdout || "").trim();
|
|
853
|
-
return firefoxPath ? { installed: true, path: firefoxPath } : { installed: false };
|
|
854
|
-
} catch {
|
|
855
|
-
return { installed: false };
|
|
856
880
|
}
|
|
881
|
+
return { installed: false };
|
|
857
882
|
}
|
|
858
883
|
async function checkGeoIP() {
|
|
859
884
|
const geoIpPath = path4.join(resolveWebautoRoot(), "geoip", "GeoLite2-City.mmdb");
|
|
860
|
-
if (
|
|
885
|
+
if (existsSync3(geoIpPath)) {
|
|
861
886
|
return { installed: true, path: geoIpPath };
|
|
862
887
|
}
|
|
863
888
|
return { installed: false };
|
|
@@ -1553,7 +1553,7 @@ function renderSetupWizard(root, ctx2) {
|
|
|
1553
1553
|
<div class="env-item" id="env-camo" style="display:flex; align-items:center; justify-content:space-between; gap:8px;">
|
|
1554
1554
|
<span style="display:flex; align-items:center; gap:8px; min-width:0;">
|
|
1555
1555
|
<span class="icon" style="color: var(--text-4);">\u25CB</span>
|
|
1556
|
-
<span class="env-label">Camo CLI</span>
|
|
1556
|
+
<span class="env-label">Camo CLI (@web-auto/camo)</span>
|
|
1557
1557
|
</span>
|
|
1558
1558
|
<button id="repair-camo-btn" class="secondary" style="display:none; flex:0 0 auto;">\u4E00\u952E\u4FEE\u590D</button>
|
|
1559
1559
|
</div>
|
|
@@ -1567,14 +1567,14 @@ function renderSetupWizard(root, ctx2) {
|
|
|
1567
1567
|
<div class="env-item" id="env-browser" style="display:flex; align-items:center; justify-content:space-between; gap:8px;">
|
|
1568
1568
|
<span style="display:flex; align-items:center; gap:8px; min-width:0;">
|
|
1569
1569
|
<span class="icon" style="color: var(--text-4);">\u25CB</span>
|
|
1570
|
-
<span class="env-label">Camo Runtime\
|
|
1570
|
+
<span class="env-label">Camo Runtime Service (7704\uFF0C\u53EF\u9009)</span>
|
|
1571
1571
|
</span>
|
|
1572
1572
|
<button id="repair-core2-btn" class="secondary" style="display:none; flex:0 0 auto;">\u4E00\u952E\u4FEE\u590D</button>
|
|
1573
1573
|
</div>
|
|
1574
1574
|
<div class="env-item" id="env-firefox" style="display:flex; align-items:center; justify-content:space-between; gap:8px;">
|
|
1575
1575
|
<span style="display:flex; align-items:center; gap:8px; min-width:0;">
|
|
1576
1576
|
<span class="icon" style="color: var(--text-4);">\u25CB</span>
|
|
1577
|
-
<span class="env-label">Camoufox
|
|
1577
|
+
<span class="env-label">Camoufox Runtime (python -m camoufox)</span>
|
|
1578
1578
|
</span>
|
|
1579
1579
|
<button id="repair-runtime-btn" class="secondary" style="display:none; flex:0 0 auto;">\u4E00\u952E\u4FEE\u590D</button>
|
|
1580
1580
|
</div>
|
|
@@ -1706,7 +1706,7 @@ function renderSetupWizard(root, ctx2) {
|
|
|
1706
1706
|
setupStatusText.textContent = "\u6B63\u5728\u62C9\u8D77\u6838\u5FC3\u670D\u52A1...";
|
|
1707
1707
|
const res = await ctx2.api.envRepairDeps({ core: true }).catch((err) => ({ ok: false, error: err?.message || String(err) }));
|
|
1708
1708
|
const ok = res?.ok !== false;
|
|
1709
|
-
const detail = res?.error || (ok ? "" : "\u6838\u5FC3\u670D\u52A1\u542F\u52A8\u5931\u8D25");
|
|
1709
|
+
const detail = res?.error || res?.core?.error || res?.core?.services?.error || (ok ? "" : "\u6838\u5FC3\u670D\u52A1\u542F\u52A8\u5931\u8D25");
|
|
1710
1710
|
return { ok, detail };
|
|
1711
1711
|
}
|
|
1712
1712
|
if (typeof ctx2.api?.envRepairCore === "function") {
|
|
@@ -1720,7 +1720,7 @@ function renderSetupWizard(root, ctx2) {
|
|
|
1720
1720
|
}
|
|
1721
1721
|
async function repairInstall({ browser, geoip, reinstall, uninstall }) {
|
|
1722
1722
|
if (typeof ctx2.api?.envRepairDeps === "function") {
|
|
1723
|
-
setupStatusText.textContent = reinstall ? "\u6B63\u5728\u5378\u8F7D\u5E76\u91CD\u88C5\u8D44\u6E90\uFF08Camoufox/GeoIP\uFF09..." : geoip && browser ? "\u6B63\u5728\u5B89\u88C5\u4F9D\u8D56\uFF08Camoufox/GeoIP\uFF09..." : geoip ? "\u6B63\u5728\u5B89\u88C5 GeoIP\uFF08\u53EF\u9009\uFF09..." : "\u6B63\u5728\u5B89\u88C5 Camoufox...";
|
|
1723
|
+
setupStatusText.textContent = reinstall ? "\u6B63\u5728\u5378\u8F7D\u5E76\u91CD\u88C5\u8D44\u6E90\uFF08Camoufox Runtime/GeoIP\uFF09..." : geoip && browser ? "\u6B63\u5728\u5B89\u88C5\u4F9D\u8D56\uFF08Camoufox Runtime/GeoIP\uFF09..." : geoip ? "\u6B63\u5728\u5B89\u88C5 GeoIP\uFF08\u53EF\u9009\uFF09..." : "\u6B63\u5728\u5B89\u88C5 Camoufox Runtime...";
|
|
1724
1724
|
const res = await ctx2.api.envRepairDeps({
|
|
1725
1725
|
browser: Boolean(browser),
|
|
1726
1726
|
geoip: Boolean(geoip),
|
|
@@ -1728,11 +1728,11 @@ function renderSetupWizard(root, ctx2) {
|
|
|
1728
1728
|
uninstall: Boolean(uninstall)
|
|
1729
1729
|
}).catch((err) => ({ ok: false, error: err?.message || String(err) }));
|
|
1730
1730
|
const ok = res?.ok !== false;
|
|
1731
|
-
const detail = res?.error || (ok ? "" : "\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25");
|
|
1731
|
+
const detail = res?.error || res?.install?.error || res?.install?.stderr || res?.install?.stdout || res?.install?.json?.error || (ok ? "" : "\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25");
|
|
1732
1732
|
return { ok, detail };
|
|
1733
1733
|
}
|
|
1734
1734
|
if (typeof ctx2.api?.cmdRunJson === "function") {
|
|
1735
|
-
setupStatusText.textContent = reinstall ? "\u6B63\u5728\u5378\u8F7D\u5E76\u91CD\u88C5\u8D44\u6E90\uFF08Camoufox/GeoIP\uFF09..." : geoip && browser ? "\u6B63\u5728\u5B89\u88C5\u4F9D\u8D56\uFF08Camoufox/GeoIP\uFF09..." : geoip ? "\u6B63\u5728\u5B89\u88C5 GeoIP\uFF08\u53EF\u9009\uFF09..." : "\u6B63\u5728\u5B89\u88C5 Camoufox...";
|
|
1735
|
+
setupStatusText.textContent = reinstall ? "\u6B63\u5728\u5378\u8F7D\u5E76\u91CD\u88C5\u8D44\u6E90\uFF08Camoufox Runtime/GeoIP\uFF09..." : geoip && browser ? "\u6B63\u5728\u5B89\u88C5\u4F9D\u8D56\uFF08Camoufox Runtime/GeoIP\uFF09..." : geoip ? "\u6B63\u5728\u5B89\u88C5 GeoIP\uFF08\u53EF\u9009\uFF09..." : "\u6B63\u5728\u5B89\u88C5 Camoufox Runtime...";
|
|
1736
1736
|
const script = ctx2.api.pathJoin("apps", "webauto", "entry", "xhs-install.mjs");
|
|
1737
1737
|
const args = [script];
|
|
1738
1738
|
if (reinstall) args.push("--reinstall");
|
|
@@ -1761,7 +1761,12 @@ function renderSetupWizard(root, ctx2) {
|
|
|
1761
1761
|
if (!res.ok) ok = false;
|
|
1762
1762
|
if (res.detail) detail = res.detail;
|
|
1763
1763
|
}
|
|
1764
|
-
if (missing.camo
|
|
1764
|
+
if (missing.camo && !missing.core) {
|
|
1765
|
+
const res = await repairCoreServices();
|
|
1766
|
+
if (!res.ok) ok = false;
|
|
1767
|
+
if (res.detail) detail = res.detail;
|
|
1768
|
+
}
|
|
1769
|
+
if (missing.runtime) {
|
|
1765
1770
|
const res = await repairInstall({ browser: true });
|
|
1766
1771
|
if (!res.ok) ok = false;
|
|
1767
1772
|
if (res.detail) detail = res.detail;
|
|
@@ -1837,7 +1842,7 @@ function renderSetupWizard(root, ctx2) {
|
|
|
1837
1842
|
updateCompleteStatus();
|
|
1838
1843
|
if (!envReady) {
|
|
1839
1844
|
const missing = [];
|
|
1840
|
-
if (!snapshot?.camo?.installed) missing.push("camo");
|
|
1845
|
+
if (!snapshot?.camo?.installed) missing.push("camo-cli");
|
|
1841
1846
|
if (!snapshot?.services?.unifiedApi) missing.push("unified-api");
|
|
1842
1847
|
if (!snapshot?.firefox?.installed) missing.push("camoufox-runtime");
|
|
1843
1848
|
setupStatusText.textContent = `\u5B58\u5728\u5F85\u4FEE\u590D\u9879: ${missing.join(", ")}`;
|
|
@@ -2069,10 +2074,14 @@ function renderSetupWizard(root, ctx2) {
|
|
|
2069
2074
|
const snapshot = await collectEnvironment();
|
|
2070
2075
|
return await repairMissing(snapshot);
|
|
2071
2076
|
});
|
|
2072
|
-
envReinstallAllBtn.onclick = () => void runRepair("\u4E00\u952E\u5378\u8F7D\u91CD\u88C5\u8D44\u6E90", () =>
|
|
2077
|
+
envReinstallAllBtn.onclick = () => void runRepair("\u4E00\u952E\u5378\u8F7D\u91CD\u88C5\u8D44\u6E90", () => (async () => {
|
|
2078
|
+
const core = await repairCoreServices();
|
|
2079
|
+
if (!core.ok) return core;
|
|
2080
|
+
return repairInstall({ browser: true, geoip: true, reinstall: true });
|
|
2081
|
+
})());
|
|
2073
2082
|
repairCoreBtn.onclick = () => void runRepair("\u4FEE\u590D\u6838\u5FC3\u670D\u52A1", repairCoreServices);
|
|
2074
2083
|
repairCore2Btn.onclick = () => void runRepair("\u4FEE\u590D\u6838\u5FC3\u670D\u52A1", repairCoreServices);
|
|
2075
|
-
repairCamoBtn.onclick = () => void runRepair("\u4FEE\u590D
|
|
2084
|
+
repairCamoBtn.onclick = () => void runRepair("\u4FEE\u590D Camo CLI", repairCoreServices);
|
|
2076
2085
|
repairRuntimeBtn.onclick = () => void runRepair("\u4FEE\u590D Camoufox Runtime", () => repairInstall({ browser: true }));
|
|
2077
2086
|
repairGeoipBtn.onclick = () => void runRepair("\u5B89\u88C5 GeoIP", () => repairInstall({ geoip: true }));
|
|
2078
2087
|
addAccountBtn.onclick = addAccount;
|
|
@@ -3726,7 +3735,7 @@ function renderAccountManager(root, ctx2) {
|
|
|
3726
3735
|
<div class="env-status-grid">
|
|
3727
3736
|
<div class="env-item" id="env-camo">
|
|
3728
3737
|
<span class="icon" style="color: var(--text-4);">\u25CB</span>
|
|
3729
|
-
<span>Camo CLI</span>
|
|
3738
|
+
<span>Camo CLI (@web-auto/camo)</span>
|
|
3730
3739
|
</div>
|
|
3731
3740
|
<div class="env-item" id="env-unified">
|
|
3732
3741
|
<span class="icon" style="color: var(--text-4);">\u25CB</span>
|
|
@@ -3734,11 +3743,11 @@ function renderAccountManager(root, ctx2) {
|
|
|
3734
3743
|
</div>
|
|
3735
3744
|
<div class="env-item" id="env-browser">
|
|
3736
3745
|
<span class="icon" style="color: var(--text-4);">\u25CB</span>
|
|
3737
|
-
<span>Camo Runtime\
|
|
3746
|
+
<span>Camo Runtime Service (7704\uFF0C\u53EF\u9009)</span>
|
|
3738
3747
|
</div>
|
|
3739
3748
|
<div class="env-item" id="env-firefox">
|
|
3740
3749
|
<span class="icon" style="color: var(--text-4);">\u25CB</span>
|
|
3741
|
-
<span>Camoufox
|
|
3750
|
+
<span>Camoufox Runtime (python -m camoufox)</span>
|
|
3742
3751
|
</div>
|
|
3743
3752
|
</div>
|
|
3744
3753
|
<div class="btn-group" style="margin-top: var(--gap);">
|
|
@@ -57,6 +57,22 @@ function resolveNpxBin(platform = process.platform, pathEnv = process.env.PATH |
|
|
|
57
57
|
return resolved || 'npx.cmd';
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
function resolveNpmBin(platform = process.platform, pathEnv = process.env.PATH || process.env.Path || '') {
|
|
61
|
+
if (platform !== 'win32') return 'npm';
|
|
62
|
+
const resolved = resolveOnPath(
|
|
63
|
+
['npm.cmd', 'npm.exe', 'npm.bat', 'npm.ps1'],
|
|
64
|
+
pathEnv,
|
|
65
|
+
';',
|
|
66
|
+
);
|
|
67
|
+
return resolved || 'npm.cmd';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function runPackageCommand(packageName, commandArgs) {
|
|
71
|
+
const viaNpx = run(resolveNpxBin(), ['--yes', `--package=${packageName}`, ...commandArgs]);
|
|
72
|
+
if (viaNpx.status === 0) return viaNpx;
|
|
73
|
+
return run(resolveNpmBin(), ['exec', '--yes', `--package=${packageName}`, '--', ...commandArgs]);
|
|
74
|
+
}
|
|
75
|
+
|
|
60
76
|
function resolveWebautoRoot() {
|
|
61
77
|
const portableRoot = String(process.env.WEBAUTO_PORTABLE_ROOT || process.env.WEBAUTO_ROOT || '').trim();
|
|
62
78
|
if (portableRoot) return path.join(portableRoot, '.webauto');
|
|
@@ -79,11 +95,13 @@ function checkCamoufoxInstalled() {
|
|
|
79
95
|
const ret = run(candidate.cmd, candidate.args);
|
|
80
96
|
if (ret.status === 0) return true;
|
|
81
97
|
}
|
|
98
|
+
const npxRet = runPackageCommand('camoufox', ['camoufox', 'path']);
|
|
99
|
+
if (npxRet.status === 0) return true;
|
|
82
100
|
return false;
|
|
83
101
|
}
|
|
84
102
|
|
|
85
103
|
function installCamoufox() {
|
|
86
|
-
const ret =
|
|
104
|
+
const ret = runPackageCommand('camoufox', ['camoufox', 'fetch']);
|
|
87
105
|
return ret.status === 0;
|
|
88
106
|
}
|
|
89
107
|
|
|
@@ -92,12 +110,12 @@ function checkGeoIPInstalled() {
|
|
|
92
110
|
}
|
|
93
111
|
|
|
94
112
|
function installGeoIP() {
|
|
95
|
-
const ret =
|
|
113
|
+
const ret = runPackageCommand('@web-auto/camo', ['camo', 'init', 'geoip']);
|
|
96
114
|
return ret.status === 0;
|
|
97
115
|
}
|
|
98
116
|
|
|
99
117
|
function uninstallCamoufox() {
|
|
100
|
-
const ret =
|
|
118
|
+
const ret = runPackageCommand('camoufox', ['camoufox', 'remove']);
|
|
101
119
|
return ret.status === 0;
|
|
102
120
|
}
|
|
103
121
|
|