fix: tolerate gateways without image profiles

This commit is contained in:
2026-07-10 07:29:01 +08:00
parent f67cbbda65
commit c79e85e635
4 changed files with 36 additions and 7 deletions
+16 -5
View File
@@ -16,6 +16,7 @@ import subprocess
import sys import sys
import tempfile import tempfile
import tomllib import tomllib
import urllib.error
import urllib.parse import urllib.parse
import urllib.request import urllib.request
from pathlib import Path from pathlib import Path
@@ -23,7 +24,7 @@ from typing import Any
APP_NAME = "codex-retry-gateway-tui" APP_NAME = "codex-retry-gateway-tui"
FALLBACK_VERSION = "0.1.8" FALLBACK_VERSION = "0.1.9"
DEFAULT_GATEWAY_ADMIN_PATH = "/__codex_retry_gateway" DEFAULT_GATEWAY_ADMIN_PATH = "/__codex_retry_gateway"
DEFAULT_GATEWAY_URL = "http://127.0.0.1:4610/__codex_retry_gateway" DEFAULT_GATEWAY_URL = "http://127.0.0.1:4610/__codex_retry_gateway"
DEFAULT_API_URL = DEFAULT_GATEWAY_URL DEFAULT_API_URL = DEFAULT_GATEWAY_URL
@@ -1150,11 +1151,21 @@ def fetch_payload(api_url: str, timeout: int, access_key: str = "") -> dict[str,
return data return data
def fetch_optional_payload(url: str, timeout: int, access_key: str = "") -> tuple[dict[str, Any], str]: def fetch_optional_payload(
url: str,
timeout: int,
access_key: str = "",
*,
allow_not_found: bool = False,
) -> tuple[dict[str, Any], str]:
if not str(url or "").strip(): if not str(url or "").strip():
return {}, "" return {}, ""
try: try:
return fetch_payload(url, timeout, access_key), "" return fetch_payload(url, timeout, access_key), ""
except urllib.error.HTTPError as exc:
if allow_not_found and exc.code == 404:
return {}, ""
return {}, str(exc)
except Exception as exc: except Exception as exc:
return {}, str(exc) return {}, str(exc)
@@ -2030,12 +2041,12 @@ def fetch_dashboard_snapshot(
"image_profiles": build_api_url(gateway_root, "/api/image-profiles"), "image_profiles": build_api_url(gateway_root, "/api/image-profiles"),
} }
def fetch_optional(url: str) -> tuple[dict[str, Any], str]: def fetch_optional(url: str, *, allow_not_found: bool = False) -> tuple[dict[str, Any], str]:
return fetch_optional_payload(url, timeout, access_key) return fetch_optional_payload(url, timeout, access_key, allow_not_found=allow_not_found)
with ThreadPoolExecutor(max_workers=5) as pool: with ThreadPoolExecutor(max_workers=5) as pool:
futures = { futures = {
name: pool.submit(fetch_optional, url) name: pool.submit(fetch_optional, url, allow_not_found=name == "image_profiles")
for name, url in endpoints.items() for name, url in endpoints.items()
} }
status_payload, status_error = futures["status"].result() status_payload, status_error = futures["status"].result()
+1 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "codex-retry-gateway-tui" name = "codex-retry-gateway-tui"
version = "0.1.8" version = "0.1.9"
description = "Terminal UI for codex-retry-gateway monitoring and control" description = "Terminal UI for codex-retry-gateway monitoring and control"
readme = "README.md" readme = "README.md"
requires-python = ">=3.11" requires-python = ">=3.11"
+18
View File
@@ -121,6 +121,24 @@ class CodexRetryGatewayTUITests(unittest.TestCase):
self.assertEqual(mod.request_updated_elapsed(row), "1.0s") self.assertEqual(mod.request_updated_elapsed(row), "1.0s")
self.assertEqual(mod.request_chunk_progress(row), "7 / 4.1KB") self.assertEqual(mod.request_chunk_progress(row), "7 / 4.1KB")
def test_optional_image_profiles_endpoint_can_be_absent_on_older_gateway(self) -> None:
mod = load_module()
missing_endpoint = mod.urllib.error.HTTPError(
"http://127.0.0.1:4610/__codex_retry_gateway/api/image-profiles",
404,
"Not Found",
{},
None,
)
with mock.patch.object(mod, "fetch_payload", side_effect=missing_endpoint):
payload, error = mod.fetch_optional_payload(
"http://127.0.0.1:4610/__codex_retry_gateway/api/image-profiles",
5,
allow_not_found=True,
)
self.assertEqual(payload, {})
self.assertEqual(error, "")
def test_request_usage_summary_shows_cached_ratio(self) -> None: def test_request_usage_summary_shows_cached_ratio(self) -> None:
mod = load_module() mod = load_module()
row = { row = {
Generated
+1 -1
View File
@@ -4,7 +4,7 @@ requires-python = ">=3.11"
[[package]] [[package]]
name = "codex-retry-gateway-tui" name = "codex-retry-gateway-tui"
version = "0.1.8" version = "0.1.9"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "textual" }, { name = "textual" },