From 16e2bcfedbca5fae0ffaec5c6cf5e7b7e41c524a Mon Sep 17 00:00:00 2001 From: enzyme2013 Date: Thu, 22 Jan 2026 17:31:11 +0800 Subject: [PATCH] fix: allow new session binding after /clear command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 isOldSession 检查,信任客户端的 session ID 作为新会话标识 - 将 sessionBindingTtlDays 默认值从 30 天改为 1 天,避免 Redis 内存累积 - 添加新会话绑定的监控日志(包含 sessionId、messages 数量、accountId 等) - 完美支持 Claude Code /clear 等合法的新会话场景 - 同步更新前端界面的默认值配置 问题背景: 用户在 Claude Code 中执行 /clear 后,会生成新的 session ID, 但旧的逻辑会检查请求内容判定为"旧会话",导致返回"本地session已污染"错误。 修复方案: 采用方案2(放宽新会话检测)+ TTL 优化,信任客户端的 session ID, 不再检查请求内容是否"看起来像旧会话",由 1 天的 TTL 自动清理过期绑定。 影响范围: - src/routes/api.js (流式和非流式两处) - src/services/claudeRelayConfigService.js - web/admin-spa/src/views/SettingsView.vue --- src/routes/api.js | 40 +++++++++--------------- src/services/claudeRelayConfigService.js | 2 +- web/admin-spa/src/views/SettingsView.vue | 4 +-- 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/routes/api.js b/src/routes/api.js index 03a97013..2dae7783 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -370,19 +370,13 @@ async function handleMessagesRequest(req, res) { accountId && accountType === 'claude-official' ) { - // 🚫 检测旧会话(污染的会话) - if (isOldSession(req.body)) { - const cfg = await claudeRelayConfigService.getConfig() - logger.warn( - `🚫 Old session rejected: sessionId=${originalSessionIdForBinding}, messages.length=${req.body?.messages?.length}, tools.length=${req.body?.tools?.length || 0}, isOldSession=true` - ) - return res.status(400).json({ - error: { - type: 'session_binding_error', - message: cfg.sessionBindingErrorMessage || '你的本地session已污染,请清理后使用。' - } - }) - } + // 🆕 允许新 session ID 创建绑定(支持 Claude Code /clear 等场景) + // 信任客户端的 session ID 作为新会话的标识,不再检查请求内容 + logger.info( + `🔗 Creating new session binding: sessionId=${originalSessionIdForBinding}, ` + + `messages.length=${req.body?.messages?.length}, tools.length=${req.body?.tools?.length || 0}, ` + + `accountId=${accountId}, accountType=${accountType}` + ) // 创建绑定 try { @@ -928,19 +922,13 @@ async function handleMessagesRequest(req, res) { accountId && accountType === 'claude-official' ) { - // 🚫 检测旧会话(污染的会话) - if (isOldSession(req.body)) { - const cfg = await claudeRelayConfigService.getConfig() - logger.warn( - `🚫 Old session rejected (non-stream): sessionId=${originalSessionIdForBindingNonStream}, messages.length=${req.body?.messages?.length}, tools.length=${req.body?.tools?.length || 0}, isOldSession=true` - ) - return res.status(400).json({ - error: { - type: 'session_binding_error', - message: cfg.sessionBindingErrorMessage || '你的本地session已污染,请清理后使用。' - } - }) - } + // 🆕 允许新 session ID 创建绑定(支持 Claude Code /clear 等场景) + // 信任客户端的 session ID 作为新会话的标识,不再检查请求内容 + logger.info( + `🔗 Creating new session binding (non-stream): sessionId=${originalSessionIdForBindingNonStream}, ` + + `messages.length=${req.body?.messages?.length}, tools.length=${req.body?.tools?.length || 0}, ` + + `accountId=${accountId}, accountType=${accountType}` + ) // 创建绑定 try { diff --git a/src/services/claudeRelayConfigService.js b/src/services/claudeRelayConfigService.js index 4fa2b411..e0aa55d8 100644 --- a/src/services/claudeRelayConfigService.js +++ b/src/services/claudeRelayConfigService.js @@ -14,7 +14,7 @@ const DEFAULT_CONFIG = { claudeCodeOnlyEnabled: false, globalSessionBindingEnabled: false, sessionBindingErrorMessage: '你的本地session已污染,请清理后使用。', - sessionBindingTtlDays: 30, // 会话绑定 TTL(天),默认30天 + sessionBindingTtlDays: 1, // 会话绑定 TTL(天),默认1天(支持 /clear 场景,避免 Redis 累积) // 用户消息队列配置 userMessageQueueEnabled: false, // 是否启用用户消息队列(默认关闭) userMessageQueueDelayMs: 200, // 请求间隔(毫秒) diff --git a/web/admin-spa/src/views/SettingsView.vue b/web/admin-spa/src/views/SettingsView.vue index b9b260a2..4f18edab 100644 --- a/web/admin-spa/src/views/SettingsView.vue +++ b/web/admin-spa/src/views/SettingsView.vue @@ -1676,7 +1676,7 @@ const claudeConfig = ref({ claudeCodeOnlyEnabled: false, globalSessionBindingEnabled: false, sessionBindingErrorMessage: '你的本地session已污染,请清理后使用。', - sessionBindingTtlDays: 30, + sessionBindingTtlDays: 1, userMessageQueueEnabled: false, // 与后端默认值保持一致 userMessageQueueDelayMs: 200, userMessageQueueTimeoutMs: 5000, // 与后端默认值保持一致(优化后锁持有时间短无需长等待) @@ -1952,7 +1952,7 @@ const loadClaudeConfig = async () => { globalSessionBindingEnabled: response.config?.globalSessionBindingEnabled ?? false, sessionBindingErrorMessage: response.config?.sessionBindingErrorMessage || '你的本地session已污染,请清理后使用。', - sessionBindingTtlDays: response.config?.sessionBindingTtlDays ?? 30, + sessionBindingTtlDays: response.config?.sessionBindingTtlDays ?? 1, userMessageQueueEnabled: response.config?.userMessageQueueEnabled ?? false, // 与后端默认值保持一致 userMessageQueueDelayMs: response.config?.userMessageQueueDelayMs ?? 200, userMessageQueueTimeoutMs: response.config?.userMessageQueueTimeoutMs ?? 5000, // 与后端默认值保持一致