Initial commit
This commit is contained in:
120
hooks/pre_compact.py
Executable file
120
hooks/pre_compact.py
Executable file
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
try:
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
except ImportError:
|
||||
pass # dotenv is optional
|
||||
|
||||
|
||||
def log_pre_compact(input_data):
|
||||
"""Log pre-compact event to logs directory."""
|
||||
# Ensure logs directory exists
|
||||
log_dir = Path(".claude/logs")
|
||||
log_dir.mkdir(parents=True, exist_ok=True)
|
||||
log_file = log_dir / 'pre_compact.json'
|
||||
|
||||
# Read existing log data or initialize empty list
|
||||
if log_file.exists():
|
||||
with open(log_file, 'r') as f:
|
||||
try:
|
||||
log_data = json.load(f)
|
||||
except (json.JSONDecodeError, ValueError):
|
||||
log_data = []
|
||||
else:
|
||||
log_data = []
|
||||
|
||||
# Append the entire input data
|
||||
log_data.append(input_data)
|
||||
|
||||
# Write back to file with formatting
|
||||
with open(log_file, 'w') as f:
|
||||
json.dump(log_data, f, indent=2)
|
||||
|
||||
|
||||
def backup_transcript(transcript_path, trigger):
|
||||
"""Create a backup of the transcript before compaction."""
|
||||
try:
|
||||
if not os.path.exists(transcript_path):
|
||||
return
|
||||
|
||||
# Create backup directory
|
||||
backup_dir = Path(".claude/logs") / "transcript_backups"
|
||||
backup_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Generate backup filename with timestamp and trigger type
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
session_name = Path(transcript_path).stem
|
||||
backup_name = f"{session_name}_pre_compact_{trigger}_{timestamp}.jsonl"
|
||||
backup_path = backup_dir / backup_name
|
||||
|
||||
# Copy transcript to backup
|
||||
import shutil
|
||||
shutil.copy2(transcript_path, backup_path)
|
||||
|
||||
return str(backup_path)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
# Parse command line arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--backup', action='store_true',
|
||||
help='Create backup of transcript before compaction')
|
||||
parser.add_argument('--verbose', action='store_true',
|
||||
help='Print verbose output')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Read JSON input from stdin
|
||||
input_data = json.loads(sys.stdin.read())
|
||||
|
||||
# Extract fields
|
||||
session_id = input_data.get('session_id', 'unknown')
|
||||
transcript_path = input_data.get('transcript_path', '')
|
||||
trigger = input_data.get('trigger', 'unknown') # "manual" or "auto"
|
||||
custom_instructions = input_data.get('custom_instructions', '')
|
||||
|
||||
# Log the pre-compact event
|
||||
log_pre_compact(input_data)
|
||||
|
||||
# Create backup if requested
|
||||
backup_path = None
|
||||
if args.backup and transcript_path:
|
||||
backup_path = backup_transcript(transcript_path, trigger)
|
||||
|
||||
# Provide feedback based on trigger type
|
||||
if args.verbose:
|
||||
if trigger == "manual":
|
||||
message = f"Preparing for manual compaction (session: {session_id[:8]}...)"
|
||||
if custom_instructions:
|
||||
message += f"\nCustom instructions: {custom_instructions[:100]}..."
|
||||
else: # auto
|
||||
message = f"Auto-compaction triggered due to full context window (session: {session_id[:8]}...)"
|
||||
|
||||
if backup_path:
|
||||
message += f"\nTranscript backed up to: {backup_path}"
|
||||
|
||||
print(message)
|
||||
|
||||
# Success - compaction will proceed
|
||||
sys.exit(0)
|
||||
|
||||
except json.JSONDecodeError:
|
||||
# Handle JSON decode errors gracefully
|
||||
sys.exit(0)
|
||||
except Exception:
|
||||
# Handle any other errors gracefully
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user