Template
86 lines
2.8 KiB
TypeScript
86 lines
2.8 KiB
TypeScript
import {
|
|
streamText,
|
|
convertToModelMessages,
|
|
stepCountIs,
|
|
pruneMessages,
|
|
} from 'ai';
|
|
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
|
|
import { tools } from '@/chat.config';
|
|
|
|
const openrouter = createOpenRouter({
|
|
apiKey: process.env.OPENROUTER_API_KEY,
|
|
});
|
|
|
|
export async function POST(request: Request) {
|
|
try {
|
|
const { messages } = await request.json();
|
|
|
|
if (!process.env.OPENROUTER_API_KEY) {
|
|
return Response.json(
|
|
{ error: 'OPENROUTER_API_KEY is not configured' },
|
|
{ status: 503 }
|
|
);
|
|
}
|
|
|
|
const model = openrouter(
|
|
process.env.OPENROUTER_MODEL || 'openai/gpt-5.6-luna-pro'
|
|
);
|
|
|
|
const webSearchEnabled = Boolean(process.env.FIRECRAWL_API_KEY);
|
|
|
|
const instructions = webSearchEnabled
|
|
? `You are an expert ChatGPT Agent with real-time access to the internet.
|
|
|
|
Your capabilities:
|
|
- Search the web using Firecrawl to find up-to-date information
|
|
- Fetch and read full web pages to extract detailed content
|
|
- Synthesize information from multiple sources into clear, accurate answers
|
|
- Cite your sources inline so the user can verify information
|
|
|
|
Guidelines:
|
|
- Always search the web before answering questions that require current or factual information
|
|
- Use multiple searches when needed to get comprehensive answers
|
|
- Cross-reference sources for accuracy
|
|
- Structure your responses clearly with headings, bullet points, and citations where appropriate
|
|
- When fetching pages, extract only the relevant information
|
|
- Be transparent about the sources you used
|
|
- Today's date is ${new Date().toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}`
|
|
: `You are a helpful AI research assistant. Answer clearly and accurately. You do not have live web access, so be transparent when a question requires current information. Today's date is ${new Date().toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}.`;
|
|
|
|
const convertedMessages = await convertToModelMessages(messages);
|
|
|
|
const prunedMessages = pruneMessages({
|
|
messages: convertedMessages,
|
|
reasoning: 'all',
|
|
toolCalls: 'none',
|
|
});
|
|
|
|
const result = await streamText({
|
|
model,
|
|
instructions,
|
|
messages: prunedMessages,
|
|
tools: webSearchEnabled ? tools : {},
|
|
stopWhen: stepCountIs(20),
|
|
providerOptions: {
|
|
openrouter: {
|
|
reasoning: {
|
|
enabled: true,
|
|
effort: 'medium',
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
return result.toUIMessageStreamResponse({ sendReasoning: true });
|
|
} 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' },
|
|
}
|
|
);
|
|
}
|
|
}
|