openzoo 0.48.3 → 0.48.4

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.
Files changed (2) hide show
  1. package/lib/grokui.mjs +37 -2
  2. package/package.json +1 -1
package/lib/grokui.mjs CHANGED
@@ -301,6 +301,35 @@ function newGroupThread(names) {
301
301
  const BIND_CHUNK_BYTES = 512 * 1024;
302
302
  // Chained auto-run commands per user message. Each hop is a paid call.
303
303
  const AUTO_MAX_STEPS = Number(process.env.OZ_AUTO_MAX_STEPS || 8);
304
+
305
+ // Injected fresh on every AUTO turn, never persisted into the thread.
306
+ //
307
+ // The auto loop only continues while directives keep parsing, so a reply that
308
+ // merely OFFERS ends the run — auto silently degrades to ask the moment the
309
+ // model hedges. Observed live: "If you want, I can rewrite the prompt with
310
+ // these fixes folded in", "Spawned mcp-integration — working on it" with
311
+ // nothing spawned, and a user reduced to answering "no, this... impl all".
312
+ // Models are trained to close on a consent question; in auto that instinct is
313
+ // the bug. The system prompt is frozen into a thread at creation, so an
314
+ // existing thread can only be reached by a per-turn message.
315
+ const AUTO_DIRECTIVE = `AUTO MODE IS ON for this thread.
316
+
317
+ Do the work in this turn. Do not ask whether to proceed, do not offer to do it,
318
+ do not say what you are "about to" do and stop. The user has already consented
319
+ by enabling auto — a question back to them is a dropped turn, and they must
320
+ type "yes" to get what they already asked for.
321
+
322
+ Concretely, NEVER end a turn with any of: "If you want, I can…", "Should I…?",
323
+ "Let me know and I'll…", "Ready to proceed?", or a plan with no directive after
324
+ it. If you catch yourself writing one, emit the RUN/WRITE/READ/SERVE/FETCH line
325
+ instead — that IS the answer.
326
+
327
+ Announcing an action does not perform it. "Spawned X", "working on it" and
328
+ "kicked that off" are false unless the directive line is in this same reply.
329
+ If a task needs several commands, emit the FIRST one now; you get its real
330
+ output back and continue from there. Only stop to ask when the next step is
331
+ genuinely destructive and irreversible, or when you truly cannot proceed
332
+ without a fact only the user has.`;
304
333
  async function bindThread(t) {
305
334
  // Only bind what's NEW since the last successful bind, continuing the
306
335
  // existing context_id — previously this rebuilt and re-sent the WHOLE
@@ -575,10 +604,16 @@ async function runTurn(threadId, userText, onEvent, images) {
575
604
  t.status = 'thinking';
576
605
  let reply = '';
577
606
  onEvent?.({ type: 'start', name: t.name, color: t.color });
607
+ // Transient: the nudge is appended for THIS call only and never pushed into
608
+ // t.messages, so it can't accumulate across a chained auto run or get bound
609
+ // into the thread's context.
610
+ const callMsgs = t.runMode === 'auto'
611
+ ? [...t.messages, { role: 'system', content: AUTO_DIRECTIVE }]
612
+ : t.messages;
578
613
  try {
579
614
  reply = onEvent
580
- ? (await brainStream(t.messages, (delta) => onEvent({ type: 'delta', name: t.name, color: t.color, delta }), t.contextId)).trim()
581
- : (await brain(t.messages, t.contextId)).trim();
615
+ ? (await brainStream(callMsgs, (delta) => onEvent({ type: 'delta', name: t.name, color: t.color, delta }), t.contextId)).trim()
616
+ : (await brain(callMsgs, t.contextId)).trim();
582
617
  } catch (e) {
583
618
  reply = `error: ${e.message}`;
584
619
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.48.3",
3
+ "version": "0.48.4",
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",