|
|
@@ -7,6 +7,7 @@ import path from "path";
|
|
|
import { fileURLToPath } from "url";
|
|
|
import { v4 as uuidv4 } from "uuid";
|
|
|
import multer from "multer";
|
|
|
+import { GoogleGenerativeAI } from "@google/generative-ai";
|
|
|
|
|
|
// Load environment variables
|
|
|
dotenv.config();
|
|
|
@@ -319,6 +320,51 @@ app.post(
|
|
|
},
|
|
|
);
|
|
|
|
|
|
+// AI Generation Route
|
|
|
+app.post("/api/ai/generate", requireAuth, async (req, res) => {
|
|
|
+ try {
|
|
|
+ const { context, prompt } = req.body;
|
|
|
+ const apiKey = process.env.GEMINI_API_KEY;
|
|
|
+
|
|
|
+ if (!apiKey) {
|
|
|
+ return res
|
|
|
+ .status(500)
|
|
|
+ .json({ error: "AI API key is not configured." });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!prompt) {
|
|
|
+ return res.status(400).json({ error: "A prompt is required." });
|
|
|
+ }
|
|
|
+
|
|
|
+ res.setHeader("Content-Type", "text/event-stream");
|
|
|
+ res.setHeader("Cache-Control", "no-cache");
|
|
|
+ res.setHeader("Connection", "keep-alive");
|
|
|
+
|
|
|
+ const genAI = new GoogleGenerativeAI(apiKey);
|
|
|
+ const model = genAI.getGenerativeModel({
|
|
|
+ model: "gemini-3-flash-preview",
|
|
|
+ });
|
|
|
+
|
|
|
+ const fullPrompt = `${context}\n\n${prompt}`;
|
|
|
+ const result = await model.generateContentStream(fullPrompt);
|
|
|
+
|
|
|
+ for await (const chunk of result.stream) {
|
|
|
+ const chunkText = chunk.text();
|
|
|
+ res.write(`data: ${JSON.stringify({ chunk: chunkText })}\n\n`);
|
|
|
+ }
|
|
|
+
|
|
|
+ res.end();
|
|
|
+ } catch (error) {
|
|
|
+ console.error("AI generation error:", error);
|
|
|
+ // We can't send a 500 status here as the headers are already sent.
|
|
|
+ // We can write an error event to the stream.
|
|
|
+ res.write(
|
|
|
+ `data: ${JSON.stringify({ error: "Failed to generate AI content." })}\n\n`,
|
|
|
+ );
|
|
|
+ res.end();
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
// MEDIA ROUTES
|
|
|
|
|
|
// POST /api/upload - Upload file
|