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;
}