feat(usage): add per-task token usage tracking
Extract token usage from Claude Code's stream-json output in real-time during task execution, replacing the inaccurate global JSONL log scanner. - New `task_usage` table: tracks (task_id, provider, model) level usage - Agent SDK: parse `message.usage` from assistant messages, accumulate per-model and return in Result - Daemon: convert agent usage to entries, send with CompleteTask - Server: store usage on task completion, expose workspace-level aggregation APIs (GET /api/usage/daily, GET /api/usage/summary)
This commit is contained in:
parent
abcc7bf3cd
commit
8a8d3ea20e
14 changed files with 477 additions and 19 deletions
47
server/pkg/db/queries/task_usage.sql
Normal file
47
server/pkg/db/queries/task_usage.sql
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
-- name: UpsertTaskUsage :exec
|
||||
INSERT INTO task_usage (task_id, provider, model, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
ON CONFLICT (task_id, provider, model)
|
||||
DO UPDATE SET
|
||||
input_tokens = EXCLUDED.input_tokens,
|
||||
output_tokens = EXCLUDED.output_tokens,
|
||||
cache_read_tokens = EXCLUDED.cache_read_tokens,
|
||||
cache_write_tokens = EXCLUDED.cache_write_tokens;
|
||||
|
||||
-- name: GetTaskUsage :many
|
||||
SELECT * FROM task_usage
|
||||
WHERE task_id = $1
|
||||
ORDER BY model;
|
||||
|
||||
-- name: GetWorkspaceUsageByDay :many
|
||||
SELECT
|
||||
DATE(atq.created_at) AS date,
|
||||
tu.model,
|
||||
SUM(tu.input_tokens)::bigint AS total_input_tokens,
|
||||
SUM(tu.output_tokens)::bigint AS total_output_tokens,
|
||||
SUM(tu.cache_read_tokens)::bigint AS total_cache_read_tokens,
|
||||
SUM(tu.cache_write_tokens)::bigint AS total_cache_write_tokens,
|
||||
COUNT(DISTINCT tu.task_id)::int AS task_count
|
||||
FROM task_usage tu
|
||||
JOIN agent_task_queue atq ON atq.id = tu.task_id
|
||||
JOIN agent a ON a.id = atq.agent_id
|
||||
WHERE a.workspace_id = $1
|
||||
AND atq.created_at >= @since::timestamptz
|
||||
GROUP BY DATE(atq.created_at), tu.model
|
||||
ORDER BY DATE(atq.created_at) DESC, tu.model;
|
||||
|
||||
-- name: GetWorkspaceUsageSummary :many
|
||||
SELECT
|
||||
tu.model,
|
||||
SUM(tu.input_tokens)::bigint AS total_input_tokens,
|
||||
SUM(tu.output_tokens)::bigint AS total_output_tokens,
|
||||
SUM(tu.cache_read_tokens)::bigint AS total_cache_read_tokens,
|
||||
SUM(tu.cache_write_tokens)::bigint AS total_cache_write_tokens,
|
||||
COUNT(DISTINCT tu.task_id)::int AS task_count
|
||||
FROM task_usage tu
|
||||
JOIN agent_task_queue atq ON atq.id = tu.task_id
|
||||
JOIN agent a ON a.id = atq.agent_id
|
||||
WHERE a.workspace_id = $1
|
||||
AND atq.created_at >= @since::timestamptz
|
||||
GROUP BY tu.model
|
||||
ORDER BY (SUM(tu.input_tokens) + SUM(tu.output_tokens)) DESC;
|
||||
Loading…
Add table
Add a link
Reference in a new issue