openzoo 0.48.59 → 0.48.61
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/mcp.js +13 -13
- package/lib/proxy.js +13 -3
- package/package.json +1 -1
package/lib/mcp.js
CHANGED
|
@@ -32,14 +32,14 @@ export function buildMcpServer() {
|
|
|
32
32
|
'openzoo — pay-per-call access to ~435 models (openzoo.fun). No API key, no account: each call is paid',
|
|
33
33
|
'from the operator\'s local burner wallet via x402 (Solana / Base / Robinhood Chain).',
|
|
34
34
|
'',
|
|
35
|
-
'
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
'
|
|
35
|
+
'Long bodies: zoo_ask\'s `corpus` accepts a whole document. leCore holographic memory sits in front of',
|
|
36
|
+
'every model, so a corpus is bound once and the model reads a few thousand tokens of it — summarising or',
|
|
37
|
+
'chunking to fit is not required here. Client-usable ceiling is ~128M tokens; a single call stays under',
|
|
38
|
+
'~9.8M. A corpus already bound is not re-uploaded, so later asks against it are near-free — asking many',
|
|
39
|
+
'questions of one corpus costs less than re-sending it. zoo_contexts lists what is bound.',
|
|
40
40
|
'',
|
|
41
|
-
'
|
|
42
|
-
'state
|
|
41
|
+
'There are no API keys or endpoints on the machine to find — payment is per-call from the wallet. zoo_wallet',
|
|
42
|
+
'shows funding state; zoo_models lists what is served with live pricing.',
|
|
43
43
|
'',
|
|
44
44
|
// Agents previously probed zoo_ask, got text back, and concluded the zoo
|
|
45
45
|
// could not do media at all — the text upstream serves NO video models.
|
|
@@ -48,9 +48,9 @@ export function buildMcpServer() {
|
|
|
48
48
|
' zoo_video asynchronous, returns a job id (Sora 2, Veo 3.1, Kling, Seedance, Wan, pixverse…)',
|
|
49
49
|
' zoo_video_result poll the job id — free, the render was paid for at submit',
|
|
50
50
|
'In zoo_models these carry kind="image" / kind="video" and are priced per image or per clip, not per token.',
|
|
51
|
-
'leCore does
|
|
52
|
-
'
|
|
53
|
-
'
|
|
51
|
+
'leCore does not participate in a render: a diffusion prompt never reaches the spill threshold, so holographic',
|
|
52
|
+
'memory has no effect on the picture. To ground a render in existing material, zoo_ask can',
|
|
53
|
+
'write the prompt from a bound corpus, and that prompt goes to zoo_image / zoo_video.',
|
|
54
54
|
'',
|
|
55
55
|
// ROUTING, STATED UNCONDITIONALLY. An agent whose OWN inference is not
|
|
56
56
|
// routed through the proxy never receives lib/brief.js, so it answers
|
|
@@ -74,7 +74,7 @@ export function buildMcpServer() {
|
|
|
74
74
|
server.registerTool('zoo_ask', {
|
|
75
75
|
description:
|
|
76
76
|
'Ask a question through openzoo.fun, paying the x402 quote transparently from the local burner wallet. '
|
|
77
|
-
+ '
|
|
77
|
+
+ 'Big context can go WHOLE into `corpus` — summarising, truncating or chunking to fit a context window is not required here. '
|
|
78
78
|
+ 'leCore holographic memory sits in front of every model, so a corpus far past the model\'s own limit '
|
|
79
79
|
+ '(client-usable ceiling ~128M tokens; keep one call under ~9.8M) is bound once and the model reads only '
|
|
80
80
|
+ 'a few thousand tokens of it. Re-asking against an already-bound corpus is near-free and much faster, so '
|
|
@@ -160,7 +160,7 @@ export function buildMcpServer() {
|
|
|
160
160
|
balances,
|
|
161
161
|
fundWith: rails ? railFundingHint(rails.live) : 'USDC or TOKEN on Solana',
|
|
162
162
|
solanaMints: Object.fromEntries(FUNDING_ASSETS.map((a) => [a.symbol, a.mint])),
|
|
163
|
-
tellTheUser: '
|
|
163
|
+
tellTheUser: 'The wallet above needs funding by the operator. This is not fixable from inside the conversation, and a retry fails identically until it is funded.',
|
|
164
164
|
}),
|
|
165
165
|
isError: true,
|
|
166
166
|
};
|
|
@@ -411,7 +411,7 @@ export function buildMcpServer() {
|
|
|
411
411
|
files: out.files.length,
|
|
412
412
|
parts: out.parts,
|
|
413
413
|
reused: out.reused,
|
|
414
|
-
next: `
|
|
414
|
+
next: `zoo_ask with context_id="${out.contextId}" and a question answers from this corpus; it is already bound, so pasting it into the prompt would send it twice.`,
|
|
415
415
|
});
|
|
416
416
|
} catch (e) {
|
|
417
417
|
return text({ error: e.message });
|
package/lib/proxy.js
CHANGED
|
@@ -1266,7 +1266,7 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
1266
1266
|
} catch (err) {
|
|
1267
1267
|
log(`context cache skipped for this call: ${err.message}`);
|
|
1268
1268
|
}
|
|
1269
|
-
const send = (buf, ctxId, topK) => client.fetch(url, {
|
|
1269
|
+
const send = (buf, ctxId, topK, corpusChars) => client.fetch(url, {
|
|
1270
1270
|
...init,
|
|
1271
1271
|
body: buf,
|
|
1272
1272
|
headers: ctxId
|
|
@@ -1275,6 +1275,16 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
1275
1275
|
'x-hrr-context': ctxId,
|
|
1276
1276
|
// Only on the spill path — a caller that set its own top-k keeps it.
|
|
1277
1277
|
...(topK ? { 'x-hrr-top-k': String(topK) } : {}),
|
|
1278
|
+
// TELL THE GATEWAY HOW BIG THE CORPUS IS. It has been guessing:
|
|
1279
|
+
// `contextChars` is populated only when a bind passes through the
|
|
1280
|
+
// gateway itself, so on an APPEND — and on every corpus that
|
|
1281
|
+
// includes files the agent read, which never appear in a request
|
|
1282
|
+
// body at all — it has no idea and falls back to the body size.
|
|
1283
|
+
// That is why the counterfactual logged `corpus ?` all day and why
|
|
1284
|
+
// a call whose corpus held 40,777 tokens priced as if it held
|
|
1285
|
+
// 4,303. The proxy assembled the corpus; it is the only party that
|
|
1286
|
+
// knows.
|
|
1287
|
+
...(corpusChars ? { 'x-hrr-corpus-chars': String(corpusChars) } : {}),
|
|
1278
1288
|
}
|
|
1279
1289
|
: init.headers,
|
|
1280
1290
|
});
|
|
@@ -1285,7 +1295,7 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
1285
1295
|
didSpill = true;
|
|
1286
1296
|
spilledChars += cached.corpus?.length || 0;
|
|
1287
1297
|
if (cached.reused) spillReuses += 1;
|
|
1288
|
-
result = await send(cached.body, cached.contextId, cached.topK);
|
|
1298
|
+
result = await send(cached.body, cached.contextId, cached.topK, cached.corpus?.length);
|
|
1289
1299
|
// Sidecar wiped between runs: the gateway 404s BEFORE the 402 (nothing
|
|
1290
1300
|
// paid). Never fail on a stale manifest — re-bind once and retry.
|
|
1291
1301
|
if (result.response.status === 404) {
|
|
@@ -1294,7 +1304,7 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
1294
1304
|
log('bound context is gone on the zoo — re-binding once...');
|
|
1295
1305
|
forgetContext(config.apiBase, cached.hash);
|
|
1296
1306
|
const rebound = await bindCorpus(cached.corpus, { force: true });
|
|
1297
|
-
result = await send(cached.body, rebound.contextId, cached.topK);
|
|
1307
|
+
result = await send(cached.body, rebound.contextId, cached.topK, cached.corpus?.length);
|
|
1298
1308
|
} else {
|
|
1299
1309
|
res.writeHead(404, { 'content-type': 'application/json' });
|
|
1300
1310
|
res.end(text);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.48.
|
|
3
|
+
"version": "0.48.61",
|
|
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",
|