Feat: Remove conda from setup (#195)

* feat:remove conda from setup

* cool. more code about removing conda & env

* optimize script

* add python check

* optimize setup

* optimize setup

* add warning info

* optimize check

* add node check & npm check

* add cmake install suggestion

* add poetry suggestion

* add python command check

* add python tools

* add poetry

* add graphrag poetry install command optimization

* active poetry shell

* fix duplicated log

* avoid poetry multipul active

* add sqlite3 check

* optimize sqlite3 setup suggestion

* optimize

* add gitignore

* reverse compose detect
This commit is contained in:
KKKKKKKevin 2025-04-10 19:39:26 +08:00 committed by GitHub
parent 18654c5e6d
commit 4c71dce682
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 869 additions and 2473 deletions

4
.env
View File

@ -19,10 +19,6 @@ LLM_SOURCE_PORT=5173
LLM_TARGET_PORT=8004
LLM_API_PREFIX=/api/chat
# Conda configurations
CUSTOM_CONDA_MODE=false
CONDA_DEFAULT_ENV=second-me
# Database configurations
DB_TYPE=sqlite
DB_FILE=data/sqlite/lpm.db

1
.gitignore vendored
View File

@ -8,6 +8,7 @@ __pycache__
.ruff_cache/
poetry.lock
.hf_cache/
.poetry-venv/
llama.cpp
*.ipynb

View File

@ -1,15 +1,4 @@
# Available Commands:
# Commands that don't require conda environment:
# make help - Show this help message
# make setup - Run complete installation script
# make start - Start all services
# make stop - Stop chat services
# make restart - Restart chat services
# make restart-backend - Restart only backend service
# make restart-force - Force restart and reset data
# make status - Show status of all services
.PHONY: install test format lint all setup start stop restart restart-backend restart-force help check-conda check-env docker-build docker-up docker-down docker-build-backend docker-build-frontend docker-restart-backend docker-restart-frontend docker-restart-all
.PHONY: install test format lint all setup start stop restart restart-backend restart-force help docker-build docker-up docker-down docker-build-backend docker-build-frontend docker-restart-backend docker-restart-frontend docker-restart-all
# Detect Apple Silicon without printing
ifeq ($(shell uname -s),Darwin)
@ -38,7 +27,7 @@ help:
@echo "\033[1mSecond-Me Makefile Commands\033[0m"
@echo "\033[0;90m$$(date)\033[0m\n"
@echo ""
@echo "\033[1;32m▶ MAIN COMMANDS:\033[0m"
@echo "\033[1;32m▶ LOCAL COMMANDS:\033[0m"
@echo " make setup - Complete installation"
@echo " make start - Start all services"
@echo " make stop - Stop all services"
@ -59,9 +48,6 @@ help:
@echo ""
@echo "\033[1mAll Available Commands:\033[0m"
@echo " make help - Show this help message"
@echo " make check-env - Check environment without installing"
@echo ""
@echo "\033[1mCommands that require conda environment:\033[0m"
@echo " make install - Install project dependencies"
@echo " make test - Run tests"
@echo " make format - Format code"
@ -73,45 +59,33 @@ help:
echo " Apple Silicon detected - Docker commands will use PLATFORM=apple"; \
fi
# Check if in conda environment
check-conda:
@if [ -z "$$CONDA_DEFAULT_ENV" ]; then \
echo "Error: Please activate conda environment first!"; \
exit 1; \
fi
# Check environment without installing
check-env:
zsh ./scripts/setup.sh --check-only
# Commands that don't require conda environment
setup:
zsh ./scripts/setup.sh
./scripts/setup.sh
start:
zsh ./scripts/start.sh
./scripts/start.sh
stop:
zsh ./scripts/stop.sh
./scripts/stop.sh
restart:
zsh ./scripts/restart.sh
./scripts/restart.sh
restart-backend:
zsh ./scripts/restart-backend.sh
./scripts/restart-backend.sh
restart-force:
zsh ./scripts/restart-force.sh
./scripts/restart-force.sh
status:
zsh ./scripts/status.sh
./scripts/status.sh
# Docker commands
# Set Docker environment variable for all Docker commands
docker-%: export IN_DOCKER_ENV=1
# 检测是否安装了 docker compose 插件
DOCKER_COMPOSE_CMD := $(shell if command -v docker compose >/dev/null 2>&1; then echo "docker compose"; else echo "docker-compose"; fi)
DOCKER_COMPOSE_CMD := $(shell if command -v docker-compose >/dev/null 2>&1; then echo "docker-compose"; else echo "docker compose"; fi)
docker-build:
$(DOCKER_COMPOSE_CMD) build
@ -146,17 +120,16 @@ docker-restart-all:
$(DOCKER_COMPOSE_CMD) build || { echo "\033[1;31m❌ Build failed! Aborting operation...\033[0m"; exit 1; }
$(DOCKER_COMPOSE_CMD) up -d
# Commands that require conda environment
install: check-conda
install:
poetry install
test: check-conda
test:
poetry run pytest tests
format: check-conda
format:
poetry run ruff format lpm_kernel/
lint: check-conda
lint:
poetry run ruff check lpm_kernel/
all: check-conda format lint test
all: format lint test

View File

@ -105,25 +105,16 @@ make help
### 🖥️ Option 2: Manual Setup (Cross-Platform Guide)
#### ✅ Prerequisites
- Miniforge/Miniconda
##### 📦 Install Dependencies
The following scripts are sourced from [`scripts/setup.sh`](https://github.com/mindverse/Second-Me/blob/master/scripts/setup.sh) and [`scripts\start_local.sh`](https://github.com/mindverse/Second-Me/blob/master/scripts/start_local.sh).
🐍 Python Environment Setup with Conda and Poetry
We recommend managing the Python environment using Miniconda, and handling dependencies with Poetry. While Conda and Poetry are independent tools, they can be used together effectively:
🐍 Python Environment Setup with Poetry
- Conda provides flexible and isolated environment management.
- Poetry offers strict and declarative dependency management.
Below is a step-by-step example of combining them:
```bash
# Set up Python Environment
conda create -n secondme python=3.12
conda activate secondme
# (Recommand) Install Poetry inside the Conda environment
# This avoids using system-wide Poetry and keeps dependencies isolated
pip install poetry
# (Optional) Set a custom Python package index (e.g., TUNA mirror for better speed in China)

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +0,0 @@
name: second-me # Generic name, actual environment name will be specified by command line argument
channels:
- conda-forge
- defaults
dependencies:
- python=3.12
- pip
- pip:
- poetry>=1.7.1 # Base package management tool
- poetry-core>=1.8.1 # Core components of poetry
- poetry-plugin-export>=1.6.0 # Poetry export plugin

View File

@ -15,14 +15,6 @@ class ScriptExecutor:
def __init__(self):
# Check if running in Docker environment
self.in_docker = os.getenv("IN_DOCKER_ENV") == "1" or os.path.exists("/.dockerenv")
# Only check conda environment if not in Docker
if not self.in_docker:
self.conda_env = os.getenv("CONDA_DEFAULT_ENV")
if not self.conda_env:
raise ValueError("CONDA_DEFAULT_ENV environment variable is not set and not running in Docker")
else:
self.conda_env = "docker-env" # Use a placeholder for Docker
def execute(
self,
@ -33,7 +25,7 @@ class ScriptExecutor:
log_file: Optional[str] = None,
) -> Dict[str, Any]:
"""
Execute scripts in the specified conda environment or directly in Docker
Execute scripts directly
Args:
script_path: Script path or command
@ -47,39 +39,15 @@ class ScriptExecutor:
"""
try:
# Build the complete command
if self.in_docker:
# In Docker, directly execute Python or the command
if script_path.endswith(".py"):
cmd = ["python", script_path]
else:
cmd = [script_path]
if script_path.endswith(".py"):
# Python script
cmd = ["python", "-u", script_path] # Add -u parameter to disable output buffering
elif script_path.endswith(".sh"):
# Shell script
cmd = ["bash", "-x", script_path] # Add -x parameter to display executed commands
else:
# In conda environment
if script_path.endswith(".py"):
# Python script
cmd = [
"conda",
"run",
"-n",
self.conda_env,
"python",
"-u",
script_path,
] # Add -u parameter to disable output buffering
elif script_path.endswith(".sh"):
# Shell script
cmd = [
"conda",
"run",
"-n",
self.conda_env,
"bash",
"-x",
script_path,
] # Add -x parameter to display executed commands
else:
# Other commands
cmd = ["conda", "run", "-n", self.conda_env, script_path]
# Other commands
cmd = [script_path]
# Add additional parameters
if args:

View File

@ -35,17 +35,9 @@ class ScriptRunner:
timestamp = time.strftime("%Y%m%d_%H%M%S")
return os.path.join(log_dir, f"{script_type}_{timestamp}.log")
def _check_conda_env(self) -> Optional[str]:
"""
Check current conda environment
Returns:
Optional[str]: conda environment name, returns None if not found
"""
return os.environ.get("CONDA_DEFAULT_ENV")
def _check_execution_env(self) -> Dict[str, str]:
"""
Get current execution environment information, supporting conda, docker or regular system environment
Get current execution environment information, supporting docker or regular system environment
Returns:
Dict[str, str]: Dictionary containing environment type and detailed information
"""
@ -60,13 +52,6 @@ class ScriptRunner:
env_info["details"] = "docker-env-variable"
return env_info
# Check if in conda environment
conda_env = self._check_conda_env()
if conda_env:
env_info["type"] = "conda"
env_info["details"] = conda_env
return env_info
# Regular system environment
try:
import platform

View File

@ -1,299 +0,0 @@
#!/bin/bash
# This file contains utility functions for conda initialization and management
# It is used by both setup.sh and start.sh to avoid code duplication
# Color definitions (if not already defined)
if [ -z "$RED" ]; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
BOLD='\033[1m'
NC='\033[0m' # No Color
fi
# Logging functions (if not already defined)
if ! type log_info > /dev/null 2>&1; then
# Get current timestamp
get_timestamp() {
date "+%Y-%m-%d %H:%M:%S"
}
# Print formatted log messages
log_info() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${GREEN}[INFO]${NC} $1"
}
log_success() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${RED}[ERROR]${NC} $1"
}
fi
# Find and source conda.sh script from a specified conda root or common locations
find_and_source_conda_sh() {
local conda_root="$1"
local return_path="$2"
# If conda_root is provided, try to find conda.sh directly
if [[ -n "$conda_root" ]]; then
local conda_sh="$conda_root/etc/profile.d/conda.sh"
if [[ -f "$conda_sh" ]]; then
log_info "Found conda.sh script at $conda_sh"
source "$conda_sh"
# If a return path variable is provided, store the path in that variable
if [[ -n "$return_path" ]]; then
eval "$return_path=\"$conda_sh\""
fi
return 0
else
log_info "conda.sh not found at specified location: $conda_sh"
log_info "Trying common locations..."
fi
fi
# Try common locations as fallback
local conda_sh_paths=(
"$HOME/anaconda3/etc/profile.d/conda.sh"
"$HOME/miniconda3/etc/profile.d/conda.sh"
"$HOME/miniconda/etc/profile.d/conda.sh"
"$HOME/anaconda/etc/profile.d/conda.sh"
"$HOME/opt/anaconda3/etc/profile.d/conda.sh"
"$HOME/opt/miniconda3/etc/profile.d/conda.sh"
"/opt/homebrew/anaconda3/etc/profile.d/conda.sh"
"/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh"
"/opt/anaconda3/etc/profile.d/conda.sh"
"/opt/miniconda3/etc/profile.d/conda.sh"
"/usr/local/anaconda3/etc/profile.d/conda.sh"
"/usr/local/miniconda3/etc/profile.d/conda.sh"
"/usr/local/Caskroom/miniconda/base/etc/profile.d/conda.sh"
"/usr/local/Caskroom/anaconda/base/etc/profile.d/conda.sh"
"/usr/share/miniconda3/etc/profile.d/conda.sh"
"/usr/share/anaconda3/etc/profile.d/conda.sh"
"/usr/local/share/miniconda3/etc/profile.d/conda.sh"
"/usr/local/share/anaconda3/etc/profile.d/conda.sh"
)
local found=false
for conda_sh_path in "${conda_sh_paths[@]}"; do
if [[ -f "$conda_sh_path" ]]; then
log_info "Found conda.sh script at $conda_sh_path"
source "$conda_sh_path"
found=true
# If a return path variable is provided, store the path in that variable
if [[ -n "$return_path" ]]; then
eval "$return_path=\"$conda_sh_path\""
fi
break
fi
done
if [[ "$found" = false ]]; then
log_error "Could not find conda.sh script in any common locations"
return 1
fi
log_info "[CONDA READY] Successfully initialized conda from common locations: $conda_sh_path"
return 0
}
# Verify if conda command is working properly
verify_conda_command() {
local conda_path="$1"
# Try to run conda --version
if ! "$conda_path" --version &>/dev/null; then
return 1
fi
return 0
}
# Try to use a conda executable and initialize it
try_source_conda_sh_by_conda_executable() {
local conda_path="$1"
local source_description="$2"
if [[ ! -f "$conda_path" ]]; then
log_info "[CONDA CHECK] Checking $source_description: $conda_path (not found)"
return 1
fi
log_info "[CONDA CHECK] Checking $source_description: $conda_path (found, verifying...)"
# Determine conda root directory from executable location
local conda_root="$(dirname "$(dirname "$conda_path")")"
# Try to find and source conda.sh
if ! find_and_source_conda_sh "$conda_root"; then
log_error "[CONDA INIT FAILED] Found conda at $conda_path but could not find conda.sh"
return 1
fi
# Verify conda is working
if ! verify_conda_command "$conda_path"; then
log_error "[CONDA VERIFICATION FAILED] Found conda at $conda_path but command is not working"
return 1
fi
log_success "[CONDA READY] Successfully initialized conda from $source_description: $conda_path"
echo "$conda_path"
return 0
}
# Check for conda command and initialize it
try_source_conda_sh_all() {
local conda_cmd
# METHOD 1: Check if CONDA_EXE environment variable is set
if [[ -n "$CONDA_EXE" ]]; then
if conda_cmd=$(try_source_conda_sh_by_conda_executable "$CONDA_EXE" "CONDA_EXE environment variable"); then
log_info "[CONDA READY] Successfully initialized conda from CONDA_EXE environment variable: $CONDA_EXE"
return 0
fi
fi
# METHOD 2: Check if conda executable is in PATH
local conda_in_path="$(command -v conda 2>/dev/null)"
if [[ -n "$conda_in_path" ]]; then
if conda_cmd=$(try_source_conda_sh_by_conda_executable "$conda_in_path" "PATH"); then
log_info "[CONDA READY] Successfully initialized conda from PATH: $conda_in_path"
return 0
fi
fi
# METHOD 3: Check common locations for conda executable
local common_conda_paths=(
"$HOME/miniconda3/bin/conda"
"$HOME/anaconda3/bin/conda"
"$HOME/miniconda/bin/conda"
"$HOME/anaconda/bin/conda"
"$HOME/opt/anaconda3/bin/conda"
"$HOME/opt/miniconda3/bin/conda"
"/opt/homebrew/Caskroom/miniconda/base/bin/conda"
"/opt/miniconda3/bin/conda"
"/opt/anaconda3/bin/conda"
"/usr/local/miniconda3/bin/conda"
"/usr/local/anaconda3/bin/conda"
"/usr/local/Caskroom/miniconda/base/bin/conda"
"/usr/local/Caskroom/anaconda/base/bin/conda"
"/usr/share/miniconda3/bin/conda"
"/usr/share/anaconda3/bin/conda"
"/usr/local/share/miniconda3/bin/conda"
"/usr/local/share/anaconda3/bin/conda"
)
# Search through common locations for conda executable
for conda_path in "${common_conda_paths[@]}"; do
if conda_cmd=$(try_source_conda_sh_by_conda_executable "$conda_path" "common locations"); then
log_info "[CONDA READY] Successfully initialized conda from common locations: $conda_path"
return 0
fi
done
# Last resort: Try to find conda.sh directly without finding conda executable first
log_info "[LAST RESORT] Trying to find conda.sh directly from common locations"
if find_and_source_conda_sh "/opt/homebrew/Caskroom/miniconda/base"; then
# If conda.sh was found and sourced, conda command should be available
if command -v conda &>/dev/null; then
log_info "[CONDA COMMAND AVAILABLE] After sourcing conda.sh, conda command is available"
echo "conda"
return 0
fi
fi
# If we reach here, we couldn't find conda executable or conda.sh anywhere
log_error "[CONDA EXECUTABLE NOT FOUND] conda executable not found in PATH or common locations"
return 1
}
# Check if custom conda mode is enabled
is_custom_conda_mode() {
if [ -f ".env" ]; then
local custom_mode=$(grep '^CUSTOM_CONDA_MODE=' .env | cut -d '=' -f2)
if [ "$custom_mode" = "true" ]; then
log_warning "Custom conda mode is enabled"
return 0
fi
fi
return 1
}
# Verify if current conda environment matches the required one
verify_conda_env() {
if [ -f ".env" ]; then
local env_name=$(grep '^CONDA_DEFAULT_ENV=' .env | cut -d '=' -f2)
if [ -n "$env_name" ]; then
log_info "Verifying conda environment..."
# Verify current environment exists in system
local current_env=$(conda info --envs 2>/dev/null | grep '*' | awk '{print $1}')
if [ "$current_env" != "$env_name" ]; then
log_warning "Please activate the specified conda environment: conda activate $env_name"
log_info "Current environment: $current_env"
return 1
fi
log_success "Conda environment verified: $env_name"
return 0
fi
fi
log_error "CONDA_DEFAULT_ENV not set in .env file"
return 1
}
# Initialize conda environment
initialize_conda() {
log_info "Initializing conda environment..."
# Use our optimized try_source_conda_sh_all function to find and initialize conda
local conda_cmd
if ! conda_cmd=$(try_source_conda_sh_all); then
log_error "Failed to initialize conda environment"
return 1
fi
# Run conda init to ensure shell integration is properly set up
log_info "Running conda init to set up shell integration..."
if ! conda init zsh bash; then
log_warning "Conda init may have encountered issues, but we'll try to continue"
else
log_success "Conda init completed successfully"
fi
# Source conda.sh to apply changes immediately
log_info "Sourcing conda.sh to apply changes immediately..."
# Determine conda root directory from conda command
local conda_root=""
if [ -n "$conda_cmd" ]; then
conda_root=$(dirname $(dirname "$conda_cmd"))
log_info "Determined conda root directory: $conda_root"
fi
local conda_sh_path
if find_and_source_conda_sh "$conda_root" conda_sh_path; then
log_success "Successfully sourced conda.sh from: $conda_sh_path"
else
log_warning "Could not source conda.sh, changes will apply after shell restart"
fi
log_success "Conda initialized successfully: $conda_cmd"
return 0
}

View File

@ -1,62 +1,18 @@
#!/bin/bash
# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Get current timestamp
get_timestamp() {
date "+%Y-%m-%d %H:%M:%S"
}
# Print formatted log messages
log_info() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${GREEN}[INFO]${NC} $1"
}
log_success() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${RED}[ERROR]${NC} $1"
}
log_step() {
echo -e "\n${GRAY}[$(get_timestamp)]${NC} ${BLUE}[STEP]${NC} ${BOLD}$1${NC}"
}
log_debug() {
if [[ "${DEBUG}" == "true" ]]; then
echo -e "${GRAY}[$(get_timestamp)]${NC} ${MAGENTA}[DEBUG]${NC} $1"
fi
}
log_section() {
echo -e "\n${CYAN}════════════════════════════════════════════════════════════════════════════════${NC}"
echo -e "${CYAN} $1${NC}"
echo -e "${CYAN}════════════════════════════════════════════════════════════════════════════════${NC}\n"
}
# Source the logging utilities
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/utils/logging.sh"
# Load configuration from .env file
load_env() {
if [ -f .env ]; then
# Load necessary environment variables
export LOCAL_BASE_DIR=$(grep '^LOCAL_BASE_DIR=' .env | cut -d '=' -f2)
# Only load necessary environment variables
export LOCAL_APP_PORT=$(grep '^LOCAL_APP_PORT=' .env | cut -d '=' -f2)
else
log_error ".env file not found!"
return 1
# Use default port if .env not found
export LOCAL_APP_PORT=8002
log_info "Using default port: ${LOCAL_APP_PORT}"
fi
}

View File

@ -1,35 +1,8 @@
#!/bin/bash
# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Get current timestamp
get_timestamp() {
date "+%Y-%m-%d %H:%M:%S"
}
# Print formatted log messages
log_info() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${GREEN}[INFO]${NC} $1"
}
log_warning() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${YELLOW}[WARN]${NC} $1"
}
log_section() {
echo -e "\n${CYAN}════════════════════════════════════════════════════════════════════════════════${NC}"
echo -e "${CYAN} $1${NC}"
echo -e "${CYAN}════════════════════════════════════════════════════════════════════════════════${NC}\n"
}
# Source the logging utilities
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/utils/logging.sh"
# Main function to force restart services
restart_services_force() {

View File

@ -1,31 +1,8 @@
#!/bin/bash
# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Get current timestamp
get_timestamp() {
date "+%Y-%m-%d %H:%M:%S"
}
# Print formatted log messages
log_info() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${GREEN}[INFO]${NC} $1"
}
log_section() {
echo -e "\n${CYAN}════════════════════════════════════════════════════════════════════════════════${NC}"
echo -e "${CYAN} $1${NC}"
echo -e "${CYAN}════════════════════════════════════════════════════════════════════════════════${NC}\n"
}
# Source the logging utilities
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/utils/logging.sh"
# Main function to restart services
restart_services() {
@ -33,11 +10,11 @@ restart_services() {
# Stop services
log_info "Stopping services..."
zsh ./scripts/stop.sh
./scripts/stop.sh
# Start services
log_info "Starting services..."
zsh ./scripts/start.sh
./scripts/start.sh
}
# Execute restart services

View File

@ -1,23 +1,15 @@
#!/bin/bash
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# 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"
# Source conda utilities
SCRIPT_DIR="$( cd "$( dirname "${0:A}" )" && pwd )"
source "$SCRIPT_DIR/conda_utils.sh"
# Total number of stages
TOTAL_STAGES=6
CURRENT_STAGE=0
@ -32,61 +24,6 @@ cleanup() {
exit 1
}
# Log a message to the console
log() {
local message="$1"
local level="${2:-INFO}"
local color="${NC}"
case $level in
INFO) color="${BLUE}" ;;
SUCCESS) color="${GREEN}" ;;
WARNING) color="${YELLOW}" ;;
ERROR) color="${RED}" ;;
DEBUG) color="${GRAY}" ;;
esac
echo -e "${color}[$(date '+%Y-%m-%d %H:%M:%S')] [${level}] ${message}${NC}"
}
# Get current timestamp
get_timestamp() {
date "+%Y-%m-%d %H:%M:%S"
}
# Print formatted log messages
log_info() {
log "$1" "INFO"
}
log_success() {
log "$1" "SUCCESS"
}
log_warning() {
log "$1" "WARNING"
}
log_error() {
log "$1" "ERROR"
}
log_step() {
echo -e "\n${GRAY}[$(get_timestamp)]${NC} ${BLUE}[STEP]${NC} ${BOLD}$1${NC}"
}
log_debug() {
if [[ "${DEBUG}" == "true" ]]; then
log "$1" "DEBUG"
fi
}
log_section() {
echo -e "\n${CYAN}════════════════════════════════════════════════════════════════════════════════${NC}"
echo -e "${CYAN} $1${NC}"
echo -e "${CYAN}════════════════════════════════════════════════════════════════════════════════${NC}\n"
}
# Display title and logo
display_header() {
local title="$1"
@ -121,62 +58,50 @@ display_stage() {
echo ""
}
# Get conda environment name from .env file
get_conda_env_name() {
if [[ -f ".env" ]]; then
local env_name=$(grep '^CONDA_DEFAULT_ENV=' .env | cut -d '=' -f2)
if [[ -n "$env_name" ]]; then
echo "$env_name"
return 0
fi
# 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
echo "second-me"
log_success "npm check passed"
return 0
}
# Setup and configure package managers (npm)
setup_npm() {
log_step "Setting up npm package manager"
# Check Node.js installation
check_node() {
log_step "Checking Node.js installation..."
# Check if npm is already installed
log_info "Checking npm installation..."
if ! command -v npm &>/dev/null; then
log_warning "npm not found - installing Node.js and npm"
if ! brew install node; then
log_error "Failed to install Node.js and npm"
return 1
fi
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"
# Verify npm was installed successfully
if ! command -v npm &>/dev/null; then
log_error "npm installation failed - command not found after installation"
return 1
fi
log_success "Successfully installed Node.js and npm"
else
log_success "npm is already installed"
fi
# Configure npm settings
log_info "Configuring npm settings..."
# Set npm registry
log_info "Setting npm registry to https://registry.npmjs.org/"
npm config set registry https://registry.npmjs.org/
# Set npm cache directory
log_info "Setting npm cache directory to $HOME/.npm"
npm config set cache "$HOME/.npm"
# Verify npm configuration
if npm config list &>/dev/null; then
log_success "npm is properly configured"
else
log_error "npm configuration failed"
return 1
fi
log_success "npm setup completed"
# 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
}
@ -188,181 +113,8 @@ check_command() {
return 0
}
# Install Homebrew packages
install_brew_packages() {
log_step "Checking additional Homebrew packages"
if ! check_command brew; then
log_error "Homebrew is not installed."
log_error "Please run the setup script from the beginning."
return 1
fi
# Required brew packages
local required_packages=(
"sqlite" # Database
"make" # Build tool
)
# Check and install each package
for package in "${required_packages[@]}"; do
if ! brew list $package &>/dev/null; then
log_warning "Installing $package..."
if ! brew install $package; then
log_error "Failed to install $package"
return 1
fi
# Verify installation
if ! brew list $package &>/dev/null; then
log_error "Failed to verify $package installation"
return 1
fi
fi
done
log_success "All Homebrew packages are installed"
return 0
}
# Install conda using Homebrew
install_conda() {
log_info "Installing Miniconda using Homebrew..."
brew install --cask miniconda
local brew_result=$?
if [ $brew_result -ne 0 ]; then
log_error "Failed to install Miniconda (exit code: $brew_result)"
return 1
fi
# Get Miniconda installation path from Homebrew cask info
local conda_info
conda_info=$(brew info --cask miniconda)
if [ $? -ne 0 ]; then
log_error "Failed to get Miniconda installation info"
return 1
fi
# Extract conda binary path from brew info output
local conda_binary
conda_binary=$(echo "$conda_info" | grep "condabin/conda" | cut -d' ' -f1)
if [ -z "$conda_binary" ]; then
log_error "Could not find conda binary path in brew info output"
return 1
fi
# Get the base directory (two levels up from condabin)
local conda_root
conda_root=$(dirname "$(dirname "$conda_binary")")
if [ ! -d "$conda_root" ]; then
log_error "Conda base directory not found at $conda_root"
return 1
fi
log_info "Using Homebrew Miniconda installation path: $conda_root"
# Initialize conda for bash and zsh
log_info "Initializing conda for shell integration..."
# First source conda.sh to make conda command available
if ! find_and_source_conda_sh "$conda_root"; then
log_error "Could not find conda.sh after installation at $conda_root"
return 1
fi
# Now run conda init for both shells
local shells=("zsh")
for shell in "${shells[@]}"; do
log_info "Running conda init for $shell..."
if ! conda init "$shell"; then
log_warning "Failed to initialize conda for $shell shell"
else
log_success "Initialized conda for $shell shell"
fi
done
# Verify shell configurations
for shell in "${shells[@]}"; do
local rc_file="$HOME/.${shell}rc"
if [ -f "$rc_file" ] && grep -q "conda initialize" "$rc_file"; then
log_success "Verified conda initialization in $rc_file"
else
log_warning "Could not verify conda initialization in $rc_file"
fi
done
# Add helpful message about shell restart
log_info "Conda has been initialized for zsh shell"
log_info "To use conda in a new shell, either:"
log_info "1. Start a new shell session, or"
log_info "2. Run: source ~/.zshrc"
log_success "Conda installed and initialized successfully"
return 0
}
# Activate Python environment
activate_python_env() {
log_section "PYTHON ENVIRONMENT ACTIVATION"
# If custom conda mode is enabled, skip to dependency installation
if is_custom_conda_mode; then
log_info "Using custom conda environment"
goto_dependency_installation
return $?
fi
# 1. Check conda installation
log_step "Checking conda installation"
if ! try_source_conda_sh_all; then
log_error "Conda not found. It should have been installed during pre-installation checks."
return 1
fi
# 2. Get environment name
local env_name
if ! env_name=$(get_conda_env_name); then
log_error "Could not get conda environment name"
return 1
fi
# 3. Create or update environment
log_step "Activating conda environment: $env_name"
if conda env list | grep -q "^${env_name} "; then
log_info "Environment exists, updating..."
if ! conda env update -f environment.yml -n "$env_name"; then
log_error "Failed to update conda environment $env_name"
return 1
fi
else
log_info "Creating new environment... $env_name"
if ! conda env create -f environment.yml -n "$env_name"; then
log_error "Failed to create conda environment $env_name"
return 1
fi
fi
# attempt to activate conda environment
log_info "Attempting to activate conda environment: $env_name"
if ! conda activate "$env_name" 2>/dev/null; then
log_info "conda activate failed, trying alternative method..."
# if conda activate fails, try using source activate
if command -v activate &>/dev/null && ! source activate "$env_name"; then
log_error "Failed to activate conda environment using both methods"
return 1
fi
fi
log_success "Successfully activated conda environment: $env_name"
goto_dependency_installation
return $?
}
# Helper function to install dependencies
goto_dependency_installation() {
install_python_dependency() {
# Install Python packages using Poetry
log_step "Installing Python packages using Poetry"
@ -386,29 +138,77 @@ goto_dependency_installation() {
return 1
fi
# Verify key packages are installed
log_info "Verifying key packages..."
# 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 ! python -c "import $pkg" 2>/dev/null; then
log_error "Package '$pkg' is not installed correctly"
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"
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
# Check and ensure correct version of graphrag is installed
log_step "Checking graphrag version"
GRAPHRAG_VERSION=$(pip show graphrag 2>/dev/null | grep "Version:" | cut -d " " -f2)
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..."
log_info "Installing correct version of graphrag in Poetry environment..."
if [ -f "$GRAPHRAG_LOCAL_PATH" ]; then
log_info "Installing graphrag from local file..."
if ! pip install --force-reinstall "$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
@ -421,8 +221,7 @@ goto_dependency_installation() {
else
log_success "Graphrag version is correct, skipping installation"
fi
log_success "Python environment setup completed"
return 0
}
@ -565,64 +364,6 @@ build_frontend() {
log_section "FRONTEND SETUP COMPLETE"
}
# Initialize Conda environment if necessary
init_conda_env_if_necessary() {
log_section "SETTING UP SHELL INTEGRATION"
local config_file="$HOME/.zshrc"
log_info "Will update shell configuration in: $config_file"
# Add Conda
if command -v conda &>/dev/null; then
log_info "Checking Conda initialization status"
# Check if already initialized
if ! grep -q "conda initialize" "$config_file" 2>/dev/null; then
log_info "Conda not initialized, running conda init"
conda init zsh
log_success "Added Conda initialization to shell configuration"
# Source the updated config
log_info "Applying new shell configuration..."
source "$config_file"
log_success "Shell configuration applied"
else
log_info "Conda already initialized"
fi
fi
log_success "Conda environment initialized"
return 0
}
# Ensure shell config file exists and is properly backed up
ensure_shell_config() {
local config_file="$1"
if [[ ! -f "$config_file" ]]; then
log_info "Shell configuration file does not exist, creating it: $config_file"
touch "$config_file"
echo "# Shell configuration file created by Second-Me setup script on $(date)" > "$config_file"
# Add basic configuration
echo "# Set basic environment variables" >> "$config_file"
echo 'export PATH="$HOME/bin:$HOME/.local/bin:$PATH"' >> "$config_file"
log_success "Created new shell configuration file: $config_file"
else
# Backup config file
cp "$config_file" "${config_file}.bak.$(date +%Y%m%d%H%M%S)"
log_info "Created backup of $config_file"
fi
# Verify file is writable
if [[ ! -w "$config_file" ]]; then
log_error "Shell configuration file is not writable: $config_file"
return 1
fi
return 0
}
# Show help information
show_help() {
echo -e "${BOLD}Second-Me Setup Script v${VERSION}${NC}"
@ -649,89 +390,25 @@ show_help() {
# Check system requirements
check_system_requirements() {
log_section "CHECKING SYSTEM REQUIREMENTS"
log_step "Checking system requirements"
# Detect current shell
local current_shell=$(basename "$SHELL")
log_info "Detected shell: $current_shell"
# Detect system type
local system_type=$(uname -s)
log_info "Detected system type: $system_type"
# Only support zsh
if [[ "$current_shell" != "zsh" ]]; then
log_error "Only zsh shell is supported"
return 1
fi
# Check if running on macOS
if [[ "$(uname)" != "Darwin" ]]; then
log_error "This script only supports macOS"
return 1
fi
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
# Check shell config file
local config_file="$HOME/.zshrc"
if ! ensure_shell_config "$config_file"; then
log_error "Failed to setup shell configuration file"
return 1
fi
# Rest of the system checks...
# Detect system architecture
local system_arch=$(uname -m)
log_info "Detected system architecture: $system_arch"
# Check installed Homebrew architecture
if command -v brew &>/dev/null; then
local brew_path=$(command -v brew)
local brew_dir=$(dirname "$(dirname "$brew_path")")
# 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"
if [[ "$system_arch" == "arm64" && "$brew_dir" != "/opt/homebrew" ]]; then
log_warning "Detected M1/M2 chip (arm64), but Homebrew installed in $brew_dir instead of /opt/homebrew"
log_warning "This may indicate Homebrew was installed for Intel chips, which may cause performance issues"
log_warning "It is recommended to uninstall current Homebrew and reinstall the arm64 version"
# Do not force exit, just warn
elif [[ "$system_arch" != "arm64" && "$brew_dir" == "/opt/homebrew" ]]; then
log_warning "Detected Intel chip, but Homebrew installed in /opt/homebrew instead of /usr/local"
log_warning "This may indicate Homebrew was installed for M1/M2 chips, which may cause compatibility issues"
# Do not force exit, just warn
else
log_success "Homebrew architecture matches system architecture"
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
# Check installed Conda architecture
if command -v conda &>/dev/null; then
local conda_info=$(conda info --json 2>/dev/null)
if [[ $? -eq 0 ]]; then
local conda_platform=$(echo "$conda_info" | grep -o '"platform": "[^"]*"' | cut -d'"' -f4)
if [[ "$system_arch" == "arm64" && "$conda_platform" != *"arm64"* && "$conda_platform" != *"aarch64"* ]]; then
log_error "Detected M1/M2 chip (arm64), but Conda seems to be installed for Intel chips (platform: $conda_platform)"
log_error "This will cause performance issues or compatibility problems"
log_error "Please uninstall current Conda and install Miniforge (a Conda distribution optimized for Apple Silicon)"
return 1
elif [[ "$system_arch" != "arm64" && ("$conda_platform" == *"arm64"* || "$conda_platform" == *"aarch64"*) ]]; then
log_error "Detected Intel chip, but Conda seems to be installed for M1/M2 chips (platform: $conda_platform)"
log_error "This will cause compatibility issues"
log_error "Please uninstall current Conda and install the correct version for your architecture"
return 1
else
log_success "Conda architecture matches system architecture"
fi
else
log_warning "Failed to retrieve Conda information, skipping Conda architecture check"
fi
fi
log_success "System requirements check passed"
return 0
}
@ -745,12 +422,6 @@ check_config_files() {
return 1
fi
# Check for environment.yml
if [[ ! -f "environment.yml" ]]; then
log_error "Missing environment.yml file"
return 1
fi
log_success "All necessary configuration files are present"
return 0
}
@ -778,7 +449,7 @@ check_directory_permissions() {
# Check for potential conflicts
check_potential_conflicts() {
log_step "Checking for potential conflicts"
log_info "Checking for potential conflicts"
# System requirements check
if ! check_system_requirements; then
@ -786,16 +457,6 @@ check_potential_conflicts() {
exit 1
fi
# Check custom conda configuration if enabled
if is_custom_conda_mode; then
log_info "Custom conda mode is enabled, verifying environment..."
if ! verify_conda_env; then
log_error "Custom conda environment verification failed"
exit 1
fi
log_success "Custom conda environment verification passed"
fi
# Configuration files check
if ! check_config_files; then
log_error "Configuration files check failed"
@ -807,83 +468,116 @@ check_potential_conflicts() {
log_error "Directory permissions check failed"
exit 1
fi
# Check Homebrew installation
if command -v brew &>/dev/null; then
log_info "Homebrew is installed"
else
log_warning "Homebrew is not installed, attempting to install it automatically..."
# Only use local copy of the Homebrew install script
local homebrew_script="${SCRIPT_DIR}/../dependencies/homebrew_install.sh"
local brew_installed=false
if [[ -f "$homebrew_script" ]]; then
log_info "Using local Homebrew install script"
if /bin/bash "$homebrew_script"; then
# Add Homebrew to PATH for the current session
if ! add_homebrew_to_path; then
log_error "Homebrew installed but couldn't be added to PATH"
return 1
fi
# Verify Homebrew is actually installed and working
if command -v brew &>/dev/null; then
log_success "Homebrew installed successfully"
else
log_error "Homebrew installation failed: brew command not found in PATH"
return 1
fi
fi
else
log_error "Local Homebrew install script not found at: $homebrew_script"
log_error "Please ensure the Homebrew install script exists in the dependencies folder."
return 1
fi
if ! check_python; then
log_error "python check failed, please install python first"
exit 1
fi
# Check Conda installation
if command -v conda &>/dev/null; then
log_info "Conda is installed"
else
log_warning "Conda is not installed, attempting to install it automatically..."
# Check if Homebrew is available now
if command -v brew &>/dev/null; then
if ! install_conda; then
log_error "Failed to install Conda automatically"
return 1
fi
else
log_error "Cannot install Conda: Homebrew is required but not available"
return 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_and_install_cmake() {
check_cmake() {
log_step "Checking for cmake installation"
if ! command -v cmake &>/dev/null; then
log_warning "cmake is not installed, attempting to install it automatically..."
if command -v brew &>/dev/null; then
log_info "Installing cmake using Homebrew..."
if ! brew install cmake; then
log_error "Failed to install cmake using Homebrew"
return 1
fi
log_success "cmake installed successfully"
else
log_error "Cannot install cmake: Homebrew is required but not available"
return 1
fi
else
log_info "cmake is installed"
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
}
@ -910,41 +604,6 @@ parse_args() {
done
}
# Add Homebrew to PATH for the current session
add_homebrew_to_path() {
log_info "Adding Homebrew to PATH..."
local brew_path="/opt/homebrew/bin"
local config_file="$HOME/.zshrc"
if [[ -f "$brew_path/brew" ]]; then
log_info "Found Homebrew installation at: $brew_path"
# Set up Homebrew environment for current session
eval "$(/opt/homebrew/bin/brew shellenv)"
# Add Homebrew initialization to .zshrc if not already present
if ! grep -q "HOMEBREW_PREFIX" "$config_file" 2>/dev/null; then
log_info "Adding Homebrew initialization to $config_file"
echo "" >> "$config_file"
echo "# Set up Homebrew environment" >> "$config_file"
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> "$config_file"
# Source the updated config
log_info "Applying new shell configuration..."
source "$config_file"
log_success "Shell configuration applied"
else
log_info "Homebrew initialization already present in shell configuration"
fi
log_success "Homebrew added to PATH successfully"
return 0
fi
log_error "Could not find Homebrew installation at $brew_path"
return 1
}
# Main function
main() {
@ -958,32 +617,30 @@ main() {
log_section "Running pre-installation checks"
# 1. Basic tools check (most fundamental)
# install homebrew, conda if necessary
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"
# 1. Setup Conda environment
if ! activate_python_env; then
if ! install_python_dependency; then
log_error "Failed to install python dependencies"
exit 1
fi
# 2. Setup npm
if ! setup_npm; then
log_error "npm setup failed"
if ! install_graphrag; then
log_error "Failed to install graphrag"
exit 1
fi
# 2. Check and install cmake
if ! check_and_install_cmake; then
log_error "cmake check and installation failed"
exit 1
fi
# 3. Build llama.cpp
if ! build_llama; then
exit 1
@ -993,19 +650,6 @@ main() {
if ! build_frontend; then
exit 1
fi
# # 5. Initialize Conda environment
# if ! init_conda_env_if_necessary; then
# exit 1
# fi
# Source the shell configuration to ensure all changes take effect
local config_file="$HOME/.zshrc"
if [[ -f "$config_file" ]]; then
log_info "Applying final shell configuration..."
source "$config_file"
log_success "Shell configuration applied"
fi
log_success "Installation complete!"
return 0

View File

@ -3,46 +3,9 @@
# Script version
VERSION="1.0.0"
# Source conda utilities
SCRIPT_DIR="$( cd "$( dirname "${0:A}" )" && pwd )"
source "$SCRIPT_DIR/conda_utils.sh"
# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Get current timestamp
get_timestamp() {
date "+%Y-%m-%d %H:%M:%S"
}
# Print formatted log messages
log_info() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${GREEN}[INFO]${NC} $1"
}
log_success() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${RED}[ERROR]${NC} $1"
}
log_section() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${BOLD}[SECTION]${NC} $1"
}
# Source the logging utilities
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/utils/logging.sh"
# Check if port is available
check_port() {
@ -53,56 +16,102 @@ check_port() {
return 0
}
# Check if backend is healthy
# Check if backend is healthy with real-time log display
check_backend_health() {
local max_attempts=$1
local attempt=1
local backend_url="http://127.0.0.1:${LOCAL_APP_PORT}/health"
local backend_log="logs/start.log"
local log_pid=0
log_info "Waiting for backend service to be ready (showing real-time logs)..."
# Start real-time log display in background if log file exists
if [ -f "$backend_log" ]; then
echo -e "${GRAY}---Backend logs begin (real-time)---${NC}"
tail -f "$backend_log" &
log_pid=$!
fi
while [ $attempt -le $max_attempts ]; do
# Non-blocking health check
if curl -s -f "$backend_url" &>/dev/null; then
# Stop the log display process
if [ $log_pid -ne 0 ]; then
kill $log_pid >/dev/null 2>&1
echo -e "${GRAY}---Backend logs end---${NC}"
fi
return 0
fi
sleep 1
attempt=$((attempt + 1))
done
# Stop the log display process if it's still running
if [ $log_pid -ne 0 ]; then
kill $log_pid >/dev/null 2>&1
echo -e "${GRAY}---Backend logs end---${NC}"
fi
return 1
}
# Check if frontend is ready
# Check if frontend is ready with real-time log display
check_frontend_ready() {
local max_attempts=$1
local attempt=1
local frontend_log="../logs/frontend.log"
local frontend_log="logs/frontend.log"
local log_pid=0
log_info "Waiting for frontend service to be ready (showing real-time logs)..."
# Don't wait for file to exist, just start tail which will wait for the file
echo -e "${GRAY}---Frontend logs begin (real-time)---${NC}"
tail -f "$frontend_log" 2>/dev/null &
log_pid=$!
# Give a small delay to allow initial logs to appear
sleep 1
while [ $attempt -le $max_attempts ]; do
if grep -q "Local:" "$frontend_log" 2>/dev/null; then
# Non-blocking ready check - check for "Local:" in the file or the existence of the frontend URL
if grep -q "Local:" "$frontend_log" 2>/dev/null || curl -s -f "http://localhost:${LOCAL_FRONTEND_PORT}" &>/dev/null; then
# Frontend is ready! Stop the log display process
if [ $log_pid -ne 0 ]; then
kill $log_pid >/dev/null 2>&1
echo -e "${GRAY}---Frontend logs end---${NC}"
fi
# Display the frontend URL that was found in the logs
if grep -q "Local:" "$frontend_log" 2>/dev/null; then
local frontend_url=$(grep "Local:" "$frontend_log" | head -n 1)
log_success "Frontend URL detected: $frontend_url"
else
log_success "Frontend is responding at http://localhost:${LOCAL_FRONTEND_PORT}"
fi
return 0
fi
sleep 1
attempt=$((attempt + 1))
done
# Stop the log display process if it's still running
if [ $log_pid -ne 0 ]; then
kill $log_pid >/dev/null 2>&1
echo -e "${GRAY}---Frontend logs end---${NC}"
fi
return 1
}
# These functions are now sourced from conda_utils.sh
# Check if setup is complete
check_setup_complete() {
log_info "Checking if setup is complete..."
# Check conda environment
if is_custom_conda_mode; then
log_info "Custom conda mode enabled, verifying environment..."
if ! verify_conda_env; then
return 1
fi
else
if ! conda env list | grep -q "${CONDA_DEFAULT_ENV:-second-me}"; then
log_error "Conda environment '${CONDA_DEFAULT_ENV:-second-me}' not found. Please run 'make setup' first."
return 1
fi
fi
# Check if frontend dependencies are installed
if [ ! -d "lpm_frontend/node_modules" ] && [ "$BACKEND_ONLY" != "true" ]; then
@ -132,16 +141,14 @@ start_services() {
if ! check_setup_complete; then
return 1
fi
log_step "Loading environment variables"
# Load environment variables
if [[ -f .env ]]; then
export CONDA_DEFAULT_ENV="$(grep '^CONDA_DEFAULT_ENV=' .env | cut -d '=' -f2)"
export LOCAL_APP_PORT="$(grep '^LOCAL_APP_PORT=' .env | cut -d '=' -f2)"
export LOCAL_FRONTEND_PORT="$(grep '^LOCAL_FRONTEND_PORT=' .env | cut -d '=' -f2)"
if [[ -z "$CONDA_DEFAULT_ENV" ]]; then
export CONDA_DEFAULT_ENV="second-me"
fi
if [[ -z "$LOCAL_APP_PORT" ]]; then
export LOCAL_APP_PORT="8002"
fi
@ -153,8 +160,10 @@ start_services() {
return 1
fi
log_success "Environment variables loaded"
# Check if ports are available
log_info "Checking port availability..."
log_step "Checking port availability..."
if ! check_port ${LOCAL_APP_PORT}; then
log_error "Backend port ${LOCAL_APP_PORT} is already in use!"
return 1
@ -165,50 +174,15 @@ start_services() {
fi
log_success "All ports are available"
# Initialize conda environment if not using custom configuration
if ! is_custom_conda_mode; then
log_info "Initializing conda environment..."
local conda_cmd
if ! conda_cmd=$(try_source_conda_sh_all); then
log_error "Failed to initialize conda environment"
return 1
fi
# get conda.sh path
local conda_sh_path
if [[ -n "$conda_cmd" ]]; then
local conda_root="$(dirname "$(dirname "$conda_cmd")")"
if ! find_and_source_conda_sh "$conda_root" conda_sh_path; then
log_error "Could not find conda.sh activation script"
return 1
fi
else
log_error "conda command not found"
return 1
fi
log_info "Found conda.sh at: $conda_sh_path"
log_success "Conda initialized successfully: $conda_cmd"
else
log_info "Using custom conda environment, skipping conda initialization"
conda_sh_path="" # Set empty value since it won't be used
fi
# Create logs directory if it doesn't exist
mkdir -p logs
mkdir -p run
# Start backend service
log_info "Starting backend service..."
log_step "Starting backend service..."
# Check if using custom conda mode
if is_custom_conda_mode; then
log_info "Using custom conda environment, skipping conda activation"
nohup zsh -c ./scripts/start_local.sh > logs/start.log 2>&1 &
else
log_info "Using conda environment: ${CONDA_DEFAULT_ENV}"
# Ensure conda is properly initialized in the subshell
nohup zsh -c "source ${conda_sh_path} && conda activate ${CONDA_DEFAULT_ENV} && exec ./scripts/start_local.sh" > logs/start.log 2>&1 &
fi
nohup bash -c ./scripts/start_local.sh > logs/start.log 2>&1 &
echo $! > run/.backend.pid
log_info "Backend service started in background with PID: $(cat run/.backend.pid)"
@ -228,7 +202,7 @@ start_services() {
return 1
fi
log_info "Starting frontend service..."
log_step "Starting frontend service..."
cd lpm_frontend
# Copy environment variables from root directory to frontend directory
@ -241,16 +215,6 @@ start_services() {
log_warning "Root directory .env file does not exist, cannot copy environment variables"
fi
# Copy environment variables from root directory to frontend directory
log_info "Copying environment variables to frontend directory..."
if [[ -f "../.env" ]]; then
# Extract required environment variables and create frontend .env file
grep -E "^(HOST_ADDRESS|LOCAL_APP_PORT)=" "../.env" > .env
log_success "Environment variables copied to frontend .env file"
else
log_warning "Root directory .env file does not exist, cannot copy environment variables"
fi
# Check if node_modules exists
if [ ! -d "node_modules" ]; then
log_info "Installing frontend dependencies..."

View File

@ -1,8 +1,12 @@
#!/bin/bash
# Source the logging utilities
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/utils/logging.sh"
# enter frontend directory
cd lpm_frontend
# start frontend service
echo "Starting frontend service on port ${LOCAL_FRONTEND_PORT}..."
log_info "Starting frontend service on port ${LOCAL_FRONTEND_PORT}..."
npm run dev

View File

@ -1,7 +1,38 @@
#!/bin/bash
# Source the logging utilities
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/utils/logging.sh"
# Activate Poetry virtual environment if available (but only if not already activated)
log_info "Setting up Python environment..."
# Check if Python environment is already activated by looking for specific environment markers
if [[ "$VIRTUAL_ENV" != "" ]]; then
log_info "Python virtual environment already activated: $VIRTUAL_ENV"
else
POETRY_ENV_PATH=""
if command -v poetry &>/dev/null; then
POETRY_ENV_PATH=$(poetry env info -p 2>/dev/null)
if [ -n "$POETRY_ENV_PATH" ] && [ -f "$POETRY_ENV_PATH/bin/activate" ]; then
log_info "Activating Poetry virtual environment: $POETRY_ENV_PATH"
source "$POETRY_ENV_PATH/bin/activate"
else
# Try using the local activation script if it exists
if [ -f ".poetry-venv/activate" ]; then
log_info "Activating Poetry environment via local script"
source ".poetry-venv/activate"
else
log_warning "Poetry environment not found. Some dependencies might be missing."
fi
fi
else
log_warning "Poetry is not installed. Some dependencies might be missing."
fi
fi
# Set environment variables
echo "Setting environment variables..."
log_info "Setting environment variables..."
export PYTHONPATH=$(pwd):${PYTHONPATH}
# Load environment variables from .env file
@ -13,51 +44,49 @@ set +a
export BASE_DIR=${LOCAL_BASE_DIR}
# Ensure using the correct Python environment
echo "Checking Python environment..."
log_info "Checking Python environment..."
PYTHON_PATH=$(which python)
echo "Using Python: $PYTHON_PATH"
log_info "Using Python: $PYTHON_PATH"
PYTHON_VERSION=$(python --version)
echo "Python version: $PYTHON_VERSION"
CONDA_ENV=$(echo $CONDA_DEFAULT_ENV)
echo "Conda environment: $CONDA_ENV"
log_info "Python version: $PYTHON_VERSION"
# Check necessary Python packages
echo "Checking necessary Python packages..."
python -c "import flask" || { echo "Error: Missing flask package"; exit 1; }
python -c "import chromadb" || { echo "Error: Missing chromadb package"; exit 1; }
log_info "Checking necessary Python packages..."
python -c "import flask" || { log_error "Error: Missing flask package"; exit 1; }
python -c "import chromadb" || { log_error "Error: Missing chromadb package"; exit 1; }
# Initialize database
echo "Initializing database..."
log_info "Initializing database..."
SQLITE_DB_PATH="${BASE_DIR}/data/sqlite/lpm.db"
mkdir -p "${BASE_DIR}/data/sqlite"
if [ ! -f "$SQLITE_DB_PATH" ]; then
echo "Initializing database..."
log_info "Initializing database..."
cat docker/sqlite/init.sql | sqlite3 "$SQLITE_DB_PATH"
echo "Database initialization completed"
log_success "Database initialization completed"
else
echo "Database already exists"
log_info "Database already exists"
fi
# Ensure necessary directories exist
echo "Checking necessary directories..."
log_info "Checking necessary directories..."
mkdir -p ${BASE_DIR}/data/chroma_db
mkdir -p ${LOCAL_LOG_DIR}
#mkdir -p ${BASE_DIR}/raw_content
#mkdir -p ${BASE_DIR}/data_pipeline
# Initialize ChromaDB
echo "Initializing ChromaDB..."
log_info "Initializing ChromaDB..."
python docker/app/init_chroma.py
# Get local IP address (excluding localhost and docker networks)
LOCAL_IP=$(ifconfig | grep "inet " | grep -v "127.0.0.1" | grep "192.168" | awk '{print $2}' | head -n 1)
# Start Flask application
echo "Starting Flask application..."
echo "Application will run at the following addresses:"
echo "- Local access: http://localhost:${LOCAL_APP_PORT}"
echo "- LAN access: http://${LOCAL_IP}:${LOCAL_APP_PORT}"
log_info "Starting Flask application..."
log_info "Application will run at the following addresses:"
log_info "- Local access: http://localhost:${LOCAL_APP_PORT}"
log_info "- LAN access: http://${LOCAL_IP}:${LOCAL_APP_PORT}"
# Output logs to file
exec python -m flask run --host=0.0.0.0 --port=${LOCAL_APP_PORT} >> "${LOCAL_LOG_DIR}/backend.log" 2>&1

View File

@ -1,55 +1,20 @@
#!/bin/bash
# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Get current timestamp
get_timestamp() {
date "+%Y-%m-%d %H:%M:%S"
}
# Print formatted log messages
log_info() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${GREEN}[INFO]${NC} $1"
}
log_success() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${RED}[ERROR]${NC} $1"
}
log_section() {
echo -e "\n${CYAN}════════════════════════════════════════════════════════════════════════════════${NC}"
echo -e "${CYAN} $1${NC}"
echo -e "${CYAN}════════════════════════════════════════════════════════════════════════════════${NC}\n"
}
# Source the logging utilities
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/utils/logging.sh"
# Load configuration from .env file
load_env() {
if [ -f .env ]; then
# Only load necessary environment variables
# Load necessary environment variables
export LOCAL_APP_PORT=$(grep '^LOCAL_APP_PORT=' .env | cut -d '=' -f2)
export LOCAL_FRONTEND_PORT=$(grep '^LOCAL_FRONTEND_PORT=' .env | cut -d '=' -f2)
else
# Use default ports if .env not found
export LOCAL_APP_PORT=8002
export LOCAL_FRONTEND_PORT=3000
log_info "Using default ports: Backend=${LOCAL_APP_PORT}, Frontend=${LOCAL_FRONTEND_PORT}"
log_warning "Using default ports: Backend=${LOCAL_APP_PORT}, Frontend=${LOCAL_FRONTEND_PORT}"
fi
}

View File

@ -1,53 +1,8 @@
#!/bin/bash
# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Get current timestamp
get_timestamp() {
date "+%Y-%m-%d %H:%M:%S"
}
# Print formatted log messages
log_info() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${GREEN}[INFO]${NC} $1"
}
log_success() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${GRAY}[$(get_timestamp)]${NC} ${RED}[ERROR]${NC} $1"
}
log_step() {
echo -e "\n${GRAY}[$(get_timestamp)]${NC} ${BLUE}[STEP]${NC} ${BOLD}$1${NC}"
}
log_debug() {
if [[ "${DEBUG}" == "true" ]]; then
echo -e "${GRAY}[$(get_timestamp)]${NC} ${MAGENTA}[DEBUG]${NC} $1"
fi
}
log_section() {
echo -e "\n${CYAN}════════════════════════════════════════════════════════════════════════════════${NC}"
echo -e "${CYAN} $1${NC}"
echo -e "${CYAN}════════════════════════════════════════════════════════════════════════════════${NC}\n"
}
# Source the logging utilities
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/utils/logging.sh"
# Load configuration from .env file
load_env() {

View File

@ -0,0 +1,291 @@
#!/bin/bash
# Installation recommendations configuration
# Import logging utilities if not already imported
if ! command -v log_warning &>/dev/null; then
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/logging.sh"
fi
# Get installation recommendation for a package
get_install_recommendation() {
local package="$1"
local system_id="$2"
case "$package" in
"python")
get_python_recommendation "$system_id"
;;
"npm")
get_npm_recommendation "$system_id"
;;
"node")
get_node_recommendation "$system_id"
;;
"cmake")
get_cmake_recommendation "$system_id"
;;
"poetry")
get_poetry_recommendation "$system_id"
;;
"sqlite")
get_sqlite_recommendation "$system_id"
;;
*)
log_warning "No specific recommendation available for $package"
;;
esac
}
# Python installation recommendations
get_python_recommendation() {
local system_id="$1"
case "$system_id" in
"macos")
log_warning "Recommended installation for macOS: 'brew install python3'"
log_warning "Or download from: https://www.python.org/downloads/macos/"
;;
"linux-debian")
log_warning "Recommended installation for Debian/Ubuntu: 'sudo apt update && sudo apt install python3 python3-pip'"
;;
"linux-fedora")
log_warning "Recommended installation for Fedora: 'sudo dnf install python3 python3-pip'"
;;
"linux-redhat")
log_warning "Recommended installation for CentOS/RHEL: 'sudo yum install python3 python3-pip'"
;;
"linux-arch")
log_warning "Recommended installation for Arch Linux: 'sudo pacman -S python python-pip'"
;;
"linux-alpine")
log_warning "Recommended installation for Alpine Linux: 'apk add python3 py3-pip'"
;;
"linux-other")
log_warning "Please install Python 3.12+ using your distribution's package manager"
log_warning "Or download from: https://www.python.org/downloads/linux/"
;;
"windows")
log_warning "Recommended installation for Windows:"
log_warning "1. Download from: https://www.python.org/downloads/windows/"
log_warning "2. Or using winget: 'winget install Python.Python.3'"
log_warning "3. Or using Chocolatey: 'choco install python'"
;;
*)
log_warning "Please download Python from: https://www.python.org/downloads/"
;;
esac
}
# NPM installation recommendations
get_npm_recommendation() {
local system_id="$1"
case "$system_id" in
"macos")
log_warning "Recommended installation for macOS: 'brew install npm'"
;;
"linux-debian")
log_warning "Recommended installation for Debian/Ubuntu: 'sudo apt update && sudo apt install npm'"
;;
"linux-fedora")
log_warning "Recommended installation for Fedora: 'sudo dnf install npm'"
;;
"linux-redhat")
log_warning "Recommended installation for CentOS/RHEL: 'sudo yum install npm'"
;;
"linux-arch")
log_warning "Recommended installation for Arch Linux: 'sudo pacman -S npm'"
;;
"linux-alpine")
log_warning "Recommended installation for Alpine Linux: 'apk add npm'"
;;
"linux-other")
log_warning "Please install npm using your distribution's package manager"
;;
"windows")
log_warning "Recommended installation for Windows:"
log_warning "1. Install Node.js (includes npm): https://nodejs.org/en/download/"
log_warning "2. Or using winget: 'winget install OpenJS.NodeJS'"
log_warning "3. Or using Chocolatey: 'choco install nodejs'"
;;
*)
log_warning "Please install Node.js (includes npm): https://nodejs.org/en/download/"
;;
esac
}
# Node.js installation recommendations
get_node_recommendation() {
local system_id="$1"
case "$system_id" in
"macos")
log_warning "Recommended installation for macOS: 'brew install node'"
;;
"linux-debian")
log_warning "Recommended installation for Debian/Ubuntu: 'sudo apt update && sudo apt install nodejs'"
;;
"linux-fedora")
log_warning "Recommended installation for Fedora: 'sudo dnf install nodejs'"
;;
"linux-redhat")
log_warning "Recommended installation for CentOS/RHEL: 'sudo yum install nodejs'"
;;
"linux-arch")
log_warning "Recommended installation for Arch Linux: 'sudo pacman -S nodejs'"
;;
"linux-alpine")
log_warning "Recommended installation for Alpine Linux: 'apk add nodejs'"
;;
"linux-other")
log_warning "Please install Node.js using your distribution's package manager"
;;
"windows")
log_warning "Recommended installation for Windows:"
log_warning "1. Download from: https://nodejs.org/en/download/"
log_warning "2. Or using winget: 'winget install OpenJS.NodeJS'"
log_warning "3. Or using Chocolatey: 'choco install nodejs'"
;;
*)
log_warning "Please download Node.js from: https://nodejs.org/en/download/"
;;
esac
}
# CMake installation recommendations
get_cmake_recommendation() {
local system_id="$1"
case "$system_id" in
"macos")
log_warning "Recommended installation for macOS: 'brew install cmake'"
;;
"linux-debian")
log_warning "Recommended installation for Debian/Ubuntu: 'sudo apt update && sudo apt install cmake'"
;;
"linux-fedora")
log_warning "Recommended installation for Fedora: 'sudo dnf install cmake'"
;;
"linux-redhat")
log_warning "Recommended installation for CentOS/RHEL: 'sudo yum install cmake'"
;;
"linux-arch")
log_warning "Recommended installation for Arch Linux: 'sudo pacman -S cmake'"
;;
"linux-alpine")
log_warning "Recommended installation for Alpine Linux: 'apk add cmake'"
;;
"linux-other")
log_warning "Please install CMake using your distribution's package manager"
log_warning "Or download from: https://cmake.org/download/"
;;
"windows")
log_warning "Recommended installation for Windows:"
log_warning "1. Download from: https://cmake.org/download/"
log_warning "2. Or using winget: 'winget install Kitware.CMake'"
log_warning "3. Or using Chocolatey: 'choco install cmake'"
;;
*)
log_warning "Please download CMake from: https://cmake.org/download/"
;;
esac
}
# Poetry installation recommendations
get_poetry_recommendation() {
local system_id="$1"
case "$system_id" in
"macos")
log_warning "Recommended installation for macOS:"
log_warning "1. 'brew install poetry'"
log_warning "2. Or using the official installer: 'curl -sSL https://install.python-poetry.org | python3 -'"
;;
"linux-debian")
log_warning "Recommended installation for Debian/Ubuntu:"
log_warning "1. Using pipx (recommended): 'sudo apt install pipx && pipx install poetry'"
log_warning "2. Or using the official installer in your home directory:"
log_warning " 'curl -sSL https://install.python-poetry.org | python3 -'"
log_warning "3. Or in a virtual environment:"
log_warning " 'python3 -m venv ~/.poetry-venv && ~/.poetry-venv/bin/pip install poetry'"
log_warning " Then add ~/.poetry-venv/bin to your PATH"
;;
"linux-fedora")
log_warning "Recommended installation for Fedora:"
log_warning "1. 'sudo dnf install poetry'"
log_warning "2. Or using the official installer: 'curl -sSL https://install.python-poetry.org | python3 -'"
;;
"linux-redhat")
log_warning "Recommended installation for CentOS/RHEL:"
log_warning "1. Using the official installer: 'curl -sSL https://install.python-poetry.org | python3 -'"
;;
"linux-arch")
log_warning "Recommended installation for Arch Linux:"
log_warning "1. 'sudo pacman -S python-poetry'"
;;
"linux-alpine")
log_warning "Recommended installation for Alpine Linux:"
log_warning "1. 'apk add py3-poetry'"
log_warning "2. Or using the official installer: 'curl -sSL https://install.python-poetry.org | python3 -'"
;;
"linux-other")
log_warning "Recommended installation for Linux:"
log_warning "1. Using the official installer: 'curl -sSL https://install.python-poetry.org | python3 -'"
;;
"windows")
log_warning "Recommended installation for Windows:"
log_warning "1. Using PowerShell: '(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | python -'"
log_warning "2. Or using Chocolatey: 'choco install poetry'"
;;
*)
log_warning "Please install Poetry using the official installer:"
log_warning "curl -sSL https://install.python-poetry.org | python3 -"
;;
esac
}
# SQLite installation recommendations
get_sqlite_recommendation() {
local system_id="$1"
case "$system_id" in
"macos")
log_warning "Recommended installation for SQLite on macOS:"
log_warning "1. 'brew install sqlite'"
log_warning "SQLite is usually pre-installed on macOS, but this will ensure you have the latest version."
;;
"linux-debian")
log_warning "Recommended installation for SQLite on Debian/Ubuntu:"
log_warning "1. 'sudo apt update && sudo apt install sqlite3'"
;;
"linux-fedora")
log_warning "Recommended installation for SQLite on Fedora:"
log_warning "1. 'sudo dnf install sqlite'"
;;
"linux-redhat")
log_warning "Recommended installation for SQLite on CentOS/RHEL:"
log_warning "1. 'sudo yum install sqlite'"
;;
"linux-arch")
log_warning "Recommended installation for SQLite on Arch Linux:"
log_warning "1. 'sudo pacman -S sqlite'"
;;
"linux-alpine")
log_warning "Recommended installation for SQLite on Alpine Linux:"
log_warning "1. 'apk add sqlite'"
;;
"linux-other")
log_warning "Recommended installation for SQLite on Linux:"
log_warning "Please install SQLite using your distribution's package manager"
;;
"windows")
log_warning "Recommended installation for SQLite on Windows:"
log_warning "1. Download from: https://www.sqlite.org/download.html"
log_warning "2. Or using Chocolatey: 'choco install sqlite'"
;;
*)
log_warning "Please download SQLite from: https://www.sqlite.org/download.html"
;;
esac
}

81
scripts/utils/logging.sh Normal file
View File

@ -0,0 +1,81 @@
#!/bin/bash
# Logging utilities for Second-Me scripts
# This file contains common logging functions that can be used by other scripts
# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Get current timestamp
get_timestamp() {
date "+%Y-%m-%d %H:%M:%S"
}
# Log a message to the console with formatting
log() {
local message="$1"
local level="${2:-INFO}"
local color="${NC}"
case $level in
INFO) color="${BLUE}" ;;
SUCCESS) color="${GREEN}" ;;
WARNING) color="${YELLOW}" ;;
ERROR) color="${RED}" ;;
DEBUG) color="${GRAY}" ;;
SECTION) color="${BOLD}" ;;
STEP) color="${GRAY}" ;;
esac
echo -e "${GRAY}[$(get_timestamp)]${NC} ${color}[${level}]${NC} ${message}"
}
# Print formatted log messages with different levels
log_info() {
log "$1" "INFO"
}
log_success() {
log "$1" "SUCCESS"
}
log_warning() {
log "$1" "WARNING"
}
log_error() {
log "$1" "ERROR"
}
log_debug() {
log "$1" "DEBUG"
}
log_section() {
log "$1" "SECTION"
}
log_step() {
log "$1" "STEP"
}
# Initialize logging
init_logging() {
# Check if we should enable debug output
if [ "${DEBUG_MODE}" = "true" ]; then
log_debug "Debug logging enabled"
fi
# Set up trap for cleanup if needed
if [ "${1}" = "trap_cleanup" ] && [ -n "${2}" ]; then
trap "${2}" INT
fi
}

View File

@ -0,0 +1,44 @@
#!/bin/bash
# OS detection utility functions
# Detect OS type: Returns "macos", "linux", "windows", or "unknown"
detect_os_type() {
if [[ "$OSTYPE" == "darwin"* ]]; then
echo "macos"
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
echo "linux"
elif [[ "$OSTYPE" == "msys"* ]] || [[ "$OSTYPE" == "cygwin"* ]] || [[ "$OSTYPE" == "win32" ]]; then
echo "windows"
else
echo "unknown"
fi
}
# Detect Linux distribution: Returns "debian", "fedora", "redhat", "arch", "alpine", or "other"
detect_linux_distro() {
if [ -f /etc/debian_version ]; then
echo "debian"
elif [ -f /etc/fedora-release ]; then
echo "fedora"
elif [ -f /etc/redhat-release ]; then
echo "redhat"
elif [ -f /etc/arch-release ]; then
echo "arch"
elif [ -f /etc/alpine-release ]; then
echo "alpine"
else
echo "other"
fi
}
# Get full system identification
get_system_id() {
local os_type=$(detect_os_type)
if [ "$os_type" = "linux" ]; then
local linux_distro=$(detect_linux_distro)
echo "${os_type}-${linux_distro}"
else
echo "$os_type"
fi
}

View File

@ -0,0 +1,46 @@
#!/bin/bash
# Python utility functions
# Import logging utilities if not already imported
if ! command -v log_warning &>/dev/null; then
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/logging.sh"
fi
# Get the appropriate Python command (python3 or python)
get_python_command() {
local python_cmd=""
# First check for python3 command
if command -v python3 &>/dev/null; then
python_cmd="python3"
# Then check for python command
elif command -v python &>/dev/null; then
python_cmd="python"
fi
# Return the command
echo "$python_cmd"
}
# Get the appropriate pip command (pip3 or pip)
get_pip_command() {
local pip_cmd=""
local python_cmd=$(get_python_command)
# First try to use the matching pip version
if [ "$python_cmd" = "python3" ] && command -v pip3 &>/dev/null; then
pip_cmd="pip3"
# Then check for any pip command
elif command -v pip &>/dev/null; then
pip_cmd="pip"
# If no pip is found, try to use python -m pip
elif [ -n "$python_cmd" ]; then
if $python_cmd -m pip --version &>/dev/null; then
pip_cmd="$python_cmd -m pip"
fi
fi
# Return the command
echo "$pip_cmd"
}