fix(ai): bump planner maxTokens 1024→4096 + teach prompt about the loop

Debug log from a "tag 4 notes" mission showed the planner's second-round
response truncated mid-step: it was proposing one add_tag_to_note per
listed note but ran out of tokens halfway through note #2. Parser
rejected the malformed JSON → loop exited with 0 staged, user saw
nothing to approve.

Raising maxTokens to 4096 fits ~15-20 step objects, which covers the
batch-tagging / batch-save pattern the reasoning loop is designed for.

Also updating the system prompt so the planner actually knows about
the loop it's running inside: read-only tools are announced as
auto-executing with outputs visible next turn, and a new rule makes
explicit that batch jobs must emit all write-steps in one plan (because
staging a propose-tool ends the turn). Step count raised 1-5 → 1-10.

Prompt snapshot tests still pass (they check structure, not text).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-16 00:55:18 +02:00
parent 8299bf004d
commit 8a5d200c84
2 changed files with 11 additions and 5 deletions

View file

@ -45,7 +45,12 @@ export const aiPlanTask: LlmTask<AiPlanInput, AiPlanOutput> = {
{ role: 'user', content: user },
],
temperature: 0.3,
maxTokens: 1024,
// 1024 truncates mid-response when the planner proposes 3+ steps with
// rich rationales — the reasoning loop amplifies this because a
// single round can legitimately stage one step per listed item
// (e.g. 10 notes → 10 add_tag_to_note calls). 4096 fits ~15-20
// step objects while still fast on browser tier.
maxTokens: 4096,
});
// Always populate debug payload (cheap — strings already in memory).

View file

@ -40,13 +40,14 @@ function buildSystemPrompt(input: AiPlanInput): string {
return `Du bist eine KI, die im Auftrag des Nutzers an einer langlebigen Mission arbeitet.
Dein Job: aus dem aktuellen Mission-Kontext einen kurzen, konkreten Plan ableiten 1 bis 5 Schritte, jeder ein Tool-Aufruf auf Nutzerdaten. Jeder Schritt MUSS eine Begründung haben (rationale), die der Nutzer in der Review-UI sieht.
Dein Job: aus dem aktuellen Mission-Kontext einen konkreten Plan ableiten 1 bis 10 Schritte, jeder ein Tool-Aufruf auf Nutzerdaten. Jeder Schritt MUSS eine Begründung haben (rationale), die der Nutzer in der Review-UI sieht.
Wichtige Regeln:
1. Nutze NUR Tools aus der Liste unten. Unbekannte Tools Plan invalide.
2. Jeder Step wird als Proposal gestaged der Nutzer approved oder rejected. Du schreibst nie direkt.
3. Berücksichtige das Feedback aus vorherigen Iterationen (unten im User-Prompt). Wenn ein Vorschlag rejected wurde, wiederhole ihn nicht ohne Änderung.
4. Antworte AUSSCHLIESSLICH mit einem JSON-Block in folgendem Format, keine Prosa davor/danach:
2. Read-only Tools (z.B. list_*, get_*) laufen automatisch ihre Ausgabe siehst du in der nächsten Planungsrunde als "Zwischenergebnisse" und kannst dann darauf aufbauend schreibende Tools vorschlagen. Write-Tools (create_*, update_*, add_tag_to_note, etc.) werden dem Nutzer zur Approval vorgelegt.
3. Wenn ein Batch-Job ansteht (z.B. "tagge alle Notizen"), gib alle Einzel-Calls in EINEM plan zurück du kriegst nach propose-Tools keinen weiteren Turn.
4. Berücksichtige das Feedback aus vorherigen Iterationen (unten im User-Prompt). Wenn ein Vorschlag rejected wurde, wiederhole ihn nicht ohne Änderung.
5. Antworte AUSSCHLIESSLICH mit einem JSON-Block in folgendem Format, keine Prosa davor/danach:
\`\`\`json
{