Resolve merge conflicts: keep origin/main version across 4 files

- backend-integration/README.md: Add Persona Studio API endpoints docs
- backend-integration/api-proxy.js: Add PS backend reverse proxy implementation
- persona-studio/frontend/chat.js: Use backend proxy instead of direct fetch
- persona-telemetry/latest-summary.json: Update timestamps and coverage format

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-03-11 07:45:36 +00:00
parent 1d48cad804
commit 33fc76a26e
4 changed files with 0 additions and 116 deletions

View File

@ -33,14 +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 |
<<<<<<< HEAD
=======
| 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 |
>>>>>>> origin/main
### 环境变量
@ -53,10 +50,7 @@ curl http://localhost:3721/api/models
| `OPENAI_API_KEY` | OpenAI 密钥(需海外服务器) |
| `GEMINI_API_KEY` | Google Gemini 密钥(需海外服务器) |
| `PROXY_PORT` | 端口(默认 3721 |
<<<<<<< HEAD
=======
| `PS_PORT` | Persona Studio 后端端口(默认 3002反向代理目标 |
>>>>>>> origin/main
| `RATE_LIMIT_RPM` | 频率限制(默认 10 次/分钟) |
### Nginx 配置

View File

@ -710,8 +710,6 @@ async function handleApiKeyChat(req, res) {
}
// ═══════════════════════════════════════════════════════
<<<<<<< HEAD
=======
// Persona Studio 后端反向代理
// 将 /api/ps/chat/*, /api/ps/auth/*, /api/ps/build/*, /api/ps/notify/*
// 转发到 persona-studio 后端服务(默认端口 3002
@ -782,7 +780,6 @@ function proxyToPersonaStudio(req, res, fullPath) {
}
// ═══════════════════════════════════════════════════════
>>>>>>> origin/main
// HTTP 服务器
// ═══════════════════════════════════════════════════════
const server = http.createServer(async (req, res) => {
@ -810,20 +807,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);
<<<<<<< HEAD
=======
} else if (shouldProxyToPersonaStudio(path)) {
await proxyToPersonaStudio(req, res, url.pathname + url.search);
>>>>>>> origin/main
} else {
jsonResponse(res, 404, {
error: true,
code: 'NOT_FOUND',
<<<<<<< HEAD
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'
>>>>>>> origin/main
});
}
} catch (err) {
@ -863,23 +853,17 @@ server.listen(PORT, () => {
console.log(' export YUNWU_API_KEY=sk-xxx');
}
<<<<<<< HEAD
=======
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/*');
>>>>>>> origin/main
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 对话');
<<<<<<< HEAD
=======
console.log(' POST /api/ps/chat/message — 知秋对话(→ PS后端');
console.log(' GET /api/ps/chat/history — 对话历史(→ PS后端');
console.log(' POST /api/ps/auth/login — 登录校验(→ PS后端');
>>>>>>> origin/main
console.log('');
});

View File

@ -140,93 +140,12 @@ async function sendMessage() {
input.focus();
}
<<<<<<< HEAD
/* ---- API Key 流式响应(浏览器直连) ---- */
=======
/* ---- API Key 对话(通过后端代理,避免 CORS 问题) ---- */
>>>>>>> origin/main
async function streamApiKeyReply(text) {
var apiMessages = conversationHistory.slice(-20).map(function (msg) {
return { role: msg.role === 'assistant' ? 'assistant' : 'user', content: msg.content };
});
<<<<<<< HEAD
var chatUrl = USER_API_BASE + '/chat/completions';
var reqBody = {
model: SELECTED_MODEL,
messages: apiMessages,
stream: true,
max_tokens: 2000,
temperature: 0.8
};
var res = await fetch(chatUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + USER_API_KEY
},
body: JSON.stringify(reqBody)
});
if (!res.ok) {
var errText = '请求失败 (HTTP ' + res.status + ')';
try {
var errData = await res.json();
errText = errData.error?.message || errText;
} catch (_e) { /* ignore parse error */ }
appendMessage('system', '⚠️ ' + errText);
return;
}
// 流式读取响应
var streamEl = appendStreamMessage();
var full = '';
var reader = res.body.getReader();
var decoder = new TextDecoder();
var buf = '';
while (true) {
var chunk = await reader.read();
if (chunk.done) break;
buf += decoder.decode(chunk.value, { stream: true });
var lines = buf.split('\n');
buf = lines.pop();
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
if (!line.startsWith('data: ')) continue;
var d = line.slice(6);
if (d === '[DONE]') continue;
try {
var parsed = JSON.parse(d);
var delta = parsed.choices && parsed.choices[0]
&& parsed.choices[0].delta
&& parsed.choices[0].delta.content;
if (delta) {
full += delta;
streamEl.textContent = full;
}
} catch (_e) { /* ignore parse error */ }
}
}
// 如果没有流式内容,尝试非流式解析
if (!full && buf) {
try {
var jsonRes = JSON.parse(buf);
if (jsonRes.choices && jsonRes.choices[0] && jsonRes.choices[0].message) {
full = jsonRes.choices[0].message.content;
streamEl.textContent = full;
}
} catch (_e) { /* ignore */ }
}
if (full) {
conversationHistory.push({ role: 'assistant', content: full });
} else {
streamEl.textContent = '(未收到有效回复)';
=======
var streamEl = appendStreamMessage();
try {
@ -261,7 +180,6 @@ async function streamApiKeyReply(text) {
}
} catch (err) {
streamEl.textContent = '⚠️ ' + (err.message || '请求失败,请检查网络连接');
>>>>>>> origin/main
}
}

View File

@ -1,10 +1,6 @@
{
"version": "1.0",
<<<<<<< HEAD
"timestamp": "2026-03-09T23:59:23.782Z",
=======
"timestamp": "2026-03-10T23:59:09.654Z",
>>>>>>> origin/main
"sessions": {
"total_24h": 0,
"active_devs": [
@ -23,11 +19,7 @@
"style_profile": "通感语言·守护者",
"style_drift_score": 0,
"memory_depth": "0 selfchecks",
<<<<<<< HEAD
"last_brain_update": "2026-03-09T23:59:23.782Z"
=======
"last_brain_update": "2026-03-10T13:24:33.728Z"
>>>>>>> origin/main
},
"dev_progress": {
"syslog_submitted": 0,
@ -40,11 +32,7 @@
"next_scheduled": null
},
"repo_health": {
<<<<<<< HEAD
"hli_coverage": "17.6%",
=======
"hli_coverage": "3/17",
>>>>>>> origin/main
"total_team_members": 9,
"green_status_count": 6
},