Gemini
fix: Resolve runtime errors and timeout issues\n\n- Create writable directories for logs and Hugging Face cache.\n- Set TRANSFORMERS_CACHE environment variable.\n- Fix SyntaxWarning in lpm_kernel/utils.py.\n- Disable ChromaDB telemetry to prevent posthog errors.
e09e6c3
#!/bin/bash
# Import utility scripts
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/utils/logging.sh"
source "$SCRIPT_DIR/utils/os_detection.sh"
source "$SCRIPT_DIR/utils/install_config.sh"
source "$SCRIPT_DIR/utils/python_tools.sh"
# Version
VERSION="1.0.0"
# Total number of stages
TOTAL_STAGES=6
CURRENT_STAGE=0
STAGE_NAME=""
# Trap ctrl-c and call cleanup
trap cleanup INT
# Cleanup function to restore terminal settings
cleanup() {
echo -e "\n${YELLOW}Setup interrupted.${NC}"
exit 1
}
# Display title and logo
display_header() {
local title="$1"
echo ""
echo -e "${CYAN}"
echo ' ███████╗███████╗ ██████╗ ██████╗ ███╗ ██╗██████╗ ███╗ ███╗███████╗'
echo ' ██╔════╝██╔════╝██╔════╝██╔═══██╗████╗ ██║██╔══██╗ ████╗ ████║██╔════╝'
echo ' ███████╗█████╗ ██║ ██║ ██║██╔██╗ ██║██║ ██║█████╗██╔████╔██║█████╗ '
echo ' ╚════██║██╔══╝ ██║ ██║ ██║██║╚██╗██║██║ ██║╚════╝██║╚██╔╝██║██╔══╝ '
echo ' ███████║███████╗╚██████╗╚██████╔╝██║ ╚████║██████╔╝ ██║ ╚═╝ ██║███████╗'
echo ' ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚═════╝ ╚═╝ ╚═╝╚══════╝'
echo -e "${NC}"
echo -e "${BOLD}Second-Me Setup Script v${VERSION}${NC}"
echo -e "${GRAY}$(date)${NC}\n"
if [ -n "$title" ]; then
echo -e "${CYAN}====== $title ======${NC}"
echo ""
fi
}
# Display stage start
display_stage() {
local stage_num=$1
local stage_name=$2
CURRENT_STAGE=$stage_num
STAGE_NAME=$stage_name
echo ""
echo -e "${CYAN}====== Stage $stage_num/$TOTAL_STAGES: $stage_name ======${NC}"
echo ""
}
# Setup and configure package managers (npm)
check_npm() {
log_step "Checking npm installation..."
# Check if npm is already installed
if ! command -v npm &>/dev/null; then
log_error "npm not found - please install npm manually"
# Get system identification and show installation recommendations
local system_id=$(get_system_id)
get_npm_recommendation "$system_id"
return 1
fi
log_success "npm check passed"
return 0
}
# Check Node.js installation
check_node() {
log_step "Checking Node.js installation..."
local node_cmd=""
# Check for node command
if command -v node &>/dev/null; then
node_cmd="node"
# Also check for nodejs command as it's used on some Linux distributions
elif command -v nodejs &>/dev/null; then
node_cmd="nodejs"
else
log_error "Node.js is not installed, please install Node.js manually"
# Get system identification and show installation recommendations
local system_id=$(get_system_id)
get_node_recommendation "$system_id"
return 1
fi
# Check version (if needed)
local version=$($node_cmd --version 2>&1 | sed 's/v//')
log_success "Node.js check passed, using $node_cmd version $version"
return 0
}
# Check if command exists
check_command() {
if ! command -v $1 &> /dev/null; then
return 1
fi
return 0
}
# Helper function to install dependencies
install_python_dependency() {
# Install Python packages using Poetry
log_step "Installing Python packages using Poetry"
# Check if pyproject.toml exists
if [ ! -f "pyproject.toml" ]; then
log_error "Missing pyproject.toml file"
return 1
fi
# Update lockfile and install dependencies
log_info "Updating Poetry lockfile..."
if ! poetry lock --no-cache; then
log_error "Failed to update Poetry lockfile"
return 1
fi
# Install dependencies
log_info "Using Poetry to install dependencies..."
if ! poetry install --no-root --no-interaction; then
log_error "Failed to install dependencies using Poetry"
return 1
fi
# Verify key packages are installed using Poetry's own environment
log_info "Verifying key packages using Poetry environment..."
local required_packages=("flask" "chromadb" "langchain")
for pkg in "${required_packages[@]}"; do
if ! poetry run python -c "import $pkg" 2>/dev/null; then
log_error "Package '$pkg' is not installed correctly in Poetry environment"
return 1
else
log_info "Package '$pkg' is installed correctly in Poetry environment"
fi
done
# Get and save the Poetry environment path
local poetry_env_path=$(poetry env info -p 2>/dev/null)
if [ -n "$poetry_env_path" ]; then
log_info "Poetry virtual environment is located at: $poetry_env_path"
# Create an activation script for convenience
create_poetry_activate_script "$poetry_env_path"
fi
log_success "Python environment setup completed"
log_info "------------------------------------------------------------------------------"
log_info "To use this Python environment, you can:"
log_info "1. Run 'poetry shell' to open a new shell with the virtual environment activated"
log_info "2. Run 'source .poetry-venv/activate' to activate the environment in your current shell"
log_info "3. Use 'poetry run python script.py' to run a single command without activating the environment"
log_info "------------------------------------------------------------------------------"
return 0
}
# Create a convenient activation script for the Poetry environment
create_poetry_activate_script() {
local env_path="$1"
local activate_dir=".poetry-venv"
local activate_script="$activate_dir/activate"
# Create directory if it doesn't exist
mkdir -p "$activate_dir"
# Create activation script
cat > "$activate_script" << EOF
#!/bin/bash
# Activation script for Poetry virtual environment
# Source the actual virtual environment activate script
source "$env_path/bin/activate"
# Print confirmation message
echo "Poetry virtual environment activated: $env_path"
echo "Use 'deactivate' command to exit this environment"
EOF
# Make script executable
chmod +x "$activate_script"
log_info "Created Poetry environment activation script at: $activate_script"
}
install_graphrag() {
log_step "Installing graphrag"
# Check the current graphrag version in Poetry environment
log_step "Checking graphrag version in Poetry environment"
GRAPHRAG_VERSION=$(poetry run pip show graphrag 2>/dev/null | grep "Version:" | cut -d " " -f2)
GRAPHRAG_TARGET="1.2.1.dev27"
GRAPHRAG_LOCAL_PATH="dependencies/graphrag-${GRAPHRAG_TARGET}.tar.gz"
if [ "$GRAPHRAG_VERSION" != "$GRAPHRAG_TARGET" ]; then
log_info "Installing correct version of graphrag in Poetry environment..."
if [ -f "$GRAPHRAG_LOCAL_PATH" ]; then
log_info "Installing graphrag from local file using Poetry..."
if ! poetry run pip install --force-reinstall "$GRAPHRAG_LOCAL_PATH"; then
log_error "Failed to install graphrag from local file"
return 1
fi
else
log_error "Local graphrag package not found at: $GRAPHRAG_LOCAL_PATH"
log_error "Please ensure the graphrag package exists in the dependencies directory"
return 1
fi
log_success "Graphrag installed successfully"
else
log_success "Graphrag version is correct, skipping installation"
fi
return 0
}
# Build llama.cpp
build_llama() {
log_section "BUILDING LLAMA.CPP"
LLAMA_LOCAL_ZIP="dependencies/llama.cpp.zip"
# Check if llama.cpp directory exists
if [ ! -d "llama.cpp" ]; then
log_info "Setting up llama.cpp..."
if [ -f "$LLAMA_LOCAL_ZIP" ]; then
log_info "Using local llama.cpp archive..."
if ! unzip -q "$LLAMA_LOCAL_ZIP"; then
log_error "Failed to extract local llama.cpp archive"
return 1
fi
else
log_error "Local llama.cpp archive not found at: $LLAMA_LOCAL_ZIP"
log_error "Please ensure the llama.cpp.zip file exists in the dependencies directory"
return 1
fi
else
log_info "Found existing llama.cpp directory"
fi
# Check if llama.cpp has been successfully compiled
if [ -f "llama.cpp/build/bin/llama-server" ]; then
log_info "Found existing llama-server build"
# Check if executable file can be run and get version info
if version_output=$(./llama.cpp/build/bin/llama-server --version 2>&1) && [[ $version_output == version:* ]]; then
log_success "Existing llama-server build is working properly (${version_output}), skipping compilation"
return 0
else
log_warning "Existing build seems broken or incompatible, will recompile..."
fi
fi
# Enter llama.cpp directory and build
cd llama.cpp
# Clean previous build
if [ -d "build" ]; then
log_info "Cleaning previous build..."
rm -rf build
fi
# Create and enter build directory
log_info "Creating build directory..."
mkdir -p build && cd build
# Configure CMake
log_info "Configuring CMake..."
if ! cmake ..; then
log_error "CMake configuration failed"
cd ../..
return 1
fi
# Build project
log_info "Building project..."
if ! cmake --build . --config Release; then
log_error "Build failed"
cd ../..
return 1
fi
# Check build result
if [ ! -f "bin/llama-server" ]; then
log_error "Build failed: llama-server executable not found"
log_error "Expected at: bin/llama-server"
cd ../..
return 1
fi
log_success "Found llama-server at: bin/llama-server"
cd ../..
log_section "LLAMA.CPP BUILD COMPLETE"
}
# Set up frontend environment
build_frontend() {
log_section "SETTING UP FRONTEND"
FRONTEND_DIR="lpm_frontend"
# Enter frontend directory
cd "$FRONTEND_DIR" || {
log_error "Failed to enter frontend directory: $FRONTEND_DIR"
log_error "Please ensure the directory exists and you have permission to access it."
return 1
}
# Check if dependencies have been installed
if [ -d "node_modules" ]; then
log_info "Found existing node_modules, checking for updates..."
if [ -f "package-lock.json" ]; then
log_info "Using existing package-lock.json..."
# Run npm install even if package-lock.json exists to ensure dependencies are complete
log_info "Running npm install to ensure dependencies are complete..."
if ! npm install; then
log_error "Failed to install frontend dependencies with existing package-lock.json"
log_error "Try removing node_modules directory and package-lock.json, then run setup again"
cd ..
return 1
fi
else
log_info "Installing dependencies..."
if ! npm install; then
log_error "Failed to install frontend dependencies"
log_error "Check your npm configuration and network connection"
log_error "You can try running 'npm install' manually in the $FRONTEND_DIR directory"
cd ..
return 1
fi
fi
else
log_info "Installing dependencies..."
if ! npm install; then
log_error "Failed to install frontend dependencies"
log_error "Check your npm configuration and network connection"
log_error "You can try running 'npm install' manually in the $FRONTEND_DIR directory"
cd ..
return 1
fi
fi
# Verify that the installation was successful
if [ ! -d "node_modules" ]; then
log_error "node_modules directory not found after npm install"
log_error "Frontend dependencies installation failed"
cd ..
return 1
fi
log_success "Frontend dependencies installed successfully"
cd ..
log_section "FRONTEND SETUP COMPLETE"
}
# Show help information
show_help() {
echo -e "${BOLD}Second-Me Setup Script v${VERSION}${NC}"
echo -e "Usage: $0 [options] [command]"
echo
echo -e "Commands:"
echo -e " python\t\tSetup Python environment only"
echo -e " llama\t\t\tBuild llama.cpp only"
echo -e " frontend\t\tSetup frontend project only"
echo -e " (no command)\t\tPerform full installation"
echo
echo -e "Options:"
echo -e " --help\t\tShow this help information"
echo -e " --require-confirmation\tRequire confirmation when warnings are present"
echo
echo -e "Examples:"
echo -e " $0 \t\t\tPerform full installation"
echo -e " $0 python\t\tSetup Python environment only"
echo -e " $0 --require-confirmation\tRequire confirmation when warnings are present"
echo
echo -e "For a complete list of all available commands, run:"
echo -e " make help"
}
# Check system requirements
check_system_requirements() {
log_step "Checking system requirements"
# Detect system type
local system_type=$(uname -s)
log_info "Detected system type: $system_type"
# Only check macOS version if on Mac
if [[ "$system_type" == "Darwin" ]]; then
local macos_version=$(sw_vers -productVersion)
log_info "Detected macOS version: $macos_version"
local major_version=$(echo "$macos_version" | cut -d. -f1)
if [[ "$major_version" -lt 14 ]]; then
log_error "This script requires macOS 14 (Sonoma) or later. Your version: $macos_version"
return 1
fi
fi
log_success "System requirements check passed"
return 0
}
# Check required configuration files
check_config_files() {
log_step "Checking necessary configuration files"
# Check for .env file
if [[ ! -f ".env" ]]; then
log_error "Missing .env file"
return 1
fi
log_success "All necessary configuration files are present"
return 0
}
# Check directory permissions
check_directory_permissions() {
log_step "Checking directory permissions"
local errors=0
local directories=("." "./scripts" "./run" "./logs")
for dir in "${directories[@]}"; do
if [[ ! -w "$dir" ]]; then
log_error "Directory without write permission: $dir"
errors=$((errors + 1))
fi
done
if [[ $errors -eq 0 ]]; then
log_success "Directory permissions check passed"
return 0
else
return 1
fi
}
# Check for potential conflicts
check_potential_conflicts() {
log_info "Checking for potential conflicts"
# System requirements check
if ! check_system_requirements; then
log_error "System requirements check failed"
exit 1
fi
# Configuration files check
if ! check_config_files; then
log_error "Configuration files check failed"
exit 1
fi
# Directory permissions check
if ! check_directory_permissions; then
log_error "Directory permissions check failed"
exit 1
fi
if ! check_python; then
log_error "python check failed, please install python first"
exit 1
fi
if ! check_node; then
log_error "Node.js check failed"
exit 1
fi
if ! check_npm; then
log_error "npm check failed"
exit 1
fi
if ! check_cmake; then
log_error "cmake check and installation failed"
exit 1
fi
if ! check_poetry; then
log_error "poetry check failed, please install poetry first"
exit 1
fi
return 0
}
check_python() {
log_step "Checking for python installation"
# Get the appropriate Python command
local python_cmd=$(get_python_command)
if [ -z "$python_cmd" ]; then
log_error "python is not installed, please install python manually"
# Get system identification and show installation recommendations
local system_id=$(get_system_id)
get_python_recommendation "$system_id"
return 1
fi
# version > 3.12
local version=$($python_cmd --version 2>&1 | cut -d ' ' -f 2)
if [[ "$version" < "3.12" ]]; then
log_error "python version $version is not supported, please install python 3.12 or higher"
return 1
fi
log_success "python check passed, using $python_cmd version $version"
return 0
}
check_poetry() {
log_step "Checking for poetry installation"
if ! command -v poetry &>/dev/null; then
log_error "poetry is not installed, please install poetry manually"
# Get system identification and show installation recommendations
local system_id=$(get_system_id)
get_poetry_recommendation "$system_id"
return 1
fi
log_success "poetry check passed"
return 0
}
# Check and install cmake if not present
check_cmake() {
log_step "Checking for cmake installation"
if ! command -v cmake &>/dev/null; then
log_warning "cmake is not installed, please install cmake manually"
# Get system identification and show installation recommendations
local system_id=$(get_system_id)
get_cmake_recommendation "$system_id"
return 1
fi
log_success "cmake check passed"
return 0
}
# Check if SQLite is installed and available
check_sqlite() {
log_step "Checking SQLite"
if ! check_command "sqlite3"; then
log_warning "SQLite3 is not installed or not in your PATH"
log_error "Please install SQLite before continuing, database operations require this dependency"
# Get system identification and show installation recommendations
local system_id=$(get_system_id)
get_sqlite_recommendation "$system_id"
return 1
fi
# SQLite is installed
local version=$(sqlite3 --version | awk '{print $1}')
log_success "SQLite check passed, version $version"
return 0
}
# Parse command line arguments
parse_args() {
REQUIRE_CONFIRMATION=false
while [[ $# -gt 0 ]]; do
case $1 in
--require-confirmation)
REQUIRE_CONFIRMATION=true
shift
;;
python|llama|frontend)
COMPONENT="$1"
shift
;;
*)
log_error "Unknown argument: $1"
show_help
exit 1
;;
esac
done
}
# Main function
main() {
# Create necessary directories with write permissions
mkdir -p "./logs"
mkdir -p "./.cache/huggingface/hub"
# Display welcome message
display_header "Second-Me Complete Installation"
# Parse command line arguments
parse_args "$@"
# All pre-installation checks
log_section "Running pre-installation checks"
# 1. Basic tools check (most fundamental)
if ! check_potential_conflicts; then
log_error "Basic tools check failed"
exit 1
fi
# Check SQLite installation
if ! check_sqlite; then
log_error "SQLite check failed"
exit 1
fi
# Start installation process
log_section "Starting installation"
if ! install_python_dependency; then
log_error "Failed to install python dependencies"
exit 1
fi
if ! install_graphrag; then
log_error "Failed to install graphrag"
exit 1
fi
# 3. Build llama.cpp
if ! build_llama; then
exit 1
fi
# 4. Build frontend
if ! build_frontend; then
exit 1
fi
log_success "Installation complete!"
return 0
}
# Start execution
main "$@"