feat(advisor): surface separate worker + advisor token counts in status bar - #190
Closed
agentforce314 wants to merge 1 commit into
Closed
feat(advisor): surface separate worker + advisor token counts in status bar#190agentforce314 wants to merge 1 commit into
agentforce314 wants to merge 1 commit into
Conversation
…us bar
The bottom toolbar already shows `tokens: N in / N out` for the
worker (haiku-4-5 in the user's setup). Now it also shows
`(advisor: N in / N out)` next to it whenever the advisor has
been consulted, so the user can see how much of the spend went to
the reviewer (opus-4-7) versus the worker.
## Display
```
openai · claude-haiku-4-5 · ~/workspace/clawcodex · advisor: opus-4-7 (client) · turns: 2 · tokens: 5400 in / 320 out (advisor: 1326 in / 282 out)
```
The `(advisor: N in / N out)` segment is suppressed when zero so the
toolbar stays compact for users who haven't enabled the advisor or
haven't triggered it yet this session.
## Data flow
1. `execute_client_advisor` (in `src/utils/advisor.py`) now returns
a 3-tuple `(ok, text, usage)` instead of `(ok, text)`. The
`usage` dict has `input_tokens` / `output_tokens` keys pulled
off the provider's ChatResponse. Failure paths return zero usage.
2. `AdvisorTool._advisor_call` (in `src/tool_system/tools/advisor.py`)
reads the 3-tuple and ACCUMULATES the counts onto
`tool_context.advisor_input_tokens` / `advisor_output_tokens`.
Multiple consultations in one session add together (not replace).
3. `ToolContext` gains two new int fields with sane defaults; the
bookkeeping is wrapped in try/except so a status-bar concern can
never break a tool result.
4. `src/repl/core.py:_bottom_toolbar` reads the ctx fields and
appends the advisor segment when non-zero.
## What didn't change
* TUI StatusLine (`src/tui/widgets/status_line.py`) — left as a
follow-up. The TUI reads token counts from AppState.usage which
doesn't yet have an advisor-specific key. Adding the AppState
field + watcher is a separate ~3-file edit. Mention it if it's
needed.
* Server-side advisor path — the worker's response already includes
`usage.iterations[]` with per-model breakdowns (per the
Anthropic API spec in the user-shared example). We don't parse
those yet; if the user moves to a 1P Anthropic main + server-side
advisor, the counts won't show. Followup.
## Tests
* New: `test_call_accumulates_advisor_tokens_onto_ctx` —
verifies two sequential AdvisorTool.call invocations sum the
token counts rather than overwriting.
* Updated 8 destructuring sites + 2 mock returns in
`test_advisor_client_side.py` for the 3-tuple signature.
* Full advisor (117) + TUI (525) suites pass.
## Live verified
```
>>> ok, text, usage = execute_client_advisor('claude-opus-4-7', fwd, main_provider=provider)
ok=True, usage={'input_tokens': 663, 'output_tokens': 141}
```
Real opus-4-7 call via litellm.singula.ai returned correct usage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Owner
Author
|
Superseded by #191 — bundled into the TUI parity PR per user's 'both followups in one PR' direction. See critic review for why the server-side iteration parsing was dropped (SDK 0.88.0 doesn't have the discriminator). |
This was referenced May 21, 2026
singlaamitesh
pushed a commit
to singlaamitesh/clawcodex
that referenced
this pull request
Jul 7, 2026
PR agentforce314#190's content (cherry-picked from advisor/separate-token-counts — `AdvisorTool` accumulates client-side advisor tokens onto `tool_context.advisor_input_tokens/advisor_output_tokens`; the legacy REPL bottom toolbar reads them) provides the data. This commit adds TUI parity: the StatusLine widget shows the same counts. ## What this adds on top of PR agentforce314#190 1. `src/tui/agent_bridge.py` (`_run_agent_in_thread`) — after the run completes, mirrors `tool_context.advisor_input_tokens` / `advisor_output_tokens` into `state.usage["advisor_input_tokens"]` / `["advisor_output_tokens"]` so the StatusLine widget can read them. Cumulative across the session (the TUI's tool_context persists across runs). 2. `src/tui/widgets/status_line.py` (`_compose_text`) — reads the two new keys off `state.usage` and appends `advisor N/N` to the right-side bits when non-zero. Worker-token display (`tokens TOTAL`) is unchanged to keep the diff minimal. ## Display TUI status line now shows e.g.: ``` openai · haiku-4-5 · advisor: opus-4-7 (client) Synthesizing 4s ~/workspace turn 2 · tokens 5720 · advisor 1326/282 ``` ## What's NOT in this PR (intentional) Server-side advisor token attribution. The user-shared `security_audit_advisor.py` example claims `usage.iterations[*].type == "advisor_message"` distinguishes advisor iterations — but the Python SDK 0.88.0 we depend on only defines `"message"` and `"compaction"` discriminators on `BetaIterationsUsageItem` (verified in `.venv/lib/.../beta/beta_iterations_usage.py` + `beta_message_iteration_usage.py`). And `BetaServerToolUsage` only has `web_fetch_requests` / `web_search_requests` — no advisor field. I drafted a parser for the `"advisor_message"` discriminator earlier in this PR but the critic correctly flagged it as non-functional — Pydantic's tagged-union discriminator would reject any value outside the two literals. Removed. When the SDK gains the advisor discriminator OR when we move to direct HTTP parsing of the API response (bypassing typed Pydantic parsing), add a second accumulator alongside the client-side flow. The TUI display logic is already in place — it just needs a second data source to feed `state.usage["advisor_*"]`. ## Critic-driven fixes applied * **Bundled PR agentforce314#190** into this PR per the user's "both followups, in one PR" instruction. Cherry-picked the commit verbatim; this PR builds on top. * **Dropped server-side iteration parsing** after verifying the SDK shape doesn't match the speculative `"advisor_message"` literal. * **Kept the existing `tokens TOTAL` format** in the TUI (didn't switch to `tokens N/N`) — avoids a user-visible format change in an unrelated part of the status line. The new advisor segment is `advisor N/N` for compactness; the asymmetry vs the worker total is acceptable as long as it's the only thing changing. ## Tests * 665 passed across full advisor + adapter + TUI + helpers + smoke suites. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
singlaamitesh
pushed a commit
to singlaamitesh/clawcodex
that referenced
this pull request
Jul 7, 2026
…fficient /advisor) Two new entries at the top of the README News section: 1. Codebase stats: 890 files / 183,768 lines (up from 894 / 177,428 on 2026-05-16; net +6.3k lines / -4 files in five days). The file delta is the agent_loop.py consolidation; the line additions are the /advisor multi-provider rewrite + status-bar cost work. 2. /advisor mode as a token-efficient coding agent — narrates the PR agentforce314#181 → agentforce314#193 arc as one story: - Cheap worker (haiku-4-5) + expensive reviewer (opus-4-7) only at decision points ≈ 6× cheaper than opus-only on typical sessions - Explicit <provider>:<model> syntax (agentforce314#192) - Cross-provider routing verified (deepseek worker + opus advisor via litellm, agentforce314#182/agentforce314#184/agentforce314#192) - Reviewer-quality prompt (agentforce314#188) — Gaps/Risks/Do-next format - Live cost + token visibility in status bar (agentforce314#190/agentforce314#191/agentforce314#193) - /advisor slash command + dedicated TUI row (agentforce314#181) Docs-only — no code or test changes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Show advisor token spend separately from worker token spend in the legacy REPL bottom toolbar. Users can now see at a glance how much of their request went to the reviewer (e.g. opus-4-7) vs the worker (e.g. haiku-4-5).
Display
```
openai · claude-haiku-4-5 · ~/workspace/clawcodex · advisor: opus-4-7 (client) · turns: 2 · tokens: 5400 in / 320 out (advisor: 1326 in / 282 out)
```
The
(advisor: N in / N out)parenthetical is suppressed when zero — the toolbar stays compact for users who haven't enabled the advisor or haven't triggered it yet this session.Data flow
src/utils/advisor.pyexecute_client_advisornow returns(ok, text, usage)— 3-tuple.usageis{input_tokens, output_tokens}pulled off the provider'sChatResponse. Failure paths return zero usage.src/tool_system/tools/advisor.pyAdvisorTool._advisor_callreads the 3-tuple and accumulates intoctx.advisor_input_tokens/ctx.advisor_output_tokens. Multiple consultations in one session sum (not replace). Bookkeeping wrapped in try/except so a status-bar concern never breaks a tool result.src/tool_system/context.pyToolContextwith sane defaults.src/repl/core.py_bottom_toolbarreads the ctx fields and appends the parenthetical when non-zero.What's NOT in this PR (followups)
AppState.usagewhich doesn't yet have an advisor-specific key; adding the AppState field + watcher is ~3 files of work, separate concern.ChatResponse.usage.iterations[]already includes per-model counts (per the Anthropic API spec), but we don't parse them. If you move to 1P Anthropic main + server-side advisor, the counts won't show. Followup.Tests
test_call_accumulates_advisor_tokens_onto_ctx— verifies two sequentialAdvisorTool.callinvocations sum the counts rather than overwriting.test_advisor_client_side.pyfor the 3-tuple signature.Live verified
Real call against the user's setup (haiku-4-5 main + opus-4-7 advisor via litellm.singula.ai):
```
Token counts populated correctly from the provider response.
🤖 Generated with Claude Code