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
@@ -249,6 +249,39 @@ public class AiPlanningService(HttpClient http, ILessonRepository lessons,
return diffs;
}
/// <summary>
/// Baut aus Einheit/Stunde/Phase und dem KI-Medienvorschlag (<see cref="AiPhaseStep.MaterialSuggestion"/>)
/// einen vollständigen, eigenständigen Prompt zum Einfügen in eine separate Claude-Sitzung —
/// die Lehrkraft kann sich das eigentliche Material (Tafelbild, Arbeitsblatt, ...) dort selbst
/// erzeugen lassen, ohne dass das über das eigene (kostenpflichtige) KI-Backend laufen muss.
/// Nur der kurze Vorschlagstext kommt von der KI, der restliche Kontext wird rein lokal aus
/// bereits vorhandenen Daten zusammengesetzt. Rein, ohne I/O.
/// </summary>
public string BuildMaterialPrompt(Unit unit, AiLesson lesson, AiPhaseStep phase)
{
var group = groups.GetById(unit.GroupId);
var subject = group?.SubjectId is { } subjectId ? subjects.GetById(subjectId) : null;
var dateText = lesson.Date?.ToString("dd.MM.yyyy", CultureInfo.InvariantCulture) ?? "noch offen";
var lines = new List<string>
{
$"Ich unterrichte {subject?.Name ?? "unbekanntes Fach"}, Klassenstufe {group?.GradeLevel ?? 0}, Gruppe {group?.Name ?? "-"}.",
$"Einheit: „{unit.Title}“",
$"Stunde: „{lesson.Topic}“ (Datum: {dateText})",
$"Phase: „{phase.Name}“, {phase.DurationMinutes} Min., Tätigkeit: {phase.Activity}",
};
if (!string.IsNullOrWhiteSpace(phase.Material))
lines.Add($"Bisheriges Material laut Planung: {phase.Material}");
lines.Add("");
lines.Add("Empfehlung aus der Unterrichtsplanung, was das Material zeigen/enthalten sollte:");
lines.Add(phase.MaterialSuggestion ?? "");
lines.Add("");
lines.Add("Bitte erstelle mir auf dieser Grundlage ein passendes Material für diese Phase " +
"(z.B. Tafelbild, Arbeitsblatt oder Visualisierung).");
return string.Join("\n", lines);
}
/// <summary>
/// Ersetzt in <paramref name="saved"/> (dem tatsächlichen Datenbankstand) jede Lesson, deren Id
/// auch in <paramref name="draft"/> vorkommt, durch die Entwurfsversion, und hängt Entwürfe ohne