mirror of
https://github.com/SuperClaude-Org/SuperClaude_Framework.git
synced 2025-12-18 02:06:36 +00:00
216 lines
7.3 KiB
Python
216 lines
7.3 KiB
Python
|
|
"""
|
||
|
|
Environment variable management for SuperClaude
|
||
|
|
Cross-platform utilities for setting up persistent environment variables
|
||
|
|
"""
|
||
|
|
|
||
|
|
import os
|
||
|
|
import sys
|
||
|
|
import subprocess
|
||
|
|
from pathlib import Path
|
||
|
|
from typing import Dict, Optional
|
||
|
|
from .ui import display_info, display_success, display_warning, Colors
|
||
|
|
from .logger import get_logger
|
||
|
|
|
||
|
|
|
||
|
|
def detect_shell_config() -> Optional[Path]:
|
||
|
|
"""
|
||
|
|
Detect user's shell configuration file
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Path to the shell configuration file, or None if not found
|
||
|
|
"""
|
||
|
|
home = Path.home()
|
||
|
|
|
||
|
|
# Check in order of preference
|
||
|
|
configs = [
|
||
|
|
home / ".zshrc", # Zsh (Mac default)
|
||
|
|
home / ".bashrc", # Bash
|
||
|
|
home / ".profile", # Generic shell profile
|
||
|
|
home / ".bash_profile" # Mac Bash profile
|
||
|
|
]
|
||
|
|
|
||
|
|
for config in configs:
|
||
|
|
if config.exists():
|
||
|
|
return config
|
||
|
|
|
||
|
|
# Default to .bashrc if none exist (will be created)
|
||
|
|
return home / ".bashrc"
|
||
|
|
|
||
|
|
|
||
|
|
def setup_environment_variables(api_keys: Dict[str, str]) -> bool:
|
||
|
|
"""
|
||
|
|
Set up environment variables across platforms
|
||
|
|
|
||
|
|
Args:
|
||
|
|
api_keys: Dictionary of environment variable names to values
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
True if all variables were set successfully, False otherwise
|
||
|
|
"""
|
||
|
|
logger = get_logger()
|
||
|
|
success = True
|
||
|
|
|
||
|
|
if not api_keys:
|
||
|
|
return True
|
||
|
|
|
||
|
|
print(f"\n{Colors.BLUE}[INFO] Setting up environment variables...{Colors.RESET}")
|
||
|
|
|
||
|
|
for env_var, value in api_keys.items():
|
||
|
|
try:
|
||
|
|
# Set for current session
|
||
|
|
os.environ[env_var] = value
|
||
|
|
|
||
|
|
if os.name == 'nt': # Windows
|
||
|
|
# Use setx for persistent user variable
|
||
|
|
result = subprocess.run(
|
||
|
|
['setx', env_var, value],
|
||
|
|
capture_output=True,
|
||
|
|
text=True
|
||
|
|
)
|
||
|
|
if result.returncode != 0:
|
||
|
|
display_warning(f"Could not set {env_var} persistently: {result.stderr.strip()}")
|
||
|
|
success = False
|
||
|
|
else:
|
||
|
|
logger.info(f"Windows environment variable {env_var} set persistently")
|
||
|
|
else: # Unix-like systems
|
||
|
|
shell_config = detect_shell_config()
|
||
|
|
|
||
|
|
# Check if the export already exists
|
||
|
|
export_line = f'export {env_var}="{value}"'
|
||
|
|
|
||
|
|
try:
|
||
|
|
with open(shell_config, 'r') as f:
|
||
|
|
content = f.read()
|
||
|
|
|
||
|
|
# Check if this environment variable is already set
|
||
|
|
if f'export {env_var}=' in content:
|
||
|
|
# Variable exists - don't duplicate
|
||
|
|
logger.info(f"Environment variable {env_var} already exists in {shell_config.name}")
|
||
|
|
else:
|
||
|
|
# Append export to shell config
|
||
|
|
with open(shell_config, 'a') as f:
|
||
|
|
f.write(f'\n# SuperClaude API Key\n{export_line}\n')
|
||
|
|
|
||
|
|
display_info(f"Added {env_var} to {shell_config.name}")
|
||
|
|
logger.info(f"Added {env_var} to {shell_config}")
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
display_warning(f"Could not update {shell_config.name}: {e}")
|
||
|
|
success = False
|
||
|
|
|
||
|
|
logger.info(f"Environment variable {env_var} configured for current session")
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"Failed to set {env_var}: {e}")
|
||
|
|
display_warning(f"Failed to set {env_var}: {e}")
|
||
|
|
success = False
|
||
|
|
|
||
|
|
if success:
|
||
|
|
display_success("Environment variables configured successfully")
|
||
|
|
if os.name != 'nt':
|
||
|
|
display_info("Restart your terminal or run 'source ~/.bashrc' to apply changes")
|
||
|
|
else:
|
||
|
|
display_info("New environment variables will be available in new terminal sessions")
|
||
|
|
else:
|
||
|
|
display_warning("Some environment variables could not be set persistently")
|
||
|
|
display_info("You can set them manually or check the logs for details")
|
||
|
|
|
||
|
|
return success
|
||
|
|
|
||
|
|
|
||
|
|
def validate_environment_setup(env_vars: Dict[str, str]) -> bool:
|
||
|
|
"""
|
||
|
|
Validate that environment variables are properly set
|
||
|
|
|
||
|
|
Args:
|
||
|
|
env_vars: Dictionary of environment variable names to expected values
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
True if all variables are set correctly, False otherwise
|
||
|
|
"""
|
||
|
|
logger = get_logger()
|
||
|
|
all_valid = True
|
||
|
|
|
||
|
|
for env_var, expected_value in env_vars.items():
|
||
|
|
current_value = os.environ.get(env_var)
|
||
|
|
|
||
|
|
if current_value is None:
|
||
|
|
logger.warning(f"Environment variable {env_var} is not set")
|
||
|
|
all_valid = False
|
||
|
|
elif current_value != expected_value:
|
||
|
|
logger.warning(f"Environment variable {env_var} has unexpected value")
|
||
|
|
all_valid = False
|
||
|
|
else:
|
||
|
|
logger.info(f"Environment variable {env_var} is set correctly")
|
||
|
|
|
||
|
|
return all_valid
|
||
|
|
|
||
|
|
|
||
|
|
def get_shell_name() -> str:
|
||
|
|
"""
|
||
|
|
Get the name of the current shell
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Name of the shell (e.g., 'bash', 'zsh', 'fish')
|
||
|
|
"""
|
||
|
|
shell_path = os.environ.get('SHELL', '')
|
||
|
|
if shell_path:
|
||
|
|
return Path(shell_path).name
|
||
|
|
return 'unknown'
|
||
|
|
|
||
|
|
|
||
|
|
def create_env_file(api_keys: Dict[str, str], env_file_path: Optional[Path] = None) -> bool:
|
||
|
|
"""
|
||
|
|
Create a .env file with the API keys (alternative to shell config)
|
||
|
|
|
||
|
|
Args:
|
||
|
|
api_keys: Dictionary of environment variable names to values
|
||
|
|
env_file_path: Path to the .env file (defaults to home directory)
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
True if .env file was created successfully, False otherwise
|
||
|
|
"""
|
||
|
|
if env_file_path is None:
|
||
|
|
env_file_path = Path.home() / ".env"
|
||
|
|
|
||
|
|
logger = get_logger()
|
||
|
|
|
||
|
|
try:
|
||
|
|
# Read existing .env file if it exists
|
||
|
|
existing_content = ""
|
||
|
|
if env_file_path.exists():
|
||
|
|
with open(env_file_path, 'r') as f:
|
||
|
|
existing_content = f.read()
|
||
|
|
|
||
|
|
# Prepare new content
|
||
|
|
new_lines = []
|
||
|
|
for env_var, value in api_keys.items():
|
||
|
|
line = f'{env_var}="{value}"'
|
||
|
|
|
||
|
|
# Check if this variable already exists
|
||
|
|
if f'{env_var}=' in existing_content:
|
||
|
|
logger.info(f"Variable {env_var} already exists in .env file")
|
||
|
|
else:
|
||
|
|
new_lines.append(line)
|
||
|
|
|
||
|
|
# Append new lines if any
|
||
|
|
if new_lines:
|
||
|
|
with open(env_file_path, 'a') as f:
|
||
|
|
if existing_content and not existing_content.endswith('\n'):
|
||
|
|
f.write('\n')
|
||
|
|
f.write('# SuperClaude API Keys\n')
|
||
|
|
for line in new_lines:
|
||
|
|
f.write(line + '\n')
|
||
|
|
|
||
|
|
# Set file permissions (readable only by owner)
|
||
|
|
env_file_path.chmod(0o600)
|
||
|
|
|
||
|
|
display_success(f"Created .env file at {env_file_path}")
|
||
|
|
logger.info(f"Created .env file with {len(new_lines)} new variables")
|
||
|
|
|
||
|
|
return True
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"Failed to create .env file: {e}")
|
||
|
|
display_warning(f"Could not create .env file: {e}")
|
||
|
|
return False
|