Skip to content

Suppress "Credit access paused" notice on free models#43669

Merged
alt-glitch merged 2 commits into
NousResearch:mainfrom
rob-maron:fix-credits-message
Jun 10, 2026
Merged

Suppress "Credit access paused" notice on free models#43669
alt-glitch merged 2 commits into
NousResearch:mainfrom
rob-maron:fix-credits-message

Conversation

@rob-maron

Copy link
Copy Markdown
Contributor

It currently causes confusion when a free or paid-with-no-credits user goes to use a free model

@rob-maron rob-maron requested review from alt-glitch and teknium1 June 10, 2026 17:19
@liuhao1024

Copy link
Copy Markdown
Contributor

Verification comment from automated review

Reviewed the diff. This correctly suppresses the "Credit access paused" notice when the active model is a Nous free-tier model (identified by :free suffix or pricing cache lookup). Key design decisions are sound:

  1. No network callsis_free_tier_model() uses only local data (:free suffix + in-process pricing cache peek). Fail-open to False on any error.
  2. No spurious "restored" notice — switching from paid→free while depleted clears the notice without emitting "Credit access restored". Only a genuine paid_access flip triggers the success notice.
  3. Re-fire on return to paid — switching back to a paid model while still depleted re-shows the depleted notice.
  4. Comprehensive tests — 5 new test scenarios cover the full state machine: suppression, clear-without-restored, re-fire, genuine recovery on free, and genuine recovery with active notice.

The _is_model_free import from hermes_cli.models is a peek-only call that never triggers a fetch, keeping it safe for hot paths. No issues found.

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/agent Core agent loop, run_agent.py, prompt builder labels Jun 10, 2026

@alt-glitch alt-glitch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Design is sound — the latch semantics are careful (no spurious "restored" on a free-model switch, depleted re-fires when switching back to a paid model, genuine recovery still emits restored), fail-open direction is right, and the zero-network guarantee is test-enforced. All 54 credits tests pass locally on this branch.

One real defect: the pricing-cache peek never fires at runtime for Nous due to a /v1 cache-key mismatch (inline comment below). The :free-suffix path carries the actual fix today, so the bug is masked rather than harmful — but the cache branch is dead code as written. One-line fix + a test using the agent-shaped base URL and this is good to merge.

Comment thread agent/credits_tracker.py Outdated
try:
from hermes_cli.models import _is_model_free, _pricing_cache

pricing = _pricing_cache.get(base_url.rstrip("/"))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: this peek never hits at runtime for Nous — /v1 cache-key mismatch.

The caller passes self.base_url, which for Nous is https://inference-api.nousresearch.com/v1 (hermes_cli/auth.py DEFAULT_NOUS_INFERENCE_URL). But _pricing_cache is keyed without /v1: get_pricing_for_provider("nous") strips a trailing /v1 before calling fetch_models_with_pricing (hermes_cli/models.py, the stripped.endswith("/v1") block), so the cache key is https://inference-api.nousresearch.com.

Verified live:

m._pricing_cache["https://inference-api.nousresearch.com"] = {"some/zero-priced": {"prompt": "0", "completion": "0"}}
is_free_tier_model("some/zero-priced", "https://inference-api.nousresearch.com/v1")  # False — agent's base_url
is_free_tier_model("some/zero-priced", "https://inference-api.nousresearch.com")     # True — picker's key

Fix: mirror the same normalization here, e.g.

key = base_url.rstrip("/")
if key.endswith("/v1"):
    key = key[:-3].rstrip("/")
pricing = _pricing_cache.get(key)

The existing tests miss this because they pass the already-stripped base — please add a case using the /v1-suffixed URL the agent actually holds.

assert is_free_tier_model("") is False
assert is_free_tier_model("Hermes-4-405B") is False

def test_pricing_cache_peek_zero_priced_model(self, monkeypatch):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth a note (comment-level, not blocking): even with the key fixed, this cache is only populated when the same process ran the model picker's pricing fetch — gateway sessions never fetch pricing, so suppression there rests entirely on the :free suffix. That's fine in practice (all Nous free SKUs carry :free), but a one-line comment in is_free_tier_model's docstring saying the cache peek is CLI-session best-effort would save the next reader the investigation.

@alt-glitch alt-glitch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both findings addressed in 2dcfdc8 — re-verified empirically:

  • /v1 key mismatch: the original repro (cache seeded under the pre-/v1 root, peek with the agent's /v1-suffixed base_url) now returns True; paid model still False.
  • Test now exercises the agent-shaped /v1 base URL plus trailing-slash variants, so a regression in the normalization would be caught.
  • Docstring notes the cache peek is CLI/TUI best-effort.

All 54 credits tests pass on the new head. LGTM.

@alt-glitch alt-glitch merged commit 6110aed into NousResearch:main Jun 10, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants