feat(dashboard): show Claude usage (tokens + requests) since server start

ClaudeBrain now returns per-reply token usage (Reply.usage from the API
response), the dashboard accumulates it (monitor.add_claude_usage), and the
header shows a "클로드 토큰" stat (input+output total, with a tooltip breaking
down input/output tokens and request count).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
EJClaw
2026-08-22 16:40:25 +09:00
parent 5d9161982f
commit f1f059a018
4 changed files with 28 additions and 1 deletions

View File

@@ -169,6 +169,10 @@ class Monitor:
"components": {},
"turns_total": 0,
"errors_total": 0,
# Claude usage since server start (this bot's own consumption).
"claude_requests": 0,
"claude_input_tokens": 0,
"claude_output_tokens": 0,
}
self._lock = threading.Lock()
self._subs: list["queue.Queue[str]"] = []
@@ -192,6 +196,14 @@ class Monitor:
s["uptime_s"] = round(_now_wall() - s["started_wall"], 1)
return s
def add_claude_usage(self, input_tokens: int, output_tokens: int) -> None:
"""Accumulate one Claude call's token usage for the dashboard."""
with self._lock:
self._status["claude_requests"] += 1
self._status["claude_input_tokens"] += int(input_tokens or 0)
self._status["claude_output_tokens"] += int(output_tokens or 0)
self._broadcast({"type": "status", "status": self.status_snapshot()})
def log(self, level: str, message: str) -> None:
"""A free-form lifecycle/error line (startup, disconnect, crash…)."""
with self._lock: