feat(sdk): richer session-stats snapshot - #9
Merged
Conversation
…ent usage
Session stats only exposed aggregate token/cost counters, so consumers could
not tell cached prompt tokens from fresh ones, could not count user turns or
compactions, and had no per-agent-definition breakdown of spend.
The reducer already receives the post-core-reducer session state, so the
spawning agent's definitionName is reachable from the inference events without
any structural change.
All new fields start at 0 / {} and state is always replayed from events, so
existing sessions keep working.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018yiScAyGwDx3A3DqaUasEA
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.
What
Extends the
session-statsSDK plugin snapshot with the counters the consumingplatform needs for per-day cost/usage reporting:
cacheReadTokens/cacheWriteTokens— frominference_completedandauxiliary_inference_completedmetrics (cachedTokens,cacheWriteTokens),so cached prompt tokens can be billed/charted apart from fresh ones.
userMessages— fromuser_chat_message_received(user-chat plugin).compactions— fromcontext_compacted(context-compact plugin).byAgent: Record<definitionName, { llmCalls, promptTokens, completionTokens, totalCost }>—per agent-definition LLM breakdown.
byAgentneeded no architecture change: state slices already receive thesession state as the third reducer argument, and the core reducer runs before
plugin slices (
composeReducers(coreReducer, …)), sosessionState.agents.get(event.agentId).definitionNameis already populatedwhen the inference event is reduced.
Compatibility
0/{}increateInitialStats().(no persisted state snapshots), so existing sessions pick the new counters up
on the next replay instead of hitting
undefined.GET /status(metrics: s.metrics), so notransport contract change is needed.
ProviderStats/AgentStatsare now exported from the package root.Verification
bun run ts:build— clean (exit 0)bun run lint— exit 0 (one pre-existing warning inplugins/uploads/preprocessors/markitdown-preprocessor.ts, untouched here)bun test packages/sdk/src— 866 pass, 4 skip, 0 failbun test packages/*/src packages/*/tests— 922 pass, 8 skip, 0 failNew
plugins/session-stats/plugin.test.tscovers each new counter (defaults,user messages, compactions, cache read/write incl. providers that report
neither, the per-agent breakdown across two definitions plus an auxiliary call,
and a regression check on the pre-existing counters).
🤖 Generated with Claude Code
https://claude.ai/code/session_018yiScAyGwDx3A3DqaUasEA