From 231c76df841a7f47277b1920376add0655a55c23 Mon Sep 17 00:00:00 2001 From: Askhz <1361267452@qq.com> Date: Fri, 8 May 2026 18:12:22 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AE=8C=E5=96=84=20serve=20=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=20session=20=E5=88=97=E8=A1=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GET /session/:id 支持从磁盘历史记录 fallback,修复历史 session 404 - 过滤无意义的管理命令会话(/exit、/model、/login 等) - 保留 /crewpilot:plan 等有意义的斜杠命令触发的会话 Co-Authored-By: Claude Opus 4.7 --- src/server/routes/session.ts | 64 +++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/src/server/routes/session.ts b/src/server/routes/session.ts index 8f9e3f8ab..e2de66a41 100644 --- a/src/server/routes/session.ts +++ b/src/server/routes/session.ts @@ -215,10 +215,26 @@ export function createSessionRoutes( } } - // 按最后活跃时间倒序 - merged.sort((a, b) => (b.last_active_at ?? 0) - (a.last_active_at ?? 0)) + // 过滤掉已知的无意义管理命令会话(用户直接输入后立即退出,没有实际对话内容) + const BORING_COMMANDS = new Set([ + '/exit', '/quit', '/bye', + '/clear', '/reset', + '/model', '/models', + '/login', '/logout', + '/help', '/version', + '/compact', + ]) + const filtered = merged.filter(s => { + const t = s.title.trim() + if (!t) return false + if (BORING_COMMANDS.has(t)) return false + return true + }) - const sessions = merged.slice(offset, offset + limit) + // 按最后活跃时间倒序 + filtered.sort((a, b) => (b.last_active_at ?? 0) - (a.last_active_at ?? 0)) + + const sessions = filtered.slice(offset, offset + limit) process.stderr.write(`[server:session] GET /session -> history=${historySessions.length} active=${handleMap.size} merged=${merged.length} returned=${sessions.length}\n`) return c.json({ sessions }) }) @@ -256,16 +272,42 @@ export function createSessionRoutes( return c.json({ sessions }) }) - .get('/session/:sessionID', c => { + .get('/session/:sessionID', async c => { const id = c.req.param('sessionID') const handle = sessionManager.getSession(id) - if (!handle) throw notFound('session not found') - const info = handle.getInfo() - return c.json({ - ...info, - message_count: handle.messageCount, - usage: handle.usage, - }) + if (handle) { + const info = handle.getInfo() + return c.json({ + ...info, + message_count: handle.messageCount, + usage: handle.usage, + }) + } + + // 内存中没有,从磁盘历史记录查找 + try { + const history = await listSessionsImpl({ limit: 1000 }) + const s = history.find(h => h.sessionId === id) + if (s) { + return c.json({ + session_id: s.sessionId, + status: 'stopped', + cwd: s.cwd ?? '', + title: (s.customTitle ?? s.firstPrompt ?? s.summary) ?? '', + model: undefined, + permission_mode: undefined, + created_at: s.createdAt ?? 0, + last_active_at: s.lastModified ?? 0, + cost_usd: 0, + input_tokens: 0, + output_tokens: 0, + message_count: 0, + usage: { input_tokens: 0, output_tokens: 0 }, + }) + } + } catch {} + + throw notFound('session not found') }) .patch('/session/:sessionID', async c => { const id = c.req.param('sessionID')