fix: 完善 serve 模式 session 列表接口

- GET /session/:id 支持从磁盘历史记录 fallback,修复历史 session 404
- 过滤无意义的管理命令会话(/exit、/model、/login 等)
- 保留 /crewpilot:plan 等有意义的斜杠命令触发的会话

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Askhz 2026-05-08 18:12:22 +08:00
parent a62989e245
commit 231c76df84

View File

@ -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')