#!/usr/bin/env bash set -u set -o pipefail PLUGIN_SOURCE="${ACN_PLUGIN_SOURCE:-github:777genius/universal-plugins-for-ai-agents//plugins/agent-code-navigator}" PLUGIN_NAME="${ACN_PLUGIN_NAME:-agent-code-navigator}" MIN_PLUGIN_KIT_VERSION="${ACN_MIN_PLUGIN_KIT_VERSION:-1.2.4}" PLUGIN_KIT_INSTALLER_URL="${PLUGIN_KIT_INSTALLER_URL:-https://raw.githubusercontent.com/777genius/plugin-kit-ai/main/scripts/install.sh}" SETUP_URL="${ACN_SETUP_URL:-https://raw.githubusercontent.com/777genius/universal-plugins-for-ai-agents/main/plugins/agent-code-navigator/scripts/setup-code-intelligence.sh}" INSTALL_PLUGIN=1 RUN_SETUP=1 SETUP_MODE="${ACN_SETUP_MODE:-}" YES="${ACN_YES:-0}" DRY_RUN=0 if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then BOLD="$(printf '\033[1m')" DIM="$(printf '\033[2m')" GREEN="$(printf '\033[32m')" CYAN="$(printf '\033[36m')" YELLOW="$(printf '\033[33m')" RED="$(printf '\033[31m')" RESET="$(printf '\033[0m')" else BOLD="" DIM="" GREEN="" CYAN="" YELLOW="" RED="" RESET="" fi usage() { cat <<'EOF' Agent Code Navigator installer Installs the plugin first, then offers optional setup for Semble, CGC, and Serena. Usage: install.sh [options] Options: --plugin-only Install only the plugin and skip optional tools. --skip-plugin Skip plugin install and only run optional tool setup. --mode Setup mode: minimal, recommended, full, check. --minimal Same as --mode minimal. --recommended Same as --mode recommended. --full Same as --mode full. --check Same as --mode check. --yes Non-interactive; use selected mode or recommended. --dry-run Print what would happen without installing. -h, --help Show this help. Examples: curl -fsSL https://raw.githubusercontent.com/777genius/universal-plugins-for-ai-agents/main/plugins/agent-code-navigator/scripts/install.sh | bash curl -fsSL https://raw.githubusercontent.com/777genius/universal-plugins-for-ai-agents/main/plugins/agent-code-navigator/scripts/install.sh | bash -s -- --yes --recommended curl -fsSL https://raw.githubusercontent.com/777genius/universal-plugins-for-ai-agents/main/plugins/agent-code-navigator/scripts/install.sh | bash -s -- --plugin-only EOF } log() { printf '%s\n' "$*" } section() { printf '\n%s==>%s %s\n' "$CYAN" "$RESET" "$*" } warn() { printf '%sWARN:%s %s\n' "$YELLOW" "$RESET" "$*" >&2 } fail() { printf '%sERROR:%s %s\n' "$RED" "$RESET" "$*" >&2 exit 1 } command_exists() { command -v "$1" >/dev/null 2>&1 } plugin_kit_version() { plugin-kit-ai version 2>/dev/null | awk '/^version:[[:space:]]*/ { print $2; exit }' } version_ge() { current="${1#v}" required="${2#v}" awk -v current="$current" -v required="$required" 'BEGIN { split(current, c, ".") split(required, r, ".") for (i = 1; i <= 3; i++) { cv = c[i] + 0 rv = r[i] + 0 if (cv > rv) exit 0 if (cv < rv) exit 1 } exit 0 }' } installed_plugin_kit_is_usable() { [ "${ACN_FORCE_PLUGIN_KIT_BOOTSTRAP:-0}" != "1" ] || return 1 command_exists plugin-kit-ai || return 1 installed_version="$(plugin_kit_version || true)" if [ -z "$installed_version" ]; then warn "found plugin-kit-ai, but could not detect its version; bootstrapping a fresh plugin-kit-ai" return 1 fi if version_ge "$installed_version" "$MIN_PLUGIN_KIT_VERSION"; then return 0 fi warn "found plugin-kit-ai $installed_version, but Agent Code Navigator needs plugin-kit-ai $MIN_PLUGIN_KIT_VERSION or newer for Cursor support; bootstrapping a fresh plugin-kit-ai" return 1 } ensure_base_path() { old_path="${PATH:-}" PATH="$old_path" for path_entry in /usr/local/bin /opt/homebrew/bin /usr/bin /bin /usr/sbin /sbin; do case ":$PATH:" in *":$path_entry:"*) ;; *) PATH="${PATH:+$PATH:}$path_entry" ;; esac done export PATH } prepend_path_once() { path_entry="$1" [ -n "$path_entry" ] || return 0 case ":${PATH:-}:" in *":$path_entry:"*) ;; *) export PATH="$path_entry:${PATH:-}" ;; esac } refresh_path() { ensure_base_path if [ -n "${BIN_DIR:-}" ]; then prepend_path_once "$BIN_DIR" elif [ -n "${HOME:-}" ]; then prepend_path_once "$HOME/.local/bin" fi if [ -n "${HOME:-}" ]; then prepend_path_once "$HOME/.cargo/bin" fi } plugin_source_requires_git() { case "$PLUGIN_SOURCE" in github:*) return 0 ;; *) return 1 ;; esac } while [ "$#" -gt 0 ]; do case "$1" in --plugin-only) RUN_SETUP=0 ;; --skip-plugin) INSTALL_PLUGIN=0 ;; --mode) [ "$#" -ge 2 ] || fail "--mode requires a value" SETUP_MODE="$2" shift ;; --minimal) SETUP_MODE="minimal" ;; --recommended) SETUP_MODE="recommended" ;; --full) SETUP_MODE="full" ;; --check) SETUP_MODE="check" ;; --yes|-y) YES=1 ;; --dry-run) DRY_RUN=1 ;; -h|--help) usage exit 0 ;; *) fail "unknown option: $1" ;; esac shift done case "$SETUP_MODE" in ""|minimal|recommended|full|check) ;; *) fail "unsupported setup mode: $SETUP_MODE" ;; esac if [ "$INSTALL_PLUGIN" = "0" ] && [ "$RUN_SETUP" = "0" ]; then fail "--plugin-only and --skip-plugin cannot be used together" fi install_plugin() { section "Installing Agent Code Navigator plugin" if [ "$DRY_RUN" = "1" ]; then if installed_plugin_kit_is_usable; then log "${DIM}DRY RUN:${RESET} plugin-kit-ai add $PLUGIN_SOURCE" else log "${DIM}DRY RUN:${RESET} curl -fsSL $PLUGIN_KIT_INSTALLER_URL | sh -s -- add $PLUGIN_SOURCE" fi return 0 fi if plugin_source_requires_git && ! command_exists git; then fail "git is required to install GitHub plugin source ($PLUGIN_SOURCE). Install git or pass --skip-plugin to configure optional tools only." fi if installed_plugin_kit_is_usable; then add_output="" if add_output="$(plugin-kit-ai add "$PLUGIN_SOURCE" 2>&1)"; then printf '%s\n' "$add_output" return 0 fi printf '%s\n' "$add_output" case "$add_output" in *"already managed"*) warn "plugin-kit-ai add failed because the plugin is already managed; trying plugin-kit-ai update $PLUGIN_NAME" plugin-kit-ai update "$PLUGIN_NAME" || fail "plugin-kit-ai add/update failed" return 0 ;; *) fail "plugin-kit-ai add failed" ;; esac fi command_exists curl || fail "curl is required to install plugin-kit-ai automatically" curl -fsSL "$PLUGIN_KIT_INSTALLER_URL" | sh -s -- add "$PLUGIN_SOURCE" || fail "plugin-kit-ai bootstrap install failed" } run_setup() { section "Optional code-intelligence setup" set -- if [ -n "$SETUP_MODE" ]; then set -- "$@" --mode "$SETUP_MODE" fi if [ "$YES" = "1" ]; then set -- "$@" --yes fi if [ "$DRY_RUN" = "1" ]; then set -- "$@" --dry-run fi script_dir="" script_path="${BASH_SOURCE[0]:-}" if [ -n "$script_path" ]; then case "$script_path" in /*) ;; *) script_path="${PWD:-.}/$script_path" ;; esac script_parent="${script_path%/*}" if script_dir="$(cd "$script_parent" 2>/dev/null && pwd -P)"; then : else script_dir="" fi fi if [ -n "$script_dir" ] && [ -f "$script_dir/setup-code-intelligence.sh" ]; then "${BASH:-bash}" "$script_dir/setup-code-intelligence.sh" "$@" return $? fi command_exists curl || fail "curl is required to fetch setup-code-intelligence.sh" curl -fsSL "$SETUP_URL" | bash -s -- "$@" } log "${BOLD}Agent Code Navigator${RESET}" log "${DIM}Plugin source:${RESET} $PLUGIN_SOURCE" refresh_path if [ "$INSTALL_PLUGIN" = "1" ]; then install_plugin else section "Skipping plugin install" fi if [ "$RUN_SETUP" = "1" ]; then if ! run_setup; then fail "optional code-intelligence setup failed" fi else section "Skipping optional tool setup" log "You can run it later:" log "curl -fsSL $SETUP_URL | bash" fi log log "${GREEN}Done.${RESET}"