← back to Norma
app/api/onboard/trigger/route.ts
80 lines
import { NextRequest, NextResponse } from 'next/server';
import { requireRole } from '@/lib/require-role';
// ─── POST /api/onboard/trigger ────────────────────────────────────────────────
// Body: { topic_id: string }
// Triggers the onboard agent at http://127.0.0.1:9808/api/skill/discover
const ONBOARD_AGENT_URL = 'http://127.0.0.1:9808/api/skill/discover';
const AGENT_TIMEOUT_MS = 30_000;
export async function POST(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
try {
const body = (await request.json()) as { topic_id?: string; topic?: string };
const { topic_id, topic } = body;
if (!topic_id && !topic) {
return NextResponse.json(
{ error: 'Provide either topic_id or topic in the request body.' },
{ status: 400 },
);
}
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), AGENT_TIMEOUT_MS);
let agentResponse: Response;
try {
agentResponse = await fetch(ONBOARD_AGENT_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ topic_id, topic }),
signal: controller.signal,
});
} finally {
clearTimeout(timeout);
}
if (!agentResponse.ok) {
const errorText = await agentResponse.text();
return NextResponse.json(
{
error: `Onboard agent returned HTTP ${agentResponse.status}`,
agent_response: errorText,
},
{ status: 502 },
);
}
const agentData = await agentResponse.json();
return NextResponse.json({
success: true,
topic_id: topic_id ?? null,
topic: topic ?? null,
agent_result: agentData,
});
} catch (err: unknown) {
const msg = (err as Error).message ?? 'Unknown error';
if (msg.includes('abort') || msg.includes('timeout')) {
return NextResponse.json(
{ error: 'Onboard agent timed out after 30s.' },
{ status: 504 },
);
}
if (msg.includes('ECONNREFUSED') || msg.includes('fetch failed')) {
return NextResponse.json(
{ error: 'Onboard agent is not reachable (port 9808).' },
{ status: 503 },
);
}
console.error('[api/onboard/trigger] Error:', msg);
return NextResponse.json({ error: msg }, { status: 500 });
}
}