mythos-code 1.7.1 → 1.7.3

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/bin/mythos.js +58 -10
  2. package/package.json +1 -1
package/bin/mythos.js CHANGED
@@ -52,10 +52,24 @@ const goalPrompt = (goal) => goal
52
52
  "\nDer Auftraggeber ist NICHT am Rechner und liest erst viel später mit, was hier im Chat passiert ist – frage ihn nichts, er kann nicht antworten. Behandle jede Entscheidung, jede Rückfrage und jedes Hindernis als etwas, das du selbst lösen musst:" +
53
53
  "\n- Gib bei Fehlern NIEMALS auf. Ein fehlgeschlagener Befehl, eine fehlende Abhängigkeit, ein kaputter Build sind Aufgaben, keine Endstationen: lies die Fehlermeldung genau, versuche eine andere Vorgehensweise, installiere Fehlendes selbst (z. B. per npm/pip/winget), nutze bei Bedarf websearch/fetch um die Lösung nachzuschlagen, und probiere es erneut. Erst wenn du wirklich mehrere grundverschiedene Ansätze erfolglos versucht hast, notierst du das Problem knapp und machst mit dem Rest der Aufgabe weiter." +
54
54
  "\n- Triff sinnvolle Annahmen statt zu fragen, und schreib kurz dazu, welche Annahme du getroffen hast." +
55
- "\n- Teile deinen Fortschritt normal im Chat mit (was du tust und warum), aber warte nicht auf eine Antwort." +
55
+ "\n- Beginne SOFORT mit einer kurzen Bestätigung und deinem Plan (2–6 Stichpunkte) als normalen Text, BEVOR du das erste Werkzeug nutzt – so sieht der Auftraggeber direkt, dass du das Ziel verstanden hast." +
56
+ "\n- Teile deinen Fortschritt normal im Chat mit (was du tust und warum), aber warte nicht auf eine Antwort. Schreibe vor jedem größeren Schritt einen kurzen Satz dazu." +
57
+ "\n- Baue große Projekte in vielen kleinen Dateien (je höchstens ca. 300 Zeilen) statt in einer riesigen Datei auf einmal." +
56
58
  "\n- Das ist eine große, langlaufende Aufgabe: Plane für 1 bis 5 Stunden durchgehende Arbeit in vielen kleinen Schritten, nicht für ein paar Minuten. Höre nicht zu früh auf – arbeite lieber zu gründlich als zu knapp." +
57
59
  "\nArbeite komplett selbstständig weiter, bis das Ziel vollständig erreicht und überprüft ist. Erst dann schreibe in deiner letzten Antwort eine eigene Zeile: ZIEL ERREICHT"
58
60
  : "";
61
+ /** Kurzer Live-Status aus der gerade gestreamten Antwort, z. B. „✍ schreibt src/main.js · 12 KB“. */
62
+ function streamActivity(full) {
63
+ if (!full) return "denkt nach…";
64
+ const k = full.lastIndexOf("<tool>");
65
+ if (k < 0 || full.indexOf("</tool>", k) >= 0) return "schreibt Antwort…";
66
+ const t = full.slice(k + 6), kb = (t.length / 1024).toFixed(1).replace(".", ",") + " KB";
67
+ const f = (key) => { const m = t.match(new RegExp('"' + key + '"\\s*:\\s*"([^"\\\\]{0,120})')); return m ? m[1] : ""; };
68
+ const name = f("name"), path = f("path");
69
+ if (name === "write" || name === "edit") return "✍ " + (name === "write" ? "schreibt " : "ändert ") + (path || "eine Datei") + " · " + kb;
70
+ if (name === "run") return "⚙ bereitet Befehl vor: " + f("cmd").slice(0, 60);
71
+ return "🔧 bereitet " + (name || "Werkzeug") + " vor…";
72
+ }
59
73
  const GOAL_NUDGE = "Das Ziel ist noch nicht als erreicht gemeldet. Der Auftraggeber ist nicht da – gib bei Problemen nicht auf, sondern versuche einen anderen Weg, nutze websearch/fetch für Lösungen und arbeite selbstständig weiter, ohne Rückfragen. Wenn es wirklich vollständig erledigt und geprüft ist, schreibe ZIEL ERREICHT.";
60
74
  const SUMMARY_PROMPT = "Fasse jetzt kurz auf Deutsch zusammen, OHNE Werkzeuge:\n**Geändert:** welche Dateien und was\n**Geklappt:** was funktioniert (und wie geprüft)\n**Offen:** was noch fehlt oder beachtet werden muss\nMaximal 12 Zeilen.";
61
75
 
@@ -452,9 +466,15 @@ async function login() {
452
466
  const fmt = (ms) => { const s = Math.floor(ms / 1000); return (s >= 60 ? Math.floor(s / 60) + "m " : "") + (s % 60) + "s"; };
453
467
 
454
468
  // Live-Timer: läuft während der ganzen Aufgabe, pausiert für Ausgaben und Rückfragen.
455
- let T0 = 0, tick = null;
469
+ let T0 = 0, tick = null, activity = "";
456
470
  const clearLine = () => process.stdout.write("\r\x1b[K");
457
- const startTick = () => { if (tick || !working) return; tick = setInterval(() => process.stdout.write("\r" + C.d + "⏳ Mythos arbeitet… " + fmt(Date.now() - T0) + " (Strg+C = stoppen)" + C.x + " "), 250); };
471
+ // Zeigt live, was Mythos gerade tut (z. B. „✍ schreibt src/main.js · 12 KB“) – auf Terminalbreite gekürzt.
472
+ const tickLine = () => {
473
+ const s = "⏳ Mythos arbeitet… " + fmt(Date.now() - T0) + (activity ? " · " + activity : "") + " (Strg+C = stoppen)";
474
+ const w = (process.stdout.columns || 100) - 2;
475
+ return s.length > w ? s.slice(0, w - 1) + "…" : s;
476
+ };
477
+ const startTick = () => { if (tick || !working) return; tick = setInterval(() => process.stdout.write("\r\x1b[K" + C.d + tickLine() + C.x), 250); };
458
478
  const stopTick = () => { if (tick) { clearInterval(tick); tick = null; } clearLine(); };
459
479
  const say = (s) => { const was = !!tick; stopTick(); console.log(s); if (was) startTick(); };
460
480
 
@@ -514,6 +534,20 @@ function streamPrinter() {
514
534
  };
515
535
  }
516
536
 
537
+ // Sichtbare Gedanken (wie bei base44): laufen gedimmt Wort für Wort, bevor die eigentliche Antwort beginnt.
538
+ function thinkPrinter() {
539
+ let printed = 0, started = false, ended = false;
540
+ return {
541
+ push(full) {
542
+ if (ended) return;
543
+ if (!started) { stopTick(); process.stdout.write(C.d + "💭 "); started = true; }
544
+ if (full.length <= printed) return;
545
+ process.stdout.write(full.slice(printed)); printed = full.length;
546
+ },
547
+ end() { if (ended) return; ended = true; if (started) process.stdout.write(C.x + "\n"); startTick(); },
548
+ };
549
+ }
550
+
517
551
  // ---------- Modell ----------
518
552
  // Verlauf kürzen, damit lange Aufgaben nicht an zu großem Kontext scheitern. level 0 = mild, 2 = stark.
519
553
  const shorten = (s, max) => s.length <= max ? s : s.slice(0, Math.floor(max * 0.7)) + "\n…[gekürzt]…\n" + s.slice(s.length - Math.floor(max * 0.3));
@@ -529,7 +563,7 @@ function compact(history, level) {
529
563
  }
530
564
 
531
565
  let tokens = { in: 0, out: 0 };
532
- async function once(messages, onText) {
566
+ async function once(messages, onText, onThink) {
533
567
  const c = ctl = new AbortController(); const to = setTimeout(() => c.abort(), 170000);
534
568
  const system = SYSTEM();
535
569
  tokens.in += estimateTokens(system, messages);
@@ -540,7 +574,7 @@ async function once(messages, onText) {
540
574
  body: JSON.stringify({ model: cfg.model || "mythos-code", max_tokens: 8000, system, messages, stream: true }),
541
575
  });
542
576
  if (!r.ok) { const j = await r.json().catch(() => ({})); const e = new Error(j?.error?.message || ("HTTP " + r.status)); e.status = r.status; throw e; }
543
- const reader = r.body.getReader(); const dec = new TextDecoder(); let buf = "", out = "";
577
+ const reader = r.body.getReader(); const dec = new TextDecoder(); let buf = "", out = "", think = "";
544
578
  while (true) {
545
579
  const { done, value } = await reader.read(); if (done) break;
546
580
  buf += dec.decode(value, { stream: true });
@@ -549,6 +583,8 @@ async function once(messages, onText) {
549
583
  if (!line.startsWith("data:")) continue;
550
584
  let p; try { p = JSON.parse(line.slice(5)); } catch { continue; }
551
585
  if (p.type === "error") { const e = new Error(p.error?.message || "Überlastet"); e.status = 529; throw e; }
586
+ // Sichtbare Gedanken: kommen als eigener Block VOR der Antwort.
587
+ if (p.delta?.type === "thinking_delta" && p.delta.thinking) { think += p.delta.thinking; if (onThink) onThink(think); }
552
588
  if (p.delta?.text) { out += p.delta.text; if (onText) onText(out); }
553
589
  }
554
590
  }
@@ -558,14 +594,16 @@ async function once(messages, onText) {
558
594
  } finally { clearTimeout(to); }
559
595
  }
560
596
 
561
- async function call(history, onText) {
597
+ async function call(history, onText, onThink) {
562
598
  for (let a = 0; a < 6; a++) {
563
599
  if (stopped) throw new Error("Gestoppt");
564
- try { return await once(compact(history, Math.min(2, Math.floor(a / 2))), onText); }
600
+ try { return await once(compact(history, Math.min(2, Math.floor(a / 2))), onText, onThink); }
565
601
  catch (e) {
566
602
  if (stopped) throw e;
567
603
  if (e.status === 401) throw new Error("Anmeldung ungültig – bitte neu anmelden: mythos login");
568
604
  if (/Daily limit/i.test(e.message)) throw new Error("Tageslimit erreicht – mit Pro unbegrenzt.");
605
+ // Konfigurationsproblem (Guthaben leer, kein Ausweich-Schlüssel) statt normaler Überlastung -> nicht sinnlos wiederholen.
606
+ if (/nicht konfiguriert/i.test(e.message)) throw e;
569
607
  await new Promise((r) => setTimeout(r, Math.min(8000, 1500 * (a + 1))));
570
608
  }
571
609
  }
@@ -647,8 +685,13 @@ async function turnInner(history) {
647
685
  let nudges = 0;
648
686
  for (let i = 0; i < max && !stopped; i++) {
649
687
  const pr = streamPrinter();
650
- const out = await call(history, (full) => pr.push(full));
651
- pr.end();
688
+ let think = null;
689
+ activity = "denkt nach…";
690
+ const out = await call(history,
691
+ (full) => { if (think) think.end(); activity = streamActivity(full); pr.push(full); },
692
+ (t) => { if (!think) think = thinkPrinter(); think.push(t); });
693
+ if (think) think.end();
694
+ pr.end(); activity = "";
652
695
  if (stopped) break;
653
696
  history.push({ role: "assistant", content: out });
654
697
  const m = out.match(/<tool>([\s\S]*?)<\/tool>/);
@@ -671,7 +714,11 @@ async function summarize(history) {
671
714
  history.push({ role: "user", content: SUMMARY_PROMPT });
672
715
  say(C.m + C.b + "📋 Zusammenfassung" + C.x);
673
716
  const pr = streamPrinter();
674
- const out = await call(history, (full) => pr.push(full));
717
+ let think = null;
718
+ const out = await call(history,
719
+ (full) => { if (think) think.end(); pr.push(full); },
720
+ (t) => { if (!think) think = thinkPrinter(); think.push(t); });
721
+ if (think) think.end();
675
722
  pr.end();
676
723
  history.push({ role: "assistant", content: out });
677
724
  return out;
@@ -812,6 +859,7 @@ async function command(q, history) {
812
859
  if (/^(stop|aus|ende|beenden)$/i.test(arg)) { goal = ""; return console.log("🎯 Ziel beendet.\n"); }
813
860
  if (!autoYes) { autoYes = true; console.log(C.d + "Vollzugriff für /goal eingeschaltet – Mythos fragt nicht mehr nach." + C.x); }
814
861
  goal = arg;
862
+ console.log(C.m + C.b + "🎯 Ziel angenommen: " + C.x + arg + C.d + "\n Mythos plant jetzt und arbeitet selbstständig – der Fortschritt erscheint hier. Stoppen: Strg+C" + C.x);
815
863
  return turn(history, "Neues Ziel: " + arg + "\nArbeite jetzt komplett selbstständig daran, bis es erreicht und geprüft ist.");
816
864
  }
817
865
  if (cmd === "/weiter") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mythos-code",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "Mythos Code – KI-Coding-Agent im Terminal (by Mythoscraft)",
5
5
  "bin": {
6
6
  "mythos": "bin/mythos.js",