diff --git a/src/gibby/client.py b/src/gibby/client.py index 80d612a..94ce40b 100644 --- a/src/gibby/client.py +++ b/src/gibby/client.py @@ -1,6 +1,7 @@ from __future__ import annotations import json +import logging import httpx @@ -10,6 +11,8 @@ from gibby.settings import Settings MODELS_URL = "https://chatgpt.com/backend-api/codex/models" +logger = logging.getLogger(__name__) + class OpenAIAPIError(RuntimeError): def __init__( @@ -104,7 +107,17 @@ class OpenAIClient: return parse_usage_payload(await self.fetch_usage_payload(access_token)) async def validate_token(self, access_token: str) -> bool: - response = await self.http_client.get(MODELS_URL, headers=self._headers(access_token)) + response = await self.http_client.get( + MODELS_URL, + headers=self._headers(access_token), + params={"client_version": "2.3.9"}, + ) + if response.status_code != 200: + logger.warning( + "token validation failed: status=%s body=%s", + response.status_code, + _extract_error_text(response), + ) return response.status_code == 200 @staticmethod diff --git a/src/gibby/manager.py b/src/gibby/manager.py index fbd9c85..5897bd0 100644 --- a/src/gibby/manager.py +++ b/src/gibby/manager.py @@ -29,10 +29,29 @@ class AccountManager: while True: state = self.store.load() if not state.accounts: + logger.error("no usable account available: no accounts in state file") raise NoUsableAccountError("No usable account available") account = await self._select_account(state) if account is None: + logger.error( + "no usable account available: active_account=%s accounts=%s", + state.active_account, + [ + { + "email": item.email, + "disabled": item.disabled, + "usage_checked_at": item.usage_checked_at, + "primary": item.usage.primary_window.used_percent + if item.usage and item.usage.primary_window + else None, + "secondary": item.usage.secondary_window.used_percent + if item.usage and item.usage.secondary_window + else None, + } + for item in state.accounts + ], + ) raise NoUsableAccountError("No usable account available") state = self.store.load()