From dd3bd70f35a11773447f94c1dd4659de9aff704a Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Wed, 22 Jul 2026 18:09:08 -0500 Subject: [PATCH] feat(cli): out-of-credits panel below the response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pin a provider-agnostic "Out of credits" panel after a billing-classified turn so the one recovery action (Nous → /topup, other providers → their billing page) stays visible instead of scrolling away as prose. --- cli.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/cli.py b/cli.py index b9641e53ee20..e0278dee40e8 100644 --- a/cli.py +++ b/cli.py @@ -12607,6 +12607,41 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin): width=self._scrollback_box_width(), )) + # Durable, provider-agnostic billing CTA below the response. The + # response panel carries the full guidance; this pins the single + # action to take (Nous → /topup, other providers → their billing + # page) so it stays visible instead of scrolling away as prose. + if result and result.get("failure_reason") == "billing": + _bb = result.get("billing_block") or {} + _prov_label = _bb.get("provider_label") or "your provider" + if _bb.get("is_nous"): + _cta_lines = [ + "Run [bold]/topup[/] to add credits, or " + "[bold]/subscription[/] to change plan.", + ] + else: + _url = _bb.get("billing_url") + _cta_lines = [ + f"Add credits with {_prov_label}" + + (f": [bold]{_url}[/]" if _url else ".") + ] + _cta_lines.append( + "Or switch providers with " + "[bold]/model --provider [/]." + ) + try: + ChatConsole().print(Panel( + "\n".join(_cta_lines), + title="[#CD7F32 bold]⚡ Out of credits[/]", + title_align="left", + border_style="#CD7F32", + box=rich_box.HORIZONTALS, + padding=(1, 4), + width=self._scrollback_box_width(), + )) + except Exception: + pass + # Play terminal bell when agent finishes (if enabled). # Works over SSH — the bell propagates to the user's terminal.