openzoo 0.48.34 → 0.48.35
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/hrr.js +6 -2
- package/lib/proxy.js +36 -5
- package/package.json +1 -1
package/lib/hrr.js
CHANGED
|
@@ -26,7 +26,7 @@ export const contextCacheDisabled = () => process.env.OPENZOO_NO_CONTEXT_CACHE =
|
|
|
26
26
|
* Ensure `corpus` is bound on the zoo. Returns
|
|
27
27
|
* { contextId, hash, reused, bytes } — reused=true means zero bytes shipped.
|
|
28
28
|
*/
|
|
29
|
-
export async function bindCorpus(corpus, { onStage, force = false } = {}) {
|
|
29
|
+
export async function bindCorpus(corpus, { onStage, force = false, appendTo = null } = {}) {
|
|
30
30
|
const hash = corpusHash(corpus);
|
|
31
31
|
const bytes = Buffer.byteLength(corpus);
|
|
32
32
|
if (!force) {
|
|
@@ -37,7 +37,11 @@ export async function bindCorpus(corpus, { onStage, force = false } = {}) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
onStage?.('binding', { bytes });
|
|
40
|
-
|
|
40
|
+
// APPEND, don't re-upload. The gateway takes context_id on /v1/hrr/bind and
|
|
41
|
+
// adds to that context — which is the difference between paying for the
|
|
42
|
+
// delta and paying for the whole transcript again on every single turn.
|
|
43
|
+
const r = await postWithUploadSignal(`${config.apiBase}/v1/hrr/bind`,
|
|
44
|
+
JSON.stringify(appendTo ? { corpus, context_id: appendTo } : { corpus }), {
|
|
41
45
|
headers: withNamespace(),
|
|
42
46
|
onUploaded: () => onStage?.('bound-uploading-done', { bytes }),
|
|
43
47
|
});
|
package/lib/proxy.js
CHANGED
|
@@ -90,6 +90,9 @@ function jsonErr(res, status, message, extraFields = {}) {
|
|
|
90
90
|
|
|
91
91
|
const mb = (n) => (n / 1048576).toFixed(1);
|
|
92
92
|
|
|
93
|
+
// anchor -> { corpus, contextId, hash } for append-only transcript spills
|
|
94
|
+
const spillMemo = new Map();
|
|
95
|
+
|
|
93
96
|
/**
|
|
94
97
|
* Every fundable balance across all three chains, for the startup line and
|
|
95
98
|
* the live refresh. Each read is independent and advisory — one lagging RPC
|
|
@@ -365,11 +368,39 @@ async function spillTranscript(body, log) {
|
|
|
365
368
|
const corpus = msgs.slice(firstSpillable, cut).map(msgText).filter(Boolean).join('\n\n');
|
|
366
369
|
if (corpus.length <= BIND_MIN_CHARS) return null;
|
|
367
370
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
371
|
+
// CONTINUE THE CONTEXT, BIND ONLY THE DELTA.
|
|
372
|
+
//
|
|
373
|
+
// A transcript grows by one message per turn, so the whole-corpus hash misses
|
|
374
|
+
// every time and the old code re-uploaded the ENTIRE prefix on every single
|
|
375
|
+
// turn — OBSERVED live: 0.4MB bound three turns running, a fresh context id
|
|
376
|
+
// each time, while only a few KB was actually new. Bind cost grew with
|
|
377
|
+
// conversation length and was re-paid per message.
|
|
378
|
+
//
|
|
379
|
+
// The corpus is append-only: each turn's corpus starts with the previous
|
|
380
|
+
// one. So when it does, send just the tail and keep the same context_id.
|
|
381
|
+
// Anchored on the FIRST 2KB, which is stable for the life of a conversation
|
|
382
|
+
// and distinguishes concurrent ones.
|
|
383
|
+
const anchor = corpus.slice(0, 2048);
|
|
384
|
+
const prior = spillMemo.get(anchor);
|
|
385
|
+
let bind;
|
|
386
|
+
if (prior && corpus.startsWith(prior.corpus) && corpus.length > prior.corpus.length) {
|
|
387
|
+
const delta = corpus.slice(prior.corpus.length);
|
|
388
|
+
await bindCorpus(delta, {
|
|
389
|
+
appendTo: prior.contextId,
|
|
390
|
+
onStage: (stage, info) => {
|
|
391
|
+
if (stage === 'binding') log(`appending ${mb(info.bytes)}MB to ${prior.contextId} (delta only)`);
|
|
392
|
+
},
|
|
393
|
+
});
|
|
394
|
+
bind = { contextId: prior.contextId, hash: prior.hash, reused: true, bytes: delta.length };
|
|
395
|
+
} else {
|
|
396
|
+
bind = await bindCorpus(corpus, {
|
|
397
|
+
onStage: (stage, info) => {
|
|
398
|
+
if (stage === 'binding') log(`binding ${mb(info.bytes)}MB of transcript to holographic memory...`);
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
spillMemo.set(anchor, { corpus, contextId: bind.contextId, hash: bind.hash });
|
|
403
|
+
if (spillMemo.size > 32) spillMemo.delete(spillMemo.keys().next().value);
|
|
373
404
|
const sent = msgs.length - cut;
|
|
374
405
|
log(bind.reused
|
|
375
406
|
? `transcript prefix already bound (${bind.contextId}) — sending ${sent}/${msgs.length} turns`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.48.
|
|
3
|
+
"version": "0.48.35",
|
|
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",
|