Pulastya B commited on
Commit
94bbef1
·
1 Parent(s): 16616fb

Fixed the File Path Issues

Browse files
src/api/app.py CHANGED
@@ -833,19 +833,43 @@ async def general_exception_handler(request, exc):
833
  async def serve_output_files(file_path: str):
834
  """
835
  Serve generated output files (reports, plots, models, etc.).
 
836
  """
837
- output_path = Path("./outputs") / file_path
838
-
839
- if not output_path.exists():
 
 
 
 
 
 
 
 
 
 
 
 
840
  raise HTTPException(status_code=404, detail=f"File not found: {file_path}")
841
 
842
- if not output_path.is_file():
843
- raise HTTPException(status_code=400, detail="Path is not a file")
844
-
845
  # Security: prevent directory traversal
846
- try:
847
- output_path.resolve().relative_to(Path("./outputs").resolve())
848
- except ValueError:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
849
  raise HTTPException(status_code=403, detail="Access denied")
850
 
851
  # Determine media type based on file extension
 
833
  async def serve_output_files(file_path: str):
834
  """
835
  Serve generated output files (reports, plots, models, etc.).
836
+ Checks multiple locations: ./outputs, /tmp/data_science_agent/outputs, and /tmp/data_science_agent.
837
  """
838
+ # Locations to check (in order of priority)
839
+ search_paths = [
840
+ Path("./outputs") / file_path, # Local development
841
+ Path("/tmp/data_science_agent/outputs") / file_path, # Production with subdirs
842
+ Path("/tmp/data_science_agent") / file_path, # Production flat
843
+ Path("/tmp/data_science_agent/outputs") / Path(file_path).name, # Production filename only
844
+ ]
845
+
846
+ output_path = None
847
+ for path in search_paths:
848
+ if path.exists() and path.is_file():
849
+ output_path = path
850
+ break
851
+
852
+ if output_path is None:
853
  raise HTTPException(status_code=404, detail=f"File not found: {file_path}")
854
 
 
 
 
855
  # Security: prevent directory traversal
856
+ resolved_path = output_path.resolve()
857
+ allowed_bases = [
858
+ Path("./outputs").resolve(),
859
+ Path("/tmp/data_science_agent").resolve()
860
+ ]
861
+
862
+ # Check if path is within allowed directories
863
+ is_allowed = False
864
+ for base in allowed_bases:
865
+ try:
866
+ resolved_path.relative_to(base)
867
+ is_allowed = True
868
+ break
869
+ except ValueError:
870
+ continue
871
+
872
+ if not is_allowed:
873
  raise HTTPException(status_code=403, detail="Access denied")
874
 
875
  # Determine media type based on file extension
src/orchestrator.py CHANGED
@@ -344,11 +344,25 @@ class DataScienceCopilot:
344
  self.specialist_agents = self._initialize_specialist_agents()
345
  self.active_agent = "Orchestrator" # Track which agent is working
346
 
 
 
 
 
 
 
 
 
 
 
347
  # Ensure output directories exist
348
- Path("./outputs").mkdir(exist_ok=True)
349
- Path("./outputs/models").mkdir(exist_ok=True)
350
- Path("./outputs/reports").mkdir(exist_ok=True)
351
- Path("./outputs/data").mkdir(exist_ok=True)
 
 
 
 
352
 
353
  def _build_tool_functions_map(self) -> Dict[str, callable]:
354
  """Build mapping of tool names to their functions - All 75 tools."""
 
344
  self.specialist_agents = self._initialize_specialist_agents()
345
  self.active_agent = "Orchestrator" # Track which agent is working
346
 
347
+ # Determine output directory based on environment
348
+ # In production (HuggingFace/Cloud Run), use /tmp for ephemeral storage
349
+ if os.path.exists("/tmp") and os.access("/tmp", os.W_OK):
350
+ self.output_base = Path("/tmp/data_science_agent/outputs")
351
+ else:
352
+ self.output_base = Path("./outputs")
353
+
354
+ # Set environment variable for tools to use
355
+ os.environ["DS_AGENT_OUTPUT_DIR"] = str(self.output_base)
356
+
357
  # Ensure output directories exist
358
+ self.output_base.mkdir(parents=True, exist_ok=True)
359
+ (self.output_base / "models").mkdir(exist_ok=True)
360
+ (self.output_base / "reports").mkdir(exist_ok=True)
361
+ (self.output_base / "data").mkdir(exist_ok=True)
362
+ (self.output_base / "plots").mkdir(exist_ok=True)
363
+ (self.output_base / "plots" / "interactive").mkdir(exist_ok=True)
364
+
365
+ print(f"📁 Output directory: {self.output_base}")
366
 
367
  def _build_tool_functions_map(self) -> Dict[str, callable]:
368
  """Build mapping of tool names to their functions - All 75 tools."""
src/tools/plotly_visualizations.py CHANGED
@@ -170,18 +170,23 @@ def generate_interactive_histogram(
170
 
171
  def generate_interactive_correlation_heatmap(
172
  file_path: str,
173
- output_path: str = "./outputs/plots/interactive/correlation_heatmap.html"
174
  ) -> Dict[str, Any]:
175
  """
176
  Create interactive correlation heatmap with Plotly.
177
 
178
  Args:
179
  file_path: Path to dataset
180
- output_path: Path to save HTML file
181
 
182
  Returns:
183
  Dictionary with plot info
184
  """
 
 
 
 
 
185
  # Validation
186
  validate_file_exists(file_path)
187
  validate_file_format(file_path)
 
170
 
171
  def generate_interactive_correlation_heatmap(
172
  file_path: str,
173
+ output_path: str = None
174
  ) -> Dict[str, Any]:
175
  """
176
  Create interactive correlation heatmap with Plotly.
177
 
178
  Args:
179
  file_path: Path to dataset
180
+ output_path: Path to save HTML file (auto-determined if None)
181
 
182
  Returns:
183
  Dictionary with plot info
184
  """
185
+ # Auto-determine output path based on environment
186
+ if output_path is None:
187
+ output_base = os.getenv("DS_AGENT_OUTPUT_DIR", "./outputs")
188
+ output_path = f"{output_base}/plots/interactive/correlation_heatmap.html"
189
+
190
  # Validation
191
  validate_file_exists(file_path)
192
  validate_file_format(file_path)