84 lines
2.8 KiB
TypeScript
84 lines
2.8 KiB
TypeScript
/**
|
|
* PBL Runtime Chat API
|
|
*
|
|
* Handles @mention routing during PBL runtime.
|
|
* Students @question or @judge an agent, and this endpoint generates a response.
|
|
*/
|
|
|
|
import { NextRequest } from 'next/server';
|
|
import { callLLM } from '@/lib/ai/llm';
|
|
import type { PBLAgent, PBLIssue } from '@/lib/pbl/types';
|
|
import { createLogger } from '@/lib/logger';
|
|
import { apiError, apiSuccess } from '@/lib/server/api-response';
|
|
import { resolveModelFromRequest } from '@/lib/server/resolve-model';
|
|
const log = createLogger('PBL Chat');
|
|
|
|
interface PBLChatRequest {
|
|
message: string;
|
|
agent: PBLAgent;
|
|
currentIssue: PBLIssue | null;
|
|
recentMessages: { agent_name: string; message: string }[];
|
|
userRole: string;
|
|
agentType?: 'question' | 'judge';
|
|
}
|
|
|
|
export async function POST(req: NextRequest) {
|
|
let agentName: string | undefined;
|
|
let resolvedAgentType: string | undefined;
|
|
try {
|
|
const body = (await req.json()) as PBLChatRequest;
|
|
const { message, agent, currentIssue, recentMessages, userRole, agentType } = body;
|
|
agentName = agent?.name;
|
|
resolvedAgentType = agentType;
|
|
|
|
if (!message || !agent) {
|
|
return apiError('MISSING_REQUIRED_FIELD', 400, 'Message and agent are required');
|
|
}
|
|
|
|
// Get model config from request headers/body
|
|
const { model, thinkingConfig } = await resolveModelFromRequest(req, body, 'pbl-chat');
|
|
|
|
// Build context for the agent, differentiating question vs judge
|
|
let issueContext = '';
|
|
if (currentIssue) {
|
|
issueContext = `\n\n## Current Issue\nTitle: ${currentIssue.title}\nDescription: ${currentIssue.description}\nPerson in Charge: ${currentIssue.person_in_charge}`;
|
|
if (currentIssue.generated_questions) {
|
|
if (agentType === 'judge') {
|
|
issueContext += `\n\nQuestions to Evaluate Against:\n${currentIssue.generated_questions}`;
|
|
} else {
|
|
issueContext += `\n\nGenerated Questions:\n${currentIssue.generated_questions}`;
|
|
}
|
|
}
|
|
}
|
|
|
|
const recentContext =
|
|
recentMessages.length > 0
|
|
? `\n\n## Recent Conversation\n${recentMessages
|
|
.slice(-5)
|
|
.map((m) => `${m.agent_name}: ${m.message}`)
|
|
.join('\n')}`
|
|
: '';
|
|
|
|
const systemPrompt = `${agent.system_prompt}${issueContext}${recentContext}${userRole ? `\n\nThe student's role is: ${userRole}` : ''}`;
|
|
|
|
const result = await callLLM(
|
|
{
|
|
model,
|
|
system: systemPrompt,
|
|
prompt: message,
|
|
},
|
|
'pbl-chat',
|
|
undefined,
|
|
thinkingConfig,
|
|
);
|
|
|
|
return apiSuccess({ message: result.text, agentName: agent.name });
|
|
} catch (error) {
|
|
log.error(
|
|
`PBL chat failed [agent="${agentName ?? 'unknown'}", type=${resolvedAgentType ?? 'question'}]:`,
|
|
error,
|
|
);
|
|
return apiError('INTERNAL_ERROR', 500, error instanceof Error ? error.message : String(error));
|
|
}
|
|
}
|