You've already forked agentic-coding-workflow
202 lines
6.4 KiB
Go
202 lines
6.4 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.31.1
|
|
// source: dashboard.sql
|
|
|
|
package acpsqlc
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
const sessionRollup = `-- name: SessionRollup :one
|
|
SELECT
|
|
COUNT(*)::bigint AS total,
|
|
COUNT(*) FILTER (WHERE status = 'exited')::bigint AS succeeded,
|
|
COUNT(*) FILTER (WHERE status = 'crashed')::bigint AS crashed,
|
|
COUNT(*) FILTER (WHERE status IN ('starting','running'))::bigint AS active,
|
|
COALESCE(SUM(cost_usd), 0)::numeric AS total_cost_usd,
|
|
COALESCE(SUM(tokens_total), 0)::bigint AS total_tokens,
|
|
COALESCE(
|
|
AVG(EXTRACT(EPOCH FROM (ended_at - started_at)))
|
|
FILTER (WHERE ended_at IS NOT NULL),
|
|
0)::float8 AS avg_duration_seconds
|
|
FROM acp_sessions
|
|
WHERE ($1::uuid IS NULL OR user_id = $1)
|
|
AND ($2::uuid IS NULL OR project_id = $2)
|
|
AND ($3::uuid IS NULL OR requirement_id = $3)
|
|
AND started_at >= $4
|
|
AND started_at < $5
|
|
`
|
|
|
|
type SessionRollupParams struct {
|
|
Column1 pgtype.UUID `json:"column_1"`
|
|
Column2 pgtype.UUID `json:"column_2"`
|
|
Column3 pgtype.UUID `json:"column_3"`
|
|
StartedAt pgtype.Timestamptz `json:"started_at"`
|
|
StartedAt_2 pgtype.Timestamptz `json:"started_at_2"`
|
|
}
|
|
|
|
type SessionRollupRow struct {
|
|
Total int64 `json:"total"`
|
|
Succeeded int64 `json:"succeeded"`
|
|
Crashed int64 `json:"crashed"`
|
|
Active int64 `json:"active"`
|
|
TotalCostUsd pgtype.Numeric `json:"total_cost_usd"`
|
|
TotalTokens int64 `json:"total_tokens"`
|
|
AvgDurationSeconds float64 `json:"avg_duration_seconds"`
|
|
}
|
|
|
|
// owner/admin scope + 可选 project/requirement + 时间窗内的会话汇总。
|
|
// success = status='exited';avg_duration_seconds 仅统计已结束(ended_at 非空)会话。
|
|
func (q *Queries) SessionRollup(ctx context.Context, arg SessionRollupParams) (SessionRollupRow, error) {
|
|
row := q.db.QueryRow(ctx, sessionRollup,
|
|
arg.Column1,
|
|
arg.Column2,
|
|
arg.Column3,
|
|
arg.StartedAt,
|
|
arg.StartedAt_2,
|
|
)
|
|
var i SessionRollupRow
|
|
err := row.Scan(
|
|
&i.Total,
|
|
&i.Succeeded,
|
|
&i.Crashed,
|
|
&i.Active,
|
|
&i.TotalCostUsd,
|
|
&i.TotalTokens,
|
|
&i.AvgDurationSeconds,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const sessionTimeline = `-- name: SessionTimeline :many
|
|
|
|
SELECT direction,
|
|
rpc_kind,
|
|
COALESCE(method, '') AS method,
|
|
COUNT(*)::bigint AS event_count,
|
|
MIN(created_at)::timestamptz AS first_at,
|
|
MAX(created_at)::timestamptz AS last_at
|
|
FROM acp_events
|
|
WHERE session_id = $1
|
|
GROUP BY direction, rpc_kind, COALESCE(method, '')
|
|
ORDER BY first_at ASC
|
|
`
|
|
|
|
type SessionTimelineRow struct {
|
|
Direction string `json:"direction"`
|
|
RpcKind string `json:"rpc_kind"`
|
|
Method string `json:"method"`
|
|
EventCount int64 `json:"event_count"`
|
|
FirstAt pgtype.Timestamptz `json:"first_at"`
|
|
LastAt pgtype.Timestamptz `json:"last_at"`
|
|
}
|
|
|
|
// dashboard.sql: run-history dashboard 读模型(只读聚合)。
|
|
// - SessionTimeline: 单会话的 RPC 事件按 (direction, rpc_kind, method) 分桶,
|
|
// 给出条数 + 首/末时间戳,用于会话时间线概览。
|
|
// - SessionRollup: 在 owner/admin scope + 可选 project/requirement 过滤下,
|
|
// 统计会话总数、成功率(exited 视为成功)、总成本、平均时长。
|
|
// - SessionsByDay: 按天的 总数 / 成功 / 失败 / 成本 时间序列。
|
|
//
|
|
// scope 约定(与 ListSessionsByUser/ListAllSessions 一致):
|
|
//
|
|
// $1 user_id 为 NULL 时不按用户过滤(admin 全量),非 NULL 时仅该用户。
|
|
//
|
|
// 单会话事件时间线:按 method/kind 分桶聚合(条数 + 首末时间)。
|
|
func (q *Queries) SessionTimeline(ctx context.Context, sessionID pgtype.UUID) ([]SessionTimelineRow, error) {
|
|
rows, err := q.db.Query(ctx, sessionTimeline, sessionID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []SessionTimelineRow
|
|
for rows.Next() {
|
|
var i SessionTimelineRow
|
|
if err := rows.Scan(
|
|
&i.Direction,
|
|
&i.RpcKind,
|
|
&i.Method,
|
|
&i.EventCount,
|
|
&i.FirstAt,
|
|
&i.LastAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const sessionsByDay = `-- name: SessionsByDay :many
|
|
SELECT
|
|
date_trunc('day', started_at)::timestamptz AS day,
|
|
COUNT(*)::bigint AS total,
|
|
COUNT(*) FILTER (WHERE status = 'exited')::bigint AS succeeded,
|
|
COUNT(*) FILTER (WHERE status = 'crashed')::bigint AS crashed,
|
|
COALESCE(SUM(cost_usd), 0)::numeric AS total_cost_usd
|
|
FROM acp_sessions
|
|
WHERE ($1::uuid IS NULL OR user_id = $1)
|
|
AND ($2::uuid IS NULL OR project_id = $2)
|
|
AND ($3::uuid IS NULL OR requirement_id = $3)
|
|
AND started_at >= $4
|
|
AND started_at < $5
|
|
GROUP BY day
|
|
ORDER BY day ASC
|
|
`
|
|
|
|
type SessionsByDayParams struct {
|
|
Column1 pgtype.UUID `json:"column_1"`
|
|
Column2 pgtype.UUID `json:"column_2"`
|
|
Column3 pgtype.UUID `json:"column_3"`
|
|
StartedAt pgtype.Timestamptz `json:"started_at"`
|
|
StartedAt_2 pgtype.Timestamptz `json:"started_at_2"`
|
|
}
|
|
|
|
type SessionsByDayRow struct {
|
|
Day pgtype.Timestamptz `json:"day"`
|
|
Total int64 `json:"total"`
|
|
Succeeded int64 `json:"succeeded"`
|
|
Crashed int64 `json:"crashed"`
|
|
TotalCostUsd pgtype.Numeric `json:"total_cost_usd"`
|
|
}
|
|
|
|
// 按天的会话时间序列(总数 / 成功 / 失败 / 成本),同 SessionRollup 的 scope。
|
|
func (q *Queries) SessionsByDay(ctx context.Context, arg SessionsByDayParams) ([]SessionsByDayRow, error) {
|
|
rows, err := q.db.Query(ctx, sessionsByDay,
|
|
arg.Column1,
|
|
arg.Column2,
|
|
arg.Column3,
|
|
arg.StartedAt,
|
|
arg.StartedAt_2,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []SessionsByDayRow
|
|
for rows.Next() {
|
|
var i SessionsByDayRow
|
|
if err := rows.Scan(
|
|
&i.Day,
|
|
&i.Total,
|
|
&i.Succeeded,
|
|
&i.Crashed,
|
|
&i.TotalCostUsd,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|