chore: v2.8.22 — Users today/7/30-day spend counts every tool, update chip follows a running update

- Users: today / 7 / 30-day spend read only token_usage_hourly, which holds
  Claude transcript hours only — omp/Codex/Antigravity/Cursor sessions,
  sub-agent files, baselines and long-context pricing were missing. Now
  booked by hourlyTokenRows + calculateCost like the cost routes.
- Update: a page adopts a plugin update the server reports as running
  (after a reload, another tab, or one started from an older bundle), and
  the progress chip shows whenever an update runs and the modal is not
  visible — also when the status stops offering it mid-run.
This commit is contained in:
2026-10-23 11:26:12 +07:00
parent 9dd97a369c
commit 572d615d4e
9 changed files with 122 additions and 62 deletions
+14 -1
View File
@@ -57,10 +57,22 @@ before(async () => {
db.prepare(
"INSERT INTO sessions (id, name, status, cwd) VALUES ('sx', 'host work', 'active', '/w/host')"
).run();
db.prepare(
`INSERT INTO token_usage (session_id, model, output_tokens)
VALUES ('sm', 'claude-sonnet-4-5-20250929', 1000000)`
).run();
db.prepare(
`INSERT INTO token_usage_hourly (session_id, hour, model, output_tokens)
VALUES ('sm', ?, 'claude-sonnet-4-5-20250929', 1000000)`
).run(new Date().toISOString().slice(0, 13));
// A tool with no hourly rows (omp, Codex…): its total counts from its start.
db.prepare(
"INSERT INTO sessions (id, name, status, cwd, lane_id, tool) VALUES ('so', 'mia omp', 'active', '/w/mia', ?, 'omp')"
).run(lane);
db.prepare(
`INSERT INTO token_usage (session_id, model, output_tokens)
VALUES ('so', 'claude-sonnet-4-5-20250929', 500000)`
).run();
});
after(() => {
@@ -76,7 +88,8 @@ describe("staff views", () => {
assert.equal(r.status, 200);
const mia = r.body.users.find((u) => u.username === "mia");
assert.equal(mia.workspaces, 1);
assert.equal(mia.sessions, 1);
assert.equal(mia.sessions, 2);
assert.equal(mia.today.tokens, 1500000, "a session with no hourly rows counts too");
assert.ok(mia.last7d.cost > 0 && mia.last30d.cost >= mia.last7d.cost);
// This hour's spend is today's in every timezone.
assert.equal(mia.today.cost, mia.last7d.cost);