Files
nextjs-chat-gpt/app/api/chat/route.ts
T

79 lines
2.1 KiB
TypeScript

import {
streamText,
convertToModelMessages,
stepCountIs,
pruneMessages,
} from 'ai';
import { getChatModel } from '@/services/chat/model';
import { getChatInstructions } from '@/services/chat/instructions';
import { chatTools } from '@/services/chat/tools';
import { isOpenRouterModelId } from '@/lib/openrouter';
export const maxDuration = 300;
export async function POST(request: Request) {
try {
const { messages, modelId } = await request.json();
if (modelId !== undefined && !isOpenRouterModelId(modelId)) {
return Response.json({ error: 'Select a supported model' }, { status: 400 });
}
if (!process.env.OPENROUTER_API_KEY) {
return Response.json(
{ error: 'OPENROUTER_API_KEY is not configured' },
{ status: 503 }
);
}
const model = getChatModel(modelId);
const webSearchEnabled = Boolean(process.env.FIRECRAWL_API_KEY);
const instructions = getChatInstructions(webSearchEnabled);
const convertedMessages = await convertToModelMessages(messages);
const prunedMessages = pruneMessages({
messages: convertedMessages,
reasoning: 'all',
toolCalls: 'none',
});
const result = streamText({
model,
instructions,
messages: prunedMessages,
abortSignal: request.signal,
tools: webSearchEnabled ? chatTools : {},
stopWhen: stepCountIs(20),
onError: ({ error }) => {
if (!request.signal.aborted) console.error('Chat stream error:', error);
},
providerOptions: {
openrouter: {
reasoning: {
enabled: true,
effort: 'medium',
},
},
},
});
return result.toUIMessageStreamResponse({
sendReasoning: true,
headers: { 'Cache-Control': 'no-cache, no-transform' },
onError: () => 'The response was interrupted. Please try again.',
});
} catch (error) {
console.error('Chat API error:', error);
return new Response(
JSON.stringify({ error: 'Failed to process chat request' }),
{
status: 500,
headers: { 'Content-Type': 'application/json' },
}
);
}
}