openzoo 0.21.6 → 0.21.8
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/setup.js +45 -12
- package/package.json +1 -1
package/lib/setup.js
CHANGED
|
@@ -202,17 +202,26 @@ export async function setupEditor(which, target) {
|
|
|
202
202
|
// With --edge-ip-version 4 the tunnel comes up in seconds; if it somehow
|
|
203
203
|
// does not, we say so plainly and still launch.
|
|
204
204
|
if (!publicUrl) {
|
|
205
|
-
|
|
206
|
-
|
|
205
|
+
// VISIBLY ALIVE, AND SHORT. A silent 90s wait is indistinguishable from a
|
|
206
|
+
// hang — which is exactly how it was read, correctly. One dot per second
|
|
207
|
+
// with a countdown, capped at 25s, because with --edge-ip-version 4 a
|
|
208
|
+
// healthy tunnel registers in ~5-10s; longer than that means it is broken,
|
|
209
|
+
// not slow, and waiting more does not help.
|
|
210
|
+
const LIMIT = Number(process.env.OPENZOO_TUNNEL_WAIT_S || 25);
|
|
211
|
+
for (let i = 0; i < LIMIT * 2 && !started?.publicUrl; i++) {
|
|
207
212
|
await new Promise((r) => setTimeout(r, 500));
|
|
208
|
-
if (i %
|
|
213
|
+
if (i % 2 === 1) process.stdout.write(`\rwaiting for the public tunnel — ${LIMIT - Math.floor(i / 2) - 1}s `);
|
|
209
214
|
}
|
|
210
|
-
|
|
215
|
+
process.stdout.write('\r\x1b[K');
|
|
211
216
|
publicUrl = started?.publicUrl ?? null;
|
|
212
217
|
tunnelKey = started?.tunnelToken ?? tunnelKey;
|
|
213
218
|
}
|
|
214
219
|
if (publicUrl) console.log(`tunnel: ${publicUrl}/v1 api_key ${tunnelKey}`);
|
|
215
|
-
else
|
|
220
|
+
else {
|
|
221
|
+
console.log('tunnel: did NOT come up. cloudflared could not reach Cloudflare\'s edge.');
|
|
222
|
+
console.log(' most common cause here: no working IPv6 route (we already force');
|
|
223
|
+
console.log(' --edge-ip-version 4). check: npx openzoo tunnel for the raw log.');
|
|
224
|
+
}
|
|
216
225
|
} else {
|
|
217
226
|
console.log(`proxy already running on ${base}`);
|
|
218
227
|
// A proxy someone else started owns the tunnel; ask it for the public URL.
|
|
@@ -276,15 +285,39 @@ export async function setupEditor(which, target) {
|
|
|
276
285
|
const models = await catalogModels(base);
|
|
277
286
|
let wrote = null;
|
|
278
287
|
if (editorBase) {
|
|
288
|
+
// UNPIN FIRST — THIS IS THE BUG THAT BROKE THE TUNNEL ALL NIGHT.
|
|
289
|
+
// pinEditorProviderConfig installs a SQL trigger that re-applies the URL it
|
|
290
|
+
// was pinned with on EVERY update to that row. A previous run's trigger
|
|
291
|
+
// therefore silently rewrote each new tunnel URL back to its own, dead one:
|
|
292
|
+
// the banner printed the live tunnel while the DB (and Cursor) got the old
|
|
293
|
+
// hostname, which answered 530. Observed verbatim in one run —
|
|
294
|
+
// tunnel: https://friendly-api-suppliers-suits.trycloudflare.com/v1
|
|
295
|
+
// settings: openAIBaseUrl -> https://motors-multiple-parade-surround...
|
|
296
|
+
// Two hostnames, one run, because the printed value is read BACK from the DB
|
|
297
|
+
// after the trigger has had its say.
|
|
298
|
+
try { unpinEditorProviderConfig(target0); } catch { /* nothing pinned yet */ }
|
|
279
299
|
try { wrote = writeEditorProviderConfig(target0, { baseUrl: editorBase, models, apiKey: tunnelKey }); } catch (e) { wrote = { error: e.message }; }
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
300
|
+
// SELF-HEAL: verify what actually landed, and if anything rewrote it, drop
|
|
301
|
+
// the pin and write again rather than launching an editor we know is
|
|
302
|
+
// pointed at a dead host.
|
|
303
|
+
for (let attempt = 0; attempt < 2 && wrote && !wrote.error; attempt++) {
|
|
304
|
+
const got = wrote.verified?.openAIBaseUrl;
|
|
305
|
+
if (!got || got === editorBase) break;
|
|
306
|
+
console.log(`settings: something rewrote the url (${got}) — unpinning and retrying`);
|
|
307
|
+
try { unpinEditorProviderConfig(target0); } catch { /* ignore */ }
|
|
308
|
+
try { wrote = writeEditorProviderConfig(target0, { baseUrl: editorBase, models, apiKey: tunnelKey }); } catch (e) { wrote = { error: e.message }; }
|
|
309
|
+
}
|
|
287
310
|
const pin = pinEditorProviderConfig(target0, { baseUrl: editorBase, models });
|
|
311
|
+
// A pin that re-applies the WRONG url is worse than no pin at all.
|
|
312
|
+
try {
|
|
313
|
+
const after = writeEditorProviderConfig(target0, { baseUrl: editorBase, models, apiKey: tunnelKey });
|
|
314
|
+
const got = after?.verified?.openAIBaseUrl;
|
|
315
|
+
if (got && got !== editorBase) {
|
|
316
|
+
console.log(`settings: the pin re-applied ${got} — removing it so the live url stands`);
|
|
317
|
+
unpinEditorProviderConfig(target0);
|
|
318
|
+
writeEditorProviderConfig(target0, { baseUrl: editorBase, models, apiKey: tunnelKey });
|
|
319
|
+
}
|
|
320
|
+
} catch { /* advisory */ }
|
|
288
321
|
console.log(` models -> ${models.join(', ')}`);
|
|
289
322
|
console.log(` selected -> ${models[0]}`);
|
|
290
323
|
console.log(pin?.pinned
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.8",
|
|
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",
|