import { randomUUID } from "node:crypto"; import { NextResponse } from "next/server"; export const dynamic = "force-dynamic"; type RunTaskBody = { prompt?: string; }; type ExecutionStep = { stepId: string; title: string; description: string; kind: "decision" | "tool_call" | "validation"; order: number; }; type ExecutionPlan = { goal: string; successDefinition: string; steps: ExecutionStep[]; }; function buildPlan(prompt: string): ExecutionPlan { return { goal: prompt, successDefinition: "Generate a clear, concise response to the prompt.", steps: [ { stepId: "step-1-prep", title: "Prepare context", description: "Read the prompt and set up the execution context.", kind: "decision", order: 1, }, { stepId: "step-2-call", title: "Call LLM provider", description: "Use the configured LLM provider to generate a response.", kind: "tool_call", order: 2, }, { stepId: "step-3-done", title: "Return result", description: "Format and return the final response.", kind: "validation", order: 3, }, ], }; } function formatTrace(plan: ExecutionPlan): string[] { const trace = [ `Goal: ${plan.goal}`, `Success definition: ${plan.successDefinition}`, ]; for (const step of plan.steps) { trace.push(`${step.order}. ${step.title} [${step.kind}] — ${step.description}`); } return trace; } async function callLlm(prompt: string, systemPrompt: string): Promise { const apiKey = process.env.OPENAI_API_KEY || ""; const model = process.env.HF_DEMO_MODEL || "gpt-4o-mini"; const baseUrl = process.env.OPENAI_BASE_URL || "https://api.openai.com/v1"; if (!apiKey) { return "LLM API key not configured (OPENAI_API_KEY)."; } try { const response = await fetch(`${baseUrl}/chat/completions`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}`, }, body: JSON.stringify({ model, messages: [ { role: "system", content: systemPrompt }, { role: "user", content: prompt }, ], temperature: 0.2, max_tokens: 1024, }), }); const data = (await response.json()) as Record; if (!response.ok) { const errorMsg = (data as Record).error; return `LLM error: ${typeof errorMsg === "object" ? JSON.stringify(errorMsg) : errorMsg}`; } const choices = data.choices as unknown[]; if (!Array.isArray(choices) || !choices[0]) return "No response from LLM."; const choice = choices[0] as Record; const message = choice.message as Record | undefined; if (!message) return "No content in LLM response."; const content = message.content; return typeof content === "string" ? content.trim() : ""; } catch (error) { const msg = error instanceof Error ? error.message : String(error); return `Failed to call LLM: ${msg}`; } } export async function POST(request: Request) { let body: RunTaskBody; try { body = (await request.json()) as RunTaskBody; } catch { body = {}; } const prompt = typeof body.prompt === "string" ? body.prompt.trim() : ""; if (!prompt) { return NextResponse.json( { error: "Prompt is required." }, { status: 400 } ); } const plan = buildPlan(prompt); const taskId = randomUUID(); const conversationId = randomUUID(); const providerLabel = process.env.LLM_PROVIDER || "openai"; // Generate the final result using the LLM const finalResult = await callLlm( prompt, "You are a helpful assistant. Provide a clear, concise response." ); return NextResponse.json({ providerUsed: providerLabel, goal: plan.goal, successDefinition: plan.successDefinition, executionTrace: formatTrace(plan), finalResult: finalResult || `Processed prompt: ${prompt.slice(0, 100)}...`, planNotes: "Hackathon demo using minimal LLM provider abstraction.", taskId, conversationId, }); }