The modal deliberately shows only a slice of the analytics; this hands off to TokenTracker's own local dashboard for the rest. The worker starts `tokentracker serve` on demand and returns the URL, the UI opens the browser. Three things the spawn has to get right: port 7680 is not free on Windows (Delivery Optimization holds [::]:7680) and serve does not fall back, so we scan 7680-7689 with a dual-stack bind probe; --no-open because the CLI would open the browser before the server answers; and the child is a cmd.exe shim, so shutdown kills the process tree. --no-sync keeps our no-cloud-sync rule.
57 lines
2.0 KiB
C#
57 lines
2.0 KiB
C#
using ClaudeDo.Worker.Usage.TokenTracker;
|
|
using ClaudeDo.Worker.Usage.TokenTracker.Interfaces;
|
|
|
|
namespace ClaudeDo.Worker.Tests.Usage.TokenTracker;
|
|
|
|
public sealed class FakeTokenTrackerClient : ITokenTrackerClient
|
|
{
|
|
private readonly SemaphoreSlim _gate = new(0);
|
|
|
|
public TokenTrackerProbe Probe { get; set; } = new(true, "1.2.3", true, "v22.1.0", null);
|
|
public TokenTrackerRunResult ExportResult { get; set; } =
|
|
new(true, TokenTrackerFixtures.SessionsJson, null);
|
|
public TokenTrackerRunResult InstallResult { get; set; } = new(true, "added 1 package", null);
|
|
|
|
public int ExportCalls;
|
|
public int ProbeCalls;
|
|
public int InstallCalls;
|
|
public DateOnly? LastFrom;
|
|
public DateOnly? LastTo;
|
|
|
|
/// <summary>When true, <see cref="ExportAsync"/> blocks until <see cref="Release"/> is called.</summary>
|
|
public bool BlockExport { get; set; }
|
|
|
|
public void Release() => _gate.Release();
|
|
|
|
public Task<TokenTrackerProbe> ProbeAsync(CancellationToken ct = default)
|
|
{
|
|
Interlocked.Increment(ref ProbeCalls);
|
|
return Task.FromResult(Probe);
|
|
}
|
|
|
|
public async Task<TokenTrackerRunResult> ExportAsync(DateOnly from, DateOnly to, CancellationToken ct = default)
|
|
{
|
|
Interlocked.Increment(ref ExportCalls);
|
|
LastFrom = from;
|
|
LastTo = to;
|
|
if (BlockExport) await _gate.WaitAsync(ct);
|
|
return ExportResult;
|
|
}
|
|
|
|
public TokenTrackerDashboard DashboardResult { get; set; } = new(true, "http://127.0.0.1:7680/", null);
|
|
public int DashboardCalls;
|
|
|
|
public Task<TokenTrackerDashboard> StartDashboardAsync(CancellationToken ct = default)
|
|
{
|
|
Interlocked.Increment(ref DashboardCalls);
|
|
return Task.FromResult(DashboardResult);
|
|
}
|
|
|
|
public Task<TokenTrackerRunResult> InstallAsync(IProgress<string>? output = null, CancellationToken ct = default)
|
|
{
|
|
Interlocked.Increment(ref InstallCalls);
|
|
output?.Report("added 1 package");
|
|
return Task.FromResult(InstallResult);
|
|
}
|
|
}
|