Files
u-tabs/docs/2026-05-16-备忘录-历史会话功能.md
绝尘 a027fe1703 新增: u-tabs 初始版本
Go TUI 项目启动器,基于 bubbletea v2 + lipgloss v2。
支持分组 Tab、多选启动、编号跳转、Windows Terminal 集成。
2026-05-16 21:01:03 +08:00

8.1 KiB
Raw Permalink Blame History

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. 优先用已有的 awaySummaryClaude 自动生成的离开摘要)
    2. 次选 customTitle + 首条用户消息 + 消息数
    3. 用户按 s 键触发 AI 按需生成,结果缓存

3. 数据源分析

3.1 存储位置

~/.claude/projects/<编码目录>/<session-uuid>.jsonl

编码规则:E:\wk-lab\u-tabsE--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 核心结构体

// 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 修改

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 异步扫描

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>:

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二次进入从缓存加载