hermes-agent/website/docs/user-guide
Kyzcreig ad345a99d8 feat(gateway): add opt-in 'latency' runtime footer field
The runtime footer (`/footer`) shows what model ran and how full the context
is, but not how long the turn took. On a messaging platform there is no
progress bar and no shell timer — a turn that took 4 seconds and one that took
four minutes produce visually identical replies. Users comparing models,
providers, or reasoning levels have no at-a-glance signal for the one
dimension they most often care about, and "was that slow or did I imagine it?"
is unanswerable after the fact.

Adds a `latency` field to the existing footer machinery, rendering the
wall-clock duration of the agent run: `<1s`, `22s`, `1m05s`.

`gateway/run.py` measures with `time.monotonic()` immediately around the
`self._run_agent(...)` await in `_handle_message_with_agent` — the same
function that already builds the footer, so the value is the user-perceived
turn duration (monotonic, so it is immune to wall-clock/NTP adjustment).

`latency` is deliberately NOT in `_DEFAULT_FIELDS`. It is opt-in via
`display.runtime_footer.fields`. Every existing footer — and every footer a
user has today without touching config — renders byte-identically.

This is enforced by tests, not just asserted:

- `test_latency_not_in_default_fields` pins the default tuple.
- `test_resolve_footer_config_default_fields_exclude_latency` pins what
  config resolution produces for an untouched config.
- `test_default_footer_renders_byte_identically` pins five exact output
  strings for default-config renders **while supplying `turn_seconds`** —
  proving that even when the caller measures timing, a default-configured
  footer does not show it.
- `test_default_build_footer_line_ignores_turn_seconds` asserts
  `build_footer_line(...) == build_footer_line(..., turn_seconds=125.0)`
  under default fields.

Adding `latency` to `_DEFAULT_FIELDS` fails 11 of these tests.

No new config surface (reuses `display.runtime_footer.fields`), no new env
vars, no new core tool, no new model-facing schema. One new module-private
helper (`_format_latency`), one new keyword argument threaded through the two
existing footer functions, and 3 lines in `gateway/run.py`.

`turn_seconds` defaults to `None` and the field is skipped when it is `None`
or negative, so any call site that does not measure timing keeps working
unchanged.

`tests/gateway/test_runtime_footer.py` (+185): `_format_latency` boundary
table (sub-second, rounding at 59.4/59.6, the `m{:02d}s` zero-pad, 60m), the
render/skip/opt-in matrix, field-order placement, `build_footer_line`
threading, and the byte-stability block above.

RED-proved by mutation — each of these breaks tests:
- `latency` added to `_DEFAULT_FIELDS` → 11 failures
- dropping the `turn_seconds is not None and >= 0` guard → 2 failures
- `{sec:02d}` → `{sec}` → 6 failures
- `build_footer_line` not threading `turn_seconds` → 1 failure

51 passed in `tests/gateway/test_runtime_footer.py`; 54 passed across the
footer blast radius. `ruff check` clean.
2026-08-03 17:16:57 +05:30
..
egress Reapply "Merge pull request #30179 from NousResearch/feat/iron-proxy" 2026-07-24 09:49:00 -07:00
features fix(hooks): single delivery_id across header+body, never follow redirects 2026-08-02 15:01:11 -07:00
messaging docs(a2a): website docs page + canonical agent-card.json path in prose 2026-08-02 15:10:15 -07:00
secrets docs: accuracy sweep + coverage for 2 months of shipped features 2026-07-29 08:48:05 -07:00
skills fix(skills): match evidence quotes through markdown markup 2026-08-02 16:18:28 -07:00
_category_.json
…
checkpoints-and-rollback.md fix(checkpoints): never auto-delete orphans on unattended startup sweep 2026-07-24 16:01:06 -07:00
cli.md feat(cli): ! shell mode — run a command without spending a model turn 2026-07-31 21:21:20 -07:00
configuration.md feat(gateway): add opt-in 'latency' runtime footer field 2026-08-03 17:16:57 +05:30
configuring-models.md docs: teach providers: dict as the canonical custom-provider format 2026-07-29 09:44:59 -07:00
desktop.md feat(desktop): add terminal font picker 2026-08-01 14:30:08 -07:00
docker.md feat(runtime)!: require Node 26 across all installers, heal, and upgrade paths 2026-08-01 21:17:51 -04:00
git-worktrees.md docs(developer-guide): document htui/hgui worktree UI dev helpers (#64783) 2026-07-16 22:51:23 -04:00
import-from-other-agents.md feat(cli): hermes import-agent — import Claude Code and Codex CLI setups 2026-07-26 17:47:07 -07:00
managed-scope.md
…
multi-profile-gateways.md fix(gateway): bind HTTP auth to routed profiles 2026-07-28 14:22:18 -07:00
profile-distributions.md
…
profiles.md
…
security.md Revert "remove Vercel AI Gateway and Vercel Sandbox (#33067)" 2026-07-29 19:48:37 -07:00
sessions.md fix(state): make VACUUM interval configurable 2026-08-02 21:32:13 +05:30
tui.md fix(docs): fix broken image and video in TUI docs (#43501) 2026-07-19 19:33:03 -04:00
windows-native.md feat(runtime)!: require Node 26 across all installers, heal, and upgrade paths 2026-08-01 21:17:51 -04:00
windows-wsl-quickstart.md
…