* fix(agents): recognize connection errors as retryable timeout failures
## Problem
When a model endpoint becomes unreachable (e.g., local proxy down,
relay server offline), the failover system fails to switch to the
next candidate model. Errors like "Connection error." are not
classified as retryable, causing the session to hang on a broken
endpoint instead of falling back to healthy alternatives.
## Root Cause
Connection/network errors are not recognized by the current failover
classifier:
- Text patterns like "Connection error.", "fetch failed", "network error"
- Error codes like ECONNREFUSED, ENOTFOUND, EAI_AGAIN (in message text)
While `failover-error.ts` handles these as error codes (err.code),
it misses them when they appear as plain text in error messages.
## Solution
Extend timeout error patterns to include connection/network failures:
**In `errors.ts` (ERROR_PATTERNS.timeout):**
- Text: "connection error", "network error", "fetch failed", etc.
- Regex: /\beconn(?:refused|reset|aborted)\b/i, /\benotfound\b/i, /\beai_again\b/i
**In `failover-error.ts` (TIMEOUT_HINT_RE):**
- Same patterns for non-assistant error paths
## Testing
Added test cases covering:
- "Connection error."
- "fetch failed"
- "network error: ECONNREFUSED"
- "ENOTFOUND" / "EAI_AGAIN" in message text
## Impact
- **Compatibility:** High - only expands retryable error detection
- **Behavior:** Connection failures now trigger automatic fallback
- **Risk:** Low - changes are additive and well-tested
* style: fix code formatting for test file
Google's loadCodeAssist API rejects "LINUX" as an invalid Platform enum
value, causing OAuth setup to fail with 400 Bad Request on Linux systems.
The pi-ai runtime already uses "PLATFORM_UNSPECIFIED" for this field.
This aligns the extension's discoverProject() with that approach by
returning "PLATFORM_UNSPECIFIED" for Linux (and other non-Windows/macOS
platforms) instead of "LINUX".
Also fixes the original resolvePlatform() which incorrectly fell through
to "MACOS" as default instead of explicitly checking for "darwin".
The parent `.chat-text` applies `overflow-wrap: anywhere; word-break: break-word;`
which forces long tokens (UUIDs, hashes) inside inline `<code>` to break across
visual lines. When copied, the browser injects spaces at those break points,
corrupting the pasted value.
Override with `overflow-wrap: normal; word-break: keep-all;` on inline `<code>`
selectors so tokens stay intact.
Fixes#32230
Signed-off-by: HCL <chenglunhu@gmail.com>
Tighten installer/runtime consistency so users on Node 22.0-22.11 are blocked before install/runtime drift, with cleaner CLI guidance.
- Enforce Node >=22.12 in scripts/install.sh preflight checks
- Align installer messages to the same 22.12+ runtime floor
- Replace openclaw.mjs thrown version error with stderr+exit to avoid noisy stack traces
Surface a clear Node 22.12+ requirement before npm/install bootstrap work so users avoid misleading downstream errors.
- Add installer shell preflight to block active Node <22 and suggest NVM recovery commands
- Add openclaw.mjs runtime preflight for npm/npx usage with explicit Node version guidance
- Keep messaging actionable for both NVM and non-NVM environments
When a Slack bot is removed from a workspace while still configured in
OpenClaw, the gateway enters an infinite retry loop on account_inactive
or invalid_auth errors, making the entire gateway unresponsive.
Add isNonRecoverableSlackAuthError() to detect permanent credential
failures (account_inactive, invalid_auth, token_revoked, etc.) and
throw immediately instead of retrying. This mirrors how the Telegram
provider already distinguishes recoverable network errors from fatal
auth errors via isRecoverableTelegramNetworkError().
The check is applied in both the startup catch block and the disconnect
reconnect path so stale credentials always fail fast with a clear error
message.
Closes#32366
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>