Ctrl K
ComunidadGuías…

install.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env bash
# OpenCompany Installer
# Usage: curl -fsSL https://opencompany.sh/install.sh | bash
#
# Served from opencompany.sh (not the GitHub raw URL) so installs are
# trackable. The release to install comes from https://opencompany.sh/version
# unless OPENCOMPANY_VERSION is set.
#
# This script installs OpenCompany and its dependencies:
# - bun (the JavaScript runtime and package manager; no Node.js, no npm)
# - Python 3.12+ (via brew/apt/dnf/pacman)
# - uv (Python package manager)
#
# Prefer the desktop app if you just want to use OpenCompany on a laptop; this
# path is for terminal and server use.

set -e

MIN_PYTHON_VERSION_MINOR=12
PKG_NAME="@zeenie-ai/opencompany"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'

info() { echo -e "${CYAN}[INFO]${NC} $*"; }
success() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error_exit() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; }

# Banner
echo ""
echo -e "${CYAN}  OpenCompany${NC}"
echo ""
echo "Self-improving AI employees, running on your own computer"
echo ""

# Detect OS
detect_os() {
  if [[ "$OSTYPE" == "darwin"* ]]; then
    echo "macos"
  elif [[ -f /etc/debian_version ]]; then
    echo "debian"
  elif [[ -f /etc/redhat-release ]]; then
    echo "redhat"
  elif [[ -f /etc/arch-release ]]; then
    echo "arch"
  else
    echo "unknown"
  fi
}

OS=$(detect_os)

# bun installs to $BUN_INSTALL (default ~/.bun) and puts global bin shims in
# its bin dir. Where it stores the global package itself varies by platform
# and configuration, so nothing below depends on that: the `company` shim
# knows its own package root and `company provision` does the rest.
BUN_HOME="${BUN_INSTALL:-$HOME/.bun}"
BUN_BIN_DIR="$BUN_HOME/bin"

# A previous npm-based install (or the pre-rebrand `machinaos` package) leaves
# a `company` / `machina` shim on PATH that would shadow the bun one. Remove it
# when npm happens to be around; skip silently otherwise.
remove_legacy_npm_installs() {
  command -v npm &> /dev/null || return 0
  for pkg in "$PKG_NAME" machinaos; do
    if npm list -g --depth=0 "$pkg" &> /dev/null; then
      info "Removing legacy npm install of $pkg..."
      npm uninstall -g "$pkg" &> /dev/null || warn "Could not remove $pkg; run: npm uninstall -g $pkg"
    fi
  done
}

# =============================================================================
# Dependency Checks and Installation
# =============================================================================

check_bun() {
  hash -r 2>/dev/null || true
  if command -v bun &> /dev/null; then
    success "bun $(bun --version)"
    return 0
  fi
  return 1
}

install_bun() {
  info "Installing bun (JavaScript runtime and package manager)..."
  curl -fsSL https://bun.sh/install | bash
  export PATH="$BUN_BIN_DIR:$PATH"
  if ! check_bun; then
    error_exit "Failed to install bun. Install it manually from https://bun.sh and re-run."
  fi
}

check_python() {
  for cmd in python3 python; do
    if command -v "$cmd" &> /dev/null; then
      version=$($cmd --version 2>&1 | sed -n 's/.*Python \([0-9]*\.[0-9]*\).*/\1/p')
      major=$(echo "$version" | cut -d. -f1)
      minor=$(echo "$version" | cut -d. -f2)
      if [ "$major" -ge 3 ] && [ "$minor" -ge "$MIN_PYTHON_VERSION_MINOR" ]; then
        success "Python $version ($cmd)"
        PYTHON_CMD="$cmd"
        return 0
      fi
    fi
  done
  warn "Python 3.$MIN_PYTHON_VERSION_MINOR+ not found"
  return 1
}

install_python() {
  info "Installing Python 3.$MIN_PYTHON_VERSION_MINOR..."

  case "$OS" in
    macos)
      if command -v brew &> /dev/null; then
        brew install python@3.12
      else
        error_exit "Please install Homebrew first: https://brew.sh/"
      fi
      ;;
    debian)
      sudo apt-get update
      sudo apt-get install -y python3.12 python3.12-venv python3-pip
      ;;
    redhat)
      sudo dnf install -y python3.12
      ;;
    arch)
      sudo pacman -S --noconfirm python python-pip
      ;;
    *)
      error_exit "Please install Python 3.12+ manually from https://python.org/"
      ;;
  esac

  if ! check_python; then
    error_exit "Failed to install Python. Please install manually."
  fi
}

check_uv() {
  if command -v uv &> /dev/null; then
    version=$(uv --version | tr -d 'uv ')
    success "uv $version"
    return 0
  fi
  return 1
}

install_uv() {
  info "Installing uv (Python package manager)..."

  # Try pip first
  if [ -n "$PYTHON_CMD" ]; then
    if $PYTHON_CMD -m pip install uv 2>/dev/null; then
      export PATH="$HOME/.local/bin:$PATH"
      if check_uv; then return 0; fi
    fi
  fi

  # Fallback to official installer
  curl -LsSf https://astral.sh/uv/install.sh | sh
  export PATH="$HOME/.local/bin:$PATH"

  if ! check_uv; then
    error_exit "Failed to install uv"
  fi
}

# bun finds its global "project" by walking up from $BUN_INSTALL/install/global
# until it meets a package.json. A stray package.json or package-lock.json in
# $HOME (an old `npm init` / `npm install` run in the home dir) therefore
# hijacks every global install: packages land in $HOME/node_modules and
# `bun add -g` dies with "InvalidNPMLockfile: failed to migrate lockfile"
# (docs-internal/errors.md #23). Giving the global dir its own manifest stops
# the walk-up before it reaches $HOME. Harmless on a clean machine: it is the
# same file bun would create there itself.
seed_bun_global_dir() {
  local global_dir="$BUN_HOME/install/global"
  mkdir -p "$global_dir"
  if [ ! -f "$global_dir/package.json" ]; then
    printf '{\n  "private": true\n}\n' > "$global_dir/package.json"
  fi
}

ensure_bun_on_path() {
  # The bun installer adds ~/.bun/bin to the shell profile; make sure the
  # `company` shim is reachable from new shells even when bun was already
  # present but its bin dir was not exported.
  case ":$PATH:" in
    *":$BUN_BIN_DIR:"*) ;;
    *)
      export PATH="$BUN_BIN_DIR:$PATH"
      if ! grep -q '\.bun/bin' "$HOME/.bashrc" 2>/dev/null; then
        echo '' >> "$HOME/.bashrc"
        echo '# bun global packages (OpenCompany installer)' >> "$HOME/.bashrc"
        echo 'export PATH="$HOME/.bun/bin:$PATH"' >> "$HOME/.bashrc"
      fi
      ;;
  esac
}

# =============================================================================
# Main Installation Flow
# =============================================================================

main() {
  echo ""
  info "Checking dependencies..."
  echo ""

  # Check and install dependencies
  check_bun || install_bun
  check_python || install_python
  check_uv || install_uv
  ensure_bun_on_path
  seed_bun_global_dir

  remove_legacy_npm_installs

  echo ""
  info "Installing OpenCompany..."
  echo ""

  # OPENCOMPANY_VERSION pins a release (the cli/terraform startup scripts set
  # it). Otherwise ask opencompany.sh which release is current; if that is
  # unreachable, fall back to the registry's latest tag.
  VERSION="${OPENCOMPANY_VERSION:-$(curl -fsSL --max-time 10 https://opencompany.sh/version 2>/dev/null | tr -d '[:space:]' || true)}"
  PKG="${PKG_NAME}${VERSION:+@$VERSION}"
  # Global install as the current user: bun's global root is user-owned, so
  # no sudo and no root-owned venvs (docs-internal/errors.md #16).
  bun add -g "$PKG" || error_exit "bun add -g $PKG failed."

  # bun runs no lifecycle scripts for a global package, so provision the Python
  # side now rather than on the first `company` command (which would do it too).
  # The shim is addressed through bun's own answer for the global bin dir.
  COMPANY="$(bun pm bin -g)/company"
  info "Provisioning the Python environment..."
  "$COMPANY" provision || error_exit "Provisioning failed. Re-run with: company provision"

  echo ""
  echo -e "${GREEN}============================================${NC}"
  echo -e "${GREEN}  OpenCompany installed successfully!${NC}"
  echo -e "${GREEN}============================================${NC}"
  echo ""
  echo "  Start OpenCompany:"
  echo "    company start"
  echo ""
  echo "  Optional: Enable JS-rendered web scraping:"
  echo "    playwright install chromium"
  echo ""
  echo "  Run diagnostics:"
  echo "    company doctor"
  echo ""
  echo "  New shells pick up the bun bin dir from your profile; in this one run:"
  echo "    export PATH=\"\$HOME/.bun/bin:\$PATH\""
  echo ""
}

# Run main
main