diff --git a/server/ai/client.js b/server/ai/client.js index 28ae2c8..143297f 100644 --- a/server/ai/client.js +++ b/server/ai/client.js @@ -5,8 +5,23 @@ function sanitizeUserId(username) { return username.replace(/[^a-zA-Z0-9\-_]/g, '_').substring(0, 64) || 'anon'; } -async function callDeepSeek(messages, temperature = 0.1, userId = '') { - console.log('🤖 调用 DeepSeek...'); +function getErrorMsg(status, data) { + var msg = data && data.error && data.error.message ? data.error.message : ''; + switch (status) { + case 400: return 'AI 请求格式错误,请联系管理员(400)' + (msg ? ':' + msg : ''); + case 401: return 'AI 认证失败,请检查 API Key(401)' + (msg ? ':' + msg : ''); + case 402: return 'AI 账户余额不足,请联系管理员充值(402)'; + case 422: return 'AI 参数错误(422)' + (msg ? ':' + msg : ''); + case 429: return 'AI 请求太频繁,请稍后重试(429)'; + case 500: return 'AI 服务器故障,请稍后重试(500)'; + case 503: return 'AI 服务器繁忙,请稍后重试(503)'; + default: return 'AI 响应异常(' + status + ')' + (msg ? ':' + msg : ''); + } +} + +async function callDeepSeek(messages, temperature, userId) { + if (temperature === undefined) temperature = 0.1; + console.log('调用 DeepSeek...'); var body = { model: 'deepseek-v4-flash', messages: messages, temperature: temperature, stream: false }; if (userId) body.user_id = sanitizeUserId(userId); var res = await fetch('https://api.deepseek.com/chat/completions', { @@ -14,10 +29,15 @@ async function callDeepSeek(messages, temperature = 0.1, userId = '') { headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + DEEPSEEK_API_KEY }, body: JSON.stringify(body) }); - const data = await res.json(); + var data = await res.json(); + if (!res.ok) { + var errMsg = getErrorMsg(res.status, data); + console.error('DeepSeek API 错误:', errMsg); + throw new Error(errMsg); + } if (!data.choices || !data.choices[0]) { - console.error('🤖 DeepSeek 返回异常:', JSON.stringify(data)); - throw new Error('DeepSeek API 返回异常: ' + (data.error?.message || JSON.stringify(data))); + console.error('DeepSeek 返回异常:', JSON.stringify(data)); + throw new Error('AI 返回数据异常'); } return data.choices[0].message.content; } diff --git a/server/routes/messages.js b/server/routes/messages.js index e6488f0..008dc5e 100644 --- a/server/routes/messages.js +++ b/server/routes/messages.js @@ -1,7 +1,7 @@ // 消息路由 + AI 分析 const express = require('express'); const { authMiddleware } = require('../middleware/auth'); -const { broadcastToRoomExcludeSelf } = require('../ws'); +const { broadcastToRoomExcludeSelf, broadcastToRoom } = require('../ws'); const { buildSystemPrompt } = require('../ai/prompt'); const { validate, normalize } = require('../ai/validator'); const { callDeepSeek } = require('../ai/client'); @@ -48,7 +48,13 @@ router.post('/:roomId/messages', authMiddleware, async (req, res) => { if (aiResponse && aiResponse.action !== 'ignore') { handleAIResult(aiResponse, roomId, username, text || '', attachments || []); } - } catch (e) { console.error('AI 分析失败:', e); } + } catch (e) { + console.error('AI 分析失败:', e.message); + var errText = '❌ ' + (e.message || 'AI 处理失败,请稍后重试'); + var result = db.prepare('INSERT INTO messages (room_id, user, text, timestamp) VALUES (?,?,?,?)').run(roomId, '小财', errText, timestamp()); + var msg = { id: result.lastInsertRowid, room_id: roomId, user: '小财', text: errText, attachments: [], timestamp: timestamp() }; + broadcastToRoom(roomId, { type: 'new_message', message: msg }); + } }); async function analyzeWithDeepSeek(text, historyMessages, username, isAdmin, roomId) {