import { NextRequest, NextResponse } from "next/server"; import { eq, desc, sql, and } from "drizzle-orm"; import { db } from "@/lib/db"; import { claws, tasks } from "@/lib/db/schema"; import { getActiveClawIds } from "@/lib/redis"; export async function GET(req: NextRequest) { try { const { searchParams } = new URL(req.url); const limitParam = parseInt(searchParams.get("limit") ?? "50", 10); const limit = Math.min(Math.max(1, limitParam), 200); const region = searchParams.get("region"); const sort = searchParams.get("sort") ?? "activity"; const conditions = []; if (region) { conditions.push(eq(claws.region, region)); } const whereClause = conditions.length > 0 ? and(...conditions) : undefined; const clawRows = await db .select() .from(claws) .where(whereClause) .orderBy(sort === "newest" ? desc(claws.createdAt) : desc(claws.lastHeartbeat)) .limit(limit); const totalResult = await db .select({ count: sql`count(*)` }) .from(claws) .where(whereClause); const total = totalResult[0]?.count ?? 0; const activeClawIds = await getActiveClawIds(); const activeSet = new Set(activeClawIds); const clawList = await Promise.all( clawRows.map(async (claw) => { const latestTaskRows = await db .select({ summary: tasks.summary, timestamp: tasks.timestamp, durationMs: tasks.durationMs, }) .from(tasks) .where(eq(tasks.clawId, claw.id)) .orderBy(desc(tasks.timestamp)) .limit(1); const lastTask = latestTaskRows[0] ?? null; return { id: claw.id, name: claw.name, model: claw.model, platform: claw.platform, city: claw.city, country: claw.country, isOnline: activeSet.has(claw.id), createdAt: claw.createdAt, lastTask, }; }) ); return NextResponse.json({ claws: clawList, total }); } catch (error) { console.error("Claws error:", error); return NextResponse.json( { error: "Internal server error" }, { status: 500 } ); } }