File size: 3,395 Bytes
ea6c2a8 d5cae2f 0c97c9d ea6c2a8 0c97c9d ea6c2a8 0c97c9d 0e737c6 0c97c9d 0e737c6 94b66c3 ea6c2a8 ae120cb 0c97c9d ae120cb 0c97c9d ae120cb 0c97c9d ae120cb 0c97c9d ea6c2a8 0c97c9d 33d4b9e 0c97c9d ffa81b7 0c97c9d c2c7576 0c97c9d 33d4b9e 0c97c9d d5cae2f 0c97c9d 33d4b9e 0c97c9d d5cae2f 0c97c9d d5cae2f 0c97c9d 33d4b9e d5cae2f 0c97c9d d81515f ffa81b7 ea6c2a8 ae120cb |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
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 <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script> 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}`);
});
|