Display session-level token usage in the chat header
Summary
Show a running token usage summary in the chat session header so users can see at a glance how much context a session has consumed. Token totals are aggregated on demand from the messages table — keeping the schema clean with a single source of truth.
Why not sum from loaded messages
ChatView lazy-loads messages (hasMoreMessages / loadPrevious). Summing token counts from currently loaded messages only reflects a partial view. Opening an old session would show an incorrect total until all pages are loaded.
Approach — aggregate query on session open
When a session is opened, run a single lightweight aggregation query against the messages table — separate from and independent of message pagination:
SELECT SUM(total_tokens), SUM(input_tokens), SUM(output_tokens)
FROM chat_messages
WHERE session_id = ? AND deleted_at IS NULL
This gives the true total immediately, before any messages are loaded. No schema changes needed. No denormalization risk.
On new AI response — append the new message's token counts to the in-memory total (optimistic delta update). No re-query needed.
On message delete / retry — re-run the aggregation query to get an accurate count (infrequent operation, acceptable cost).
UI
A compact token pill in the existing session header card in ChatView.kt, sitting between the session title and the dropdown menu (the directive dropdown is going to move to the ChatInputField in this ticket #535):
Shows ~12K tokens when total > 0
Hidden for new/empty sessions
Hover tooltip shows full breakdown: 12,450 total · 8,230 in / 4,220 out
What to figure out
Where to run the aggregation query — repository method, service layer, or ViewModel on session load?
How to expose the result to ChatState — a dedicated sessionTokenSummary field or inline on the session object?
Optimistic delta update on new response — where does this live cleanly without leaking into ChatView?
Files likely affected
- ChatMessageRepository (local) — add sumTokensBySessionId(sessionId) query method
- ChatSessionService / SessionManager — call aggregation on session open, expose result
- ChatView.kt — render the token pill in the header
Display session-level token usage in the chat header
Summary
Show a running token usage summary in the chat session header so users can see at a glance how much context a session has consumed. Token totals are aggregated on demand from the messages table — keeping the schema clean with a single source of truth.
Why not sum from loaded messages
ChatViewlazy-loads messages (hasMoreMessages/loadPrevious). Summing token counts from currently loaded messages only reflects a partial view. Opening an old session would show an incorrect total until all pages are loaded.Approach — aggregate query on session open
When a session is opened, run a single lightweight aggregation query against the messages table — separate from and independent of message pagination:
This gives the true total immediately, before any messages are loaded. No schema changes needed. No denormalization risk.
On new AI response — append the new message's token counts to the in-memory total (optimistic delta update). No re-query needed.
On message delete / retry — re-run the aggregation query to get an accurate count (infrequent operation, acceptable cost).
UI
A compact token pill in the existing session header card in ChatView.kt, sitting between the session title and the dropdown menu (the directive dropdown is going to move to the ChatInputField in this ticket #535):
Shows ~12K tokens when total > 0
Hidden for new/empty sessions
Hover tooltip shows full breakdown: 12,450 total · 8,230 in / 4,220 out
What to figure out
Where to run the aggregation query — repository method, service layer, or ViewModel on session load?
How to expose the result to ChatState — a dedicated sessionTokenSummary field or inline on the session object?
Optimistic delta update on new response — where does this live cleanly without leaking into ChatView?
Files likely affected