Skip to content

feat(gateway): add provider_model, context_full, and reasoning runtime footer fields - #47600

Closed
Kyzcreig wants to merge 2 commits into
NousResearch:mainfrom
ANG-Ventures:feat/footer-provider-context-fields
Closed

feat(gateway): add provider_model, context_full, and reasoning runtime footer fields#47600
Kyzcreig wants to merge 2 commits into
NousResearch:mainfrom
ANG-Ventures:feat/footer-provider-context-fields

Conversation

@Kyzcreig

@Kyzcreig Kyzcreig commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

What

Adds three new optional fields to the opt-in gateway runtime footer (/footer), and makes them the default field set:

  • provider_model — renders provider/model (e.g. claude-bridge-f3/claude-opus-4-8). When the provider is unset but the model string carries a provider/model prefix, it's split so the footer reads cleanly. Bare model with no provider renders just the model (no leading slash).
  • context_full — renders used/window (pct) (e.g. 50.2k/1M (5%)). The used count is the used and window both humanized (50.2k/1M (5%)).
  • reasoning — renders the model's reasoning-effort level as r:<level> (e.g. r:xhigh), sourced from agent.reasoning_effort (the config key /reasoning <level> writes to). Skipped silently when unset.

New default field set: [provider_model, context_full, reasoning, cwd] (was [model, context_pct, cwd]). The original model and context_pct fields are unchanged and still selectable.

Example footer:

claude-bridge-f3/claude-opus-4-8 · 50.2k/1M (5%) · r:xhigh · ~

Why

The footer previously showed only the bare model name and a context percentage. Surfacing the provider (useful behind bridges/proxies/failover where the same model is served by different providers), the absolute token occupancy alongside the percentage, and the active reasoning-effort level gives a far more useful at-a-glance runtime readout — at zero cost when disabled (footer is off by default).

How

All in the existing footer machinery — no new config surface, no new core tool, no new env vars:

  • gateway/runtime_footer.py — added provider_model, context_full, and reasoning field branches to format_runtime_footer; a provider and a reasoning kwarg threaded through build_footer_line; _split_provider_model, _humanize_tok, and _reasoning_from_config helpers. format_runtime_footer stays pure (explicit args); build_footer_line resolves reasoning from agent.reasoning_effort in the passed user_config when the caller doesn't supply it. Fields skip silently when their data is missing (no ?%/empty-slot artifacts).
  • gateway/run.py — pass provider=agent_result.get("provider") into build_footer_line (already present in agent_result). Reasoning needs no call-site change — it's config-sourced.
  • gateway/slash_commands.py — keep the /footer toggle preview's fallback field list in sync with the new default.

Config

display:
  runtime_footer:
    enabled: true                                              # off by default
    fields: [provider_model, context_full, reasoning, cwd]     # order shown; drop any to hide

All behavioral settings stay in config.yaml — no new env vars.

Tests

tests/gateway/test_runtime_footer.py: added per-field tests for provider_model (explicit / prefix-split / bare), context_full (full / no-window / no-data), reasoning (render / empty-skip / config-resolution / config-absent), _split_provider_model, _humanize_tok, and end-to-end tests reproducing the exact target footer strings. Updated the default-field assertions to the new default set. 49 passed against the upstream base.

@alt-glitch alt-glitch added type/feature New feature or request comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have labels Jun 17, 2026
@Kyzcreig
Kyzcreig force-pushed the feat/footer-provider-context-fields branch from 8b6dedb to 2073f39 Compare June 18, 2026 07:08
@Kyzcreig Kyzcreig changed the title feat(gateway): add provider_model and context_full runtime footer fields feat(gateway): add provider_model, context_full, and reasoning runtime footer fields Jun 18, 2026
@Kyzcreig
Kyzcreig force-pushed the feat/footer-provider-context-fields branch 3 times, most recently from 93f82c1 to ddfb92d Compare June 20, 2026 01:08
Kyzcreig added a commit to ANG-Ventures/hermes-agent that referenced this pull request Jun 20, 2026
WHAT: gateway/run.py now resolves _resolved_provider = getattr(_agent,
"provider", None) and includes "provider" in both _run_agent result
dicts (success path + the early/failure return). gateway/runtime_footer.py
guards _split_provider_model so a model string already carrying a
"provider/" prefix wins over a redundant passed provider (no triple
"a/b/model"). Adds the triple-collapse test case.

WHY: the runtime footer reads agent_result.get("provider"), but the
result dict only ever set "model" (bare, prefix already stripped) and
never "provider" — so provider_model silently degraded to a bare model
name on every live gateway turn (observed in Discord:
"claude-opus-4-8 · …" with no "claude-app/" prefix). Unit tests passed
provider explicitly, so the green suite never caught the missing dict key
— a classic green-in-tests / dead-on-the-gateway gap.

EFFECT: live footer now renders "claude-app/claude-opus-4-8 · …".
Confirmed live on both Apollo and Aegis gateways. 50/50 footer tests green.

This is the same change shipped to fork PR NousResearch#47600 (commit ddfb92dbb,
on a fresh-origin/main base); committing it to live fork/main so the
running gateway's behavior is reproducible and reset-proof rather than a
floating uncommitted working-tree edit.

No new config surface, no env vars, presentation-layer only.

@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 provider/model and context-footprint expansion. The feature remains useful on current main, but a salvage needs to align it with the current gateway configuration and session state.

Problems

  • hermes_cli/config.py:1922-1925 still defines the default fields as model, context_pct, and cwd; hermes_cli/cli_commands_mixin.py:2390 uses the same fallback. The diff changes neither, so the claimed new default is inconsistent.
  • The new reasoning lookup reads config only, but /reasoning <level> is session-scoped by default (gateway/slash_commands.py:2643-2645, 2754) and effective resolution checks _session_reasoning_overrides first (gateway/run.py:4835-4852). The footer can therefore report a stale/global value rather than the active session setting.
  • The changed gateway /footer preview fallback omits reasoning, despite the PR declaring it part of the default set.
  • website/docs/user-guide/configuration.md:1474-1485 and website/docs/reference/slash-commands.md:80 still document only the original fields; this diff contains no documentation update.

Suggested changes

  • Make config defaults, CLI/gateway fallbacks, preview, and docs agree.
  • Thread the effective session reasoning configuration into the footer and add a session-override regression test. Open #63812 already targets that resolution path.

Automated hermes-sweeper review.

Comment thread gateway/runtime_footer.py Outdated
@@ -140,10 +224,16 @@ def build_footer_line(
cfg = resolve_footer_config(user_config, platform_key)
if not cfg.get("enabled"):
return ""
# Reasoning effort comes from config (agent.reasoning_effort); caller may
# override with a live value if it ever has one.

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 reads only persisted config, but /reasoning <level> is session-scoped by default and stored in _session_reasoning_overrides (gateway/run.py:4835-4852). Thread the active session's resolved reasoning configuration through the footer call so this displays the value actually selected for the turn.

Comment thread gateway/slash_commands.py
@@ -2478,7 +2478,7 @@ async def _handle_footer_command(self, event: MessageEvent) -> str:
model=_resolve_gateway_model(user_config) or None,

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.

The new fallback omits reasoning, while _DEFAULT_FIELDS in this PR includes it. Use the same shared default contract so /footer on preview does not disagree with the rendered default footer.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades 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 labels Jul 14, 2026
Kyzcreig added 2 commits July 26, 2026 06:27
…e footer fields

Add three optional fields to the opt-in /footer runtime footer:

- provider_model: provider/model (the model's own provider/ prefix is authoritative; a separately-supplied provider is ignored to avoid a triple prefix)

- context_full: humanized used/window (pct), e.g. 50.2k/1M (5%)

- reasoning: model reasoning-effort level as r:<level>, sourced from agent.reasoning_effort

Also thread the resolved provider through the _run_agent result dict so the footer can render provider_model (the result previously carried model but not provider, so provider_model degraded to a bare model name).

New default field set [provider_model, context_full, reasoning, cwd]; model and context_pct remain selectable. Fields skip silently when data is missing. No new config surface or env vars.
…ion reasoning

Follow-up to the sweeper review on this PR. Four changes:

1. Keep _DEFAULT_FIELDS as ("model", "context_pct", "cwd"). The three new
   fields (provider_model, context_full, reasoning) are opt-in via
   display.runtime_footer.fields. This resolves the review's inconsistency
   finding at its root: hermes_cli/config.py, cli_commands_mixin.py, and the
   /footer preview fallback all already say model/context_pct/cwd, and now
   agree with the module default — nothing to re-sync. It also means every
   existing footer renders byte-identically.

2. Resolve `reasoning` through the shared chokepoint
   hermes_constants.resolve_reasoning_config instead of reading
   agent.reasoning_effort raw, so per-model overrides
   (agent.reasoning_overrides) and the YAML-boolean "disabled" spelling are
   honored exactly as the agent honors them.

3. Thread the session-effective reasoning config into the footer:
   gateway/run.py now passes _resolve_session_reasoning_config(...) as
   build_footer_line(reasoning_config=...), so a session-scoped
   `/reasoning <level>` is reported rather than a stale global value.

4. Document the full field table in
   website/docs/user-guide/configuration.md and update the /footer row in
   website/docs/reference/slash-commands.md.

Tests: byte-stability tests pinning default-config output to the exact
pre-change strings, plus session-override and per-model-override regression
tests. All three behaviors RED-proved by mutation. 61 passed in
tests/gateway/test_runtime_footer.py; 92 passed across the footer/reasoning
blast radius.
@Kyzcreig

Kyzcreig commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #80661, which re-ports this feature onto current main.

This branch had drifted ~2.9k commits behind and hard-conflicted with two upstream changes (the latency footer field and the TurnRunner extraction in gateway/run.py), so I re-applied it cleanly on top of both — same three opt-in fields, same review-response behavior (default field set unchanged, session-scoped /reasoning honored), now coexisting with latency. Closing to keep the queue honest; review belongs on #80661. Thanks!

@Kyzcreig Kyzcreig closed this Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades 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