Skip to content

Commit 658c854

Browse files
committed
Prefer codex rate limit bucket over spark
1 parent 99f2f94 commit 658c854

4 files changed

Lines changed: 89 additions & 3 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "codexapi"
7-
version = "0.7.2"
7+
version = "0.7.3"
88
description = "Minimal Python API for running the Codex CLI."
99
readme = "README.md"
1010
requires-python = ">=3.8"

src/codexapi/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@
2727
"task_result",
2828
"lead",
2929
]
30-
__version__ = "0.7.2"
30+
__version__ = "0.7.3"

src/codexapi/rate_limits.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def rate_limits():
3636

3737
def _extract_rate_limits(path):
3838
last = None
39+
preferred = None
3940
try:
4041
with open(path, "r", encoding="utf-8", errors="replace") as handle:
4142
for line in handle:
@@ -49,9 +50,23 @@ def _extract_rate_limits(path):
4950
rate_data = payload.get("rate_limits")
5051
if isinstance(rate_data, dict):
5152
last = rate_data
53+
if _is_primary_limit(rate_data):
54+
preferred = rate_data
5255
except OSError:
5356
return None
54-
return last
57+
return preferred or last
58+
59+
60+
def _is_primary_limit(rate_data):
61+
limit_id = rate_data.get("limit_id")
62+
if isinstance(limit_id, str):
63+
return limit_id == "codex"
64+
limit_name = rate_data.get("limit_name")
65+
if limit_name is None:
66+
return True
67+
if isinstance(limit_name, str):
68+
return not limit_name.strip()
69+
return False
5570

5671

5772
def quota_line():

tests/test_rate_limits.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import json
2+
import os
3+
import sys
4+
import tempfile
5+
import unittest
6+
from pathlib import Path
7+
8+
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
9+
10+
from codexapi.rate_limits import _extract_rate_limits
11+
12+
13+
def _write_events(path, rates):
14+
with open(path, "w", encoding="utf-8") as handle:
15+
for rate in rates:
16+
event = {"payload": {"rate_limits": rate}}
17+
handle.write(json.dumps(event))
18+
handle.write("\n")
19+
20+
21+
class RateLimitsTests(unittest.TestCase):
22+
def test_extract_prefers_codex_limit_id_when_spark_is_last(self):
23+
with tempfile.NamedTemporaryFile(delete=False) as handle:
24+
path = handle.name
25+
try:
26+
_write_events(
27+
path,
28+
[
29+
{"limit_id": "codex", "primary": {"used_percent": 3}},
30+
{
31+
"limit_id": "codex_bengalfox",
32+
"limit_name": "GPT-5.3-Codex-Spark",
33+
"primary": {"used_percent": 0},
34+
},
35+
],
36+
)
37+
found = _extract_rate_limits(path)
38+
finally:
39+
os.unlink(path)
40+
self.assertEqual(found["limit_id"], "codex")
41+
self.assertEqual(found["primary"]["used_percent"], 3)
42+
43+
def test_extract_falls_back_to_last_when_codex_missing(self):
44+
with tempfile.NamedTemporaryFile(delete=False) as handle:
45+
path = handle.name
46+
try:
47+
_write_events(
48+
path,
49+
[
50+
{"limit_id": "codex_bengalfox", "primary": {"used_percent": 1}},
51+
{"limit_id": "codex_lynx", "primary": {"used_percent": 2}},
52+
],
53+
)
54+
found = _extract_rate_limits(path)
55+
finally:
56+
os.unlink(path)
57+
self.assertEqual(found["limit_id"], "codex_lynx")
58+
59+
def test_extract_keeps_legacy_single_limit_without_limit_id(self):
60+
with tempfile.NamedTemporaryFile(delete=False) as handle:
61+
path = handle.name
62+
try:
63+
_write_events(path, [{"primary": {"used_percent": 22}}])
64+
found = _extract_rate_limits(path)
65+
finally:
66+
os.unlink(path)
67+
self.assertEqual(found["primary"]["used_percent"], 22)
68+
69+
70+
if __name__ == "__main__":
71+
unittest.main()

0 commit comments

Comments
 (0)