KI-Feature 4.5.22: KI-Unterstützung direkt aus dem Stunden-Editor starten
Bisher musste man aus dem Stunden-Editor raus, die KI-Hilfe für die ganze Einheit aufrufen und die gewünschte Stunde in der freien Anweisung erst benennen. Neuer Button "KI-Unterstützung für diese Stunde" im LessonDialog öffnet denselben AiAssistDialog im neuen Fokus-Modus. AiPlanningRequest.FocusLessonId weist die KI im Systemprompt an, sich auf genau diese Stunde zu beschränken; zusätzlich wie beim Umfangs-Umschalter client-seitig hart durchgesetzt in Send() und ApplyResponse, statt der KI-Antwort blind zu vertrauen. Da "Übernehmen" direkt ins Repository speichert, wären die noch offenen Feldwerte des ursprünglichen LessonDialog danach veraltet gewesen - der Dialog schließt sich deshalb nach einer angewendeten KI-Änderung automatisch mit dem frischen Stand statt ihn mit alten Werten zu überschreiben. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -631,6 +631,18 @@ public partial class LessonDialogViewModel : ObservableObject
|
||||
public string DialogTitle => _editingLesson is null ? "Neue Stunde anlegen" : "Stunde bearbeiten";
|
||||
public string SaveButtonText => _editingLesson is null ? "Anlegen" : "Speichern";
|
||||
|
||||
// Für die KI-Unterstützung mit Fokus auf genau diese Stunde (4.5.22) — nur für bereits
|
||||
// gespeicherte Stunden sinnvoll, eine gerade erst angelegte, noch ungespeicherte Stunde hat
|
||||
// keine echte Id, auf die sich die KI beziehen könnte.
|
||||
public Guid UnitId => _unitId;
|
||||
public Lesson? EditingLesson => _editingLesson;
|
||||
public bool CanAiAssist => _editingLesson is not null;
|
||||
|
||||
/// Vom Code-Behind nach einer über die KI angewendeten Änderung aufgerufen: der Dialog schließt
|
||||
/// sich danach mit Result != null, damit die aufrufende Liste neu lädt — die eigenen, jetzt
|
||||
/// veralteten Feldwerte dieses Fensters werden NICHT mehr über die KI-Änderung gespeichert.
|
||||
public void MarkAppliedExternally(Lesson updated) => Result = updated;
|
||||
|
||||
public LessonDialogViewModel(ILessonRepository lessons, IShorthandCodeRepository shorthandCodes,
|
||||
IAlternativeLessonPathRepository alternativePaths, ITimetableSlotRepository timetableSlots,
|
||||
PeriodScheduleService periodSchedule, Guid unitId, Guid groupId,
|
||||
@@ -1156,6 +1168,7 @@ public partial class AiAssistDialogViewModel : ObservableObject
|
||||
private readonly AiSettingsService _aiSettings;
|
||||
private readonly ILessonRepository _lessons;
|
||||
private readonly Unit _unit;
|
||||
private readonly Lesson? _focusLesson;
|
||||
|
||||
[ObservableProperty] private string _instruction = "";
|
||||
[ObservableProperty] private bool _allowModifyingExisting = true;
|
||||
@@ -1168,10 +1181,22 @@ public partial class AiAssistDialogViewModel : ObservableObject
|
||||
public ObservableCollection<AiLessonReviewItem> ReviewItems { get; } = [];
|
||||
public bool Result { get; private set; }
|
||||
|
||||
/// Aus dem Editor einer einzelnen Stunde heraus gestartet (statt aus der Einheiten-Übersicht,
|
||||
/// Nutzer-Feedback nach den ersten Live-Tests) — die KI darf dann ausschließlich diese eine
|
||||
/// Stunde bearbeiten, der Umfangs-Umschalter macht in diesem Modus keinen Sinn und wird
|
||||
/// ausgeblendet (siehe AiAssistDialog.axaml).
|
||||
public bool IsFocusMode => _focusLesson is not null;
|
||||
public string? FocusLabel => _focusLesson is null ? null
|
||||
: $"Fokus: nur diese Stunde — „{_focusLesson.Topic}“ ({_focusLesson.Date:dd.MM.yyyy})";
|
||||
|
||||
public AiAssistDialogViewModel(AiPlanningService aiPlanning, AiSettingsService aiSettings,
|
||||
ILessonRepository lessons, Unit unit)
|
||||
ILessonRepository lessons, Unit unit, Lesson? focusLesson = null)
|
||||
{
|
||||
_aiPlanning = aiPlanning; _aiSettings = aiSettings; _lessons = lessons; _unit = unit;
|
||||
_focusLesson = focusLesson;
|
||||
// Ohne Änderungserlaubnis gäbe es im Fokus-Modus nichts, was die KI überhaupt vorschlagen
|
||||
// dürfte (neue Stunden sind hier ja ausdrücklich nicht das Ziel) — deshalb erzwungen an.
|
||||
if (IsFocusMode) AllowModifyingExisting = true;
|
||||
var lessonCount = lessons.GetByUnit(unit.Id).Count;
|
||||
UnitSummary = $"Einheit: {unit.Title} — {lessonCount} Stunde(n)";
|
||||
}
|
||||
@@ -1196,11 +1221,18 @@ public partial class AiAssistDialogViewModel : ObservableObject
|
||||
ErrorMessage = ""; IsBusy = true;
|
||||
try
|
||||
{
|
||||
var response = await _aiPlanning.RequestPlanAsync(_unit, Instruction, token, AllowModifyingExisting, draftOverrides);
|
||||
var response = await _aiPlanning.RequestPlanAsync(_unit, Instruction, token, AllowModifyingExisting,
|
||||
draftOverrides, _focusLesson?.Id);
|
||||
var existingLessons = _lessons.GetByUnit(_unit.Id).ToDictionary(l => l.Id);
|
||||
|
||||
// Im Fokus-Modus hart auf die eine angefragte Stunde beschränken, statt der KI-Antwort
|
||||
// zu vertrauen — dieselbe Absicherung wie beim Umfangs-Umschalter unten.
|
||||
var lessonsToShow = IsFocusMode
|
||||
? response.Lessons.Where(l => l.Id == _focusLesson!.Id).ToList()
|
||||
: response.Lessons;
|
||||
|
||||
ReviewItems.Clear();
|
||||
foreach (var l in response.Lessons)
|
||||
foreach (var l in lessonsToShow)
|
||||
{
|
||||
var isExisting = l.Id is { } id && existingLessons.ContainsKey(id);
|
||||
// Falls der Modus Änderungen an bestehenden Stunden verbietet, aber die KI die
|
||||
@@ -1226,7 +1258,7 @@ public partial class AiAssistDialogViewModel : ObservableObject
|
||||
private void Apply()
|
||||
{
|
||||
var accepted = ReviewItems.Where(i => i.Accepted).Select(i => i.Source).ToList();
|
||||
foreach (var lesson in _aiPlanning.ApplyResponse(_unit, accepted, AllowModifyingExisting))
|
||||
foreach (var lesson in _aiPlanning.ApplyResponse(_unit, accepted, AllowModifyingExisting, _focusLesson?.Id))
|
||||
_lessons.Save(lesson);
|
||||
Result = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user