Add CutOS Agent installer

This commit is contained in:
yankun
2026-08-02 16:37:06 +08:00
commit 10fb734df3
2 changed files with 237 additions and 0 deletions
Executable
+216
View File
@@ -0,0 +1,216 @@
#!/usr/bin/env bash
# CutOS Agent installer
# Run: curl -fsSL https://git.cutos.ai/claw-daemon/cutos-agent/raw/main/install.sh | bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[cutos-agent]${NC} $*"; }
warn() { echo -e "${YELLOW}[cutos-agent]${NC} $*"; }
error() { echo -e "${RED}[cutos-agent]${NC} $*" >&2; exit 1; }
require_command() {
if ! command -v "$1" >/dev/null 2>&1; then
error "$1 not found. Please install $1 and run this installer again."
fi
}
run_root() {
if [ "${EUID:-$(id -u)}" -eq 0 ]; then
"$@"
return
fi
require_command sudo
sudo "$@"
}
detect_user() {
if [ "${EUID:-$(id -u)}" -eq 0 ]; then
if [ -n "${SUDO_USER:-}" ] && [ "${SUDO_USER}" != "root" ]; then
printf '%s' "$SUDO_USER"
else
printf 'root'
fi
else
id -un
fi
}
detect_home() {
local user="$1"
local home=""
if command -v getent >/dev/null 2>&1; then
home="$(getent passwd "$user" | cut -d: -f6 || true)"
fi
if [ -z "$home" ]; then
home="${HOME:-}"
fi
if [ -z "$home" ]; then
error "Cannot determine home directory for user $user"
fi
printf '%s' "$home"
}
npm_global_install() {
info "Installing $* ..."
if npm install -g "$@"; then
return
fi
if [ "${EUID:-$(id -u)}" -eq 0 ]; then
error "npm install failed: $*"
fi
warn "Retrying global npm install with sudo ..."
run_root env PATH="$PATH" npm install -g "$@"
}
run_as_target_user() {
if [ "$TARGET_USER" = "root" ]; then
HOME="$TARGET_HOME" "$@"
return
fi
if [ "${EUID:-$(id -u)}" -eq 0 ]; then
runuser -u "$TARGET_USER" -- env HOME="$TARGET_HOME" PATH="$PATH" "$@"
else
HOME="$TARGET_HOME" "$@"
fi
}
install_pi_package() {
local package="$1"
info "Installing Pi extension: $package"
run_as_target_user "$PI_BIN" install "$package"
}
resolve_bin() {
local name="$1"
local found=""
found="$(command -v "$name" || true)"
if [ -n "$found" ]; then
printf '%s' "$found"
return
fi
local prefix=""
prefix="$(npm prefix -g 2>/dev/null || true)"
if [ -n "$prefix" ] && [ -x "$prefix/bin/$name" ]; then
printf '%s' "$prefix/bin/$name"
return
fi
if [ -x "/usr/local/bin/$name" ]; then
printf '%s' "/usr/local/bin/$name"
return
fi
if [ -x "/usr/bin/$name" ]; then
printf '%s' "/usr/bin/$name"
return
fi
error "Cannot find $name after installation"
}
write_pi_web_service() {
local pi_web_bin="$1"
local service_file="/etc/systemd/system/pi-web.service"
info "Writing pi-web systemd service ..."
run_root tee "$service_file" >/dev/null <<EOF
[Unit]
Description=Pi Web Console
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=$TARGET_USER
Environment=HOME=$TARGET_HOME
WorkingDirectory=$PI_HOME
ExecStart=$pi_web_bin --no-open
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
run_root systemctl daemon-reload
run_root systemctl enable pi-web.service
run_root systemctl restart pi-web.service
}
require_command node
require_command npm
NODE_VER="$(node -e "process.stdout.write(process.versions.node)")"
NODE_MAJOR="$(printf '%s' "$NODE_VER" | cut -d. -f1)"
if [ "$NODE_MAJOR" -lt 18 ]; then
error "Node.js $NODE_VER is too old. Please install Node.js >= 18."
fi
info "Node.js $NODE_VER OK"
TARGET_USER="$(detect_user)"
TARGET_HOME="$(detect_home "$TARGET_USER")"
TARGET_GROUP="$(id -gn "$TARGET_USER" 2>/dev/null || printf '%s' "$TARGET_USER")"
PI_HOME="$TARGET_HOME/.pi"
info "Installing for user: $TARGET_USER"
info "Pi working directory: $PI_HOME"
run_root mkdir -p "$PI_HOME"
if [ "$TARGET_USER" != "root" ]; then
run_root chown "$TARGET_USER:$TARGET_GROUP" "$PI_HOME"
fi
npm_global_install @earendil-works/pi-coding-agent@latest --allow-scripts=@google/genai,protobufjs,sharp
npm_global_install @agegr/pi-web
PI_BIN="$(resolve_bin pi)"
PI_WEB_BIN="$(resolve_bin pi-web)"
info "pi CLI: $PI_BIN"
info "pi-web: $PI_WEB_BIN"
install_pi_package npm:pi-wechat-assistant
install_pi_package npm:@jay-zod/speakturbo
install_pi_package npm:pi-codex-image-gen
install_pi_package npm:@mammothb/pi-office
install_pi_package npm:@zosmaai/pi-llm-wiki
install_pi_package npm:pi-git-commands-extension
install_pi_package npm:@xjuai/pi-feishu-lark
install_pi_package npm:pi-ocr
install_pi_package npm:pi-schedule-prompt
write_pi_web_service "$PI_WEB_BIN"
sleep 2
if systemctl is-active --quiet pi-web.service; then
info "pi-web is running"
else
warn "pi-web failed to start. Check logs with: journalctl -u pi-web -n 50 --no-pager"
fi
cat <<EOF
CutOS Agent install complete.
Pi home: $PI_HOME
Service: pi-web.service
Logs: journalctl -u pi-web -f
Console: http://127.0.0.1:30141/
EOF