Route pet asset downloads through the shared HTTP client (#36008)

## Why

Built-in pet downloads used a standalone blocking client, so CDN redirects did
not use Codex's configured route handling.

## What changed

- Download pet spritesheets asynchronously with a reusable
  `RouteAwareClientPool`.
- Keep cache validation, asset installation, and pet decoding off the async
  runtime while sharing one asset-and-load path across startup, previews, and
  selection.
- Preserve the download size limit while consuming streamed response chunks,
  and remove the TUI's direct `reqwest` dependency.

## Testing

Add coverage for oversized response chunks, cached built-in assets, pet loads
without an existing Tokio runtime, and stale preview and selection completions.

GitOrigin-RevId: 725e76f3ddb7e84b7212769892f28dc0add15741
This commit is contained in:
Celia Chen authored and copyberry committed 2026-07-29 18:40:38 +00:00
1 parent ad6fc66b6d
commit 09cf609218
11 files changed
+293 -95

No files matched your search

@@ -85,11 +85,16 @@ impl ChatWidget {
&chat_keymap.edit_queued_message,
current_terminal_info,
);
let pet_http_client = codex_http_client::RouteAwareClientPool::new(
config.http_client_factory(),
codex_http_client::ClientRouteClass::Other,
);
pets::start_configured_pet_load_if_needed(
&config,
/*ambient_pet_missing*/ true,
frame_requester.clone(),
app_event_tx.clone(),
pet_http_client.clone(),
);
let mut widget = Self {
app_event_tx: app_event_tx.clone(),
@@ -184,6 +189,7 @@ impl ChatWidget {
status_state: StatusState::default(),
review: ReviewState::default(),
active_hook_cell: None,
pet_http_client,
ambient_pet: None,
pet_picker_preview_state: crate::pets::PetPickerPreviewState::default(),
pet_picker_preview_pet: None,