Skip to main content
Glama

Voice Mode

by mbailey
build_hooks.py4.92 kB
"""Build hooks for compiling the frontend during Python package build.""" import os import shutil import subprocess import sys from pathlib import Path from typing import Any, Dict from hatchling.builders.hooks.plugin.interface import BuildHookInterface class CustomBuildHook(BuildHookInterface): """Custom build hook to compile the Next.js frontend.""" PLUGIN_NAME = "custom" def initialize(self, version: str, build_data: Dict[str, Any]) -> None: """Initialize the build hook and compile frontend if needed.""" super().initialize(version, build_data) # Only build frontend for wheel builds (not sdist) if self.target_name != "wheel": return frontend_dir = Path("voice_mode/frontend") if not frontend_dir.exists(): print("Frontend directory not found, skipping frontend build") return # Check if we should build the frontend should_build = os.environ.get("BUILD_FRONTEND", "auto").lower() if should_build == "false": print("Skipping frontend build (BUILD_FRONTEND=false)") return elif should_build == "true": print("Building frontend (BUILD_FRONTEND=true)") self._build_frontend(frontend_dir) elif should_build == "auto": # Auto-detect: build if Node.js is available and no build exists build_dir = frontend_dir / ".next" if build_dir.exists(): print("Found existing frontend build, skipping rebuild") return elif self._check_nodejs(): print("Node.js available, building frontend automatically") self._build_frontend(frontend_dir) else: print("Node.js not available, including source files only") print("Users will need Node.js for development mode") def _check_nodejs(self) -> bool: """Check if Node.js is available.""" try: subprocess.run(["node", "--version"], capture_output=True, check=True) return True except (subprocess.CalledProcessError, FileNotFoundError): return False def _build_frontend(self, frontend_dir: Path) -> None: """Build the frontend using available package manager.""" print("Building Next.js frontend for production...") # Change to frontend directory original_cwd = os.getcwd() try: os.chdir(frontend_dir) # Check if dependencies are installed if not (frontend_dir / "node_modules").exists(): print("Installing frontend dependencies...") self._install_dependencies() # Build the frontend print("Compiling frontend...") env = os.environ.copy() env["BUILD_STANDALONE"] = "true" subprocess.run( ["npm", "run", "build:standalone"], check=True, env=env ) print("✅ Frontend built successfully") # Verify build output build_dir = frontend_dir / ".next" if build_dir.exists(): standalone_dir = build_dir / "standalone" static_dir = build_dir / "static" if standalone_dir.exists(): print(f" Standalone server: {standalone_dir}") if static_dir.exists(): print(f" Static assets: {static_dir}") else: raise RuntimeError("Build completed but .next directory not found") except subprocess.CalledProcessError as e: print(f"❌ Frontend build failed: {e}") print(" Users will need to run the frontend in development mode") # Don't fail the Python build, just warn except Exception as e: print(f"❌ Unexpected error during frontend build: {e}") # Don't fail the Python build finally: os.chdir(original_cwd) def _install_dependencies(self) -> None: """Install frontend dependencies using available package manager.""" # Try package managers in order of preference for pm in ["pnpm", "npm", "yarn"]: try: subprocess.run([pm, "--version"], capture_output=True, check=True) print(f"Using {pm} to install dependencies...") subprocess.run([pm, "install"], check=True) return except (subprocess.CalledProcessError, FileNotFoundError): continue raise RuntimeError("No package manager found (tried pnpm, npm, yarn)")

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mbailey/voicemode'

If you have feedback or need assistance with the MCP directory API, please join our Discord server