Skip to content

feat(gateway): add opt-in token usage footer to responses - #11394

Open
Floris-Jan wants to merge 1 commit into
NousResearch:mainfrom
Floris-Jan:feat/token-usage-footer
Open

feat(gateway): add opt-in token usage footer to responses#11394
Floris-Jan wants to merge 1 commit into
NousResearch:mainfrom
Floris-Jan:feat/token-usage-footer

Conversation

@Floris-Jan

Copy link
Copy Markdown

What does this PR do?

Token data is tracked internally (session_prompt_tokens, session_completion_tokens) but only visible via explicit /usage command. Users report "token cost anxiety" — they want per-response visibility without asking.

Changes:

  • New opt-in config: display.token_usage_footer (default: false)
  • Appends compact footer after each gateway response: 📊 1.2k in · 456 out · ~$0.0234 · claude-sonnet-4
  • Gated by per-platform display config (same system as show_reasoning)
  • Skipped on failed responses

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)

Changes Made

  • gateway/run.py — after reasoning display block, before agent:end hook: reads display.token_usage_footer config (via resolve_display_setting), formats compact footer with token counts + estimated cost + model name, appends to response
  • hermes_cli/config.py — added "token_usage_footer": False to display defaults
  • tests/gateway/test_token_usage_footer.py (new) — 8 tests covering formatting (small/large counts, cost/no-cost, model name extraction) and config default verification

How to Test

  1. pytest tests/gateway/test_token_usage_footer.py -v — all 8 tests pass
  2. Set display.token_usage_footer: true in ~/.hermes/config.yaml
  3. Send a message via Telegram/Discord gateway — response should end with 📊 X in · Y out · $Z · model-name
  4. Disable config — footer disappears

Checklist

  • I've read the Contributing Guide
  • Commit follows Conventional Commits: feat(gateway): add opt-in token usage footer to responses
  • No duplicate PRs found
  • PR contains only token usage footer changes
  • pytest tests/gateway/test_token_usage_footer.py -v — 8 passed
  • Tests added
  • Tested on: Ubuntu 24.04 (WSL2)
  • Config key added to cli-config.yaml.example — N/A (no example file for gateway display keys)

Token data is tracked internally (session_prompt_tokens, etc.) but
only visible via explicit /usage command. Users report 'token cost
anxiety' — they want per-response visibility without asking.

- New config: display.token_usage_footer (default: false)
- Appends compact footer: '📊 1.2k in · 456 out · ~$0.0234 · claude-sonnet-4'
- Gated by per-platform display config (same system as show_reasoning)
- Skipped on failed responses

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the focused opt-in footer contribution. The token/cost capability is not yet present on current main, but this implementation predates the merged canonical footer system and needs a rewrite rather than a direct salvage.

Problems

  • gateway/run.py:18818-18819 populates agent_result["input_tokens"] and agent_result["output_tokens"] from cumulative session counters. The proposed reads at gateway/run.py:4032-4033 would display and price session totals after each reply, not per-response usage.
  • Current gateway/runtime_footer.py:106-118 is the canonical configurable footer renderer, merged in e123f4ecf (#17026). It supports model, context_pct, and cwd; the proposed separate display.token_usage_footer path would bypass that system and its streaming trailing-footer handling in gateway/run.py:12065-12071.
  • tests/gateway/test_token_usage_footer.py:6 copies formatter logic into a test helper, so it does not exercise the production config, result, or delivery paths.

Suggested changes

  • Extend display.runtime_footer.fields and gateway/runtime_footer.py with usage/cost fields.
  • Pass a per-turn usage delta to the renderer, then cover the real renderer and both streamed and non-streamed gateway delivery paths.

This is an automated hermes-sweeper review.

Comment thread gateway/run.py
_show_usage_footer = False

if _show_usage_footer and response and not agent_result.get("failed"):
_input_toks = agent_result.get("input_tokens", 0) or 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

agent_result["input_tokens"] is populated from the cumulative AIAgent.session_prompt_tokens counter on current main (gateway/run.py:18818-18819), so this would show a growing session total on every reply rather than the claimed per-response usage. Please plumb a per-turn usage delta before rendering or pricing it.

import pytest


def _format_usage_footer(input_tokens, output_tokens, model, cost_amount=None, cost_status="estimated"):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This helper duplicates production formatting rather than testing the gateway path. Please test the canonical footer renderer/delivery integration so config resolution, failed responses, and streamed trailing-footers are covered.

@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform area/usage-cost Token accounting, usage reporting, billing, cost tracking labels Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/usage-cost Token accounting, usage reporting, billing, cost tracking comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants