using System.Text.Json; namespace ClawdDotNet.Core.Deploymentcenter; /// Was aus einem Bugtracker-Eintrag geworden ist. /// Nummer des Eintrags im Deploymentcenter. /// False, wenn ein bestehender Eintrag hochgezählt wurde. /// Wie oft dieses Vorkommnis bisher gezählt wurde. /// Adresse der Übersicht, für einen Hinweis an den Benutzer. public sealed record BugtrackerReport(long ItemId, bool IsNew, int OccurrenceCount, string? Url); /// Art eines Eintrags. Der Server kennt darüber hinaus noch idea. public static class BugtrackerItemType { public const string Bug = "bug"; public const string Feature = "feature"; public const string Idea = "idea"; } /// /// Anbindung an POST /api/bugtracker/v1/report — der Weg, auf dem ClawdDotNet /// selbst (oder ein Benutzer über die Oberfläche) einen Fehler oder Wunsch einträgt. /// /// Abgegrenzt vom : Der meldet ungefangene /// Ausnahmen automatisch; hier geht es um bewusst formulierte Einträge mit Titel und /// Beschreibung. Serverseitig landen beide in derselben Tabelle — was richtig ist, /// denn ein zweiter Speicher wäre nur ein zweiter Ort, an dem man suchen müsste. /// /// Der Absender kommt aus dem Token und lässt sich nicht frei wählen — /// sonst könnte sich ein Agent als ein anderer ausgeben. /// public sealed class BugtrackerClient( DeploymentcenterApi api, string projectSlug, string environment, string build) { /// Siehe . /// /// Freier Idempotenz-Schlüssel. Zweimal derselbe Wert erzeugt keinen zweiten /// Eintrag — nützlich, wenn eine Meldung nach einem Verbindungsabbruch wiederholt /// wird. /// public async Task ReportAsync( string type, string title, string? description = null, string severity = "medium", string? clientRef = null, IReadOnlyDictionary? context = null, CancellationToken ct = default) { var payload = new Dictionary { ["project_slug"] = projectSlug, ["type"] = type, ["title"] = title, ["description"] = description, ["severity"] = severity, ["environment"] = environment, ["build_version"] = build }; if (!string.IsNullOrWhiteSpace(clientRef)) payload["client_ref"] = clientRef; if (context is { Count: > 0 }) payload["context"] = context; var response = await api.PostAsync("/api/bugtracker/v1/report", payload, ct) .ConfigureAwait(false); return new BugtrackerReport( ReadLong(response, "item_id"), ReadBool(response, "is_new"), (int)ReadLong(response, "occurrence_count"), ReadString(response, "url")); } private static long ReadLong(JsonElement root, string name) => root.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.Number ? v.GetInt64() : 0; private static bool ReadBool(JsonElement root, string name) => root.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.True; private static string? ReadString(JsonElement root, string name) => root.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.String ? v.GetString() : null; }