feat(gateway): add /context command for a detailed context-window view - #52184
feat(gateway): add /context command for a detailed context-window view#52184CharlesMcquade wants to merge 1 commit into
Conversation
|
Reviewed this PR end-to-end. The feature shape looks good and the rest of the diff is solid: command registration, mid-turn gateway dispatch, localization strings, and targeted coverage all line up with the existing gateway patterns. I found one current-main merge issue: I tried to push a small maintainer fix directly to this branch, but GitHub denied my token push to the fork even though maintainer edits are enabled. I pushed the fix here instead: CharlesMcquade#1 The fix is intentionally minimal:
Verification I ran:
Once that small fix lands on this PR branch, I’m satisfied with the PR and would approve. |
|
Thanks for the thorough review and the fix @whoislikemiha — landed it in |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused gateway command and the follow-up async SessionDB/sentinel fixes. /context is not present on current main, so the feature remains independently useful, but it needs two current-main adjustments before salvage.
Problems
gateway/slash_commands.py:3618and:3748call synchronoussession_storemethods from the async handler. Current main's9d38a2309enforcesasync_session_storefor this boundary; current/usageawaits it atgateway/slash_commands.py:4064-4065.gateway/slash_commands.py:3714-3726restores cache read/write and hit-rate output. Commit446b8e239intentionally removed cache reporting from every user-facing surface because providers that omit cached-token details produce misleading values.
Suggested changes
- Use awaited
async_session_storecalls for the session entry and transcript fallback. - Keep the context gauge/compression view, but remove cache-hit reporting and its strings/tests.
Automated hermes-sweeper review.
| from gateway.run import _AGENT_PENDING_SENTINEL | ||
| source = event.source | ||
| session_key = self._session_key_for_source(source) | ||
| session_entry = self.session_store.get_or_create_session(source) |
There was a problem hiding this comment.
Current main requires async gateway handlers to use await self.async_session_store.get_or_create_session(source) (commit 9d38a2309); calling the synchronous store here bypasses the enforced off-loop boundary. Apply the same change to the transcript fallback below.
| if savings is not None: | ||
| lines.append(t("gateway.context.last_savings", savings=f"{savings:.0f}")) | ||
|
|
||
| cache_read = getattr(agent, "session_cache_read_tokens", 0) or 0 |
There was a problem hiding this comment.
Please do not restore cache read/write or hit-rate reporting. Current main removed these values from every user-facing surface in 446b8e239 because providers that omit cached-token details produce misleading cache results.
A dedicated /context (alias /ctx) gateway slash command that gives a full context-window view with: - Usage gauge: visual bar + fraction + percentage + headroom - Auto-compression threshold and how far away it is - Compression count and how much the last one freed - Cumulative session throughput (explicitly labelled as throughput, NOT context size — each call re-sends the window) - Cascading fallback: running agent → cached agent → SessionStore metadata → rough transcript estimate Not included (per current-main design): - Cache reporting removed: commit 446b8e2 intentionally removed cache reporting from user-facing surfaces because providers that omit cached-token details produce misleading values - Sync DB calls replaced with async_session_store (current main requires AsyncSessionStore with await) Also rewords the /status tokens line from 'Cumulative API tokens (re-sent each call)' to 'Lifetime tokens billed: ... (not your current context size; use /context)' to reduce the recurring confusion that the cumulative figure is the current context window. Fixes salvation of PR NousResearch#52184 (salvage commit replaces a 12K-commit-behind fork branch with a fresh implementation against current main, incorporating reviewer feedback from @whoislikemiha and the hermes-sweeper).
7737918 to
656856e
Compare
|
Both points from the review are already addressed in the current branch head (
All 21 tests in |
A dedicated /context (alias /ctx) gateway slash command that gives a full context-window view with: - Usage gauge: visual bar + fraction + percentage + headroom - Auto-compression threshold and how far away it is - Compression count and how much the last one freed - Cumulative session throughput (explicitly labelled as throughput, NOT context size — each call re-sends the window) - Cascading fallback: running agent → cached agent → SessionStore metadata → rough transcript estimate Not included (per current-main design): - Cache reporting removed: commit 446b8e2 intentionally removed cache reporting from user-facing surfaces because providers that omit cached-token details produce misleading values - Sync DB calls replaced with async_session_store (current main requires AsyncSessionStore with await) Also rewords the /status tokens line from 'Cumulative API tokens (re-sent each call)' to 'Lifetime tokens billed: ... (not your current context size; use /context)' to reduce the recurring confusion that the cumulative figure is the current context window. Fixes salvation of PR #52184 (salvage commit replaces a 12K-commit-behind fork branch with a fresh implementation against current main, incorporating reviewer feedback from @whoislikemiha and the hermes-sweeper).
Extends the cherry-picked /context command (PR #52184) and prompt-size attribution helpers (PR #66656) into one visual context view across surfaces, and absorbs the per-component budget-visibility goal of the /tokens proposal (PR #48470): - agent/context_breakdown.py: pure renderers over the existing payload — a 5x20 glyph block grid (1 cell ~= 1% of the model window), an 'Estimated usage by category' table with free space, and expanded per-skill / per-toolset listings via compute_context_details(), which reuses the prompt-size attribution mechanism (skills index-line bytes + registry tool->toolset map) converted to the same chars/4 heuristic. - cli.py: /context [all] renders grid + category table (+ expanded listings) from the live agent and in-memory conversation history. - gateway/slash_commands.py: /context appends the plain-text category table (no grid — monospace not guaranteed on messaging platforms); /context all adds the expanded listings. Fail-open: breakdown errors never break the gauge. - hermes_cli/commands.py: /context gains the 'all' subcommand; /version demoted to /hermes version on Slack to keep the 50-slash cap. - tests: renderer unit tests against synthetic payloads, registry test, gateway /context + /context all + failure-degradation handler tests. - docs: slash-commands reference + CLI guide entries. Read-only and locally computed: no provider calls, no prompt-cache impact. Co-authored-by: RemyFevry <29257684+RemyFevry@users.noreply.github.com> Co-authored-by: joelbrilliant <joelbrilliant1@gmail.com> Co-authored-by: CharlesMcquade <6466275+CharlesMcquade@users.noreply.github.com>
A dedicated /context (alias /ctx) gateway slash command that gives a full context-window view with: - Usage gauge: visual bar + fraction + percentage + headroom - Auto-compression threshold and how far away it is - Compression count and how much the last one freed - Cumulative session throughput (explicitly labelled as throughput, NOT context size — each call re-sends the window) - Cascading fallback: running agent → cached agent → SessionStore metadata → rough transcript estimate Not included (per current-main design): - Cache reporting removed: commit 446b8e2 intentionally removed cache reporting from user-facing surfaces because providers that omit cached-token details produce misleading values - Sync DB calls replaced with async_session_store (current main requires AsyncSessionStore with await) Also rewords the /status tokens line from 'Cumulative API tokens (re-sent each call)' to 'Lifetime tokens billed: ... (not your current context size; use /context)' to reduce the recurring confusion that the cumulative figure is the current context window. Fixes salvation of PR #52184 (salvage commit replaces a 12K-commit-behind fork branch with a fresh implementation against current main, incorporating reviewer feedback from @whoislikemiha and the hermes-sweeper).
Extends the cherry-picked /context command (PR #52184) and prompt-size attribution helpers (PR #66656) into one visual context view across surfaces, and absorbs the per-component budget-visibility goal of the /tokens proposal (PR #48470): - agent/context_breakdown.py: pure renderers over the existing payload — a 5x20 glyph block grid (1 cell ~= 1% of the model window), an 'Estimated usage by category' table with free space, and expanded per-skill / per-toolset listings via compute_context_details(), which reuses the prompt-size attribution mechanism (skills index-line bytes + registry tool->toolset map) converted to the same chars/4 heuristic. - cli.py: /context [all] renders grid + category table (+ expanded listings) from the live agent and in-memory conversation history. - gateway/slash_commands.py: /context appends the plain-text category table (no grid — monospace not guaranteed on messaging platforms); /context all adds the expanded listings. Fail-open: breakdown errors never break the gauge. - hermes_cli/commands.py: /context gains the 'all' subcommand; /version demoted to /hermes version on Slack to keep the 50-slash cap. - tests: renderer unit tests against synthetic payloads, registry test, gateway /context + /context all + failure-degradation handler tests. - docs: slash-commands reference + CLI guide entries. Read-only and locally computed: no provider calls, no prompt-cache impact. Co-authored-by: RemyFevry <29257684+RemyFevry@users.noreply.github.com> Co-authored-by: joelbrilliant <joelbrilliant1@gmail.com> Co-authored-by: CharlesMcquade <6466275+CharlesMcquade@users.noreply.github.com>
A dedicated /context (alias /ctx) gateway slash command that gives a full context-window view with: - Usage gauge: visual bar + fraction + percentage + headroom - Auto-compression threshold and how far away it is - Compression count and how much the last one freed - Cumulative session throughput (explicitly labelled as throughput, NOT context size — each call re-sends the window) - Cascading fallback: running agent → cached agent → SessionStore metadata → rough transcript estimate Not included (per current-main design): - Cache reporting removed: commit 446b8e2 intentionally removed cache reporting from user-facing surfaces because providers that omit cached-token details produce misleading values - Sync DB calls replaced with async_session_store (current main requires AsyncSessionStore with await) Also rewords the /status tokens line from 'Cumulative API tokens (re-sent each call)' to 'Lifetime tokens billed: ... (not your current context size; use /context)' to reduce the recurring confusion that the cumulative figure is the current context window. Fixes salvation of PR #52184 (salvage commit replaces a 12K-commit-behind fork branch with a fresh implementation against current main, incorporating reviewer feedback from @whoislikemiha and the hermes-sweeper).
Extends the cherry-picked /context command (PR #52184) and prompt-size attribution helpers (PR #66656) into one visual context view across surfaces, and absorbs the per-component budget-visibility goal of the /tokens proposal (PR #48470): - agent/context_breakdown.py: pure renderers over the existing payload — a 5x20 glyph block grid (1 cell ~= 1% of the model window), an 'Estimated usage by category' table with free space, and expanded per-skill / per-toolset listings via compute_context_details(), which reuses the prompt-size attribution mechanism (skills index-line bytes + registry tool->toolset map) converted to the same chars/4 heuristic. - cli.py: /context [all] renders grid + category table (+ expanded listings) from the live agent and in-memory conversation history. - gateway/slash_commands.py: /context appends the plain-text category table (no grid — monospace not guaranteed on messaging platforms); /context all adds the expanded listings. Fail-open: breakdown errors never break the gauge. - hermes_cli/commands.py: /context gains the 'all' subcommand; /version demoted to /hermes version on Slack to keep the 50-slash cap. - tests: renderer unit tests against synthetic payloads, registry test, gateway /context + /context all + failure-degradation handler tests. - docs: slash-commands reference + CLI guide entries. Read-only and locally computed: no provider calls, no prompt-cache impact. Co-authored-by: RemyFevry <29257684+RemyFevry@users.noreply.github.com> Co-authored-by: joelbrilliant <joelbrilliant1@gmail.com> Co-authored-by: CharlesMcquade <6466275+CharlesMcquade@users.noreply.github.com>
A dedicated /context (alias /ctx) gateway slash command that gives a full context-window view with: - Usage gauge: visual bar + fraction + percentage + headroom - Auto-compression threshold and how far away it is - Compression count and how much the last one freed - Cumulative session throughput (explicitly labelled as throughput, NOT context size — each call re-sends the window) - Cascading fallback: running agent → cached agent → SessionStore metadata → rough transcript estimate Not included (per current-main design): - Cache reporting removed: commit 446b8e2 intentionally removed cache reporting from user-facing surfaces because providers that omit cached-token details produce misleading values - Sync DB calls replaced with async_session_store (current main requires AsyncSessionStore with await) Also rewords the /status tokens line from 'Cumulative API tokens (re-sent each call)' to 'Lifetime tokens billed: ... (not your current context size; use /context)' to reduce the recurring confusion that the cumulative figure is the current context window. Fixes salvation of PR NousResearch#52184 (salvage commit replaces a 12K-commit-behind fork branch with a fresh implementation against current main, incorporating reviewer feedback from @whoislikemiha and the hermes-sweeper).
Extends the cherry-picked /context command (PR NousResearch#52184) and prompt-size attribution helpers (PR NousResearch#66656) into one visual context view across surfaces, and absorbs the per-component budget-visibility goal of the /tokens proposal (PR NousResearch#48470): - agent/context_breakdown.py: pure renderers over the existing payload — a 5x20 glyph block grid (1 cell ~= 1% of the model window), an 'Estimated usage by category' table with free space, and expanded per-skill / per-toolset listings via compute_context_details(), which reuses the prompt-size attribution mechanism (skills index-line bytes + registry tool->toolset map) converted to the same chars/4 heuristic. - cli.py: /context [all] renders grid + category table (+ expanded listings) from the live agent and in-memory conversation history. - gateway/slash_commands.py: /context appends the plain-text category table (no grid — monospace not guaranteed on messaging platforms); /context all adds the expanded listings. Fail-open: breakdown errors never break the gauge. - hermes_cli/commands.py: /context gains the 'all' subcommand; /version demoted to /hermes version on Slack to keep the 50-slash cap. - tests: renderer unit tests against synthetic payloads, registry test, gateway /context + /context all + failure-degradation handler tests. - docs: slash-commands reference + CLI guide entries. Read-only and locally computed: no provider calls, no prompt-cache impact. Co-authored-by: RemyFevry <29257684+RemyFevry@users.noreply.github.com> Co-authored-by: joelbrilliant <joelbrilliant1@gmail.com> Co-authored-by: CharlesMcquade <6466275+CharlesMcquade@users.noreply.github.com>
What does this PR do?
Adds a dedicated
/contextgateway slash command (alias/ctx) that gives a full context-window view, and clarifies the/statusline that users routinely misread as their current context size./statusalready shows a one-lineContext: used / total (pct)summary./contextis the deep view for anyone who wants to understand and tune their context budget — and it answers the recurring "why is that token number millions?" confusion directly:All numbers come straight from the agent's
context_compressor. It resolves the live agent mid-turn (_running_agents) and the cached agent between turns (_agent_cache), with a rough transcript estimate when no agent is resident yet — mirroring the existing/usageresolution pattern.It also relabels the
/statuscumulative-tokens line. It readCumulative API tokens (re-sent each call)and was widely mistaken for the current context size (it's actually a lifetime billing total dominated by re-counted cache reads). It now readsLifetime tokens billed: … (not your current context size; use /context).Related Issue
Fixes #
Type of Change
Changes Made
gateway/slash_commands.py— new_handle_context_command(live → cached → transcript-estimate fallback).gateway/run.py— dispatch in both the mid-turn dedicated-handler block and the cold path, so/contextworks while an agent is running (the most useful time) and between turns.hermes_cli/commands.py— register/context(alias/ctx) and add it toACTIVE_SESSION_BYPASS_COMMANDS.locales/en.yaml—gateway.context.*strings; rewordedgateway.status.tokens.tests/gateway/test_status_command.py— four/contexttests (live window, over-threshold flag, transcript fallback, no-data) plus updated/statuslabel assertions.No new config keys; no provider/account calls (read-only, off the billing path); English-only strings (other locales fall back to English, per
agent/i18n.py).How to Test
/context(or/ctx) — verify the gauge, threshold, compression, cache, and throughput lines./contextagain mid-turn (while the agent is responding) — it returns live numbers rather than the "busy" reply./contextin a brand-new session with no agent yet — verify the transcript-estimate fallback / no-data message./status— verify the tokens line now readsLifetime tokens billed: ….scripts/run_tests.sh tests/gateway/test_status_command.py -qChecklist
Code
pytest tests/ -qand all tests pass — added tests are statically validated (py_compile) and the handler output was verified against a live gateway, but I was unable to run the suite in my environment; CI will exercise it.Documentation & Housekeeping
CommandDefregistry entry🤖 Generated with Claude Code