openzoo 0.48.55 → 0.48.57
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 +15 -2
- package/lib/proxy.js +23 -5
- package/package.json +1 -1
package/lib/brief.js
CHANGED
|
@@ -54,8 +54,21 @@ export function injectBrief(body, selfUrl = null) {
|
|
|
54
54
|
if (msgs.some((m) => typeof m?.content === 'string' && m.content.includes('connected through an openzoo proxy'))) return null;
|
|
55
55
|
|
|
56
56
|
const brief = { role: 'system', content: briefFor(selfUrl) };
|
|
57
|
-
|
|
57
|
+
// THE LEADING SYSTEM RUN ONLY — NOT THE LAST SYSTEM ANYWHERE.
|
|
58
|
+
//
|
|
59
|
+
// This used to reduce over the WHOLE array for the last `role === 'system'`,
|
|
60
|
+
// which is the same thing only while every system message sits at the front.
|
|
61
|
+
// The moment anything injects one later, the brief is spliced in AFTER the
|
|
62
|
+
// user's turn, and the conversation the model receives ends with operator
|
|
63
|
+
// notes instead of a question.
|
|
64
|
+
//
|
|
65
|
+
// OBSERVED live: forwarded tail `s a t a t a u s a u s s` — two system
|
|
66
|
+
// messages after the last user message. The agent replied "I don't see an
|
|
67
|
+
// explicit question or task for this turn", answered the PREVIOUS turn, and
|
|
68
|
+
// read as one message behind for an entire session.
|
|
69
|
+
let lead = -1;
|
|
70
|
+
while (lead + 1 < msgs.length && msgs[lead + 1]?.role === 'system') lead += 1;
|
|
58
71
|
const out = [...msgs];
|
|
59
|
-
out.splice(
|
|
72
|
+
out.splice(lead + 1, 0, brief); // after the leading system block, before any turn
|
|
60
73
|
return { ...body, messages: out };
|
|
61
74
|
}
|
package/lib/proxy.js
CHANGED
|
@@ -406,7 +406,12 @@ async function spillTranscript(body, log, req) {
|
|
|
406
406
|
// saving — a bigger tail is a bigger `sent` — and that is the correct trade:
|
|
407
407
|
// measured 8.13x on the fleet leaves room to spend some of it on an agent
|
|
408
408
|
// that remembers its own last few moves.
|
|
409
|
-
|
|
409
|
+
// 12 was set while the model was ALSO missing its own last turn to a brief
|
|
410
|
+
// spliced in behind it (fixed in 0.48.56), so part of that floor was paying
|
|
411
|
+
// for a bug rather than for coherence. 6 turns still covers "what did I just
|
|
412
|
+
// do" — the case retrieval cannot answer, because the model does not know to
|
|
413
|
+
// query for it — and hands the rest back as saving.
|
|
414
|
+
const minTurns = Number(process.env.OPENZOO_TAIL_MIN_TURNS || 6);
|
|
410
415
|
if (msgs.length - cut < minTurns) {
|
|
411
416
|
for (let i = Math.max(firstSpillable + 1, msgs.length - minTurns); i > firstSpillable; i--) {
|
|
412
417
|
if (severable(i)) { cut = i; break; }
|
|
@@ -510,6 +515,13 @@ async function spillTranscript(body, log, req) {
|
|
|
510
515
|
// NAME THE KEY. A memo keyed on the wrong thing fails silently — it just
|
|
511
516
|
// re-binds forever and collides sessions — so the log says which key was used.
|
|
512
517
|
const keyKind = sessionId ? `sid ${String(sessionId).slice(0, 8)}` : 'content-anchor';
|
|
518
|
+
// WHAT ACTUALLY REACHES THE MODEL. Inference about this cut has been wrong
|
|
519
|
+
// twice; the roles of the forwarded tail settle it in one line.
|
|
520
|
+
if (process.env.OPENZOO_LOG_TAIL === '1') {
|
|
521
|
+
const roles = msgs.slice(cut).map((m) => (m.role || '?')[0]).join('');
|
|
522
|
+
const lastU = msgs.slice(cut).some((m) => m.role === 'user' && msgText(m).trim());
|
|
523
|
+
log(` tail roles=${roles} firstSpillable=${firstSpillable} cut=${cut} hasUserText=${lastU}`);
|
|
524
|
+
}
|
|
513
525
|
log(bind.reused
|
|
514
526
|
? `transcript prefix already bound (${bind.contextId}, ${keyKind}) — sending ${sent}/${msgs.length} turns`
|
|
515
527
|
: `transcript prefix bound (${mb(bind.bytes)}MB → ${bind.contextId}, ${keyKind}) — sending ${sent}/${msgs.length} turns`);
|
|
@@ -527,12 +539,18 @@ async function spillTranscript(body, log, req) {
|
|
|
527
539
|
// far less context than a detailed one — and is clamped so a huge ask cannot
|
|
528
540
|
// drag the whole corpus back in.
|
|
529
541
|
const askChars = msgText(msgs[msgs.length - 1] || {}).length;
|
|
542
|
+
// BREADTH IS THE LEVER, AND MORE OF IT IS WORSE. MEASURED on a 56,265-token
|
|
543
|
+
// corpus: top_k 32 handed back 9,990 tokens and scored 2.45x, top_k 8 handed
|
|
544
|
+
// back 2,574 and scored 4.73x — same question, same answer, nearly double the
|
|
545
|
+
// saving. Spilling 34k tokens to recall 22k of them back is a round trip, not
|
|
546
|
+
// a saving. So budget the recall tighter and cap k where the measurement says
|
|
547
|
+
// the value is, rather than at the largest number that still fits.
|
|
530
548
|
const budget = Math.min(
|
|
531
|
-
Number(process.env.OPENZOO_RECALL_MAX_TOKENS ||
|
|
532
|
-
Math.max(Number(process.env.OPENZOO_RECALL_MIN_TOKENS ||
|
|
533
|
-
Math.round(askChars /
|
|
549
|
+
Number(process.env.OPENZOO_RECALL_MAX_TOKENS || 3000),
|
|
550
|
+
Math.max(Number(process.env.OPENZOO_RECALL_MIN_TOKENS || 1200),
|
|
551
|
+
Math.round(askChars / 3)),
|
|
534
552
|
);
|
|
535
|
-
const topK = Math.max(4, Math.min(
|
|
553
|
+
const topK = Math.max(4, Math.min(12, Math.round(budget / 320)));
|
|
536
554
|
|
|
537
555
|
return {
|
|
538
556
|
body: Buffer.from(JSON.stringify({ ...body, messages: [...head, ...msgs.slice(cut)] })),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.48.
|
|
3
|
+
"version": "0.48.57",
|
|
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",
|