mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-05-22 19:54:22 +00:00
fix: improve error messages and UX consistency across CLI and shell scripts (#466)
- Clarify download error messages: distinguish HTTP errors from network errors with specific status codes in the message - Add actionable next steps to OAuth timeout: re-run command or set key manually - Standardize error help labels to "How to fix:" across CLI and shell scripts (was inconsistently "What to do:", "Troubleshooting:", or missing) - Add API method/endpoint context to retry failure messages so users know which API call failed - Make verify_agent_installed error cases mutually exclusive: first for PATH/installation issues, second for runtime/dependency issues Agent: ux-engineer Co-authored-by: A <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d47bbbd592
commit
d9037fad32
5 changed files with 37 additions and 25 deletions
|
|
@ -392,30 +392,33 @@ async function downloadScriptWithFallback(primaryUrl: string, fallbackUrl: strin
|
|||
}
|
||||
|
||||
function reportDownloadFailure(primaryUrl: string, fallbackUrl: string, primaryStatus: number, fallbackStatus: number): void {
|
||||
p.log.error("Script download failed");
|
||||
|
||||
if (primaryStatus === 404 && fallbackStatus === 404) {
|
||||
p.log.error("Script download failed (HTTP 404: not found)");
|
||||
console.error("\nThe script file could not be found.");
|
||||
console.error("This usually means the combination hasn't been published yet,");
|
||||
console.error("even though it may appear in the matrix.");
|
||||
console.error(`\nWhat to do:`);
|
||||
console.error(`\nHow to fix:`);
|
||||
console.error(` 1. Verify the combination is implemented: ${pc.cyan("spawn list")}`);
|
||||
console.error(` 2. Try again later (the script may be deploying)`);
|
||||
console.error(` 3. Report the issue: ${pc.cyan(`https://github.com/${REPO}/issues`)}`);
|
||||
} else {
|
||||
console.error(`\nNetwork or server error (HTTP ${primaryStatus}) - try again in a few moments.`);
|
||||
p.log.error(`Script download failed (HTTP ${primaryStatus}/${fallbackStatus})`);
|
||||
console.error(`\nBoth download sources returned errors.`);
|
||||
if (primaryStatus >= 500 || fallbackStatus >= 500) {
|
||||
console.error("The server may be experiencing temporary issues.");
|
||||
}
|
||||
console.error(`\nHow to fix:`);
|
||||
console.error(` 1. Wait a moment and try again`);
|
||||
console.error(` 2. Check GitHub status: ${pc.cyan("https://www.githubstatus.com")}`);
|
||||
}
|
||||
}
|
||||
|
||||
function reportDownloadError(ghUrl: string, err: unknown): never {
|
||||
p.log.error("Failed to download spawn script");
|
||||
p.log.error("Script download failed (network error)");
|
||||
console.error("\nError:", getErrorMessage(err));
|
||||
console.error("\nTroubleshooting:");
|
||||
console.error(` 1. Verify this combination exists: ${pc.cyan("spawn list")}`);
|
||||
console.error(" 2. Check your internet connection");
|
||||
console.error("\nHow to fix:");
|
||||
console.error(" 1. Check your internet connection");
|
||||
console.error(` 2. Verify this combination exists: ${pc.cyan("spawn list")}`);
|
||||
console.error(` 3. Try accessing the script directly: ${ghUrl}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
|
@ -927,7 +930,7 @@ export async function cmdUpdate(): Promise<void> {
|
|||
} catch (err) {
|
||||
s.stop(pc.red(`Failed to check for updates ${pc.dim(`(current: v${VERSION})`)}`));
|
||||
console.error("Error:", getErrorMessage(err));
|
||||
console.error(`\nTroubleshooting:`);
|
||||
console.error(`\nHow to fix:`);
|
||||
console.error(` 1. Check your internet connection`);
|
||||
console.error(` 2. Try again in a few moments`);
|
||||
console.error(` 3. Update manually: ${pc.cyan(`curl -fsSL ${RAW_BASE}/cli/install.sh | bash`)}`);
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ export async function loadManifest(forceRefresh = false): Promise<Manifest> {
|
|||
throw new Error(
|
||||
`Cannot load manifest: failed to fetch from GitHub and no local cache available.\n` +
|
||||
`\n` +
|
||||
`Troubleshooting:\n` +
|
||||
`How to fix:\n` +
|
||||
` 1. Check your internet connection\n` +
|
||||
` 2. Try again in a few moments (GitHub may be temporarily unreachable)\n` +
|
||||
` 3. If the problem persists, clear the cache and retry:\n` +
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ _report_modal_create_error() {
|
|||
log_error " - Network connectivity issues"
|
||||
log_error " - Invalid sandbox name (must be alphanumeric with dashes)"
|
||||
log_error ""
|
||||
log_error "Troubleshooting:"
|
||||
log_error "How to fix:"
|
||||
log_error " 1. Re-authenticate: modal setup"
|
||||
log_error " 2. Verify account status: https://modal.com/settings"
|
||||
log_error " 3. Check Modal status: https://status.modal.com"
|
||||
|
|
|
|||
|
|
@ -704,10 +704,15 @@ _await_oauth_callback() {
|
|||
|
||||
if ! _wait_for_oauth "${code_file}"; then
|
||||
cleanup_oauth_session "${server_pid}" "${oauth_dir}"
|
||||
log_warn "OAuth timed out after 120 seconds. Common causes:"
|
||||
log_warn "OAuth timed out after 120 seconds. Possible causes:"
|
||||
log_warn " - Browser did not open (try visiting the URL manually)"
|
||||
log_warn " - Authentication was not completed in the browser"
|
||||
log_warn " - Firewall or proxy blocked the local callback on port ${actual_port}"
|
||||
log_warn ""
|
||||
log_warn "How to fix:"
|
||||
log_warn " 1. Re-run the command to try again"
|
||||
log_warn " 2. Set the key manually: export OPENROUTER_API_KEY=sk-or-..."
|
||||
log_warn " (get a key at https://openrouter.ai/keys)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
|
@ -1155,11 +1160,12 @@ _handle_api_transient_error() {
|
|||
# Example: generic_cloud_api "$DO_API_BASE" "$DO_API_TOKEN" GET "/account" "" 5
|
||||
# Retries on: 429 (rate limit), 503 (service unavailable), network errors
|
||||
# Internal retry loop shared by generic_cloud_api and generic_cloud_api_custom_auth
|
||||
# Usage: _cloud_api_retry_loop REQUEST_FUNC MAX_RETRIES [REQUEST_FUNC_ARGS...]
|
||||
# Usage: _cloud_api_retry_loop REQUEST_FUNC MAX_RETRIES API_DESCRIPTION [REQUEST_FUNC_ARGS...]
|
||||
_cloud_api_retry_loop() {
|
||||
local request_func="${1}"
|
||||
local max_retries="${2}"
|
||||
shift 2
|
||||
local api_description="${3}"
|
||||
shift 3
|
||||
|
||||
local attempt=1
|
||||
local interval=2
|
||||
|
|
@ -1187,7 +1193,7 @@ _cloud_api_retry_loop() {
|
|||
return 0
|
||||
done
|
||||
|
||||
log_error "Cloud API request failed after ${max_retries} attempts"
|
||||
log_error "Cloud API request failed after ${max_retries} attempts (${api_description})"
|
||||
log_warn "This is usually caused by rate limiting or temporary provider issues."
|
||||
log_warn "Wait a minute and try again, or check the provider's status page."
|
||||
return 1
|
||||
|
|
@ -1201,7 +1207,7 @@ generic_cloud_api() {
|
|||
local body="${5:-}"
|
||||
local max_retries="${6:-3}"
|
||||
|
||||
_cloud_api_retry_loop _make_api_request "${max_retries}" "${base_url}" "${auth_token}" "${method}" "${endpoint}" "${body}"
|
||||
_cloud_api_retry_loop _make_api_request "${max_retries}" "${method} ${endpoint}" "${base_url}" "${auth_token}" "${method}" "${endpoint}" "${body}"
|
||||
}
|
||||
|
||||
# Helper to make API request with custom curl auth args (e.g., Basic Auth, custom headers)
|
||||
|
|
@ -1249,7 +1255,7 @@ generic_cloud_api_custom_auth() {
|
|||
shift 5
|
||||
# Remaining args are custom curl auth flags
|
||||
|
||||
_cloud_api_retry_loop _make_api_request_custom_auth "${max_retries}" "${base_url}${endpoint}" "${method}" "${body}" "$@"
|
||||
_cloud_api_retry_loop _make_api_request_custom_auth "${max_retries}" "${method} ${endpoint}" "${base_url}${endpoint}" "${method}" "${body}" "$@"
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
|
|
@ -1275,23 +1281,26 @@ verify_agent_installed() {
|
|||
log_error ""
|
||||
log_error "Possible causes:"
|
||||
log_error " - The installation script encountered an error (check logs above)"
|
||||
log_error " - Network connectivity issues during download"
|
||||
log_error " - Insufficient disk space or permissions"
|
||||
log_error " - The binary was installed to a directory not in PATH"
|
||||
log_error " - Network issues prevented the download from completing"
|
||||
log_error ""
|
||||
log_error "Try running the script again, or install ${agent_name} manually."
|
||||
log_error "How to fix:"
|
||||
log_error " 1. Re-run the script to retry the installation"
|
||||
log_error " 2. Install ${agent_name} manually and ensure it is in PATH"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! "${agent_cmd}" "${verify_arg}" &> /dev/null; then
|
||||
log_error "${agent_name} installation failed: '${agent_cmd} ${verify_arg}' returned an error"
|
||||
log_error "${agent_name} verification failed: '${agent_cmd} ${verify_arg}' returned an error"
|
||||
log_error ""
|
||||
log_error "The command was installed but doesn't execute properly."
|
||||
log_error "The command exists but does not run correctly."
|
||||
log_error "Possible causes:"
|
||||
log_error " - Missing runtime dependencies (Python, Node.js, etc.)"
|
||||
log_error " - Incompatible system architecture or OS version"
|
||||
log_error " - Corrupted download or partial installation"
|
||||
log_error ""
|
||||
log_error "Try running the script again, or check ${agent_name}'s installation docs."
|
||||
log_error "How to fix:"
|
||||
log_error " 1. Check ${agent_name}'s installation docs for prerequisites"
|
||||
log_error " 2. Run '${agent_cmd} ${verify_arg}' manually to see the error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ verify_sprite_connectivity() {
|
|||
|
||||
log_error "Sprite '${sprite_name}' failed to respond after ${max_attempts} attempts"
|
||||
log_error ""
|
||||
log_error "Troubleshooting:"
|
||||
log_error "How to fix:"
|
||||
log_error " 1. Check sprite status: sprite list"
|
||||
log_error " 2. View sprite logs: sprite logs ${sprite_name}"
|
||||
log_error " 3. Try recreating the sprite: sprite delete ${sprite_name} && sprite create ${sprite_name}"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue