KI-Feature 4.5.20: Medienvorschlag + Zwischenablage-Prompt für externe Erzeugung

Die KI liefert je Verlaufsplan-Phase optional einen kurzen Vorschlag, was ein
Medium/Material (z.B. Tafelbild) zeigen sollte (AiPhaseStep.MaterialSuggestion),
nur wenn das über das ohnehin genannte Material hinaus einen Mehrwert hätte.
Bewusst nicht ins Domänenmodell übernommen (keine Migration nötig) — nur für
die Review-Anzeige relevant.

AiPlanningService.BuildMaterialPrompt baut daraus rein lokal (kein weiterer
KI-Aufruf) einen vollständigen Prompt aus Fach/Stufe/Gruppe, Einheit, Stunde
und Phase. Im AiAssistDialog landet er per Klick in der Zwischenablage, zum
Einfügen in eine separate Claude-Sitzung für die eigentliche Materialerzeugung.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 21:22:12 +02:00
co-authored by Claude Sonnet 5
parent da62a08437
commit f703fe7b66
8 changed files with 161 additions and 3 deletions
@@ -205,6 +205,50 @@ public sealed class AiPlanningServiceTests
Assert.Contains(service.DescribeChanges(existing, proposed), d => d.Contains("Verlaufsplan"));
}
[Fact]
public void BuildMaterialPrompt_EnthaeltKontextUndVorschlag()
{
var subject = new Subject { Name = "Chemie" };
var group = new LearningGroup { Name = "9c", SubjectId = subject.Id, GradeLevel = 9 };
var unit = new Unit { GroupId = group.Id, Title = "Redoxreaktionen" };
var lesson = new AiLesson { Topic = "Elektrolyse", Date = new DateOnly(2026, 3, 17), Phases = [] };
var phase = new AiPhaseStep
{
Name = "Erarbeitung", DurationMinutes = 20, Activity = "Experiment auswerten",
Material = "AB003", MaterialSuggestion = "Tafelbild mit dem Aufbau der Elektrolysezelle.",
};
var service = Build(new FakeLessons(), new FakeGroups([group]), new FakeSubjects([subject]),
new FakeCompetencyDomains(), new FakeAlternativeLessonPaths([]));
var prompt = service.BuildMaterialPrompt(unit, lesson, phase);
Assert.Contains("Chemie", prompt);
Assert.Contains("9c", prompt);
Assert.Contains("Redoxreaktionen", prompt);
Assert.Contains("Elektrolyse", prompt);
Assert.Contains("Erarbeitung", prompt);
Assert.Contains("AB003", prompt);
Assert.Contains("Tafelbild mit dem Aufbau der Elektrolysezelle.", prompt);
}
[Fact]
public void BuildMaterialPrompt_OhneBisherigesMaterial_LaesstZeileWeg()
{
var group = new LearningGroup();
var unit = new Unit { GroupId = group.Id, Title = "T" };
var lesson = new AiLesson { Topic = "Stunde", Phases = [] };
var phase = new AiPhaseStep { Name = "Einstieg", MaterialSuggestion = "Kurzer Impuls per Bild." };
var service = Build(new FakeLessons(), new FakeGroups([group]), new FakeSubjects([]),
new FakeCompetencyDomains(), new FakeAlternativeLessonPaths([]));
var prompt = service.BuildMaterialPrompt(unit, lesson, phase);
Assert.DoesNotContain("Bisheriges Material", prompt);
Assert.Contains("Kurzer Impuls per Bild.", prompt);
}
[Fact]
public void ApplyResponse_BekannteId_WirdAlsUpdateBehandelt()
{