acecalisto3 commited on
Commit
6c6f5bc
·
verified ·
1 Parent(s): ea748e3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +166 -0
app.py CHANGED
@@ -2600,6 +2600,172 @@ def create_ui(manager: IssueManager) -> gr.Blocks:
2600
  # Return default updates to clear the UI
2601
  return default_updates
2602
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2603
  try:
2604
  # The first column (index 0) is the Issue ID
2605
  selected_id = int(evt.value[0])
 
2600
  # Return default updates to clear the UI
2601
  return default_updates
2602
 
2603
+ try:
2604
+ # The first column (index 0) is the Issue ID
2605
+ selected_id = int(evt.value[0])
2606
+ logger.info(f"Issue selected via Dataframe: ID {selected_id}")
2607
+
2608
+ if selected_id not in manager.issues:
2609
+ logger.error(f"Selected issue ID {selected_id} not found in manager's issue list.")
2610
+ return {
2611
+ **default_updates,
2612
+ "issue_preview_html": gr.update(value=f"<p style='color: red; font-weight: bold;'>Error: Issue {selected_id} not found in the current list. Try re-scanning.</p>"),
2613
+ "selected_issue_id_hidden": gr.update(value=""), # Ensure hidden state is cleared
2614
+ }
2615
+
2616
+ issue_data = manager.issues[selected_id]
2617
+ files_content: Dict[str, str] = {}
2618
+ context_source_msg = "Loading context..."
2619
+ context_load_start = time.time()
2620
+
2621
+ # --- Load or Compute Code Context ---
2622
+ # Prioritize pre-computed context if available
2623
+ context_data = manager.precomputed_context.get(selected_id) # Use .get for safety
2624
+
2625
+ if context_data:
2626
+ timestamp = context_data.get('timestamp', 0)
2627
+ timestamp_str = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
2628
+ if context_data.get("error"):
2629
+ context_source_msg = f"Pre-computed (Failed @ {timestamp_str})"
2630
+ files_content["error_context.txt"] = f"# Error loading pre-computed context:\n# {context_data['error']}"
2631
+ elif context_data.get("files"):
2632
+ context_source_msg = f"Pre-computed ({len(context_data['files'])} files @ {timestamp_str})"
2633
+ logger.info(f"Loading {len(context_data['files'])} files from pre-computed context for issue {selected_id}: {context_data['files']}")
2634
+ loaded_count = 0
2635
+ for file_path_str in context_data["files"]:
2636
+ full_path = manager.repo_local_path / file_path_str
2637
+ try:
2638
+ if full_path.is_file():
2639
+ # Use resolved path for robust reading
2640
+ resolved_full_path = full_path.resolve()
2641
+ # Double-check it's still in the repo path after resolve
2642
+ if resolved_full_path.is_relative_to(manager.repo_local_path.resolve()):
2643
+ files_content[file_path_str] = resolved_full_path.read_text(encoding='utf-8', errors='ignore')
2644
+ loaded_count += 1
2645
+ else:
2646
+ logger.warning(f"Pre-computed file path {file_path_str} resolved outside repo during load for issue {selected_id}.")
2647
+ files_content[file_path_str] = f"# File path resolved outside repository: {file_path_str}"
2648
+ else:
2649
+ logger.warning(f"Pre-computed file path {file_path_str} not found or not a file during load for issue {selected_id}.")
2650
+ files_content[file_path_str] = f"# File not found or not a file: {file_path_str}"
2651
+ except Exception as e:
2652
+ logger.warning(f"Error reading pre-computed file {full_path} for issue {selected_id}: {e}")
2653
+ files_content[file_path_str] = f"# Error reading file: {e}"
2654
+ # This check should be outside the for loop, indented the same as the for loop
2655
+ if loaded_count == 0 and context_data.get("files"): # Use .get for safety
2656
+ files_content["error_reading_files.txt"] = "# Precomputed context found file references, but failed to read any file content."
2657
+ # This else corresponds to elif context_data.get("files"):
2658
+ else: # Line 2690 - Corrected indentation
2659
+ context_source_msg = f"Pre-computed (No files found @ {timestamp_str})"
2660
+ files_content[f"issue_{selected_id}_context.md"] = context_data.get("content", "# No specific code context found (pre-computed).")
2661
+
2662
+ else: # Handle on-demand context computation
2663
+ logger.info(f"Context not pre-computed for issue {selected_id}, computing on demand for editor.")
2664
+ context_source_msg = "Computed On-Demand"
2665
+ context_result = await manager._get_code_context(issue_data)
2666
+
2667
+ # Store the newly computed context for future use (e.g., patch generation)
2668
+ manager.precomputed_context[selected_id] = {
2669
+ "content": context_result.get("content"),
2670
+ "files": context_result.get("files", []),
2671
+ "error": context_result.get("error"),
2672
+ "timestamp": time.time()
2673
+ }
2674
+
2675
+ if "error" in context_result and context_result["error"]:
2676
+ context_source_msg += f" (Error: {context_result['error']})"
2677
+ files_content["error_context.txt"] = f"# Error loading context on demand:\n# {context_result['error']}"
2678
+ elif context_result.get("files"):
2679
+ context_source_msg += f" ({len(context_result['files'])} files)"
2680
+ logger.info(f"Loading {len(context_result['files'])} files computed on-demand for issue {selected_id}: {context_result['files']}")
2681
+ loaded_count = 0
2682
+ for file_path_str in context_result["files"]:
2683
+ full_path = manager.repo_local_path / file_path_str
2684
+ try:
2685
+ if full_path.is_file():
2686
+ resolved_full_path = full_path.resolve()
2687
+ if resolved_full_path.is_relative_to(manager.repo_local_path.resolve()):
2688
+ files_content[file_path_str] = resolved_full_path.read_text(encoding='utf-8', errors='ignore')
2689
+ loaded_count +=1
2690
+ else:
2691
+ logger.warning(f"On-demand file path {file_path_str} resolved outside repo during load for issue {selected_id}.")
2692
+ files_content[file_path_str] = f"# File path resolved outside repository: {file_path_str}"
2693
+ else:
2694
+ logger.warning(f"On-demand file path {file_path_str} not found or not a file during load for issue {selected_id}.")
2695
+ files_content[file_path_str] = f"# File not found or not a file: {file_path_str}"
2696
+ except Exception as e:
2697
+ logger.warning(f"Error reading on-demand file {full_path} for issue {selected_id}: {e}")
2698
+ files_content[file_path_str] = f"# Error reading file: {e}"
2699
+ # This check should be outside the try/except and for loop
2700
+ if loaded_count == 0 and context_result.get("files"): # Use .get for safety
2701
+ files_content["error_reading_files.txt"] = "# Context computation found file references, but failed to read any file content."
2702
+ # This else corresponds to the inner if/elif within the on-demand block
2703
+ else:
2704
+ context_source_msg += " (No files found)"
2705
+ files_content[f"issue_{selected_id}_context.md"] = context_result.get("content", "# No specific code context found.")
2706
+
2707
+ # This line should be outside both the 'if context_data' and its 'else' branch
2708
+ context_load_duration = time.time() - context_load_start
2709
+ logger.info(f"Context loading for editor took {context_load_duration:.2f}s. Source: {context_source_msg}")
2710
+
2711
+ if not files_content:
2712
+ files_content["placeholder.txt"] = f"# No relevant files found or context failed to load for issue {selected_id}."
2713
+
2714
+ # Initialize or update the OT editor instance for this issue
2715
+ manager.code_editors[selected_id] = OTCodeEditor(initial_value=files_content)
2716
+ logger.info(f"Initialized/Updated OT editor state for issue {selected_id} with files: {list(files_content.keys())}")
2717
+
2718
+ # Determine the initial language hint for the editor based on the first file extension
2719
+ initial_language = "text" # Default to plain text
2720
+ if files_content:
2721
+ first_file_name = list(files_content.keys())[0]
2722
+ # Extract extension (part after the last dot)
2723
+ _, ext = os.path.splitext(first_file_name)
2724
+ if ext:
2725
+ # Remove leading dot and convert to lowercase
2726
+ ext = ext[1:].lower()
2727
+ # Map common extensions to ACE editor modes (approximate)
2728
+ # Check available modes in ACE editor documentation if needed
2729
+ lang_map = {
2730
+ 'py': 'python', 'js': 'javascript', 'jsx': 'javascript', 'ts': 'typescript', 'tsx': 'typescript',
2731
+ 'java': 'java', 'c': 'c_cpp', 'cpp': 'c_cpp', 'h': 'c_cpp', 'hpp': 'c_cpp', 'cs': 'csharp',
2732
+ 'go': 'golang', 'rs': 'rust', 'php': 'php', 'rb': 'ruby', 'html': 'html', 'css': 'css',
2733
+ 'scss': 'scss', 'less': 'less', 'md': 'markdown', 'yaml': 'yaml', 'yml': 'yaml', 'json': 'json',
2734
+ 'toml': 'toml', 'sh': 'sh', 'bash': 'sh', 'zsh': 'sh', 'sql': 'sql', 'xml': 'xml',
2735
+ 'dockerfile': 'dockerfile', 'makefile': 'makefile', 'txt': 'text', 'log': 'text',
2736
+ 'conf': 'text', 'cfg': 'text', 'ini': 'ini'
2737
+ }
2738
+ initial_language = lang_map.get(ext, 'text')
2739
+
2740
+
2741
+ # Prepare updates for all relevant UI components
2742
+ updates = {
2743
+ # Update the hidden state element with the selected ID (as string)
2744
+ "selected_issue_id_hidden": gr.update(value=str(selected_id)),
2745
+ "issue_preview_html": gr.update(value=generate_issue_preview(selected_id)),
2746
+ "code_edit_component": gr.update(value=files_content, interactive=True, language=initial_language),
2747
+ "ai_output_display": gr.update(value=f"*Context loaded ({context_source_msg}). Ready for AI actions or editing.*"),
2748
+ "copy_patch_btn": gr.update(visible=False), # Hide copy button on new selection
2749
+ }
2750
+ return updates
2751
+
2752
+ except (ValueError, TypeError, IndexError, KeyError, AttributeError) as e:
2753
+ logger.exception(f"Error processing issue selection event (evt.value: {getattr(evt, 'value', 'N/A')}): {e}")
2754
+ # Return default state plus an error message
2755
+ return {
2756
+ **default_updates,
2757
+ "issue_preview_html": gr.update(value="<p style='color: red; font-weight: bold;'>Error loading issue details. Please check logs and try again.</p>"),
2758
+ "code_edit_component": gr.update(value={"error.txt": f"# Error loading code context for selection.\n# Error: {e}"}, interactive=False, language="text"),
2759
+ "ai_output_display": gr.update(value="*Error processing selection. See logs.*"),
2760
+ "selected_issue_id_hidden": gr.update(value=""), # Ensure hidden state is cleared
2761
+ "copy_patch_btn": gr.update(visible=False), # Hide copy button on error
2762
+ }
2763
+ # Check if a row was actually selected and has a value
2764
+ if evt.index is None or not hasattr(evt, 'value') or not evt.value or evt.value[0] is None:
2765
+ logger.info("Issue deselected or invalid selection event.")
2766
+ # Return default updates to clear the UI
2767
+ return default_updates
2768
+
2769
  try:
2770
  # The first column (index 0) is the Issue ID
2771
  selected_id = int(evt.value[0])