fix(pi): count standalone usage entries

Merged
JP
2d ago
+308-27

Why

Pi's standalone usage entries are a standard, documented Pi session feature. They record model usage outside assistant replies. Pi itself uses them for cache warming through SessionManager.appendUsage().

References:

TokScale currently reads assistant messages but skips these standalone records, so their tokens are missing from totals. This change reads the existing standard format. It does not introduce a custom record type, a provider integration, or Jev-specific parsing.

Human-written explanation

I'm doing this because Pi recently added support for Jev, a decision model. Jev can be used as a model router, and redirect the user message to model A or B (like sol or luna). Very useful to redirect to a smaller model when the user's input is simple.
But tokscale only track the usage of the real model (sol, luna, etc), not Jev. With this PR, Pi extensions can write usage from Jev into the session, and tokscale can read the usage. Voilà!

Changes

  • Parse top-level usage, model, provider, and timestamp fields for standalone usage entries. Accept arbitrary kind values.
  • Preserve session, workspace, title, agent, and existing pricing behavior.
  • Keep copied usage entries deduplicated without colliding with assistant-message identities. Preserve Kimchi's existing session-scoped behavior.
  • Keep Prime Agent's fresh and cached accounting aligned without treating background usage as assistant completions.
  • Bump the shared Pi-format parser version so existing caches are reparsed. Document the standard record format.

Validation

Seven new regressions cover the shared Pi-compatible clients, arbitrary kinds, malformed records, attribution, fork copies, identity collisions, Prime accounting, and cache invalidation.

  • cargo fmt --all -- --check passes.
  • cargo clippy --locked --workspace --all-features -- -D warnings passes.
  • cargo test --locked --workspace --all-features passes: 4,515 tests pass and five existing tests remain ignored.
  • cargo build --locked --release -p tokscale-cli --bin tokscale passes.
  • The installed CLI exactly matches three real classifier calls: 1,302 input tokens and 123 output tokens. Tool continuation does not add another classifier call.
  • The actual terminal UI shows standalone classifier usage as a separate model row alongside normal assistant models.

Source-reported costs keep the existing Pi parser behavior. TokScale still uses its own price resolver, rather than treating Pi catalog estimates as provider-billed charges.

How it looks like

tokscale-pi-usage-2026-10-16

Summary by cubic

Counts Pi's standalone usage session entries so tokens from background model calls (like cache warming) are included in totals instead of being skipped. Also retains the upstream accounting for the other billed operations and their reported costs after merging main.

  • Parses top-level usage, model, provider, and timestamp fields; accepts any kind, skips malformed records, and ignores unrelated metadata that reuses those field names.
  • Adds standalone usage as separate model rows alongside assistant replies, preserving recorded costs and falling back to existing pricing data when absent.
  • Keeps copied usage entries deduplicated without colliding with assistant-message identities, and preserves Kimchi's session-scoped behavior.
  • Keeps Prime Agent's fresh and cached accounting aligned without treating background usage as assistant completions, even when IDs collide with assistant messages.
  • Bumps the shared Pi-format parser version so existing caches are reparsed, and documents the record format in the README and its maintained translations.