openzoo 0.23.0 → 0.24.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.
package/lib/cursorcfg.js CHANGED
@@ -109,6 +109,12 @@ const DEFAULT_SLOTS = {
109
109
  };
110
110
 
111
111
  export function slotFor(id) {
112
+ // KILL SWITCH: if a custom label ever makes the editor treat a row as
113
+ // unavailable, OPENZOO_NO_LABELS=1 puts the bland id back as the label. The
114
+ // mapping (which zoo model answers) is unaffected — only the text changes.
115
+ if (process.env.OPENZOO_NO_LABELS === '1') {
116
+ return { served: (DEFAULT_SLOTS[id] || {}).served || id, label: id };
117
+ }
112
118
  const env = process.env.OPENZOO_EDITOR_MAP;
113
119
  if (env) {
114
120
  for (const part of env.split(',')) {
package/lib/proxy.js CHANGED
@@ -285,6 +285,10 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
285
285
  // origin, not off whether the URL exists yet, so there is no startup window
286
286
  // where public traffic slips through ungated.
287
287
  let tunnelGate = null;
288
+ // How many chat requests actually ARRIVED. The single number that answers
289
+ // "is the editor really routing through us?" — an editor that silently keeps
290
+ // using its own backend leaves this at 0 while looking perfectly healthy.
291
+ let servedRequests = 0;
288
292
  let tunnelError = null;
289
293
 
290
294
  const server = http.createServer(async (req, res) => {
@@ -343,6 +347,7 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
343
347
  yourEndpoint: self,
344
348
  reachedVia: viaTunnel ? 'public tunnel' : 'localhost',
345
349
  publicTunnel: tunnelGate?.publicUrl ? `${tunnelGate.publicUrl}/v1` : null,
350
+ servedRequests,
346
351
  mcp: `${self.replace(/\/v1$/, '')}/mcp`,
347
352
  upstream: config.apiBase,
348
353
  payment: 'x402 per request from the operator\'s local burner wallet — no API key, no account',
@@ -467,6 +472,7 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
467
472
  // carries a model field, not just chat/completions, so /completions,
468
473
  // /responses and future shapes all work. Never silent.
469
474
  let wantsStream = false;
475
+ if ((req.url || '').includes('/chat/completions') && req.method === 'POST') servedRequests += 1;
470
476
  if (rewritablePath(req.method, req.url)) {
471
477
  const rw = await maybeRewriteModel(bodyBuf);
472
478
  if (rw) {
package/lib/setup.js CHANGED
@@ -416,6 +416,34 @@ export async function setupEditor(which, target) {
416
416
  console.error(`could not launch ${picked.which}: ${e.message}`);
417
417
  });
418
418
  child.unref();
419
+
420
+ // DID IT ACTUALLY ROUTE? The editor can look perfectly configured and still
421
+ // serve every message from its OWN backend — it answers normally, so a reply
422
+ // proves nothing. This watches the only number that does: chat requests that
423
+ // actually ARRIVED here. Costs nothing and ends the guessing.
424
+ (async () => {
425
+ const seen = async () => {
426
+ try {
427
+ const r = await fetch(`${base}/info`, { signal: AbortSignal.timeout(3000) });
428
+ return (await r.json())?.servedRequests ?? 0;
429
+ } catch { return 0; }
430
+ };
431
+ const before = await seen();
432
+ for (let i = 0; i < 40; i++) { // ~2 min
433
+ await new Promise((r) => setTimeout(r, 3000));
434
+ const now = await seen();
435
+ if (now > before) {
436
+ console.log(`\nROUTING CONFIRMED — ${now - before} request(s) reached the zoo.`);
437
+ console.log(' (a receipt line above shows what each one paid)');
438
+ return;
439
+ }
440
+ }
441
+ console.log('\nNOT ROUTING — 0 requests reached the zoo in 2 minutes.');
442
+ console.log(' The editor is answering from its OWN backend. Check, in order:');
443
+ console.log(' 1. did you QUIT the editor fully before this ran? it caches config at launch');
444
+ console.log(' 2. Settings -> Models -> "Override OpenAI Base URL" toggle is ON');
445
+ console.log(' 3. the model you picked is one of the ids written above');
446
+ })();
419
447
  // Keep this process alive when we own the proxy — killing it would kill the
420
448
  // zoo the editor was just pointed at.
421
449
  if (publicUrl || !(await proxyUp(base))) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
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",