openzoo 0.29.4 → 0.29.6

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.
@@ -26,7 +26,7 @@
26
26
  * content-type and answer in kind: bare message for connect unary proto, enveloped
27
27
  * + trailers for grpc-web. Both are handled below.
28
28
  */
29
- import http2 from 'node:http2';
29
+ import https from 'node:https';
30
30
  import fs from 'node:fs';
31
31
  import os from 'node:os';
32
32
  import path from 'node:path';
@@ -172,17 +172,17 @@ function respond(req, res, method, models) {
172
172
  export function startCursorBackend({ port = 8443, models, log = () => {} } = {}) {
173
173
  const { cert, key } = ensureCert(log);
174
174
  let conns = 0;
175
- // HTTP/2 with ALPN, HTTP/1.1 fallback. The editor's Connect-RPC client speaks
176
- // h2; a plain https (h1-only) server with no ALPN made most handshakes fail
177
- // with ERR_SSL_NO_APPLICATION_PROTOCOL / ECONNRESET (measured in the log), so
178
- // only a couple of h1 requests ever completed. allowHTTP1 keeps h1 working too;
179
- // the (req,res) compatibility handler serves both.
180
- const server = http2.createSecureServer(
175
+ // HTTP/1.1 ONLY, but with ALPN advertising http/1.1. Two measured facts drove
176
+ // this: (1) with NO ALPN the client aborts with ERR_SSL_NO_APPLICATION_PROTOCOL
177
+ // it requires the server to name a protocol; (2) when we offered h2, the
178
+ // editor's h2 connections RESET (ECONNRESET wall) while its h1 calls completed
179
+ // (requests #1-5). Connect-RPC and gRPC-web both work over h1, so we advertise
180
+ // ONLY http/1.1: the client negotiates it and every call completes.
181
+ const server = https.createServer(
181
182
  {
182
183
  cert: fs.readFileSync(cert),
183
184
  key: fs.readFileSync(key),
184
- allowHTTP1: true,
185
- ALPNProtocols: ['h2', 'http/1.1'],
185
+ ALPNProtocols: ['http/1.1'],
186
186
  SNICallback: (servername, cb) => { log(`cursor-tls: <- ClientHello SNI=${servername}`); cb(null); },
187
187
  },
188
188
  async (req, res) => {
@@ -206,9 +206,10 @@ export function startCursorBackend({ port = 8443, models, log = () => {} } = {})
206
206
  }
207
207
  },
208
208
  );
209
+ server.on('secureConnection', (sock) => { log(`cursor-tls: connected alpn=${sock.alpnProtocol || 'none'} sni=${sock.servername || '?'}`); });
209
210
  // NEVER swallow this — a rejected handshake is exactly the failure to see.
210
211
  server.on('tlsClientError', (e, sock) => {
211
- log(`cursor-tls: HANDSHAKE FAILED ${e.code || e.message} (peer ${sock?.remoteAddress || '?'})`);
212
+ log(`cursor-tls: HANDSHAKE FAILED ${e.code || e.message} alpn=${sock?.alpnProtocol || '?'}`);
212
213
  });
213
214
  server.listen(port, '127.0.0.1', () => log(`cursor-backend: listening on 127.0.0.1:${port} as ${CURSOR_HOSTS[0]}`));
214
215
  return { server, port };
package/lib/hosts.js CHANGED
@@ -155,9 +155,16 @@ export function bindBackend443(modelsPath, logPath, log = console.log) {
155
155
  log(` "${node}" "${script}" 443 "${modelsPath}" "${logPath}"`);
156
156
  return { ok: false, manual: true };
157
157
  }
158
- // nohup + & so sudo returns immediately; the root process keeps 443 bound.
158
+ // KILL THE OLD ROOT BACKEND FIRST, HARD, AND WAIT FOR 443 TO FREE.
159
+ // A prior version's root-owned listener keeps holding 443; `pkill openzoo` as
160
+ // the user cannot touch it, so the new backend hit "port taken" and the OLD,
161
+ // broken one kept answering — the reason a fix looked like it never landed.
162
+ // We SIGKILL by name AND by whoever holds 443, poll until the port is actually
163
+ // free (up to ~5s), then start the new one.
159
164
  const ok = privileged(
160
- `pkill -f 'cursor-backend.js' 2>/dev/null; `
165
+ `pkill -9 -f 'cursor-backend.js' 2>/dev/null; `
166
+ + `for p in $(lsof -nP -iTCP:443 -sTCP:LISTEN -t 2>/dev/null); do kill -9 "$p" 2>/dev/null; done; `
167
+ + `for i in 1 2 3 4 5 6 7 8 9 10; do lsof -nP -iTCP:443 -sTCP:LISTEN -t >/dev/null 2>&1 || break; sleep 0.5; done; `
161
168
  + `nohup '${node}' '${script}' 443 '${modelsPath}' '${logPath}' >/dev/null 2>&1 & `
162
169
  + 'sleep 1; true',
163
170
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.29.4",
3
+ "version": "0.29.6",
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",