diff --git a/skillopt/model/codex_backend.py b/skillopt/model/codex_backend.py index ff7f79cd..09149093 100644 --- a/skillopt/model/codex_backend.py +++ b/skillopt/model/codex_backend.py @@ -12,13 +12,13 @@ from typing import Any from urllib.parse import unquote, urlparse +from skillopt.model.backend_config import get_codex_exec_config from skillopt.model.common import ( CompatAssistantMessage, CompatToolCall, CompatToolFunction, - tracker, + TokenTracker, ) -from skillopt.model.backend_config import get_codex_exec_config CODEX_BIN = os.environ.get("CODEX_CLI_BIN", "codex") @@ -29,6 +29,7 @@ TARGET_DEPLOYMENT = os.environ.get("TARGET_DEPLOYMENT", "gpt-4o") REASONING_EFFORT: str | None = None +tracker = TokenTracker() def _default_working_directory() -> str: diff --git a/tests/test_codex_optimizer_backend.py b/tests/test_codex_optimizer_backend.py index 8701a0e9..c0b6bfd8 100644 --- a/tests/test_codex_optimizer_backend.py +++ b/tests/test_codex_optimizer_backend.py @@ -251,6 +251,35 @@ def test_token_summary_merges_codex_once_with_existing_backends( assert summary["_total"]["total_tokens"] == 36 +def test_codex_usage_is_not_double_counted_by_shared_tracker( + isolate_backend_state: tuple[Any, Any, Any, Any], +) -> None: + model_module, _backend_config, codex_backend, _azure_openai = isolate_backend_state + from skillopt.model import claude_backend + + model_module.reset_token_tracker() + try: + assert codex_backend.tracker is not claude_backend.tracker + + codex_backend.tracker.record("optimizer", 11, 13) + summary = model_module.get_token_summary() + + assert summary["optimizer"] == { + "calls": 1, + "prompt_tokens": 11, + "completion_tokens": 13, + "total_tokens": 24, + } + assert summary["_total"] == { + "calls": 1, + "prompt_tokens": 11, + "completion_tokens": 13, + "total_tokens": 24, + } + finally: + model_module.reset_token_tracker() + + def test_reset_token_tracker_resets_codex_and_existing_backends( monkeypatch: pytest.MonkeyPatch, isolate_backend_state: tuple[Any, Any, Any, Any],