v3 M2: OpenAI Codex provider — real rate-limit % from local Codex rollouts

OpenAICodexProvider replaces the openai stub. It reads the rate-limit snapshot
the Codex CLI already records locally (no second auth): each turn Codex writes a
token_count event into $CODEX_HOME/sessions/**/rollout-*.jsonl whose
payload.rate_limits mirrors Claude's model — primary (5h) + secondary (weekly),
each with used_percent + resets_at + plan_type. The provider surfaces the
freshest such snapshot; a window whose reset time has passed is reported as a
fresh 0% (local read, so current in-session and self-heals between sessions).

primary -> s/sr, secondary -> w/wr, plan_type -> status ("Plus"/…),
rate_limit_reached_type -> "limited". No per-token cost (subscription), so the
two rate-limit bars are the metric, per the locked v3 decision.

Verified against the real ~/.codex: full daemon payload with openai active =
{pv:openai, pnm:"OpenAI Codex", ac:0x10a37f, st:"Plus", ok:true, weekly reset}.
registry test updated (openai now real, zai still stub); +7 provider tests.
113 passed, 2 Linux-only failures (baseline). spec: hiddenimport added.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wenil
2026-07-10 07:14:15 +03:00
co-authored by Claude Opus 4.8
parent a975eb434b
commit b63a6a62ae
5 changed files with 247 additions and 5 deletions
+7 -3
View File
@@ -9,7 +9,8 @@ import asyncio
import json
from daemon import config
from daemon.providers import get_provider, AnthropicProvider, StubProvider, ProviderStatus
from daemon.providers import (
get_provider, AnthropicProvider, OpenAICodexProvider, StubProvider, ProviderStatus)
def _run(coro):
@@ -68,9 +69,12 @@ def test_enabled_providers_respects_order_and_flag(tmp_path, monkeypatch):
def test_registry_types():
a = get_provider("anthropic")
assert isinstance(a, AnthropicProvider) and a.id == "anthropic"
stub = get_provider("openai")
o = get_provider("openai")
assert isinstance(o, OpenAICodexProvider)
assert o.id == "openai" and o.accent == "10a37f"
stub = get_provider("zai") # z.ai is still a stub until M3
assert isinstance(stub, StubProvider)
assert stub.id == "openai" and stub.accent == "10a37f"
assert stub.id == "zai" and stub.accent == "3859ff"
def test_stub_provider_poll_is_safe():