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.
Files changed (2) hide show
  1. package/cli.mjs +56 -36
  2. 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 (if available) ─────────
774
+ // ── Auto-register MCP server with mcporter ────────────────────────
775
775
  // Writes directly to ~/.mcporter/mcporter.json for reliability.
776
776
  //
777
- // KEY FIX: We resolve stable paths instead of using process.execPath
778
- // which may point to a temp npx cache (/Users/x/.npm/_npx/<hash>/node)
779
- // that disappears after npx exits. We find the REAL node binary and
780
- // the globally-installed mcp.mjs (or realpath of the current one).
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, realpathSync } = await import("node:fs");
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
- // Resolve stable node binary (follow symlinks out of npx temp dir)
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
- stableMcpPath = realpathSync(mcpPath);
797
- } catch {
798
- stableMcpPath = mcpPath;
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
- // If paths are still in npx temp cache, try to find the real install
802
- if (stableMcpPath.includes("_npx") || stableMcpPath.includes(".npm/_npx")) {
803
- // Check if openclaw-navigator is installed globally
804
- const nodeDir = dirname(stableNode);
805
- const globalMcp = join(dirname(nodeDir), "lib/node_modules/openclaw-navigator/mcp.mjs");
806
- if (existsSync(globalMcp)) {
807
- stableMcpPath = globalMcp;
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
- // If still temp, that's OK — mcporter will use the path we give it
810
- // and the bridge running alongside keeps the MCP server alive anyway
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 { writeFileSync: writePlist, existsSync: plistExists, mkdirSync: mkPlist } = await import("node:fs");
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
- // Resolve the stable node path (same one we found above for mcporter)
858
- const { realpathSync: rp } = await import("node:fs");
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 { nodeForPlist = rp(process.execPath); } catch { nodeForPlist = process.execPath; }
861
-
862
- // Find npx next to the stable node
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 { ex(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" }); } catch { /* not loaded */ }
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 { /* launchctl not available */ }
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}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-navigator",
3
- "version": "4.3.6",
3
+ "version": "4.3.7",
4
4
  "description": "One-command bridge + tunnel for the Navigator browser — works on any machine, any OS",
5
5
  "keywords": [
6
6
  "browser",