openzoo 0.48.35 → 0.48.37
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/launch.js +8 -1
- package/lib/proxy.js +34 -3
- package/package.json +1 -1
package/lib/launch.js
CHANGED
|
@@ -179,7 +179,14 @@ export async function launchClaude(argv) {
|
|
|
179
179
|
// — which is the difference between an omission and a fact.
|
|
180
180
|
+ 'const sx=Number(j.savingX);const sv=Number(j.savedUsd)||0;'
|
|
181
181
|
+ 'const col=(sx>1)?"\\x1b[32m":"\\x1b[90m";'
|
|
182
|
-
|
|
182
|
+
// Prefer the SPILLED-call ratio: the session-wide one averages in every
|
|
183
|
+
// small turn that had nothing to offload, so it slides toward 1.0 as a
|
|
184
|
+
// conversation grows and reads as the mechanism failing when it is not.
|
|
185
|
+
+ 'const sx2=Number(sp.savingX);'
|
|
186
|
+
+ 'const on=(isFinite(sx2)&&sx2>0)?sx2:sx;'
|
|
187
|
+
+ 'const lbl=(isFinite(sx2)&&sx2>0)?"x on spilled":"x vs direct";'
|
|
188
|
+
+ 'const col2=(on>1)?"\\x1b[32m":"\\x1b[90m";'
|
|
189
|
+
+ 'const save=(on==null||!isFinite(on))?"":(" \\u00b7 "+col2+on.toFixed(4)+lbl+(sv>0?(" ($"+sv.toFixed(4)+" saved)"):"")+"\\x1b[0m");'
|
|
183
190
|
+ 'process.stdout.write("\\x1b[38;5;208m\\u25cf\\x1b[0m openzoo $"+(Number(j.spendUsd)||0).toFixed(4)+" "+(j.paidCalls||0)+" call"+((j.paidCalls||0)===1?"":"s")+save+spill+cr+" \\u00b7 x402")}'
|
|
184
191
|
+ 'catch{process.stdout.write("\\x1b[38;5;208m\\u25cf\\x1b[0m openzoo \\u00b7 x402")}})\'\n');
|
|
185
192
|
fs.chmodSync(scriptPath, 0o755);
|
package/lib/proxy.js
CHANGED
|
@@ -385,12 +385,23 @@ async function spillTranscript(body, log) {
|
|
|
385
385
|
let bind;
|
|
386
386
|
if (prior && corpus.startsWith(prior.corpus) && corpus.length > prior.corpus.length) {
|
|
387
387
|
const delta = corpus.slice(prior.corpus.length);
|
|
388
|
-
|
|
388
|
+
// FIRE AND FORGET. This delta is history for FUTURE turns — the answer
|
|
389
|
+
// being generated right now is served from the tail plus what is already
|
|
390
|
+
// bound, so waiting on the upload buys nothing and costs the user the
|
|
391
|
+
// round trip on every single turn. The context id is already known, so
|
|
392
|
+
// nothing is lost by not waiting for it.
|
|
393
|
+
//
|
|
394
|
+
// The FIRST bind is deliberately NOT async: the request must carry
|
|
395
|
+
// x-hrr-context, and that id does not exist until the bind returns. Firing
|
|
396
|
+
// that one off would send the opening turn with no context at all — a
|
|
397
|
+
// silently worse answer traded for a shorter pause, which is the wrong way
|
|
398
|
+
// round.
|
|
399
|
+
void bindCorpus(delta, {
|
|
389
400
|
appendTo: prior.contextId,
|
|
390
401
|
onStage: (stage, info) => {
|
|
391
|
-
if (stage === 'binding') log(`appending ${mb(info.bytes)}MB to ${prior.contextId} (delta
|
|
402
|
+
if (stage === 'binding') log(`appending ${mb(info.bytes)}MB to ${prior.contextId} (delta, background)`);
|
|
392
403
|
},
|
|
393
|
-
});
|
|
404
|
+
}).catch((e) => log(`append failed (history may lag one turn): ${e.message}`));
|
|
394
405
|
bind = { contextId: prior.contextId, hash: prior.hash, reused: true, bytes: delta.length };
|
|
395
406
|
} else {
|
|
396
407
|
bind = await bindCorpus(corpus, {
|
|
@@ -543,6 +554,13 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
543
554
|
let spillCalls = 0;
|
|
544
555
|
let spilledChars = 0;
|
|
545
556
|
let spillReuses = 0;
|
|
557
|
+
// Spend/direct for ONLY the calls that spilled. The session-wide savingX
|
|
558
|
+
// averages these with every small turn that had nothing to offload, so it
|
|
559
|
+
// slides toward 1.0 as a conversation grows — which reads as the mechanism
|
|
560
|
+
// degrading when it is just the mix changing. OBSERVED: 1.3166 -> 1.1823
|
|
561
|
+
// while spilled calls and offloaded tokens both sat completely still.
|
|
562
|
+
let spillSpend = 0;
|
|
563
|
+
let spillDirect = 0;
|
|
546
564
|
// CREDIT, CACHED. Users cannot tell prepaid credit from wallet balance and
|
|
547
565
|
// have to guess whether a call was even paid for ("I don't think x402 made me
|
|
548
566
|
// pay this at all"). The status line runs EVERY turn, so this is refreshed at
|
|
@@ -670,6 +688,9 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
670
688
|
// saving is actually made of.
|
|
671
689
|
tokensApprox: Math.round(spilledChars / 4),
|
|
672
690
|
reusedBinds: spillReuses,
|
|
691
|
+
spend: spillSpend,
|
|
692
|
+
direct: spillDirect,
|
|
693
|
+
savingX: spillSpend > 0 ? Number((spillDirect / spillSpend).toFixed(4)) : null,
|
|
673
694
|
},
|
|
674
695
|
spendUsd: sessionSpent,
|
|
675
696
|
creditUsd,
|
|
@@ -984,9 +1005,11 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
984
1005
|
}
|
|
985
1006
|
: init.headers,
|
|
986
1007
|
});
|
|
1008
|
+
let didSpill = false;
|
|
987
1009
|
let result;
|
|
988
1010
|
if (cached) {
|
|
989
1011
|
spillCalls += 1;
|
|
1012
|
+
didSpill = true;
|
|
990
1013
|
spilledChars += cached.corpus?.length || 0;
|
|
991
1014
|
if (cached.reused) spillReuses += 1;
|
|
992
1015
|
result = await send(cached.body, cached.contextId, cached.topK);
|
|
@@ -1028,6 +1051,10 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
1028
1051
|
// attach call that is the whole bound corpus, which is why it can be
|
|
1029
1052
|
// orders of magnitude above what was billed. directUsd is exact and
|
|
1030
1053
|
// always present; savesVsDirect is the same number as a ratio.
|
|
1054
|
+
if (didSpill) {
|
|
1055
|
+
spillSpend += receipt.billedUsd || 0;
|
|
1056
|
+
spillDirect += typeof receipt.directUsd === 'number' ? receipt.directUsd : (receipt.billedUsd || 0);
|
|
1057
|
+
}
|
|
1031
1058
|
sessionDirect += typeof receipt.directUsd === 'number'
|
|
1032
1059
|
? receipt.directUsd
|
|
1033
1060
|
: typeof receipt.savesVsDirect === 'number'
|
|
@@ -1073,6 +1100,10 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
1073
1100
|
sessionSpent += x.billedUsd;
|
|
1074
1101
|
sessionCogs += typeof x.cogsUsd === 'number' ? x.cogsUsd : x.billedUsd / MARKUP;
|
|
1075
1102
|
sessionDirect += typeof x.directUsd === 'number' ? x.directUsd : x.billedUsd;
|
|
1103
|
+
if (didSpill) {
|
|
1104
|
+
spillSpend += x.billedUsd;
|
|
1105
|
+
spillDirect += typeof x.directUsd === 'number' ? x.directUsd : x.billedUsd;
|
|
1106
|
+
}
|
|
1076
1107
|
paidCalls += 1;
|
|
1077
1108
|
if (viaTunnel) tunnelSpent += x.billedUsd;
|
|
1078
1109
|
say(`credit -> $${x.billedUsd.toFixed(6)} · session $${sessionSpent.toFixed(6)}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.48.
|
|
3
|
+
"version": "0.48.37",
|
|
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",
|