新增: u-tabs 初始版本
Go TUI 项目启动器,基于 bubbletea v2 + lipgloss v2。 支持分组 Tab、多选启动、编号跳转、Windows Terminal 集成。
This commit is contained in:
245
docs/2026-05-16-备忘录-历史会话功能.md
Normal file
245
docs/2026-05-16-备忘录-历史会话功能.md
Normal file
@@ -0,0 +1,245 @@
|
||||
# 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 <session-id>` 恢复会话
|
||||
- 通过 `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/<编码目录>/<session-uuid>.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 <session-id>`:
|
||||
|
||||
```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,二次进入从缓存加载
|
||||
Reference in New Issue
Block a user