← back to PoppyPetitions
app/api/compute/route.ts
83 lines
import { NextRequest, NextResponse } from 'next/server';
import { verifyAuth } from '@/lib/auth';
import { query } from '@/lib/db';
export async function GET(request: NextRequest) {
const user = verifyAuth(request);
if (!user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
try {
// Overall totals
const totalsResult = await query(`
SELECT
COALESCE(SUM(total_tokens), 0)::bigint AS total_tokens,
COALESCE(SUM(cost_usd), 0)::numeric(10,6) AS total_cost,
COUNT(*)::int AS total_actions,
COUNT(DISTINCT agent_id)::int AS unique_agents
FROM poppy.compute_usage
`);
// Cost by action type
const byActionResult = await query(`
SELECT action_type,
SUM(total_tokens)::bigint AS total_tokens,
SUM(cost_usd)::numeric(10,6) AS total_cost,
COUNT(*)::int AS action_count,
AVG(total_tokens)::int AS avg_tokens
FROM poppy.compute_usage
GROUP BY action_type
ORDER BY total_cost DESC
`);
// Top agents by compute spend
const topAgentsResult = await query(`
SELECT a.id, a.name, a.codename,
a.compute_tokens_used::bigint AS tokens_used,
a.compute_cost_usd::numeric(10,6) AS cost_usd,
a.petition_count,
a.vote_count
FROM poppy.agents a
WHERE a.compute_tokens_used > 0
ORDER BY a.compute_cost_usd DESC
LIMIT 20
`);
// Usage over time (daily)
const timeSeriesResult = await query(`
SELECT
DATE(created_at AT TIME ZONE 'America/Los_Angeles') AS day,
SUM(total_tokens)::bigint AS tokens,
SUM(cost_usd)::numeric(10,6) AS cost,
COUNT(*)::int AS actions
FROM poppy.compute_usage
GROUP BY DATE(created_at AT TIME ZONE 'America/Los_Angeles')
ORDER BY day DESC
LIMIT 30
`);
// Model usage breakdown
const byModelResult = await query(`
SELECT model,
SUM(total_tokens)::bigint AS total_tokens,
SUM(cost_usd)::numeric(10,6) AS total_cost,
COUNT(*)::int AS call_count
FROM poppy.compute_usage
GROUP BY model
ORDER BY total_cost DESC
`);
return NextResponse.json({
totals: totalsResult.rows[0],
byAction: byActionResult.rows,
topAgents: topAgentsResult.rows,
timeSeries: timeSeriesResult.rows,
byModel: byModelResult.rows,
});
} catch (err) {
console.error('[compute GET]', (err as Error).message);
return NextResponse.json({ error: 'Internal error' }, { status: 500 });
}
}