openzoo 0.51.24 → 0.51.26
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 +31 -0
- package/package.json +1 -1
package/lib/proxy.js
CHANGED
|
@@ -998,6 +998,37 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
998
998
|
result = await client.fetch(url, init);
|
|
999
999
|
}
|
|
1000
1000
|
}
|
|
1001
|
+
// A 5xx IS NOT A REASON TO CHANGE THE MODEL. An earlier build routed any
|
|
1002
|
+
// gateway 5xx to OPENZOO_OUTAGE_FALLBACK and gated the model 60s. That
|
|
1003
|
+
// was wrong twice over: `/model fable-5.1` then reported `x402 door for
|
|
1004
|
+
// grok-4.6 failed`, so the caller read an error for a model they never
|
|
1005
|
+
// picked, and a silent substitution bills them for a DIFFERENT model's
|
|
1006
|
+
// answer than the one they chose and are reading. When the requested
|
|
1007
|
+
// model's door is down, say so about THAT model and let the caller
|
|
1008
|
+
// decide. Only the 402 "insufficient credits" branch above still
|
|
1009
|
+
// reroutes, because there the gateway itself refunds and the request
|
|
1010
|
+
// was never served at all.
|
|
1011
|
+
const RETRYABLE_5XX = new Set([500, 502, 503, 504]);
|
|
1012
|
+
if (RETRYABLE_5XX.has(result.response?.status)) {
|
|
1013
|
+
let detail = '';
|
|
1014
|
+
try { const j = await result.response.clone().json(); detail = String(j?.error?.message || j?.error || '').slice(0, 300); } catch { /* opaque 5xx */ }
|
|
1015
|
+
log(`upstream ${result.response.status} for ${outageKey(init)}${detail ? `: ${detail}` : ''} — surfacing as-is, model NOT swapped`);
|
|
1016
|
+
// "no door quoted <model>: … wrong asset/rail (base)" IS AN EMPTY
|
|
1017
|
+
// WALLET WEARING A 502. Measured 2026-09-13: Solana USDC ran down to
|
|
1018
|
+
// dust, the rail picker fell through to Base (which held $0.0016), and
|
|
1019
|
+
// every door that only quotes Solana refused the offer — grok-4.6,
|
|
1020
|
+
// deepseek and fable all "502"d while abliterated-model (~$0.0005/call)
|
|
1021
|
+
// still paid out of the dust and looked fine. The raw 502 sent the
|
|
1022
|
+
// harness into a reconnect storm and read like a dead model. Say what
|
|
1023
|
+
// it is, and name the model the caller actually asked for.
|
|
1024
|
+
if (/no door quoted|wrong asset\/rail/i.test(detail)) {
|
|
1025
|
+
const rail = /\(([^)]+)\)/.exec(detail.match(/wrong asset\/rail \([^)]*\)/i)?.[0] || '')?.[1] || '';
|
|
1026
|
+
let msg = `${outageKey(init)} could not be paid for: the x402 door refused the offer${rail ? ` on the ${rail} rail` : ''}. This is almost always an empty wallet on the rail that door takes — the request never reached the model, and nothing was charged.`;
|
|
1027
|
+
msg = await withOnrampLink(msg, { solana: client.address, evm: client.evmAddress, force: true });
|
|
1028
|
+
jsonErr(res, 402, msg);
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1001
1032
|
// A PAID 400 `invalid_tools` on a Responses body we did not flatten:
|
|
1002
1033
|
// this model is a function-tools-only door we had not learned yet.
|
|
1003
1034
|
// Flatten, remember it, and buy the turn once more — one billed miss
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.51.
|
|
3
|
+
"version": "0.51.26",
|
|
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",
|