99
1010def get_hyphenated_cwd () -> str :
1111 """Convert current working directory to hyphenated format for Claude log path.
12-
12+
1313 Returns:
1414 Hyphenated directory name (e.g., "/Users/john/project" -> "users-john-project")
1515 """
1616 cwd = os .getcwd ()
1717 # Remove leading slash and replace slashes and spaces with hyphens
18- hyphenated = cwd .replace ('/' , '-' ).replace (' ' , '-' )
18+ hyphenated = cwd .replace ("/" , "-" ).replace (" " , "-" ). replace ( "_" , "-" )
1919 # Remove any double hyphens
20- hyphenated = re .sub (r'-+' , '-' , hyphenated )
20+ hyphenated = re .sub (r"-+" , "-" , hyphenated )
2121 return hyphenated
2222
2323
2424def get_claude_session_log_path (session_id : str ) -> Path :
2525 """Get the path to the Claude session log file.
26-
26+
2727 Args:
2828 session_id: The Claude session ID
29-
29+
3030 Returns:
3131 Path to the session log file
3232 """
3333 claude_dir = Path .home () / ".claude"
3434 projects_dir = claude_dir / "projects"
3535 hyphenated_cwd = get_hyphenated_cwd ()
3636 project_dir = projects_dir / hyphenated_cwd
37-
37+
3838 log_file = project_dir / f"{ session_id } .jsonl"
3939 return log_file
4040
4141
4242def parse_jsonl_line (line : str ) -> Optional [Dict [str , Any ]]:
4343 """Parse a single line from a JSONL file.
44-
44+
4545 Args:
4646 line: Raw line from JSONL file
47-
47+
4848 Returns:
4949 Parsed JSON object or None if parsing fails
5050 """
5151 line = line .strip ()
5252 if not line :
5353 return None
54-
54+
5555 try :
5656 return json .loads (line )
5757 except json .JSONDecodeError :
@@ -60,10 +60,10 @@ def parse_jsonl_line(line: str) -> Optional[Dict[str, Any]]:
6060
6161def ensure_log_directory (session_id : str ) -> Path :
6262 """Ensure the log directory exists and return the log file path.
63-
63+
6464 Args:
6565 session_id: The Claude session ID
66-
66+
6767 Returns:
6868 Path to the session log file
6969 """
@@ -74,53 +74,53 @@ def ensure_log_directory(session_id: str) -> Path:
7474
7575def read_existing_log_lines (log_path : Path ) -> int :
7676 """Count existing lines in a log file.
77-
77+
7878 Args:
7979 log_path: Path to the log file
80-
80+
8181 Returns:
8282 Number of existing lines
8383 """
8484 if not log_path .exists ():
8585 return 0
86-
86+
8787 try :
88- with open (log_path , 'r' , encoding = ' utf-8' ) as f :
88+ with open (log_path , "r" , encoding = " utf-8" ) as f :
8989 return sum (1 for _ in f )
9090 except (OSError , UnicodeDecodeError ):
9191 return 0
9292
9393
9494def validate_log_entry (log_entry : Dict [str , Any ]) -> bool :
9595 """Validate a log entry before sending to API.
96-
96+
9797 Args:
9898 log_entry: The log entry to validate
99-
99+
100100 Returns:
101101 True if valid, False otherwise
102102 """
103103 if not isinstance (log_entry , dict ):
104104 return False
105-
105+
106106 # Basic validation - ensure it has some content
107107 if not log_entry :
108108 return False
109-
109+
110110 # Optionally validate specific fields that Claude Code uses
111111 # This can be expanded based on actual Claude log format
112112 return True
113113
114114
115115def format_log_for_api (log_entry : Dict [str , Any ]) -> Dict [str , Any ]:
116116 """Format a log entry for sending to the API.
117-
117+
118118 Args:
119119 log_entry: Raw log entry from Claude
120-
120+
121121 Returns:
122122 Formatted log entry ready for API
123123 """
124124 # For now, pass through as-is since API expects dict[str, Any]
125125 # This can be enhanced to transform or filter fields as needed
126- return log_entry
126+ return log_entry
0 commit comments