diff --git a/env_prod.env b/env_prod.env index 041943a5..8a2e2aaf 100644 --- a/env_prod.env +++ b/env_prod.env @@ -1,7 +1,7 @@ # Production Environment Configuration # System Configuration -APP_ENV_TYPE = dev +APP_ENV_TYPE = prod APP_ENV_LABEL = Production Instance APP_CALL=uvicorn app:app --host 0.0.0.0 --port 8000 diff --git a/modules/agentCoder.py b/modules/agentCoder.py index 9af8fd7d..60dc0072 100644 --- a/modules/agentCoder.py +++ b/modules/agentCoder.py @@ -591,10 +591,182 @@ Return ONLY Python code without explanations or markdown. return code, requirements - def _executeCode(self, code: str, requirements: List[str] = None) -> Dict[str, Any]: + def _executeCodeProd(self, code: str, requirements: List[str] = None) -> Dict[str, Any]: + """ + Execute Python code in Azure environment using the antenv interpreter. + Optimized for production use in Azure Web App environment where venv creation fails. + + Args: + code: Python code to execute + requirements: List of required packages + + Returns: + Execution result dictionary + """ + try: + # 1. Create temp directory for code files + self.tempDir = tempfile.mkdtemp(prefix="code_exec_") + + # Try different possible paths to find the antenv Python interpreter + possible_python_paths = [ + "/home/site/wwwroot/antenv/bin/python", + "/antenv/bin/python", + "/tmp/8dd8c226509f116/antenv/bin/python", # Path from your error logs + sys.executable # Fallback to system Python + ] + + pythonExe = None + for path in possible_python_paths: + if os.path.exists(path): + pythonExe = path + logger.info(f"Found Python interpreter at: {pythonExe}") + break + + if not pythonExe: + logger.error("Could not find a valid Python interpreter in Azure environment") + return { + "success": False, + "output": "", + "error": "Could not find a valid Python interpreter in Azure environment", + "result": None, + "exitCode": -1 + } + + # 2. Install requirements to a temporary user directory if provided + if requirements: + logger.info(f"Installing requirements in Azure environment: {requirements}") + + # Create requirements.txt + reqFile = os.path.join(self.tempDir, "requirements.txt") + with open(reqFile, "w") as f: + f.write("\n".join(requirements)) + + # Set up a custom PYTHONUSERBASE to isolate package installations + custom_user_base = os.path.join(self.tempDir, "pip_packages") + os.makedirs(custom_user_base, exist_ok=True) + + env = os.environ.copy() + env["PYTHONUSERBASE"] = custom_user_base + + # Install requirements to the custom user directory + try: + pipResult = subprocess.run( + [pythonExe, "-m", "pip", "install", "--user", "-r", reqFile], + capture_output=True, + text=True, + env=env, + timeout=int(APP_CONFIG.get("Agent_Coder_INSTALL_TIMEOUT")) + ) + + if pipResult.returncode != 0: + logger.warning(f"Error installing requirements in Azure: {pipResult.stderr}") + else: + logger.info(f"Requirements installed successfully to {custom_user_base}") + + # Try to find the site-packages directory + import glob + site_packages = os.path.join(custom_user_base, "lib", "python*", "site-packages") + site_packages_paths = glob.glob(site_packages) + + if site_packages_paths: + env["PYTHONPATH"] = os.pathsep.join([site_packages_paths[0], env.get("PYTHONPATH", "")]) + logger.info(f"Added {site_packages_paths[0]} to PYTHONPATH") + else: + # Alternative paths for different Python versions + alt_site_packages = os.path.join(custom_user_base, "site-packages") + if os.path.exists(alt_site_packages): + env["PYTHONPATH"] = os.pathsep.join([alt_site_packages, env.get("PYTHONPATH", "")]) + logger.info(f"Added {alt_site_packages} to PYTHONPATH") + except Exception as e: + logger.warning(f"Exception during requirements installation in Azure: {str(e)}") + else: + env = os.environ.copy() + + # 3. Write code to file + codeFile = os.path.join(self.tempDir, "code.py") + with open(codeFile, "w", encoding="utf-8") as f: + f.write(code) + + # 4. Execute code with the modified environment + logger.debug(f"Executing code in Azure environment with timeout of {self.executorTimeout} seconds") + process = subprocess.run( + [pythonExe, codeFile], + timeout=self.executorTimeout, + capture_output=True, + text=True, + env=env + ) + + # 5. Process results + stdout = process.stdout + stderr = process.stderr + + # Try to extract result from stdout + resultData = None + if process.returncode == 0: + try: + # Find the last line that might be JSON + jsonLines = [] + for line in stdout.strip().split('\n'): + line = line.strip() + if line and line[0] in '{[' and line[-1] in '}]': + try: + parsed = json.loads(line) + jsonLines.append((line, parsed)) + except json.JSONDecodeError: + continue + + # Use the last valid JSON that appears to be a dictionary + if jsonLines: + for line, parsed in reversed(jsonLines): + if isinstance(parsed, dict): + resultData = parsed + logger.debug(f"Extracted result data from stdout: {type(resultData)}") + break + except Exception as e: + logger.debug(f"Error extracting result from stdout: {str(e)}") + + # Enhanced logging of what was found + if resultData: + logger.info(f"Found result dictionary with {len(resultData)} entries: {list(resultData.keys())}") + else: + logger.warning("No result dictionary found in output") + + # Create result dictionary + return { + "success": process.returncode == 0, + "output": stdout, + "error": stderr if process.returncode != 0 else "", + "result": resultData, + "exitCode": process.returncode + } + + except subprocess.TimeoutExpired: + logger.error(f"Execution in Azure timed out after {self.executorTimeout} seconds") + return { + "success": False, + "output": "", + "error": f"Execution timed out after {self.executorTimeout} seconds", + "result": None, + "exitCode": -1 + } + except Exception as e: + logger.error(f"Execution error in Azure environment: {str(e)}") + return { + "success": False, + "output": "", + "error": f"Execution error in Azure environment: {str(e)}", + "result": None, + "exitCode": -1 + } + finally: + # Clean up resources + self._cleanupExecution() + + def _executeCodeVenv(self, code: str, requirements: List[str] = None) -> Dict[str, Any]: """ Execute Python code in a virtual environment. - Integrated executor functionality with enhanced result extraction. + Original implementation with venv creation for non-Azure environments. Args: code: Python code to execute @@ -788,6 +960,32 @@ Return ONLY Python code without explanations or markdown. # Clean up resources self._cleanupExecution() + def _executeCode(self, code: str, requirements: List[str] = None) -> Dict[str, Any]: + """ + Execute Python code in the appropriate environment based on configuration. + + Args: + code: Python code to execute + requirements: List of required packages + + Returns: + Execution result dictionary + """ + # Check if we're in a production Azure environment + env_type = APP_CONFIG.get("APP_ENV_TYPE", "dev").lower() + + logger.info(f"Executing code in environment type: {env_type}") + + if env_type == "prod": + # Use the Azure-optimized execution method + logger.info("Using Azure-optimized code execution method") + return self._executeCodeProd(code, requirements) + else: + # Use the standard virtual environment execution method + logger.info("Using standard virtual environment execution method") + return self._executeCodeVenv(code, requirements) + + def _cleanupExecution(self): """Clean up temporary resources from code execution.""" if self.tempDir and os.path.exists(self.tempDir):