From 0ac3d0e1011ccd38f283feb77ce073a3d8d34cb7 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Tue, 6 May 2025 21:58:16 +0200 Subject: [PATCH 01/16] cleanup install script --- install.sh | 682 ++++++++++++++++++++++++++++------------------------- 1 file changed, 360 insertions(+), 322 deletions(-) diff --git a/install.sh b/install.sh index 9ff853d0..1cf2f354 100755 --- a/install.sh +++ b/install.sh @@ -16,6 +16,11 @@ tty_cyan="$(tty_mkbold 36)" tty_magenta="$(tty_mkbold 35)" tty_underline="$(tty_escape 4)" +CAT=${CAT:-cat} +ARCH=$(uname -m) +OS=$(uname -s) + + ohai() { printf "${tty_blue}==>${tty_bold} %s${tty_reset}\n" "$1" } @@ -33,132 +38,137 @@ abort() { exit 1 } -success() { - ohai "Installation complete! Run 'agentuity --help' to get started." - ohai "For more information, visit: $(url "https://agentuity.dev")" - - if ! command -v agentuity >/dev/null 2>&1; then - printf "${tty_blue}==>${tty_bold} ${tty_magenta}To apply PATH changes, restart your terminal or run:${tty_reset} source ~/.$(basename $SHELL)rc\n" + +check_known_arch() { + if [[ "$ARCH" != "x86_64" ]] && [[ "$ARCH" != "amd64" ]] && [[ "$ARCH" != "arm64" ]] && [[ "$ARCH" != "aarch64" ]]; then + abort "Unsupported architecture: $ARCH" fi - - exit 0 } -OS="$(uname -s)" -ARCH="$(uname -m)" - -if [[ "$ARCH" == "x86_64" ]]; then - ARCH="x86_64" -elif [[ "$ARCH" == "amd64" ]]; then - ARCH="x86_64" -elif [[ "$ARCH" == "arm64" ]]; then - ARCH="arm64" -elif [[ "$ARCH" == "aarch64" ]]; then - ARCH="arm64" -else - abort "Unsupported architecture: $ARCH" -fi +is_x86_64() { + check_known_arch + if [[ "$ARCH" == "x86_64" ]] || [[ "$ARCH" == "amd64" ]]; then + return 0 + else + return 1 + fi +} -if [[ "$OS" == "Darwin" ]]; then - OS="Darwin" - EXTENSION="tar.gz" - if [[ -d "$HOME/.local/bin" ]] && [[ -w "$HOME/.local/bin" ]]; then - INSTALL_DIR="$HOME/.local/bin" - elif [[ -d "$HOME/.bin" ]] && [[ -w "$HOME/.bin" ]]; then - INSTALL_DIR="$HOME/.bin" - elif [[ -d "$HOME/bin" ]] && [[ -w "$HOME/bin" ]]; then - INSTALL_DIR="$HOME/bin" +is_arm64() { + check_known_arch + if [[ "$ARCH" == "arm64" ]] || [[ "$ARCH" == "aarch64" ]]; then + return 0 else - INSTALL_DIR="/usr/local/bin" + return 1 fi -elif [[ "$OS" == "Linux" ]]; then - OS="Linux" - EXTENSION="tar.gz" - if [[ -d "$HOME/.local/bin" ]] && [[ -w "$HOME/.local/bin" ]]; then - INSTALL_DIR="$HOME/.local/bin" - elif [[ -d "$HOME/.bin" ]] && [[ -w "$HOME/.bin" ]]; then - INSTALL_DIR="$HOME/.bin" - elif [[ -d "$HOME/bin" ]] && [[ -w "$HOME/bin" ]]; then - INSTALL_DIR="$HOME/bin" +} + +is_windows() { + check_known_arch + if [[ "$OS" == "Windows" ]]; then + return 0 else - INSTALL_DIR="/usr/local/bin" + return 1 fi -elif [[ "$OS" == "MINGW"* ]] || [[ "$OS" == "MSYS"* ]] || [[ "$OS" == "CYGWIN"* ]]; then - OS="Windows" - EXTENSION="msi" - INSTALL_DIR="$HOME/bin" -else - abort "Unsupported operating system: $OS" -fi +} -VERSION="latest" -INSTALL_PATH="$INSTALL_DIR" - -while [[ $# -gt 0 ]]; do - case "$1" in - -v|--version) - VERSION="$2" - shift 2 - ;; - -d|--dir) - INSTALL_PATH="$2" - shift 2 - ;; - --no-brew) - NO_BREW=true - shift - ;; - -h|--help) - echo "Usage: install.sh [options]" - echo "Options:" - echo " -v, --version VERSION Install specific version" - echo " -d, --dir DIRECTORY Install to specific directory" - if [[ "$OS" == "Darwin" ]]; then - echo " --no-brew Skip Homebrew installation on macOS" - fi - echo " -h, --help Show this help message" - exit 0 - ;; - *) - warn "Unknown option: $1" - shift - ;; - esac -done - -if [[ ! -d "$INSTALL_PATH" ]]; then - ohai "Creating install directory: $INSTALL_PATH" - mkdir -p "$INSTALL_PATH" 2>/dev/null || true # Don't abort if mkdir fails -fi +is_macos() { + check_known_arch + if [[ "$OS" == "Darwin" ]]; then + return 0 + else + return 1 + fi +} -if [[ "$OS" == "Darwin" ]] && command -v brew >/dev/null 2>&1 && [[ "$NO_BREW" != "true" ]]; then - ohai "Homebrew detected! Installing Agentuity CLI using Homebrew..." - - if [[ "$VERSION" != "latest" ]]; then - ohai "Installing Agentuity CLI version $VERSION using Homebrew..." - - if [[ -z "$VERSION" ]]; then - abort "Version is empty. This should not happen." - fi - - VERSION="${VERSION#v}" - - ohai "Using Homebrew formula: agentuity/tap/agentuity@$VERSION" - brew install "agentuity/tap/agentuity@$VERSION" +is_linux() { + check_known_arch + if [[ "$OS" == "Linux" ]]; then + return 0 else - ohai "Installing latest Agentuity CLI version using Homebrew..." - brew install -q agentuity/tap/agentuity + return 1 fi - - if command -v agentuity >/dev/null 2>&1; then - success +} + +setup_extension_var() { + if is_macos; then + EXTENSION="tar.gz" + elif is_linux; then + EXTENSION="tar.gz" + elif is_windows; then + EXTENSION="msi" else - abort "Homebrew installation failed. Please try again or use manual installation." + abort "Unsupported operating system: $OS" fi -fi +} + +setup_install_path_var() { + if is_macos; then + if [[ -d "$HOME/.local/bin" ]] && [[ -w "$HOME/.local/bin" ]]; then + INSTALL_PATH="$HOME/.local/bin" + elif [[ -d "$HOME/.bin" ]] && [[ -w "$HOME/.bin" ]]; then + INSTALL_PATH="$HOME/.bin" + elif [[ -d "$HOME/bin" ]] && [[ -w "$HOME/bin" ]]; then + INSTALL_PATH="$HOME/bin" + else + INSTALL_PATH="/usr/local/bin" + fi + elif is_linux; then + if [[ -d "$HOME/.local/bin" ]] && [[ -w "$HOME/.local/bin" ]]; then + INSTALL_PATH="$HOME/.local/bin" + elif [[ -d "$HOME/.bin" ]] && [[ -w "$HOME/.bin" ]]; then + INSTALL_PATH="$HOME/.bin" + elif [[ -d "$HOME/bin" ]] && [[ -w "$HOME/bin" ]]; then + INSTALL_PATH="$HOME/bin" + else + INSTALL_PATH="/usr/local/bin" + fi + elif is_windows; then + INSTALL_PATH="$HOME/bin" + else + abort "Unsupported operating system: $OS" + fi +} + +usage() { +$CAT 1>&2 </dev/null || true # Don't abort if mkdir fails + fi + + if [[ -w "$INSTALL_PATH" ]]; then + return + fi -if [[ ! -d "$INSTALL_PATH" ]] || [[ ! -w "$INSTALL_PATH" ]]; then if [[ "$INSTALL_PATH" == "/usr/local/bin" ]]; then ohai "No write permission to $INSTALL_PATH. Trying alternative locations..." @@ -183,256 +193,284 @@ if [[ ! -d "$INSTALL_PATH" ]] || [[ ! -w "$INSTALL_PATH" ]]; then else abort "No write permission to $INSTALL_PATH. Try running with sudo or specify a different directory with --dir." fi -fi +} -TMP_DIR="$(mktemp -d)" -cleanup() { - rm -rf "$TMP_DIR" +check_version() { + if [[ -z "$VERSION" ]]; then + abort "Version is empty. This should not happen." + fi } -trap cleanup EXIT - -if [[ "$VERSION" == "latest" ]]; then - ohai "Fetching latest release information..." - RELEASE_URL="https://agentuity.sh/release/cli" - VERSION=$(curl -s $RELEASE_URL | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') - if [[ -z "$VERSION" ]]; then - abort "Failed to fetch latest version information" + +check_latest_release() { + if [[ "$VERSION" == "latest" ]]; then + ohai "Fetching latest release information..." + RELEASE_URL="https://agentuity.sh/release/cli" + VERSION=$(curl -s $RELEASE_URL | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + if [[ -z "$VERSION" ]]; then + abort "Failed to fetch latest version information" + fi fi -fi +} -VERSION="${VERSION#v}" +install_mac() { + if command -v brew >/dev/null 2>&1 && [[ "$NO_BREW" != "true" ]]; then + ohai "Homebrew detected! Installing Agentuity CLI using Homebrew..." + + if [[ "$VERSION" != "latest" ]]; then + ohai "Installing Agentuity CLI version $VERSION using Homebrew..." + brew install agentuity/tap/agentuity@${VERSION#v} + else + ohai "Installing latest Agentuity CLI version using Homebrew..." + brew install -q agentuity/tap/agentuity + fi -if [[ "$OS" == "Windows" ]]; then - if [[ "$ARCH" == "x86_64" ]]; then - DOWNLOAD_FILENAME="agentuity-x64.msi" - elif [[ "$ARCH" == "arm64" ]]; then - DOWNLOAD_FILENAME="agentuity-arm64.msi" - else - DOWNLOAD_FILENAME="agentuity-x86.msi" + if command -v agentuity >/dev/null 2>&1; then + success + else + abort "Homebrew installation failed. Please try again or use manual installation." + fi + + else + ohai "Installing Agentuity CLI using curl..." + curl -fsSL https://agentuity.sh/install.sh | bash fi -else - DOWNLOAD_FILENAME="agentuity_${OS}_${ARCH}.${EXTENSION}" -fi -DOWNLOAD_URL="https://github.com/agentuity/cli/releases/download/v${VERSION}/${DOWNLOAD_FILENAME}" -CHECKSUMS_URL="https://github.com/agentuity/cli/releases/download/v${VERSION}/checksums.txt" +} -ohai "Downloading Agentuity CLI v${VERSION} for ${OS}/${ARCH}..." -curl -L --progress-bar "$DOWNLOAD_URL" -o "$TMP_DIR/$DOWNLOAD_FILENAME" || abort "Failed to download from $DOWNLOAD_URL" +download_release() { -if [[ "$OS" != "Windows" ]]; then - ohai "Downloading checksums for verification..." - if ! curl -L --silent "$CHECKSUMS_URL" -o "$TMP_DIR/checksums.txt"; then - warn "Failed to download checksums file. Skipping verification." - else - ohai "Verifying checksum..." - if command -v sha256sum >/dev/null 2>&1; then - CHECKSUM_TOOL="sha256sum" - elif command -v shasum >/dev/null 2>&1; then - CHECKSUM_TOOL="shasum -a 256" + if [[ is_windows ]]; then + if is_x86_64; then + DOWNLOAD_FILENAME="agentuity-x64.msi" + elif is_arm64; then + DOWNLOAD_FILENAME="agentuity-arm64.msi" else - warn "Neither sha256sum nor shasum found. Skipping checksum verification." - CHECKSUM_TOOL="" + DOWNLOAD_FILENAME="agentuity-x86.msi" fi - - if [[ -n "$CHECKSUM_TOOL" ]]; then - cd "$TMP_DIR" - COMPUTED_CHECKSUM=$($CHECKSUM_TOOL "$DOWNLOAD_FILENAME" | cut -d ' ' -f 1) - EXPECTED_CHECKSUM=$(grep "$DOWNLOAD_FILENAME" checksums.txt | cut -d ' ' -f 1) - - if [[ -z "$EXPECTED_CHECKSUM" ]]; then - warn "Checksum for $DOWNLOAD_FILENAME not found in checksums.txt. Skipping verification." - elif [[ "$COMPUTED_CHECKSUM" != "$EXPECTED_CHECKSUM" ]]; then - abort "Checksum verification failed. Expected: $EXPECTED_CHECKSUM, Got: $COMPUTED_CHECKSUM" + else + DOWNLOAD_FILENAME="agentuity_${OS}_${ARCH}.${EXTENSION}" + fi + + DOWNLOAD_URL="https://github.com/agentuity/cli/releases/download/v${VERSION#v}/${DOWNLOAD_FILENAME}" + + ohai "Downloading Agentuity CLI v${VERSION} for ${OS}/${ARCH}..." + curl -L --progress-bar "$DOWNLOAD_URL" -o "$TMP_DIR/$DOWNLOAD_FILENAME" || abort "Failed to download from $DOWNLOAD_URL" +} + +download_checksums() { + CHECKSUMS_URL="https://github.com/agentuity/cli/releases/download/v${VERSION#v}/checksums.txt" + if is_windows; then + ohai "Downloading checksums for verification..." + if ! curl -L --silent "$CHECKSUMS_URL" -o "$TMP_DIR/checksums.txt"; then + warn "Failed to download checksums file. Skipping verification." + else + ohai "Verifying checksum..." + if command -v sha256sum >/dev/null 2>&1; then + CHECKSUM_TOOL="sha256sum" + elif command -v shasum >/dev/null 2>&1; then + CHECKSUM_TOOL="shasum -a 256" else - ohai "Checksum verification passed!" + warn "Neither sha256sum nor shasum found. Skipping checksum verification." + CHECKSUM_TOOL="" + fi + + if [[ -n "$CHECKSUM_TOOL" ]]; then + cd "$TMP_DIR" + COMPUTED_CHECKSUM=$($CHECKSUM_TOOL "$DOWNLOAD_FILENAME" | cut -d ' ' -f 1) + EXPECTED_CHECKSUM=$(grep "$DOWNLOAD_FILENAME" checksums.txt | cut -d ' ' -f 1) + + if [[ -z "$EXPECTED_CHECKSUM" ]]; then + warn "Checksum for $DOWNLOAD_FILENAME not found in checksums.txt. Skipping verification." + elif [[ "$COMPUTED_CHECKSUM" != "$EXPECTED_CHECKSUM" ]]; then + abort "Checksum verification failed. Expected: $EXPECTED_CHECKSUM, Got: $COMPUTED_CHECKSUM" + else + ohai "Checksum verification passed!" + fi + cd - > /dev/null fi - cd - > /dev/null fi fi -fi +} -ohai "Processing download..." -if [[ "$OS" == "Windows" ]]; then - ohai "Downloaded Windows MSI installer to $TMP_DIR/$DOWNLOAD_FILENAME" - - if [[ -n "${CI}" || -n "${GITHUB_ACTIONS}" || -n "${NONINTERACTIVE}" ]]; then - warn "Non-interactive environment detected, skipping automatic MSI installation" - cp "$TMP_DIR/$DOWNLOAD_FILENAME" "$HOME/" || abort "Failed to copy MSI to $HOME/" - ohai "MSI installer copied to $HOME/$DOWNLOAD_FILENAME" - ohai "To install manually, run the MSI installer at:" - echo " $HOME/$DOWNLOAD_FILENAME" - exit 0 - fi - - ohai "Attempting to run MSI installer automatically..." - if command -v msiexec >/dev/null 2>&1; then - ohai "Running installer with msiexec..." - msiexec /i "$TMP_DIR/$DOWNLOAD_FILENAME" /qn /norestart - INSTALL_STATUS=$? - if [[ $INSTALL_STATUS -eq 0 ]]; then - ohai "Installation completed successfully!" - exit 0 - else - warn "Automatic installation failed with status: $INSTALL_STATUS" +install_agentuity() { + ohai "Installing to $INSTALL_PATH..." + if [[ -f "$TMP_DIR/agentuity" ]]; then + if [[ is_macos ]] && [[ -f "$INSTALL_PATH/agentuity" ]]; then + ohai "Removing existing binary to avoid macOS quarantine issues..." + rm -f "$INSTALL_PATH/agentuity" || abort "Failed to remove existing binary from $INSTALL_PATH" fi + cp "$TMP_DIR/agentuity" "$INSTALL_PATH/" || abort "Failed to copy binary to $INSTALL_PATH" + chmod +x "$INSTALL_PATH/agentuity" || abort "Failed to make binary executable" else - warn "msiexec not found, cannot run installer automatically" + abort "Binary not found in extracted archive" fi - - cp "$TMP_DIR/$DOWNLOAD_FILENAME" "$HOME/" || abort "Failed to copy MSI to $HOME/" - ohai "MSI installer copied to $HOME/$DOWNLOAD_FILENAME" - ohai "To install manually, run the MSI installer at:" - echo " $HOME/$DOWNLOAD_FILENAME" - exit 0 -elif [[ "$EXTENSION" == "tar.gz" ]]; then - ohai "Extracting..." - tar -xzf "$TMP_DIR/$DOWNLOAD_FILENAME" -C "$TMP_DIR" || abort "Failed to extract archive" -elif [[ "$EXTENSION" == "zip" ]]; then - ohai "Extracting..." - unzip -q "$TMP_DIR/$DOWNLOAD_FILENAME" -d "$TMP_DIR" || abort "Failed to extract archive" -else - abort "Unknown archive format: $EXTENSION" -fi -ohai "Installing to $INSTALL_PATH..." -if [[ -f "$TMP_DIR/agentuity" ]]; then - if [[ "$OS" == "Darwin" ]] && [[ -f "$INSTALL_PATH/agentuity" ]]; then - ohai "Removing existing binary to avoid macOS quarantine issues..." - rm -f "$INSTALL_PATH/agentuity" || abort "Failed to remove existing binary from $INSTALL_PATH" + if command -v "$INSTALL_PATH/agentuity" >/dev/null 2>&1; then + ohai "Successfully installed Agentuity CLI to $INSTALL_PATH/agentuity" + else + abort "Installation verification failed" fi - cp "$TMP_DIR/agentuity" "$INSTALL_PATH/" || abort "Failed to copy binary to $INSTALL_PATH" - chmod +x "$INSTALL_PATH/agentuity" || abort "Failed to make binary executable" -else - abort "Binary not found in extracted archive" -fi - -if command -v "$INSTALL_PATH/agentuity" >/dev/null 2>&1; then - ohai "Successfully installed Agentuity CLI to $INSTALL_PATH/agentuity" -else - abort "Installation verification failed" -fi +} -if [[ ":$PATH:" != *":$INSTALL_PATH:"* ]]; then - ohai "Adding $INSTALL_PATH to your PATH..." - - SHELL_CONFIG="" - case "$SHELL" in - */bash*) - SHELL_CONFIG="$HOME/.bashrc" - if [[ -f "$HOME/.bash_profile" ]]; then - SHELL_CONFIG="$HOME/.bash_profile" - fi - ;; - */zsh*) - SHELL_CONFIG="$HOME/.zshrc" - ;; - */fish*) - SHELL_CONFIG="$HOME/.config/fish/config.fish" - ;; - esac - - if [[ -n "$SHELL_CONFIG" ]] && [[ -w "$SHELL_CONFIG" ]]; then - echo "export PATH=\"\$PATH:$INSTALL_PATH\"" >> "$SHELL_CONFIG" - ohai "Added $INSTALL_PATH to PATH in $SHELL_CONFIG" +set_path() { + if [[ ":$PATH:" != *":$INSTALL_PATH:"* ]]; then + ohai "Adding $INSTALL_PATH to your PATH..." - if ! command -v agentuity >/dev/null 2>&1; then - printf "${tty_blue}==>${tty_bold} ${tty_magenta}To apply changes, restart your terminal or run:${tty_reset} source $SHELL_CONFIG\n" - fi - - export PATH="$PATH:$INSTALL_PATH" - else - warn "$INSTALL_PATH is not in your PATH. You may need to add it manually to use the agentuity command." + SHELL_CONFIG="" case "$SHELL" in */bash*) - echo " echo 'export PATH=\"\$PATH:$INSTALL_PATH\"' >> ~/.bashrc" - echo " source ~/.bashrc # To apply changes immediately" + SHELL_CONFIG="$HOME/.bashrc" + if [[ -f "$HOME/.bash_profile" ]]; then + SHELL_CONFIG="$HOME/.bash_profile" + fi ;; */zsh*) - echo " echo 'export PATH=\"\$PATH:$INSTALL_PATH\"' >> ~/.zshrc" - echo " source ~/.zshrc # To apply changes immediately" + SHELL_CONFIG="$HOME/.zshrc" ;; */fish*) - echo " echo 'set -gx PATH \$PATH $INSTALL_PATH' >> ~/.config/fish/config.fish" - echo " source ~/.config/fish/config.fish # To apply changes immediately" - ;; - *) - echo " Add $INSTALL_PATH to your PATH" - echo " Then restart your terminal or reload your shell configuration" + SHELL_CONFIG="$HOME/.config/fish/config.fish" ;; esac + + if [[ -n "$SHELL_CONFIG" ]] && [[ -w "$SHELL_CONFIG" ]]; then + echo "export PATH=\"\$PATH:$INSTALL_PATH\"" >> "$SHELL_CONFIG" + ohai "Added $INSTALL_PATH to PATH in $SHELL_CONFIG" + + if ! command -v agentuity >/dev/null 2>&1; then + printf "${tty_blue}==>${tty_bold} ${tty_magenta}To apply changes, restart your terminal or run:${tty_reset} source $SHELL_CONFIG\n" + fi + + export PATH="$PATH:$INSTALL_PATH" + else + warn "$INSTALL_PATH is not in your PATH. You may need to add it manually to use the agentuity command." + case "$SHELL" in + */bash*) + echo " echo 'export PATH=\"\$PATH:$INSTALL_PATH\"' >> ~/.bashrc" + echo " source ~/.bashrc # To apply changes immediately" + ;; + */zsh*) + echo " echo 'export PATH=\"\$PATH:$INSTALL_PATH\"' >> ~/.zshrc" + echo " source ~/.zshrc # To apply changes immediately" + ;; + */fish*) + echo " echo 'set -gx PATH \$PATH $INSTALL_PATH' >> ~/.config/fish/config.fish" + echo " source ~/.config/fish/config.fish # To apply changes immediately" + ;; + *) + echo " Add $INSTALL_PATH to your PATH" + echo " Then restart your terminal or reload your shell configuration" + ;; + esac + fi fi -fi +} -ohai "Setting up shell completions..." -if command -v "$INSTALL_PATH/agentuity" >/dev/null 2>&1; then - COMPLETION_DIR="" - - case "$OS" in - "Darwin") - if [[ -d "/usr/local/etc/bash_completion.d" ]]; then - BASH_COMPLETION_DIR="/usr/local/etc/bash_completion.d" - if [[ -w "$BASH_COMPLETION_DIR" ]]; then - ohai "Generating bash completion script..." - "$INSTALL_PATH/agentuity" completion bash > "$BASH_COMPLETION_DIR/agentuity" - ohai "Bash completion installed to $BASH_COMPLETION_DIR/agentuity" - else - warn "No write permission to $BASH_COMPLETION_DIR. Skipping bash completion installation." +install_completions() { + if command -v "$INSTALL_PATH/agentuity" >/dev/null 2>&1; then + COMPLETION_DIR="" + if is_macos; then + if [[ -d "/usr/local/etc/bash_completion.d" ]]; then + BASH_COMPLETION_DIR="/usr/local/etc/bash_completion.d" + if [[ -w "$BASH_COMPLETION_DIR" ]]; then + ohai "Generating bash completion script..." + "$INSTALL_PATH/agentuity" completion bash > "$BASH_COMPLETION_DIR/agentuity" + ohai "Bash completion installed to $BASH_COMPLETION_DIR/agentuity" + else + warn "No write permission to $BASH_COMPLETION_DIR. Skipping bash completion installation." + fi fi - fi - - if [[ -d "/usr/local/share/zsh/site-functions" ]]; then - ZSH_COMPLETION_DIR="/usr/local/share/zsh/site-functions" - if [[ -w "$ZSH_COMPLETION_DIR" ]]; then - ohai "Generating zsh completion script..." - "$INSTALL_PATH/agentuity" completion zsh > "$ZSH_COMPLETION_DIR/_agentuity" - ohai "Zsh completion installed to $ZSH_COMPLETION_DIR/_agentuity" - else - warn "No write permission to $ZSH_COMPLETION_DIR. Skipping zsh completion installation." + + if [[ -d "/usr/local/share/zsh/site-functions" ]]; then + ZSH_COMPLETION_DIR="/usr/local/share/zsh/site-functions" + if [[ -w "$ZSH_COMPLETION_DIR" ]]; then + ohai "Generating zsh completion script..." + "$INSTALL_PATH/agentuity" completion zsh > "$ZSH_COMPLETION_DIR/_agentuity" + ohai "Zsh completion installed to $ZSH_COMPLETION_DIR/_agentuity" + else + warn "No write permission to $ZSH_COMPLETION_DIR. Skipping zsh completion installation." + fi fi fi - ;; - "Linux") - if [[ -d "/etc/bash_completion.d" ]]; then - BASH_COMPLETION_DIR="/etc/bash_completion.d" - if [[ -w "$BASH_COMPLETION_DIR" ]]; then - ohai "Generating bash completion script..." - "$INSTALL_PATH/agentuity" completion bash > "$BASH_COMPLETION_DIR/agentuity" - ohai "Bash completion installed to $BASH_COMPLETION_DIR/agentuity" - else - warn "No write permission to $BASH_COMPLETION_DIR. Skipping bash completion installation." - ohai "You can manually install bash completion with:" - echo " $INSTALL_PATH/agentuity completion bash > ~/.bash_completion" + + + + if is_linux; then + if [[ -d "/etc/bash_completion.d" ]]; then + BASH_COMPLETION_DIR="/etc/bash_completion.d" + if [[ -w "$BASH_COMPLETION_DIR" ]]; then + ohai "Generating bash completion script..." + "$INSTALL_PATH/agentuity" completion bash > "$BASH_COMPLETION_DIR/agentuity" + ohai "Bash completion installed to $BASH_COMPLETION_DIR/agentuity" + else + warn "No write permission to $BASH_COMPLETION_DIR. Skipping bash completion installation." + ohai "You can manually install bash completion with:" + echo " $INSTALL_PATH/agentuity completion bash > ~/.bash_completion" + fi fi - fi - - if [[ -d "/usr/share/zsh/vendor-completions" ]]; then - ZSH_COMPLETION_DIR="/usr/share/zsh/vendor-completions" - if [[ -w "$ZSH_COMPLETION_DIR" ]]; then - ohai "Generating zsh completion script..." - "$INSTALL_PATH/agentuity" completion zsh > "$ZSH_COMPLETION_DIR/_agentuity" - ohai "Zsh completion installed to $ZSH_COMPLETION_DIR/_agentuity" - else - warn "No write permission to $ZSH_COMPLETION_DIR. Skipping zsh completion installation." - ohai "You can manually install zsh completion with:" - echo " mkdir -p ~/.zsh/completion" - echo " $INSTALL_PATH/agentuity completion zsh > ~/.zsh/completion/_agentuity" - echo " echo 'fpath=(~/.zsh/completion \$fpath)' >> ~/.zshrc" - echo " echo 'autoload -U compinit && compinit' >> ~/.zshrc" + + if [[ -d "/usr/share/zsh/vendor-completions" ]]; then + ZSH_COMPLETION_DIR="/usr/share/zsh/vendor-completions" + if [[ -w "$ZSH_COMPLETION_DIR" ]]; then + ohai "Generating zsh completion script..." + "$INSTALL_PATH/agentuity" completion zsh > "$ZSH_COMPLETION_DIR/_agentuity" + ohai "Zsh completion installed to $ZSH_COMPLETION_DIR/_agentuity" + else + warn "No write permission to $ZSH_COMPLETION_DIR. Skipping zsh completion installation." + ohai "You can manually install zsh completion with:" + echo " mkdir -p ~/.zsh/completion" + echo " $INSTALL_PATH/agentuity completion zsh > ~/.zsh/completion/_agentuity" + echo " echo 'fpath=(~/.zsh/completion \$fpath)' >> ~/.zshrc" + echo " echo 'autoload -U compinit && compinit' >> ~/.zshrc" + fi fi fi - ;; - "Windows") - ohai "You can manually install PowerShell completion with:" - echo " $INSTALL_PATH/agentuity completion powershell > agentuity.ps1" - echo " Move agentuity.ps1 to a directory in your PowerShell module path" - ;; - esac + + if is_windows; then + ohai "You can manually install PowerShell completion with:" + echo " $INSTALL_PATH/agentuity completion powershell > agentuity.ps1" + echo " Move agentuity.ps1 to a directory in your PowerShell module path" + fi + fi +} + +success() { + ohai "Installation complete! Run 'agentuity --help' to get started." + ohai "For more information, visit: $(url "https://agentuity.dev")" - ohai "To manually set up shell completions, run:" - echo " For bash: $INSTALL_PATH/agentuity completion bash > /path/to/bash_completion.d/agentuity" - echo " For zsh: $INSTALL_PATH/agentuity completion zsh > /path/to/zsh/site-functions/_agentuity" - echo " For fish: $INSTALL_PATH/agentuity completion fish > ~/.config/fish/completions/agentuity.fish" -fi + if ! command -v agentuity >/dev/null 2>&1; then + printf "${tty_blue}==>${tty_bold} ${tty_magenta}To apply PATH changes, restart your terminal or run:${tty_reset} source ~/.$(basename $SHELL)rc\n" + fi + + exit 0 +} + + +cleanup() { + rm -rf "$TMP_DIR" +} + +main() { + + VERSION="latest" + TMP_DIR="$(mktemp -d)" + + trap cleanup EXIT + setup_extension_var + setup_install_path_var + + parse_cli_args "$@" + check_install_path + check_version + if is_macos; then + install_mac + fi + check_latest_release + download_release + download_checksums + install_agentuity + set_path + install_completions + success +} -success +main "$@" From 19a31f9f223c54eb7e9b3cef77ffac871def8734 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Tue, 6 May 2025 22:21:09 +0200 Subject: [PATCH 02/16] remove windows support --- install.sh | 200 +++++++++++++++++++++-------------------------------- 1 file changed, 77 insertions(+), 123 deletions(-) diff --git a/install.sh b/install.sh index 1cf2f354..2afeffd2 100755 --- a/install.sh +++ b/install.sh @@ -20,6 +20,35 @@ CAT=${CAT:-cat} ARCH=$(uname -m) OS=$(uname -s) +usage() { +$CAT 1>&2 <${tty_bold} %s${tty_reset}\n" "$1" @@ -45,35 +74,7 @@ check_known_arch() { fi } -is_x86_64() { - check_known_arch - if [[ "$ARCH" == "x86_64" ]] || [[ "$ARCH" == "amd64" ]]; then - return 0 - else - return 1 - fi -} - -is_arm64() { - check_known_arch - if [[ "$ARCH" == "arm64" ]] || [[ "$ARCH" == "aarch64" ]]; then - return 0 - else - return 1 - fi -} - -is_windows() { - check_known_arch - if [[ "$OS" == "Windows" ]]; then - return 0 - else - return 1 - fi -} - is_macos() { - check_known_arch if [[ "$OS" == "Darwin" ]]; then return 0 else @@ -82,7 +83,6 @@ is_macos() { } is_linux() { - check_known_arch if [[ "$OS" == "Linux" ]]; then return 0 else @@ -90,13 +90,17 @@ is_linux() { fi } +abort_if_windows() { + if [[ "$OS" == "Windows" ]]; then + abort "Windows is not supported. Please use WSL or a native Windows installation." + fi +} + setup_extension_var() { if is_macos; then EXTENSION="tar.gz" elif is_linux; then EXTENSION="tar.gz" - elif is_windows; then - EXTENSION="msi" else abort "Unsupported operating system: $OS" fi @@ -123,42 +127,11 @@ setup_install_path_var() { else INSTALL_PATH="/usr/local/bin" fi - elif is_windows; then - INSTALL_PATH="$HOME/bin" else abort "Unsupported operating system: $OS" fi } -usage() { -$CAT 1>&2 </dev/null; then if [[ -w "$HOME/.local/bin" ]]; then @@ -216,19 +188,19 @@ install_mac() { if command -v brew >/dev/null 2>&1 && [[ "$NO_BREW" != "true" ]]; then ohai "Homebrew detected! Installing Agentuity CLI using Homebrew..." - if [[ "$VERSION" != "latest" ]]; then - ohai "Installing Agentuity CLI version $VERSION using Homebrew..." - brew install agentuity/tap/agentuity@${VERSION#v} - else - ohai "Installing latest Agentuity CLI version using Homebrew..." - brew install -q agentuity/tap/agentuity - fi + if [[ "$VERSION" != "latest" ]]; then + ohai "Installing Agentuity CLI version $VERSION using Homebrew..." + brew install agentuity/tap/agentuity@${VERSION#v} + else + ohai "Installing latest Agentuity CLI version using Homebrew..." + brew install -q agentuity/tap/agentuity + fi - if command -v agentuity >/dev/null 2>&1; then - success - else - abort "Homebrew installation failed. Please try again or use manual installation." - fi + if command -v agentuity >/dev/null 2>&1; then + success + else + abort "Homebrew installation failed. Please try again or use manual installation." + fi else ohai "Installing Agentuity CLI using curl..." @@ -239,18 +211,7 @@ install_mac() { download_release() { - if [[ is_windows ]]; then - if is_x86_64; then - DOWNLOAD_FILENAME="agentuity-x64.msi" - elif is_arm64; then - DOWNLOAD_FILENAME="agentuity-arm64.msi" - else - DOWNLOAD_FILENAME="agentuity-x86.msi" - fi - else - DOWNLOAD_FILENAME="agentuity_${OS}_${ARCH}.${EXTENSION}" - fi - + DOWNLOAD_FILENAME="agentuity_${OS}_${ARCH}.${EXTENSION}" DOWNLOAD_URL="https://github.com/agentuity/cli/releases/download/v${VERSION#v}/${DOWNLOAD_FILENAME}" ohai "Downloading Agentuity CLI v${VERSION} for ${OS}/${ARCH}..." @@ -259,35 +220,33 @@ download_release() { download_checksums() { CHECKSUMS_URL="https://github.com/agentuity/cli/releases/download/v${VERSION#v}/checksums.txt" - if is_windows; then - ohai "Downloading checksums for verification..." - if ! curl -L --silent "$CHECKSUMS_URL" -o "$TMP_DIR/checksums.txt"; then - warn "Failed to download checksums file. Skipping verification." + ohai "Downloading checksums for verification..." + if ! curl -L --silent "$CHECKSUMS_URL" -o "$TMP_DIR/checksums.txt"; then + warn "Failed to download checksums file. Skipping verification." + else + ohai "Verifying checksum..." + if command -v sha256sum >/dev/null 2>&1; then + CHECKSUM_TOOL="sha256sum" + elif command -v shasum >/dev/null 2>&1; then + CHECKSUM_TOOL="shasum -a 256" else - ohai "Verifying checksum..." - if command -v sha256sum >/dev/null 2>&1; then - CHECKSUM_TOOL="sha256sum" - elif command -v shasum >/dev/null 2>&1; then - CHECKSUM_TOOL="shasum -a 256" - else - warn "Neither sha256sum nor shasum found. Skipping checksum verification." - CHECKSUM_TOOL="" - fi + warn "Neither sha256sum nor shasum found. Skipping checksum verification." + CHECKSUM_TOOL="" + fi + + if [[ -n "$CHECKSUM_TOOL" ]]; then + cd "$TMP_DIR" + COMPUTED_CHECKSUM=$($CHECKSUM_TOOL "$DOWNLOAD_FILENAME" | cut -d ' ' -f 1) + EXPECTED_CHECKSUM=$(grep "$DOWNLOAD_FILENAME" checksums.txt | cut -d ' ' -f 1) - if [[ -n "$CHECKSUM_TOOL" ]]; then - cd "$TMP_DIR" - COMPUTED_CHECKSUM=$($CHECKSUM_TOOL "$DOWNLOAD_FILENAME" | cut -d ' ' -f 1) - EXPECTED_CHECKSUM=$(grep "$DOWNLOAD_FILENAME" checksums.txt | cut -d ' ' -f 1) - - if [[ -z "$EXPECTED_CHECKSUM" ]]; then - warn "Checksum for $DOWNLOAD_FILENAME not found in checksums.txt. Skipping verification." - elif [[ "$COMPUTED_CHECKSUM" != "$EXPECTED_CHECKSUM" ]]; then - abort "Checksum verification failed. Expected: $EXPECTED_CHECKSUM, Got: $COMPUTED_CHECKSUM" - else - ohai "Checksum verification passed!" - fi - cd - > /dev/null + if [[ -z "$EXPECTED_CHECKSUM" ]]; then + warn "Checksum for $DOWNLOAD_FILENAME not found in checksums.txt. Skipping verification." + elif [[ "$COMPUTED_CHECKSUM" != "$EXPECTED_CHECKSUM" ]]; then + abort "Checksum verification failed. Expected: $EXPECTED_CHECKSUM, Got: $COMPUTED_CHECKSUM" + else + ohai "Checksum verification passed!" fi + cd - > /dev/null fi fi } @@ -295,7 +254,7 @@ download_checksums() { install_agentuity() { ohai "Installing to $INSTALL_PATH..." if [[ -f "$TMP_DIR/agentuity" ]]; then - if [[ is_macos ]] && [[ -f "$INSTALL_PATH/agentuity" ]]; then + if is_macos && [[ -f "$INSTALL_PATH/agentuity" ]]; then ohai "Removing existing binary to avoid macOS quarantine issues..." rm -f "$INSTALL_PATH/agentuity" || abort "Failed to remove existing binary from $INSTALL_PATH" fi @@ -392,8 +351,6 @@ install_completions() { fi fi - - if is_linux; then if [[ -d "/etc/bash_completion.d" ]]; then BASH_COMPLETION_DIR="/etc/bash_completion.d" @@ -424,12 +381,6 @@ install_completions() { fi fi fi - - if is_windows; then - ohai "You can manually install PowerShell completion with:" - echo " $INSTALL_PATH/agentuity completion powershell > agentuity.ps1" - echo " Move agentuity.ps1 to a directory in your PowerShell module path" - fi fi } @@ -451,6 +402,9 @@ cleanup() { main() { + abort_if_windows + check_known_arch + VERSION="latest" TMP_DIR="$(mktemp -d)" From a266d74e30bab9c92842ffe8ae5c4e22fec919fa Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Tue, 6 May 2025 22:32:11 +0200 Subject: [PATCH 03/16] oops --- install.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/install.sh b/install.sh index 2afeffd2..cf5bfde5 100755 --- a/install.sh +++ b/install.sh @@ -143,8 +143,7 @@ check_install_path() { fi if [[ "$INSTALL_PATH" == "/usr/local/bin" ]]; then - - if [[ -d "$HOME/.local/bin" ]] || mkdir -p "$HOME/.local/bin" 2>/dev/null; then + if [[ -d "$HOME/.local/bin" ]] || mkdir -p "$HOME/.local/bin" 2>/dev/null; then if [[ -w "$HOME/.local/bin" ]]; then ohai "Using $HOME/.local/bin instead" INSTALL_PATH="$HOME/.local/bin" @@ -162,8 +161,6 @@ check_install_path() { else abort "Could not find or create a writable installation directory. Try running with sudo or specify a different directory with --dir." fi - else - abort "No write permission to $INSTALL_PATH. Try running with sudo or specify a different directory with --dir." fi } From 91f67afedd21dd816ea9444c83f989b62dfed6cf Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Tue, 6 May 2025 22:48:33 +0200 Subject: [PATCH 04/16] Extract and get the correct architecture --- install.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/install.sh b/install.sh index cf5bfde5..1ea15935 100755 --- a/install.sh +++ b/install.sh @@ -72,6 +72,12 @@ check_known_arch() { if [[ "$ARCH" != "x86_64" ]] && [[ "$ARCH" != "amd64" ]] && [[ "$ARCH" != "arm64" ]] && [[ "$ARCH" != "aarch64" ]]; then abort "Unsupported architecture: $ARCH" fi + + if [[ "$ARCH" == "x86_64" || "$ARCH" == "amd64" ]]; then + ARCH="x86_64" + else + ARCH="arm64" + fi } is_macos() { @@ -248,6 +254,19 @@ download_checksums() { fi } +extract_release() { + if [[ "$EXTENSION" == "tar.gz" ]]; then + ohai "Extracting..." + tar -xzf "$TMP_DIR/$DOWNLOAD_FILENAME" -C "$TMP_DIR" || abort "Failed to extract archive" + elif [[ "$EXTENSION" == "zip" ]]; then + ohai "Extracting..." + unzip -q "$TMP_DIR/$DOWNLOAD_FILENAME" -d "$TMP_DIR" || abort "Failed to extract archive" + else + abort "Unknown archive format: $EXTENSION" + fi +} + + install_agentuity() { ohai "Installing to $INSTALL_PATH..." if [[ -f "$TMP_DIR/agentuity" ]]; then @@ -418,6 +437,7 @@ main() { check_latest_release download_release download_checksums + extract_release install_agentuity set_path install_completions From 9f1f16a87b3f97a2ad37545d128aea79cdfbbcea Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Tue, 6 May 2025 22:50:25 +0200 Subject: [PATCH 05/16] Remove windows from workflow --- .github/workflows/go.yml | 45 ---------------------------------------- 1 file changed, 45 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index a1b1ce96..f80bfae3 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -94,51 +94,6 @@ jobs: echo "macOS double installation test passed - segfault fix verified" shell: bash - - name: Test Bash Install Script (Windows) - if: matrix.os == 'windows-latest' - run: | - # Windows test - simplified to avoid bash usage - Write-Host "Testing bash install script on Windows..." - - # Set up environment for testing - $env:NONINTERACTIVE = "true" - $env:OS = "Windows" - $env:ARCH = "x86_64" - - # Make script executable using PowerShell - if (Test-Path "install.sh") { - Write-Host "Found install.sh script" - } else { - Write-Host "install.sh not found" - exit 1 - } - - # Test with default options (latest version) - Write-Host "Testing install script with default options..." - & sh -c "./install.sh -d '$env:TEMP/agentuity-test-download'" - - # Verify MSI was downloaded - if (Test-Path "$env:USERPROFILE/agentuity-x64.msi") { - Write-Host "MSI download verification successful" - - # Test with specific version - Write-Host "Testing install script with specific version..." - & sh -c "./install.sh -d '$env:TEMP/agentuity-test-version-download' -v 0.0.74" - - # Verify version-specific MSI was downloaded - if (Test-Path "$env:USERPROFILE/agentuity-x64.msi") { - Write-Host "Version-specific MSI download verification successful" - } else { - Write-Host "Version-specific MSI download verification failed" - exit 1 - } - } else { - Write-Host "MSI download verification failed" - exit 1 - } - shell: pwsh - - - name: Test PowerShell Install Script (Windows) if: matrix.os == 'windows-latest' env: GITHUB_TOKEN: ${{ github.token }} From 776e80e9fd0b6b8f0b60b694d39d6f537ca849f2 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Wed, 7 May 2025 21:35:38 +0200 Subject: [PATCH 06/16] Final changes --- Makefile | 7 +- README.md | 19 +- install.ps1 | 1282 --------------------------- install.sh | 149 +++- install_test/Dockerfile | 20 + install_test/docker-test-install.sh | 37 + installer.wsx | 88 -- 7 files changed, 184 insertions(+), 1418 deletions(-) delete mode 100644 install.ps1 create mode 100644 install_test/Dockerfile create mode 100644 install_test/docker-test-install.sh delete mode 100644 installer.wsx diff --git a/Makefile b/Makefile index 3dbf54e4..504656e7 100644 --- a/Makefile +++ b/Makefile @@ -8,4 +8,9 @@ fmt: generate: @echo "Running go generate..." - @go generate ./... \ No newline at end of file + @go generate ./... + +test_install_linux: + @docker build -t agentuity-test-install-linux -f install_test/Dockerfile . + @docker run -it agentuity-test-install-linux + diff --git a/README.md b/README.md index cb741a7b..4e0cc231 100644 --- a/README.md +++ b/README.md @@ -15,28 +15,33 @@ The command line tools for the Agentuity Agent Cloud Platform. These tools are ## Installation -You can install the CLI using the install script: +You can install the CLI using the install script (Linux, macOS, or WSL): ```bash curl -fsSL https://agentuity.sh/install.sh | bash ``` -If you are on a Mac, you can install the CLI using Homebrew: +If you are on a Mac, you can install the CLI using Homebrew (by default, the install script will use Homebrew if it is installed and not disabled): ```bash - brew install agentuity/tap/agentuity +brew install agentuity/tap/agentuity ``` -Note: The install script will automatically use Homebrew if it is available. - -For Windows, you can install the CLI using the install script: +You can force the install script to use the direct binary install (not Homebrew) with: ```bash -irm https://agentuity.sh/install.ps1 | iex +curl -fsSL https://agentuity.sh/install.sh | bash -s -- --no-brew ``` +**Windows:** Native Windows installation is no longer supported. Please use [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/) and run the install script from your WSL terminal. + For other platforms, please download the binary from the [Releases](https://github.com/agentuity/cli/releases) page. +**Supported platforms:** +- Linux +- macOS +- Windows (via WSL only) + ## Upgrade If you have already installed the CLI, you can upgrade to the latest version using the upgrade command: diff --git a/install.ps1 b/install.ps1 deleted file mode 100644 index cce8e7ed..00000000 --- a/install.ps1 +++ /dev/null @@ -1,1282 +0,0 @@ -<# -.SYNOPSIS - Installer script for Agentuity CLI on Windows. -.DESCRIPTION - Downloads and installs the latest version of the Agentuity CLI for Windows. - This script can be invoked directly with: - iwr https://agentuity.sh/install.ps1 -useb | iex -.PARAMETER Version - Specific version to install. If not specified, installs the latest version. -.PARAMETER InstallDir - Custom installation directory. If not specified, uses Program Files. -.PARAMETER NoPrompt - Skip confirmation prompts. Useful for automated installations. -.EXAMPLE - .\install.ps1 - Installs the latest version of Agentuity CLI. -.EXAMPLE - .\install.ps1 -Version 1.2.3 - Installs version 1.2.3 of Agentuity CLI. -.EXAMPLE - .\install.ps1 -InstallDir "C:\Tools" - Installs the latest version of Agentuity CLI to C:\Tools. -.NOTES - Author: Agentuity, Inc. - Website: https://agentuity.com -#> - -[CmdletBinding()] -param ( - [string]$Version = "latest", - [string]$InstallDir = "", - [switch]$NoPrompt = $false -) - -# Script version -$ScriptVersion = "1.0.0" - -#region Helper Functions - -function Write-ColorOutput { - param ( - [Parameter(Mandatory = $true)] - [string]$Message, - - [Parameter(Mandatory = $false)] - [string]$ForegroundColor = "White" - ) - - $originalColor = $host.UI.RawUI.ForegroundColor - $host.UI.RawUI.ForegroundColor = $ForegroundColor - Write-Output $Message - $host.UI.RawUI.ForegroundColor = $originalColor -} - -function Write-Step { - param ( - [Parameter(Mandatory = $true)] - [string]$Message - ) - - Write-ColorOutput "==> $Message" -ForegroundColor Cyan -} - -function Write-Success { - param ( - [Parameter(Mandatory = $true)] - [string]$Message - ) - - Write-ColorOutput $Message -ForegroundColor Green -} - -function Write-Warning { - param ( - [Parameter(Mandatory = $true)] - [string]$Message - ) - - Write-ColorOutput "Warning: $Message" -ForegroundColor Yellow -} - -function Write-Error { - param ( - [Parameter(Mandatory = $true)] - [string]$Message, - - [Parameter(Mandatory = $false)] - [switch]$Exit = $false - ) - - Write-ColorOutput "Error: $Message" -ForegroundColor Red - - if ($Exit) { - exit 1 - } -} - -function Write-Url { - param ( - [Parameter(Mandatory = $true)] - [string]$Url - ) - - Write-ColorOutput $Url -ForegroundColor Blue -} - -function Test-Administrator { - $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) - return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) -} - -function Request-AdminPrivileges { - param ( - [Parameter(Mandatory = $true)] - [string]$ScriptPath - ) - - Write-Step "Requesting administrator privileges..." - - $arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$ScriptPath`"" - if ($Version -ne "latest") { - $arguments += " -Version `"$Version`"" - } - if ($InstallDir -ne "") { - $arguments += " -InstallDir `"$InstallDir`"" - } - if ($NoPrompt) { - $arguments += " -NoPrompt" - } - - try { - Start-Process -FilePath PowerShell.exe -ArgumentList $arguments -Verb RunAs -Wait - exit 0 - } - catch { - Write-Error "Failed to restart with administrator privileges: $_" -Exit - } -} - -function Get-UserConfirmation { - param ( - [Parameter(Mandatory = $true)] - [string]$Message, - - [Parameter(Mandatory = $false)] - [bool]$DefaultToYes = $true - ) - - if ($NoPrompt) { - return $true - } - - $choices = if ($DefaultToYes) { "&Yes (default)|&No" } else { "&Yes|&No (default)" } - $defaultChoice = if ($DefaultToYes) { 0 } else { 1 } - - $decision = $Host.UI.PromptForChoice("", $Message, $choices.Split('|'), $defaultChoice) - - return $decision -eq 0 -} - -function Get-LatestReleaseVersion { - # Use Out-Null to suppress debug output from being captured in the return value - Write-Step "Fetching latest release information..." | Out-Null - - try { - # Set TLS 1.2 for compatibility with GitHub - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - - $userAgent = "AgentuityInstaller/PowerShell/$ScriptVersion ($env:OS; $env:PROCESSOR_ARCHITECTURE)" - $headers = @{ - "Accept" = "application/vnd.github+json" - "X-GitHub-Api-Version" = "2022-11-28" - "User-Agent" = $userAgent - } - - # Add GitHub token if available (for CI environments) - if ($env:GITHUB_TOKEN) { - Write-Step "Using authenticated GitHub API request" | Out-Null - $headers["Authorization"] = "token $env:GITHUB_TOKEN" - } - - # For CI testing, if a specific version is set in the environment, use it - if ($env:AGENTUITY_TEST_VERSION) { - Write-Step "Using test version from environment: $env:AGENTUITY_TEST_VERSION" | Out-Null - return $env:AGENTUITY_TEST_VERSION - } - - $releaseUrl = "https://agentuity.sh/release/cli" - $response = Invoke-RestMethod -Uri $releaseUrl -Headers $headers -Method Get - - if ($null -eq $response.tag_name) { - Write-Error "Failed to parse version from GitHub API response" -Exit - } - - return $response.tag_name - } - catch { - # In CI environment, if API call fails, use a fallback version for testing - if ($env:CI -eq "true") { - $fallbackVersion = "0.0.74" - Write-Warning "GitHub API request failed in CI environment. Using fallback version: $fallbackVersion" | Out-Null - return $fallbackVersion - } - - Write-Error "Failed to fetch latest release information: $_" -Exit - } -} - -function Get-Architecture { - $arch = $env:PROCESSOR_ARCHITECTURE - - if ($arch -eq "AMD64") { - return "x64" - } - elseif ($arch -eq "ARM64") { - return "arm64" - } - elseif ($arch -eq "X86") { - return "x86" - } - else { - Write-Warning "Unknown architecture: $arch. Defaulting to x86." - return "x86" - } -} - -function Get-DefaultInstallDir { - if ([string]::IsNullOrEmpty($InstallDir)) { - if (Test-Administrator) { - $programFilesX86Path = [System.IO.Path]::Combine(${env:ProgramFiles(x86)}) - if (Test-Path -Path $programFilesX86Path) { - return [System.IO.Path]::Combine(${env:ProgramFiles(x86)}, "Agentuity") - } - else { - # Return the standard Program Files path by default - return [System.IO.Path]::Combine($env:ProgramFiles, "Agentuity") - } - } - else { - return [System.IO.Path]::Combine($env:LOCALAPPDATA, "Agentuity") - } - } - else { - return $InstallDir - } -} - -function Test-PathInEnvironment { - param ( - [Parameter(Mandatory = $true)] - [string]$PathToCheck - ) - - $envPaths = $env:PATH -split ';' - return $envPaths -contains $PathToCheck -} - -function Add-ToPath { - param ( - [Parameter(Mandatory = $true)] - [string]$PathToAdd - ) - - if (Test-PathInEnvironment -PathToCheck $PathToAdd) { - Write-Step "$PathToAdd is already in PATH" - return - } - - Write-Step "Adding $PathToAdd to PATH environment variable..." - - try { - if (Test-Administrator) { - # System-wide PATH update (requires admin) - $systemPath = [Environment]::GetEnvironmentVariable("PATH", [EnvironmentVariableTarget]::Machine) - $newSystemPath = "$systemPath;$PathToAdd" - [Environment]::SetEnvironmentVariable("PATH", $newSystemPath, [EnvironmentVariableTarget]::Machine) - Write-Success "Added to system PATH" - } - else { - # User PATH update (doesn't require admin) - $userPath = [Environment]::GetEnvironmentVariable("PATH", [EnvironmentVariableTarget]::User) - $newUserPath = "$userPath;$PathToAdd" - [Environment]::SetEnvironmentVariable("PATH", $newUserPath, [EnvironmentVariableTarget]::User) - Write-Success "Added to user PATH" - } - - # Update current session PATH - $env:PATH = "$env:PATH;$PathToAdd" - - # Force PowerShell to refresh its command discovery - # Remove any existing function with this name first - if (Get-Command "agentuity" -ErrorAction SilentlyContinue) { - if ((Get-Command "agentuity").CommandType -eq "Function") { - Remove-Item -Path "Function:\agentuity" -ErrorAction SilentlyContinue - } - } - - # Create a temporary function that will redirect to the actual executable - $scriptBlock = { - param($argumentList) - & (Join-Path -Path $PathToAdd -ChildPath "agentuity.exe") @argumentList - } - - # Register the function in the current session - Set-Item -Path "Function:\agentuity" -Value $scriptBlock -Force - - Write-Success "Command 'agentuity' is now available in the current session" - } - catch { - Write-Error "Failed to update PATH: $_" - Write-Warning "You may need to manually add $PathToAdd to your PATH environment variable." - } -} - -function Load-InCurrentSession { - param ( - [Parameter(Mandatory = $true)] - [string]$ExePath - ) - - Write-Step "Loading Agentuity CLI in current session..." - - try { - # Verify the executable exists - if (-not (Test-Path -Path $ExePath)) { - Write-Warning "Executable not found at $ExePath" - return - } - - # Test that the executable is actually accessible - try { - $testOutput = & $ExePath version 2>&1 - if ($LASTEXITCODE -ne 0) { - Write-Warning "Executable verification failed with exit code $LASTEXITCODE" - return - } - Write-Success "Verified executable is accessible: $testOutput" - } - catch { - Write-Warning "Failed to execute $ExePath" - Write-Warning "Error: $($_.Exception.Message)" - return - } - - # Create a temporary function that will redirect to the actual executable - $scriptBlock = { - param($argumentList) - & $ExePath @argumentList - } - - # Register the function in the current session - Set-Item -Path "Function:\agentuity" -Value $scriptBlock -Force - - Write-Success "Agentuity CLI loaded in current session" - } - catch { - Write-Warning "Failed to load Agentuity CLI in current session" - Write-Warning "Error: $($_.Exception.Message)" - } -} - -function Get-FileHash256 { - param ( - [Parameter(Mandatory = $true)] - [string]$FilePath - ) - - try { - $hash = Get-FileHash -Path $FilePath -Algorithm SHA256 - return $hash.Hash.ToLower() - } - catch { - Write-Warning "Failed to compute file hash: $_" - return $null - } -} - -function Install-MSI { - param ( - [Parameter(Mandatory = $true)] - [string]$MsiPath, - - [Parameter(Mandatory = $false)] - [string]$LogPath = "$env:TEMP\agentuity_install.log", - - [Parameter(Mandatory = $false)] - [string]$InstallDir = "" - ) - - Write-Step "Installing Agentuity CLI..." - - # For CI environments, extract MSI directly instead of installing - if ($env:CI -eq "true") { - Write-Step "CI environment detected, extracting MSI contents directly..." - - # Create a temporary directory for extraction - $extractDir = if ([string]::IsNullOrEmpty($InstallDir)) { - Join-Path -Path $env:TEMP -ChildPath "agentuity_extract_$(Get-Random)" - } else { - $InstallDir - } - - if (-not (Test-Path -Path $extractDir)) { - New-Item -Path $extractDir -ItemType Directory -Force | Out-Null - } - - Write-Step "Extracting MSI to $extractDir" - - try { - # Use lessmsi to extract MSI contents (if available) - $lessmsiPath = "C:\ProgramData\chocolatey\bin\lessmsi.exe" - if (Test-Path $lessmsiPath) { - Write-Step "Using lessmsi to extract MSI contents" - $process = Start-Process -FilePath $lessmsiPath -ArgumentList "x `"$MsiPath`" `"$extractDir`"" -Wait -PassThru - - if ($process.ExitCode -ne 0) { - Write-Warning "lessmsi extraction failed with exit code $($process.ExitCode), falling back to direct copy" - } - } - - # If lessmsi failed or isn't available, copy the executable directly - if (-not (Test-Path -Path (Join-Path -Path $extractDir -ChildPath "agentuity.exe"))) { - Write-Step "Copying executable directly to installation directory" - - # Try to find the executable in the MSI - $tempDir = Join-Path -Path $env:TEMP -ChildPath "agentuity_temp_$(Get-Random)" - New-Item -Path $tempDir -ItemType Directory -Force | Out-Null - - # Use msiexec to extract files to temp directory - $extractArgs = "/a `"$MsiPath`" /qn TARGETDIR=`"$tempDir`"" - Write-Step "Extracting MSI with command: msiexec.exe $extractArgs" - $extractProcess = Start-Process -FilePath "msiexec.exe" -ArgumentList $extractArgs -Wait -PassThru - - # Search for the executable in the extracted files - $exeFiles = Get-ChildItem -Path $tempDir -Filter "agentuity.exe" -Recurse - if ($exeFiles.Count -gt 0) { - Write-Step "Found executable at $($exeFiles[0].FullName)" - Copy-Item -Path $exeFiles[0].FullName -Destination $extractDir - } else { - Write-Warning "Could not find agentuity.exe in extracted MSI" - - # Create a dummy executable for testing purposes - Write-Step "Creating dummy executable for CI testing" - $dummyExePath = Join-Path -Path $extractDir -ChildPath "agentuity.exe" - Set-Content -Path $dummyExePath -Value "echo 0.0.74" - - # Make it executable - $acl = Get-Acl -Path $dummyExePath - $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("Everyone", "FullControl", "Allow") - $acl.SetAccessRule($accessRule) - Set-Acl -Path $dummyExePath -AclObject $acl - } - - # Clean up temp directory - Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue - } - - return $true - } - catch { - Write-Error "Failed to extract MSI: $_" - return $false - } - } - else { - # Normal MSI installation for non-CI environments - try { - # For non-admin users, extract MSI directly to LOCALAPPDATA instead of standard installation - if (-not (Test-Administrator)) { - $localAppDataPath = [System.IO.Path]::Combine($env:LOCALAPPDATA, "Agentuity") - Write-Step "Non-admin user detected, extracting MSI directly to $localAppDataPath" - - # Create the directory if it doesn't exist - if (-not (Test-Path -Path $localAppDataPath)) { - Write-Step "Creating installation directory: $localAppDataPath" - New-Item -Path $localAppDataPath -ItemType Directory -Force | Out-Null - } - - # Use msiexec to extract files to LOCALAPPDATA - $extractArgs = "/a `"$MsiPath`" /qn TARGETDIR=`"$localAppDataPath`"" - Write-Step "Extracting MSI with command: msiexec.exe $extractArgs" - $extractProcess = Start-Process -FilePath "msiexec.exe" -ArgumentList $extractArgs -Wait -PassThru - - if ($extractProcess.ExitCode -ne 0) { - Write-Error "Extraction failed with exit code $($extractProcess.ExitCode). Check the log for details." - return $false - } - - # Check for common nested directory structures - $nestedDirs = @( - (Join-Path -Path $localAppDataPath -ChildPath "Agentuity"), - (Join-Path -Path $localAppDataPath -ChildPath "PFiles\Agentuity") - ) - - foreach ($nestedDir in $nestedDirs) { - if (Test-Path -Path $nestedDir) { - Write-Step "Found nested directory at $nestedDir, moving files to correct location" - - # Check if the executable exists in this nested directory - $nestedExePath = Join-Path -Path $nestedDir -ChildPath "agentuity.exe" - if (Test-Path -Path $nestedExePath) { - Write-Step "Found executable in nested directory, copying to root installation directory" - try { - Copy-Item -Path $nestedExePath -Destination (Join-Path -Path $localAppDataPath -ChildPath "agentuity.exe") -Force -ErrorAction SilentlyContinue - Write-Success "Successfully copied executable from nested directory" - } catch { - Write-Warning "Failed to copy executable from nested directory: $_" - } - } - - # Move all files from nested directory to parent - Get-ChildItem -Path $nestedDir -Recurse -ErrorAction SilentlyContinue | ForEach-Object { - try { - $relativePath = $_.FullName.Substring($nestedDir.Length) - $targetPath = Join-Path -Path $localAppDataPath -ChildPath $relativePath - $targetDir = Split-Path -Parent $targetPath - - # Create target directory if it doesn't exist - if (-not (Test-Path -Path $targetDir)) { - New-Item -Path $targetDir -ItemType Directory -Force -ErrorAction SilentlyContinue | Out-Null - } - - # Copy the item instead of moving to avoid permission issues - Copy-Item -Path $_.FullName -Destination $targetPath -Force -ErrorAction SilentlyContinue - } catch { - Write-Warning "Failed to copy item from nested directory: $_" - } - } - } - } - - # Also check for PFiles directory without Agentuity subdirectory - $pfilesDir = Join-Path -Path $localAppDataPath -ChildPath "PFiles" - if (Test-Path -Path $pfilesDir) { - Write-Step "Found PFiles directory, checking for executable" - $exeFiles = Get-ChildItem -Path $pfilesDir -Recurse -Filter "agentuity.exe" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName - - if ($exeFiles.Count -gt 0) { - Write-Step "Found executable in PFiles directory, copying to root installation directory" - try { - Copy-Item -Path $exeFiles[0] -Destination (Join-Path -Path $localAppDataPath -ChildPath "agentuity.exe") -Force -ErrorAction SilentlyContinue - Write-Success "Successfully copied executable from PFiles directory" - } catch { - Write-Warning "Failed to copy executable from PFiles directory: $_" - } - } - } - - # If no executable found, try to extract files directly - $exePath = Join-Path -Path $localAppDataPath -ChildPath "agentuity.exe" - if (-not (Test-Path -Path $exePath)) { - Write-Step "Executable not found after extraction, trying direct file copy" - - # Create a temporary directory to extract MSI contents - $tempExtractDir = Join-Path -Path $env:TEMP -ChildPath "AgentuityExtract" - if (Test-Path -Path $tempExtractDir) { - Remove-Item -Path $tempExtractDir -Recurse -Force - } - New-Item -Path $tempExtractDir -ItemType Directory -Force | Out-Null - - # Extract MSI to temp directory - $tempExtractArgs = "/a `"$MsiPath`" /qn TARGETDIR=`"$tempExtractDir`"" - Start-Process -FilePath "msiexec.exe" -ArgumentList $tempExtractArgs -Wait -PassThru | Out-Null - - # Search for the executable in the extracted files - $foundExes = Get-ChildItem -Path $tempExtractDir -Recurse -Filter "agentuity.exe" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName - - if ($foundExes.Count -gt 0) { - Write-Step "Found executable in extracted files, copying to installation directory" - $foundExePath = $foundExes[0] - $foundExeDir = Split-Path -Parent $foundExePath - - # Copy all files from the directory containing the executable - # Use error handling to skip files that can't be accessed due to permission issues - Get-ChildItem -Path $foundExeDir -Recurse -ErrorAction SilentlyContinue | ForEach-Object { - try { - $targetPath = $_.FullName.Replace($foundExeDir, $localAppDataPath) - $targetDir = Split-Path -Parent $targetPath - - # Create target directory if it doesn't exist - if (-not (Test-Path -Path $targetDir)) { - New-Item -Path $targetDir -ItemType Directory -Force -ErrorAction SilentlyContinue | Out-Null - } - - # Copy the item, skip if access denied - Copy-Item -Path $_.FullName -Destination $targetPath -Force -ErrorAction SilentlyContinue - } catch { - Write-Warning "Skipping file due to access error: $($_.FullName)" - } - } - - # As a fallback, try to copy just the executable directly - try { - Copy-Item -Path $foundExePath -Destination (Join-Path -Path $localAppDataPath -ChildPath "agentuity.exe") -Force -ErrorAction SilentlyContinue - Write-Step "Copied executable directly to installation directory" - } catch { - Write-Warning "Failed to copy executable directly: $_" - } - } - - # Clean up temp directory - Remove-Item -Path $tempExtractDir -Recurse -Force -ErrorAction SilentlyContinue - } - - # Final fallback: If executable still not found, download it directly - if (-not (Test-Path -Path $exePath)) { - Write-Step "Executable still not found, attempting direct download as final fallback" - - try { - # Set TLS 1.2 for compatibility with GitHub - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - - # Get the version from the MSI filename or use latest - $versionFromMsi = if ($MsiPath -match "agentuity_([0-9]+\.[0-9]+\.[0-9]+)_") { - $matches[1] - } else { - "latest" - } - - # Construct the download URL for the executable - $arch = Get-Architecture - $downloadUrl = "https://github.com/agentuity/cli/releases/download/v$versionFromMsi/agentuity_${versionFromMsi}_windows_$arch.exe" - - Write-Step "Downloading executable directly from: $downloadUrl" - - # Create a WebClient to download the file - $webClient = New-Object System.Net.WebClient - $webClient.Headers.Add("User-Agent", "AgentuityInstaller/PowerShell/$ScriptVersion") - - # Download the file directly to the installation directory - $webClient.DownloadFile($downloadUrl, $exePath) - - if (Test-Path -Path $exePath) { - Write-Success "Successfully downloaded executable directly to $exePath" - } else { - Write-Warning "Failed to download executable to $exePath" - } - } catch { - Write-Warning "Failed to download executable directly: $_" - - # Try alternative download method as last resort - try { - Write-Step "Trying alternative download method" - - # Try to get the latest release info - $releaseUrl = "https://agentuity.sh/release/cli" - $response = Invoke-RestMethod -Uri $releaseUrl -Method Get -ErrorAction SilentlyContinue - - if ($null -ne $response -and $null -ne $response.assets) { - # Find the correct asset for Windows and the current architecture - $arch = Get-Architecture - $asset = $response.assets | Where-Object { $_.name -like "*windows*$arch*.exe" } | Select-Object -First 1 - - if ($null -ne $asset -and $null -ne $asset.browser_download_url) { - Write-Step "Found executable download URL: $($asset.browser_download_url)" - - # Download the file - Invoke-WebRequest -Uri $asset.browser_download_url -OutFile $exePath -ErrorAction SilentlyContinue - - if (Test-Path -Path $exePath) { - Write-Success "Successfully downloaded executable using alternative method" - } - } - } - } catch { - Write-Warning "Alternative download method also failed: $_" - } - } - } - - # Add registry entries to allow uninstallation without admin privileges - Write-Step "Setting registry keys for non-admin uninstallation" - try { - # Create registry key for the application - $regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\Agentuity" - if (-not (Test-Path -Path $regPath)) { - New-Item -Path $regPath -Force | Out-Null - } - - # Try to extract product code from MSI - $productCode = "" - try { - # Create a temporary directory to extract MSI property - $tempDir = Join-Path -Path $env:TEMP -ChildPath "AgentuityMsiInfo" - if (-not (Test-Path -Path $tempDir)) { - New-Item -Path $tempDir -ItemType Directory -Force | Out-Null - } - - # Use Windows Installer automation to get product code - $windowsInstaller = New-Object -ComObject WindowsInstaller.Installer - $database = $windowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $windowsInstaller, @($MsiPath, 0)) - - $query = "SELECT `Value` FROM `Property` WHERE `Property` = 'ProductCode'" - $view = $database.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $database, @($query)) - $view.GetType().InvokeMember("Execute", "InvokeMethod", $null, $view, $null) - - $record = $view.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $view, $null) - if ($record -ne $null) { - $productCode = $record.GetType().InvokeMember("StringData", "GetProperty", $null, $record, 1) - } - - # Clean up - $view.GetType().InvokeMember("Close", "InvokeMethod", $null, $view, $null) - [System.Runtime.InteropServices.Marshal]::ReleaseComObject($database) | Out-Null - [System.Runtime.InteropServices.Marshal]::ReleaseComObject($windowsInstaller) | Out-Null - - Write-Step "Extracted product code: $productCode" - } catch { - Write-Warning "Failed to extract product code from MSI: $_" - } - - # Create an uninstaller script in the installation directory - $uninstallerPath = Join-Path -Path $localAppDataPath -ChildPath "uninstall.cmd" - $uninstallerContent = @" -@echo off -echo Uninstalling Agentuity CLI... - -REM Remove the executable and other files -if exist "$($localAppDataPath -replace '\\', '\\')\agentuity.exe" ( - echo Removing executable files... - del /f /q "$($localAppDataPath -replace '\\', '\\')\agentuity.exe" >nul 2>&1 -) - -REM Remove the installation directory -echo Removing installation directory... -rd /s /q "$($localAppDataPath -replace '\\', '\\')" >nul 2>&1 - -REM Remove from PATH -echo Updating PATH environment variable... -for /f "tokens=2*" %%a in ('reg query HKCU\Environment /v PATH 2^>nul ^| find "PATH"') do ( - setx PATH "%%b" | findstr /v "$($localAppDataPath -replace '\\', '\\')" >nul 2>&1 -) - -REM Remove registry entries -echo Removing registry entries... -reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\Agentuity" /f >nul 2>&1 - -echo Agentuity CLI has been uninstalled successfully. -pause -"@ - - # Write the uninstaller script - try { - Set-Content -Path $uninstallerPath -Value $uninstallerContent -Force - Write-Step "Created uninstaller script at $uninstallerPath" - } catch { - Write-Warning "Failed to create uninstaller script: $_" - } - - # Create a direct uninstall command that uses our script - $uninstallCmd = "cmd.exe /c start `"Agentuity CLI Uninstaller`" /wait `"$uninstallerPath`"" - - # Set required properties for Add/Remove Programs - New-ItemProperty -Path $regPath -Name "DisplayName" -Value "Agentuity CLI" -PropertyType String -Force | Out-Null - New-ItemProperty -Path $regPath -Name "DisplayVersion" -Value (Get-LatestReleaseVersion) -PropertyType String -Force | Out-Null - New-ItemProperty -Path $regPath -Name "UninstallString" -Value $uninstallCmd -PropertyType String -Force | Out-Null - # Don't set QuietUninstallString to ensure the user sees the uninstall process - New-ItemProperty -Path $regPath -Name "DisplayIcon" -Value "$exePath,0" -PropertyType String -Force | Out-Null - New-ItemProperty -Path $regPath -Name "InstallLocation" -Value $localAppDataPath -PropertyType String -Force | Out-Null - New-ItemProperty -Path $regPath -Name "InstallSource" -Value $localAppDataPath -PropertyType String -Force | Out-Null - New-ItemProperty -Path $regPath -Name "Publisher" -Value "Agentuity" -PropertyType String -Force | Out-Null - New-ItemProperty -Path $regPath -Name "NoModify" -Value 1 -PropertyType DWord -Force | Out-Null - New-ItemProperty -Path $regPath -Name "NoRepair" -Value 1 -PropertyType DWord -Force | Out-Null - New-ItemProperty -Path $regPath -Name "SystemComponent" -Value 0 -PropertyType DWord -Force | Out-Null - - # Add estimated size (in KB) - $sizeInKB = 5000 # Default size if we can't calculate - try { - $exePath = Join-Path -Path $localAppDataPath -ChildPath "agentuity.exe" - if (Test-Path -Path $exePath) { - $fileInfo = Get-Item -Path $exePath - $sizeInKB = [math]::Ceiling($fileInfo.Length / 1024) - } - } catch { - Write-Warning "Failed to get executable size: $_" - } - New-ItemProperty -Path $regPath -Name "EstimatedSize" -Value $sizeInKB -PropertyType DWord -Force | Out-Null - - Write-Success "Successfully set registry keys for uninstallation" - } catch { - Write-Warning "Failed to set registry keys: $_" - # Continue anyway as this is not critical - } - - return $true - } - - # Standard MSI installation for admin users - $installDirParam = "" - if (-not [string]::IsNullOrEmpty($InstallDir)) { - $installDirParam = "INSTALLDIR=`"$InstallDir`"" - } - - $quietParam = "/qn" - $installScopeParams = "ALLUSERS=1" - $arguments = "/i `"$MsiPath`" $quietParam /norestart /log `"$LogPath`" $installScopeParams $installDirParam" - Write-Step "MSI command: msiexec.exe $arguments" - - $process = Start-Process -FilePath "msiexec.exe" -ArgumentList $arguments -Wait -PassThru - - if ($process.ExitCode -ne 0) { - Write-Error "Installation failed with exit code $($process.ExitCode). Check the log at $LogPath for details." - - # Provide more specific guidance based on common MSI error codes - switch ($process.ExitCode) { - 1601 { Write-Warning "The Windows Installer service could not be accessed." } - 1602 { Write-Warning "User cancelled installation." } - 1603 { Write-Warning "Fatal error during installation. Check the log for details." } - 1618 { Write-Warning "Another installation is already in progress." } - 1619 { Write-Warning "Installation package could not be opened." } - 1620 { Write-Warning "Installation package could not be opened." } - 1622 { Write-Warning "Error opening installation log file." } - 1623 { Write-Warning "Language of this installation package is not supported by your system." } - 1625 { Write-Warning "This installation is forbidden by system policy." } - 1638 { Write-Warning "Another version of this product is already installed." } - 1639 { Write-Warning "Invalid command line argument." } - default { Write-Warning "Check the log at $LogPath for details." } - } - - return $false - } - - return $true - } - catch { - Write-Error "Failed to start installation: $_" - return $false - } -} -} - -function Test-Installation { - param ( - [Parameter(Mandatory = $true)] - [string]$InstallPath - ) - - $exePath = Join-Path -Path $InstallPath -ChildPath "agentuity.exe" - - if (-not (Test-Path -Path $exePath)) { - Write-Warning "Agentuity executable not found at $exePath" - return $false - } - - try { - $output = & $exePath version 2>&1 - if ($LASTEXITCODE -ne 0) { - Write-Warning "Agentuity CLI verification failed with exit code $LASTEXITCODE" - return $false - } - - Write-Success "Agentuity CLI verified: $output" - return $true - } - catch { - Write-Warning "Failed to verify Agentuity CLI: $_" - return $false - } -} - -function Test-ExecutionPolicy { - $currentPolicy = Get-ExecutionPolicy - $allowedPolicies = @("Unrestricted", "RemoteSigned", "Bypass") - - if ($allowedPolicies -contains $currentPolicy) { - return $true - } - - Write-Warning "PowerShell execution policy is set to '$currentPolicy' which may prevent script execution." - Write-Warning "Allowed policies are: $($allowedPolicies -join ', ')" - - if ($NoPrompt) { - Write-Warning "Skipping PowerShell completion setup due to execution policy restrictions" - return $false - } - - $message = "Would you like to temporarily set the execution policy to 'RemoteSigned' for this session?" - if (Get-UserConfirmation -Message $message -DefaultToYes $true) { - try { - Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force - Write-Success "Temporarily set execution policy to RemoteSigned for this session" - return $true - } - catch { - Write-Warning "Failed to set execution policy: $_" - return $false - } - } - - return $false -} - -function Set-PowerShellCompletion { - param ( - [Parameter(Mandatory = $true)] - [string]$ExePath - ) - - Write-Step "Setting up PowerShell completion..." - - # Check execution policy first - if (-not (Test-ExecutionPolicy)) { - Write-Warning "Skipping PowerShell completion setup due to execution policy restrictions" - Write-Warning "You can manually set up completion by running these commands:" - Write-Warning " mkdir -Force $HOME\Documents\WindowsPowerShell\Completion" - Write-Warning " $ExePath completion powershell > $HOME\Documents\WindowsPowerShell\Completion\agentuity.ps1" - Write-Warning " Add '. `"$HOME\Documents\WindowsPowerShell\Completion\agentuity.ps1`"' to your PowerShell profile" - Write-Warning " To edit your profile, run: notepad $PROFILE" - return - } - - try { - # Verify the executable exists - if (-not (Test-Path -Path $ExePath)) { - # If the provided path doesn't exist, try to find the executable in Program Files (x86) - $programFilesX86Path = [System.IO.Path]::Combine(${env:ProgramFiles(x86)}, "Agentuity", "agentuity.exe") - - if (Test-Path -Path $programFilesX86Path) { - Write-Step "Found executable in Program Files (x86) instead of the expected location" - $ExePath = $programFilesX86Path - } else { - Write-Warning "Executable not found at $ExePath or $programFilesX86Path" - throw "Executable not found" - } - } - - # Test that the executable is actually accessible - try { - $testOutput = & $ExePath version 2>&1 - if ($LASTEXITCODE -ne 0) { - Write-Warning "Executable verification failed with exit code $LASTEXITCODE" - throw "Executable verification failed" - } - Write-Success "Verified executable is accessible: $testOutput" - } - catch { - $errorMessage = $_.Exception.Message - Write-Warning "Failed to execute $ExePath" - Write-Warning "Error: $errorMessage" - throw "Executable verification failed" - } - - # Create PowerShell profile directory if it doesn't exist - $profileDir = Split-Path -Parent $PROFILE - if (-not (Test-Path -Path $profileDir)) { - New-Item -Path $profileDir -ItemType Directory -Force | Out-Null - } - - # Create completion directory - $completionDir = Join-Path -Path $profileDir -ChildPath "Completion" - if (-not (Test-Path -Path $completionDir)) { - New-Item -Path $completionDir -ItemType Directory -Force | Out-Null - } - - # Generate completion script - $completionPath = Join-Path -Path $completionDir -ChildPath "agentuity.ps1" - Write-Step "Generating PowerShell completion script at $completionPath" - - try { - $completionOutput = & $ExePath completion powershell 2>&1 - if ($LASTEXITCODE -ne 0) { - Write-Warning "Failed to generate completion script: $completionOutput" - throw "Completion generation failed" - } - $completionOutput | Out-File -FilePath $completionPath -Encoding utf8 -Force - } - catch { - $errorMessage = $_.Exception.Message - Write-Warning "Failed to generate completion script" - Write-Warning "Error: $errorMessage" - throw "Completion generation failed" - } - - # Check if the profile exists, create if not - if (-not (Test-Path -Path $PROFILE)) { - New-Item -Path $PROFILE -ItemType File -Force | Out-Null - } - - # Add completion to profile if not already there - $profileContent = Get-Content -Path $PROFILE -Raw -ErrorAction SilentlyContinue - $completionLine = ". '$completionPath'" - - if (-not $profileContent -or -not $profileContent.Contains($completionLine)) { - Add-Content -Path $PROFILE -Value "`n# Agentuity CLI completion`n$completionLine" -Force - Write-Success "PowerShell completion installed to $completionPath and added to your profile" - Write-Step "NOTE: You'll need to restart PowerShell or run '. $PROFILE' for completion to take effect in future sessions" - } - else { - Write-Success "PowerShell completion already configured in your profile" - } - - # Source the completion script in the current session - try { - . $completionPath - Write-Success "PowerShell completion loaded in current session" - } - catch { - $errorMessage = $_.Exception.Message - Write-Warning "Failed to load completion in current session" - Write-Warning "Error: $errorMessage" - Write-Warning "Completion will be available in new PowerShell sessions" - } - } - catch { - $errorMessage = $_.Exception.Message - Write-Warning "Failed to set up PowerShell completion" - Write-Warning "Error: $errorMessage" - Write-Warning "You can manually set up completion by running these commands:" - Write-Warning " mkdir -Force $HOME\Documents\WindowsPowerShell\Completion" - Write-Warning " $ExePath completion powershell > $HOME\Documents\WindowsPowerShell\Completion\agentuity.ps1" - Write-Warning " Add '. `"$HOME\Documents\WindowsPowerShell\Completion\agentuity.ps1`"' to your PowerShell profile" - Write-Warning " To edit your profile, run: notepad $PROFILE" - } -} - -#endregion - -#region Main Script - -# Check PowerShell version -if ($PSVersionTable.PSVersion.Major -lt 5) { - Write-Warning "PowerShell 5.0 or later is recommended. You are running version $($PSVersionTable.PSVersion)." - - if (-not (Get-UserConfirmation -Message "Continue with PowerShell $($PSVersionTable.PSVersion)?" -DefaultToYes $false)) { - Write-Step "Installation cancelled. Please upgrade PowerShell and try again." - exit 0 - } -} - -# Check if running as administrator for system-wide installation -if (-not (Test-Administrator) -and [string]::IsNullOrEmpty($InstallDir)) { - $message = "You are not running as Administrator. The installer can:" - $message += "`n1. Install for current user only (recommended)" - $message += "`n2. Restart with administrator privileges for system-wide installation" - - Write-ColorOutput $message -ForegroundColor Yellow - $choice = Read-Host "Enter choice (1 or 2)" - - if ($choice -eq "2") { - Request-AdminPrivileges -ScriptPath $MyInvocation.MyCommand.Definition - } - else { - Write-Step "Continuing with user installation..." - } -} - -# Determine version to install -if ($Version -eq "latest") { - $VersionToUse = Get-LatestReleaseVersion -} else { - $VersionToUse = $Version -} - -# Remove 'v' prefix if present -$VersionToUse = $VersionToUse.TrimStart('v') - -# Determine architecture -$arch = Get-Architecture - -# Determine installation directory -$installDir = Get-DefaultInstallDir - -# Create installation directory if it doesn't exist -if (-not (Test-Path -Path $installDir)) { - Write-Step "Creating installation directory: $installDir" - try { - New-Item -Path $installDir -ItemType Directory -Force | Out-Null - } - catch { - $errorMessage = $_.Exception.Message - Write-Error "Failed to create installation directory: $errorMessage" -Exit - } -} - -# Determine download filename based on architecture -if ($arch -eq "x64") { - $downloadFilename = "agentuity-x64.msi" -} -elseif ($arch -eq "arm64") { - $downloadFilename = "agentuity-arm64.msi" -} -else { - $downloadFilename = "agentuity-x86.msi" -} - -# Construct download URLs -$downloadUrl = "https://github.com/agentuity/cli/releases/download/v${VersionToUse}/${downloadFilename}" -$checksumsUrl = "https://github.com/agentuity/cli/releases/download/v${VersionToUse}/checksums.txt" - -# Create temporary directory -$tempDir = Join-Path -Path $env:TEMP -ChildPath "agentuity_install_$([Guid]::NewGuid().ToString())" -New-Item -Path $tempDir -ItemType Directory -Force | Out-Null - -try { - # Download MSI installer - $msiPath = Join-Path -Path $tempDir -ChildPath $downloadFilename - Write-Step "Downloading Agentuity CLI v${VersionToUse} for Windows/$arch..." - - try { - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - $webClient = New-Object System.Net.WebClient - $webClient.DownloadFile($downloadUrl, $msiPath) - } - catch { - $errorMessage = $_.Exception.Message - Write-Error "Failed to download from ${downloadUrl}: ${errorMessage}" -Exit - } - - # Download and verify checksums - $checksumsPath = Join-Path -Path $tempDir -ChildPath "checksums.txt" - Write-Step "Downloading checksums for verification..." - - try { - $webClient.DownloadFile($checksumsUrl, $checksumsPath) - - # Verify checksum - Write-Step "Verifying checksum..." - $computedChecksum = Get-FileHash256 -FilePath $msiPath - $expectedChecksum = (Get-Content -Path $checksumsPath | Where-Object { $_ -match $downloadFilename } | Select-Object -First 1) -split '\s+' | Select-Object -First 1 - - if ([string]::IsNullOrEmpty($expectedChecksum)) { - Write-Warning "Checksum for $downloadFilename not found in checksums.txt. Skipping verification." - } - elseif ($computedChecksum -ne $expectedChecksum) { - Write-Error "Checksum verification failed. Expected: ${expectedChecksum}, Got: ${computedChecksum}" -Exit - } - else { - Write-Success "Checksum verification passed!" - } - } - catch { - $errorMessage = $_.Exception.Message - Write-Warning "Failed to verify checksum" - Write-Warning "Error: $errorMessage" - - if (-not (Get-UserConfirmation -Message "Continue without checksum verification?" -DefaultToYes $false)) { - Write-Step "Installation cancelled." - exit 0 - } - } - - # Confirm installation - if (-not $NoPrompt) { - $confirmMessage = "Ready to install Agentuity CLI v${VersionToUse} to $installDir. Continue?" - if (-not (Get-UserConfirmation -Message $confirmMessage -DefaultToYes $true)) { - Write-Step "Installation cancelled." - exit 0 - } - } - - # Install MSI - $installSuccess = Install-MSI -MsiPath $msiPath -InstallDir $installDir - - if (-not $installSuccess) { - Write-Warning "MSI installation may have failed. Attempting to verify installation..." - } - - # Verify installation - $programFilesPath = [System.IO.Path]::Combine($env:ProgramFiles, "Agentuity") - $programFilesX86Path = [System.IO.Path]::Combine(${env:ProgramFiles(x86)}, "Agentuity") - $localAppDataPath = [System.IO.Path]::Combine($env:LOCALAPPDATA, "Agentuity") - - # Prioritize paths based on admin status and installation directory - if (Test-Administrator) { - # For admin users, check Program Files locations first - $installPaths = @($programFilesX86Path, $programFilesPath, $localAppDataPath, $installDir) - } else { - # For non-admin users, check LOCALAPPDATA first - $installPaths = @($localAppDataPath, $installDir, $programFilesX86Path, $programFilesPath) - } - $installVerified = $false - - # In CI environment, list all paths being checked - if ($env:CI -eq "true") { - Write-Step "Checking for installation in the following paths:" - foreach ($path in $installPaths) { - Write-Step " - $path" - if (Test-Path -Path $path) { - Write-Step " Directory exists" - $files = Get-ChildItem -Path $path -Recurse | Select-Object -ExpandProperty FullName - if ($files.Count -gt 0) { - Write-Step " Files found:" - foreach ($file in $files) { - Write-Step " $file" - } - } else { - Write-Step " Directory is empty" - } - } else { - Write-Step " Directory does not exist" - } - } - } - - foreach ($path in $installPaths) { - if (Test-Installation -InstallPath $path) { - $installVerified = $true - $exePath = Join-Path -Path $path -ChildPath "agentuity.exe" - - # Add to PATH if not already there - Add-ToPath -PathToAdd $path - - # Load in current session - Load-InCurrentSession -ExePath $exePath - - # Set up PowerShell completion - Set-PowerShellCompletion -ExePath $exePath - - break - } - } - - # For CI environment, try to find the executable anywhere on the system - if (-not $installVerified -and $env:CI -eq "true") { - Write-Step "Installation not found in expected paths, searching system-wide..." - $possibleExes = Get-ChildItem -Path "C:\" -Recurse -Filter "agentuity.exe" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName - - if ($possibleExes.Count -gt 0) { - Write-Step "Found potential executables:" - foreach ($exe in $possibleExes) { - Write-Step " $exe" - $installDir = Split-Path -Parent $exe - if (Test-Installation -InstallPath $installDir) { - $installVerified = $true - $exePath = $exe - Write-Step "Verified installation at unexpected location: $installDir" - - # Add to PATH if not already there - Add-ToPath -PathToAdd $installDir - - # Load in current session - Load-InCurrentSession -ExePath $exePath - - # Set up PowerShell completion - Set-PowerShellCompletion -ExePath $exePath - - break - } - } - } else { - Write-Step "No agentuity.exe found on the system" - } - } - - if (-not $installVerified) { - Write-Error "Failed to verify installation. The MSI may have installed to a different location or failed silently." - Write-Warning "Please check the installation log at ${env:TEMP}\agentuity_install.log for details." - exit 1 - } - - # Final verification that the command is accessible - Write-Step "Verifying command is accessible in current session..." - try { - $verifyOutput = & agentuity version 2>&1 - if ($LASTEXITCODE -eq 0) { - Write-Success "Agentuity CLI is ready to use in the current session!" - Write-Success "Installation complete! Run 'agentuity --help' to get started." - } else { - Write-Warning "Command verification failed with exit code $LASTEXITCODE" - Write-Warning "You may need to restart your PowerShell session or manually add the installation directory to your PATH" - Write-Warning "Installation directory: $installDir" - Write-Warning "To manually add to PATH, run: `${env:PATH} += ';${installDir}'" - } - } catch { - $errorMessage = $_.Exception.Message - Write-Warning "Command 'agentuity' is not accessible in the current session" - Write-Warning "Error: $errorMessage" - Write-Warning "You may need to restart your PowerShell session or manually add the installation directory to your PATH" - Write-Warning "Installation directory: $installDir" - Write-Warning "To manually add to PATH, run: `${env:PATH} += ';${installDir}'" - } - - Write-Step "For more information, visit: $(Write-Url "https://agentuity.dev")" -} -finally { - # Clean up temporary directory - if (Test-Path -Path $tempDir) { - Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue - } -} - -#endregion diff --git a/install.sh b/install.sh index 1ea15935..21de1eff 100755 --- a/install.sh +++ b/install.sh @@ -16,9 +16,12 @@ tty_cyan="$(tty_mkbold 36)" tty_magenta="$(tty_mkbold 35)" tty_underline="$(tty_escape 4)" +USE_BREW="true" CAT=${CAT:-cat} ARCH=$(uname -m) OS=$(uname -s) +EXTENSION="tar.gz" +DEBUG="false" usage() { $CAT 1>&2 < VERSION: $VERSION" + debug " > INSTALL_PATH: $INSTALL_PATH" + debug " > USE_BREW: $USE_BREW" } +debug() { + if [[ "$DEBUG" == "true" ]]; then + printf "${tty_magenta}[DEBUG] ${tty_bold} %s${tty_reset}\n" "$1" + fi +} ohai() { printf "${tty_blue}==>${tty_bold} %s${tty_reset}\n" "$1" @@ -78,6 +96,8 @@ check_known_arch() { else ARCH="arm64" fi + + debug " > Architecture: $ARCH" } is_macos() { @@ -102,17 +122,7 @@ abort_if_windows() { fi } -setup_extension_var() { - if is_macos; then - EXTENSION="tar.gz" - elif is_linux; then - EXTENSION="tar.gz" - else - abort "Unsupported operating system: $OS" - fi -} - -setup_install_path_var() { +setup_default_install_path_var() { if is_macos; then if [[ -d "$HOME/.local/bin" ]] && [[ -w "$HOME/.local/bin" ]]; then INSTALL_PATH="$HOME/.local/bin" @@ -136,9 +146,12 @@ setup_install_path_var() { else abort "Unsupported operating system: $OS" fi + + debug " > Install Path: $INSTALL_PATH" } check_install_path() { + if [[ ! -d "$INSTALL_PATH" ]]; then ohai "Creating install directory: $INSTALL_PATH" mkdir -p "$INSTALL_PATH" 2>/dev/null || true # Don't abort if mkdir fails @@ -148,53 +161,71 @@ check_install_path() { ohai "No write permission to $INSTALL_PATH. Trying alternative locations..." fi - if [[ "$INSTALL_PATH" == "/usr/local/bin" ]]; then - if [[ -d "$HOME/.local/bin" ]] || mkdir -p "$HOME/.local/bin" 2>/dev/null; then - if [[ -w "$HOME/.local/bin" ]]; then - ohai "Using $HOME/.local/bin instead" - INSTALL_PATH="$HOME/.local/bin" - fi - elif [[ -d "$HOME/.bin" ]] || mkdir -p "$HOME/.bin" 2>/dev/null; then - if [[ -w "$HOME/.bin" ]]; then - ohai "Using $HOME/.bin instead" - INSTALL_PATH="$HOME/.bin" - fi - elif [[ -d "$HOME/bin" ]] || mkdir -p "$HOME/bin" 2>/dev/null; then - if [[ -w "$HOME/bin" ]]; then - ohai "Using $HOME/bin instead" - INSTALL_PATH="$HOME/bin" + if [[ ! -d "$INSTALL_PATH" ]]; then + + if [[ "$INSTALL_PATH" == "/usr/local/bin" ]]; then + ohai "1No write permission to $INSTALL_PATH. Trying alternative locations..." + + if [[ -d "$HOME/.local/bin" ]] || mkdir -p "$HOME/.local/bin" 2>/dev/null; then + if [[ -w "$HOME/.local/bin" ]]; then + ohai "Using $HOME/.local/bin instead" + INSTALL_PATH="$HOME/.local/bin" + fi + elif [[ -d "$HOME/.bin" ]] || mkdir -p "$HOME/.bin" 2>/dev/null; then + if [[ -w "$HOME/.bin" ]]; then + ohai "Using $HOME/.bin instead" + INSTALL_PATH="$HOME/.bin" + fi + elif [[ -d "$HOME/bin" ]] || mkdir -p "$HOME/bin" 2>/dev/null; then + if [[ -w "$HOME/bin" ]]; then + ohai "Using $HOME/bin instead" + INSTALL_PATH="$HOME/bin" + fi + else + abort "Could not find or create a writable installation directory. Try running with sudo or specify a different directory with --dir." fi else - abort "Could not find or create a writable installation directory. Try running with sudo or specify a different directory with --dir." + abort "No write permission to $INSTALL_PATH. Try running with sudo or specify a different directory with --dir." fi + debug " > Install Path Changed: $INSTALL_PATH" + else + debug " > Install Path Not Changed" fi + } check_version() { if [[ -z "$VERSION" ]]; then abort "Version is empty. This should not happen." fi + + debug " > Version: $VERSION" } check_latest_release() { if [[ "$VERSION" == "latest" ]]; then ohai "Fetching latest release information..." - RELEASE_URL="https://agentuity.sh/release/cli" - VERSION=$(curl -s $RELEASE_URL | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + VERSION=$(curl -s $"https://agentuity.sh/release/cli" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') if [[ -z "$VERSION" ]]; then abort "Failed to fetch latest version information" fi fi + + debug " > Version: $VERSION" + } install_mac() { - if command -v brew >/dev/null 2>&1 && [[ "$NO_BREW" != "true" ]]; then + if command -v brew >/dev/null 2>&1 && [[ "$USE_BREW" == "true" ]]; then + ohai "Homebrew detected! Installing Agentuity CLI using Homebrew..." if [[ "$VERSION" != "latest" ]]; then ohai "Installing Agentuity CLI version $VERSION using Homebrew..." brew install agentuity/tap/agentuity@${VERSION#v} else + + debug " > heloooooooo 2?: $USE_BREW" ohai "Installing latest Agentuity CLI version using Homebrew..." brew install -q agentuity/tap/agentuity fi @@ -205,20 +236,30 @@ install_mac() { abort "Homebrew installation failed. Please try again or use manual installation." fi - else + else ohai "Installing Agentuity CLI using curl..." - curl -fsSL https://agentuity.sh/install.sh | bash fi } + download_release() { DOWNLOAD_FILENAME="agentuity_${OS}_${ARCH}.${EXTENSION}" DOWNLOAD_URL="https://github.com/agentuity/cli/releases/download/v${VERSION#v}/${DOWNLOAD_FILENAME}" - ohai "Downloading Agentuity CLI v${VERSION} for ${OS}/${ARCH}..." - curl -L --progress-bar "$DOWNLOAD_URL" -o "$TMP_DIR/$DOWNLOAD_FILENAME" || abort "Failed to download from $DOWNLOAD_URL" + debug " > DOWNLOAD_URL: $DOWNLOAD_URL" + debug " > DOWNLOAD_FILENAME: $DOWNLOAD_FILENAME" + debug " > TMP_DIR: $TMP_DIR" + + if curl --head --silent --fail "$DOWNLOAD_URL" > /dev/null 2>&1; then + ohai "Downloading Agentuity CLI v${VERSION} for ${OS}/${ARCH}..." + curl -L --progress-bar "$DOWNLOAD_URL" -o "$TMP_DIR/$DOWNLOAD_FILENAME" || abort "Failed to download from $DOWNLOAD_URL" + else + abort "Failed to download from $DOWNLOAD_URL" + fi + + } download_checksums() { @@ -268,7 +309,7 @@ extract_release() { install_agentuity() { - ohai "Installing to $INSTALL_PATH..." + ohai "Installing in path $INSTALL_PATH" if [[ -f "$TMP_DIR/agentuity" ]]; then if is_macos && [[ -f "$INSTALL_PATH/agentuity" ]]; then ohai "Removing existing binary to avoid macOS quarantine issues..." @@ -320,15 +361,15 @@ set_path() { warn "$INSTALL_PATH is not in your PATH. You may need to add it manually to use the agentuity command." case "$SHELL" in */bash*) - echo " echo 'export PATH=\"\$PATH:$INSTALL_PATH\"' >> ~/.bashrc" + echo " echo '\nexport PATH=\"\$PATH:$INSTALL_PATH\"' >> ~/.bashrc" echo " source ~/.bashrc # To apply changes immediately" ;; */zsh*) - echo " echo 'export PATH=\"\$PATH:$INSTALL_PATH\"' >> ~/.zshrc" + echo " echo '\nexport PATH=\"\$PATH:$INSTALL_PATH\"' >> ~/.zshrc" echo " source ~/.zshrc # To apply changes immediately" ;; */fish*) - echo " echo 'set -gx PATH \$PATH $INSTALL_PATH' >> ~/.config/fish/config.fish" + echo " echo '\nset -gx PATH \$PATH $INSTALL_PATH' >> ~/.config/fish/config.fish" echo " source ~/.config/fish/config.fish # To apply changes immediately" ;; *) @@ -419,28 +460,56 @@ cleanup() { main() { abort_if_windows + + debug "1 check_known_arch" check_known_arch + VERSION="latest" TMP_DIR="$(mktemp -d)" trap cleanup EXIT - setup_extension_var - setup_install_path_var + + debug "2 setup_install_path_var" + setup_default_install_path_var + debug "3 parse_cli_args: $@" parse_cli_args "$@" + + debug "4 check_install_path" check_install_path + + debug "5 check_version" check_version + + if is_macos; then + debug "6 install_mac" install_mac fi + + debug "7 check_latest_release" check_latest_release + + debug "8 download_release" download_release + + debug "9 download_checksums" download_checksums + + debug "10 extract_release" extract_release + + debug "11 install_agentuity" install_agentuity + + debug "12 set_path" set_path + + debug "13 install_completions" install_completions + + debug "14 success" success } diff --git a/install_test/Dockerfile b/install_test/Dockerfile new file mode 100644 index 00000000..345f27e4 --- /dev/null +++ b/install_test/Dockerfile @@ -0,0 +1,20 @@ +FROM ubuntu:22.04 + +# Install dependencies +RUN apt-get update && \ + apt-get install -y curl tar ca-certificates && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /workspace + +# Copy install.sh into the image +COPY install.sh ./ + +# Make it executable +RUN chmod +x install.sh + +# Add a script to run the install and verification steps +COPY install_test/docker-test-install.sh ./ +RUN chmod +x docker-test-install.sh + +CMD ["./docker-test-install.sh"] \ No newline at end of file diff --git a/install_test/docker-test-install.sh b/install_test/docker-test-install.sh new file mode 100644 index 00000000..2147f4b6 --- /dev/null +++ b/install_test/docker-test-install.sh @@ -0,0 +1,37 @@ +#!/bin/bash +set -e + + +echo "####################################################################################################" +echo "### Test Install without arguments (latest version and default install path)" +./install.sh +# Verify installation +LATEST_VERSION=$(agentuity --version) +echo "Installed version: $LATEST_VERSION" +echo "####################################################################################################" +echo "" +echo "" +echo "####################################################################################################" +echo "### Test Install with version" +./install.sh -v 0.0.118 + +# Verify installation +CURRENT_VERSION=$(agentuity --version) +echo "Installed version (specific): $LATEST_VERSION" +if [ "$CURRENT_VERSION" != "0.0.118" ]; then + echo "Version verification failed" + exit 1 +fi +echo "####################################################################################################" +echo "" +echo "" +echo "####################################################################################################" +echo "### Test Install with directory and version" +./install.sh -d /tmp/agentuity-test-version -v 0.0.118 +CURRENT_VERSION=$(/tmp/agentuity-test-version/agentuity --version) +if [ "$CURRENT_VERSION" != "0.0.118" ]; then + echo "Version verification failed" + exit 1 +fi +echo "####################################################################################################" + diff --git a/installer.wsx b/installer.wsx deleted file mode 100644 index 375b6e11..00000000 --- a/installer.wsx +++ /dev/null @@ -1,88 +0,0 @@ - - - {{ if eq .MsiArch "x64" }} - - - - {{ else }} - - - - {{ end }} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From fb7c85813087dec8432eb3275905ff5c132f2845 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Wed, 7 May 2025 21:56:52 +0200 Subject: [PATCH 07/16] last minute change --- install.sh | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/install.sh b/install.sh index 21de1eff..91201246 100755 --- a/install.sh +++ b/install.sh @@ -161,37 +161,34 @@ check_install_path() { ohai "No write permission to $INSTALL_PATH. Trying alternative locations..." fi - if [[ ! -d "$INSTALL_PATH" ]]; then + + if [[ "$INSTALL_PATH" == "/usr/local/bin" ]]; then + ohai "No write permission to $INSTALL_PATH. Trying alternative locations..." - if [[ "$INSTALL_PATH" == "/usr/local/bin" ]]; then - ohai "1No write permission to $INSTALL_PATH. Trying alternative locations..." - - if [[ -d "$HOME/.local/bin" ]] || mkdir -p "$HOME/.local/bin" 2>/dev/null; then - if [[ -w "$HOME/.local/bin" ]]; then - ohai "Using $HOME/.local/bin instead" - INSTALL_PATH="$HOME/.local/bin" - fi - elif [[ -d "$HOME/.bin" ]] || mkdir -p "$HOME/.bin" 2>/dev/null; then - if [[ -w "$HOME/.bin" ]]; then - ohai "Using $HOME/.bin instead" - INSTALL_PATH="$HOME/.bin" - fi - elif [[ -d "$HOME/bin" ]] || mkdir -p "$HOME/bin" 2>/dev/null; then - if [[ -w "$HOME/bin" ]]; then - ohai "Using $HOME/bin instead" - INSTALL_PATH="$HOME/bin" - fi - else - abort "Could not find or create a writable installation directory. Try running with sudo or specify a different directory with --dir." + if [[ -d "$HOME/.local/bin" ]] || mkdir -p "$HOME/.local/bin" 2>/dev/null; then + if [[ -w "$HOME/.local/bin" ]]; then + ohai "Using $HOME/.local/bin instead" + INSTALL_PATH="$HOME/.local/bin" + fi + elif [[ -d "$HOME/.bin" ]] || mkdir -p "$HOME/.bin" 2>/dev/null; then + if [[ -w "$HOME/.bin" ]]; then + ohai "Using $HOME/.bin instead" + INSTALL_PATH="$HOME/.bin" + fi + elif [[ -d "$HOME/bin" ]] || mkdir -p "$HOME/bin" 2>/dev/null; then + if [[ -w "$HOME/bin" ]]; then + ohai "Using $HOME/bin instead" + INSTALL_PATH="$HOME/bin" fi else - abort "No write permission to $INSTALL_PATH. Try running with sudo or specify a different directory with --dir." + abort "Could not find or create a writable installation directory. Try running with sudo or specify a different directory with --dir." fi debug " > Install Path Changed: $INSTALL_PATH" - else - debug " > Install Path Not Changed" fi + if [[ ! -w "$INSTALL_PATH" ]]; then + abort "No write permission to $INSTALL_PATH. Try running with sudo or specify a different directory with --dir." + fi } check_version() { From 581a36c8e48ff60a77c030d1386367d4dad0385a Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Wed, 7 May 2025 23:04:14 +0200 Subject: [PATCH 08/16] Fix some issues for sh shell --- Makefile | 8 +- install.sh | 156 ++++++++---------- install_test/Dockerfile-Alpine | 20 +++ .../{Dockerfile => Dockerfile-Ubuntu} | 0 install_test/docker-test-install.sh | 4 + 5 files changed, 98 insertions(+), 90 deletions(-) create mode 100644 install_test/Dockerfile-Alpine rename install_test/{Dockerfile => Dockerfile-Ubuntu} (100%) diff --git a/Makefile b/Makefile index 504656e7..fb99063e 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build fmt generate +.PHONY: build fmt generate test_install_linux test_install_alpine build: fmt generate @go build -o agentuity @@ -11,6 +11,10 @@ generate: @go generate ./... test_install_linux: - @docker build -t agentuity-test-install-linux -f install_test/Dockerfile . + @docker build -t agentuity-test-install-linux -f install_test/Dockerfile-Ubuntu . @docker run -it agentuity-test-install-linux +test_install_alpine: + @docker build -t agentuity-test-install-alpine -f install_test/Dockerfile-Alpine . + @docker run -it agentuity-test-install-alpine + diff --git a/install.sh b/install.sh index 91201246..5addc1ec 100755 --- a/install.sh +++ b/install.sh @@ -1,8 +1,9 @@ -#!/bin/bash +#!/bin/sh +# shellcheck shell=sh set -e -if [[ -t 1 ]]; then +if [ -t 1 ]; then tty_escape() { printf "\033[%sm" "$1"; } else tty_escape() { :; } @@ -18,6 +19,7 @@ tty_underline="$(tty_escape 4)" USE_BREW="true" CAT=${CAT:-cat} +CURL=${CURL:-curl} ARCH=$(uname -m) OS=$(uname -s) EXTENSION="tar.gz" @@ -36,7 +38,7 @@ EOF } parse_cli_args() { - while [[ $# -gt 0 ]]; do + while [ $# -gt 0 ]; do case "$1" in -v|--version) VERSION="$2" @@ -63,7 +65,7 @@ parse_cli_args() { } debug() { - if [[ "$DEBUG" == "true" ]]; then + if [ "$DEBUG" = "true" ]; then printf "${tty_magenta}[DEBUG] ${tty_bold} %s${tty_reset}\n" "$1" fi } @@ -87,11 +89,11 @@ abort() { check_known_arch() { - if [[ "$ARCH" != "x86_64" ]] && [[ "$ARCH" != "amd64" ]] && [[ "$ARCH" != "arm64" ]] && [[ "$ARCH" != "aarch64" ]]; then + if [ "$ARCH" != "x86_64" ] && [ "$ARCH" != "amd64" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "aarch64" ]; then abort "Unsupported architecture: $ARCH" fi - if [[ "$ARCH" == "x86_64" || "$ARCH" == "amd64" ]]; then + if [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "amd64" ]; then ARCH="x86_64" else ARCH="arm64" @@ -101,7 +103,7 @@ check_known_arch() { } is_macos() { - if [[ "$OS" == "Darwin" ]]; then + if [ "$OS" = "Darwin" ]; then return 0 else return 1 @@ -109,7 +111,7 @@ is_macos() { } is_linux() { - if [[ "$OS" == "Linux" ]]; then + if [ "$OS" = "Linux" ]; then return 0 else return 1 @@ -117,28 +119,28 @@ is_linux() { } abort_if_windows() { - if [[ "$OS" == "Windows" ]]; then + if [ "$OS" = "Windows" ]; then abort "Windows is not supported. Please use WSL or a native Windows installation." fi } setup_default_install_path_var() { if is_macos; then - if [[ -d "$HOME/.local/bin" ]] && [[ -w "$HOME/.local/bin" ]]; then + if [ -d "$HOME/.local/bin" ] && [ -w "$HOME/.local/bin" ]; then INSTALL_PATH="$HOME/.local/bin" - elif [[ -d "$HOME/.bin" ]] && [[ -w "$HOME/.bin" ]]; then + elif [ -d "$HOME/.bin" ] && [ -w "$HOME/.bin" ]; then INSTALL_PATH="$HOME/.bin" - elif [[ -d "$HOME/bin" ]] && [[ -w "$HOME/bin" ]]; then + elif [ -d "$HOME/bin" ] && [ -w "$HOME/bin" ]; then INSTALL_PATH="$HOME/bin" else INSTALL_PATH="/usr/local/bin" fi elif is_linux; then - if [[ -d "$HOME/.local/bin" ]] && [[ -w "$HOME/.local/bin" ]]; then + if [ -d "$HOME/.local/bin" ] && [ -w "$HOME/.local/bin" ]; then INSTALL_PATH="$HOME/.local/bin" - elif [[ -d "$HOME/.bin" ]] && [[ -w "$HOME/.bin" ]]; then + elif [ -d "$HOME/.bin" ] && [ -w "$HOME/.bin" ]; then INSTALL_PATH="$HOME/.bin" - elif [[ -d "$HOME/bin" ]] && [[ -w "$HOME/bin" ]]; then + elif [ -d "$HOME/bin" ] && [ -w "$HOME/bin" ]; then INSTALL_PATH="$HOME/bin" else INSTALL_PATH="/usr/local/bin" @@ -152,31 +154,30 @@ setup_default_install_path_var() { check_install_path() { - if [[ ! -d "$INSTALL_PATH" ]]; then + if [ ! -d "$INSTALL_PATH" ]; then ohai "Creating install directory: $INSTALL_PATH" mkdir -p "$INSTALL_PATH" 2>/dev/null || true # Don't abort if mkdir fails fi - if [[ -w "$INSTALL_PATH" ]]; then + if [ -w "$INSTALL_PATH" ]; then ohai "No write permission to $INSTALL_PATH. Trying alternative locations..." fi - if [[ "$INSTALL_PATH" == "/usr/local/bin" ]]; then - ohai "No write permission to $INSTALL_PATH. Trying alternative locations..." + if [ "$INSTALL_PATH" = "/usr/local/bin" ]; then - if [[ -d "$HOME/.local/bin" ]] || mkdir -p "$HOME/.local/bin" 2>/dev/null; then - if [[ -w "$HOME/.local/bin" ]]; then + if [ -d "$HOME/.local/bin" ] || mkdir -p "$HOME/.local/bin" 2>/dev/null; then + if [ -w "$HOME/.local/bin" ]; then ohai "Using $HOME/.local/bin instead" INSTALL_PATH="$HOME/.local/bin" fi - elif [[ -d "$HOME/.bin" ]] || mkdir -p "$HOME/.bin" 2>/dev/null; then - if [[ -w "$HOME/.bin" ]]; then + elif [ -d "$HOME/.bin" ] || mkdir -p "$HOME/.bin" 2>/dev/null; then + if [ -w "$HOME/.bin" ]; then ohai "Using $HOME/.bin instead" INSTALL_PATH="$HOME/.bin" fi - elif [[ -d "$HOME/bin" ]] || mkdir -p "$HOME/bin" 2>/dev/null; then - if [[ -w "$HOME/bin" ]]; then + elif [ -d "$HOME/bin" ] || mkdir -p "$HOME/bin" 2>/dev/null; then + if [ -w "$HOME/bin" ]; then ohai "Using $HOME/bin instead" INSTALL_PATH="$HOME/bin" fi @@ -186,13 +187,13 @@ check_install_path() { debug " > Install Path Changed: $INSTALL_PATH" fi - if [[ ! -w "$INSTALL_PATH" ]]; then + if [ ! -w "$INSTALL_PATH" ]; then abort "No write permission to $INSTALL_PATH. Try running with sudo or specify a different directory with --dir." fi } check_version() { - if [[ -z "$VERSION" ]]; then + if [ -z "$VERSION" ]; then abort "Version is empty. This should not happen." fi @@ -200,10 +201,10 @@ check_version() { } check_latest_release() { - if [[ "$VERSION" == "latest" ]]; then + if [ "$VERSION" = "latest" ]; then ohai "Fetching latest release information..." - VERSION=$(curl -s $"https://agentuity.sh/release/cli" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') - if [[ -z "$VERSION" ]]; then + VERSION=$($CURL -s "https://agentuity.sh/release/cli" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + if [ -z "$VERSION" ]; then abort "Failed to fetch latest version information" fi fi @@ -213,16 +214,14 @@ check_latest_release() { } install_mac() { - if command -v brew >/dev/null 2>&1 && [[ "$USE_BREW" == "true" ]]; then + if command -v brew >/dev/null 2>&1 && [ "$USE_BREW" = "true" ]; then ohai "Homebrew detected! Installing Agentuity CLI using Homebrew..." - if [[ "$VERSION" != "latest" ]]; then + if [ "$VERSION" != "latest" ]; then ohai "Installing Agentuity CLI version $VERSION using Homebrew..." brew install agentuity/tap/agentuity@${VERSION#v} else - - debug " > heloooooooo 2?: $USE_BREW" ohai "Installing latest Agentuity CLI version using Homebrew..." brew install -q agentuity/tap/agentuity fi @@ -275,14 +274,14 @@ download_checksums() { CHECKSUM_TOOL="" fi - if [[ -n "$CHECKSUM_TOOL" ]]; then + if [ -n "$CHECKSUM_TOOL" ]; then cd "$TMP_DIR" COMPUTED_CHECKSUM=$($CHECKSUM_TOOL "$DOWNLOAD_FILENAME" | cut -d ' ' -f 1) EXPECTED_CHECKSUM=$(grep "$DOWNLOAD_FILENAME" checksums.txt | cut -d ' ' -f 1) - if [[ -z "$EXPECTED_CHECKSUM" ]]; then + if [ -z "$EXPECTED_CHECKSUM" ]; then warn "Checksum for $DOWNLOAD_FILENAME not found in checksums.txt. Skipping verification." - elif [[ "$COMPUTED_CHECKSUM" != "$EXPECTED_CHECKSUM" ]]; then + elif [ "$COMPUTED_CHECKSUM" != "$EXPECTED_CHECKSUM" ]; then abort "Checksum verification failed. Expected: $EXPECTED_CHECKSUM, Got: $COMPUTED_CHECKSUM" else ohai "Checksum verification passed!" @@ -293,10 +292,10 @@ download_checksums() { } extract_release() { - if [[ "$EXTENSION" == "tar.gz" ]]; then + if [ "$EXTENSION" = "tar.gz" ]; then ohai "Extracting..." tar -xzf "$TMP_DIR/$DOWNLOAD_FILENAME" -C "$TMP_DIR" || abort "Failed to extract archive" - elif [[ "$EXTENSION" == "zip" ]]; then + elif [ "$EXTENSION" = "zip" ]; then ohai "Extracting..." unzip -q "$TMP_DIR/$DOWNLOAD_FILENAME" -d "$TMP_DIR" || abort "Failed to extract archive" else @@ -307,8 +306,8 @@ extract_release() { install_agentuity() { ohai "Installing in path $INSTALL_PATH" - if [[ -f "$TMP_DIR/agentuity" ]]; then - if is_macos && [[ -f "$INSTALL_PATH/agentuity" ]]; then + if [ -f "$TMP_DIR/agentuity" ]; then + if is_macos && [ -f "$INSTALL_PATH/agentuity" ]; then ohai "Removing existing binary to avoid macOS quarantine issues..." rm -f "$INSTALL_PATH/agentuity" || abort "Failed to remove existing binary from $INSTALL_PATH" fi @@ -326,16 +325,12 @@ install_agentuity() { } set_path() { - if [[ ":$PATH:" != *":$INSTALL_PATH:"* ]]; then - ohai "Adding $INSTALL_PATH to your PATH..." - - SHELL_CONFIG="" + # Determine the shell config file + if [ -n "$SHELL" ]; then case "$SHELL" in */bash*) SHELL_CONFIG="$HOME/.bashrc" - if [[ -f "$HOME/.bash_profile" ]]; then - SHELL_CONFIG="$HOME/.bash_profile" - fi + [ -f "$HOME/.bash_profile" ] && SHELL_CONFIG="$HOME/.bash_profile" ;; */zsh*) SHELL_CONFIG="$HOME/.zshrc" @@ -343,48 +338,33 @@ set_path() { */fish*) SHELL_CONFIG="$HOME/.config/fish/config.fish" ;; + *) + SHELL_CONFIG="$HOME/.profile" + ;; esac - - if [[ -n "$SHELL_CONFIG" ]] && [[ -w "$SHELL_CONFIG" ]]; then - echo "export PATH=\"\$PATH:$INSTALL_PATH\"" >> "$SHELL_CONFIG" - ohai "Added $INSTALL_PATH to PATH in $SHELL_CONFIG" - - if ! command -v agentuity >/dev/null 2>&1; then - printf "${tty_blue}==>${tty_bold} ${tty_magenta}To apply changes, restart your terminal or run:${tty_reset} source $SHELL_CONFIG\n" - fi - - export PATH="$PATH:$INSTALL_PATH" - else - warn "$INSTALL_PATH is not in your PATH. You may need to add it manually to use the agentuity command." - case "$SHELL" in - */bash*) - echo " echo '\nexport PATH=\"\$PATH:$INSTALL_PATH\"' >> ~/.bashrc" - echo " source ~/.bashrc # To apply changes immediately" - ;; - */zsh*) - echo " echo '\nexport PATH=\"\$PATH:$INSTALL_PATH\"' >> ~/.zshrc" - echo " source ~/.zshrc # To apply changes immediately" - ;; - */fish*) - echo " echo '\nset -gx PATH \$PATH $INSTALL_PATH' >> ~/.config/fish/config.fish" - echo " source ~/.config/fish/config.fish # To apply changes immediately" - ;; - *) - echo " Add $INSTALL_PATH to your PATH" - echo " Then restart your terminal or reload your shell configuration" - ;; - esac - fi + else + SHELL_CONFIG="$HOME/.profile" fi + + # Ensure the config file exists + touch "$SHELL_CONFIG" + + # Append the PATH export if not already present + if ! grep -q "$INSTALL_PATH" "$SHELL_CONFIG"; then + printf "export PATH=\"\$PATH:%s\"\n" "$INSTALL_PATH" >> "$SHELL_CONFIG" + ohai "Added $INSTALL_PATH to PATH in $SHELL_CONFIG" + fi + + export PATH="$PATH:$INSTALL_PATH" } install_completions() { if command -v "$INSTALL_PATH/agentuity" >/dev/null 2>&1; then COMPLETION_DIR="" if is_macos; then - if [[ -d "/usr/local/etc/bash_completion.d" ]]; then + if [ -d "/usr/local/etc/bash_completion.d" ]; then BASH_COMPLETION_DIR="/usr/local/etc/bash_completion.d" - if [[ -w "$BASH_COMPLETION_DIR" ]]; then + if [ -w "$BASH_COMPLETION_DIR" ]; then ohai "Generating bash completion script..." "$INSTALL_PATH/agentuity" completion bash > "$BASH_COMPLETION_DIR/agentuity" ohai "Bash completion installed to $BASH_COMPLETION_DIR/agentuity" @@ -393,9 +373,9 @@ install_completions() { fi fi - if [[ -d "/usr/local/share/zsh/site-functions" ]]; then + if [ -d "/usr/local/share/zsh/site-functions" ]; then ZSH_COMPLETION_DIR="/usr/local/share/zsh/site-functions" - if [[ -w "$ZSH_COMPLETION_DIR" ]]; then + if [ -w "$ZSH_COMPLETION_DIR" ]; then ohai "Generating zsh completion script..." "$INSTALL_PATH/agentuity" completion zsh > "$ZSH_COMPLETION_DIR/_agentuity" ohai "Zsh completion installed to $ZSH_COMPLETION_DIR/_agentuity" @@ -406,9 +386,9 @@ install_completions() { fi if is_linux; then - if [[ -d "/etc/bash_completion.d" ]]; then + if [ -d "/etc/bash_completion.d" ]; then BASH_COMPLETION_DIR="/etc/bash_completion.d" - if [[ -w "$BASH_COMPLETION_DIR" ]]; then + if [ -w "$BASH_COMPLETION_DIR" ]; then ohai "Generating bash completion script..." "$INSTALL_PATH/agentuity" completion bash > "$BASH_COMPLETION_DIR/agentuity" ohai "Bash completion installed to $BASH_COMPLETION_DIR/agentuity" @@ -419,9 +399,9 @@ install_completions() { fi fi - if [[ -d "/usr/share/zsh/vendor-completions" ]]; then + if [ -d "/usr/share/zsh/vendor-completions" ]; then ZSH_COMPLETION_DIR="/usr/share/zsh/vendor-completions" - if [[ -w "$ZSH_COMPLETION_DIR" ]]; then + if [ -w "$ZSH_COMPLETION_DIR" ]; then ohai "Generating zsh completion script..." "$INSTALL_PATH/agentuity" completion zsh > "$ZSH_COMPLETION_DIR/_agentuity" ohai "Zsh completion installed to $ZSH_COMPLETION_DIR/_agentuity" @@ -443,7 +423,7 @@ success() { ohai "For more information, visit: $(url "https://agentuity.dev")" if ! command -v agentuity >/dev/null 2>&1; then - printf "${tty_blue}==>${tty_bold} ${tty_magenta}To apply PATH changes, restart your terminal or run:${tty_reset} source ~/.$(basename $SHELL)rc\n" + printf "${tty_blue}==>${tty_bold} ${tty_magenta}To apply PATH changes, restart your terminal or run:${tty_reset} source ~/.$(basename $SHELL 2>/dev/null)rc\n" fi exit 0 diff --git a/install_test/Dockerfile-Alpine b/install_test/Dockerfile-Alpine new file mode 100644 index 00000000..1e516b10 --- /dev/null +++ b/install_test/Dockerfile-Alpine @@ -0,0 +1,20 @@ +FROM alpine:3.18 + +# Install dependencies +RUN apk update && \ + apk add --no-cache curl tar ca-certificates && \ + rm -rf /var/cache/apk/* + +WORKDIR /workspace + +# Copy install.sh into the image +COPY install.sh ./ + +# Make it executable +RUN chmod +x install.sh + +# Add a script to run the install and verification steps +COPY install_test/docker-test-install.sh ./ +RUN chmod +x docker-test-install.sh + +CMD ["sh", "./docker-test-install.sh"] \ No newline at end of file diff --git a/install_test/Dockerfile b/install_test/Dockerfile-Ubuntu similarity index 100% rename from install_test/Dockerfile rename to install_test/Dockerfile-Ubuntu diff --git a/install_test/docker-test-install.sh b/install_test/docker-test-install.sh index 2147f4b6..e1d872f1 100644 --- a/install_test/docker-test-install.sh +++ b/install_test/docker-test-install.sh @@ -1,10 +1,14 @@ #!/bin/bash set -e +source ./install.sh echo "####################################################################################################" echo "### Test Install without arguments (latest version and default install path)" ./install.sh + + + # Verify installation LATEST_VERSION=$(agentuity --version) echo "Installed version: $LATEST_VERSION" From 48a4100134c11b75fb41015264da66375dbe40db Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Wed, 7 May 2025 23:05:57 +0200 Subject: [PATCH 09/16] Test with debian as well --- Makefile | 3 +++ install_test/Dockerfile-Debian | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 install_test/Dockerfile-Debian diff --git a/Makefile b/Makefile index fb99063e..90a6ceb9 100644 --- a/Makefile +++ b/Makefile @@ -18,3 +18,6 @@ test_install_alpine: @docker build -t agentuity-test-install-alpine -f install_test/Dockerfile-Alpine . @docker run -it agentuity-test-install-alpine +test_install_debian: + @docker build -t agentuity-test-install-debian -f install_test/Dockerfile-Debian . + @docker run -it agentuity-test-install-debian diff --git a/install_test/Dockerfile-Debian b/install_test/Dockerfile-Debian new file mode 100644 index 00000000..580cad96 --- /dev/null +++ b/install_test/Dockerfile-Debian @@ -0,0 +1,20 @@ +FROM debian:12 + +# Install dependencies +RUN apt-get update && \ + apt-get install -y curl tar ca-certificates && \ + rm -rf /var/cache/apt/* + +WORKDIR /workspace + +# Copy install.sh into the image +COPY install.sh ./ + +# Make it executable +RUN chmod +x install.sh + +# Add a script to run the install and verification steps +COPY install_test/docker-test-install.sh ./ +RUN chmod +x docker-test-install.sh + +CMD ["./docker-test-install.sh"] \ No newline at end of file From d819bd634744e059f945896013f88941068bc65a Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Wed, 7 May 2025 23:37:44 +0200 Subject: [PATCH 10/16] Wring condition --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 5addc1ec..584739c9 100755 --- a/install.sh +++ b/install.sh @@ -159,7 +159,7 @@ check_install_path() { mkdir -p "$INSTALL_PATH" 2>/dev/null || true # Don't abort if mkdir fails fi - if [ -w "$INSTALL_PATH" ]; then + if [ ! -w "$INSTALL_PATH" ]; then ohai "No write permission to $INSTALL_PATH. Trying alternative locations..." fi From 9d214eb8c201a8890d6ba50a2d66c986ee10a715 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Thu, 8 May 2025 00:02:41 +0200 Subject: [PATCH 11/16] use agentuity.sh instead of github --- install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 584739c9..0459319d 100755 --- a/install.sh +++ b/install.sh @@ -242,7 +242,7 @@ install_mac() { download_release() { DOWNLOAD_FILENAME="agentuity_${OS}_${ARCH}.${EXTENSION}" - DOWNLOAD_URL="https://github.com/agentuity/cli/releases/download/v${VERSION#v}/${DOWNLOAD_FILENAME}" + DOWNLOAD_URL="https://agentuity.sh/release/cli/v${VERSION#v}/${DOWNLOAD_FILENAME}" debug " > DOWNLOAD_URL: $DOWNLOAD_URL" debug " > DOWNLOAD_FILENAME: $DOWNLOAD_FILENAME" @@ -259,7 +259,7 @@ download_release() { } download_checksums() { - CHECKSUMS_URL="https://github.com/agentuity/cli/releases/download/v${VERSION#v}/checksums.txt" + CHECKSUMS_URL="https://agentuity.sh/release/cli/v${VERSION#v}/checksums.txt" ohai "Downloading checksums for verification..." if ! curl -L --silent "$CHECKSUMS_URL" -o "$TMP_DIR/checksums.txt"; then warn "Failed to download checksums file. Skipping verification." From a5a4a31520fce0bf04d3f78115eeb26b066b6c7f Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Thu, 8 May 2025 14:33:11 +0200 Subject: [PATCH 12/16] Test install script in CI --- .github/workflows/go.yml | 99 ++---------------------------- .github/workflows/upgrade-test.yml | 2 +- 2 files changed, 6 insertions(+), 95 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index f80bfae3..26633945 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -16,7 +16,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [blacksmith-4vcpu-ubuntu-2204, windows-latest, macos-latest] + os: [blacksmith-4vcpu-ubuntu-2204, blacksmith-4vcpu-ubuntu-2204-arm, windows-latest, macos-latest] steps: - uses: actions/checkout@v4 @@ -50,31 +50,11 @@ jobs: - uses: actions/checkout@v4 - name: Test Install Script (Linux) - if: matrix.os == 'blacksmith-4vcpu-ubuntu-2204' + if: matrix.os == 'blacksmith-4vcpu-ubuntu-2204' || matrix.os == 'blacksmith-4vcpu-ubuntu-2204-arm' run: | - chmod +x ./install.sh - # Test with default options (latest version) - ./install.sh -d /tmp/agentuity-test - # Verify installation - /tmp/agentuity-test/agentuity --version - - # Test with specific version if available - simplified to avoid potential issues - LATEST_VERSION=$(/tmp/agentuity-test/agentuity --version) - if [ -n "$LATEST_VERSION" ]; then - echo "Testing installation with specific version: $LATEST_VERSION" - ./install.sh -d /tmp/agentuity-test-version -v $LATEST_VERSION - # Verify installation with specific version - INSTALLED_VERSION=$(/tmp/agentuity-test-version/agentuity --version) - echo "Installed version: $INSTALLED_VERSION" - echo "Expected version: $LATEST_VERSION" - if [ "$INSTALLED_VERSION" = "$LATEST_VERSION" ]; then - echo "Version verification successful" - else - echo "Version verification failed" - exit 1 - fi - fi - shell: bash + chmod +x ./install_test/docker-test-install.sh + ./install_test/docker-test-install.sh + shell: sh - name: Test Install Script (macOS) if: matrix.os == 'macos-latest' @@ -94,72 +74,3 @@ jobs: echo "macOS double installation test passed - segfault fix verified" shell: bash - if: matrix.os == 'windows-latest' - env: - GITHUB_TOKEN: ${{ github.token }} - CI: true - AGENTUITY_TEST_VERSION: "0.0.74" - run: | - Write-Host "Testing PowerShell install script on Windows..." - - # Verify the PowerShell script exists - if (Test-Path "install.ps1") { - Write-Host "Found install.ps1 script" - } else { - Write-Host "install.ps1 not found" - exit 1 - } - - # Create test directory - $testDir = Join-Path $env:TEMP "agentuity-ps-test" - if (Test-Path $testDir) { - Remove-Item -Path $testDir -Recurse -Force - } - New-Item -Path $testDir -ItemType Directory -Force | Out-Null - - # Test with default options but NoPrompt - Write-Host "Testing PowerShell install script with default options..." - & powershell -ExecutionPolicy Bypass -File .\install.ps1 -InstallDir $testDir -NoPrompt - - # Verify installation - $exePath = Join-Path -Path $testDir -ChildPath "agentuity.exe" - if (Test-Path $exePath) { - Write-Host "Installation verification successful" - - # Get installed version - $installedVersion = & $exePath version - Write-Host "Installed version: $installedVersion" - - # Test with specific version from environment variable - $specificVersion = $env:AGENTUITY_TEST_VERSION - Write-Host "Testing PowerShell install script with specific version $specificVersion..." - $versionTestDir = Join-Path $env:TEMP "agentuity-ps-test-version" - if (Test-Path $versionTestDir) { - Remove-Item -Path $versionTestDir -Recurse -Force - } - New-Item -Path $versionTestDir -ItemType Directory -Force | Out-Null - - & powershell -ExecutionPolicy Bypass -File .\install.ps1 -Version $specificVersion -InstallDir $versionTestDir -NoPrompt - - # Verify version-specific installation - $versionExePath = Join-Path -Path $versionTestDir -ChildPath "agentuity.exe" - if (Test-Path $versionExePath) { - Write-Host "Version-specific installation verification successful" - $versionInstalledVersion = & $versionExePath version - Write-Host "Version-specific installed version: $versionInstalledVersion" - - if ($versionInstalledVersion -match $specificVersion) { - Write-Host "Version verification successful" - } else { - Write-Host "Version verification failed. Expected: $specificVersion, Got: $versionInstalledVersion" - exit 1 - } - } else { - Write-Host "Version-specific installation verification failed" - exit 1 - } - } else { - Write-Host "Installation verification failed" - exit 1 - } - shell: pwsh \ No newline at end of file diff --git a/.github/workflows/upgrade-test.yml b/.github/workflows/upgrade-test.yml index 82c00ced..66729c07 100644 --- a/.github/workflows/upgrade-test.yml +++ b/.github/workflows/upgrade-test.yml @@ -17,7 +17,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [blacksmith-4vcpu-ubuntu-2204, macos-latest, windows-latest] + os: [blacksmith-4vcpu-ubuntu-2204, blacksmith-4vcpu-ubuntu-2204-arm, macos-latest, windows-latest] steps: - name: Checkout code From b7232a38ee3751b7441811682eacdf91c1fc6043 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Thu, 8 May 2025 14:40:54 +0200 Subject: [PATCH 13/16] set -ex --- README.md | 4 ++-- install_test/docker-test-install.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4e0cc231..b4916fbf 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ The command line tools for the Agentuity Agent Cloud Platform. These tools are You can install the CLI using the install script (Linux, macOS, or WSL): ```bash -curl -fsSL https://agentuity.sh/install.sh | bash +curl -fsSL https://agentuity.sh/install.sh | sh ``` If you are on a Mac, you can install the CLI using Homebrew (by default, the install script will use Homebrew if it is installed and not disabled): @@ -30,7 +30,7 @@ brew install agentuity/tap/agentuity You can force the install script to use the direct binary install (not Homebrew) with: ```bash -curl -fsSL https://agentuity.sh/install.sh | bash -s -- --no-brew +curl -fsSL https://agentuity.sh/install.sh | sh -s -- --no-brew ``` **Windows:** Native Windows installation is no longer supported. Please use [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/) and run the install script from your WSL terminal. diff --git a/install_test/docker-test-install.sh b/install_test/docker-test-install.sh index e1d872f1..1ca12469 100644 --- a/install_test/docker-test-install.sh +++ b/install_test/docker-test-install.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -e +set -ex source ./install.sh From 2ecb7503c88c20dd8198383031771f9fb3883e4b Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Thu, 8 May 2025 14:49:50 +0200 Subject: [PATCH 14/16] fix test script --- .github/workflows/go.yml | 9 ++++++++- install_test/docker-test-install.sh | 8 ++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 26633945..d682ba8e 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -50,7 +50,14 @@ jobs: - uses: actions/checkout@v4 - name: Test Install Script (Linux) - if: matrix.os == 'blacksmith-4vcpu-ubuntu-2204' || matrix.os == 'blacksmith-4vcpu-ubuntu-2204-arm' + if: matrix.os == 'blacksmith-4vcpu-ubuntu-2204' + run: | + chmod +x ./install_test/docker-test-install.sh + ./install_test/docker-test-install.sh + shell: sh + + - name: Test Install Script (Linux ARM) + if: matrix.os == 'blacksmith-4vcpu-ubuntu-2204-arm' run: | chmod +x ./install_test/docker-test-install.sh ./install_test/docker-test-install.sh diff --git a/install_test/docker-test-install.sh b/install_test/docker-test-install.sh index 1ca12469..606026a7 100644 --- a/install_test/docker-test-install.sh +++ b/install_test/docker-test-install.sh @@ -1,7 +1,7 @@ #!/bin/bash -set -ex +set -e -source ./install.sh +chmod +x ./install.sh echo "####################################################################################################" echo "### Test Install without arguments (latest version and default install path)" @@ -10,7 +10,7 @@ echo "### Test Install without arguments (latest version and default install pat # Verify installation -LATEST_VERSION=$(agentuity --version) +LATEST_VERSION=$(/root/.local/bin/agentuity --version) echo "Installed version: $LATEST_VERSION" echo "####################################################################################################" echo "" @@ -20,7 +20,7 @@ echo "### Test Install with version" ./install.sh -v 0.0.118 # Verify installation -CURRENT_VERSION=$(agentuity --version) +CURRENT_VERSION=$(/root/.local/bin/agentuity --version) echo "Installed version (specific): $LATEST_VERSION" if [ "$CURRENT_VERSION" != "0.0.118" ]; then echo "Version verification failed" From d7128f6f43d9f1deee516a39015163b3764f5339 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Thu, 8 May 2025 15:02:59 +0200 Subject: [PATCH 15/16] Export path in test-install --- install_test/docker-test-install.sh | 33 +++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/install_test/docker-test-install.sh b/install_test/docker-test-install.sh index 606026a7..c342e2ff 100644 --- a/install_test/docker-test-install.sh +++ b/install_test/docker-test-install.sh @@ -3,14 +3,39 @@ set -e chmod +x ./install.sh +# Same logic as install.sh +if [ -d "$HOME/.local/bin" ] && [ -w "$HOME/.local/bin" ]; then + INSTALL_PATH="$HOME/.local/bin" +elif [ -d "$HOME/.bin" ] && [ -w "$HOME/.bin" ]; then + INSTALL_PATH="$HOME/.bin" +elif [ -d "$HOME/bin" ] && [ -w "$HOME/bin" ]; then + INSTALL_PATH="$HOME/bin" +else + if [ -d "$HOME/.local/bin" ] || mkdir -p "$HOME/.local/bin" 2>/dev/null; then + if [ -w "$HOME/.local/bin" ]; then + INSTALL_PATH="$HOME/.local/bin" + fi + elif [ -d "$HOME/.bin" ] || mkdir -p "$HOME/.bin" 2>/dev/null; then + if [ -w "$HOME/.bin" ]; then + INSTALL_PATH="$HOME/.bin" + fi + elif [ -d "$HOME/bin" ] || mkdir -p "$HOME/bin" 2>/dev/null; then + if [ -w "$HOME/bin" ]; then + INSTALL_PATH="$HOME/bin" + fi + else + abort "Could not find or create a writable installation directory. Try running with sudo or specify a different directory with --dir." + fi +fi + +export PATH="$INSTALL_PATH:$PATH" + echo "####################################################################################################" echo "### Test Install without arguments (latest version and default install path)" ./install.sh - - # Verify installation -LATEST_VERSION=$(/root/.local/bin/agentuity --version) +LATEST_VERSION=$(agentuity --version) echo "Installed version: $LATEST_VERSION" echo "####################################################################################################" echo "" @@ -20,7 +45,7 @@ echo "### Test Install with version" ./install.sh -v 0.0.118 # Verify installation -CURRENT_VERSION=$(/root/.local/bin/agentuity --version) +CURRENT_VERSION=$(agentuity --version) echo "Installed version (specific): $LATEST_VERSION" if [ "$CURRENT_VERSION" != "0.0.118" ]; then echo "Version verification failed" From 4c5d684d787b2952c99c3c8726663187da424c3a Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Thu, 8 May 2025 16:40:30 +0200 Subject: [PATCH 16/16] remove windows installer from goreleaser --- .goreleaser.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index a4391319..4f62d6c8 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -121,13 +121,3 @@ brews: alternative_names: - "agentuity@{{ .Version }}" -msi: - - id: agentuity - name: "agentuity-{{.MsiArch}}" - wxs: ./installer.wsx - ids: - - agentuity - goamd64: v1 - replace: true - mod_timestamp: "{{ .CommitTimestamp }}" - version: v3