Some OpenAI-compat backends (e.g. glm-5.1-fast) return 400 with
"no parseable body" when the request payload is too large to parse,
rather than a proper context_length_exceeded error. Without this marker,
is_context_window_error() returns false and the auto-compact retry
loop never triggers — the user just sees an opaque 400 error.
💘 Generated with Crush
Assisted-by: GLM 5.1 FP8 via Crush <crush@charm.land>
Some providers/proxies return HTTP 400 with bodies like "no parseable
body" or "connection reset" during transient network blips. These are
not real bad requests — they're gateway errors wearing a 400 mask.
Detect known gateway error phrases in 400 response bodies and mark
them as retryable so the existing exponential backoff handles them.
- Add TimeoutConfig to HTTP client builder with connect_timeout (30s)
and request_timeout (5min) defaults, configurable via
CLAW_API_CONNECT_TIMEOUT and CLAW_API_REQUEST_TIMEOUT env vars
- Add with_timeout() builder to both AnthropicClient and
OpenAiCompatClient for per-client timeout configuration
- Parse Retry-After header on 429 responses and use it to override
exponential backoff delay when present
- Add ApiTimeoutConfig to runtime config with apiTimeout settings
in ~/.claw/settings.json (connectTimeout, requestTimeout, maxRetries)
- Add retry_after field to ApiError::Api for propagating rate limit
backoff hints through the retry pipeline