Skip to content

feat: provider-agnostic balance/credits display in Hermes Desktop - #51182

Closed
DavidMetcalfe wants to merge 1 commit into
NousResearch:mainfrom
DavidMetcalfe:feat/provider-balance-display
Closed

feat: provider-agnostic balance/credits display in Hermes Desktop#51182
DavidMetcalfe wants to merge 1 commit into
NousResearch:mainfrom
DavidMetcalfe:feat/provider-balance-display

Conversation

@DavidMetcalfe

Copy link
Copy Markdown
Contributor

Closes #51175

Summary

Adds a general, provider-agnostic system for displaying AI provider balance/credit
information in the Desktop statusbar. Starts with Kilo AI; adding a new provider
is one Python file + one-line registration call — no frontend changes needed.

Backend

  • agent/balance_provider.pyBalanceProvider(ABC), ProviderBalance
    dataclass, BalanceConfig, and BalanceProviderRegistry (thread-safe,
    TTL-based caching with in-flight dedup)
  • plugins/model-providers/kilocode/balance.pyKiloBalanceProvider
    fetching GET https://api.kilo.ai/api/profile/balance
  • tui_gateway/server.py@method("balance.view") RPC handler that
    resolves the active runtime provider, merges config.yaml overrides with
    provider defaults, and returns cached or fresh balance data

Desktop Frontend

  • Statusbar item between session-timer and YOLO toggle showing the active
    provider's balance (e.g. "Kilo AI .61"). Color-coded: red when depleted,
    amber when low (< ). Click to force-refresh.
  • Auto-poll every 2 minutes + 60s registry cache TTL.
  • Fail-open: any error hides the item. Zero impact on users without Kilo
    credentials or with an unsupported provider.

Config

Optional providers.<slug>.balance: subsection in config.yaml:

providers:
  kilocode:
    balance:
      enabled: true
      cache_ttl_seconds: 60
      endpoint: https://api.kilo.ai/api/profile/balance

Extensibility

Adding OpenAI, OpenRouter, Anthropic, etc.:

  1. Create plugins/model-providers/<slug>/balance.py (~40 lines)
  2. Add BalanceProviderRegistry.register(YourBalanceProvider) to __init__.py
  3. Zero frontend changes

Review Notes

All review findings from Gemini 3.5 Flash + GPT-OSS cross-vendor audit addressed:

  • ✅ Missing { in statusbar items array (compile error — fixed)
  • cached field no longer hardcoded True
  • ✅ Race condition in cached_or_fetch (in-flight tracking added)
  • ✅ Stale balance no longer retained on fetch error
  • httpx import moved to top level
  • ✅ Redundant "Depleted + Low balance" tooltip fixed
  • ✅ Dead display property removed

@DavidMetcalfe
DavidMetcalfe force-pushed the feat/provider-balance-display branch from 7414a99 to bac2ef3 Compare June 23, 2026 03:45
@DavidMetcalfe

Copy link
Copy Markdown
Contributor Author

Known Limitation: Hardcoded low-balance threshold

The Desktop statusbar uses a hardcoded value < 5 threshold to show the amber warning icon and "Low balance" tooltip (see use-statusbar-items.tsx:414,423). This assumes the balance is in USD.

For non-USD providers (EUR, GBP) or providers that report in abstract credits (e.g. OpenRouter's credit system), this threshold will produce incorrect warnings. The currency field on ProviderBalance is already sent over the wire but isn't consumed by the frontend for threshold decisions.

Future improvement: Make the low-balance threshold configurable per-provider via providers.<slug>.balance.low_threshold in config.yaml, or include it in the backend ProviderBalance response so each provider can declare its own scale.

@alt-glitch alt-glitch added type/feature New feature or request comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/tui Terminal UI (ui-tui/ + tui_gateway/) comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have labels Jun 23, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Implements feature request #51175. Related Nous-credits family: #44776 (/credits), #40011 (usage-aware credits), #23879 (DeepSeek status-bar balance).

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Summary

Verdict: Comment (high surface area)

This PR adds a provider-agnostic balance/credits display to Hermes Desktop across 21 files (+2334 lines). The scope is broad — changes touch MCP client setup, balance calculation, desktop UI components, and configuration handling. Given the size and multi-area nature, human review is recommended before merging.

Observations

  • The api_key_env field appears to be a config lookup (not a hardcoded credential) — safe.
  • The banner error message on line 1401 is a UI string literal, not a security issue.
  • The KILOCODE_API_KEY and balance config defaults are config field references, not exposed secrets.

The changes appear reasonable but warrant a thorough review given the scope.


Reviewed by Hermes Agent

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Summary

Verdict: Comment (high surface area + prior COMMENT)

Overview

New feature: provider-agnostic balance/credits display in Hermes Desktop and Web UI. Implements BalanceProvider ABC, BalanceProviderRegistry, and the UI components to show balance in the status bar.

Surface Area Note

21 files changed with ~2,334 additions. This exceeds the surface-area threshold (15+ files or ~1000+ additions). Key areas touched:

  • agent/balance_provider.py — new ABC + registry with thread-safe caching
  • apps/desktop/ — TypeScript hooks and state management
  • web/src/ — React components, i18n, plugin registry
  • plugins/model-providers/kilocode/balance.py — first provider implementation
  • plugins/kanban/dashboard/dist/index.jspre-compiled artifact (not reviewable in diff form)

Architectural Quality

The balance provider architecture is clean: ABC pattern, thread-safe registry, cache with TTL, and per-provider subclasses. This is a good design.

Concerns

  1. Pre-compiled artifact: dist/index.js is not reviewable as a diff. Full review of the kanban dashboard changes is deferred.
  2. Surface area: The combined scope of agent ABC, desktop UI, web UI, and plugin changes is substantial. Consider whether the dashboard/kanban changes could be reviewed separately.

Prior Review Note

This PR has a prior COMMENT-only review from another session. This review adds additional observations without overwriting the prior review.


Reviewed by Hermes Agent (cron/heavy mode)

Add a general system for displaying AI provider balance/credits information
in the Desktop statusbar, starting with Kilo AI.

Backend:
- agent/balance_provider.py: BalanceProvider ABC, ProviderBalance dataclass,
  BalanceConfig, and thread-safe BalanceProviderRegistry with TTL caching
- plugins/model-providers/kilocode/balance.py: KiloBalanceProvider fetching
  GET https://api.kilo.ai/api/profile/balance
- tui_gateway/server.py: @method('balance.view') RPC handler — resolves
  the active runtime provider, merges config.yaml overrides with per-class
  defaults, and returns cached or fresh balance data

Desktop frontend:
- apps/desktop/src/types/hermes.ts: ProviderBalance and BalanceViewResponse types
- apps/desktop/src/store/provider-balance.ts: nanostore atom for balance state
- apps/desktop/src/lib/hooks/use-provider-balance.ts: React hook with 2min
  auto-poll, gateway-connect trigger, and click-to-force-refresh
- apps/desktop/src/app/shell/hooks/use-statusbar-items.tsx: statusbar item
  between session-timer and YOLO toggle (color-coded: red=depleted,
  amber=low)
- apps/desktop/src/app/desktop-controller.tsx: wired useProviderBalance

Design: provider-agnostic from day one. Adding a new provider is one Python
file + one-line BalanceProviderRegistry.register() call — no frontend changes.
Config keys under providers.<slug>.balance: { endpoint, enabled,
cache_ttl_seconds }. Fail-open on all error paths.

Closes NousResearch#51175
@DavidMetcalfe
DavidMetcalfe force-pushed the feat/provider-balance-display branch from bac2ef3 to 196ef8c Compare June 23, 2026 13:44
@DavidMetcalfe

Copy link
Copy Markdown
Contributor Author

Branch cleaned up. The previous version included 7 unrelated commits (kanban dialog work, dashboard fix) that leaked in from my fork's base branch. I've rebased onto current main — the diff is now exactly 9 files / +536 lines with only the balance feature.

This should resolve the surface-area concern. Happy to address any further review feedback.

@alt-glitch alt-glitch added comp/desktop Electron desktop app (apps/desktop/*) comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/tui Terminal UI (ui-tui/ + tui_gateway/) provider/kilo Kilo Code and removed comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels Jun 26, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused, rebased implementation.

This automated hermes-sweeper review is closing this PR under the standing in-tree-provider-integration policy:

  • The PR adds a Kilo AI-specific balance endpoint adapter at plugins/model-providers/kilocode/balance.py, supported by new core registry, gateway RPC, and Desktop UI paths.
  • AGENTS.md:126-135 directs third-party vendor integrations to standalone plugin repositories rather than the core tree, due to the ongoing maintenance burden of external API contracts.
  • The linked feature request [Feature]: Provider-agnostic balance/credits display in Hermes Desktop #51175 was already closed by @teknium1 under this same policy, including consideration of this rebased nine-file implementation and the documented currency-threshold limitation.
  • Please publish the provider-specific integration as a standalone plugin installable under ~/.hermes/plugins/ or through a pip entry point; it can be promoted in the Nous Research Discord #plugins-skills-and-skins channel.

This is a coupling-and-maintenance decision, not a judgment on the quality of the work.


Closed as not-planned per standing maintainer policy (in-tree-provider-integration). This is a design-direction decision, not a code-quality judgment — see the Contribution Rubric in AGENTS.md for what the project is looking for. If you believe this policy was misapplied to your change, comment here and a maintainer will take a look.

@teknium1 teknium1 closed this Jul 15, 2026
@teknium1 teknium1 added the sweeper:not-planned Sweeper: closed per standing maintainer policy (design direction) label Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/dashboard Web dashboard / control panel UI (dashboard/, landing) comp/desktop Electron desktop app (apps/desktop/*) comp/plugins Plugin system and bundled plugins comp/tui Terminal UI (ui-tui/ + tui_gateway/) P3 Low — cosmetic, nice to have provider/kilo Kilo Code sweeper:not-planned Sweeper: closed per standing maintainer policy (design direction) type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Provider-agnostic balance/credits display in Hermes Desktop

4 participants