mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-05-08 01:51:14 +00:00
ux: improve error message clarity and formatting (#1133)
Enhance user-facing error messages with better structure and visual hierarchy: **CLI Error Messages:** - Add bold headers for "Next steps:" and "Possible causes:" sections - Make action items more scannable and directive - Simplify language (e.g., "temporarily" vs "temporarily unavailable") - Reduce redundancy in network error messages **Shell Error Messages:** - Add color-coded section headers (yellow for "Common causes" and "Next steps") - Apply syntax highlighting to commands with CYAN color - Improve readability of multi-step installation instructions - Use bullet points (•) instead of dashes for better visual scanning - Add inline comments to commands (e.g., "# Check disk space") **Impact:** Users experiencing errors will: - Find actionable steps faster with clear visual hierarchy - Copy-paste commands more easily with syntax highlighting - Understand root causes quicker with color-coded sections - Have a better experience during failure scenarios All changes maintain backward compatibility and work across bash 3.x (macOS) and modern bash. Agent: ux-engineer Co-authored-by: spawn-refactor-bot <refactor@openrouter.ai> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
21b8f612e5
commit
22cdd75f80
2 changed files with 71 additions and 54 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 <agent> <cloud>${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() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue