openzoo 0.26.0 → 0.28.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/proxy.js +13 -4
- package/lib/setup.js +18 -18
- package/package.json +1 -1
package/lib/proxy.js
CHANGED
|
@@ -268,6 +268,12 @@ async function maybeCacheCorpus(req, bodyBuf, log) {
|
|
|
268
268
|
export async function startProxy({ silent = false, requireToken = null, sessionMaxUsd = null, autoTunnel = false } = {}) {
|
|
269
269
|
const client = new PayClient();
|
|
270
270
|
const log = silent ? () => {} : (...a) => console.log(...a);
|
|
271
|
+
// ALWAYS-ON. `silent: true` is used by the editor path to keep startup tidy,
|
|
272
|
+
// but it also swallowed the per-request lines and the payment receipts — so the
|
|
273
|
+
// terminal sat blank and there was no way to tell a working setup from an editor
|
|
274
|
+
// quietly answering from its own backend. Traffic and receipts are the whole
|
|
275
|
+
// point of watching this window; they are never silenced.
|
|
276
|
+
const say = (...a) => console.log(...a);
|
|
271
277
|
let sessionSpent = 0;
|
|
272
278
|
let tunnelSpent = 0;
|
|
273
279
|
// Live balance refresh state — the real implementation is assigned in the
|
|
@@ -472,7 +478,10 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
472
478
|
// carries a model field, not just chat/completions, so /completions,
|
|
473
479
|
// /responses and future shapes all work. Never silent.
|
|
474
480
|
let wantsStream = false;
|
|
475
|
-
if ((req.url || '').includes('/chat/completions') && req.method === 'POST')
|
|
481
|
+
if ((req.url || '').includes('/chat/completions') && req.method === 'POST') {
|
|
482
|
+
servedRequests += 1;
|
|
483
|
+
say(`\n<- request #${servedRequests} from ${(req.headers['user-agent'] || 'unknown').slice(0, 40)}`);
|
|
484
|
+
}
|
|
476
485
|
if (rewritablePath(req.method, req.url)) {
|
|
477
486
|
const rw = await maybeRewriteModel(bodyBuf);
|
|
478
487
|
if (rw) {
|
|
@@ -581,9 +590,9 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
581
590
|
}
|
|
582
591
|
const line = receipt.ok ? receipt.line : `paid retry -> HTTP ${receipt.status}`;
|
|
583
592
|
// Wherever a running total is the thing to watch, it rides the receipt.
|
|
584
|
-
if (requireToken)
|
|
585
|
-
else if (viaTunnel)
|
|
586
|
-
else
|
|
593
|
+
if (requireToken) say(`${line} · session $${sessionSpent.toFixed(6)}`);
|
|
594
|
+
else if (viaTunnel) say(`${line} · public-url session $${tunnelSpent.toFixed(6)}`);
|
|
595
|
+
else say(line);
|
|
587
596
|
scheduleRefresh(4000); // settlement lands on-chain in a few seconds
|
|
588
597
|
}
|
|
589
598
|
// Chat completions come back as one JSON object (settle-before-serve).
|
package/lib/setup.js
CHANGED
|
@@ -420,30 +420,30 @@ export async function setupEditor(which, target) {
|
|
|
420
420
|
// route its own inference takes. Blackholing it in the hosts file is what
|
|
421
421
|
// leaves the configured base URL as the only way out. System-wide and
|
|
422
422
|
// needs a password, so it is opt-in and reversible.
|
|
423
|
-
// THE BACKEND BLOCK IS
|
|
423
|
+
// THE BACKEND BLOCK IS REQUIRED FOR ROUTING — measured, not assumed.
|
|
424
424
|
//
|
|
425
|
-
//
|
|
426
|
-
//
|
|
427
|
-
//
|
|
428
|
-
//
|
|
429
|
-
//
|
|
430
|
-
//
|
|
431
|
-
//
|
|
432
|
-
|
|
425
|
+
// With api2.cursor.sh reachable the editor answers from its OWN backend and the
|
|
426
|
+
// custom base URL is never used: servedRequests stayed 0 through a whole session.
|
|
427
|
+
// With it blackholed, requests arrive and settle — two Solana payments at
|
|
428
|
+
// 10:38:27Z and 10:38:30Z on the same machine, same config, block on.
|
|
429
|
+
//
|
|
430
|
+
// The cost is that this host also serves the editor's own model catalog, so its
|
|
431
|
+
// picker cannot self-populate. That is fine BECAUSE WE WRITE THE MODELS
|
|
432
|
+
// OURSELVES (availableAPIKeyModels + availableDefaultModels2 above) — the picker
|
|
433
|
+
// is ours, not theirs. If our write fails, the picker collapses to "Auto", and
|
|
434
|
+
// that is the symptom to chase, not the block.
|
|
435
|
+
//
|
|
436
|
+
// --no-block opts out for anyone who would rather keep the vendor catalog.
|
|
437
|
+
if (target0 === 'cursor' && !process.argv.includes('--no-block')) {
|
|
433
438
|
const { blockBackend, isBlocked } = await import('./hosts.js');
|
|
434
439
|
const r = blockBackend();
|
|
435
|
-
if (r.already) console.log('backend: already blocked (npx openzoo unblock to
|
|
436
|
-
else console.log(
|
|
437
|
-
|
|
438
|
-
const { isBlocked } = await import('./hosts.js');
|
|
439
|
-
if (isBlocked()) {
|
|
440
|
-
console.log('backend: BLOCKED in /etc/hosts from an earlier run.');
|
|
441
|
-
console.log(' That stops the editor loading its own model catalog — if the picker');
|
|
442
|
-
console.log(' shows only "Auto", this is why. Undo with: npx openzoo unblock');
|
|
443
|
-
}
|
|
440
|
+
if (r.already) console.log('backend: already blocked (required for routing; npx openzoo unblock to undo)');
|
|
441
|
+
else if (isBlocked()) console.log('backend: blocked -> 127.0.0.1 (this is what forces the editor onto the zoo)');
|
|
442
|
+
else console.log('backend: NOT blocked — the editor will keep using its own backend and\n nothing will reach the zoo. Re-run and enter your password.');
|
|
444
443
|
}
|
|
445
444
|
|
|
446
445
|
|
|
446
|
+
|
|
447
447
|
// 3. LAUNCH with that env. Editor resolved platform-agnostically; Cursor
|
|
448
448
|
// wins when both are installed.
|
|
449
449
|
// Open the directory you ran this from, or the one you named. The earlier
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.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",
|