Spaces:
Paused
Paused
| 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<string, string> = { | |
| ".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<string>({ | |
| 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}`); | |