Budgetsperre sichtbar machen (#608), Gedaechtnisabruf kuerzt statt wegzulassen (#607)

#608: Ein wegen erschoepften Budgets abgelehnter Lauf hinterlaesst jetzt einen Beleg
(Status BudgetExceeded) an Aufgabe und Verlauf; die Log-Warnung kommt einmal je Agent,
Grenze und Tag. Die Kostenprognose zaehlt Ablehnungen nicht als Lauf und warnt, wenn die
geplanten Aufgaben eines Agenten sein Tagesbudget uebersteigen (API + Verbrauchsansicht).

#607: Passt schon der erste Treffer nicht in den Abruf, wird er gekuerzt (Anfang und Ende
bleiben) statt ganz zu fehlen. remember weist auf gleichnamige Eintraege ohne Schluessel und
auf Eintraege nahe der Abrufgrenze hin.

Version 0.1.9.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-09-15 18:59:14 +02:00
co-authored by Claude Opus 5
parent b0997b5334
commit f5731c50f8
12 changed files with 408 additions and 22 deletions
@@ -113,6 +113,46 @@ public sealed class KostenPrognoseTests
p.SummeProTag.ShouldBe(3.44m);
}
[Fact]
public void Budgetablehnungen_druecken_den_Schnitt_nicht()
{
// #608: Eine Ablehnung steht als Beleg ueber 0 USD im Verlauf - sie ist kein Lauf.
var abgelehnt = Beleg("t-1", 0m) with { Status = "BudgetExceeded" };
var zeile = Rechne([Stuendlich("t-1")], Belege(("t-1", [Beleg("t-1", 0.02m, 2), abgelehnt])))
.Aufgaben.Single();
zeile.KostenJeLauf.ShouldBe(0.02m);
zeile.Stichprobe.ShouldBe(1);
}
[Fact]
public void Warnt_wenn_die_Aufgaben_das_Tagesbudget_des_Agenten_uebersteigen()
{
var knapp = new AgentConfig { AgentId = "nachrichten", Model = Nachrichten.Model, SystemPrompt = "x" };
knapp.Budget.DailyCostUsd = 0.40m;
var p = KostenPrognose.Berechne(
[Stuendlich("t-1")], Belege(("t-1", [Beleg("t-1", 0.02m)])), [], [knapp], null, Jetzt);
var warnung = p.Budgetwarnungen.ShouldHaveSingleItem();
warnung.AgentId.ShouldBe("nachrichten");
warnung.KostenProTag.ShouldBe(0.48m);
warnung.BudgetProTag.ShouldBe(0.40m);
}
[Theory]
[InlineData(0)] // keine Grenze gesetzt
[InlineData(1.0)] // Budget reicht
public void Ohne_Grenze_oder_mit_Luft_keine_Budgetwarnung(double budget)
{
var agent = new AgentConfig { AgentId = "nachrichten", Model = Nachrichten.Model, SystemPrompt = "x" };
agent.Budget.DailyCostUsd = (decimal)budget;
KostenPrognose.Berechne([Stuendlich("t-1")], Belege(("t-1", [Beleg("t-1", 0.02m)])), [], [agent], null, Jetzt)
.Budgetwarnungen.ShouldBeEmpty();
}
[Fact]
public void Werkzeugjob_zaehlt_nur_tatsaechliche_Weckungen()
{