Files
agent-bounty-protocol/apps/web/src/app/api/cron/a2a-swarm/route.ts
OG T 745ff300b5
Some checks failed
Deploy to 110 WOOO Server / deploy (push) Failing after 7s
feat: harden A2A funnel and paid proposal intake
2026-06-11 11:28:08 +08:00

121 lines
4.1 KiB
TypeScript

import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { cronUnauthorizedResponse, isCronRequestAuthorized } from "@/lib/cron-auth";
export const dynamic = 'force-dynamic';
export async function POST(request: Request) {
if (!isCronRequestAuthorized(request)) {
return cronUnauthorizedResponse("A2A Swarm");
}
console.log("[A2A Swarm] Starting task decomposition scan...");
try {
// 1. Find all OPEN high-value EPIC tasks that haven't been decomposed yet
const epicTasks = await prisma.task.findMany({
where: {
status: "OPEN",
difficulty: "EPIC",
}
});
if (epicTasks.length === 0) {
console.log('[A2A Swarm] No EPIC tasks found to decompose.');
return NextResponse.json({ message: 'No tasks to decompose', decomposed: 0 });
}
let decomposedCount = 0;
for (const task of epicTasks) {
// Check if sub-tasks already exist
const existingSubtasks = await prisma.task.count({
where: { parent_task_id: task.id }
});
if (existingSubtasks > 0) {
console.log(`[A2A Swarm] Task ${task.id} already decomposed into ${existingSubtasks} subtasks.`);
continue;
}
console.log(`[A2A Swarm] Decomposing EPIC task ${task.id}: ${task.title}`);
// We divide the reward. E.g., 40% Frontend, 40% Backend, 20% QA
const totalReward = task.reward_amount;
const r1 = Math.floor(totalReward * 0.4);
const r2 = Math.floor(totalReward * 0.4);
const r3 = totalReward - r1 - r2;
// 2. Create sub-tasks
await prisma.$transaction(async (tx) => {
// Subtask 1: Frontend
await tx.task.create({
data: {
title: `[Frontend] ${task.title}`,
description: `Frontend implementation for ${task.title}. Refer to parent task.`,
status: "OPEN",
difficulty: "COMPONENT",
scope_clarity_score: task.scope_clarity_score,
reward_amount: r1,
reward_currency: task.reward_currency,
acceptance_criteria: task.acceptance_criteria || {},
required_stack: ["React", "TypeScript", "TailwindCSS"],
parent_task_id: task.id
}
});
// Subtask 2: Backend
await tx.task.create({
data: {
title: `[Backend] ${task.title}`,
description: `Backend implementation for ${task.title}. Refer to parent task.`,
status: "OPEN",
difficulty: "COMPONENT",
scope_clarity_score: task.scope_clarity_score,
reward_amount: r2,
reward_currency: task.reward_currency,
acceptance_criteria: task.acceptance_criteria || {},
required_stack: ["Node.js", "Express", "PostgreSQL"],
parent_task_id: task.id
}
});
// Subtask 3: QA
await tx.task.create({
data: {
title: `[QA/Audit] ${task.title}`,
description: `Quality Assurance and Auditing for ${task.title}.`,
status: "OPEN",
difficulty: "COMPONENT",
scope_clarity_score: Math.max(1.0, task.scope_clarity_score + 0.1),
reward_amount: r3,
reward_currency: task.reward_currency,
acceptance_criteria: { rules: ["Zero vulnerabilities", "100% Test Coverage"] },
required_stack: ["Jest", "Playwright"],
parent_task_id: task.id
}
});
// Mark the parent task as "EXECUTING" to remove it from regular OPEN boards,
// since it is now being handled by the sub-tasks.
await tx.task.update({
where: { id: task.id },
data: { status: "EXECUTING" }
});
});
console.log(`[A2A Swarm] Successfully decomposed Task ${task.id} into 3 subtasks.`);
decomposedCount++;
}
return NextResponse.json({
message: "Swarm decomposition completed",
decomposed: decomposedCount
});
} catch (error: unknown) {
console.error("[A2A Swarm] Error during decomposition:", error);
return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
}
}