diff --git a/cli/src/commands.ts b/cli/src/commands.ts index e3ad3c2c..d609bc07 100644 --- a/cli/src/commands.ts +++ b/cli/src/commands.ts @@ -648,23 +648,25 @@ function reportDownloadFailure(primaryUrl: string, fallbackUrl: string, primaryS console.error("\nThe spawn script doesn't exist at the expected location."); console.error("\nThis usually means:"); console.error(" • The agent + cloud combination hasn't been implemented yet"); - console.error(" • The script is currently being deployed (rare, but possible)"); + console.error(" • The script is currently being deployed (rare)"); console.error(" • There's a temporary issue with the file server"); - console.error(`\nWhat to do:`); - console.error(` 1. Check if it's marked as implemented: ${pc.cyan("spawn matrix")}`); - console.error(` 2. If the matrix shows it's available, wait 1-2 minutes and retry`); - console.error(` 3. Still not working? Report it: ${pc.cyan(`https://github.com/${REPO}/issues`)}`); + console.error(`\n${pc.bold("Next steps:")}`); + console.error(` 1. Verify it's implemented: ${pc.cyan("spawn matrix")}`); + console.error(` 2. If the matrix shows ✓, wait 1-2 minutes and retry`); + console.error(` 3. Still broken? Report it: ${pc.cyan(`https://github.com/${REPO}/issues`)}`); } else { p.log.error(`Script download failed`); console.error(`\nCouldn't download the spawn script (HTTP ${primaryStatus} from primary, ${fallbackStatus} from fallback).`); if (primaryStatus >= 500 || fallbackStatus >= 500) { - console.error("\nThe servers are experiencing issues or are temporarily unavailable."); + console.error("\nThe servers are experiencing issues or temporarily unavailable."); + } + console.error(`\n${pc.bold("Next steps:")}`); + console.error(` 1. Check your internet connection`); + console.error(` 2. Wait a moment and try again`); + console.error(` 3. Check GitHub's status: ${pc.cyan("https://www.githubstatus.com")}`); + if (primaryStatus >= 500 || fallbackStatus >= 500) { + console.error(` 4. If GitHub is down, retry when it's back up`); } - console.error(`\nWhat to do:`); - console.error(` 1. Verify your internet connection is working`); - console.error(` 2. Wait a minute and try again (servers may be recovering)`); - console.error(` 3. Check GitHub's status page: ${pc.cyan("https://www.githubstatus.com")}`); - console.error(` 4. If GitHub is down, wait and retry when it's back up`); } } @@ -676,30 +678,30 @@ function reportDownloadError(ghUrl: string, err: unknown): never { const isTimeout = errMsg.toLowerCase().includes("timeout"); const isConnection = errMsg.toLowerCase().includes("connect") || errMsg.toLowerCase().includes("enotfound"); - console.error("\nWhat's wrong:"); + console.error(`\n${pc.bold("Possible causes:")}`); if (isTimeout) { - console.error(" • Your internet connection is slow or unstable"); - console.error(" • The download server isn't responding (possibly overloaded)"); - console.error(" • A firewall may be slowing the connection"); + console.error(" • Slow or unstable internet connection"); + console.error(" • Download server not responding (possibly overloaded)"); + console.error(" • Firewall blocking or slowing the connection"); } else if (isConnection) { - console.error(" • No internet connection detected"); - console.error(" • A firewall or proxy is blocking GitHub access"); - console.error(" • DNS isn't resolving GitHub's domain (check your DNS settings)"); + console.error(" • No internet connection"); + console.error(" • Firewall or proxy blocking GitHub access"); + console.error(" • DNS not resolving GitHub's domain"); } else { - console.error(" • There's an issue with your internet connection"); - console.error(" • GitHub's servers may be temporarily down"); + console.error(" • Internet connection issue"); + console.error(" • GitHub's servers temporarily down"); } - console.error("\nWhat to do:"); - console.error(" 1. Check that your internet connection is working"); + console.error(`\n${pc.bold("Next steps:")}`); + console.error(" 1. Check your internet connection"); if (isConnection) { - console.error(" 2. Test accessing github.com in your browser"); - console.error(" 3. Check if a firewall or VPN is blocking access"); - console.error(" 4. Try disabling any proxy settings temporarily"); + console.error(" 2. Test github.com access in your browser"); + console.error(" 3. Check firewall/VPN settings"); + console.error(" 4. Try disabling proxy temporarily"); } else { - console.error(` 2. Verify this combination exists: ${pc.cyan("spawn matrix")}`); - console.error(" 3. Wait a minute and try again"); - console.error(` 4. Test accessing the URL directly: ${pc.dim(ghUrl)}`); + console.error(` 2. Verify combination exists: ${pc.cyan("spawn matrix")}`); + console.error(" 3. Wait a moment and retry"); + console.error(` 4. Test URL directly: ${pc.dim(ghUrl)}`); } process.exit(1); } @@ -866,7 +868,7 @@ export function getScriptFailureGuidance(exitCode: number | null, cloud: string, if (!entry) { // Default/unknown exit code return [ - "Common causes:", + `${pc.bold("Common causes:")}`, ...credentialHints(cloud, authHint, "Missing"), " - Cloud provider API rate limit or quota exceeded", " - Missing local dependencies (SSH, curl, jq)", @@ -874,7 +876,7 @@ export function getScriptFailureGuidance(exitCode: number | null, cloud: string, ]; } - const lines = [entry.header, ...entry.lines]; + const lines = [pc.bold(entry.header), ...entry.lines]; // Special handling for exit code 127 (missing command) if (exitCode === 127) { diff --git a/shared/common.sh b/shared/common.sh index ff500669..4b37791c 100644 --- a/shared/common.sh +++ b/shared/common.sh @@ -67,28 +67,29 @@ log_install_failed() { local install_cmd="${2:-}" local server_ip="${3:-}" - log_error "${agent_name} installation failed to complete successfully" + log_error "${agent_name} installation failed" log_error "" log_error "The agent could not be installed or verified on the server." log_error "" - log_error "Common causes:" - log_error " - Network timeout downloading packages (npm, pip, etc.)" - log_error " - Insufficient disk space or memory on the server" - log_error " - Missing system dependencies for ${agent_name}" - log_error " - Cloud provider's package mirror is temporarily unavailable" + printf '%b\n' "${YELLOW}Common causes:${NC}" >&2 + log_error " • Network timeout downloading packages (npm, pip, etc.)" + log_error " • Insufficient disk space or memory on the server" + log_error " • Missing system dependencies for ${agent_name}" + log_error " • Cloud provider's package mirror temporarily unavailable" log_error "" - log_error "Debugging steps:" + printf '%b\n' "${YELLOW}Next steps:${NC}" >&2 if [[ -n "${server_ip}" ]]; then - log_error " 1. SSH into the server and check logs:" - log_error " ssh root@${server_ip}" - log_error " Check: df -h (disk space)" - log_error " Check: free -h (memory)" + log_error " 1. SSH into the server to investigate:" + log_error " ${CYAN}ssh root@${server_ip}${NC}" + log_error " ${CYAN}df -h${NC} # Check disk space" + log_error " ${CYAN}free -h${NC} # Check memory" fi if [[ -n "${install_cmd}" ]]; then - log_error " 2. Try the installation manually:" - log_error " ${install_cmd}" + log_error " 2. Try manual installation:" + log_error " ${CYAN}${install_cmd}${NC}" fi - log_error " 3. Re-run spawn to try on a fresh server (some failures are transient)" + log_error " 3. Retry with a fresh server (many failures are transient)" + log_error " ${CYAN}spawn ${NC}" } # ============================================================ @@ -110,11 +111,18 @@ check_python_available() { log_error "" log_error "Spawn uses Python 3 for JSON parsing and API interactions." log_error "" - log_error "Install Python 3:" - log_error " Ubuntu/Debian: sudo apt-get update && sudo apt-get install -y python3" - log_error " Fedora/RHEL: sudo dnf install -y python3" - log_error " macOS: brew install python3" - log_error " Arch Linux: sudo pacman -S python" + printf '%b\n' "${YELLOW}Install Python 3:${NC}" >&2 + log_error " ${CYAN}# Ubuntu/Debian${NC}" + log_error " sudo apt-get update && sudo apt-get install -y python3" + log_error "" + log_error " ${CYAN}# Fedora/RHEL${NC}" + log_error " sudo dnf install -y python3" + log_error "" + log_error " ${CYAN}# macOS${NC}" + log_error " brew install python3" + log_error "" + log_error " ${CYAN}# Arch Linux${NC}" + log_error " sudo pacman -S python" log_error "" return 1 fi @@ -158,11 +166,18 @@ _install_jq_apk() { _report_jq_not_found() { log_error "jq is required but not installed" log_error "" - log_error "Install jq for your system:" - log_error " Ubuntu/Debian: sudo apt-get install -y jq" - log_error " Fedora/RHEL: sudo dnf install -y jq" - log_error " macOS: brew install jq" - log_error " Other: https://jqlang.github.io/jq/download/" + printf '%b\n' "${YELLOW}Install jq for your system:${NC}" >&2 + log_error " ${CYAN}# Ubuntu/Debian${NC}" + log_error " sudo apt-get install -y jq" + log_error "" + log_error " ${CYAN}# Fedora/RHEL${NC}" + log_error " sudo dnf install -y jq" + log_error "" + log_error " ${CYAN}# macOS${NC}" + log_error " brew install jq" + log_error "" + log_error " ${CYAN}# Other systems${NC}" + log_error " https://jqlang.github.io/jq/download/" } ensure_jq() {