"""Environment setup utilities for VoiceAgent. Ensures that PATH in os.environ includes all user binary locations, login shell PATH, and tool locations (such as Paseo CLI, OpenCode, Cargo, Homebrew, etc.). """ import os import subprocess from pathlib import Path from loguru import logger def setup_environment_path(): """Ensure PATH in os.environ includes all user binary locations and login shell PATH.""" current_path = os.environ.get("PATH", "") # 1. Fetch user's login shell PATH to capture custom paths from .zshrc / .bash_profile shell_path = "" shell = os.environ.get("SHELL", "/bin/zsh") try: res = subprocess.run([shell, "-l", "-c", "echo $PATH"], capture_output=True, text=True, timeout=3.0) if res.returncode == 0: shell_path = res.stdout.strip() except Exception as e: logger.debug(f"Login shell PATH lookup failed: {e}") combined = [] # Add login shell path entries if shell_path: for p in shell_path.split(os.pathsep): if p and p not in combined: combined.append(p) # Standard user binary locations user_dirs = [ os.path.expanduser("~/.local/bin"), os.path.expanduser("~/.opencode/bin"), os.path.expanduser("~/.cargo/bin"), os.path.expanduser("~/.meta/bin"), os.path.expanduser("~/bin"), os.path.expanduser("~/.bun/bin"), "/opt/homebrew/bin", "/opt/homebrew/sbin", "/usr/local/bin", ] for d in user_dirs: if d not in combined: combined.append(d) # Existing process PATH for p in current_path.split(os.pathsep): if p and p not in combined: combined.append(p) os.environ["PATH"] = os.pathsep.join(combined) logger.debug(f"Environment PATH configured: {os.environ['PATH']}") # Run automatically on module import setup_environment_path()