import express from "express"; import path from "path"; import { fileURLToPath } from "url"; import dotenv from "dotenv"; import bodyParser from "body-parser"; dotenv.config(); const app = express(); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const PORT = process.env.APP_PORT || 7860; const ApiKey = process.env.OPENROUTER_API_KEY; const Model = process.env.OPENROUTER_MODEL; const ApiUrl = "https://openrouter.ai/api/v1"; app.use(bodyParser.json()); app.use(express.static(path.join(__dirname, "dist"))); app.post("/api/ask-ai", async (req, res) => { const { prompt, html, previousPrompt } = req.body; if (!prompt) { return res.status(400).send({ ok: false, message: "Missing prompt" }); } if (!ApiKey || !Model) { return res.status(500).send({ ok: false, message: "Missing API Key or Model in .env file", }); } res.setHeader("Content-Type", "text/plain"); res.setHeader("Cache-Control", "no-cache"); res.setHeader("Connection", "keep-alive"); const systemPrompt = `ONLY USE HTML, CSS AND JAVASCRIPT. No explanations, ONLY CODE. If you want to use ICON make sure to import the library first. Try to create the best UI possible using TailwindCSS. If not possible, use custom CSS (remember to import in the head). ALWAYS GIVE THE RESPONSE INTO A SINGLE HTML FILE`; try { const response = await fetch(`${ApiUrl}/chat/completions`, { method: "POST", headers: { Authorization: `Bearer ${ApiKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ model: Model, stream: true, messages: [ { role: "system", content: systemPrompt }, ...(previousPrompt ? [{ role: "user", content: previousPrompt }] : []), ...(html ? [{ role: "assistant", content: `The current code is: ${html}` }] : []), { role: "user", content: prompt }, ], }), }); if (!response.ok || !response.body) { return res.status(500).send({ ok: false, message: "Failed to fetch OpenRouter response", }); } const reader = response.body.getReader(); const decoder = new TextDecoder(); while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); const lines = chunk.split('\n').filter(line => line.trim()); for (const line of lines) { if (!line || !line.startsWith('data: ') || line.includes('[DONE]')) continue; try { const json = line.slice(6).trim(); if (!json.startsWith('{')) continue; const message = JSON.parse(json); const content = message?.choices?.[0]?.delta?.content; if (content) res.write(content); } catch (err) { console.error("Streaming error:", err.message); continue; } } } res.end(); } catch (error) { console.error("Request error:", error.message); res.status(500).send({ ok: false, message: error.message || "Unexpected error", }); } }); app.get("*", (_req, res) => { res.sendFile(path.join(__dirname, "dist", "index.html")); }); app.listen(PORT, () => { console.log(`✅ Server running on port ${PORT}`); });