Repository navigation
fix(antigravity): deduplicate unkeyed mirror usage via step index fallback - #2027
Conversation
…lback Co-authored-by: zhibisora <[email protected]>
|
Important Review skippedBot user detected. To trigger a single review, invoke the
|
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
ccusage-guide | ba4be79 | Commit Preview URL Branch Preview URL |
Nov 09 2026, 07:37 PM |
…ck identity The step/generator positional fallback identity identifies the primary turn, but it was also attached to every unkeyed retry_infos entry. Because deduplicate_events merges by taking the max of each token field, a real failed attempt (e.g. same input, fewer output tokens) was folded into the successful attempt and its usage silently disappeared. retry_infos lists every attempt, including the one already reported as the primary usage. So the only retry that duplicates the primary is that one mirror entry, whatever the attempt count. Drop exactly that entry (not only when there is a single retry, which still left 2x for multi-attempt turns), and leave the remaining retries without the turn's positional identity so they are counted as their own usage.
ccusage
@ccusage/ccusage-darwin-arm64
@ccusage/ccusage-darwin-x64
@ccusage/ccusage-linux-arm64
@ccusage/ccusage-linux-x64
@ccusage/ccusage-win32-x64
commit: |
ccusage performance comparisonPR SHA: This compares the Rust PR release binary against the configured base package on the same CI runner. Package runtime diagnosticsCompares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself. Fixtures: Claude
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures. Fixtures: Claude
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
ccusage performance comparisonPR SHA: This compares the PR package against the configured base package on the same CI runner. Package runtime diagnosticsCompares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself. Fixtures: Claude
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures. Fixtures: Claude
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
Upstream tip: 660e07c (2026-11-13, chore(pricing): update models.dev snapshot) Previous fork base: 30b653f (the upstream commit this fork was synced to) Synced 100 upstream commits on top of 30b653f: 53 automated pricing snapshot refreshes, 23 dependency bumps, 2 releases, and: 3541115 feat(cline): add extension and CLI usage adapter (ccusage#1977) 5e5c475 fix(antigravity): report real model names instead of placeholders (ccusage#2071) e39ed83 fix(claude): keep the cache TTL split when deduping equal copies (ccusage#2060) c17c591 feat(adapter): report 1h cache writes in JSON model breakdowns (ccusage#2059) a06f4bc perf(claude): halve `ccusage claude` report time (ccusage#2058) de43952 fix(claude): show model breakdowns for session --id (ccusage#2057) 5f31039 fix(all): count only in-window Claude usage in unified session reports (ccusage#2052) e4f0ea9 fix(codex): count spawned subagent requests stamped at the fork instant (ccusage#2051) b85b28f fix(opencode): count usage from completed v2 compaction rows (ccusage#2050) 00fead0 fix(antigravity): deduplicate unkeyed mirror usage (ccusage#2027) 2248106 fix(opencode): exclude Claude Agent turns by default (ccusage#2022) 4fb1c0d fix(codex): guard truncated type fields from panicking the parser (ccusage#2034) 86707db build(perf): make the PR performance comparison catch real regressions (ccusage#2061) 686a1a8 ci: support a merge queue on main (ccusage#2062) Fork wins kept: the Codex optimized scanner with its fork-replay instant, the Antigravity model resolver, the OpenCode retained-ledger cache with its per-namespace rows, the SQLite on-disk cache, the table renderer, the fork CI and tag-only release workflow, and the exact `=` dependency pins. Hand-resolved conflicts: rust/adapters/claude/src/lib.rs: the fork's DedupedEntries copy pairs stay and take upstream's carries_more_usage_detail tiebreak (speed rank, then a cache TTL split); main_thread_session_days reads the recorded session of each copy. rust/adapters/opencode/{loader,parser}.rs: the fork's retain_via_ledger stays beside upstream's v2 compaction scan; SessionMessageKind and MessageRowColumns carry the row type through the five-value scan. rust/adapters/codex/{replay,parser}.rs: open_rollout_reader_with_capacity and CodexForkReplay both land in the shared parser state. rust/crates/ccusage-core/src/{cache,pricing}.rs: the opencode-db-compaction namespace joins the ledger namespaces; the fork's embedded pricing loader and OnceLock path stay. rust/crates/ccusage/src/cli/timezone.rs: Cline joins the shared-args arm, the ClearCache arm stays unreachable from the parser. rust/Cargo.toml: the fork's exact `=` pins stay; jiff 0.2.41, schemars 1.2.2, serde 1.0.229, smallvec 1.16.5, toml 1.2.1. .github/workflows/{ci,release}.yaml: the fork's design is kept, including its own release flow. Upstream's merge-queue, tagpr and pkg.pr.new jobs need scripts this fork deleted, so they are not taken; the two save-nix-cache inputs upstream passes to the native-package actions are dropped because the fork's composite actions declare no such input. packages/ccusage-*/package.json (6 files), the contribution-gate scripts, sponsors.md, blacksmith.png and rust/adapters/claude/src/daily.rs stay deleted; the two Blacksmith SVG logos upstream added are not taken. Docs: the agent lists take upstream's Cline addition but keep this fork's `pi` name, because the CLI subcommand is still `pi`; upstream renamed the docs to `pi-agent` without renaming the command. Snapshots regenerated for the fork table renderer: the Cline adapter, CLI and unified reports, codex issue_2046, opencode compaction, claude session --id and the config schema (new Cline section). Validation: cargo test --workspace --offline 1297 passed, 0 failed; cargo clippy --workspace --all-targets clean; rustfmt --check clean. Version: take upstream's 20.0.50 in package.json, apps/ccusage/package.json and docs/package.json; the Rust workspace keeps version 0.0.0. DO NOT push a v20.0.50 tag from this fork: release.yaml would publish fork bytes under upstream identity.
References #2026 triple-counting of unkeyed Gemini turns in
rust/adapters/antigravity.CortexStepGeneratorMetadata.step_indices(field 2, unpacked and packed) and usesstep:{session}:{step_idx}as fallback identity whenModelUsageStatslacks response/provider/message IDs, sogen_metadatarows merge with theirstepsrows indeduplicate_events.retry_infos[0]mirror copies in both generator and step metadata when token counts match and identities are a subset of the primary, preventing intra-row 2x.gen:{session}:{gen_idx}whenstep_indicesis empty, so unkeyed mirrors still collapse to 1x.Tests:
cargo test --manifest-path rust/Cargo.toml -p ccusage -p ccusage-adapter-antigravity --features ccusage/fetch-litellm-pricing --lib— 39 passed, including newdeduplicates_unkeyed_mirror_copies_via_step_index,drops_unkeyed_retry_mirror_without_step_link,parses_step_indices_and_drops_mirror_retry, andkeeps_distinct_retry_attempt_for_deduplication.cargo clippy ... --features ccusage/fetch-litellm-pricing -- -D warnings— clean.cargo fmt --all -- --check— clean.Closes #2026
Summary by cubic
Fixes triple-counting of unkeyed Gemini turns in
rust/adapters/antigravityby giving generator rows a step-index fallback identity so mirrored usage rows collapse to 1x instead of 2–3x.gen_metadatarows fall back tostep:{session}:{step_idx}(parsed fromstep_indices), orgen:{session}:{gen_idx}when step indices are absent, so unkeyed usage merges with its step row.retry_infosentry that is an exact mirror of the primary usage, and leaves remaining retries unlinked from the turn identity so distinct failed attempts are counted as their own usage instead of being folded into the primary by max-merge deduplication.Tests added for step-index parsing, mirror dropping, and preserving distinct retry attempts;
cargo test,clippy, andfmtall pass. Closes #2026.Written for commit ba4be79. Summary will update on new commits.