import http from 'node:http'; import { readFileSync } from 'node:fs'; import { resolve, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); const port = Number(process.env.UI_PORT || 8856); const upstream = process.env.UI_UPSTREAM || 'http://127.0.0.1:8855'; const files = new Map([ ['/', ['AI团队协作台-统一面板-R7.html', 'text/html']], ['/index.html', ['AI团队协作台-统一面板-R7.html', 'text/html']], ['/ui/workspace.css', ['web/workspace/workspace.css', 'text/css']], ['/ui/lucide.min.js', ['web/workspace/lucide.min.js', 'text/javascript']], ]); export function createUiServer({ target = upstream } = {}) { return http.createServer((req, res) => { const url = new URL(req.url, 'http://localhost'); const file = files.get(url.pathname); if (file && req.method === 'GET') { try { const content = readFileSync(resolve(root, file[0])); res.writeHead(200, { 'content-type': file[1] + '; charset=utf-8', 'cache-control': 'no-store' }); res.end(content); } catch { res.writeHead(500); res.end('UI asset unavailable'); } return; } if (!url.pathname.startsWith('/api/') && !['/submit', '/xcr', '/xcrb'].includes(url.pathname)) { res.writeHead(404); res.end('Not found'); return; } // Preserve status and download headers from the existing gateway. const proxy = http.request(new URL(url.pathname + url.search, target), { method: req.method, headers: { ...req.headers, host: new URL(target).host }, }, (response) => { res.writeHead(response.statusCode, response.headers); response.pipe(res); }); proxy.setTimeout(120000, () => proxy.destroy(new Error('Upstream timeout'))); proxy.on('error', () => { if (res.headersSent) { res.destroy(); return; } res.writeHead(502, { 'content-type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ error: '服务暂时无法连接,请确认原协作台和任务引擎已启动。' })); }); req.pipe(proxy); }); } if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { const server = createUiServer(); server.on('error', (error) => { console.error(error.message); process.exitCode = 1; }); server.listen(port, '127.0.0.1', () => console.log('Task workspace: http://127.0.0.1:' + port + '/')); }