claude-self-reflect 2.5.19 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Quick import script for current project's latest conversations.
4
+ Designed for PreCompact hook integration - targets <10 second imports.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import json
10
+ import subprocess
11
+ from datetime import datetime, timedelta
12
+ from pathlib import Path
13
+ import logging
14
+
15
+ # Configuration
16
+ LOGS_DIR = os.getenv("LOGS_DIR", os.path.expanduser("~/.claude/projects"))
17
+ STATE_FILE = os.getenv("STATE_FILE", os.path.expanduser("~/.claude-self-reflect-state.json"))
18
+ HOURS_BACK = int(os.getenv("IMPORT_HOURS_BACK", "2")) # Only import last 2 hours by default
19
+
20
+ # Set up logging
21
+ logging.basicConfig(
22
+ level=logging.INFO,
23
+ format='%(asctime)s - %(levelname)s - %(message)s'
24
+ )
25
+ logger = logging.getLogger(__name__)
26
+
27
+ def load_state():
28
+ """Load import state from file."""
29
+ if os.path.exists(STATE_FILE):
30
+ try:
31
+ with open(STATE_FILE, 'r') as f:
32
+ return json.load(f)
33
+ except:
34
+ return {}
35
+ return {}
36
+
37
+ def save_state(state):
38
+ """Save import state to file."""
39
+ os.makedirs(os.path.dirname(STATE_FILE), exist_ok=True)
40
+ with open(STATE_FILE, 'w') as f:
41
+ json.dump(state, f, indent=2)
42
+
43
+ def get_project_from_cwd():
44
+ """Detect project from current working directory."""
45
+ cwd = os.getcwd()
46
+ # Convert path to project name format used in logs
47
+ # Claude logs use format: -Users-username-path-to-project
48
+ project_name = cwd.replace('/', '-')
49
+ # Keep the leading dash as that's how Claude stores it
50
+ if not project_name.startswith('-'):
51
+ project_name = '-' + project_name
52
+ return project_name
53
+
54
+ def get_recent_files(project_path: Path, hours_back: int):
55
+ """Get JSONL files modified in the last N hours."""
56
+ cutoff_time = datetime.now() - timedelta(hours=hours_back)
57
+ recent_files = []
58
+
59
+ for jsonl_file in project_path.glob("*.jsonl"):
60
+ mtime = datetime.fromtimestamp(jsonl_file.stat().st_mtime)
61
+ if mtime > cutoff_time:
62
+ recent_files.append(jsonl_file)
63
+
64
+ return sorted(recent_files, key=lambda f: f.stat().st_mtime, reverse=True)
65
+
66
+ def main():
67
+ """Main quick import function."""
68
+ start_time = datetime.now()
69
+
70
+ # Detect current project
71
+ project_name = get_project_from_cwd()
72
+ project_path = Path(LOGS_DIR) / project_name
73
+
74
+ if not project_path.exists():
75
+ logger.warning(f"Project logs not found: {project_path}")
76
+ logger.info("Make sure you're in a project directory with Claude conversations.")
77
+ return
78
+
79
+ logger.info(f"Quick importing latest conversations for: {project_name}")
80
+
81
+ # Get recent files
82
+ recent_files = get_recent_files(project_path, HOURS_BACK)
83
+ logger.info(f"Found {len(recent_files)} files modified in last {HOURS_BACK} hours")
84
+
85
+ if not recent_files:
86
+ logger.info("No recent conversations to import")
87
+ return
88
+
89
+ # For now, just call the unified importer with the specific project
90
+ # This is a temporary solution until we implement incremental imports
91
+ script_dir = os.path.dirname(os.path.abspath(__file__))
92
+ unified_script = os.path.join(script_dir, "import-conversations-unified.py")
93
+
94
+ # Set environment to only process this project
95
+ env = os.environ.copy()
96
+ env['LOGS_DIR'] = str(project_path.parent)
97
+ env['IMPORT_PROJECT'] = project_name
98
+
99
+ try:
100
+ # Run the unified importer for just this project
101
+ result = subprocess.run(
102
+ [sys.executable, unified_script],
103
+ env=env,
104
+ capture_output=True,
105
+ text=True,
106
+ timeout=60 # 60 second timeout
107
+ )
108
+
109
+ if result.returncode == 0:
110
+ logger.info("Quick import completed successfully")
111
+ else:
112
+ logger.error(f"Import failed: {result.stderr}")
113
+
114
+ except subprocess.TimeoutExpired:
115
+ logger.warning("Import timed out after 60 seconds")
116
+ except Exception as e:
117
+ logger.error(f"Error during import: {e}")
118
+
119
+ # Report timing
120
+ elapsed = (datetime.now() - start_time).total_seconds()
121
+ logger.info(f"Quick import completed in {elapsed:.1f} seconds")
122
+
123
+ if __name__ == "__main__":
124
+ main()