@@ -277,12 +277,11 @@ class GameMetadata:
277277 """Metadata about a game session"""
278278
279279 results : dict [str , Any ]
280- main_log : str
281280 main_log_path : str
282281 metadata_file_path : str
283282 rounds : list [dict [str , Any ]]
284283 agent_info : list [AgentInfo ] | None = None
285- all_logs : dict [str , dict [str , str ]] | None = None # {log_type: {"content": content, " path": path}}
284+ all_logs : dict [str , dict [str , str ]] | None = None # {log_type: {"path": path}} - content loaded on demand
286285
287286
288287def process_round_results (
@@ -385,12 +384,11 @@ def parse_game_metadata(self) -> GameMetadata:
385384 results = metadata .raw_data
386385 metadata_file_path = str (self .log_dir / "metadata.json" )
387386
388- # Parse tournament. log if it exists
387+ # Get path to main log but don't load content
389388 main_log_file = self .log_dir / "tournament.log"
390- main_log = main_log_file .read_text () if main_log_file .exists () else "No tournament log found"
391389 main_log_path = str (main_log_file ) if main_log_file .exists () else ""
392390
393- # Parse all available logs
391+ # Parse all available logs (metadata only, no content)
394392 all_logs = self ._parse_all_logs ()
395393
396394 # Extract agent information once
@@ -411,7 +409,6 @@ def parse_game_metadata(self) -> GameMetadata:
411409
412410 return GameMetadata (
413411 results = results ,
414- main_log = main_log ,
415412 main_log_path = main_log_path ,
416413 metadata_file_path = metadata_file_path ,
417414 rounds = rounds ,
@@ -468,7 +465,9 @@ def parse_trajectory(self, player_name: str, round_num: int) -> TrajectoryInfo |
468465 trajectory_file_path = str (traj_file ),
469466 diff_by_files = diff_by_files ,
470467 incremental_diff_by_files = incremental_diff_by_files ,
471- valid_submission = self ._get_metadata ().round_stats [str (round_num )]['player_stats' ][player_name ]['valid_submit' ]
468+ valid_submission = self ._get_metadata ().round_stats [str (round_num )]["player_stats" ][player_name ][
469+ "valid_submit"
470+ ],
472471 )
473472 except (json .JSONDecodeError , KeyError ) as e :
474473 logger .error (f"Error parsing { traj_file } : { e } " , exc_info = True )
@@ -670,7 +669,7 @@ def load_matrix_analysis(self) -> dict[str, Any] | None:
670669 return None
671670
672671 def _parse_all_logs (self ) -> dict [str , dict [str , str ]]:
673- """Parse all available log files in the tournament directory"""
672+ """Parse all available log files in the tournament directory (metadata only, no content) """
674673 all_logs = {}
675674
676675 # Define log files to look for
@@ -680,11 +679,7 @@ def _parse_all_logs(self) -> dict[str, dict[str, str]]:
680679 for log_file , display_name in log_files .items ():
681680 log_path = self .log_dir / log_file
682681 if log_path .exists ():
683- try :
684- content = log_path .read_text ()
685- all_logs [display_name ] = {"content" : content , "path" : str (log_path )}
686- except (OSError , UnicodeDecodeError ) as e :
687- all_logs [display_name ] = {"content" : f"Error reading log file: { e } " , "path" : str (log_path )}
682+ all_logs [display_name ] = {"path" : str (log_path )}
688683
689684 # Check for player logs
690685 players_dir = self .log_dir / "players"
@@ -697,13 +692,8 @@ def _parse_all_logs(self) -> dict[str, dict[str, str]]:
697692 player_log = player_dir / "player.log"
698693
699694 if player_log .exists ():
700- try :
701- content = player_log .read_text ()
702- display_name = f"Player { player_name } Log"
703- all_logs [display_name ] = {"content" : content , "path" : str (player_log )}
704- except (OSError , UnicodeDecodeError ) as e :
705- display_name = f"Player { player_name } Log"
706- all_logs [display_name ] = {"content" : f"Error reading log file: { e } " , "path" : str (player_log )}
695+ display_name = f"Player { player_name } Log"
696+ all_logs [display_name ] = {"path" : str (player_log )}
707697
708698 return all_logs
709699
@@ -1220,4 +1210,38 @@ def download_file():
12201210 return jsonify ({"success" : False , "error" : str (e )}), 500
12211211
12221212
1213+ @app .route ("/load-log" )
1214+ def load_log ():
1215+ """Load log file content on demand"""
1216+ file_path = request .args .get ("path" )
1217+
1218+ if not file_path :
1219+ return jsonify ({"success" : False , "error" : "No file path provided" }), 400
1220+
1221+ try :
1222+ # Convert to Path object
1223+ file_path_obj = Path (file_path )
1224+
1225+ # Security check: ensure the file exists
1226+ if not file_path_obj .exists ():
1227+ return jsonify ({"success" : False , "error" : "File does not exist" }), 404
1228+
1229+ # Security check: ensure the file is not a directory
1230+ if not file_path_obj .is_file ():
1231+ return jsonify ({"success" : False , "error" : "Path is not a file" }), 400
1232+
1233+ # Security check: ensure the path is within our expected logs directory
1234+ try :
1235+ file_path_obj .relative_to (LOG_BASE_DIR )
1236+ except ValueError :
1237+ return jsonify ({"success" : False , "error" : "Invalid file path" }), 403
1238+
1239+ # Read and return the file content
1240+ content = file_path_obj .read_text ()
1241+ return jsonify ({"success" : True , "content" : content })
1242+
1243+ except (OSError , UnicodeDecodeError ) as e :
1244+ return jsonify ({"success" : False , "error" : f"Error reading file: { str (e )} " }), 500
1245+
1246+
12231247# Use run_viewer.py to launch the application
0 commit comments