openzoo 0.24.0 → 0.26.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/bin/openzoo.js +5 -4
- package/lib/setup.js +71 -2
- package/package.json +1 -1
package/bin/openzoo.js
CHANGED
|
@@ -12,10 +12,11 @@ usage:
|
|
|
12
12
|
a missing dir is created)
|
|
13
13
|
--profile use an isolated editor profile the
|
|
14
14
|
vendor account cannot re-sync over
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
--block-backend OPT-IN: point cursor's own backend
|
|
16
|
+
at 127.0.0.1 so it cannot re-sync over your
|
|
17
|
+
model list. WARNING: that host also serves
|
|
18
|
+
cursor's own catalog, so the picker may show
|
|
19
|
+
only "Auto". Undo: npx openzoo unblock
|
|
19
20
|
npx openzoo vscode [path] same, for VS Code
|
|
20
21
|
npx openzoo editor [path] whichever is installed (Cursor wins if both)
|
|
21
22
|
npx openzoo launch <cmd> [args] launch a TERMINAL Messages API client
|
package/lib/setup.js
CHANGED
|
@@ -193,8 +193,48 @@ async function proxyUp(base) {
|
|
|
193
193
|
} catch { return false; }
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
|
|
197
|
+
/** Facts about THIS run, before anything can go wrong silently. */
|
|
198
|
+
async function printStartupDiagnostic(base, which) {
|
|
199
|
+
const q = (fn, dflt = '?') => { try { return fn(); } catch { return dflt; } };
|
|
200
|
+
let version = '?';
|
|
201
|
+
try {
|
|
202
|
+
const here = path.dirname(new URL(import.meta.url).pathname);
|
|
203
|
+
version = JSON.parse(fs.readFileSync(path.join(here, '..', 'package.json'), 'utf8')).version;
|
|
204
|
+
} catch { /* keep ? */ }
|
|
205
|
+
|
|
206
|
+
const picked = q(() => pickEditor(which), null);
|
|
207
|
+
let hosts = 'n/a';
|
|
208
|
+
try {
|
|
209
|
+
const { isBlocked, BACKEND_HOSTS } = await import('./hosts.js');
|
|
210
|
+
hosts = isBlocked() ? `blocked (${BACKEND_HOSTS.join(', ')})` : 'NOT blocked';
|
|
211
|
+
} catch { /* n/a */ }
|
|
212
|
+
|
|
213
|
+
const portBusy = await proxyUp(base);
|
|
214
|
+
|
|
215
|
+
console.log('openzoo diagnostic');
|
|
216
|
+
console.log(` version : ${version} node ${process.version} ${process.platform}/${process.arch}`);
|
|
217
|
+
console.log(` port ${config.port} : ${portBusy ? 'ALREADY SERVING (an older proxy may still be running — kill it if this build is newer)' : 'free'}`);
|
|
218
|
+
console.log(` editor : ${picked ? `${picked.which} @ ${picked.cmd}` : 'NONE FOUND'}`);
|
|
219
|
+
console.log(` running : ${picked ? (q(() => editorRunning(picked.which), false) ? 'yes — will be quit so settings stick' : 'no') : '-'}`);
|
|
220
|
+
console.log(` backend : ${hosts}`);
|
|
221
|
+
console.log(` upstream : ${config.apiBase}`);
|
|
222
|
+
const envs = ['OPENZOO_DEFAULT_MODEL', 'OPENZOO_EDITOR_MODELS', 'OPENZOO_EDITOR_MAP', 'OPENZOO_NO_LABELS', 'OPENZOO_NO_TUNNEL']
|
|
223
|
+
.filter((k) => process.env[k]).map((k) => `${k}=${process.env[k]}`);
|
|
224
|
+
if (envs.length) console.log(` env : ${envs.join(' ')}`);
|
|
225
|
+
console.log('');
|
|
226
|
+
}
|
|
227
|
+
|
|
196
228
|
export async function setupEditor(which, target) {
|
|
197
229
|
const base = `http://localhost:${config.port}/v1`;
|
|
230
|
+
|
|
231
|
+
// STARTUP DIAGNOSTIC. Printed unconditionally because every hard bug tonight
|
|
232
|
+
// was invisible from the outside: a STALE BUILD writing old config (npm caches
|
|
233
|
+
// metadata and silently serves an older version), a hosts block that never
|
|
234
|
+
// applied because the sudo prompt was skipped, an editor that was still running
|
|
235
|
+
// so it clobbered the write, a tunnel that printed a URL and never served.
|
|
236
|
+
// One block up front turns each of those from a guess into a fact.
|
|
237
|
+
await printStartupDiagnostic(base, which);
|
|
198
238
|
const mcpFile = addMcpServer(MCP_FILES[which] || MCP_FILES.cursor);
|
|
199
239
|
|
|
200
240
|
// 1. PROXY + TUNNEL. Start in-process if nothing is listening, so the user
|
|
@@ -360,6 +400,18 @@ export async function setupEditor(which, target) {
|
|
|
360
400
|
? ' pinned -> yes (the editor re-syncs these from its account; a DB trigger re-applies them)'
|
|
361
401
|
: ` pinned -> NO (${pin?.error || 'unavailable'}) — the editor may revert these on launch`);
|
|
362
402
|
console.log(' verify: send one message, watch for "paid $0.0… · rail solana · tx …" here.');
|
|
403
|
+
// READ-BACK, not what we intended to write. A pin trigger or a running editor
|
|
404
|
+
// can rewrite this between the write and the launch, and that silent revert
|
|
405
|
+
// is exactly what made the editor point at a dead tunnel for hours.
|
|
406
|
+
try {
|
|
407
|
+
const back = writeEditorProviderConfig(target0, { baseUrl: editorBase, models, apiKey: tunnelKey })?.verified;
|
|
408
|
+
console.log(' db now : baseUrl=' + (back?.openAIBaseUrl || '?'));
|
|
409
|
+
console.log(' models =' + (Array.isArray(back?.availableAPIKeyModels)
|
|
410
|
+
? back.availableAPIKeyModels.map((m) => m.name).join(', ') : '?'));
|
|
411
|
+
if (back?.openAIBaseUrl && back.openAIBaseUrl !== editorBase) {
|
|
412
|
+
console.log(' WARNING : the database does NOT match what we wrote — something is reverting it.');
|
|
413
|
+
}
|
|
414
|
+
} catch (e) { console.log(' db now : could not read back (' + e.message + ')'); }
|
|
363
415
|
}
|
|
364
416
|
|
|
365
417
|
// 2b. THE BACKEND BLOCK. Pinning the database is not sufficient on its own:
|
|
@@ -368,13 +420,30 @@ export async function setupEditor(which, target) {
|
|
|
368
420
|
// route its own inference takes. Blackholing it in the hosts file is what
|
|
369
421
|
// leaves the configured base URL as the only way out. System-wide and
|
|
370
422
|
// needs a password, so it is opt-in and reversible.
|
|
371
|
-
|
|
423
|
+
// THE BACKEND BLOCK IS NOW OPT-IN — it was doing more harm than good.
|
|
424
|
+
//
|
|
425
|
+
// Blackholing api2.cursor.sh stopped the editor re-syncing its model list over
|
|
426
|
+
// ours, which was real. But that same host serves the editor's OWN catalog and
|
|
427
|
+
// auth, so blocking it means the picker cannot populate — the symptom is a
|
|
428
|
+
// picker showing only "Auto" and every named model "unavailable". It also
|
|
429
|
+
// re-applied itself on every run, so a user who removed the line by hand got it
|
|
430
|
+
// straight back and could not tell why.
|
|
431
|
+
// Routing does not need it: the editor honours the custom base URL on its own.
|
|
432
|
+
if (target0 === 'cursor' && process.argv.includes('--block-backend')) {
|
|
372
433
|
const { blockBackend, isBlocked } = await import('./hosts.js');
|
|
373
434
|
const r = blockBackend();
|
|
374
435
|
if (r.already) console.log('backend: already blocked (npx openzoo unblock to restore)');
|
|
375
|
-
else console.log(`backend: ${isBlocked() ? 'blocked -> 127.0.0.1' : 'NOT blocked
|
|
436
|
+
else console.log(`backend: ${isBlocked() ? 'blocked -> 127.0.0.1' : 'NOT blocked'}`);
|
|
437
|
+
} else if (target0 === 'cursor') {
|
|
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
|
+
}
|
|
376
444
|
}
|
|
377
445
|
|
|
446
|
+
|
|
378
447
|
// 3. LAUNCH with that env. Editor resolved platform-agnostically; Cursor
|
|
379
448
|
// wins when both are installed.
|
|
380
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.26.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",
|