Implement LLM-WP-0008: provider-scoped account balance CLI
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Add pluggable balance registry, OpenRouter credits/key limit client,
and llm-connect balance with one-shot --provider that does not change
library defaults.
This commit is contained in:
tegwick 2026-08-03 23:49:01 +02:00
parent c0d5c4ad08
commit ed7c632155
11 changed files with 783 additions and 14 deletions

View file

@ -113,6 +113,74 @@ def test_cost_estimate_cli(capsys):
assert payload["cost_eur"] == 0.018
def test_balance_cli_json(monkeypatch, capsys):
from llm_connect.balance import AccountBalance
def fake_get_balance(provider=None, *, registry=None, fx=None):
assert provider is None # default path
return AccountBalance(
provider="openrouter",
currency="USD",
source="openrouter:/api/v1/credits+auth/key",
credits_remaining=12.5,
credits_remaining_eur=11.5,
limit_remaining=9.5,
limit_remaining_eur=8.74,
limit=10.0,
limit_reset="monthly",
fx_source="explicit",
)
monkeypatch.setattr("llm_connect.cli.get_account_balance", fake_get_balance)
assert main(["balance", "--json"]) == 0
payload = json.loads(capsys.readouterr().out)
assert payload["provider"] == "openrouter"
assert payload["credits_remaining"] == 12.5
assert payload["limit_remaining"] == 9.5
def test_balance_cli_explicit_provider_one_shot(monkeypatch, capsys):
from llm_connect.balance import AccountBalance
from llm_connect.config import LLMConfig
from llm_connect.openrouter import _DEFAULT_MODEL
seen = {}
def fake_get_balance(provider=None, *, registry=None, fx=None):
seen["provider"] = provider
return AccountBalance(
provider="openrouter",
currency="USD",
source="test",
credits_remaining=1.0,
)
before_provider = LLMConfig().provider
before_model = _DEFAULT_MODEL
monkeypatch.setattr("llm_connect.cli.get_account_balance", fake_get_balance)
assert main(["balance", "--provider", "openrouter"]) == 0
assert seen["provider"] == "openrouter"
assert LLMConfig().provider == before_provider
assert _DEFAULT_MODEL == before_model
assert "account credits remaining" in capsys.readouterr().out
def test_balance_cli_unsupported_provider(monkeypatch, capsys):
from llm_connect.exceptions import LLMBalanceUnsupportedError
def boom(provider=None, *, registry=None, fx=None):
raise LLMBalanceUnsupportedError(
"not supported",
provider=provider or "",
supported=["openrouter"],
)
monkeypatch.setattr("llm_connect.cli.get_account_balance", boom)
assert main(["balance", "--provider", "gemini"]) == 2
err = capsys.readouterr().err
assert "not supported" in err
def test_spend_week_current_and_last(tmp_path, capsys, monkeypatch):
ledger_path = tmp_path / "usage.jsonl"
ledger = UsageLedger(ledger_path)