using ClawdDotNet.Core.Engine; using ClawdDotNet.Core.Tests.Infrastructure; using Shouldly; namespace ClawdDotNet.Core.Tests.Engine; /// /// T2 aus der Token-Analyse: Ein einzelnes Tool-Ergebnis konnte den Kontext sprengen. /// Ein WebFetch mit dem Standardlimit von 512 KB entspricht rund 130.000 Tokens in /// EINER Antwort — die Compaction greift erst danach, bezahlt ist der Request längst. /// public sealed class ToolResultTruncationTests { [Fact] public async Task Ein_riesiges_Toolergebnis_wird_gekappt_bevor_es_in_den_Kontext_geht() { var riesig = new string('x', 500_000); var fixture = new EngineFixture().WithTool(FakeTool.Returning(riesig)); var agent = fixture.AddAgent("agent-trunc", "TestTool"); agent.MaxToolResultChars = 16_000; fixture.Client .RespondsWithToolCall("TestTool") .RespondsWithText("Fertig"); await fixture.Engine.ChatAsync(agent, "Hol die Daten", "test-instance", default); var context = fixture.Engine.GetChatContext(agent.AgentId); var toolMessage = context.Single(m => m.Role == "tool"); toolMessage.Content!.Length.ShouldBeLessThan(20_000); toolMessage.Content.ShouldContain("gekürzt"); } [Fact] public async Task Ein_kleines_Toolergebnis_bleibt_unveraendert() { const string klein = "Alles in Ordnung."; var fixture = new EngineFixture().WithTool(FakeTool.Returning(klein)); var agent = fixture.AddAgent("agent-klein", "TestTool"); fixture.Client .RespondsWithToolCall("TestTool") .RespondsWithText("Fertig"); await fixture.Engine.ChatAsync(agent, "Prüfe", "test-instance", default); var context = fixture.Engine.GetChatContext(agent.AgentId); context.Single(m => m.Role == "tool").Content.ShouldBe(klein); } [Theory] [InlineData(100, 50)] [InlineData(1_000, 999)] [InlineData(50_000, 16_000)] public void Gekappte_Ergebnisse_nennen_die_Menge_der_entfallenen_Zeichen(int length, int limit) { var result = AgentEngine.TruncateToolResult(new string('a', length), limit); result.ShouldStartWith(new string('a', limit)); result.ShouldContain((length - limit).ToString("N0")); } [Fact] public void Ohne_Limit_wird_nicht_gekappt() { var original = new string('a', 100_000); AgentEngine.TruncateToolResult(original, 0).ShouldBe(original); } [Fact] public void Genau_auf_der_Grenze_wird_nicht_gekappt() { var original = new string('a', 1_000); AgentEngine.TruncateToolResult(original, 1_000).ShouldBe(original); } }