openclaw-navigator 2.0.0 → 2.1.0

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 +61 -3
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -79,6 +79,35 @@ function getTailscaleIP() {
79
79
  return null;
80
80
  }
81
81
 
82
+ function getTailscaleDNS() {
83
+ try {
84
+ const raw = execSync("tailscale status --json", { encoding: "utf8", timeout: 5000 });
85
+ const status = JSON.parse(raw);
86
+ const dns = status?.Self?.DNSName;
87
+ if (dns) return dns.replace(/\.$/, "");
88
+ } catch { /* ignore */ }
89
+ return null;
90
+ }
91
+
92
+ function setupTailscaleServe(localPort, httpsPort = 8443) {
93
+ try {
94
+ // Set up tailscale serve to proxy HTTPS → our local HTTP server
95
+ execSync(`tailscale serve --bg --https=${httpsPort} http://localhost:${localPort}`, {
96
+ stdio: "ignore",
97
+ timeout: 10_000,
98
+ });
99
+ return true;
100
+ } catch {
101
+ return false;
102
+ }
103
+ }
104
+
105
+ function teardownTailscaleServe(httpsPort = 8443) {
106
+ try {
107
+ execSync(`tailscale serve --https=${httpsPort} off`, { stdio: "ignore", timeout: 5000 });
108
+ } catch { /* ignore */ }
109
+ }
110
+
82
111
  function commandExists(cmd) {
83
112
  try {
84
113
  execSync(`which ${cmd}`, { stdio: "ignore" });
@@ -396,9 +425,12 @@ ${BOLD}What this does:${RESET}
396
425
  const tailscaleIP = getTailscaleIP();
397
426
  const localIP = getLocalIP();
398
427
 
428
+ const tailscaleDNS = tailscaleIP ? getTailscaleDNS() : null;
429
+
399
430
  const methods = [];
400
431
  if (hasCloudflared) methods.push({ value: "cloudflare", label: "Cloudflare Tunnel (recommended)", hint: "works anywhere, no config" });
401
- if (tailscaleIP) methods.push({ value: "tailscale", label: "Tailscale", hint: tailscaleIP });
432
+ if (tailscaleDNS) methods.push({ value: "tailscale-https", label: "Tailscale HTTPS (recommended)", hint: tailscaleDNS });
433
+ else if (tailscaleIP) methods.push({ value: "tailscale", label: "Tailscale (raw IP)", hint: tailscaleIP });
402
434
  methods.push({ value: "ssh", label: "SSH Tunnel", hint: "run SSH on your Mac" });
403
435
  if (localIP) methods.push({ value: "lan", label: "Direct LAN", hint: localIP });
404
436
 
@@ -406,6 +438,8 @@ ${BOLD}What this does:${RESET}
406
438
 
407
439
  // ── Step 3: Resolve gateway URL ───────────────────────────────────────
408
440
  let gatewayURL;
441
+ let usedTailscaleServe = false;
442
+ const tailscaleHttpsPort = 8443;
409
443
 
410
444
  switch (method) {
411
445
  case "cloudflare": {
@@ -421,6 +455,22 @@ ${BOLD}What this does:${RESET}
421
455
  gatewayURL = tunnelURL;
422
456
  break;
423
457
  }
458
+ case "tailscale-https": {
459
+ process.stdout.write(`\n${DIM}Setting up Tailscale HTTPS on port ${tailscaleHttpsPort}...${RESET}`);
460
+ const served = setupTailscaleServe(port, tailscaleHttpsPort);
461
+ process.stdout.write("\r" + " ".repeat(70) + "\r");
462
+ if (served) {
463
+ gatewayURL = `https://${tailscaleDNS}:${tailscaleHttpsPort}`;
464
+ usedTailscaleServe = true;
465
+ ok(`Tailscale HTTPS active: ${gatewayURL}`);
466
+ } else {
467
+ // Fallback to raw IP
468
+ warn("tailscale serve failed, falling back to raw IP");
469
+ gatewayURL = `http://${tailscaleIP}:${port}`;
470
+ ok(`Using Tailscale IP: ${tailscaleIP}:${port}`);
471
+ }
472
+ break;
473
+ }
424
474
  case "tailscale": {
425
475
  gatewayURL = `http://${tailscaleIP}:${port}`;
426
476
  ok(`Using Tailscale: ${tailscaleIP}:${port}`);
@@ -457,14 +507,22 @@ ${BOLD}What this does:${RESET}
457
507
  console.log(`${DIM}Press Ctrl+C to stop.${RESET}\n`);
458
508
 
459
509
  // Graceful shutdown
510
+ const cleanup = () => {
511
+ if (usedTailscaleServe) {
512
+ console.log(`${DIM}Removing tailscale serve...${RESET}`);
513
+ teardownTailscaleServe(tailscaleHttpsPort);
514
+ }
515
+ server.close();
516
+ };
517
+
460
518
  process.on("SIGINT", () => {
461
519
  console.log(`\n${DIM}Shutting down bridge...${RESET}`);
462
- server.close();
520
+ cleanup();
463
521
  process.exit(0);
464
522
  });
465
523
 
466
524
  process.on("SIGTERM", () => {
467
- server.close();
525
+ cleanup();
468
526
  process.exit(0);
469
527
  });
470
528
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-navigator",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Self-contained Navigator bridge server — connects the Navigator browser to any machine",
5
5
  "license": "MIT",
6
6
  "bin": {