import os import sys import shutil import subprocess import json import platform import time from pathlib import Path # --- Helpers --- def run_cmd(cmd, shell=False): print(f"Running: {' '.join(cmd) if isinstance(cmd, list) else cmd}") subprocess.check_call(cmd, shell=shell) def get_home(): return Path.home() def set_unix_env_var(name, value): """Appends export command to shell config files""" if not value: return shell = os.environ.get("SHELL", "/bin/bash") rc_files = set() # Detect shell config files home = get_home() if "zsh" in shell: rc_files.add(home / ".zshrc") rc_files.add(home / ".zprofile") elif "bash" in shell: rc_files.add(home / ".bashrc") rc_files.add(home / ".bash_profile") else: rc_files.add(home / ".profile") entry = f'\nexport {name}="{value}"' for rc in rc_files: if not rc.exists(): continue # Only append to existing files try: content = rc.read_text(encoding='utf-8') if f'export {name}=' in content: print(f"Update: {name} already exists in {rc.name}, skipping append (manual check recommended).") else: with open(rc, "a", encoding='utf-8') as f: f.write(entry) print(f"✅ Added {name} to {rc.name}") except Exception as e: print(f"⚠️ Could not write to {rc}: {e}") # --- Steps --- def step1_init_files(): print("\n[Api/Files] Running Step 1: Project Initialization...") try: # Run Step1_init_project_files.py run_cmd([sys.executable, "Step1_init_project_files.py"]) except Exception as e: print(f"Step 1 failed: {e}") sys.exit(1) def step2_brain_system_prompt(): print("\n[Config] Running Step 2: Configure Brain Consultant Persona...") src = Path("brain-consultant.md").resolve() if not src.exists(): print(f"Error: {src} not found.") return dest_dir = get_home() / ".claude" / "agents" dest_dir.mkdir(parents=True, exist_ok=True) dest = dest_dir / "brain-consultant.md" shutil.copy2(src, dest) print(f"✅ Copied Persona to: {dest}") def step3_setup_mcp(): print("\n[MCP] Running Step 3: Setup MCP Server...") script_path = Path("platform_functions.py").resolve() if not script_path.exists(): print("Error: platform_functions.py not found.") sys.exit(1) print("Installing Python dependencies for MCP...") pip_cmd = [sys.executable, "-m", "pip", "install", "playwright", "beautifulsoup4", "pandas", "requests", "mcp"] run_cmd(pip_cmd) print("Installing Playwright browsers...") run_cmd([sys.executable, "-m", "playwright", "install", "chromium"]) # Configure Claude MCP print("Configuring Claude MCP...") # Remove old try: run_cmd(["claude", "mcp", "remove", "brain-mcp"]) except: pass # Ignore if not exists # Add new # On Unix we just call python3 directly # Using sys.executable to ensure we use the same python env mcp_cmd = ["claude", "mcp", "add", "--scope", "user", "brain-mcp", "--", sys.executable, str(script_path)] try: run_cmd(mcp_cmd) except Exception as e: print("Note: 'claude mcp add' might have failed if clauce CLI is not logged in or ready. Continuing to config edit...") # Edit config for timeout config_path = get_home() / ".claude.json" if config_path.exists(): try: with open(config_path, 'r', encoding='utf-8') as f: config = json.load(f) # Ensure structure if "mcpServers" not in config: config["mcpServers"] = {} if "brain-mcp" not in config["mcpServers"]: config["mcpServers"]["brain-mcp"] = {} brain_mcp = config["mcpServers"]["brain-mcp"] brain_mcp["timeout"] = 900 brain_mcp["description"] = "WorldQuant BRAIN Platform MCP Server - Comprehensive trading platform integration. Credentials in user_config.json. Docs/Forum support." with open(config_path, 'w', encoding='utf-8') as f: json.dump(config, f, indent=2, ensure_ascii=False) print("✅ Updated .claude.json with timeout/description") except Exception as e: print(f"Failed to update config json: {e}") def step4_api_config(): print("\n[API] Running Step 4: Configure API Model...") # We will import Step4 module to use its interactive logic, but we need to patch the env var setter # Because Step4 currently uses PowerShell try: # Load Step4 as a module import importlib.util spec = importlib.util.spec_from_file_location("Step4", "Step4_SetAPI_And_Check_LLMModel.py") step4_module = importlib.util.module_from_spec(spec) # Monkey patch the windows env var function step4_module.set_windows_env_var = set_unix_env_var # Execute spec.loader.exec_module(step4_module) # Run main if hasattr(step4_module, "main"): step4_module.main() except Exception as e: print(f"Error running Step 4 logic: {e}") print("Fallback: Please manually set ANTHROPIC_BASE_URL and ANTHROPIC_API_KEY in your shell.") def main(): print("=== WorldQuant BRAIN Setup (Linux/Mac) ===") # Prereq check (Runtime) if not shutil.which("claude"): print("❌ 'claude' command not found. Please install it via 'npm install -g @anthropic-ai/claude-code'") sys.exit(1) step1_init_files() step2_brain_system_prompt() step3_setup_mcp() step4_api_config() print("\n✅ Setup Complete!") print("Please RESTART your terminal to ensure environment variables are loaded.") print("Then run: claude --agent brain-consultant") if __name__ == "__main__": main()