feat(worker): add OAuth usage client + poller

Adds Usage/ with ClaudeOAuthUsageClient (reads the access token Claude
Code keeps fresh at ~/.claude/.credentials.json, calls the Anthropic
OAuth usage endpoint, defensively parses buckets/limits), UsageState
(threadsafe last-good-snapshot holder that never regresses on
failure), and UsageMonitorService (BackgroundService polling on the
new usage_poll_interval_seconds config, min 15s, one poll at startup,
warns at most once per distinct error).
This commit is contained in:
mika kuns
2026-08-05 10:00:25 +02:00
parent 8d7ba1e314
commit 20d17c6887
11 changed files with 619 additions and 0 deletions
+11
View File
@@ -19,6 +19,8 @@ using ClaudeDo.Worker.Refine;
using ClaudeDo.Worker.Report;
using ClaudeDo.Worker.Report.Interfaces;
using ClaudeDo.Worker.Skills;
using ClaudeDo.Worker.Usage;
using ClaudeDo.Worker.Usage.Interfaces;
using ClaudeDo.Worker.Worktrees;
using Microsoft.EntityFrameworkCore;
using Serilog;
@@ -193,6 +195,15 @@ if (cfg.OnlineInbox.Enabled)
builder.Services.AddHostedService<OnlineSyncService>();
}
// OAuth usage monitor: reads the access token Claude Code keeps fresh in
// ~/.claude/.credentials.json and polls Anthropic's usage endpoint.
builder.Services.AddSingleton<UsageState>();
builder.Services.AddHttpClient<IUsageClient, ClaudeOAuthUsageClient>(client =>
{
client.Timeout = TimeSpan.FromSeconds(5);
});
builder.Services.AddHostedService<UsageMonitorService>();
// Loopback-only bind. Firewall is irrelevant for 127.0.0.1.
builder.WebHost.UseUrls($"http://127.0.0.1:{cfg.SignalRPort}");