Skip to content

历史记录 (history.ts)

history.ts (~476 行) 实现会话历史的持久化存储与检索,使用 异步生成器 模式高效读取大量历史记录。

数据结构

typescript
// 序列化到磁盘的历史条目
type LogEntry = {
  display: string                    // 非 displayText
  pastedContents: Record<number, StoredPastedContent>  // 复数,Record 类型
  timestamp: number
  project: string                    // 必需(非可选)
  sessionId?: string                 // 可选(非必需)
}

// 读取后的历史条目(来自 src/utils/config.ts)
interface HistoryEntry {
  display: string                    // 非 displayText
  pastedContents: Record<number, PastedContent>  // 不继承 LogEntry
}

// 粘贴内容存储类型(单一对象,非联合类型)
type StoredPastedContent = {
  id: number
  type: 'text' | 'image'
  content?: string                   // 内联内容(小内容)
  contentHash?: string               // 哈希引用(大内容)
  mediaType?: string
  filename?: string
}

核心 API

getHistory() — 异步生成器读取

typescript
// 无 project 参数(项目过滤在内部通过 getProjectRoot() 实现)
async function* getHistory(): AsyncGenerator<HistoryEntry> {
  const currentProject = getProjectRoot()
  const currentSession = getSessionId()

  for await (const entry of makeLogEntryReader()) {
    if (entry.project !== currentProject) continue
    // 当前会话条目优先输出,其他会话条目延后
    yield await logEntryToHistoryEntry(entry)
  }
}

addToHistory() — 写入历史

typescript
// 同步函数(非 async),参数为 HistoryEntry | string(非 LogEntry)
function addToHistory(command: HistoryEntry | string): void {
  // 跳过 Tungsten 会话
  if (isEnvTruthy(process.env.CLAUDE_CODE_SKIP_PROMPT_HISTORY)) return

  // 内部异步刷新到磁盘
}

// 其他写入函数:
// addToPromptHistory(entry: HistoryEntry) — 写入提示历史(处理粘贴内容哈希)
// immediateFlushHistory() — 立即刷新历史

去重与显示

历史记录按显示文本去重,确保用户看到的历史列表无重复项。去重逻辑嵌入在历史加载流程内部。

存储位置

~/.claude/
├── history.jsonl      # 单个 JSONL 文件(非按月份分目录)
└── paste-store/       # 大粘贴内容存储
    ├── abc123.txt     # 按哈希命名
    └── ...