import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' function bridgeProxyPlugin() { return { name: 'bridge-proxy', configureServer(server) { // Proxy a request to the OpenClaw bridge const proxyRequest = (targetPath) => async (req, res) => { if (req.method === 'OPTIONS') { res.writeHead(204, { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', }) res.end() return } try { const { default: http } = await import('http') const chunks = [] for await (const chunk of req) chunks.push(chunk) const body = Buffer.concat(chunks) await new Promise((resolve, reject) => { const proxyReq = http.request( `http://localhost:8081${targetPath}`, { method: req.method, headers: { 'Content-Type': req.headers['content-type'] || 'application/json', 'Content-Length': body.length, }, timeout: 120000, }, (proxyRes) => { res.writeHead(proxyRes.statusCode, { 'Content-Type': proxyRes.headers['content-type'] || 'application/json', 'Access-Control-Allow-Origin': '*', }) proxyRes.pipe(res) proxyRes.on('end', resolve) proxyRes.on('error', resolve) } ) proxyReq.on('error', reject) proxyReq.on('timeout', () => { proxyReq.destroy() reject(new Error('timeout')) }) proxyReq.write(body) proxyReq.end() }) } catch { if (!res.headersSent) { res.writeHead(502, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ error: 'Bridge unreachable' })) } } } server.middlewares.use('/api/agent/message', proxyRequest('/api/agent/message')) server.middlewares.use('/api/tts', proxyRequest('/api/tts')) server.middlewares.use('/api/stt', proxyRequest('/api/stt')) // Health check — direct to bridge server.middlewares.use('/api/health', async (req, res) => { try { const { default: http } = await import('http') const start = Date.now() await new Promise((resolve, reject) => { const reqObj = http.get('http://localhost:8081/', { timeout: 5000 }, (resp) => { resp.resume() resolve() }) reqObj.on('error', reject) reqObj.on('timeout', () => { reqObj.destroy(); reject(new Error('timeout')) }) }) res.writeHead(200, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ status: 'online', responseTime: Date.now() - start })) } catch { res.writeHead(200, { 'Content-Type': 'application/json' }) res.end(JSON.stringify({ status: 'offline', responseTime: null })) } }) }, } } export default defineConfig({ plugins: [ bridgeProxyPlugin(), tailwindcss(), react(), ], server: { host: '0.0.0.0', port: 5174, }, })