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.
- package/bin/mythos.js +58 -10
- 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-
|
|
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
|
-
|
|
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
|
-
|
|
651
|
-
|
|
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
|
-
|
|
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") {
|