fluxy-bot 0.5.70 → 0.5.72

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxy-bot",
3
- "version": "0.5.70",
3
+ "version": "0.5.72",
4
4
  "releaseNotes": [
5
5
  "Fixed some bugs to iOs ",
6
6
  "2. ",
@@ -784,17 +784,18 @@ export async function startSupervisor() {
784
784
  config.tunnelUrl = tunnelUrl;
785
785
  saveConfig(config);
786
786
 
787
- // Wait for the tunnel to be reachable before telling the relay about it.
787
+ // Wait for local server to be reachable before telling the relay.
788
+ // Probes localhost directly — avoids macOS issue where server can't
789
+ // reach itself through the Cloudflare tunnel URL.
788
790
  let tunnelReady = false;
789
- log.info(`Readiness probe: waiting for tunnel ${tunnelUrl}`);
791
+ log.info('Readiness probe: waiting for local server...');
790
792
  for (let i = 0; i < 30; i++) {
791
793
  try {
792
- const res = await fetch(tunnelUrl + `/api/health?_cb=${Date.now()}`, {
794
+ const res = await fetch(`http://127.0.0.1:${config.port}/api/health?_cb=${Date.now()}`, {
793
795
  signal: AbortSignal.timeout(3000),
794
- headers: { 'Cache-Control': 'no-cache, no-store' },
795
796
  });
796
797
  log.info(`Readiness probe #${i + 1}: ${res.status}`);
797
- if (res.status !== 502 && res.status !== 503) {
798
+ if (res.ok) {
798
799
  tunnelReady = true;
799
800
  break;
800
801
  }
@@ -804,7 +805,7 @@ export async function startSupervisor() {
804
805
  await new Promise(r => setTimeout(r, 1000));
805
806
  }
806
807
  if (!tunnelReady) {
807
- log.warn('Tunnel readiness probe timed out — updating relay anyway');
808
+ log.warn('Local server readiness probe timed out — updating relay anyway');
808
809
  }
809
810
 
810
811
  // Now register tunnel URL with relay and start heartbeats
@@ -837,17 +838,16 @@ export async function startSupervisor() {
837
838
  config.tunnelUrl = tunnelUrl;
838
839
  saveConfig(config);
839
840
 
840
- // Readiness probe against the user's domain
841
+ // Readiness probe check local server (not tunnel URL, avoids macOS self-reach issue)
841
842
  let tunnelReady = false;
842
- log.info(`Readiness probe: waiting for tunnel ${tunnelUrl}`);
843
+ log.info('Readiness probe: waiting for local server...');
843
844
  for (let i = 0; i < 30; i++) {
844
845
  try {
845
- const res = await fetch(tunnelUrl + `/api/health?_cb=${Date.now()}`, {
846
+ const res = await fetch(`http://127.0.0.1:${config.port}/api/health?_cb=${Date.now()}`, {
846
847
  signal: AbortSignal.timeout(3000),
847
- headers: { 'Cache-Control': 'no-cache, no-store' },
848
848
  });
849
849
  log.info(`Readiness probe #${i + 1}: ${res.status}`);
850
- if (res.status !== 502 && res.status !== 503) {
850
+ if (res.ok) {
851
851
  tunnelReady = true;
852
852
  break;
853
853
  }
@@ -857,7 +857,7 @@ export async function startSupervisor() {
857
857
  await new Promise(r => setTimeout(r, 1000));
858
858
  }
859
859
  if (!tunnelReady) {
860
- log.warn('Named tunnel readiness probe timed out');
860
+ log.warn('Local server readiness probe timed out');
861
861
  }
862
862
 
863
863
  console.log('__READY__');
@@ -880,7 +880,7 @@ export async function startSupervisor() {
880
880
  lastTick = now; // Update immediately so concurrent ticks don't see a stale gap
881
881
 
882
882
  if (wakeGap || periodicCheck) {
883
- const alive = await isTunnelAlive(tunnelUrl!);
883
+ const alive = await isTunnelAlive(tunnelUrl!, config.port);
884
884
  if (!alive) {
885
885
  log.warn('Tunnel dead, restarting...');
886
886
  try {
@@ -892,26 +892,8 @@ export async function startSupervisor() {
892
892
  // Quick tunnel: restart and get new URL
893
893
  const newUrl = await restartTunnel(config.port);
894
894
 
895
- // Wait for the new tunnel to be reachable before updating the relay
896
- log.info(`Waiting for new tunnel to become reachable: ${newUrl}`);
897
- let tunnelReady = false;
898
- for (let i = 0; i < 30; i++) {
899
- try {
900
- const res = await fetch(newUrl + `/api/health?_cb=${Date.now()}`, {
901
- signal: AbortSignal.timeout(3000),
902
- headers: { 'Cache-Control': 'no-cache, no-store' },
903
- });
904
- if (res.status !== 502 && res.status !== 503) {
905
- tunnelReady = true;
906
- log.info(`Tunnel reachable after ${i + 1} probes`);
907
- break;
908
- }
909
- } catch {}
910
- await new Promise(r => setTimeout(r, 1000));
911
- }
912
- if (!tunnelReady) {
913
- log.warn('Tunnel readiness probe timed out — updating relay anyway');
914
- }
895
+ // Brief pause to let cloudflared establish the tunnel
896
+ await new Promise(r => setTimeout(r, 3000));
915
897
 
916
898
  tunnelUrl = newUrl;
917
899
 
@@ -116,19 +116,33 @@ export function stopTunnel(): void {
116
116
  proc = null;
117
117
  }
118
118
 
119
- export async function isTunnelAlive(url: string): Promise<boolean> {
120
- // Two attempts with a short gap — avoids false positives from transient Cloudflare errors
121
- for (let attempt = 0; attempt < 2; attempt++) {
119
+ /** Check if the cloudflared child process is still running */
120
+ export function isTunnelProcessAlive(): boolean {
121
+ return proc !== null && proc.exitCode === null && proc.signalCode === null;
122
+ }
123
+
124
+ export async function isTunnelAlive(url: string, localPort?: number): Promise<boolean> {
125
+ // 1. Process check — if cloudflared exited, tunnel is definitely dead
126
+ if (!isTunnelProcessAlive()) return false;
127
+
128
+ // 2. Local reachability check — confirm the local server is still responding.
129
+ // We probe localhost directly instead of the tunnel URL because on macOS
130
+ // the server can't reach itself through the Cloudflare tunnel (DNS/firewall).
131
+ // If localhost responds and cloudflared is running, the tunnel is alive.
132
+ if (localPort) {
122
133
  try {
123
- const res = await fetch(url + `/api/health?_cb=${Date.now()}`, {
124
- signal: AbortSignal.timeout(8000),
125
- headers: { 'Cache-Control': 'no-cache, no-store' },
134
+ const res = await fetch(`http://127.0.0.1:${localPort}/api/health?_cb=${Date.now()}`, {
135
+ signal: AbortSignal.timeout(3000),
126
136
  });
127
- if (res.status !== 502 && res.status !== 503) return true;
137
+ if (res.ok) return true;
128
138
  } catch {}
129
- if (attempt === 0) await new Promise(r => setTimeout(r, 3000));
139
+ // Local server not responding but cloudflared is alive, so tunnel is still up.
140
+ // The worker may be restarting. Don't kill the tunnel for a local issue.
141
+ return true;
130
142
  }
131
- return false;
143
+
144
+ // No local port provided — process alive is enough
145
+ return true;
132
146
  }
133
147
 
134
148
  export async function restartTunnel(port: number): Promise<string> {