feat: API timeout config, Retry-After header support, and configurable retry

- 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
This commit is contained in:
TheArchitectit
2026-04-27 11:38:31 -05:00
parent 4d3dc5b873
commit d8c57ed317
8 changed files with 266 additions and 80 deletions

View File

@@ -11570,7 +11570,8 @@ mod tests {
body: String::new(),
retryable: true,
suggested_action: None,
};
retry_after: None,
};
let rendered = format_user_visible_api_error("session-issue-22", &error);
assert!(rendered.contains("provider_internal"));
@@ -11593,7 +11594,8 @@ mod tests {
body: String::new(),
retryable: true,
suggested_action: None,
}),
retry_after: None,
}),
};
let rendered = format_user_visible_api_error("session-issue-22", &error);
@@ -11657,7 +11659,8 @@ mod tests {
body: String::new(),
retryable: false,
suggested_action: None,
};
retry_after: None,
};
let rendered = format_user_visible_api_error("session-issue-32", &error);
assert!(rendered.contains("context_window_blocked"), "{rendered}");
@@ -11724,7 +11727,8 @@ mod tests {
body: String::new(),
retryable: false,
suggested_action: None,
}),
retry_after: None,
}),
};
let rendered = format_user_visible_api_error("session-issue-32", &error);