avneesh123 commited on
Commit
4bcf7cb
·
verified ·
1 Parent(s): 1d3accf

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +367 -187
server.js CHANGED
@@ -4,241 +4,421 @@ import fs from "fs-extra";
4
  import path from "path";
5
  import { spawn, exec } from "child_process";
6
  import httpProxy from "http-proxy";
 
7
 
 
 
 
 
 
8
  const app = express();
9
-
10
- // ================= 1. SECURITY & IFRAME HEADERS =================
11
- // Ye block Iframe connection refused aur CSP errors ko fix karta hai
12
- app.use((req, res, next) => {
13
- const allowedOrigin = "https://avneesh123-autodev-mark2.hf.space";
14
-
15
- res.removeHeader("X-Frame-Options");
16
- // Content-Security-Policy: Sirf tera frontend is engine ko embed kar payega
17
- res.setHeader(
18
- "Content-Security-Policy",
19
- `frame-ancestors 'self' ${allowedOrigin} https://*.hf.space`
20
- );
21
- res.setHeader("X-Frame-Options", "ALLOWALL");
22
- next();
23
- });
24
-
25
- const PORT = 7860;
26
- const VITE_PORT = 5173;
27
  const PROJECT_DIR = path.join(process.cwd(), "project");
 
 
28
  const MASTER_KEY = "AVNEESH_GOD_MODE_777";
 
 
29
 
 
30
  let viteProcess = null;
31
  let isBooting = false;
32
  let buildRetryCount = 0;
33
- const MAX_RETRIES = 3;
 
 
34
 
35
- // ================= 2. PERSISTENCE & LOCKS =================
36
- const FOUNDATION_LOCK = path.join(process.cwd(), ".foundation_lock");
37
  const DEPS_LOCK = path.join(process.cwd(), ".deps_lock");
 
38
 
39
- /* ================= 3. LOGGING SYSTEM ================= */
 
 
 
 
40
  let logs = [];
41
  let clients = new Set();
42
 
43
  function pushLog(message, type = "info") {
44
- const entry = {
45
- id: Date.now() + Math.random(),
46
- time: new Date().toLocaleTimeString(),
47
- message,
48
- type
49
- };
50
- logs.push(entry);
51
- if (logs.length > 500) logs.shift();
52
- const payload = `data: ${JSON.stringify(entry)}\n\n`;
53
- clients.forEach(c => {
54
- try { c.write(payload); } catch { clients.delete(c); }
55
- });
56
- console.log(`[${type.toUpperCase()}] ${message}`);
 
 
 
 
 
 
 
 
57
  }
58
 
59
- /* ================= 4. MIDDLEWARE & CORS ================= */
60
- const ALLOWED_ORIGINS = [
61
- "https://avneesh123-autodev-mark2.hf.space",
62
- "https://avneesh123-autodev-mark2-engine.hf.space",
63
- "http://localhost:5173",
64
- ];
65
-
66
- app.use(cors({
67
- origin: (origin, callback) => {
68
- if (!origin || ALLOWED_ORIGINS.includes(origin) || origin.endsWith(".hf.space")) {
69
- return callback(null, true);
70
- }
71
- callback(new Error("CORS_DENIED"));
72
- },
73
- credentials: true
74
- }));
75
-
76
- app.use(express.json({ limit: "50mb" }));
77
 
78
- if (!fs.existsSync(PROJECT_DIR)) {
79
- fs.mkdirSync(PROJECT_DIR, { recursive: true });
80
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
- /* ================= 5. VITE PROCESS MANAGER ================= */
83
- function killVite() {
84
- return new Promise((resolve) => {
85
- if (viteProcess) {
86
- pushLog("[SYSTEM] Killing existing Vite process", "system");
87
- viteProcess.kill("SIGKILL");
88
- viteProcess = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  }
90
- // Port cleanup logic
91
- const killCmd = process.platform === "win32"
92
- ? `for /f "tokens=5" %a in ('netstat -aon ^| findstr :${VITE_PORT}') do taskkill /F /PID %a`
93
- : `fuser -k ${VITE_PORT}/tcp`;
94
-
95
- exec(killCmd, () => {
96
- setTimeout(resolve, 1500);
97
- });
98
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  }
100
 
101
- function startVite(forceRestart = false) {
102
- // RACE CONDITION LOCK: Agar boot ho raha hai toh naya start mat karo
103
- if (isBooting && !forceRestart) return;
104
- if (viteProcess && !forceRestart) return;
105
-
106
- isBooting = true;
107
- if (forceRestart) {
108
- killVite().then(() => bootVite());
109
- } else {
110
- bootVite();
111
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  }
113
 
114
- function bootVite() {
115
- pushLog("[SYSTEM] Starting Vite dev server...", "system");
116
- const nodeModules = path.join(PROJECT_DIR, "node_modules");
117
-
118
- const boot = () => {
119
- // Check if package.json exists to avoid "Missing script: dev"
120
- const pkgPath = path.join(PROJECT_DIR, "package.json");
121
- if (!fs.existsSync(pkgPath)) {
122
- pushLog("[ERROR] package.json missing in project folder!", "error");
123
- isBooting = false;
124
- return;
125
  }
126
 
127
- viteProcess = spawn("pnpm", ["run", "dev", "--", "--host", "0.0.0.0", "--port", String(VITE_PORT)], {
128
- cwd: PROJECT_DIR,
129
- shell: true,
130
- env: { ...process.env, FORCE_COLOR: "0" }
131
- });
 
 
132
 
133
- viteProcess.stdout.on("data", d => {
134
- const msg = d.toString().trim();
135
- if (msg.includes("Local:") || msg.includes("ready in")) {
136
- isBooting = false;
137
- buildRetryCount = 0;
138
- pushLog("[SYSTEM] Vite is ready!", "success");
139
- }
140
- pushLog("[VITE] " + msg, "info");
141
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
- viteProcess.stderr.on("data", d => pushLog("[VITE ERROR] " + d.toString().trim(), "error"));
 
 
 
 
144
 
145
- viteProcess.on("close", (code) => {
146
- viteProcess = null;
147
- isBooting = false;
148
- if (code !== 0 && buildRetryCount < MAX_RETRIES) {
149
- buildRetryCount++;
150
- setTimeout(() => startVite(true), 3000);
151
- }
152
- });
153
- };
154
-
155
- if (fs.existsSync(DEPS_LOCK) && fs.existsSync(nodeModules)) {
156
- boot();
157
- } else {
158
- pushLog("[INSTALL] Installing dependencies...", "system");
159
- const install = spawn("pnpm", ["install"], { cwd: PROJECT_DIR, shell: true });
160
- install.on("close", code => {
161
- if (code === 0) {
162
- fs.writeFileSync(DEPS_LOCK, new Date().toISOString());
163
- boot();
164
- } else {
165
- isBooting = false;
166
- pushLog("[ERROR] pnpm install failed", "error");
167
- }
168
- });
169
- }
170
- }
171
 
172
- /* ================= 6. API ROUTES ================= */
173
- function verify(req, res, next) {
174
- const token = req.headers["x-api-key"] || req.body?.token;
175
- if (token !== MASTER_KEY) return res.status(403).json({ error: "UNAUTHORIZED" });
176
- next();
177
- }
 
 
 
178
 
 
179
  app.get("/api/logs", (req, res) => {
180
- res.setHeader("Content-Type", "text/event-stream");
181
- res.setHeader("Cache-Control", "no-cache");
182
- res.setHeader("Connection", "keep-alive");
183
- clients.add(res);
184
- req.on("close", () => clients.delete(res));
 
 
 
 
 
 
 
 
 
 
 
 
185
  });
186
 
187
- app.post("/api/update", verify, async (req, res) => {
188
- const { files, restart = false } = req.body;
189
- try {
190
- for (const [p, c] of Object.entries(files)) {
191
- const fp = path.join(PROJECT_DIR, p);
192
- await fs.ensureDir(path.dirname(fp));
193
- await fs.writeFile(fp, c, "utf-8");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  }
195
- if (restart) startVite(true); else startVite();
196
- res.json({ success: true });
197
- } catch (e) {
198
- res.status(500).json({ error: e.message });
199
- }
200
  });
201
 
202
- app.post("/api/reset", verify, async (req, res) => {
203
- await killVite();
204
- await fs.remove(PROJECT_DIR);
205
- fs.mkdirSync(PROJECT_DIR, { recursive: true });
206
- if (fs.existsSync(DEPS_LOCK)) fs.removeSync(DEPS_LOCK);
207
- pushLog("[SYSTEM] Project Reset Complete", "warning");
208
- res.json({ success: true });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  });
210
 
211
- app.get("/health", (req, res) => res.json({ status: "ok", vite: !!viteProcess }));
 
 
 
 
212
 
213
- /* ================= 7. PROXY MANAGER ================= */
214
  const proxy = httpProxy.createProxyServer({
215
- target: `http://127.0.0.1:${VITE_PORT}`,
216
- changeOrigin: true,
217
- ws: true
218
  });
219
 
 
220
  proxy.on("error", (err, req, res) => {
221
- if (res.writeHead) {
222
- res.writeHead(503, { "Content-Type": "text/html" });
223
- res.end("<html><body>Vite is booting... Refresh in 5s</body></html>");
224
- }
 
 
 
 
 
 
 
 
 
 
225
  });
226
 
 
227
  app.use((req, res) => {
228
- if (req.path.startsWith("/api") || req.path === "/health") return;
229
-
230
- // Security check for preview access
231
- const isRoot = req.path === "/" || req.path === "";
232
- if (isRoot) {
233
- const secret = req.headers["x-autodev-preview"] || req.query["__autodev"];
234
- if (secret !== "AUTODEV_PREVIEW_777") {
235
- return res.status(403).send("ACCESS DENIED");
236
  }
237
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
 
239
- if (!viteProcess && !isBooting) startVite();
240
- proxy.web(req, res);
 
241
  });
242
 
243
- const server = app.listen(PORT, () => pushLog(`Engine running on port ${PORT}`, "success"));
244
- server.on("upgrade", (req, socket, head) => proxy.ws(req, socket, head));
 
 
 
 
 
 
 
 
4
  import path from "path";
5
  import { spawn, exec } from "child_process";
6
  import httpProxy from "http-proxy";
7
+ import os from "os";
8
 
9
+ /**
10
+ * ============================================================
11
+ * CONFIGURATION & CONSTANTS
12
+ * ============================================================
13
+ */
14
  const app = express();
15
+ const PORT = 7860; // Hugging Face default port
16
+ const VITE_PORT = 5173; // Internal Vite dev server port
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  const PROJECT_DIR = path.join(process.cwd(), "project");
18
+
19
+ // Security Credentials
20
  const MASTER_KEY = "AVNEESH_GOD_MODE_777";
21
+ const PREVIEW_SECRET = "AUTODEV_PREVIEW_777";
22
+ const FRONTEND_URL = "https://avneesh123-autodev-mark2.hf.space";
23
 
24
+ // State Management
25
  let viteProcess = null;
26
  let isBooting = false;
27
  let buildRetryCount = 0;
28
+ const MAX_RETRIES = 5;
29
+ let lastActivityTime = Date.now();
30
+ const IDLE_TIMEOUT = 15 * 60 * 1000; // 15 Minutes
31
 
32
+ // Persistence Locks
 
33
  const DEPS_LOCK = path.join(process.cwd(), ".deps_lock");
34
+ const FOUNDATION_LOCK = path.join(process.cwd(), ".foundation_lock");
35
 
36
+ /**
37
+ * ============================================================
38
+ * LOGGING SYSTEM (SSE)
39
+ * ============================================================
40
+ */
41
  let logs = [];
42
  let clients = new Set();
43
 
44
  function pushLog(message, type = "info") {
45
+ const entry = {
46
+ id: Date.now() + Math.random(),
47
+ time: new Date().toLocaleTimeString(),
48
+ timestamp: Date.now(),
49
+ message,
50
+ type // info | error | success | warning | system
51
+ };
52
+
53
+ logs.push(entry);
54
+ if (logs.length > 1000) logs.shift(); // Max 1000 logs in memory
55
+
56
+ const payload = `data: ${JSON.stringify(entry)}\n\n`;
57
+ clients.forEach(client => {
58
+ try {
59
+ client.write(payload);
60
+ } catch (err) {
61
+ clients.delete(client);
62
+ }
63
+ });
64
+
65
+ console.log(`[${type.toUpperCase()}] ${message}`);
66
  }
67
 
68
+ /**
69
+ * ============================================================
70
+ * SECURITY MIDDLEWARE (THE LOCKDOWN)
71
+ * ============================================================
72
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
+ // 1. Iframe & CSP Lockdown
75
+ app.use((req, res, next) => {
76
+ // Remove default headers that might block embedding
77
+ res.removeHeader("X-Frame-Options");
78
+ res.removeHeader("Content-Security-Policy");
79
+
80
+ // Allow only YOUR frontend to embed this engine
81
+ res.setHeader(
82
+ "Content-Security-Policy",
83
+ `frame-ancestors 'self' ${FRONTEND_URL}`
84
+ );
85
+ res.setHeader("X-Frame-Options", "ALLOW-FROM " + FRONTEND_URL);
86
+ res.setHeader("Access-Control-Allow-Credentials", "true");
87
+
88
+ next();
89
+ });
90
 
91
+ // 2. Direct Access & Secret Key Enforcement
92
+ const privateAccessCheck = (req, res, next) => {
93
+ const isApiRequest = req.path.startsWith("/api") || req.path === "/health";
94
+
95
+ if (!isApiRequest) {
96
+ const querySecret = req.query["__autodev"];
97
+ const headerSecret = req.headers["x-autodev-preview"];
98
+
99
+ if (querySecret !== PREVIEW_SECRET && headerSecret !== PREVIEW_SECRET) {
100
+ pushLog(`[SECURITY] Blocked direct access attempt from ${req.ip}`, "warning");
101
+ return res.status(403).send(`
102
+ <!DOCTYPE html>
103
+ <html>
104
+ <head>
105
+ <title>Access Denied</title>
106
+ <style>
107
+ body { background: #09090b; color: #ef4444; font-family: monospace; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; flex-direction: column; }
108
+ .box { border: 1px solid #ef444440; padding: 40px; border-radius: 20px; text-align: center; background: #ef444405; }
109
+ h1 { letter-spacing: -2px; font-size: 2rem; margin: 0; }
110
+ p { color: #71717a; margin-top: 10px; font-size: 0.9rem; }
111
+ </style>
112
+ </head>
113
+ <body>
114
+ <div class="box">
115
+ <h1>ACCESS DENIED</h1>
116
+ <p>AutoDev Mark-II Engine is in private lockdown mode.</p>
117
+ </div>
118
+ </body>
119
+ </html>
120
+ `);
121
+ }
122
  }
123
+ next();
124
+ };
125
+
126
+ app.use(privateAccessCheck);
127
+
128
+ /**
129
+ * ============================================================
130
+ * RATE LIMITER
131
+ * ============================================================
132
+ */
133
+ const rateLimitMap = new Map();
134
+ function checkRateLimit(req, res, next) {
135
+ const ip = req.ip || req.headers['x-forwarded-for'];
136
+ const now = Date.now();
137
+
138
+ if (!rateLimitMap.has(ip)) {
139
+ rateLimitMap.set(ip, []);
140
+ }
141
+
142
+ const requests = rateLimitMap.get(ip).filter(timestamp => now - timestamp < 60000);
143
+ if (requests.length > 50) { // Max 50 requests per minute
144
+ pushLog(`[RATE LIMIT] Throttling IP: ${ip}`, "warning");
145
+ return res.status(429).json({ error: "TOO_MANY_REQUESTS" });
146
+ }
147
+
148
+ requests.push(now);
149
+ rateLimitMap.set(ip, requests);
150
+ next();
151
  }
152
 
153
+ /**
154
+ * ============================================================
155
+ * CORE ENGINE LOGIC (VITE MANAGEMENT)
156
+ * ============================================================
157
+ */
158
+
159
+ async function killVite() {
160
+ return new Promise((resolve) => {
161
+ if (viteProcess) {
162
+ pushLog("[SYSTEM] Terminating active Vite instance...", "system");
163
+ viteProcess.kill("SIGKILL");
164
+ viteProcess = null;
165
+ }
166
+
167
+ // Cross-platform port clearing
168
+ const command = process.platform === "win32"
169
+ ? `for /f "tokens=5" %a in ('netstat -aon ^| findstr :${VITE_PORT}') do taskkill /F /PID %a`
170
+ : `fuser -k ${VITE_PORT}/tcp`;
171
+
172
+ exec(command, (err) => {
173
+ // Wait 1.5s for OS to release the socket
174
+ setTimeout(resolve, 1500);
175
+ });
176
+ });
177
  }
178
 
179
+ function startVite(force = false) {
180
+ if (isBooting && !force) return;
181
+ if (viteProcess && !force) {
182
+ pushLog("[SYSTEM] Vite already active.", "info");
183
+ return;
 
 
 
 
 
 
184
  }
185
 
186
+ isBooting = true;
187
+ if (force) {
188
+ killVite().then(() => bootProcess());
189
+ } else {
190
+ bootProcess();
191
+ }
192
+ }
193
 
194
+ function bootProcess() {
195
+ pushLog("[SYSTEM] Initializing Vite environment...", "system");
196
+ const nodeModules = path.join(PROJECT_DIR, "node_modules");
197
+
198
+ const launch = () => {
199
+ const pkgJson = path.join(PROJECT_DIR, "package.json");
200
+ if (!fs.existsSync(pkgJson)) {
201
+ pushLog("[ERROR] package.json not found. Boot aborted.", "error");
202
+ isBooting = false;
203
+ return;
204
+ }
205
+
206
+ viteProcess = spawn("pnpm", ["run", "dev", "--", "--host", "0.0.0.0", "--port", String(VITE_PORT)], {
207
+ cwd: PROJECT_DIR,
208
+ shell: true,
209
+ env: { ...process.env, FORCE_COLOR: "0" }
210
+ });
211
+
212
+ viteProcess.stdout.on("data", (data) => {
213
+ const msg = data.toString().trim();
214
+ if (msg.includes("Local:") || msg.includes("ready in")) {
215
+ isBooting = false;
216
+ buildRetryCount = 0;
217
+ pushLog("[SYSTEM] Vite is ready and listening.", "success");
218
+ }
219
+ pushLog("[VITE] " + msg, "info");
220
+ });
221
+
222
+ viteProcess.stderr.on("data", (data) => {
223
+ pushLog("[VITE ERROR] " + data.toString().trim(), "error");
224
+ });
225
+
226
+ viteProcess.on("close", (code) => {
227
+ pushLog(`[SYSTEM] Vite process exited with code ${code}`, "warning");
228
+ viteProcess = null;
229
+ isBooting = false;
230
+
231
+ if (code !== 0 && buildRetryCount < MAX_RETRIES) {
232
+ buildRetryCount++;
233
+ pushLog(`[RECOVERY] Attempting auto-restart (${buildRetryCount}/${MAX_RETRIES})`, "system");
234
+ setTimeout(() => startVite(true), 3000);
235
+ }
236
+ });
237
+ };
238
+
239
+ // Check for Dependencies
240
+ if (fs.existsSync(DEPS_LOCK) && fs.existsSync(nodeModules)) {
241
+ launch();
242
+ } else {
243
+ pushLog("[INSTALL] Running dependency installation...", "system");
244
+ const install = spawn("pnpm", ["install"], { cwd: PROJECT_DIR, shell: true });
245
+
246
+ install.stdout.on("data", (d) => pushLog("[INSTALL] " + d.toString().trim(), "info"));
247
+
248
+ install.on("close", (code) => {
249
+ if (code === 0) {
250
+ fs.writeFileSync(DEPS_LOCK, new Date().toISOString());
251
+ pushLog("[INSTALL] Dependencies successfully locked.", "success");
252
+ launch();
253
+ } else {
254
+ isBooting = false;
255
+ pushLog("[ERROR] Dependency installation failed.", "error");
256
+ }
257
+ });
258
+ }
259
+ }
260
 
261
+ /**
262
+ * ============================================================
263
+ * API ENDPOINTS
264
+ * ============================================================
265
+ */
266
 
267
+ app.use(cors({ origin: [FRONTEND_URL], credentials: true }));
268
+ app.use(express.json({ limit: "50mb" }));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
+ // Token Verification Helper
271
+ const auth = (req, res, next) => {
272
+ const token = req.headers["x-api-key"] || req.body?.token;
273
+ if (token !== MASTER_KEY) {
274
+ pushLog(`[SECURITY] Unauthorized API request from ${req.ip}`, "error");
275
+ return res.status(403).json({ error: "UNAUTHORIZED_ACCESS" });
276
+ }
277
+ next();
278
+ };
279
 
280
+ // 1. Logs Stream (SSE)
281
  app.get("/api/logs", (req, res) => {
282
+ res.setHeader("Content-Type", "text/event-stream");
283
+ res.setHeader("Cache-Control", "no-cache");
284
+ res.setHeader("Connection", "keep-alive");
285
+
286
+ clients.add(res);
287
+ req.on("close", () => clients.delete(res));
288
+ });
289
+
290
+ // 2. Health & Status
291
+ app.get("/health", (req, res) => {
292
+ res.json({
293
+ status: "ok",
294
+ viteActive: !!viteProcess,
295
+ booting: isBooting,
296
+ uptime: process.uptime(),
297
+ memory: process.memoryUsage().rss
298
+ });
299
  });
300
 
301
+ // 3. File Updates
302
+ app.post("/api/update", auth, checkRateLimit, async (req, res) => {
303
+ const { files, restart = false } = req.body;
304
+ lastActivityTime = Date.now();
305
+
306
+ try {
307
+ const fileEntries = Object.entries(files);
308
+ for (const [filePath, content] of fileEntries) {
309
+ const fullPath = path.join(PROJECT_DIR, filePath);
310
+ await fs.ensureDir(path.dirname(fullPath));
311
+ await fs.writeFile(fullPath, content, "utf-8");
312
+ }
313
+
314
+ pushLog(`[FILES] Synchronized ${fileEntries.length} files.`, "success");
315
+
316
+ if (restart) startVite(true);
317
+ else if (!viteProcess) startVite();
318
+
319
+ res.json({ success: true });
320
+ } catch (err) {
321
+ pushLog(`[ERROR] File sync failed: ${err.message}`, "error");
322
+ res.status(500).json({ error: err.message });
323
  }
 
 
 
 
 
324
  });
325
 
326
+ // 4. Project Reset
327
+ app.post("/api/reset", auth, async (req, res) => {
328
+ pushLog("[SYSTEM] Initiating full project wipe...", "warning");
329
+ await killVite();
330
+ await fs.remove(PROJECT_DIR);
331
+ fs.mkdirSync(PROJECT_DIR, { recursive: true });
332
+
333
+ if (fs.existsSync(DEPS_LOCK)) fs.unlinkSync(DEPS_LOCK);
334
+ if (fs.existsSync(FOUNDATION_LOCK)) fs.unlinkSync(FOUNDATION_LOCK);
335
+
336
+ res.json({ success: true, message: "Project directory cleared." });
337
+ });
338
+
339
+ // 5. Command Execution
340
+ app.post("/api/execute", auth, checkRateLimit, (req, res) => {
341
+ const { command } = req.body;
342
+ pushLog(`[SHELL] Executing: ${command}`, "system");
343
+
344
+ exec(command, { cwd: PROJECT_DIR, timeout: 30000 }, (err, stdout, stderr) => {
345
+ res.json({
346
+ success: !err,
347
+ output: stdout || stderr || (err ? err.message : ""),
348
+ code: err ? err.code : 0
349
+ });
350
+ });
351
  });
352
 
353
+ /**
354
+ * ============================================================
355
+ * PROXY & SERVER INITIALIZATION
356
+ * ============================================================
357
+ */
358
 
 
359
  const proxy = httpProxy.createProxyServer({
360
+ target: `http://127.0.0.1:${VITE_PORT}`,
361
+ changeOrigin: true,
362
+ ws: true
363
  });
364
 
365
+ // Proxy Error Handler
366
  proxy.on("error", (err, req, res) => {
367
+ if (res.writeHead) {
368
+ res.writeHead(503, { "Content-Type": "text/html" });
369
+ res.end(`
370
+ <html>
371
+ <body style="background:#09090b;color:#71717a;font-family:monospace;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;">
372
+ <div style="text-align:center;">
373
+ <p style="color:#eab308;font-weight:bold;">ENGINE WARMING UP</p>
374
+ <p>Vite is still booting. Auto-refreshing in 3s...</p>
375
+ <script>setTimeout(() => location.reload(), 3000);</script>
376
+ </div>
377
+ </body>
378
+ </html>
379
+ `);
380
+ }
381
  });
382
 
383
+ // Root Handler for Preview
384
  app.use((req, res) => {
385
+ if (req.path.startsWith("/api") || req.path === "/health") return;
386
+
387
+ lastActivityTime = Date.now();
388
+ if (!viteProcess && !isBooting) {
389
+ pushLog("[IDLE] Activity detected. Waking up engine...", "system");
390
+ startVite();
 
 
391
  }
392
+
393
+ proxy.web(req, res);
394
+ });
395
+
396
+ // Idle Auto-Shutdown to save Hugging Face Resources
397
+ setInterval(() => {
398
+ const now = Date.now();
399
+ if (viteProcess && (now - lastActivityTime > IDLE_TIMEOUT)) {
400
+ pushLog("[IDLE] Hibernating engine due to inactivity.", "warning");
401
+ killVite();
402
+ }
403
+ }, 60000);
404
+
405
+ // Startup
406
+ const server = app.listen(PORT, () => {
407
+ pushLog(`AutoDev Engine Kernel Online (Port: ${PORT})`, "success");
408
+ pushLog(`Project Workspace: ${PROJECT_DIR}`, "system");
409
+ });
410
 
411
+ // WebSocket Support for HMR
412
+ server.on("upgrade", (req, socket, head) => {
413
+ proxy.ws(req, socket, head);
414
  });
415
 
416
+ /**
417
+ * ============================================================
418
+ * GRACEFUL SHUTDOWN
419
+ * ============================================================
420
+ */
421
+ process.on("SIGTERM", async () => {
422
+ await killVite();
423
+ process.exit(0);
424
+ });