#!/usr/bin/env bash # ═══════════════════════════════════════════════════════════════════════ # SYNTHOS v3 — One-liner installer # ═══════════════════════════════════════════════════════════════════════ # # Usage: # curl -fsSL https://synthos.dev/install.sh | bash # wget -qO- https://synthos.dev/install.sh | bash # # Works on: macOS, Linux, WSL, Windows (Git Bash / MSYS2) # Requires: Python ≥ 3.9, pip, curl or wget # ═══════════════════════════════════════════════════════════════════════ set -euo pipefail # ── Colors ──────────────────────────────────────────────────────────── RED='\033[0;31m' GREEN='\033[0;32m' CYAN='\033[0;36m' YELLOW='\033[1;33m' BOLD='\033[1m' DIM='\033[2m' RESET='\033[0m' info() { printf "${CYAN}▸${RESET} %s\n" "$1"; } ok() { printf "${GREEN}✓${RESET} %s\n" "$1"; } warn() { printf "${YELLOW}⚠${RESET} %s\n" "$1"; } err() { printf "${RED}✗${RESET} %s\n" "$1"; exit 1; } # ── Banner ──────────────────────────────────────────────────────────── printf "\n${BOLD}${CYAN}" cat << 'EOF' ____ _ _ _ _ _____ _ _ ___ ____ / ___|| \ | | \ | |_ _| | | |/ _ \/ ___| \___ \| \| | \| | | | | |_| | | | \___ \ ___) | |\ | |\ | | | | _ | |_| |___) | |____/|_| \_|_| \_| |_| |_| |_|\___/|____/ EOF printf "${RESET}${DIM} v3.0 · 7 Layers · Deep Research · STC Cipher${RESET}\n\n" # ── Platform detection ──────────────────────────────────────────────── OS="$(uname -s)" ARCH="$(uname -m)" info "Detected platform: ${OS} ${ARCH}" case "$OS" in Linux*) PLATFORM="linux" ;; Darwin*) PLATFORM="macos" ;; MINGW*|MSYS*|CYGWIN*) PLATFORM="windows" ;; *) PLATFORM="unknown" ;; esac # ── Check prerequisites ────────────────────────────────────────────── check_cmd() { if ! command -v "$1" &>/dev/null; then return 1 fi return 0 } # Python PYTHON="" for py in python3 python; do if check_cmd "$py"; then PY_VER=$("$py" -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null || echo "0.0") PY_MAJOR=$(echo "$PY_VER" | cut -d. -f1) PY_MINOR=$(echo "$PY_VER" | cut -d. -f2) if [ "$PY_MAJOR" -ge 3 ] && [ "$PY_MINOR" -ge 9 ]; then PYTHON="$py" break fi fi done if [ -z "$PYTHON" ]; then err "Python ≥ 3.9 is required but not found. Install it first: macOS: brew install python@3.12 Ubuntu: sudo apt install python3.12 python3.12-venv Windows: winget install Python.Python.3.12 Or visit: https://python.org/downloads" fi ok "Python found: $PYTHON ($PY_VER)" # pip PIP="$PYTHON -m pip" if ! $PIP --version &>/dev/null; then warn "pip not found, attempting to bootstrap..." $PYTHON -m ensurepip --upgrade 2>/dev/null || err "Could not install pip. Install manually: https://pip.pypa.io" fi ok "pip available" # curl or wget (for downloading source) if ! check_cmd curl && ! check_cmd wget; then err "curl or wget is required. Install one first: Ubuntu: sudo apt install curl macOS: (curl is pre-installed)" fi ok "Download tool available ($(check_cmd curl && echo curl || echo wget))" # ── Install location ───────────────────────────────────────────────── INSTALL_DIR="${SYNTHOS_HOME:-$HOME/.synthos}" REPO_DIR="$INSTALL_DIR/repo" info "Installing to: $INSTALL_DIR" mkdir -p "$INSTALL_DIR" # ── Download source ────────────────────────────────────────────────── SOURCE_ZIP_URL="${SYNTHOS_ZIP:-https://synthos-ai.org/synthos-v3.zip}" if [ -d "$REPO_DIR" ] && [ -f "$REPO_DIR/pyproject.toml" ]; then info "Existing installation found, re-downloading latest..." rm -rf "$REPO_DIR" fi info "Downloading SYNTHOS source..." TMP_ZIP="$(mktemp /tmp/synthos-XXXXXX.zip)" # Try curl first, then wget if check_cmd curl; then curl -fsSL "$SOURCE_ZIP_URL" -o "$TMP_ZIP" || err "Failed to download SYNTHOS source from $SOURCE_ZIP_URL" elif check_cmd wget; then wget -qO "$TMP_ZIP" "$SOURCE_ZIP_URL" || err "Failed to download SYNTHOS source from $SOURCE_ZIP_URL" else err "curl or wget is required to download SYNTHOS. Install one and retry." fi ok "Downloaded source archive" # Extract info "Extracting..." TMP_EXTRACT="$(mktemp -d /tmp/synthos-extract-XXXXXX)" if check_cmd unzip; then unzip -qo "$TMP_ZIP" -d "$TMP_EXTRACT" else # Python fallback for systems without unzip $PYTHON -c "import zipfile,sys; zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])" "$TMP_ZIP" "$TMP_EXTRACT" fi # Move extracted contents into REPO_DIR # The zip contains top-level dirs (synthos/, tests/, etc.) — move them all mkdir -p "$REPO_DIR" cp -r "$TMP_EXTRACT"/* "$REPO_DIR/" 2>/dev/null || cp -r "$TMP_EXTRACT"/*/* "$REPO_DIR/" 2>/dev/null || true # Cleanup temp files rm -f "$TMP_ZIP" rm -rf "$TMP_EXTRACT" if [ ! -f "$REPO_DIR/pyproject.toml" ]; then err "Extraction failed — pyproject.toml not found in $REPO_DIR" fi ok "Source ready" # ── Create virtual environment (optional but recommended) ──────────── VENV_DIR="$INSTALL_DIR/venv" if [ "${SYNTHOS_NO_VENV:-}" != "1" ]; then if [ ! -d "$VENV_DIR" ]; then info "Creating virtual environment..." $PYTHON -m venv "$VENV_DIR" 2>/dev/null || { warn "venv creation failed — installing globally" VENV_DIR="" } fi if [ -n "$VENV_DIR" ] && [ -d "$VENV_DIR" ]; then # Activate if [ -f "$VENV_DIR/bin/activate" ]; then source "$VENV_DIR/bin/activate" elif [ -f "$VENV_DIR/Scripts/activate" ]; then source "$VENV_DIR/Scripts/activate" fi ok "Virtual environment active" fi fi # ── Install SYNTHOS ────────────────────────────────────────────────── info "Installing SYNTHOS and dependencies..." cd "$REPO_DIR" pip install -e ".[dev]" --quiet 2>&1 | tail -1 || pip install -e . --quiet 2>&1 | tail -1 ok "SYNTHOS installed" # ── Make synthos available on PATH persistently ───────────────────── if [ -n "$VENV_DIR" ] && [ -d "$VENV_DIR" ]; then BIN_DIR="$VENV_DIR/bin" [ -d "$VENV_DIR/Scripts" ] && BIN_DIR="$VENV_DIR/Scripts" # Windows else BIN_DIR="$($PYTHON -m site --user-base)/bin" fi EXPORT_LINE="export PATH=\"$BIN_DIR:\$PATH\"" # Add to shell profile if not already present add_to_profile() { local profile="$1" if [ -f "$profile" ]; then if ! grep -qF "$BIN_DIR" "$profile" 2>/dev/null; then printf '\n# SYNTHOS\n%s\n' "$EXPORT_LINE" >> "$profile" return 0 fi fi return 1 } PROFILE_UPDATED="" # Try common shell profiles for rc in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.profile" "$HOME/.bash_profile"; do if add_to_profile "$rc"; then PROFILE_UPDATED="$rc" break fi done # If no profile existed, create .profile if [ -z "$PROFILE_UPDATED" ]; then printf '# SYNTHOS\n%s\n' "$EXPORT_LINE" >> "$HOME/.profile" PROFILE_UPDATED="$HOME/.profile" fi # Also export for current session detection export PATH="$BIN_DIR:$PATH" if check_cmd synthos; then INSTALLED_VER=$(synthos version 2>/dev/null || echo "v3.0") ok "synthos is on your PATH ($INSTALLED_VER)" else ok "SYNTHOS installed to $BIN_DIR" fi if [ -n "$PROFILE_UPDATED" ]; then ok "PATH added to $PROFILE_UPDATED" fi # ── Create default config ──────────────────────────────────────────── CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/synthos" if [ ! -f "$CONFIG_DIR/config.yaml" ]; then mkdir -p "$CONFIG_DIR" cat > "$CONFIG_DIR/config.yaml" << 'YAML' # SYNTHOS v3 Configuration verbose: 1 models: [] # - name: llama3.1-8b # provider: ollama # base_url: http://localhost:11434 # model_id: llama3.1 crypto: mode: cbc authenticate: true lattice_rows: 4 lattice_cols: 4 attention_heads: 8 context_window: 512 max_words: 4000 max_search_queries: 12 max_sources: 8 YAML ok "Created config at $CONFIG_DIR/config.yaml" fi # ── Done! ──────────────────────────────────────────────────────────── printf "\n${BOLD}${GREEN}═══════════════════════════════════════════════${RESET}\n" printf "${BOLD}${GREEN} SYNTHOS v3 installed successfully!${RESET}\n" printf "${BOLD}${GREEN}═══════════════════════════════════════════════${RESET}\n\n" if [ -n "$PROFILE_UPDATED" ]; then printf " ${YELLOW}▸ Open a new terminal${RESET} or run:\n" printf " ${CYAN}source $PROFILE_UPDATED${RESET}\n\n" fi echo " Get started:" echo "" printf " ${CYAN}synthos${RESET} Launch the TUI\n" printf " ${CYAN}synthos chat${RESET} Headless REPL\n" printf " ${CYAN}synthos encrypt \"hi\"${RESET} STC cipher\n" printf " ${CYAN}synthos eval${RESET} Benchmark models\n" printf " ${CYAN}synthos --help${RESET} Full CLI reference\n" echo "" printf " ${DIM}Docs: https://synthos-ai.org/docs${RESET}\n" printf " ${DIM}Config: $CONFIG_DIR/config.yaml${RESET}\n\n"