# u-tabs 历史会话功能 — 需求备忘录 > 日期: 2026-05-16 | 状态: 分析完成 --- ## 1. 需求概述 在 u-tabs 最后一个 Tab 新增「历史会话」功能,浏览和管理 Claude Code 所有项目的历史会话记录。 ## 2. 核心需求 ### 2.1 新增 HISTORY Tab - 作为最后一个 Tab 追加到现有 Tab 栏(CORE / LAB / TOOLS / ME / **HISTORY**) - 切换到该 Tab 时展示三栏布局(其他 Tab 保持原有两栏不变) ### 2.2 三栏布局 ``` ┌──────────────┬────────────────────┬──────────────────────────┐ │ 项目目录 │ 会话列表 │ 会话详情 │ │ │ │ │ │ ▸ E:/wk-flux │ ▸ 05-16 01:27 │ 标题: 龙享花API对接 │ │ E:/wk-lab │ 05-15 23:01 │ 时间: 05-16 01:27 │ │ E:/wk-oth │ 05-14 15:30 │ 目录: E:/wk-flux │ │ E:/wk-abc │ │ 消息: 94条 │ │ ... │ │ 摘要: 整理龙享花平台API │ │ │ │ 文档并编写测试代码... │ └──────────────┴────────────────────┴──────────────────────────┘ ``` | 栏位 | 内容 | 交互 | |------|------|------| | 左栏 | 按 `cwd` 分组的项目目录列表 | 上下键切换目录 | | 中栏 | 当前目录下的会话列表(时间+标题) | 上下键切换会话 | | 右栏 | 选中会话的详情(标题/时间/消息数/AI摘要) | 只读展示 | ### 2.3 恢复会话 - 按 `Enter` 在对应项目目录下执行 `claude -r ` 恢复会话 - 通过 `wt.exe` 打开新 Tab 执行(与现有启动逻辑一致) ### 2.4 AI 摘要生成 - 会话标题和摘要通过 AI 分析生成(`claude -p` 非交互模式) - 生成结果缓存到本地(`~/.u-tabs/session-cache.json`),避免重复分析 - 分层策略: 1. 优先用已有的 `awaySummary`(Claude 自动生成的离开摘要) 2. 次选 `customTitle` + 首条用户消息 + 消息数 3. 用户按 `s` 键触发 AI 按需生成,结果缓存 --- ## 3. 数据源分析 ### 3.1 存储位置 ``` ~/.claude/projects/<编码目录>/.jsonl ``` 编码规则:`E:\wk-lab\u-tabs` → `E--wk-lab-u-tabs` ### 3.2 JSONL 关键 entry 类型 | type | 关键字段 | 用途 | |------|----------|------| | `custom-title` | `customTitle` | 会话标题 | | `user` | `message.content` | 用户消息(string 或 text block 数组) | | `assistant` | `message.content` | 助手回复 | | `system` (subtype=`away_summary`) | `content` | AI 自动生成的离开摘要 | | 大多数 entry | `cwd`, `timestamp`, `sessionId`, `gitBranch` | 通用元数据 | ### 3.3 扫描策略 **流式扫描,不全量加载:** - `bufio.Scanner` 逐行读取,`bytes.Contains` 预过滤避免无用 JSON 解析 - 超过 2000 行的文件提前终止(元数据通常在前 50-100 行) - 缓存机制:`~/.u-tabs/session-cache.json` 记录每个 session 的 modTime + 元数据 - 只重新读取 modTime 变化的文件 - 后续启动从缓存加载,接近即时完成 --- ## 4. 技术方案 ### 4.1 现有代码结构 ``` internal/ ├── app.go # Model, Update, View, 启动逻辑 (405行) ├── workspace.go # Workspace/Group 结构体, 运行时状态 ├── config.go # YAML 配置加载 └── style/style.go # Tokyo Night 样式 ``` ### 4.2 文件变更清单 | 文件 | 操作 | 职责 | |------|------|------| | `internal/history.go` | **新建** | Session/ProjectDir/HistoryState 结构体、JSONL 扫描器、缓存、三栏渲染、按键处理、会话恢复 | | `internal/app.go` | **修改** | Model 增加 `history` 字段、Update/View 分支 HISTORY 逻辑、Tab 栏追加 HISTORY、ScanCompleteMsg 处理 | | `internal/style/style.go` | **修改** | GroupStyles 增加 HISTORY、会话列表/详情专用样式 | | `internal/workspace.go` | 不变 | — | | `internal/config.go` | 不变 | — | | `main.go` | 不变 | — | ### 4.3 核心结构体 ```go // Session — 单个会话的元数据 type Session struct { ID string // UUID (文件名) CustomTitle string // customTitle 字段 Cwd string // 实际工作目录 StartTime time.Time // 首条 timestamp EndTime time.Time // 末条 timestamp MsgCount int // user + assistant 行数 FirstMsg string // 首条用户消息 (截断) AwaySummary string // away_summary 系统摘要 } // ProjectDir — 按目录分组的会话 type ProjectDir struct { Dir string // 完整路径 Sessions []*Session // 按时间倒序 } // HistoryState — HISTORY Tab 视图状态 type HistoryState struct { Projects []*ProjectDir DirCursor int // 左栏光标 SessCursor int // 中栏光标 FocusPanel int // 0=左栏 1=中栏 Loaded bool Scanning bool } ``` ### 4.4 Model 修改 ```go type Model struct { // ... 现有字段不变 ... history HistoryState // 新增:HISTORY Tab 状态 } ``` HISTORY Tab 判断:`m.activeGroup == len(Groups)`(最后一个位置)。 ### 4.5 Tab 切换改动 - 现有:`% len(Groups)` 循环 - 改为:`% (len(Groups) + 1)` 包含 HISTORY - 新增 `5` 键直接跳转 HISTORY ### 4.6 三栏渲染 ``` 可用宽度 = terminal width - 2 (分隔符) 左栏 (目录): 20% 宽度, 最小 20 字符 中栏 (会话): 40% 宽度, 最小 30 字符 右栏 (详情): 剩余宽度, 最小 30 字符 ``` ### 4.7 异步扫描 ```go type ScanCompleteMsg struct { Projects []*ProjectDir } // 首次进入 HISTORY Tab 时触发 func ScanSessionsCmd() tea.Cmd { return func() tea.Msg { return ScanCompleteMsg{Projects: scanAllProjects()} } } ``` 扫描期间显示 "scanning..." 占位。 ### 4.8 会话恢复 复用现有 `encodePSCommand` + `wt.exe` 模式,改用 `claude -r `: ```go func resumeSession(s *Session) { script := fmt.Sprintf(`cd "%s"; claude -r %s`, s.Cwd, s.ID) encoded := encodePSCommand(script) exec.Command("wt.exe", "-w", "0", "-d", s.Cwd, "--tabColor", randomColor, "pwsh", "-NoExit", "-EncodedCommand", encoded).Start() } ``` ### 4.9 HISTORY Tab 按键 | 键 | 动作 | |----|------| | `j`/`down` | 当前面板光标下移 | | `k`/`up` | 当前面板光标上移 | | `tab`/`right`/`l` | 焦点切到中栏 | | `shift+tab`/`left`/`h` | 焦点切到左栏 | | `enter` | 恢复选中会话 | | `s` | AI 生成摘要(按需) | | `5` | 从其他 Tab 跳转到 HISTORY | | `q`/`ctrl+c` | 退出 | --- ## 5. 实现阶段 | 阶段 | 内容 | 涉及文件 | |------|------|----------| | P1 数据层 | Session 结构体 + JSONL 流式扫描器 + 缓存 | `history.go` | | P2 集成 | Model 扩展 + Update 分支 + Tab 栏扩展 | `app.go` | | P3 渲染 | 三栏布局 + 目录/会话/详情面板 | `history.go` | | P4 动作 | 会话恢复 + AI 摘要按需生成 | `history.go`, `app.go` | | P5 样式 | HISTORY Tab 样式 + 会话专用样式 | `style.go` | --- ## 6. 风险与对策 | 风险 | 对策 | |------|------| | 大文件 (1MB+) 扫描慢 | 流式扫描 + 2000 行截断 + modTime 缓存 | | 项目目录过多 | 左栏滚动显示,按最近活跃排序 | | `claude -p` 生成摘要慢 | 按需触发(`s` 键),非自动;结果缓存 | | 窄终端三栏挤压 | 定义面板最小宽度,不足时降级为两栏 | --- ## 7. 验证标准 1. HISTORY Tab 出现在 Tab 栏末尾,样式与其他 Tab 一致 2. 左栏列出所有有会话的项目目录,按路径排序 3. 选中目录后中栏显示该目录下所有会话,按时间倒序 4. 选中会话后右栏显示完整详情 5. `Enter` 键在正确目录下通过 `wt.exe` 恢复会话 6. `s` 键触发 AI 摘要生成,结果写入缓存 7. 其他 Tab 功能不受影响 8. 首次进入扫描显示 loading,二次进入从缓存加载