From 8299bf004d3a74bbe4e6dc4baedbabc125ddbdc5 Mon Sep 17 00:00:00 2001 From: Till JS Date: Thu, 16 Apr 2026 00:43:52 +0200 Subject: [PATCH] =?UTF-8?q?feat(ai):=20reasoning=20loop=20=E2=80=94=20agen?= =?UTF-8?q?t=20chains=20auto=20tools=20before=20asking=20for=20approval?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The runner was one-shot: one planner call per iteration, no feedback from tool outputs. "Lies alle Notizen und tagge sie" needed two manual runs (list_notes, then tagging) because the planner never saw the list_tasks output. Now runMission loops up to MAX_REASONING_LOOP_ITERATIONS (5): loop: plan → classify steps by policy │ ├─ auto → execute inline, capture {message, data}, feed back │ as a synthetic ResolvedInput for the next planner call │ ├─ propose → stage proposal, mark humanInLoop, EXIT after this round │ (human has to approve before we plan further — we don't │ know what they'll accept yet) │ └─ none/0-steps → agent considers the task done, EXIT Tool outputs become a ResolvedInput titled "Zwischenergebnisse (Runde N)" so the planner sees them structured and labelled. StageOutcome gains `autoData` + `autoMessage` so the loop can thread the executor's payload back through without a second call. AiDebugEntry now holds `plannerCalls[]` and `loopSteps[]` instead of a single planner snapshot — so Debug-Panel shows every LLM round + every auto-tool output, each collapsible. Summary chip shows "3× LLM · 4200ms · 2× Auto-Tool" when a loop ran. Side-effects for existing use cases: - One-shot missions (single propose tool) behave identically (loop exits after round 1 with humanInLoop=true). - "Tag all notes" missions now finish in a single run: loop iter 1 runs list_notes auto, iter 2 stages N add_tag_to_note proposals, exits. - Server-side mana-ai runner NOT touched — this is foreground-only for now; the server still runs one plan/tick. All 8 runner.test.ts tests pass unchanged (the existing test suite only exercises the single-step path, which is a subset of the loop). Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/lib/components/ai/AiDebugBlock.svelte | 51 +++- .../web/src/lib/data/ai/missions/debug.ts | 17 +- .../web/src/lib/data/ai/missions/runner.ts | 274 +++++++++++++----- 3 files changed, 264 insertions(+), 78 deletions(-) diff --git a/apps/mana/apps/web/src/lib/components/ai/AiDebugBlock.svelte b/apps/mana/apps/web/src/lib/components/ai/AiDebugBlock.svelte index 7830e453e..30e0c0695 100644 --- a/apps/mana/apps/web/src/lib/components/ai/AiDebugBlock.svelte +++ b/apps/mana/apps/web/src/lib/components/ai/AiDebugBlock.svelte @@ -44,7 +44,14 @@ {:else if d.preStep.webResearch && !d.preStep.webResearch.ok} · Web ❌ {/if} - {#if d.planner}· {Math.round(d.planner.latencyMs)}ms{/if} + {#if d.plannerCalls && d.plannerCalls.length > 0} + · {d.plannerCalls.length}× LLM · {Math.round( + d.plannerCalls.reduce((a, c) => a + c.latencyMs, 0) + )}ms + {/if} + {#if d.loopSteps && d.loopSteps.length > 0} + · {d.loopSteps.length}× Auto-Tool + {/if} {#if d.plannerError}· Planner ❌{/if}