openzoo 0.48.55 → 0.48.56

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 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
- const lastSystem = msgs.reduce((acc, m, i) => (m?.role === 'system' ? i : acc), -1);
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(lastSystem + 1, 0, brief); // after any leading system block, before the user turns
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
@@ -510,6 +510,13 @@ async function spillTranscript(body, log, req) {
510
510
  // NAME THE KEY. A memo keyed on the wrong thing fails silently — it just
511
511
  // re-binds forever and collides sessions — so the log says which key was used.
512
512
  const keyKind = sessionId ? `sid ${String(sessionId).slice(0, 8)}` : 'content-anchor';
513
+ // WHAT ACTUALLY REACHES THE MODEL. Inference about this cut has been wrong
514
+ // twice; the roles of the forwarded tail settle it in one line.
515
+ if (process.env.OPENZOO_LOG_TAIL === '1') {
516
+ const roles = msgs.slice(cut).map((m) => (m.role || '?')[0]).join('');
517
+ const lastU = msgs.slice(cut).some((m) => m.role === 'user' && msgText(m).trim());
518
+ log(` tail roles=${roles} firstSpillable=${firstSpillable} cut=${cut} hasUserText=${lastU}`);
519
+ }
513
520
  log(bind.reused
514
521
  ? `transcript prefix already bound (${bind.contextId}, ${keyKind}) — sending ${sent}/${msgs.length} turns`
515
522
  : `transcript prefix bound (${mb(bind.bytes)}MB → ${bind.contextId}, ${keyKind}) — sending ${sent}/${msgs.length} turns`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.48.55",
3
+ "version": "0.48.56",
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",