import { serve } from "bun"; import { readFile } from "fs/promises"; import { join } from "path"; import { GameState } from "./gameState"; import { AIService, MODEL } from "./aiService"; const PORT = parseInt(process.env.PORT || "7860"); const ROOT_DIR = import.meta.dir; const gameState = new GameState(); // Single shared game state const mimeTypes: Record = { ".html": "text/html", ".js": "application/javascript", ".css": "text/css", ".map": "application/octet-stream", ".ico": "image/x-icon", ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".gif": "image/gif", ".svg": "image/svg+xml", ".webp": "image/webp", ".json": "application/json", }; serve({ port: PORT, async fetch(req) { const url = new URL(req.url); const pathname = url.pathname; // Simple config endpoint to expose runtime info to the UI if (pathname === "/config") { return new Response(JSON.stringify({ model: MODEL }), { headers: { "Content-Type": "application/json" }, }); } // Handle SSE connection if (pathname === "/game-stream") { const stream = new ReadableStream({ start(controller) { gameState.setController(controller); gameState.sendUpdate(); // Initial state will be sent by gameState // Start AI agent loop const runAI = async () => { const state = gameState.getState(); const action = await AIService.getNextAction( state.map, state.history ); await gameState.handleAction(action); // Schedule next AI action setTimeout(runAI, 1000); }; runAI(); }, cancel() { // No need to cleanup since we're using a shared state }, }); return new Response(stream, { headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive", }, }); } // Serve static files if (pathname === "/" || pathname === "/index.html") { const data = await readFile(join(ROOT_DIR, "index.html")); return new Response(data, { headers: { "Content-Type": "text/html" }, }); } const filePath = join(ROOT_DIR, pathname); try { const data = await readFile(filePath); const ext = filePath.slice(filePath.lastIndexOf(".")); const mimeType = mimeTypes[ext] || "application/octet-stream"; return new Response(data, { status: 200, headers: { "Content-Type": mimeType, }, }); } catch (error) { return new Response("Not Found", { status: 404 }); } }, }); console.log(`Server is running at http://localhost:${PORT}`);