🔍 上下文恢复真相揭秘

⚠️ 数据库统计的 tokens 可能不准确
🚨

核心真相

数据库记录的消息 ≠ Claude 实际加载的上下文
两者是完全独立的系统!

🔍 深度分析:代码到底做了什么?

// feishu-ws.js:385 - 调用 Claude
await queryClaude(userText, {
sessionId: session.claude_session_id, ← 只传了 session_id
cwd: session.project_path
}, writer);
// claude-cli.js:47 - 构建命令参数
if (sessionId) {
args.push('--resume=' + sessionId); ← 只加了 --resume 参数
}
args.push(command); ← 只传了当前消息
// claude-cli.js:143 - 实际执行的命令
spawn('claude', [
'-p',
'--resume=session-abc123', ← 依赖 Claude CLI 自己恢复
'--output-format', 'stream-json',
'当前用户消息' ← 没有传历史消息!
], { cwd: '/home/event' });

🎯 关键发现

1️⃣ 代码从未读取数据库的历史消息

检查整个代码库,没有任何地方feishu_message_log 表读取历史消息并传递给 Claude。

数据库的 feishu_message_log 表只是日志记录,用于审计和统计,不参与上下文恢复。

2️⃣ 完全依赖 Claude CLI 的 --resume 机制

当我们传递 --resume=session-abc123 时,Claude CLI 会:

  • Anthropic 远程 API 获取该 session_id 的完整对话历史
  • 或者从 本地缓存(位置未知)加载会话状态
  • 自动拼接历史消息 + 当前消息,一起发送给 API

问题:如果 Claude CLI 的会话过期/清理,--resume 会静默失败,导致丢失上下文!

3️⃣ 数据库统计的 tokens 只是估算,不是真实值

我们统计的"累积字符数 ÷ 3"只是粗略估算,实际情况:

  • Claude 实际加载的上下文包含系统提示词(500-1000 tokens)
  • 包含工具调用的完整记录(每次 50-200 tokens)
  • 包含错误重试的临时消息
  • 可能包含内部推理过程(thinking blocks)

真实 tokens 可能是数据库估算的 2-3 倍!

📊 两个独立系统的对比

💾 数据库系统

  • 表:feishu_message_log
  • 存储:用户消息 + 机器人回复
  • 用途:审计、统计、UI 展示
  • 局限:只记录文本,不含系统提示
  • 生命周期:永久存储(直到手动删除)

🤖 Claude API 会话

  • 存储:Anthropic 远程服务器
  • 内容:完整对话历史 + 工具调用
  • 用途:上下文恢复、记忆管理
  • 特性:包含系统提示、thinking blocks
  • 生命周期:未知(可能有过期机制)

上下文恢复流程图

数据库
feishu_message_log
(只做日志)
不传递
Claude CLI
只传 session_id
我们的代码
--resume=session-abc123
Claude API
自己恢复历史
(远程存储)
完整上下文
历史 + 当前消息

⚠️ 潜在问题

❌ 可能出现的问题

  • Claude API 会话过期(时间未知)
  • --resume 失败但没有错误提示
  • 用户以为有上下文,实际已丢失
  • 数据库有记录,Claude 已忘记
  • 无法验证上下文是否真的恢复

✅ 当前可以确定的

  • Claude CLI 的 --resume 机制确实存在
  • 数据库日志系统运行正常
  • session_id 正确传递和存储
  • 短期内(几小时)恢复有效
  • YOLO 模式正常工作

💡 改进建议

方案 1:验证机制(推荐)

  1. 在每次 --resume 前,先测试会话是否有效(发送 "status" 命令)
  2. 如果会话失效,清空数据库的 claude_session_id,重新创建
  3. 给用户明确提示:"会话已过期,重新开始对话"

方案 2:手动上下文管理(复杂)

  1. 从数据库读取最近 N 轮对话(如最近 10 轮)
  2. 手动拼接成 messages 数组
  3. 不使用 --resume,直接传递完整历史
  4. 优点:完全掌控上下文,缺点:增加复杂度

方案 3:混合模式(平衡)

  1. 优先使用 --resume(快速、简单)
  2. 定期(如每 10 轮)验证上下文有效性
  3. 如果发现不一致,切换到手动上下文管理
  4. 在 UI 显示"上下文健康度"指标
🎯

最终结论

数据库统计的 tokens 不准确
实际上下文可能是估算值的 2-3 倍

--resume 机制是黑盒
完全依赖 Claude API 的远程存储

需要增加验证机制
确保用户感知到的上下文与实际一致