openzoo 0.21.1 → 0.21.2

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/lib/tunnel.js +17 -3
  2. package/package.json +1 -1
package/lib/tunnel.js CHANGED
@@ -105,10 +105,18 @@ export async function ensureCloudflared(log = console.log) {
105
105
  * edge-IP or protocol survives — so cascade instead of giving up.
106
106
  */
107
107
  const TUNNEL_RUNGS = [
108
+ // IPv4 FIRST, deliberately. cloudflared prefers IPv6+QUIC to reach the edge
109
+ // whenever the interface merely HAS an IPv6 address — it never checks the
110
+ // route is usable. MEASURED on a box with an IPv6 address and no IPv6 route:
111
+ // failed to dial to edge with quic: write udp6 [::]->[2606:4700:a8::1]:7844:
112
+ // sendmsg: no route to host
113
+ // ...on every retry, so the tunnel registered and immediately died and the
114
+ // edge served 502/530 — which looks exactly like a dead origin or a rate
115
+ // limit, and is neither. Forcing v4 registered first try on the same machine.
116
+ { args: ['--edge-ip-version', '4'], why: 'ipv4 edge' },
108
117
  { args: [], why: 'default (quic, auto edge ip)' },
109
- { args: ['--edge-ip-version', '4'], why: 'ipv4 edge (the ipv6 path failed to register)' },
118
+ { args: ['--edge-ip-version', '4', '--protocol', 'http2'], why: 'ipv4 + http2' },
110
119
  { args: ['--protocol', 'http2'], why: 'http2 (quic/udp blocked or lossy)' },
111
- { args: ['--edge-ip-version', '4', '--protocol', 'http2'], why: 'ipv4 + http2 (most conservative)' },
112
120
  ];
113
121
 
114
122
  /**
@@ -194,7 +202,13 @@ export function superviseTunnel({ bin, port, url, proc, log = () => {}, onRebind
194
202
  /** Start a quick tunnel to localhost:<port>; resolve with its public URL. */
195
203
  export function startCloudflared(bin, port, log, { args = [] } = {}) {
196
204
  return new Promise((resolve, reject) => {
197
- const proc = spawn(bin, ['tunnel', '--url', `http://localhost:${port}`, '--no-autoupdate', ...args], {
205
+ // 127.0.0.1, NOT localhost. MEASURED: the proxy binds IPv4 only, while
206
+ // `localhost` resolves to ::1 FIRST on macOS — cloudflared dialled the IPv6
207
+ // loopback, got connection-refused, and reported "Unable to reach the origin
208
+ // service" (502) on a tunnel that had registered with Cloudflare perfectly.
209
+ // Every rung failed identically, which is what made it look like a network
210
+ // or rate-limit problem when it was a loopback address-family mismatch.
211
+ const proc = spawn(bin, ['tunnel', '--url', `http://127.0.0.1:${port}`, '--no-autoupdate', ...args], {
198
212
  stdio: ['ignore', 'pipe', 'pipe'],
199
213
  });
200
214
  let settled = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.21.1",
3
+ "version": "0.21.2",
4
4
  "description": "Local x402-paying proxy + MCP server for openzoo.fun — point any OpenAI-compatible harness (Cursor, Claude Code, aider, SDKs) at localhost and it pays per call from a local burner wallet. Solana and Base rails live; Robinhood experimental.",
5
5
  "license": "MIT",
6
6
  "type": "module",