fix: 修复 Persona Studio 对话无回复 · API代理层新增反向代理 + PM2配置补全 + 模块自检修复
问题根因:Nginx 将所有 /api/* 路由到 api-proxy (port 3721),但 api-proxy 未处理 /api/ps/chat/*, /api/ps/auth/* 等 Persona Studio 后端路由,导致请求返回 404,用户发送消息后无回复。 修复内容: 1. api-proxy.js 新增反向代理,将 /api/ps/chat/*, /api/ps/auth/*, /api/ps/build/*, /api/ps/notify/* 转发到 PS 后端 (port 3002) 2. ecosystem.config.js 补全 api-proxy + persona-studio PM2 配置 3. m15-cloud-drive/ 补全 README.md(模块自检修复) 4. README.md 开发者公告栏更新修复状态 Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
This commit is contained in:
parent
ae0e52029e
commit
df64cb221d
16
README.md
16
README.md
|
|
@ -78,6 +78,8 @@
|
|||
<!-- BINGSHUO_BULLETIN_START -->
|
||||
| 时间 | 检查项 | 状态 |
|
||||
|------|--------|------|
|
||||
| 03-10 22:19 | 🔧 Persona Studio 对话修复 · API代理层新增反向代理 · `/api/ps/chat/*`,`/api/ps/auth/*`,`/api/ps/build/*`,`/api/ps/notify/*` → PS后端(port 3002) · PM2 配置补全 · `m15-cloud-drive/` README.md 补全 | 铸渊(冰朔指令) |
|
||||
| 03-10 22:19 | ✅ 铸渊模块自检完成 · 发现 2 个问题 · 自动修复 2 项 | 铸渊自检 |
|
||||
| 03-10 21:57 | 🔧 系统更新: `.github/` | 铸渊 (Copilot) |
|
||||
| 03-10 21:57 | 🔧 系统更新: `scripts/` | 铸渊 (Copilot) |
|
||||
| 03-10 21:54 | ✅ 📢 更新系统公告区 · 成功 | 冰朔 |
|
||||
|
|
@ -98,9 +100,12 @@
|
|||
### 🤖 铸渊自动提醒
|
||||
|
||||
<!-- BINGSHUO_ALERT_START -->
|
||||
> 🟢 **今日无需冰朔手动干预** · 系统一切正常
|
||||
> 🟢 **铸渊模块自检完成 · 已自动修复 2 项**
|
||||
>
|
||||
> 🗓️ 2026-03-10 · 铸渊自动检测
|
||||
> ✅ `api-proxy.js` 新增 Persona Studio 反向代理 · 修复对话无回复问题
|
||||
> ✅ `m15-cloud-drive/` 补全 README.md
|
||||
>
|
||||
> 🗓️ 2026-03-10 · 铸渊自动修复
|
||||
<!-- BINGSHUO_ALERT_END -->
|
||||
|
||||
---
|
||||
|
|
@ -123,12 +128,11 @@
|
|||
### 🤖 铸渊自动提醒 · 合作者
|
||||
|
||||
<!-- COLLABORATOR_ALERT_START -->
|
||||
> 🔴 **以下合作者需要手动干预:**
|
||||
> 🟢 **所有合作者模块自检通过** · 无需手动干预
|
||||
>
|
||||
> **🎨 燕樊(DEV-003):**
|
||||
> - ⚠️ `m15-cloud-drive/` 缺少 README.md
|
||||
> ✅ `m15-cloud-drive/` README.md 已由铸渊自动补全
|
||||
>
|
||||
> 🗓️ 2026-03-10 · 铸渊已发送邮件提醒
|
||||
> 🗓️ 2026-03-10 · 铸渊自动修复
|
||||
<!-- COLLABORATOR_ALERT_END -->
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ curl http://localhost:3721/api/models
|
|||
| GET | `/api/health` | 健康检查 |
|
||||
| POST | `/api/ps/apikey/detect-models` | 用户 API Key 模型检测(Persona Studio) |
|
||||
| POST | `/api/ps/apikey/chat` | 用户 API Key 对话(Persona Studio) |
|
||||
| POST | `/api/ps/chat/message` | 知秋对话(→ PS 后端 port 3002) |
|
||||
| GET | `/api/ps/chat/history` | 对话历史(→ PS 后端 port 3002) |
|
||||
| POST | `/api/ps/auth/login` | 开发编号登录(→ PS 后端 port 3002) |
|
||||
| POST | `/api/ps/build/start` | 开发任务触发(→ PS 后端 port 3002) |
|
||||
| POST | `/api/ps/notify/send` | 邮件通知(→ PS 后端 port 3002) |
|
||||
|
||||
### 环境变量
|
||||
|
||||
|
|
@ -45,6 +50,7 @@ curl http://localhost:3721/api/models
|
|||
| `OPENAI_API_KEY` | OpenAI 密钥(需海外服务器) |
|
||||
| `GEMINI_API_KEY` | Google Gemini 密钥(需海外服务器) |
|
||||
| `PROXY_PORT` | 端口(默认 3721) |
|
||||
| `PS_PORT` | Persona Studio 后端端口(默认 3002,反向代理目标) |
|
||||
| `RATE_LIMIT_RPM` | 频率限制(默认 10 次/分钟) |
|
||||
|
||||
### Nginx 配置
|
||||
|
|
|
|||
|
|
@ -709,6 +709,74 @@ async function handleApiKeyChat(req, res) {
|
|||
}
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// Persona Studio 后端反向代理
|
||||
// 将 /api/ps/chat/*, /api/ps/auth/*, /api/ps/build/*, /api/ps/notify/*
|
||||
// 转发到 persona-studio 后端服务(默认端口 3002)
|
||||
// ═══════════════════════════════════════════════════════
|
||||
const PS_BACKEND_PORT = parseInt(process.env.PS_PORT || '3002', 10);
|
||||
const PS_PROXY_PATHS = ['/api/ps/chat/', '/api/ps/auth/', '/api/ps/build/', '/api/ps/notify/'];
|
||||
|
||||
function shouldProxyToPersonaStudio(pathname) {
|
||||
return PS_PROXY_PATHS.some(prefix => pathname.startsWith(prefix));
|
||||
}
|
||||
|
||||
function proxyToPersonaStudio(req, res, fullPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const options = {
|
||||
hostname: '127.0.0.1',
|
||||
port: PS_BACKEND_PORT,
|
||||
path: fullPath,
|
||||
method: req.method,
|
||||
headers: Object.assign({}, req.headers, {
|
||||
host: '127.0.0.1:' + PS_BACKEND_PORT
|
||||
}),
|
||||
timeout: 60000
|
||||
};
|
||||
|
||||
const proxyReq = http.request(options, (proxyRes) => {
|
||||
// Forward status and headers (preserve CORS headers already set)
|
||||
const headers = {};
|
||||
for (const [key, value] of Object.entries(proxyRes.headers)) {
|
||||
if (!key.startsWith('access-control-')) {
|
||||
headers[key] = value;
|
||||
}
|
||||
}
|
||||
res.writeHead(proxyRes.statusCode, headers);
|
||||
proxyRes.pipe(res);
|
||||
proxyRes.on('end', resolve);
|
||||
proxyRes.on('error', reject);
|
||||
});
|
||||
|
||||
proxyReq.on('error', (err) => {
|
||||
console.error('[代理→PS] persona-studio 后端连接失败:', err.message);
|
||||
if (!res.headersSent) {
|
||||
jsonResponse(res, 502, {
|
||||
error: true,
|
||||
code: 'PS_BACKEND_UNAVAILABLE',
|
||||
message: 'Persona Studio 后端服务不可用,请稍后重试'
|
||||
});
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
|
||||
proxyReq.on('timeout', () => {
|
||||
proxyReq.destroy();
|
||||
if (!res.headersSent) {
|
||||
jsonResponse(res, 504, {
|
||||
error: true,
|
||||
code: 'PS_BACKEND_TIMEOUT',
|
||||
message: 'Persona Studio 后端响应超时'
|
||||
});
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
|
||||
// Pipe the original request body to the proxy request
|
||||
req.pipe(proxyReq);
|
||||
});
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// HTTP 服务器
|
||||
// ═══════════════════════════════════════════════════════
|
||||
|
|
@ -737,11 +805,13 @@ const server = http.createServer(async (req, res) => {
|
|||
await handleDetectModels(req, res);
|
||||
} else if (path === '/api/ps/apikey/chat' && req.method === 'POST') {
|
||||
await handleApiKeyChat(req, res);
|
||||
} else if (shouldProxyToPersonaStudio(path)) {
|
||||
await proxyToPersonaStudio(req, res, url.pathname + url.search);
|
||||
} else {
|
||||
jsonResponse(res, 404, {
|
||||
error: true,
|
||||
code: 'NOT_FOUND',
|
||||
message: '接口不存在。可用接口: POST /api/chat, GET /api/models, GET /api/health, POST /api/ps/apikey/detect-models, POST /api/ps/apikey/chat'
|
||||
message: '接口不存在。可用接口: POST /api/chat, GET /api/models, GET /api/health, POST /api/ps/apikey/detect-models, POST /api/ps/apikey/chat, POST /api/ps/chat/message, GET /api/ps/chat/history, POST /api/ps/auth/login'
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
|
|
@ -781,11 +851,17 @@ server.listen(PORT, () => {
|
|||
console.log(' export YUNWU_API_KEY=sk-xxx');
|
||||
}
|
||||
|
||||
console.log(`\n Persona Studio 后端代理: http://127.0.0.1:${PS_BACKEND_PORT}`);
|
||||
console.log(' 代理路径: /api/ps/chat/*, /api/ps/auth/*, /api/ps/build/*, /api/ps/notify/*');
|
||||
|
||||
console.log('\n 可用接口:');
|
||||
console.log(' POST /api/chat — 聊天代理(SSE 流式)');
|
||||
console.log(' GET /api/models — 列出可用模型');
|
||||
console.log(' GET /api/health — 健康检查');
|
||||
console.log(' POST /api/ps/apikey/detect-models — 用户 API Key 模型检测');
|
||||
console.log(' POST /api/ps/apikey/chat — 用户 API Key 对话');
|
||||
console.log(' POST /api/ps/chat/message — 知秋对话(→ PS后端)');
|
||||
console.log(' GET /api/ps/chat/history — 对话历史(→ PS后端)');
|
||||
console.log(' POST /api/ps/auth/login — 登录校验(→ PS后端)');
|
||||
console.log('');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -25,5 +25,33 @@ module.exports = {
|
|||
error_file: 'logs/error.log',
|
||||
out_file: 'logs/out.log',
|
||||
},
|
||||
{
|
||||
name: 'api-proxy',
|
||||
script: 'backend-integration/api-proxy.js',
|
||||
instances: 1,
|
||||
exec_mode: 'fork',
|
||||
watch: false,
|
||||
env: {
|
||||
NODE_ENV: 'production',
|
||||
PROXY_PORT: 3721,
|
||||
},
|
||||
log_date_format: 'YYYY-MM-DD HH:mm:ss',
|
||||
error_file: 'logs/api-proxy-error.log',
|
||||
out_file: 'logs/api-proxy-out.log',
|
||||
},
|
||||
{
|
||||
name: 'persona-studio',
|
||||
script: 'persona-studio/backend/server.js',
|
||||
instances: 1,
|
||||
exec_mode: 'fork',
|
||||
watch: false,
|
||||
env: {
|
||||
NODE_ENV: 'production',
|
||||
PS_PORT: 3002,
|
||||
},
|
||||
log_date_format: 'YYYY-MM-DD HH:mm:ss',
|
||||
error_file: 'logs/persona-studio-error.log',
|
||||
out_file: 'logs/persona-studio-out.log',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
# M15 云盘系统
|
||||
|
||||
- 负责人:燕樊(DEV-003)
|
||||
- 状态:已毕业
|
||||
- 技术栈:HTML + CSS + JavaScript(纯前端)
|
||||
- 依赖模块:无
|
||||
|
||||
## 功能说明
|
||||
|
||||
HoloLake 网站云盘系统前端界面,提供文件管理交互体验。
|
||||
|
||||
### 包含文件
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| `cloud-drive.html` | 云盘主页面 |
|
||||
| `cloud-drive.js` | 交互逻辑(文件夹切换、文件选中、上传等) |
|
||||
| `cloud-drive-style.css` | 样式表 |
|
||||
|
||||
### 核心功能
|
||||
|
||||
- 📁 文件夹切换与导航
|
||||
- 📄 文件列表展示与选中
|
||||
- ⬆️ 文件上传交互
|
||||
- 💾 存储用量展示
|
||||
Loading…
Reference in New Issue