Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

148 lines
4.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

require('dotenv').config();
const express = require('express');
const cors = require('cors');
const path = require('path');
const http = require('http');
const authRoutes = require('./routes/auth');
const chatRoutes = require('./routes/chat');
const buildRoutes = require('./routes/build');
const notifyRoutes = require('./routes/notify');
const apikeyRoutes = require('./routes/apikey');
const previewRoutes = require('./routes/preview');
const proxyRoutes = require('./routes/proxy');
const app = express();
app.use(cors({
origin: [
'http://localhost:3002',
'http://127.0.0.1:3002',
'http://43.134.16.246',
'https://guanghulab.com',
'http://guanghulab.com',
'https://qinfendebingshuo.github.io'
],
credentials: true
}));
app.use(express.json({ limit: '2mb' }));
// ── 静态文件persona-studio 前端 ──
app.use('/persona-studio', express.static(path.join(__dirname, '..', 'frontend')));
// ── API 路由(统一前缀 /api/ps──
app.use('/api/ps/auth', authRoutes);
app.use('/api/ps/chat', chatRoutes);
app.use('/api/ps/build', buildRoutes);
app.use('/api/ps/notify', notifyRoutes);
app.use('/api/ps/apikey', apikeyRoutes);
app.use('/api/ps/proxy', proxyRoutes);
// ── 健康检查 ──
// ── 健康检查 ──app.use('/api/ps/preview', previewRoutes);
app.use('/api/dashboard', require('./routes/dashboard-api'));
// ── 健康检查 ──
app.get('/api/ps/health', (_req, res) => {
res.json({
status: 'ok',
service: 'persona-studio',
version: '1.0.0',
timestamp: new Date().toISOString()
});
});
// 兼容 /api/health 路径
app.get('/api/health', (_req, res) => {
res.json({
status: 'ok',
service: 'persona-studio',
version: '1.0.0',
timestamp: new Date().toISOString()
});
});
// ── 根路由 ──
app.get('/', (_req, res) => {
res.json({
status: 'ok',
message: 'Persona Studio 后端服务运行中',
version: '2.0.0',
routes: [
'/api/ps/auth/login',
'/api/ps/chat/message',
'/api/ps/chat/history',
'/api/ps/build/start',
'/api/ps/notify/send',
'/api/ps/apikey/detect-models',
'/api/ps/apikey/chat',
'/api/ps/proxy/status',
'/api/ps/proxy/models',
'/api/ps/proxy/chat',
'/api/ps/proxy/chat/stream',
'/api/ps/preview/:devId/:project',
'/api/ps/health'
]
});
});
const PORT = process.env.PS_PORT || 3002;
// ── WebSocket 服务(预览进度推送) ──
const server = http.createServer(app);
// WebSocket clients map: dev_id -> Set<ws>
const wsClients = new Map();
try {
const WebSocket = require('ws');
const wss = new WebSocket.Server({ server, path: '/ws/preview' });
wss.on('connection', (ws, req) => {
const url = new URL(req.url, 'http://localhost');
const devId = url.searchParams.get('dev_id') || 'unknown';
if (!wsClients.has(devId)) {
wsClients.set(devId, new Set());
}
wsClients.get(devId).add(ws);
ws.on('close', () => {
const clients = wsClients.get(devId);
if (clients) {
clients.delete(ws);
if (clients.size === 0) wsClients.delete(devId);
}
});
ws.on('error', () => {
const clients = wsClients.get(devId);
if (clients) {
clients.delete(ws);
if (clients.size === 0) wsClients.delete(devId);
}
});
});
// Export broadcast function for other modules
app.locals.broadcastToClient = function (devId, data) {
const clients = wsClients.get(devId);
if (!clients) return;
const msg = typeof data === 'string' ? data : JSON.stringify(data);
clients.forEach(function (ws) {
if (ws.readyState === WebSocket.OPEN) {
ws.send(msg);
}
});
};
} catch (_e) {
// ws module not installed, WebSocket disabled
console.warn('[Persona Studio] ws module not available, WebSocket features disabled');
app.locals.broadcastToClient = function () {};
}
server.listen(PORT, () => {
console.log(`🌊 Persona Studio 后端服务启动 · 端口 ${PORT}`);
});
module.exports = app;