route.ts 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. import { streamText } from "ai";
  2. import { gateway } from "@ai-sdk/gateway";
  3. import { headers } from "next/headers";
  4. import { generateGameAIPrompt } from "@/lib/ai-game-prompt";
  5. import { minuteRateLimit, dailyRateLimit } from "@/lib/rate-limit";
  6. export async function POST(req: Request) {
  7. const headersList = await headers();
  8. const ip = headersList.get("x-forwarded-for")?.split(",")[0] ?? "anonymous";
  9. const [minuteResult, dailyResult] = await Promise.all([
  10. minuteRateLimit.limit(ip),
  11. dailyRateLimit.limit(ip),
  12. ]);
  13. if (!minuteResult.success || !dailyResult.success) {
  14. const isMinuteLimit = !minuteResult.success;
  15. return new Response(
  16. JSON.stringify({
  17. error: "Rate limit exceeded",
  18. message: isMinuteLimit
  19. ? "Too many requests. Please wait a moment before trying again."
  20. : "Daily limit reached. Please try again tomorrow.",
  21. }),
  22. {
  23. status: 429,
  24. headers: { "Content-Type": "application/json" },
  25. },
  26. );
  27. }
  28. const { prompt, objects, previousPrompts } = await req.json();
  29. if (!prompt) {
  30. return Response.json({ error: "Prompt is required" }, { status: 400 });
  31. }
  32. const sceneObjects = Array.isArray(objects) ? objects : [];
  33. const result = streamText({
  34. model: gateway(
  35. process.env.AI_GATEWAY_MODEL || "anthropic/claude-sonnet-4-6",
  36. ),
  37. prompt: generateGameAIPrompt(prompt, sceneObjects, previousPrompts || []),
  38. });
  39. return result.toTextStreamResponse();
  40. }