#!/usr/bin/env bash # ============================================================================= # FranklinWH Toolbox - Kiro CLI 安装脚本 # ============================================================================= # 作用:为后端 AI 对话功能安装 kiro-cli。后端通过 ACP 协议以子进程方式拉起 # `kiro-cli`,并降权到 config.env 中的 KIRO_RUN_AS_USER(HOME=KIRO_HOME)。 # 因此 kiro-cli 必须: # 1. 安装到可被该用户执行的位置(默认装到该用户的 ~/.local/bin); # 2. 该用户完成 `kiro-cli login`(AWS Builder ID,交互式)后方可使用。 # # 安装方式(优先级): # 1. ZIP 安装包(离线/可控,默认):下载官方 kirocli--linux[-musl].zip, # 解压后以目标用户身份运行 install.sh --no-confirm。 # 2. 官方一键脚本(KIRO_INSTALL_METHOD=curl):curl -fsSL https://cli.kiro.dev/install | bash # # 前置条件:curl、unzip(缺失会尝试用 apt 安装) # # 环境变量: # KIRO_RUN_AS_USER 安装并运行 kiro-cli 的系统用户 (默认当前用户) # KIRO_HOME 该用户 HOME(决定 ~/.kiro 配置位置) (默认该用户家目录) # KIRO_INSTALL_METHOD zip | curl (默认 zip) # KIRO_LIBC gnu | musl(zip 方式的 C 库变体) (默认 gnu) # KIRO_ZIP_URL 自定义 ZIP 下载地址(覆盖自动推断) (默认空) # KIRO_DO_LOGIN 安装后是否立即交互式登录 (y/n) (默认 n) # ============================================================================= set -euo pipefail KIRO_RUN_AS_USER="${KIRO_RUN_AS_USER:-$(id -un)}" KIRO_HOME="${KIRO_HOME:-}" KIRO_INSTALL_METHOD="${KIRO_INSTALL_METHOD:-zip}" KIRO_LIBC="${KIRO_LIBC:-gnu}" KIRO_ZIP_URL="${KIRO_ZIP_URL:-}" KIRO_DO_LOGIN="${KIRO_DO_LOGIN:-n}" c_reset='\033[0m'; c_blue='\033[1;34m'; c_green='\033[1;32m'; c_yellow='\033[1;33m'; c_red='\033[1;31m' info() { echo -e "${c_blue}[INFO]${c_reset} $*"; } ok() { echo -e "${c_green}[ OK ]${c_reset} $*"; } warn() { echo -e "${c_yellow}[WARN]${c_reset} $*"; } err() { echo -e "${c_red}[FAIL]${c_reset} $*" >&2; } has() { command -v "$1" >/dev/null 2>&1; } # 解析目标用户 HOME(KIRO_HOME 优先,否则取该用户 passwd 家目录) resolve_home() { if [[ -n "${KIRO_HOME}" ]]; then echo "${KIRO_HOME}"; return 0 fi getent passwd "${KIRO_RUN_AS_USER}" | cut -d: -f6 } # 以目标用户身份执行命令(设置正确的 HOME/USER),当前用户即目标用户时直接执行 as_target_user() { local home; home="$(resolve_home)" if [[ "${KIRO_RUN_AS_USER}" == "$(id -un)" ]]; then HOME="${home}" bash -lc "$*" else sudo -u "${KIRO_RUN_AS_USER}" -H env HOME="${home}" bash -lc "$*" fi } # --------------------------------------------------------------------------- # 0. 前置依赖 # --------------------------------------------------------------------------- ensure_prereqs() { local need=() has curl || need+=(curl) has unzip || need+=(unzip) if [[ ${#need[@]} -gt 0 ]]; then info "安装依赖:${need[*]}" if has apt-get; then sudo apt-get update -y sudo apt-get install -y "${need[@]}" else err "缺少 ${need[*]},且系统无 apt-get,请手动安装后重试" return 1 fi fi if ! getent passwd "${KIRO_RUN_AS_USER}" >/dev/null; then err "系统用户不存在:${KIRO_RUN_AS_USER}(请先创建,或修正 KIRO_RUN_AS_USER)" return 1 fi } # 已装则跳过(检测目标用户可见的 kiro-cli) already_installed() { if as_target_user 'command -v kiro-cli >/dev/null 2>&1'; then local ver; ver="$(as_target_user 'kiro-cli version 2>/dev/null | head -n1' || true)" ok "kiro-cli 已安装(用户 ${KIRO_RUN_AS_USER}):${ver:-unknown}" return 0 fi return 1 } # 推断 ZIP 下载地址 resolve_zip_url() { if [[ -n "${KIRO_ZIP_URL}" ]]; then echo "${KIRO_ZIP_URL}"; return 0; fi local arch; arch="$(uname -m)" local platform case "${arch}" in x86_64|amd64) platform="x86_64-linux" ;; aarch64|arm64) platform="aarch64-linux" ;; *) err "未知架构:${arch}(可用 KIRO_ZIP_URL 手动指定下载地址)"; return 1 ;; esac [[ "${KIRO_LIBC}" == "musl" ]] && platform="${platform}-musl" echo "https://desktop-release.q.us-east-1.amazonaws.com/latest/kirocli-${platform}.zip" } # --------------------------------------------------------------------------- # 1a. ZIP 方式安装 # --------------------------------------------------------------------------- install_via_zip() { local url; url="$(resolve_zip_url)" || return 1 info "下载 Kiro CLI 安装包:${url}" local tmp; tmp="$(mktemp -d)" # 以目标用户身份下载/解压/安装,确保产物落到其家目录且属主正确 local home; home="$(resolve_home)" sudo chown "${KIRO_RUN_AS_USER}" "${tmp}" 2>/dev/null || true as_target_user "cd '${tmp}' && \ curl --proto '=https' --tlsv1.2 -sSf '${url}' -o kirocli.zip && \ unzip -q kirocli.zip && \ bash ./kirocli/install.sh --no-confirm" rm -rf "${tmp}" ok "Kiro CLI 安装完成(ZIP 方式)" } # --------------------------------------------------------------------------- # 1b. 官方一键脚本安装 # --------------------------------------------------------------------------- install_via_curl() { info "使用官方一键脚本安装 Kiro CLI ..." as_target_user "curl -fsSL https://cli.kiro.dev/install | bash" ok "Kiro CLI 安装完成(curl 方式)" } # --------------------------------------------------------------------------- # 2. 校验 # --------------------------------------------------------------------------- verify() { info "校验 kiro-cli 可用性(用户 ${KIRO_RUN_AS_USER})..." if as_target_user 'command -v kiro-cli >/dev/null 2>&1'; then local ver; ver="$(as_target_user 'kiro-cli version 2>/dev/null | head -n1' || true)" ok "kiro-cli 可用:${ver:-installed}" else warn "在登录 shell 中未找到 kiro-cli。安装脚本可能已把它装到 ~/.local/bin," warn "需确保该目录在 PATH 中(安装脚本一般会写入 shell 配置,重登后生效)。" warn "后端拉起 kiro-cli 时依赖 PATH/HOME,请确认 KIRO_HOME 与该用户一致。" fi } # --------------------------------------------------------------------------- # 3. 登录(可选,交互式) # --------------------------------------------------------------------------- login() { [[ "${KIRO_DO_LOGIN}" == "y" ]] || return 0 info "启动 kiro-cli 登录(AWS Builder ID,按提示在浏览器完成认证)..." as_target_user "kiro-cli login" || warn "登录未完成,可稍后以 ${KIRO_RUN_AS_USER} 身份运行 'kiro-cli login'" } main() { info "== 安装 Kiro CLI(AI 对话依赖)==" info "运行用户=${KIRO_RUN_AS_USER} HOME=$(resolve_home) 方式=${KIRO_INSTALL_METHOD}" ensure_prereqs if already_installed; then verify; login return 0 fi case "${KIRO_INSTALL_METHOD}" in zip) install_via_zip ;; curl) install_via_curl ;; *) err "未知 KIRO_INSTALL_METHOD:${KIRO_INSTALL_METHOD}(可选 zip|curl)"; exit 1 ;; esac verify login cat <