diff --git a/src/routes/api.js b/src/routes/api.js index 898293bd..62729389 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -1085,6 +1085,18 @@ router.post('/v1/messages/count_tokens', authenticateApiKey, async (req, res) => return res.status(error.httpStatus).json(error.errorPayload) } + // 客户端断开连接不是错误,使用 INFO 级别 + if (error.message === 'Client disconnected') { + logger.info('🔌 Client disconnected during token count request') + if (!res.headersSent) { + return res.status(499).end() // 499 Client Closed Request + } + if (!res.destroyed && !res.finished) { + res.end() + } + return + } + logger.error('❌ Token count error:', error) if (!res.headersSent) { return res.status(500).json({ diff --git a/src/routes/openaiRoutes.js b/src/routes/openaiRoutes.js index 6367241e..207d0e0f 100644 --- a/src/routes/openaiRoutes.js +++ b/src/routes/openaiRoutes.js @@ -258,9 +258,9 @@ const handleResponses = async (req, res) => { const isStream = req.body?.stream !== false // 默认为流式(兼容现有行为) // 判断是否为 Codex CLI 的请求 - const isCodexCLI = req.body?.instructions?.startsWith( - 'You are a coding agent running in the Codex CLI' - ) + const isCodexCLI = + req.body?.instructions?.startsWith('You are a coding agent running in the Codex CLI') || + req.body?.instructions?.startsWith('You are Codex') // 如果不是 Codex CLI 请求,则进行适配 if (!isCodexCLI) { diff --git a/src/services/claudeConsoleRelayService.js b/src/services/claudeConsoleRelayService.js index 46c72996..58272cb5 100644 --- a/src/services/claudeConsoleRelayService.js +++ b/src/services/claudeConsoleRelayService.js @@ -317,7 +317,12 @@ class ClaudeConsoleRelayService { } } catch (error) { // 处理特定错误 - if (error.name === 'AbortError' || error.code === 'ECONNABORTED') { + if ( + error.name === 'AbortError' || + error.name === 'CanceledError' || + error.code === 'ECONNABORTED' || + error.code === 'ERR_CANCELED' + ) { logger.info('Request aborted due to client disconnect') throw new Error('Client disconnected') }