问题描述
功能 1:普通模式缺少 Block 级别 Session Summary
当前 Unified Block Model 已经为每个 Block 存储 session_stats 字段,但普通模式(normal mode)的会话统计信息不完整。
当前行为:
- Geek/Evolution 模式:显示完整的 SessionSummary(duration, tokens, tools, cost)
- 普通模式:仅显示基础 duration,缺少 token 统计、工具调用详情等
期望行为:
- 普通模式也应显示完整的 SessionSummary,包括:
- 思考时间 (thinking_duration_ms)
- 生成时间 (generation_duration_ms)
- Token 使用量 (input/output tokens)
- 工具调用统计 (tools_used, tool_call_count)
功能 2:Geek 与 Evolution 模式 CC Session 隔离验证
后端已实现独立的 CC Session ID 生成逻辑,需要验证前端是否正确区分和显示两个模式的会话统计。
当前实现:
- Geek Mode:
UUID v5(null_namespace, "conversation_<id>")
- Evolution Mode:
UUID v5(user_namespace, "evolution_<id>")
需要验证:
- 前端 SessionSummaryPanel 是否正确区分两个模式的统计
- 模式切换时是否正确加载对应的 session stats
解决方案
架构原则:统计收集下沉到 LLM 层
❌ 错误方案:每个 Agent 重复实现 SessionStatsProvider
// 不要这样做
type MemoParrot struct { stats *SessionStats } // 重复实现
type ScheduleParrot struct { stats *SessionStats } // 重复实现
type AmazingParrot struct { stats *SessionStats } // 重复实现
✅ 正确方案:LLM Client 层统一收集,Agent 直接获取
// LLM 层统一收集
type LLMClient struct {
stats *LLMCallStats // 一次调用完整的统计
}
// Agent 从 LLM 获取
func (p *MemoParrot) GetSessionStats() *SessionStats {
return p.llm.GetStats() // 直接使用 LLM 层的统计
}
Phase 1:LLM 层统一统计收集
-
扩展 ai/core/llm/ 接口
- 添加
GetStats() 方法到 LLMClient
- 记录每次 LLM 调用的:
- input/output/cache tokens
- thinking 时间(首字延迟)
- generation 时间(流式输出总时长)
-
定义统一的 LLM 统计结构
type LLMCallStats struct {
InputTokens int
OutputTokens int
CacheWriteTokens int
CacheReadTokens int
ThinkingDurationMs int64 // 首字延迟
GenerationDurationMs int64 // 流式输出总时长
StartTime time.Time
EndTime time.Time
}
-
为所有 Parrot Agent 添加统一的 SessionStatsProvider 实现
- 在
ai/agent/base_parrot.go 或 types.go 中提供基础实现
- 各 Agent 组合 LLM stats + tool stats
Phase 2:验证 CC Session 隔离
-
验证后端 SessionID 生成
- 确认 Geek 和 Evolution 使用不同的 namespace
- 确认生成的 SessionID 不会冲突
-
前端显示验证
- 检查
SessionSummaryPanel.tsx 是否正确处理两种模式
- 确保 Block 的
cc_session_id 字段正确存储和读取
验收标准
技术细节
架构分层
┌─────────────────────────────────────────────────────────┐
│ Parrot Agents │
│ MemoParrot | ScheduleParrot | AmazingParrot │
│ │ │ │ │
│ └─────────────┴──────────────────┘ │
│ │ │
│ GetSessionStats() { │
│ return llm.GetStats() + toolStats │
│ } │
├─────────────────────────────────────────────────────────┤
│ LLM Layer │
│ ┌─────────────────────────────────────────────────┐ │
│ │ LLMClient.GetStats() │ │
│ │ - InputTokens, OutputTokens │ │
│ │ - ThinkingDurationMs (首字延迟) │ │
│ │ - GenerationDurationMs (流式总时长) │ │
│ └─────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ SessionStatsProvider (Interface) │
│ GetSessionStats() *SessionStats │
└─────────────────────────────────────────────────────────┘
相关文件
LLM 层(核心修改):
ai/core/llm/client.go - 添加统计收集
ai/core/llm/stream.go - 记录流式时间
ai/core/llm/types.go - LLMCallStats 定义
Agent 层(组合实现):
ai/agent/base_parrot.go - 提供基础 SessionStatsProvider 实现(新建)
ai/agent/types.go - 接口定义
Handler 层(无需修改,已支持):
server/router/api/v1/ai/handler.go:669-706
前端:
web/src/components/AIChat/SessionSummaryPanel.tsx
接口定义
// LLM 层统计
type LLMCallStats struct {
InputTokens int
OutputTokens int
CacheWriteTokens int
CacheReadTokens int
ThinkingDurationMs int64 // 首字时间
GenerationDurationMs int64 // 总生成时间
StartTime time.Time
EndTime time.Time
}
type LLMClient interface {
// 现有方法...
GetStats() *LLMCallStats
ResetStats() // 开始新一轮对话时重置
}
// Agent 层组合
type BaseParrot struct {
llm LLMClient
tools []Tool
}
func (b *BaseParrot) GetSessionStats() *SessionStats {
llmStats := b.llm.GetStats()
return &SessionStats{
InputTokens: llmStats.InputTokens,
OutputTokens: llmStats.OutputTokens,
CacheWriteTokens: llmStats.CacheWriteTokens,
CacheReadTokens: llmStats.CacheReadTokens,
ThinkingDurationMs: llmStats.ThinkingDurationMs,
GenerationDurationMs: llmStats.GenerationDurationMs,
TotalDurationMs: llmStats.EndTime.Sub(llmStats.StartTime).Milliseconds(),
ToolCallCount: b.countToolCalls(),
ToolsUsed: b.getToolsUsed(),
}
}
优先级
P1 - 功能增强(用户体验提升)+ 架构优化
Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com
问题描述
功能 1:普通模式缺少 Block 级别 Session Summary
当前 Unified Block Model 已经为每个 Block 存储
session_stats字段,但普通模式(normal mode)的会话统计信息不完整。当前行为:
期望行为:
功能 2:Geek 与 Evolution 模式 CC Session 隔离验证
后端已实现独立的 CC Session ID 生成逻辑,需要验证前端是否正确区分和显示两个模式的会话统计。
当前实现:
UUID v5(null_namespace, "conversation_<id>")UUID v5(user_namespace, "evolution_<id>")需要验证:
解决方案
架构原则:统计收集下沉到 LLM 层
❌ 错误方案:每个 Agent 重复实现 SessionStatsProvider
✅ 正确方案:LLM Client 层统一收集,Agent 直接获取
Phase 1:LLM 层统一统计收集
扩展
ai/core/llm/接口GetStats()方法到 LLMClient定义统一的 LLM 统计结构
为所有 Parrot Agent 添加统一的 SessionStatsProvider 实现
ai/agent/base_parrot.go或types.go中提供基础实现Phase 2:验证 CC Session 隔离
验证后端 SessionID 生成
前端显示验证
SessionSummaryPanel.tsx是否正确处理两种模式cc_session_id字段正确存储和读取验收标准
make test-ai通过pnpm lint通过技术细节
架构分层
相关文件
LLM 层(核心修改):
ai/core/llm/client.go- 添加统计收集ai/core/llm/stream.go- 记录流式时间ai/core/llm/types.go- LLMCallStats 定义Agent 层(组合实现):
ai/agent/base_parrot.go- 提供基础 SessionStatsProvider 实现(新建)ai/agent/types.go- 接口定义Handler 层(无需修改,已支持):
server/router/api/v1/ai/handler.go:669-706前端:
web/src/components/AIChat/SessionSummaryPanel.tsx接口定义
优先级
P1 - 功能增强(用户体验提升)+ 架构优化
Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com