#!/usr/bin/env node /** * PreCompact Hook - 上下文压缩前自动保存会话状态 * 将当前任务摘要写入 ~/.claude/session-state/handoff.json */ const fs = require('fs'); const path = require('path'); const CLAUDE_ROOT = require('./lib/root.js'); const readStdin = require('./lib/read-stdin.js'); const SESSION_STATE_DIR = path.join(CLAUDE_ROOT, 'session-state'); const HANDOFF_PATH = path.join(SESSION_STATE_DIR, 'handoff.json'); (async () => { try { let hookData = {}; try { hookData = await readStdin(); } catch (_) {} // 确保目录存在 if (!fs.existsSync(SESSION_STATE_DIR)) { fs.mkdirSync(SESSION_STATE_DIR, { recursive: true }); } // 构造 handoff 数据 const handoff = { timestamp: new Date().toISOString(), session_id: hookData.session_id || `session-${Date.now()}`, context_hint: '会话因上下文压缩中断,以下是压缩前的状态摘要', conversation_summary: hookData.transcript_summary || '(由 PreCompact hook 自动捕获)', tool_call_count: hookData.tool_call_count || 'unknown', working_directory: process.cwd(), note: '此文件由 pre-compact-handoff.js 自动生成,SessionStart 时自动读取并注入恢复上下文' }; fs.writeFileSync(HANDOFF_PATH, JSON.stringify(handoff, null, 2), 'utf8'); // 同时重置 heartbeat 计数器(compact 相当于新会话起点) const heartbeatFile = path.join(CLAUDE_ROOT, 'debug', 'session-heartbeat.json'); if (fs.existsSync(heartbeatFile)) { fs.writeFileSync(heartbeatFile, JSON.stringify({ count: 0, lastActivity: Date.now(), notified: [] }), 'utf8'); } console.log(JSON.stringify({ continue: true, suppressOutput: false, systemMessage: '[PRE_COMPACT] 上下文即将压缩。handoff.json 已写入。请在压缩前将当前任务的关键决策和待完成步骤总结到 handoff 记录中。' })); } catch { // fail-open console.log(JSON.stringify({ continue: true, suppressOutput: true })); } process.exit(0); })();