namespace ClawdDotNet.Core.Accounting; /// Verbrauch eines abgeschlossenen Laufs. public sealed record RunUsage { public long Id { get; init; } public string AgentId { get; init; } = ""; public string Model { get; init; } = ""; public int PromptTokens { get; init; } public int CompletionTokens { get; init; } /// Anteil der Eingabe-Tokens aus dem Prompt-Cache — in PromptTokens enthalten. public int CachedTokens { get; init; } public int TotalTokens => PromptTokens + CompletionTokens; public decimal CostUsd { get; init; } /// /// Ob für das Modell Preise vorlagen. Ohne diese Angabe wäre eine zu niedrige /// Summe von einer vollständigen nicht zu unterscheiden. /// public bool CostIsKnown { get; init; } public string Status { get; init; } = ""; public int StepCount { get; init; } public long DurationMs { get; init; } public DateTime OccurredAt { get; init; } /// /// #717: The task whose special budget the run drew on; empty for the daily budget. Such /// runs do not count against the daily limits — that is what the pot is for. /// public string BudgetPot { get; init; } = ""; /// #712: The runtime of the run; empty for native. public string Runtime { get; init; } = ""; /// #712: Paid from a subscription's quota. The cost is 0 $, the tokens are real (#699). public bool OnSubscription { get; init; } } /// Verbrauch eines Tages, aggregiert. public sealed record DailyUsage( DateOnly Date, int PromptTokens, int CompletionTokens, decimal CostUsd, bool CostIsComplete, int RunCount) { public int TotalTokens => PromptTokens + CompletionTokens; public static DailyUsage Empty(DateOnly date) => new(date, 0, 0, 0m, true, 0); } public interface IUsageRepository { Task RecordAsync(RunUsage usage, CancellationToken ct); /// Tagesverbrauch eines Agenten. leer = ganze Instanz. Task GetDailyAsync(DateOnly date, string agentId, CancellationToken ct); /// /// #717: What counts against the daily limits — the day's usage without runs that drew on /// a special budget. keeps showing everything that was used. /// Task GetDailyForBudgetAsync(DateOnly date, string agentId, CancellationToken ct) => GetDailyAsync(date, agentId, ct); Task> GetRecentAsync(int limit, CancellationToken ct); /// /// #716: The most recent runs of one agent — the basis for estimating what a run of /// it will cost. Without an implementation there is no estimate, and a reservation /// counts nothing. /// Task> GetRecentForAgentAsync(string agentId, int limit, CancellationToken ct) => Task.FromResult>([]); /// Entfernt Einträge älter als das angegebene Datum. Gibt die Anzahl zurück. Task PurgeBeforeAsync(DateOnly date, CancellationToken ct); }