feat: Untis-Hub-Kadenzkopplung, anpassbarer Statusvorschlag + KI-/MCP-Unterstuetzung beim Fehlzeitenabgleich (Nutzer-Feedback)
CI / build-and-test (push) Canceled after 0s
CI / build-and-test (push) Canceled after 0s
- UntisHubService.RecordRun: ein abgeschlossener Langzeit-Fehlzeitenabgleich schliesst die kurzfristige Kadenz derselben Gruppe automatisch mit ab (nicht umgekehrt). - Fehlzeitenabgleich-Dialog: neue "Uebernahme als"-ComboBox statt starrem Zielstatus, vorbelegt mit dem berechneten Vorschlag, aber frei aenderbar. - Neuer ai-backend-Endpunkt untis-status.php + AiPlanningService.RequestUntisStatusSuggestionsAsync: gebuendelter, anonymisierter KI-Statusvorschlag (nur Positions-Id + Rohsignale, nie Name/Klasse/ Datum), mit hartem Id-Mengen-Abgleich gegen Verwechslung. - Neue MCP-Tools (UntisComparisonTools): get_untis_hub_status, get_untis_absence_rows/ apply_untis_absence_status (anonymer Weg ueber ENr-Zuordnung) sowie get_named_untis_absence_pattern als bewusste, eng begrenzte Ausnahme (Name+Fehlzeiten fuer explizit angegebene Schueler-IDs, mit Bestaetigung ohne Sitzungsfreigabe - dafuer IMcpConfirmationService.ConfirmAsync um allowSessionTrust erweitert). - MapStatus/ENr-Zuordnung aus dem ViewModel in das neue, geteilte UntisLessonAbsenceHelper gezogen, damit Dialog und MCP-Tool nie unterschiedliche Statusvorschlaege berechnen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -40,15 +40,18 @@ public sealed class AvaloniaMcpConfirmationService(AppLogger logger) : IMcpConfi
|
||||
private bool _trustAll;
|
||||
|
||||
public async Task<bool> ConfirmAsync(string title, string message, CancellationToken ct,
|
||||
[CallerMemberName] string operationKey = "")
|
||||
[CallerMemberName] string operationKey = "", bool allowSessionTrust = true)
|
||||
{
|
||||
bool alreadyTrusted;
|
||||
lock (_trustLock) alreadyTrusted = _trustAll || _trustedOperations.Contains(operationKey);
|
||||
if (alreadyTrusted)
|
||||
if (allowSessionTrust)
|
||||
{
|
||||
logger.Info($"MCP: „{title}“ automatisch bestätigt (Sitzungsfreigabe für " +
|
||||
$"{(_trustAll ? "alle Aktionen" : operationKey)}).");
|
||||
return true;
|
||||
bool alreadyTrusted;
|
||||
lock (_trustLock) alreadyTrusted = _trustAll || _trustedOperations.Contains(operationKey);
|
||||
if (alreadyTrusted)
|
||||
{
|
||||
logger.Info($"MCP: „{title}“ automatisch bestätigt (Sitzungsfreigabe für " +
|
||||
$"{(_trustAll ? "alle Aktionen" : operationKey)}).");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime { MainWindow: { } owner })
|
||||
@@ -65,7 +68,11 @@ public sealed class AvaloniaMcpConfirmationService(AppLogger logger) : IMcpConfi
|
||||
|
||||
var dialog = new McpConfirmDialog
|
||||
{
|
||||
DataContext = new McpConfirmDialogInfo { Title = title, Message = message, ConfirmText = "Übernehmen" },
|
||||
DataContext = new McpConfirmDialogInfo
|
||||
{
|
||||
Title = title, Message = message, ConfirmText = "Übernehmen",
|
||||
AllowSessionTrust = allowSessionTrust,
|
||||
},
|
||||
};
|
||||
var dialogTask = dialog.ShowDialog<McpConfirmDialogResult>(owner);
|
||||
var timeoutTask = Task.Delay(Timeout, ct);
|
||||
@@ -78,7 +85,7 @@ public sealed class AvaloniaMcpConfirmationService(AppLogger logger) : IMcpConfi
|
||||
return await dialogTask;
|
||||
});
|
||||
|
||||
if (result.Approved)
|
||||
if (result.Approved && allowSessionTrust)
|
||||
{
|
||||
lock (_trustLock)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user