11import db from '@codebuff/common/db'
22import * as schema from '@codebuff/common/db/schema'
3- import { sql } from 'drizzle-orm'
3+ import { sql , eq , and , gte } from 'drizzle-orm'
44import { NextResponse } from 'next/server'
55
66import { logger } from '@/util/logger'
77
88export async function GET ( ) {
99 try {
10- // Get all published agents with their publisher info
10+ const oneWeekAgo = new Date ( Date . now ( ) - 7 * 24 * 60 * 60 * 1000 )
11+
12+ // Get all published agents with their publisher info and real usage metrics
1113 const agents = await db
1214 . select ( {
1315 id : schema . agentConfig . id ,
@@ -25,31 +27,128 @@ export async function GET() {
2527 schema . publisher ,
2628 sql `${ schema . agentConfig . publisher_id } = ${ schema . publisher . id } `
2729 )
28- . orderBy ( sql `${ schema . agentConfig . created_at } DESC` ) // Sort by date descending
29- . limit ( 100 ) // Limit for performance
30+ . orderBy ( sql `${ schema . agentConfig . created_at } DESC` )
31+
32+ // Get all-time usage metrics for all agents
33+ const usageMetrics = await db
34+ . select ( {
35+ agent_id : schema . agentRun . agent_id ,
36+ publisher_id : schema . agentRun . publisher_id ,
37+ agent_name : schema . agentRun . agent_name ,
38+ agent_version : schema . agentRun . agent_version ,
39+ total_invocations : sql < number > `COUNT(*)` ,
40+ total_dollars : sql < number > `COALESCE(SUM(${ schema . agentRun . total_credits } ) / 100.0, 0)` ,
41+ avg_cost_per_run : sql < number > `COALESCE(AVG(${ schema . agentRun . total_credits } ) / 100.0, 0)` ,
42+ unique_users : sql < number > `COUNT(DISTINCT ${ schema . agentRun . user_id } )` ,
43+ last_used : sql < Date > `MAX(${ schema . agentRun . created_at } )` ,
44+ } )
45+ . from ( schema . agentRun )
46+ . where (
47+ and (
48+ eq ( schema . agentRun . status , 'completed' ) ,
49+ sql `${ schema . agentRun . agent_id } != 'test-agent'`
50+ )
51+ )
52+ . groupBy (
53+ schema . agentRun . agent_id ,
54+ schema . agentRun . publisher_id ,
55+ schema . agentRun . agent_name ,
56+ schema . agentRun . agent_version
57+ )
58+
59+ // Get weekly usage metrics separately
60+ const weeklyMetrics = await db
61+ . select ( {
62+ agent_id : schema . agentRun . agent_id ,
63+ publisher_id : schema . agentRun . publisher_id ,
64+ agent_name : schema . agentRun . agent_name ,
65+ weekly_dollars : sql < number > `COALESCE(SUM(${ schema . agentRun . total_credits } ) / 100.0, 0)` ,
66+ } )
67+ . from ( schema . agentRun )
68+ . where (
69+ and (
70+ eq ( schema . agentRun . status , 'completed' ) ,
71+ gte ( schema . agentRun . created_at , oneWeekAgo ) ,
72+ sql `${ schema . agentRun . agent_id } != 'test-agent'`
73+ )
74+ )
75+ . groupBy (
76+ schema . agentRun . agent_id ,
77+ schema . agentRun . publisher_id ,
78+ schema . agentRun . agent_name
79+ )
80+
81+ // Create weekly metrics map
82+ const weeklyMap = new Map ( )
83+ weeklyMetrics . forEach ( ( metric ) => {
84+ const keys = [
85+ metric . agent_id ,
86+ metric . publisher_id && metric . agent_name
87+ ? `${ metric . publisher_id } /${ metric . agent_name } `
88+ : null ,
89+ ] . filter ( Boolean )
3090
31- // Transform the data to include parsed agent data and mock usage metrics
91+ keys . forEach ( ( key ) => {
92+ weeklyMap . set ( key , Number ( metric . weekly_dollars ) )
93+ } )
94+ } )
95+
96+ // Create a map of usage metrics by agent identifier
97+ const metricsMap = new Map ( )
98+ usageMetrics . forEach ( ( metric ) => {
99+ // Try to match by full agent_id first, then by publisher/name combination
100+ const keys = [
101+ metric . agent_id ,
102+ metric . publisher_id && metric . agent_name
103+ ? `${ metric . publisher_id } /${ metric . agent_name } `
104+ : null ,
105+ ] . filter ( Boolean )
106+
107+ keys . forEach ( ( key ) => {
108+ const existingMetric = metricsMap . get ( key )
109+ if ( ! existingMetric || existingMetric . last_used < metric . last_used ) {
110+ metricsMap . set ( key , {
111+ weekly_dollars : weeklyMap . get ( key ) || 0 ,
112+ total_dollars : Number ( metric . total_dollars ) ,
113+ total_invocations : Number ( metric . total_invocations ) ,
114+ avg_cost_per_run : Number ( metric . avg_cost_per_run ) ,
115+ unique_users : Number ( metric . unique_users ) ,
116+ last_used : metric . last_used ,
117+ } )
118+ }
119+ } )
120+ } )
121+
122+ // Transform the data to include parsed agent data and real usage metrics
32123 const transformedAgents = agents . map ( ( agent ) => {
33- const agentData = typeof agent . data === 'string' ? JSON . parse ( agent . data ) : agent . data
34-
35- // Mock usage metrics (in a real app, these would come from analytics/usage tables)
36- const mockUsageCount = Math . floor ( Math . random ( ) * 50000 ) + 1000
37- const mockTotalSpent = Math . floor ( Math . random ( ) * 5000 ) + 100 // $100-$5100
38- const mockAvgCostPerInvocation = mockTotalSpent / mockUsageCount
39- const mockResponseTime = Math . floor ( Math . random ( ) * 3000 ) + 500 // 500-3500ms
40-
124+ const agentData =
125+ typeof agent . data === 'string' ? JSON . parse ( agent . data ) : agent . data
126+ const agentName = agentData . name || agent . id
127+
128+ const agentKey = `${ agent . publisher . id } /${ agentName } `
129+ const metrics = metricsMap . get ( agentKey ) ||
130+ metricsMap . get ( agent . id ) || {
131+ weekly_dollars : 0 ,
132+ total_dollars : 0 ,
133+ total_invocations : 0 ,
134+ avg_cost_per_run : 0 ,
135+ unique_users : 0 ,
136+ last_used : null ,
137+ }
138+
41139 return {
42140 id : agent . id ,
43- name : agentData . name || agent . id ,
141+ name : agentName ,
44142 description : agentData . description ,
45143 publisher : agent . publisher ,
46144 version : agent . version ,
47145 created_at : agent . created_at ,
48- usage_count : mockUsageCount ,
49- total_spent : mockTotalSpent ,
50- avg_cost_per_invocation : mockAvgCostPerInvocation ,
51- avg_response_time : mockResponseTime ,
52-
146+ usage_count : metrics . total_invocations ,
147+ weekly_spent : metrics . weekly_dollars ,
148+ total_spent : metrics . total_dollars ,
149+ avg_cost_per_invocation : metrics . avg_cost_per_run ,
150+ unique_users : metrics . unique_users ,
151+ last_used : metrics . last_used ,
53152 tags : agentData . tags || [ ] ,
54153 }
55154 } )
@@ -58,13 +157,16 @@ export async function GET() {
58157 const latestAgents = new Map ( )
59158 transformedAgents . forEach ( ( agent ) => {
60159 const key = `${ agent . publisher . id } /${ agent . name } `
61- if ( ! latestAgents . has ( key ) ) { // Since it's sorted, the first one is the latest
160+ if ( ! latestAgents . has ( key ) ) {
62161 latestAgents . set ( key , agent )
63162 }
64163 } )
65164
66165 const result = Array . from ( latestAgents . values ( ) )
67166
167+ // Sort by weekly usage (most prominent metric)
168+ result . sort ( ( a , b ) => ( b . weekly_spent || 0 ) - ( a . weekly_spent || 0 ) )
169+
68170 return NextResponse . json ( result )
69171 } catch ( error ) {
70172 logger . error ( { error } , 'Error fetching agents' )
@@ -73,4 +175,4 @@ export async function GET() {
73175 { status : 500 }
74176 )
75177 }
76- }
178+ }
0 commit comments