From e01b04de466d28ccba145868fc81ddd8296d8131 Mon Sep 17 00:00:00 2001 From: alt-glitch Date: Sat, 13 Jun 2026 19:16:44 +0530 Subject: [PATCH] fix(tui): chrome cost from Nous portal headers only (F3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The status-bar cost segment must show cost ONLY when running against the Nous portal — per-model cache/input/output pricing is unreliable across the model long tail, so a guessed figure is worse than none. - New nous_header_cost_usd(agent): the chrome cost source, derived ONLY from the x-nous-credits-* header delta (deliberately ignores the OpenRouter usage.cost accumulator). _get_usage now uses it for cost_usd, so a non-Nous session reports no cost and the TUI hides the segment. - The /usage accounting page is unchanged in spirit: it now reads real_session_cost_usd(agent) directly (both provider-reported sources) instead of the chrome-narrowed _get_usage cost_usd, so OpenRouter cost still shows there. Tests: new TestNousHeaderCost (header-only, OR-accumulator ignored, clamp, no-method); updated gateway _get_usage tests for the chrome narrowing; /usage page test still asserts the full provider-reported figure. 316 gateway + 25 cost tests green. --- agent/usage_pricing.py | 27 ++++++++++++++++++++++ tests/agent/test_provider_cost_capture.py | 28 ++++++++++++++++++++++- tests/test_tui_gateway_server.py | 11 ++++++--- tui_gateway/server.py | 27 ++++++++++++++++------ 4 files changed, 82 insertions(+), 11 deletions(-) diff --git a/agent/usage_pricing.py b/agent/usage_pricing.py index 33ebd229862..0c496839833 100644 --- a/agent/usage_pricing.py +++ b/agent/usage_pricing.py @@ -919,6 +919,33 @@ def real_session_cost_usd(agent: Any) -> Optional[float]: return total +def nous_header_cost_usd(agent: Any) -> Optional[float]: + """Session-cumulative cost in USD derived ONLY from the Nous portal + ``x-nous-credits-*`` header delta, or None. + + This is the STATUS-BAR cost source (glitch 2026-06-13, F3): the TUI chrome + must show cost ONLY when the session runs against the Nous portal, because + the header delta is the one figure we can trust without re-deriving per-model + cache/input/output pricing (which is unreliable across the model long tail). + Unlike :func:`real_session_cost_usd`, this DELIBERATELY ignores the + OpenRouter ``usage.cost`` accumulator — a non-Nous route reports no header, + so the chrome hides its cost segment entirely. + + The ``/usage`` accounting page keeps using ``real_session_cost_usd`` (both + provider-reported sources); only the chrome bar narrows to header-only. + """ + try: + spent_micros = agent.get_credits_spent_micros() + except Exception: + return None + if spent_micros is None: + return None + try: + return max(0, int(spent_micros)) / 1_000_000 + except (TypeError, ValueError): + return None + + def has_known_pricing( model_name: str, provider: Optional[str] = None, diff --git a/tests/agent/test_provider_cost_capture.py b/tests/agent/test_provider_cost_capture.py index 73df27b4044..a1e27691ce1 100644 --- a/tests/agent/test_provider_cost_capture.py +++ b/tests/agent/test_provider_cost_capture.py @@ -10,7 +10,7 @@ from types import SimpleNamespace import pytest -from agent.usage_pricing import extract_provider_cost_usd, real_session_cost_usd +from agent.usage_pricing import extract_provider_cost_usd, nous_header_cost_usd, real_session_cost_usd # ── extract_provider_cost_usd — the per-response REAL cost reader ──────────── @@ -86,6 +86,32 @@ class TestRealSessionCost: assert real_session_cost_usd(agent) is None +# ── nous_header_cost_usd — the CHROME status-bar cost (F3: header-only) ────── + + +class TestNousHeaderCost: + def test_header_delta_only(self): + # 123_400 micros = $0.1234 — the Nous header source feeds the chrome. + assert nous_header_cost_usd(_FakeAgent(credits_micros=123_400)) == pytest.approx(0.1234) + + def test_openrouter_accumulator_ignored(self): + # The OpenRouter usage.cost accumulator must NOT feed the chrome bar: + # a non-Nous session (no header → None) reports no cost even when the + # OpenRouter accumulator has a value. + assert nous_header_cost_usd(_FakeAgent(actual=0.42)) is None + + def test_no_header_is_none(self): + assert nous_header_cost_usd(_FakeAgent()) is None + + def test_negative_delta_clamped(self): + # A mid-session top-up makes the delta negative — never show negative. + assert nous_header_cost_usd(_FakeAgent(credits_micros=-50_000)) == 0.0 + + def test_agent_without_credits_method_is_none(self): + agent = SimpleNamespace(session_actual_cost_usd=0.42) + assert nous_header_cost_usd(agent) is None + + # ── Nous header fixture → real accumulator (full _capture_credits path) ───── diff --git a/tests/test_tui_gateway_server.py b/tests/test_tui_gateway_server.py index 886744d6880..176dc837047 100644 --- a/tests/test_tui_gateway_server.py +++ b/tests/test_tui_gateway_server.py @@ -7444,11 +7444,15 @@ def test_get_usage_cost_absent_when_provider_reports_nothing(monkeypatch): assert usage["input"] == 35_000 -def test_get_usage_cost_present_when_provider_reported(monkeypatch): +def test_get_usage_cost_absent_for_openrouter_accumulator_chrome(monkeypatch): + """F3: the chrome status bar shows cost ONLY from the Nous header delta. + An OpenRouter usage.cost accumulator alone (no x-nous-credits header) must + NOT surface cost_usd in _get_usage — the chrome hides cost off-Nous. (The + /usage accounting page still counts the accumulator; that's a separate path.) + """ agent = _usage_agent(session_actual_cost_usd=0.4321) usage = server._get_usage(agent) - assert usage["cost_usd"] == pytest.approx(0.4321) - assert usage["cost_status"] == "actual" + assert "cost_usd" not in usage def test_get_usage_cost_from_nous_credits_delta(monkeypatch): @@ -7456,6 +7460,7 @@ def test_get_usage_cost_from_nous_credits_delta(monkeypatch): agent.get_credits_spent_micros = lambda: 250_000 # $0.25 real header delta usage = server._get_usage(agent) assert usage["cost_usd"] == pytest.approx(0.25) + assert usage["cost_status"] == "actual" def test_compact_usage_per_model_rows_and_real_cost(monkeypatch): diff --git a/tui_gateway/server.py b/tui_gateway/server.py index 9364dd2c07a..aa4a599849b 100644 --- a/tui_gateway/server.py +++ b/tui_gateway/server.py @@ -2154,14 +2154,17 @@ def _get_usage(agent) -> dict: usage["context_max"] = ctx_max usage["context_percent"] = max(0, min(100, round(ctx_used / ctx_max * 100))) usage["compressions"] = getattr(comp, "compression_count", 0) or 0 - # Cost: provider-REPORTED only (OpenRouter usage.cost accumulator and/or - # the Nous x-nous-credits-* header delta). Never estimated. When nothing - # was reported `cost_usd` is ABSENT (not $0.00) and the TUI hides its - # cost segment — that's the intended UX. + # Cost (chrome status bar): Nous portal header delta ONLY (F3, glitch + # 2026-06-13). The OpenRouter usage.cost accumulator is deliberately NOT + # used here — per-model cache/input/output pricing is unreliable across the + # model long tail, so the bar shows cost ONLY on a Nous-portal session and + # hides it everywhere else. `cost_usd` is ABSENT (not $0.00) when no header + # was seen, and the TUI hides its cost segment. (The /usage accounting page + # still uses real_session_cost_usd — both provider-reported sources.) try: - from agent.usage_pricing import real_session_cost_usd + from agent.usage_pricing import nous_header_cost_usd - real_cost = real_session_cost_usd(agent) + real_cost = nous_header_cost_usd(agent) if real_cost is not None: usage["cost_usd"] = real_cost usage["cost_status"] = "actual" @@ -2234,7 +2237,17 @@ def _compact_usage_text(session: dict) -> str: tail.append(f"compressions {u['compressions']}") lines.append(" " + " · ".join(tail)) - cost_usd = u.get("cost_usd") + # The /usage page reports the FULL provider-reported cost (OpenRouter + # usage.cost accumulator AND/OR the Nous header delta) — NOT the chrome's + # Nous-header-only figure (F3 narrowed `_get_usage["cost_usd"]` to the + # status bar). Read it straight from real_session_cost_usd here so the + # accounting page keeps both sources. + try: + from agent.usage_pricing import real_session_cost_usd + + cost_usd = real_session_cost_usd(agent) + except Exception: + cost_usd = None if cost_usd is not None: lines.append(f" session cost: ${cost_usd:.4f} (provider-reported)") else: