openzoo 0.48.36 → 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 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
- + 'const save=(sx==null||!isFinite(sx))?"":(" \\u00b7 "+col+sx.toFixed(4)+"x vs direct"+(sv>0?(" ($"+sv.toFixed(4)+" saved)"):"")+"\\x1b[0m");'
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
@@ -554,6 +554,13 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
554
554
  let spillCalls = 0;
555
555
  let spilledChars = 0;
556
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;
557
564
  // CREDIT, CACHED. Users cannot tell prepaid credit from wallet balance and
558
565
  // have to guess whether a call was even paid for ("I don't think x402 made me
559
566
  // pay this at all"). The status line runs EVERY turn, so this is refreshed at
@@ -681,6 +688,9 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
681
688
  // saving is actually made of.
682
689
  tokensApprox: Math.round(spilledChars / 4),
683
690
  reusedBinds: spillReuses,
691
+ spend: spillSpend,
692
+ direct: spillDirect,
693
+ savingX: spillSpend > 0 ? Number((spillDirect / spillSpend).toFixed(4)) : null,
684
694
  },
685
695
  spendUsd: sessionSpent,
686
696
  creditUsd,
@@ -995,9 +1005,11 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
995
1005
  }
996
1006
  : init.headers,
997
1007
  });
1008
+ let didSpill = false;
998
1009
  let result;
999
1010
  if (cached) {
1000
1011
  spillCalls += 1;
1012
+ didSpill = true;
1001
1013
  spilledChars += cached.corpus?.length || 0;
1002
1014
  if (cached.reused) spillReuses += 1;
1003
1015
  result = await send(cached.body, cached.contextId, cached.topK);
@@ -1039,6 +1051,10 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
1039
1051
  // attach call that is the whole bound corpus, which is why it can be
1040
1052
  // orders of magnitude above what was billed. directUsd is exact and
1041
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
+ }
1042
1058
  sessionDirect += typeof receipt.directUsd === 'number'
1043
1059
  ? receipt.directUsd
1044
1060
  : typeof receipt.savesVsDirect === 'number'
@@ -1084,6 +1100,10 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
1084
1100
  sessionSpent += x.billedUsd;
1085
1101
  sessionCogs += typeof x.cogsUsd === 'number' ? x.cogsUsd : x.billedUsd / MARKUP;
1086
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
+ }
1087
1107
  paidCalls += 1;
1088
1108
  if (viaTunnel) tunnelSpent += x.billedUsd;
1089
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.36",
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",