openzoo 0.48.53 → 0.48.55
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/brief.js +8 -10
- package/lib/info.js +38 -9
- package/package.json +1 -1
package/lib/brief.js
CHANGED
|
@@ -19,24 +19,22 @@
|
|
|
19
19
|
* not an API) because nothing in the conversation named the real one.
|
|
20
20
|
*/
|
|
21
21
|
export const briefFor = (selfUrl) => [
|
|
22
|
-
'
|
|
22
|
+
'Environment notes for this endpoint (descriptive — verify anything you rely on):',
|
|
23
23
|
'',
|
|
24
24
|
...(selfUrl ? [
|
|
25
|
-
|
|
25
|
+
`- Base URL: ${selfUrl}. It already ends in /v1, so routes are ${selfUrl}/chat/completions, ${selfUrl}/hrr/bind, ${selfUrl}/models. A doubled /v1 is repaired by the proxy but logs a warning. openzoo.fun is a website, not an API host.`,
|
|
26
26
|
'',
|
|
27
27
|
] : []),
|
|
28
|
-
'
|
|
28
|
+
'- Long bodies: requests over ~16KB are carved and bound to a holographic (HRR) memory before the model sees them, and the model answers from retrieval over that. So a large corpus can be sent whole; summarising or chunking it to fit is not required here, though nothing stops you. `context_length` in /v1/models reports the client-usable ceiling (128M tokens); the transformer window is `max_model_len`. A single POST over ~9.8M tokens (~32MiB) is rejected by the edge.',
|
|
29
29
|
'',
|
|
30
|
-
'
|
|
30
|
+
'- Repeat sends: a corpus placed first, followed by a blank line and then a question, binds once. Later questions reusing it ship only the question, which is cheaper and faster. Re-sending the same corpus each turn costs full price each time.',
|
|
31
31
|
'',
|
|
32
|
-
'
|
|
33
|
-
'
|
|
34
|
-
' Paths: your base_url already ends in /v1, so post to {base_url}/hrr/bind — NOT {base_url}/v1/hrr/bind (that double /v1 404s; the proxy repairs it, but do not rely on that).',
|
|
32
|
+
' Explicit bind (unpaid): POST /v1/hrr/bind with {"corpus": "..."} returns {"context_id": "..."}. Passing that id as the X-HRR-Context header on later /v1/chat/completions calls lets the body stay small. Passing an existing context_id alongside a new corpus appends to it, which is how a corpus larger than one request gets bound in parts.',
|
|
33
|
+
' Request size: single requests over ~8MB are dropped by the network hop before reaching the proxy (opaque 413 or dead connection). That is a request limit, not a context limit.',
|
|
35
34
|
'',
|
|
36
|
-
'
|
|
37
|
-
' AUTH, precisely: /hrr/bind and GET /models need NO key, so a script you write can call them directly. Paid endpoints (/chat/completions) need the bearer key your client is already configured with — you cannot read that key, so DO NOT write a standalone script that calls a paid endpoint. Bind from a script if you like, then ask through this conversation, which is already authenticated.',
|
|
35
|
+
'- Payment: calls are settled per request from the operator\'s own wallet via x402 (Solana / Base / Robinhood Chain, whichever is funded). There is no account to create and no key for you to supply or handle. GET / on this proxy returns the same description. /hrr/bind and GET /models are unpaid; /chat/completions is paid and uses the bearer key the client is already configured with, which is not readable from inside the conversation.',
|
|
38
36
|
'',
|
|
39
|
-
'
|
|
37
|
+
'- Model ids: unknown ids are matched to the nearest served model rather than erroring. /v1/models lists what is actually served, and each alias row carries `served_by`.',
|
|
40
38
|
].join('\n');
|
|
41
39
|
|
|
42
40
|
/** Back-compat: the briefing with no endpoint line. */
|
package/lib/info.js
CHANGED
|
@@ -38,11 +38,23 @@ async function quotedPrices() {
|
|
|
38
38
|
try {
|
|
39
39
|
// Imported here, not at module scope, matching affordableUsd below — this
|
|
40
40
|
// file is loaded by `openzoo address`, which must work with no network.
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
// PRICE OFF THE CHAT 402, NOT THE CREDIT 402.
|
|
42
|
+
//
|
|
43
|
+
// /v1/credits/topup sells a USD-denominated product, so every rail in its
|
|
44
|
+
// challenge quotes tokenUsd = 1 — a dollar of credit costs a dollar,
|
|
45
|
+
// whichever asset pays for it. Reading unit prices from there valued every
|
|
46
|
+
// holding at $1: MEASURED, a wallet of 776,302 TOKEN (actually worth ~$178 at the
|
|
47
|
+
// chat 402's 0.00022906) printed "$776302.53", and 1,985 ROBINHOODS worth
|
|
48
|
+
// ~$0.01 printed "$1985.78". Total "≈ $778288.41" for roughly $180 of
|
|
49
|
+
// assets — and `openzoo topup all` then tried to buy $758,819 of credit off
|
|
50
|
+
// that number.
|
|
51
|
+
//
|
|
52
|
+
// The chat challenge prices each asset at its real spot (DexScreener), and
|
|
53
|
+
// needs no namespace signature, so it is both correct and simpler.
|
|
54
|
+
const r = await fetch(`${config.apiBase}/v1/chat/completions`, {
|
|
43
55
|
method: 'POST',
|
|
44
|
-
headers:
|
|
45
|
-
body: JSON.stringify({
|
|
56
|
+
headers: { 'content-type': 'application/json' },
|
|
57
|
+
body: JSON.stringify({ model: config.defaultModel || 'anthropic/claude-sonnet-5', max_tokens: 1, messages: [{ role: 'user', content: 'x' }] }),
|
|
46
58
|
});
|
|
47
59
|
if (r.status !== 402) return out;
|
|
48
60
|
const ch = await r.json().catch(() => ({}));
|
|
@@ -180,15 +192,32 @@ export async function affordableUsd() {
|
|
|
180
192
|
export async function topUp(usdArg) {
|
|
181
193
|
// "all" spends everything the wallet can cover, minus a small margin so a
|
|
182
194
|
// price tick between quote and settle does not fail the payment outright.
|
|
195
|
+
// A BARE `openzoo topup` IS NOT `all`.
|
|
196
|
+
//
|
|
197
|
+
// It used to be, and the result was alarming: with a TOKEN-heavy wallet the
|
|
198
|
+
// no-arg form printed "wallet covers ~$782288.39 — buying $758819.73" and only
|
|
199
|
+
// THEN hit the 1-500 clamp and threw. Nothing was ever spent, but a user
|
|
200
|
+
// reading their terminal has every reason to think a three-quarter-million
|
|
201
|
+
// dollar purchase just started. A command with no argument prints usage and
|
|
202
|
+
// touches no wallet.
|
|
203
|
+
if (usdArg === undefined || usdArg === null || String(usdArg).trim() === '') {
|
|
204
|
+
throw new Error('usage: openzoo topup <usd|all> (1-500)');
|
|
205
|
+
}
|
|
206
|
+
const MAX_TOPUP = 500;
|
|
183
207
|
let usd = Number(usdArg);
|
|
184
|
-
if (String(usdArg).toLowerCase() === 'all'
|
|
208
|
+
if (String(usdArg).toLowerCase() === 'all') {
|
|
185
209
|
const max = await affordableUsd();
|
|
186
|
-
|
|
210
|
+
// CLAMP TO THE CEILING THE VALIDATOR ENFORCES. Without this, "all" on any
|
|
211
|
+
// wallet worth more than ~$515 computes a number the very next line
|
|
212
|
+
// rejects, so the feature was unusable for exactly the wallets it was for.
|
|
213
|
+
usd = Math.min(Math.floor(max * 0.97 * 100) / 100, MAX_TOPUP);
|
|
187
214
|
if (!(usd >= 1)) throw new Error(`wallet covers only $${max.toFixed(4)} of credit — fund it first (openzoo balance)`);
|
|
188
|
-
console.log(
|
|
215
|
+
console.log(max > MAX_TOPUP
|
|
216
|
+
? `wallet covers ~$${max.toFixed(2)} — buying $${usd.toFixed(2)} (per-topup max is $${MAX_TOPUP}; run it again for more)`
|
|
217
|
+
: `wallet covers ~$${max.toFixed(2)} — buying $${usd.toFixed(2)}`);
|
|
189
218
|
}
|
|
190
|
-
if (!Number.isFinite(usd) || usd < 1 || usd >
|
|
191
|
-
throw new Error(
|
|
219
|
+
if (!Number.isFinite(usd) || usd < 1 || usd > MAX_TOPUP) {
|
|
220
|
+
throw new Error(`usage: openzoo topup <usd|all> (1-${MAX_TOPUP})`);
|
|
192
221
|
}
|
|
193
222
|
const { PayClient } = await import('./pay.js');
|
|
194
223
|
const client = new PayClient();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.48.
|
|
3
|
+
"version": "0.48.55",
|
|
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",
|