feat: add token usage tracking and leaderboard

- Add token_usage table with composite unique index for claw_id + date
- Add API endpoints: POST /token, GET /token/leaderboard, GET /token/stats
- Add TokenLeaderboard component with daily/total period toggle
- Add CLI commands: `token` and `stats` for reporting and viewing usage
- Add Redis caching for leaderboard with 1-minute TTL
- Add shared utilities: authenticateRequest, getTodayDateString
- Use UPSERT pattern for atomic token updates
- Add i18n translations (en/zh) for new UI elements
This commit is contained in:
richarjiang
2026-03-15 15:17:10 +08:00
parent 8d094ad5cc
commit 36f10954cf
22 changed files with 3140 additions and 11 deletions

View File

@@ -0,0 +1,69 @@
CREATE TABLE `claws` (
`id` varchar(21) NOT NULL,
`api_key` varchar(64) NOT NULL,
`name` varchar(100) NOT NULL,
`platform` varchar(20),
`model` varchar(50),
`ip` varchar(45),
`latitude` decimal(10,7),
`longitude` decimal(10,7),
`city` varchar(100),
`country` varchar(100),
`country_code` varchar(5),
`region` varchar(50),
`last_heartbeat` datetime,
`total_tasks` int DEFAULT 0,
`created_at` datetime DEFAULT NOW(),
`updated_at` datetime DEFAULT NOW(),
CONSTRAINT `claws_id` PRIMARY KEY(`id`),
CONSTRAINT `claws_api_key_unique` UNIQUE(`api_key`)
);
--> statement-breakpoint
CREATE TABLE `geo_cache` (
`ip` varchar(45) NOT NULL,
`latitude` decimal(10,7),
`longitude` decimal(10,7),
`city` varchar(100),
`country` varchar(100),
`country_code` varchar(5),
`region` varchar(50),
`updated_at` datetime DEFAULT NOW(),
CONSTRAINT `geo_cache_ip` PRIMARY KEY(`ip`)
);
--> statement-breakpoint
CREATE TABLE `heartbeats` (
`id` bigint AUTO_INCREMENT NOT NULL,
`claw_id` varchar(21) NOT NULL,
`ip` varchar(45),
`timestamp` datetime DEFAULT NOW(),
CONSTRAINT `heartbeats_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `tasks` (
`id` bigint AUTO_INCREMENT NOT NULL,
`claw_id` varchar(21) NOT NULL,
`summary` varchar(500),
`duration_ms` int,
`model` varchar(50),
`tools_used` json,
`timestamp` datetime DEFAULT NOW(),
CONSTRAINT `tasks_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `token_usage` (
`id` bigint AUTO_INCREMENT NOT NULL,
`claw_id` varchar(21) NOT NULL,
`date` varchar(10) NOT NULL,
`input_tokens` bigint NOT NULL DEFAULT 0,
`output_tokens` bigint NOT NULL DEFAULT 0,
`created_at` datetime DEFAULT NOW(),
`updated_at` datetime DEFAULT NOW(),
CONSTRAINT `token_usage_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE INDEX `heartbeats_claw_id_idx` ON `heartbeats` (`claw_id`);--> statement-breakpoint
CREATE INDEX `heartbeats_timestamp_idx` ON `heartbeats` (`timestamp`);--> statement-breakpoint
CREATE INDEX `tasks_claw_id_idx` ON `tasks` (`claw_id`);--> statement-breakpoint
CREATE INDEX `tasks_timestamp_idx` ON `tasks` (`timestamp`);--> statement-breakpoint
CREATE INDEX `token_usage_claw_id_idx` ON `token_usage` (`claw_id`);--> statement-breakpoint
CREATE INDEX `token_usage_date_idx` ON `token_usage` (`date`);