test(codex): cover ChatGPT-Account-Id header on /models probe

Add regression tests locking in the new behavior: a JWT carrying a
chatgpt_account_id claim causes the probe to send ChatGPT-Account-Id,
while a malformed token omits the header instead of crashing.
This commit is contained in:
TARS 2026-07-15 17:32:20 +10:00 committed by Teknium
parent c44c2fbb0b
commit b49b1e5b93

View file

@ -113,6 +113,83 @@ def test_fetch_from_api_keeps_supported_in_api_false_models(monkeypatch):
assert "gpt-5-internal" not in models
def test_fetch_from_api_sends_chatgpt_account_id_header(monkeypatch):
"""The Codex /models endpoint only returns the per-account catalog when
the ``ChatGPT-Account-Id`` header is present. Without it, the response
is ``{"models":[]}`` (HTTP 200), which makes the picker silently
degrade to the curated fallback list and send invalid slugs on later
requests. Regression test for the upstream bug behind slow first
responses and HTTP 520/120s SSE hangs.
"""
import sys
from hermes_cli import codex_models
captured = {}
class _FakeResp:
status_code = 200
def json(self):
return {"models": [{"slug": "gpt-5.6-sol", "priority": 0}]}
class _FakeHttpx:
@staticmethod
def get(url, headers=None, timeout=None):
captured["url"] = url
captured["headers"] = dict(headers or {})
return _FakeResp()
monkeypatch.setitem(sys.modules, "httpx", _FakeHttpx)
# Hand-crafted JWT carrying the chatgpt_account_id claim.
import base64
import json
payload = base64.urlsafe_b64encode(
json.dumps(
{"https://api.openai.com/auth": {"chatgpt_account_id": "acct-test-123"}}
).encode()
).rstrip(b"=").decode()
fake_jwt = f"header.{payload}.sig"
models = codex_models._fetch_models_from_api(access_token=fake_jwt)
assert captured["headers"]["Authorization"] == f"Bearer {fake_jwt}"
assert captured["headers"].get("ChatGPT-Account-Id") == "acct-test-123"
assert "gpt-5.6-sol" in models
def test_fetch_from_api_omits_account_id_header_when_jwt_unparseable(monkeypatch):
"""A malformed token must not crash the probe — it should still send the
bearer header and let the upstream decide. We just verify the probe
returns ``[]`` cleanly without the optional header.
"""
import sys
from hermes_cli import codex_models
captured = {}
class _FakeResp:
status_code = 200
def json(self):
return {"models": []}
class _FakeHttpx:
@staticmethod
def get(url, headers=None, timeout=None):
captured["headers"] = dict(headers or {})
return _FakeResp()
monkeypatch.setitem(sys.modules, "httpx", _FakeHttpx)
models = codex_models._fetch_models_from_api(access_token="not-a-jwt")
assert "ChatGPT-Account-Id" not in captured["headers"]
assert captured["headers"]["Authorization"] == "Bearer not-a-jwt"
assert models == []
def test_model_command_uses_runtime_access_token_for_codex_list(monkeypatch):
from hermes_cli.main import _model_flow_openai_codex