openzoo 0.34.3 → 0.34.4

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/hosts.js +28 -4
  2. package/package.json +1 -1
package/lib/hosts.js CHANGED
@@ -269,9 +269,31 @@ export function bindBackend443(modelsPath, logPath, log = console.log) {
269
269
  );
270
270
  // Report whether it ACTUALLY came up rather than whether sudo exited 0 —
271
271
  // `nohup ... &` always succeeds, so `ok` alone said nothing about the bind.
272
- const listening = spawnSync('sh', ['-c',
273
- 'for i in 1 2 3 4 5 6 7 8; do lsof -nP -iTCP:443 -sTCP:LISTEN -t >/dev/null 2>&1 && exit 0; sleep 0.5; done; exit 1',
274
- ]).status === 0;
272
+ //
273
+ // PROBE BY CONNECTING, NOT BY lsof. The backend we just started is ROOT-owned;
274
+ // unprivileged `lsof -iTCP:443` cannot see another user's descriptors and exits
275
+ // 1 even while `netstat -an` shows `*.443 LISTEN`. That false negative made the
276
+ // caller tear down a WORKING setup and print "FAILED to bind" directly under
277
+ // the backend's own "listening on [::]+127.0.0.1:443" log line. A TCP connect
278
+ // is ownership-blind, and it proves the far more useful property anyway: that
279
+ // the socket actually accepts. Try both families — hosts.js pins both.
280
+ const listening = spawnSync(node, ['-e', `
281
+ const net = require('net');
282
+ const hit = (host) => new Promise((r) => {
283
+ const s = net.connect({ host, port: 443 });
284
+ s.setTimeout(1000);
285
+ s.on('connect', () => { s.destroy(); r(true); });
286
+ s.on('error', () => r(false));
287
+ s.on('timeout', () => { s.destroy(); r(false); });
288
+ });
289
+ (async () => {
290
+ for (let i = 0; i < 10; i++) {
291
+ if (await hit('127.0.0.1') || await hit('::1')) process.exit(0);
292
+ await new Promise((r) => setTimeout(r, 500));
293
+ }
294
+ process.exit(1);
295
+ })();
296
+ `], { timeout: 20000 }).status === 0;
275
297
  if (!listening) {
276
298
  log(` backend did NOT bind :443 — see ${logPath}`);
277
299
  try {
@@ -288,6 +310,8 @@ export function unbindBackend443() {
288
310
  return { ok: privileged(
289
311
  flushPf
290
312
  + "pkill -9 -f 'cursor-backend.js' 2>/dev/null; "
291
- + 'for p in $(lsof -nP -iTCP:8443 -sTCP:LISTEN -t 2>/dev/null); do kill -9 "$p" 2>/dev/null; done; true',
313
+ // 443 as well as 8443: the backend binds :443 directly now, and this runs
314
+ // under sudo so lsof CAN see the root-owned socket here.
315
+ + 'for p in $(lsof -nP -iTCP:443 -sTCP:LISTEN -t 2>/dev/null) $(lsof -nP -iTCP:8443 -sTCP:LISTEN -t 2>/dev/null); do kill -9 "$p" 2>/dev/null; done; true',
292
316
  ) };
293
317
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.34.3",
3
+ "version": "0.34.4",
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",