File size: 3,656 Bytes
b6ecafa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { NextRequest, NextResponse } from 'next/server'
import { requireRole } from '@/lib/auth'
import { readLimiter } from '@/lib/rate-limit'
import { logger } from '@/lib/logger'
import {
  analyzeTokenEfficiency,
  analyzeToolPatterns,
  getFleetBenchmarks,
  generateRecommendations,
} from '@/lib/agent-optimizer'

export async function GET(request: NextRequest) {
  const auth = requireRole(request, 'operator')
  if ('error' in auth) return NextResponse.json({ error: auth.error }, { status: auth.status })

  const rateCheck = readLimiter(request)
  if (rateCheck) return rateCheck

  try {
    const { searchParams } = new URL(request.url)
    const agent = searchParams.get('agent')
    const hours = parseInt(searchParams.get('hours') || '24', 10)
    const workspaceId = auth.user.workspace_id ?? 1

    if (!agent) {
      return NextResponse.json({ error: 'Missing required parameter: agent' }, { status: 400 })
    }

    const efficiency = analyzeTokenEfficiency(agent, hours, workspaceId)
    const toolPatterns = analyzeToolPatterns(agent, hours, workspaceId)
    const fleet = getFleetBenchmarks(workspaceId)
    const recommendations = generateRecommendations(agent, workspaceId)

    // Calculate fleet percentile for tokens per session
    const fleetTokens = fleet
      .map(f => f.tokensPerTask)
      .filter(t => t > 0)
      .sort((a, b) => a - b)
    const agentTokensPerTask = efficiency.sessionsCount > 0 ? efficiency.avgTokensPerSession : 0
    const percentile = fleetTokens.length > 0
      ? Math.round((fleetTokens.filter(t => t >= agentTokensPerTask).length / fleetTokens.length) * 100)
      : 50

    // Fleet average cost
    const fleetAvgCost = fleet.length > 0
      ? fleet.reduce((sum, f) => sum + f.costPerTask, 0) / fleet.length
      : 0

    // Tool analysis
    const mostUsed = toolPatterns.topTools.slice(0, 5)
    const leastEffective = toolPatterns.topTools
      .filter(t => t.successRate < 80)
      .sort((a, b) => a.successRate - b.successRate)
      .slice(0, 5)

    // Performance from fleet benchmarks
    const agentBenchmark = fleet.find(f => f.agentName === agent)

    return NextResponse.json({
      agent,
      analyzedAt: new Date().toISOString(),
      efficiency: {
        tokensPerTask: agentTokensPerTask,
        fleetAverage: fleetTokens.length > 0
          ? Math.round(fleetTokens.reduce((a, b) => a + b, 0) / fleetTokens.length)
          : 0,
        percentile,
        trend: efficiency.totalTokens,
        costPerTask: efficiency.avgCostPerSession,
      },
      toolPatterns: {
        mostUsed: mostUsed.map(t => ({
          name: t.toolName,
          count: t.count,
          successRate: t.successRate,
        })),
        leastEffective: leastEffective.map(t => ({
          name: t.toolName,
          count: t.count,
          successRate: t.successRate,
        })),
        unusedCapabilities: [],
      },
      performance: {
        taskCompletionRate: agentBenchmark?.tasksCompleted ?? 0,
        avgTaskDuration: toolPatterns.avgDurationMs,
        errorRate: toolPatterns.failureRate,
        fleetRanking: fleet.findIndex(f => f.agentName === agent) + 1 || fleet.length + 1,
      },
      recommendations: recommendations.map(r => ({
        category: r.category,
        priority: r.severity,
        title: r.category.charAt(0).toUpperCase() + r.category.slice(1) + ' issue',
        description: r.message,
        expectedImpact: r.metric ?? null,
      })),
    })
  } catch (error) {
    logger.error({ err: error }, 'GET /api/agents/optimize error')
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
  }
}