GET /usage serves the numbers behind Claude Code's /usage, read with the CLI's own stored OAuth credentials (nothing to configure). The endpoint is undocumented, so parsing is defensive -- the generic limits[] array becomes labeled window bars, unknown kinds surface under their raw name, and any failure degrades to an 'unavailable' snapshot with the reason. One UsageProvider per paid service behind a caching monitor that enforces the >=180s minimum poll regardless of phone refreshes; no background polling at all. ureq (rustls) does the outbound call, with the process-level CryptoProvider now chosen explicitly in main -- ureq brings ring while axum-server brings aws-lc-rs, and with both in the graph rustls refuses to guess. App: a Usage screen off the session list -- per-window bars colored by utilization with relative reset times. Verified live: 74%/26%/16% windows rendered against the real endpoint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xn8nHw1tw1R6PtiY1eEtw
46 lines
1.6 KiB
TOML
46 lines
1.6 KiB
TOML
[package]
|
|
name = "ai-server"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
|
|
[[bin]]
|
|
name = "ai-server"
|
|
path = "src/main.rs"
|
|
|
|
[dependencies]
|
|
axum = { version = "0.8", features = ["json", "multipart"] }
|
|
axum-server = { version = "0.8", features = ["tls-rustls"] }
|
|
tokio = { version = "1", features = ["rt-multi-thread", "macros", "net", "sync", "time", "process", "io-util"] }
|
|
tokio-stream = "0.1"
|
|
tracing = "0.1"
|
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
clap = { version = "4", features = ["derive"] }
|
|
anyhow = "1"
|
|
thiserror = "2"
|
|
# Token auth: hash for storage, constant-time compare for verification,
|
|
# CSPRNG-backed generation, base64url for the enrollment string.
|
|
sha2 = "0.11"
|
|
subtle = "2"
|
|
rand = "0.10"
|
|
base64 = "0.23"
|
|
# Renders the enrollment QR straight to the terminal; no image output needed.
|
|
qrcode = { version = "0.14", default-features = false }
|
|
# The wg0-bound listener needs the interface's address; the stdlib has no
|
|
# getifaddrs. This is the smallest crate that wraps just that.
|
|
if-addrs = "0.15"
|
|
# Outbound HTTPS for the usage endpoint. A small blocking client fits an
|
|
# every-few-minutes poll better than pulling in reqwest's tower stack;
|
|
# rustls-backed like the rest of the TLS here.
|
|
ureq = "3"
|
|
# Direct dependency only to pick the process-level CryptoProvider in main:
|
|
# ureq pulls rustls-with-ring, axum-server rustls-with-aws-lc-rs, and with
|
|
# both in the graph rustls refuses to auto-select one.
|
|
rustls = "0.23"
|
|
|
|
[dev-dependencies]
|
|
tempfile = "3"
|
|
# ServiceExt::oneshot, to drive the auth middleware without a socket.
|
|
tower = { version = "0.5", features = ["util"] }
|