Ctrl K
ComunidadGuías…

install.sh

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

Archivo original ↗Preguntar a KiBot
#!/bin/bash
# Scout Agent 一键安装 — Linux / macOS
# 用法: curl -fsSL <repo-url>/raw/main/install.sh | bash
#    或: bash install.sh

set -e

# ── 颜色 ──
if [ -t 1 ]; then
    R='\033[0;31m'; G='\033[0;32m'; Y='\033[1;33m'; B='\033[0;34m'; N='\033[0m'
else
    R=''; G=''; Y=''; B=''; N=''
fi
ok()   { echo -e "  ${G}✓${N} $1"; }
info() { echo -e "  ${B}→${N} $1"; }
warn() { echo -e "  ${Y}⚠${N} $1"; }
fail() { echo -e "  ${R}✗${N} $1"; exit 1; }

echo ""
echo -e "${B}  🧭 Scout Agent 安装程序${N}"
echo -e "  ─────────────────────────────"
echo ""

# ── 0. 进入项目目录 ──
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
cd "$SCRIPT_DIR"

# ── 1. 检测 OS ──
OS="$(uname -s)"
ARCH="$(uname -m)"
case "$OS" in
    Linux*)  PLATFORM=linux ;;
    Darwin*) PLATFORM=mac ;;
    *)       fail "不支持的系统: $OS" ;;
esac
ok "系统: $OS ($ARCH)"

# ── 2. 检测/安装 Python 3.11+ ──
find_python() {
    for cmd in python3.13 python3.12 python3.11 python3; do
        if command -v "$cmd" &>/dev/null; then
            ver=$("$cmd" -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null)
            major=$(echo "$ver" | cut -d. -f1)
            minor=$(echo "$ver" | cut -d. -f2)
            if [ "$major" -ge 3 ] && [ "$minor" -ge 11 ]; then
                echo "$cmd"
                return
            fi
        fi
    done
}

PYTHON=$(find_python)

if [ -z "$PYTHON" ]; then
    warn "未找到 Python 3.11+,正在安装..."

    if [ "$PLATFORM" = "mac" ]; then
        # macOS: 优先 Homebrew
        if command -v brew &>/dev/null; then
            info "通过 Homebrew 安装 Python 3.11..."
            brew install python@3.11
            # brew 安装后可能需要 link
            brew link python@3.11 2>/dev/null || true
        else
            # 无 Homebrew → 用 Miniconda
            info "下载 Miniconda..."
            if [ "$ARCH" = "arm64" ]; then
                MC_URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh"
            else
                MC_URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh"
            fi
            curl -fsSL "$MC_URL" -o /tmp/miniconda.sh
            bash /tmp/miniconda.sh -b -p "$HOME/miniconda3"
            rm /tmp/miniconda.sh
            export PATH="$HOME/miniconda3/bin:$PATH"
            conda init --quiet 2>/dev/null || true
            eval "$(conda shell.bash hook 2>/dev/null)" || true
            conda create -n scout python=3.11 -y -q
            conda activate scout
        fi
    else
        # Linux: 检测包管理器
        if command -v apt-get &>/dev/null; then
            info "通过 apt 安装 Python 3.11..."
            sudo apt-get update -qq
            sudo apt-get install -y -qq software-properties-common
            sudo add-apt-repository -y ppa:deadsnakes/ppa 2>/dev/null || true
            sudo apt-get update -qq
            sudo apt-get install -y -qq python3.11 python3.11-venv python3.11-dev
        elif command -v dnf &>/dev/null; then
            info "通过 dnf 安装 Python 3.11..."
            sudo dnf install -y python3.11
        elif command -v yum &>/dev/null; then
            info "通过 yum 安装 Python 3.11..."
            sudo yum install -y python3.11
        elif command -v pacman &>/dev/null; then
            info "通过 pacman 安装 Python..."
            sudo pacman -Sy --noconfirm python python-pip
        else
            # 兜底: Miniconda
            info "通过 Miniconda 安装 Python 3.11..."
            curl -fsSL https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -o /tmp/miniconda.sh
            bash /tmp/miniconda.sh -b -p "$HOME/miniconda3"
            rm /tmp/miniconda.sh
            export PATH="$HOME/miniconda3/bin:$PATH"
            conda init --quiet 2>/dev/null || true
            eval "$(conda shell.bash hook 2>/dev/null)" || true
            conda create -n scout python=3.11 -y -q
            conda activate scout
        fi
    fi

    PYTHON=$(find_python)
    [ -z "$PYTHON" ] && fail "Python 安装失败,请手动安装 Python 3.11+"
fi

ok "Python: $($PYTHON --version 2>&1)"

# ── 3. 检测/安装 pip ──
if ! $PYTHON -m pip --version &>/dev/null; then
    info "安装 pip..."
    curl -fsSL https://bootstrap.pypa.io/get-pip.py | $PYTHON
fi
ok "pip: $($PYTHON -m pip --version 2>&1 | awk '{print $2}')"

# ── 4. 创建 venv(如果不在 conda 环境中) ──
if [ -z "$CONDA_DEFAULT_ENV" ] && [ ! -d ".venv" ]; then
    info "创建虚拟环境 .venv..."
    $PYTHON -m venv .venv
fi
if [ -d ".venv" ]; then
    source .venv/bin/activate
    ok "虚拟环境: .venv"
fi

# ── 5. 安装依赖 ──
info "安装 Python 依赖..."
pip install --upgrade pip -q
if [ -f "requirements.txt" ]; then
    pip install -r requirements.txt -q
fi
# 安装自身
pip install -e . -q 2>/dev/null || true
ok "依赖安装完成"

# ── 6. 配置 .env(引导式) ──
if [ ! -f ".env" ]; then
    # 有模板则复制,否则直接生成最小配置
    if [ -f ".env.example" ]; then
        cp .env.example .env
    else
        cat > .env <<'EOF'
SCOUT_LLM_PROVIDER=dashscope
SCOUT_LLM_MODEL=qwen3.7-plus
SCOUT_LLM_API_KEY=
SCOUT_LLM_TEMPERATURE=0.7
SCOUT_LLM_MAX_TOKENS=4096
SCOUT_EMBEDDING_PROVIDER=
SCOUT_LOG_LEVEL=INFO
EOF
    fi
    ok ".env 已创建"
    # 交互式收集 API Key(非 TTY 环境自动跳过)
    if [ -t 0 ]; then
        printf "\n  ${B}现在配置 LLM API Key?${N}(直接回车跳过,稍后可运行 scout key --add)\n"
        printf "  Provider [dashscope]: "
        read -r _provider
        _provider=${_provider:-dashscope}
        printf "  模型 [qwen3.7-plus]: "
        read -r _model
        _model=${_model:-qwen3.7-plus}
        printf "  API Key: "
        read -r _apikey
        if [ -n "$_apikey" ]; then
            if grep -q "^SCOUT_LLM_PROVIDER=" .env; then
                sed -i.bak "s|^SCOUT_LLM_PROVIDER=.*|SCOUT_LLM_PROVIDER=$_provider|" .env
                sed -i.bak "s|^SCOUT_LLM_MODEL=.*|SCOUT_LLM_MODEL=$_model|" .env
                sed -i.bak "s|^SCOUT_LLM_API_KEY=.*|SCOUT_LLM_API_KEY=$_apikey|" .env
                rm -f .env.bak
            else
                printf "SCOUT_LLM_PROVIDER=%s\nSCOUT_LLM_MODEL=%s\nSCOUT_LLM_API_KEY=%s\n" \
                    "$_provider" "$_model" "$_apikey" >> .env
            fi
            ok "已写入 .env: provider=$_provider model=$_model api_key=***"
        else
            warn "已跳过,稍后可运行: scout key --add dashscope <你的key>"
        fi
    else
        warn "非交互环境,请手动编辑 .env 填入 API Key"
    fi
else
    ok ".env 已存在"
fi

# ── 7. 嵌入配置(默认纯文本检索,无需本地模型)──
# 如需向量语义检索,配置 API 嵌入(见 .env.example 中 SCOUT_EMBEDDING_* 注释)。
info "嵌入: 默认纯文本检索(无需模型与密钥)"

# ── 8. 设置权限 ──
[ -f "run.sh" ] && chmod +x run.sh

# ── 9. 注册 scout 快捷指令(写入 shell 环境变量 PATH) ──
register_shortcut() {
    local scout_bin=""
    # 1) 项目 venv
    if [ -x "$(pwd)/.venv/bin/scout" ]; then
        scout_bin="$(pwd)/.venv/bin"
    # 2) 当前 conda 环境
    elif [ -n "$CONDA_PREFIX" ] && [ -x "$CONDA_PREFIX/bin/scout" ]; then
        scout_bin="$CONDA_PREFIX/bin"
    # 3) 已全局可用
    elif command -v scout &>/dev/null; then
        scout_bin="$(cd "$(dirname "$(command -v scout)")" && pwd)"
    fi

    if [ -z "$scout_bin" ]; then
        warn "未找到 scout 可执行文件,跳过快捷指令注册"
        return 1
    fi

    # 已在当前会话 PATH 且不属于项目 venv → 视为已可用,无需写 rc 文件
    if echo ":$PATH:" | grep -qF ":$scout_bin:" && [ "$scout_bin" != "$(pwd)/.venv/bin" ]; then
        ok "快捷指令 scout 已可用: $scout_bin"
        return 0
    fi

    local rc=""
    case "${SHELL##*/}" in
        zsh)  rc="$HOME/.zshrc" ;;
        bash) rc="$HOME/.bashrc" ;;
        *)    rc="$HOME/.profile" ;;
    esac

    if grep -qF "scout" "$rc" 2>/dev/null; then
        ok "快捷指令 scout 已在 $rc 中注册 → $scout_bin"
        return 0
    fi

    printf '\n# Scout Agent CLI 快捷指令\nexport PATH="$PATH:%s"\n' "$scout_bin" >> "$rc"
    ok "已注册快捷指令到 $rc: export PATH=\"\$PATH:$scout_bin\""
    info "新开终端即可直接运行 scout;当前终端请先执行: source $rc"
}
register_shortcut

# ── 完成 ──
echo ""
echo -e "${G}  ╔═══════════════════════════════════════╗${N}"
echo -e "${G}  ║       🎉 安装完成!                   ║${N}"
echo -e "${G}  ╚═══════════════════════════════════════╝${N}"
echo ""
echo -e "  ${Y}下一步:${N}"
echo ""
echo -e "    1. 环境自检:      ${B}scout doctor${N}"
echo -e "    2. 配置 API Key:  ${B}scout key --add <provider> <key>${N}  或  ${B}nano .env${N}"
echo -e "    3. 启动 Web 服务: ${B}bash run.sh --web${N}"
echo -e "    4. 打开浏览器:    ${B}http://localhost:8848${N}"
echo ""