跳转至

Deep Dive | src/commands/insights.ts 3200 行 — /insights 用量分析报告

重要性:⭐⭐⭐(/insights 命令——全 session 扫描 + 统计 + HTML 报告生成) 真实位置src/commands/insights.ts3200 行角色:扫描所有 session 日志、提取元数据 / facets(通过 API)、聚合数据、生成 HTML 用量报告 关联topics/deep-dive-session-storage.md(session 持久化)、topics/deep-dive-claude-api.md(facets 提取调用)


1. 文件全景

insights.ts (3200 行)
├── 行 1-50    :imports + 2 个 model helper
│   ├── getAnalysisModel() —— facets 提取用的模型
│   └── getInsightsModel() —— insight 生成用的模型
├── 行 50-420  :4 个 type 定义
│   ├── RemoteHostInfo
│   ├── SessionMeta (行 228)
│   ├── SessionFacets (行 260)
│   └── AggregatedData (行 275)
├── 行 420-470 :3 个路径 helper + 1 个 prompt
│   ├── getDataDir / getFacetsDir / getSessionMetaDir
│   └── FACET_EXTRACTION_PROMPT (行 430, ~30 行)
├── 行 462-940 :单 session 分析
│   ├── getLanguageFromPath (行 462)
│   ├── extractToolStats (行 467, ~260 行) — 工具使用统计
│   ├── hasValidDates (行 730)
│   ├── logToSessionMeta (行 737, ~75 行) — 提取 session 元数据
│   ├── deduplicateSessionBranches (行 812)
│   ├── formatTranscriptForFacets (行 831, ~40 行)
│   ├── SUMMARIZE_CHUNK_PROMPT (行 870, ~10 行)
│   ├── summarizeTranscriptChunk (行 881, ~25 行)
│   └── formatTranscriptWithSummarization (行 906, ~35 行)
├── 行 941-1000:缓存层
│   ├── loadCachedFacets (行 941)
│   ├── saveFacets (行 963)
│   ├── loadCachedSessionMeta (行 976)
│   └── saveSessionMeta (行 988)
├── 行 1001-1062:extractFacetsFromAPI (行 1001, ~60 行) — 调 API 提取 facets
├── 行 1062-1145:detectMultiClauding (行 1062, ~80 行) — 检测多 claude 实例
├── 行 1145-1330:aggregateData (行 1145, ~180 行) — 聚合所有 sessions
├── 行 1329-1610:Insight section
│   ├── InsightSection type (行 1329, ~170 行)
│   ├── InsightResults type (行 1497, ~75 行)
│   ├── generateSectionInsight (行 1572, ~40 行)
│   └── generateParallelInsights (行 1612, ~190 行) — 并行生成
├── 行 1610-1947:HTML 生成 helpers
│   ├── escapeHtmlWithBold (行 1801)
│   ├── SATISFACTION_ORDER / OUTCOME_ORDER
│   ├── generateBarChart (行 1824, ~40 行)
│   ├── generateResponseTimeHistogram (行 1863, ~40 行)
│   ├── generateTimeOfDayChart (行 1902, ~40 行)
│   └── getHourCountsJson (行 1939)
├── 行 1947-2655:**generateHtmlReport (行 1947, ~700 行)** — 完整 HTML 报告
├── 行 2655-2796:导出
│   ├── InsightsExport type (行 2655)
│   ├── buildExportData (行 2679, ~65 行)
│   └── LiteSessionInfo type (行 2743)
└── 行 2755-3200:generateUsageReport (行 2796, ~230 行) + safeEntries + safeKeys + isValidSessionFacets

2. 2 个 Model 助手

function getAnalysisModel(): string { ... }  // facets 提取模型
function getInsightsModel(): string { ... }  // insight 生成模型

2 个模型: - getAnalysisModel —— 用于"分析 session 提取结构化 facets"(快模型) - getInsightsModel —— 用于"从 facets 生成可读 insight"(可能更大模型)


3. 4 个核心类型

type SessionMeta = { ... }      // 单 session 元数据
type SessionFacets = { ... }    // LLM 提取的结构化 facets
type AggregatedData = { ... }   // 聚合后的数据
type InsightSection = { ... }   // 报告 section
type InsightResults = { ... }   // 多 sections 结果

数据流

session log → SessionMeta + SessionFacets → AggregatedData → InsightSections → HTML


4. extractToolStats — 260 行(行 467)

function extractToolStats(log: LogOption): ToolStats {
  // 行 467
  // 遍历 messages,统计每个 tool 的:
  // - 调用次数
  // - 成功 / 失败次数
  // - 平均响应时间
  // - 关联文件
}

单 session 工具统计——260 行反映"工具分析"是核心。


5. logToSessionMeta — 75 行(行 737)

function logToSessionMeta(log: LogOption): SessionMeta {
  // 行 737
  // 提取 session 元数据:起始时间、消息数、模型、文件、用户文本
}

Session → Meta——SessionMeta 是"轻量级"摘要。


6. formatTranscriptForFacets + formatTranscriptWithSummarization

2 个 transcript 格式化函数: - formatTranscriptForFacets —— 直接格式化(短 transcript) - formatTranscriptWithSummarization —— 长 transcript 先 summarize(调 API)

为什么 2 个: - 短 transcript:直接发(节省 API 调用) - 长 transcript:先 Haiku summarize,再发(避免超 token)


7. extractFacetsFromAPI — 60 行(行 1001)

async function extractFacetsFromAPI(log: LogOption, model: string): Promise<SessionFacets> {
  // 行 1001
  // 1. 格式化 transcript
  // 2. 调模型
  // 3. 解析 JSON facets
  // 4. 校验
}

API 提取 facets —— 用 FACET_EXTRACTION_PROMPT 让模型返回结构化 JSON。

Facets 提取的字段(推测): - 主要任务 - 用户满意度 - 结果(成功/失败/部分) - 工具使用模式 - 用户/Claude 比例


8. detectMultiClauding — 80 行(行 1062)

export function detectMultiClauding(sessions: SessionMeta[]): ... {
  // 行 1062
  // 检测多 claude 实例并行运行
}

多 Claude 检测 —— 当用户并行多个 claude 时,识别这种模式。


9. aggregateData — 180 行(行 1145)

function aggregateData(sessions: SessionMeta[], facets: SessionFacets[]): AggregatedData {
  // 行 1145
  // 1. 累计工具调用
  // 2. 时间分布
  // 3. 模型使用
  // 4. 任务类型分布
  // 5. 多 claude 标志
}

聚合 —— 多个 session → 整体统计。


10. Insight 生成

10.1 generateSectionInsight — 40 行(行 1572)

async function generateSectionInsight(section: InsightSection, data: AggregatedData): Promise<string> {
  // 行 1572
  // 单 section 生成可读文字
}

单 section —— 一个 insight section → 一段文字。

10.2 generateParallelInsights — 190 行(行 1612)

async function generateParallelInsights(sections: InsightSection[], data: AggregatedData): Promise<InsightResults> {
  // 行 1612
  // 并行生成所有 sections
}

并行 —— Promise.all 同时生成多个 section 的 insight。


11. HTML 报告生成

11.1 4 个 chart helper

function generateBarChart(...)             // 柱状图(SVG)
function generateResponseTimeHistogram(...) // 响应时间直方图
function generateTimeOfDayChart(...)        // 时间分布
function getHourCountsJson(...)             // JSON 数据

SVG chart helpers —— 不依赖外部库,手写 SVG

11.2 generateHtmlReport — 700 行(行 1947-2655)

function generateHtmlReport(
  data: AggregatedData,
  insights: InsightResults,
  exportData: InsightsExport,
): string {
  // 行 1947
  // 完整 HTML 报告
  // 含 CSS + SVG + 数据可视化
}

700 行——单文件 700 行 HTML 生成: - 顶部摘要 - 多个 sections - 多个 charts (SVG) - 数据表 - 完整 CSS

自包含——单 HTML 文件,无外部依赖。


12. generateUsageReport — 230 行(行 2796)

export async function generateUsageReport(options?: {
  daysBack?: number;
  format?: 'html' | 'json';
  outputPath?: string;
}): Promise<...> {
  // 1. scanAllSessions()
  // 2. 提取 facets (并行)
  // 3. 聚合
  // 4. 生成 insight
  // 5. 输出 HTML/JSON
}

主入口 —— /insights 命令调它。


13. 关键设计模式

13.1 3 阶段:scan → extract → aggregate → generate

4 阶段管道: 1. Scan —— 读所有 session log 文件 2. Extract —— 调 API 提取 facets 3. Aggregate —— 聚合成统计 4. Generate —— 输出 HTML/JSON

13.2 缓存层(4 个 cache)

loadCachedFacets / saveFacets
loadCachedSessionMeta / saveSessionMeta

避免重复 API 调用 —— 第二次跑 /insights 毫秒级返回。

13.3 Long transcript 处理

formatTranscriptWithSummarization —— 长 transcript 先 Haiku summarize。

节省 token——避免一次 API 调用超过上下文窗口。

13.4 并行生成 insight

generateParallelInsights —— Promise.all 并行。

多 section 报告从 ~10s 降到 ~2s

13.5 SVG charts 无外部库

generateBarChart / generateHistogram —— 手写 SVG。

单 HTML 文件——无 CDN 依赖。

13.6 Facets 提取 = "AI 总结 session"

FACET_EXTRACTION_PROMPT —— LLM 提取结构化字段

LLM-as-classifier 模式

13.7 安全 / 隐私

t('F') (isValidSessionFacets) 校验 facets 结构 —— 防止恶意 log 注入

13.8 LiteSessionInfo 模式

type LiteSessionInfo = { ... }  // session 列表的轻量数据

减少内存 —— 不存完整 log,只存摘要。


14. 复杂度分析

维度 数字
总行数 3200
阶段 4 (scan/extract/aggregate/generate)
Cache 函数 4 (load/save × 2)
Chart helpers 4
generateHtmlReport 700 行
模型调用 2 (analysis + insights)

15. 性能特征

15.1 首次跑

  • 扫描:~100ms-1s(取决于 session 数)
  • Facets 提取:~30-60s(每个 session 调 API)
  • 聚合:~100ms
  • Insight 生成:~10-20s(多个 section 并行)
  • HTML 生成:~100ms
  • 总计 ~1-2min(100 sessions)

15.2 第二次跑(cache 命中)

  • 全部从 cache 读
  • ~1-2s 总时间

15.3 优化

  • 4 层 cache
  • 并行 API 调用
  • Haiku summarize 节省 token
  • 轻量级 session 索引

16. 与其他文件的关系

insights.ts
  ├──→ sessionStorage.ts (读 session log)
  ├──→ claude.ts (调 API 提取 facets / insight)
  ├──→ analytics/ (telemetry: 用户跑 /insights)
  └──→ report.html (输出)

/insights 是"自省工具"——用户用它理解自己的使用模式。


17. 关键洞察

17.1 LLM-as-classifier = "用 LLM 提取结构化字段"

FACET_EXTRACTION_PROMPT 让 LLM 输出 JSON,比正则/规则强 100 倍

17.2 Cache 是必需

不 cache 会每次跑都重新分析所有 session——慢得不可用。

17.3 长 transcript 分块 summarize

避免单次 API 超 token 限制——实际工程考量

17.4 SVG charts 自包含

不用 Chart.js / D3 —— 单 HTML 文件可分享。

17.5 4 阶段管道清晰

scan → extract → aggregate → generate —— 每阶段可独立测试

17.6 isValidSessionFacets 是安全

unknown → SessionFacets —— zod-like 校验防止恶意 log。


18. 阅读建议

  1. 看 4 个 type(行 228-420)—— 数据模型
  2. 看 extractToolStats(行 467)—— 工具统计
  3. 看 extractFacetsFromAPI(行 1001)—— LLM 提取
  4. 看 aggregateData(行 1145)—— 聚合
  5. 跳看 generateHtmlReport(行 1947)—— 700 行 HTML
  6. 看 generateUsageReport(行 2796)—— 入口

19. 与其他深度拆解的关系

文件 关系
sessionStorage.ts 读 session log
claude.ts 调 API
analytics/ telemetry
report.html 输出(运行时生成)

20. 阅读清单

  1. ✅ 看 4 个 type(行 228-420)
  2. ✅ 看 extractToolStats(行 467)
  3. ✅ 看 extractFacetsFromAPI(行 1001)
  4. ✅ 看 aggregateData(行 1145)
  5. ✅ 看 generateUsageReport(行 2796)
  6. 📌 跑 /insights 看实际报告

21. 练习任务

  1. 数 chart helpers(grep)—— 4 个 SVG 生成
  2. 数 cache 函数(grep)—— 4 个
  3. 画 4 阶段管道 —— scan → extract → aggregate → generate
  4. 手写迷你 insights(~50 行)—— 1 个 chart + 1 个 summary
  5. 思考:除了 LLM 提取 facets,还有什么方式能从 log 提取模式?