feat: 多会话支持 — /sessions、/switch、/session 命令#174
Conversation
cc18b3f to
e193c4b
Compare
|
Triage 路过 — 这个 PR 目前与 |
|
Thank you for this — the 1. Stale base — SessionManager has movedSince this PR was opened, the engine abstraction landed and 2. Coordination with #243 and #244
Concretely: please rebase after #243 + #244 land, not before — otherwise we'll be chasing three-way conflicts. 3. Concurrency on
|
将 SessionManager 从扁平的 per-chatId 模型重构为 SessionGroup 分组模型,
允许用户在一个聊天中维护多个对话线程。
主要变更:
- resetSession() 创建新会话而非清除旧会话,历史会话保留可切换
- 新增 /sessions 列出所有会话、/switch N 按编号切换、/session <prefix> 按 ID 前缀切换
- 虚拟 chatId ({chatId}::{N}) 确保 SessionRegistry 中不同会话的记录隔离
- 自动记录会话标题(首条消息预览)
- 持久化格式向后兼容:自动将旧扁平格式迁移为分组格式
- 24 个测试覆盖所有新功能
设计参考 xvirobotics#239 统一命令规范。基于 upstream/main 全新重写(原 PR xvirobotics#174)。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. saveToDisk 过滤 bug:新创建的空会话(无 sessionId)被持久化过滤器 跳过,导致 /reset 后重启服务会丢失新会话。改为保存 group 内所有 session。 2. /switch 未释放 persistent executor:切换会话时旧的长驻 Claude 进程 仍在运行,其 sessionId 会覆盖切换后的会话。现在 /switch 和 /session 命令都会调用 releaseExecutor。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
e193c4b to
372296a
Compare
|
@floodsung 感谢详细的 review!已基于最新 1. 文件迁移 ✅已在 2. #243/#244 依赖两个 PR 自 5/9 以来作者 uestney 未回应 review 意见,处于停滞状态。当前实现基于现有 SessionRegistry(SQLite)可正常工作,等 #243/#244 合并后会做一次适配 rebase。 3. 并发安全 ✅分析后确认不需要加锁:MessageBridge 通过 4. 统一命令设计 ✅按 #239 讨论结果增加了
飞书集成测试在 persistent executor 模式下完成了完整的多会话生命周期验证:创建会话 → 测试中发现并修复了两个 bug: |
|
@floodsung 补充说明:关于你提到的 #243 依赖问题,我们已经在 PR #278 中独立解决了 —— 基于 @uestney 的设计将 SessionRegistry 从 SQLite 迁移为 JSON 文件持久化,并补全了你在 #243 review 中要求的 warn 日志、测试覆盖和迁移说明。 所以目前:
两个 PR 互不依赖,合并顺序随意。期待 review! |
概要
将 SessionManager 从扁平的 per-chatId 模型重构为 SessionGroup 分组模型,允许用户在一个聊天中维护多个对话线程。
/reset不再销毁会话,而是创建新会话,旧会话保留可切换/sessions列出当前聊天的所有会话(编号、标题、ID 前缀、活跃标记)/switch N按编号切换会话/session <prefix>按 sessionId 前缀切换(按 [Feature] 能否实现通过指令列出和切换 Claude Code / Codex 历史会话? #239 统一命令设计){chatId}::{N}确保 SessionRegistry 记录隔离对 reviewer 反馈的回应
upstream/main(a6ce914)全新重写,代码位于src/engines/claude/session-manager.ts,保留了所有上游新字段(engine, model, goal 等)runningTasksMap 保证每个 chatId 同时只有一个任务在执行,activeIndex读写不存在竞态条件。已在代码中注释说明此不变量/session <prefix>命令,命令空间与 feat: add /api and /resume commands for remote management #227 的/resume正交变更文件
src/engines/claude/session-manager.tssrc/bridge/command-handler.ts/sessions、/switch、/session命令 +/help更新src/bridge/message-bridge.tstests/session-manager.test.ts测试计划
npm run build— 编译通过(预存的 kimi/marked 错误与本 PR 无关)npm test— 24 个新测试 + 5 个原有测试全部通过npm run lint— 无新错误飞书集成测试记录
环境:bot
xiaobai,persistent executor 模式/reset/switch 1关键验证:切换回旧会话后,Claude 正确回忆了"中国的首都"而非"法国的首都",证明会话隔离和上下文恢复功能正常。
集成测试中发现并修复的 bug
/reset后尚无 sessionId)被持久化过滤器跳过,导致重启后丢失/switch未调用releaseExecutor,导致旧 Claude 进程的 sessionId 覆盖切换后的会话两个 bug 均已在第二个 commit 中修复。