// Code generated by sqlc. DO NOT EDIT. // versions: // sqlc v1.31.1 // source: runtime_usage.sql package db import ( "context" "github.com/jackc/pgx/v5/pgtype" ) const getRuntimeTaskHourlyActivity = `-- name: GetRuntimeTaskHourlyActivity :many SELECT EXTRACT(HOUR FROM started_at AT TIME ZONE $2::text)::int AS hour, COUNT(*)::int AS count FROM agent_task_queue WHERE runtime_id = $1 AND started_at IS NOT NULL GROUP BY hour ORDER BY hour ` type GetRuntimeTaskHourlyActivityParams struct { RuntimeID pgtype.UUID `json:"runtime_id"` Tz string `json:"tz"` } type GetRuntimeTaskHourlyActivityRow struct { Hour int32 `json:"hour"` Count int32 `json:"count"` } // Hour-of-day distribution for queue starts. Bucketed in the viewer's // tz so "this runtime is busy in the afternoon" actually means // the operator's afternoon, not UTC's. func (q *Queries) GetRuntimeTaskHourlyActivity(ctx context.Context, arg GetRuntimeTaskHourlyActivityParams) ([]GetRuntimeTaskHourlyActivityRow, error) { rows, err := q.db.Query(ctx, getRuntimeTaskHourlyActivity, arg.RuntimeID, arg.Tz) if err != nil { return nil, err } defer rows.Close() items := []GetRuntimeTaskHourlyActivityRow{} for rows.Next() { var i GetRuntimeTaskHourlyActivityRow if err := rows.Scan(&i.Hour, &i.Count); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const getRuntimeUsageByHour = `-- name: GetRuntimeUsageByHour :many SELECT EXTRACT(HOUR FROM tu.created_at AT TIME ZONE $2::text)::int AS hour, tu.model, SUM(tu.input_tokens)::bigint AS input_tokens, SUM(tu.output_tokens)::bigint AS output_tokens, SUM(tu.cache_read_tokens)::bigint AS cache_read_tokens, SUM(tu.cache_write_tokens)::bigint AS 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 WHERE atq.runtime_id = $1 AND tu.created_at >= $3::timestamptz GROUP BY EXTRACT(HOUR FROM tu.created_at AT TIME ZONE $2::text), tu.model ORDER BY hour, tu.model ` type GetRuntimeUsageByHourParams struct { RuntimeID pgtype.UUID `json:"runtime_id"` Tz string `json:"tz"` Since pgtype.Timestamptz `json:"since"` } type GetRuntimeUsageByHourRow struct { Hour int32 `json:"hour"` Model string `json:"model"` InputTokens int64 `json:"input_tokens"` OutputTokens int64 `json:"output_tokens"` CacheReadTokens int64 `json:"cache_read_tokens"` CacheWriteTokens int64 `json:"cache_write_tokens"` TaskCount int32 `json:"task_count"` } // Per-(hour, model) token aggregates (hour ∈ 0..23) for a runtime since a // cutoff. Powers the "By hour" tab — shows when in the day this runtime is // doing real work, with model preserved for client-side cost calculation // (same reason as ListRuntimeUsageByAgent above). Hours with zero activity // are omitted; the client fills the 24-bucket axis. // // Hours are extracted in the viewer's tz via @tz so afternoon // work bucketed at UTC 06:00 lands in 14:00 for a UTC+8 viewer. func (q *Queries) GetRuntimeUsageByHour(ctx context.Context, arg GetRuntimeUsageByHourParams) ([]GetRuntimeUsageByHourRow, error) { rows, err := q.db.Query(ctx, getRuntimeUsageByHour, arg.RuntimeID, arg.Tz, arg.Since) if err != nil { return nil, err } defer rows.Close() items := []GetRuntimeUsageByHourRow{} for rows.Next() { var i GetRuntimeUsageByHourRow if err := rows.Scan( &i.Hour, &i.Model, &i.InputTokens, &i.OutputTokens, &i.CacheReadTokens, &i.CacheWriteTokens, &i.TaskCount, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listRuntimeUsage = `-- name: ListRuntimeUsage :many SELECT DATE(bucket_hour AT TIME ZONE $2::text) AS date, provider, model, SUM(input_tokens)::bigint AS input_tokens, SUM(output_tokens)::bigint AS output_tokens, SUM(cache_read_tokens)::bigint AS cache_read_tokens, SUM(cache_write_tokens)::bigint AS cache_write_tokens FROM task_usage_hourly WHERE runtime_id = $1 AND bucket_hour >= $3::timestamptz GROUP BY DATE(bucket_hour AT TIME ZONE $2::text), provider, model ORDER BY DATE(bucket_hour AT TIME ZONE $2::text) DESC, provider, model ` type ListRuntimeUsageParams struct { RuntimeID pgtype.UUID `json:"runtime_id"` Tz string `json:"tz"` Since pgtype.Timestamptz `json:"since"` } type ListRuntimeUsageRow struct { Date pgtype.Date `json:"date"` Provider string `json:"provider"` Model string `json:"model"` InputTokens int64 `json:"input_tokens"` OutputTokens int64 `json:"output_tokens"` CacheReadTokens int64 `json:"cache_read_tokens"` CacheWriteTokens int64 `json:"cache_write_tokens"` } // Reads from the UTC-bucketed `task_usage_hourly` rollup table, // aggregated to per-(date, provider, model) under the // caller-supplied @tz. Powers the trend chart on the runtime detail // page and the per-row cost cell on the runtimes list. // // @tz is required, even if the caller intends "UTC", so the bucket // cast is unambiguous — `bucket_hour` is UTC and the caller picks the // calendar boundary per request. func (q *Queries) ListRuntimeUsage(ctx context.Context, arg ListRuntimeUsageParams) ([]ListRuntimeUsageRow, error) { rows, err := q.db.Query(ctx, listRuntimeUsage, arg.RuntimeID, arg.Tz, arg.Since) if err != nil { return nil, err } defer rows.Close() items := []ListRuntimeUsageRow{} for rows.Next() { var i ListRuntimeUsageRow if err := rows.Scan( &i.Date, &i.Provider, &i.Model, &i.InputTokens, &i.OutputTokens, &i.CacheReadTokens, &i.CacheWriteTokens, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listRuntimeUsageByAgent = `-- name: ListRuntimeUsageByAgent :many SELECT atq.agent_id, tu.model, SUM(tu.input_tokens)::bigint AS input_tokens, SUM(tu.output_tokens)::bigint AS output_tokens, SUM(tu.cache_read_tokens)::bigint AS cache_read_tokens, SUM(tu.cache_write_tokens)::bigint AS 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 WHERE atq.runtime_id = $1 AND tu.created_at >= $2::timestamptz GROUP BY atq.agent_id, tu.model ORDER BY atq.agent_id, tu.model ` type ListRuntimeUsageByAgentParams struct { RuntimeID pgtype.UUID `json:"runtime_id"` Since pgtype.Timestamptz `json:"since"` } type ListRuntimeUsageByAgentRow struct { AgentID pgtype.UUID `json:"agent_id"` Model string `json:"model"` InputTokens int64 `json:"input_tokens"` OutputTokens int64 `json:"output_tokens"` CacheReadTokens int64 `json:"cache_read_tokens"` CacheWriteTokens int64 `json:"cache_write_tokens"` TaskCount int32 `json:"task_count"` } // Per-(agent, model) token aggregates for a runtime since a cutoff. Powers // the runtime-detail "Cost by agent" tab. task_usage only carries task_id, // so we join the queue to expose agent_id. The model dimension is kept on // purpose: cost is computed client-side from a per-model pricing table, so // collapsing models server-side would erase the information needed to do // that arithmetic. The client groups by agent_id and sums cost per agent. // // This view doesn't bucket by date, so it doesn't need @tz; only the // @since cutoff is provided in runtime-local terms (computed in Go). func (q *Queries) ListRuntimeUsageByAgent(ctx context.Context, arg ListRuntimeUsageByAgentParams) ([]ListRuntimeUsageByAgentRow, error) { rows, err := q.db.Query(ctx, listRuntimeUsageByAgent, arg.RuntimeID, arg.Since) if err != nil { return nil, err } defer rows.Close() items := []ListRuntimeUsageByAgentRow{} for rows.Next() { var i ListRuntimeUsageByAgentRow if err := rows.Scan( &i.AgentID, &i.Model, &i.InputTokens, &i.OutputTokens, &i.CacheReadTokens, &i.CacheWriteTokens, &i.TaskCount, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil }