openclaw-navigator 4.3.6 → 4.3.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.
- package/cli.mjs +56 -36
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -771,49 +771,57 @@ ${BOLD}How it works:${RESET}
|
|
|
771
771
|
|
|
772
772
|
ok(`MCP server started (PID ${mcpProcess.pid}) — bridge: http://localhost:${port}`);
|
|
773
773
|
|
|
774
|
-
// ── Auto-register MCP server with mcporter
|
|
774
|
+
// ── Auto-register MCP server with mcporter ────────────────────────
|
|
775
775
|
// Writes directly to ~/.mcporter/mcporter.json for reliability.
|
|
776
776
|
//
|
|
777
|
-
//
|
|
778
|
-
//
|
|
779
|
-
//
|
|
780
|
-
// the
|
|
777
|
+
// npx runs from a temp cache dir (.npm/_npx/<hash>/) that disappears.
|
|
778
|
+
// To get stable paths we:
|
|
779
|
+
// 1. Install openclaw-navigator globally (npm i -g)
|
|
780
|
+
// 2. Use the global install path for mcporter config
|
|
781
|
+
// 3. If global install fails, find node's real path via `which node`
|
|
781
782
|
try {
|
|
782
|
-
const { readFileSync, writeFileSync, mkdirSync
|
|
783
|
+
const { readFileSync, writeFileSync, mkdirSync } = await import("node:fs");
|
|
784
|
+
const { execSync } = await import("node:child_process");
|
|
783
785
|
const { homedir } = await import("node:os");
|
|
784
786
|
|
|
785
|
-
//
|
|
787
|
+
// Step 1: Install globally to get a stable path
|
|
786
788
|
let stableNode;
|
|
787
|
-
try {
|
|
788
|
-
stableNode = realpathSync(process.execPath);
|
|
789
|
-
} catch {
|
|
790
|
-
stableNode = process.execPath;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
// Resolve stable mcp.mjs path
|
|
794
789
|
let stableMcpPath;
|
|
790
|
+
|
|
795
791
|
try {
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
792
|
+
info(" Installing openclaw-navigator globally for stable paths...");
|
|
793
|
+
execSync("npm install -g openclaw-navigator@latest", {
|
|
794
|
+
stdio: ["ignore", "ignore", "ignore"],
|
|
795
|
+
timeout: 30000,
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
// Find the global node and mcp.mjs
|
|
799
|
+
const globalPrefix = execSync("npm prefix -g", { encoding: "utf8" }).trim();
|
|
800
|
+
stableMcpPath = join(globalPrefix, "lib/node_modules/openclaw-navigator/mcp.mjs");
|
|
801
|
+
// Find node via `which` — always gives the real PATH-resolved binary
|
|
802
|
+
stableNode = execSync("which node", { encoding: "utf8" }).trim();
|
|
803
|
+
|
|
804
|
+
if (!existsSync(stableMcpPath)) {
|
|
805
|
+
throw new Error(`Global mcp.mjs not found at ${stableMcpPath}`);
|
|
806
|
+
}
|
|
800
807
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
//
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
+
ok(`Global install: ${stableMcpPath}`);
|
|
809
|
+
} catch (installErr) {
|
|
810
|
+
// Global install failed (permissions?) — fallback to which node + current mcpPath
|
|
811
|
+
warn(`Global install failed: ${installErr.message}`);
|
|
812
|
+
try {
|
|
813
|
+
stableNode = execSync("which node", { encoding: "utf8" }).trim();
|
|
814
|
+
} catch {
|
|
815
|
+
stableNode = process.execPath;
|
|
808
816
|
}
|
|
809
|
-
|
|
810
|
-
|
|
817
|
+
stableMcpPath = mcpPath;
|
|
818
|
+
info(` Falling back to: ${stableNode} ${stableMcpPath}`);
|
|
811
819
|
}
|
|
812
820
|
|
|
813
821
|
info(` mcporter: node=${stableNode}`);
|
|
814
822
|
info(` mcporter: mcp=${stableMcpPath}`);
|
|
815
823
|
|
|
816
|
-
// Write directly to ~/.mcporter/mcporter.json
|
|
824
|
+
// Step 2: Write directly to ~/.mcporter/mcporter.json
|
|
817
825
|
const mcporterDir = join(homedir(), ".mcporter");
|
|
818
826
|
const mcporterConfigPath = join(mcporterDir, "mcporter.json");
|
|
819
827
|
|
|
@@ -848,18 +856,24 @@ ${BOLD}How it works:${RESET}
|
|
|
848
856
|
// so the bridge + MCP server starts automatically on login.
|
|
849
857
|
if (process.platform === "darwin") {
|
|
850
858
|
try {
|
|
851
|
-
const {
|
|
859
|
+
const {
|
|
860
|
+
writeFileSync: writePlist,
|
|
861
|
+
existsSync: plistExists,
|
|
862
|
+
mkdirSync: mkPlist,
|
|
863
|
+
} = await import("node:fs");
|
|
852
864
|
const { homedir: homeDir } = await import("node:os");
|
|
853
865
|
const home = homeDir();
|
|
854
866
|
const launchAgentsDir = join(home, "Library/LaunchAgents");
|
|
855
867
|
const plistPath = join(launchAgentsDir, "com.openclaw.navigator-bridge.plist");
|
|
856
868
|
|
|
857
|
-
//
|
|
858
|
-
const {
|
|
869
|
+
// Find stable node/npx paths via `which` (not temp npx cache)
|
|
870
|
+
const { execSync: whichExec } = await import("node:child_process");
|
|
859
871
|
let nodeForPlist;
|
|
860
|
-
try {
|
|
861
|
-
|
|
862
|
-
|
|
872
|
+
try {
|
|
873
|
+
nodeForPlist = whichExec("which node", { encoding: "utf8" }).trim();
|
|
874
|
+
} catch {
|
|
875
|
+
nodeForPlist = process.execPath;
|
|
876
|
+
}
|
|
863
877
|
const npxForPlist = join(dirname(nodeForPlist), "npx");
|
|
864
878
|
|
|
865
879
|
const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -901,9 +915,15 @@ ${BOLD}How it works:${RESET}
|
|
|
901
915
|
// Load the service (unload first if already loaded)
|
|
902
916
|
try {
|
|
903
917
|
const { execSync: ex } = await import("node:child_process");
|
|
904
|
-
try {
|
|
918
|
+
try {
|
|
919
|
+
ex(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
920
|
+
} catch {
|
|
921
|
+
/* not loaded */
|
|
922
|
+
}
|
|
905
923
|
// Don't load now — we're already running. It'll start on next login.
|
|
906
|
-
} catch {
|
|
924
|
+
} catch {
|
|
925
|
+
/* launchctl not available */
|
|
926
|
+
}
|
|
907
927
|
|
|
908
928
|
ok("Auto-start installed — bridge will start on login");
|
|
909
929
|
info(` Plist: ${plistPath}`);
|