← Back to PRs

#20650: fix(gateway): include deleted/reset sessions in usage.cost RPC (#20599)

by lailoo open 2026-02-19 05:36 View on GitHub →
gateway size: S experienced-contributor
## Summary - **Bug**: `usage.cost` RPC undercounts tokens and cost by ignoring deleted/reset session transcripts - **Root cause**: `loadCostUsageSummary` in `src/infra/session-cost-usage.ts` filters files with `.endsWith(".jsonl")`, excluding `*.jsonl.deleted.*` and `*.jsonl.reset.*` archives - **Fix**: Widen the file filter to include archived session transcripts Fixes #20599 ## Problem When sessions are deleted or reset, their transcript files are renamed from `foo.jsonl` to `foo.jsonl.deleted.<timestamp>` or `foo.jsonl.reset.<timestamp>` (via `archiveFileOnDisk` in `session-utils.fs.ts`). These files remain on disk with full usage data intact. However, `loadCostUsageSummary` only scans files ending in `.jsonl`: ```typescript .filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")) ``` This means all usage from deleted/reset sessions is invisible to the dashboard. In the reporter's deployment, this resulted in 85% of actual cost being hidden. **Before fix:** - Active sessions: 100 tokens, $0.10 - Deleted session (on disk as `*.jsonl.deleted.*`): 200 tokens, $0.20 - Reset session (on disk as `*.jsonl.reset.*`): 300 tokens, $0.30 - `usage.cost` RPC returns: 100 tokens, $0.10 ## Changes - `src/infra/session-cost-usage.ts` — Add `isSessionTranscriptFile()` helper that matches `*.jsonl`, `*.jsonl.deleted.*`, and `*.jsonl.reset.*`; use it in `loadCostUsageSummary` file filter - `src/gateway/server.usage-cost-deleted-sessions.e2e.test.ts` — E2E test: starts real gateway, creates active + deleted + reset session files, calls `usage.cost` RPC, verifies all tokens are counted - `CHANGELOG.md` — Add fix entry **After fix:** - `usage.cost` RPC returns: 600 tokens, $0.60 (all sessions counted) ## Test plan - [x] New e2e test: real gateway with active + deleted + reset sessions, verifies totalTokens >= 600 - [x] All 8 existing session-cost-usage tests pass - [x] All 5 existing usage handler tests pass - [x] Format check passes - [x] Lint passes ## Effect on User Experience **Before:** Usage dashboard shows only active session costs. Deleted/reset sessions (which can represent 85%+ of actual spend) are invisible, giving users a false sense of low usage. **After:** Dashboard accurately reports total cost across all sessions, including those that have been deleted or reset. <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes a critical bug where the `usage.cost` RPC undercounted tokens and costs by ignoring deleted and reset session transcripts. **Root cause:** The file filter in `loadCostUsageSummary` (line 329) only matched `*.jsonl` files, excluding archived sessions (`*.jsonl.deleted.*` and `*.jsonl.reset.*`) that are created when sessions are deleted or reset via `archiveFileOnDisk`. **Changes:** - Added `isSessionTranscriptFile()` helper function that matches all three file patterns: active (`*.jsonl`), deleted (`*.jsonl.deleted.*`), and reset (`*.jsonl.reset.*`) sessions - Updated the file filter in `loadCostUsageSummary` to use this new helper - Added comprehensive E2E test verifying all session types are counted - Updated CHANGELOG with user-facing fix description **Impact:** Users previously saw only active session costs in their dashboard. This bug could hide 85%+ of actual usage if many sessions were deleted/reset. After this fix, the dashboard accurately reflects total cost across all sessions. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk - The fix is surgical, well-tested, and addresses a clearly-defined bug. The new helper function correctly matches the exact naming patterns used by `archiveFileOnDisk`, the E2E test provides comprehensive coverage with all three file types, and the change is backward-compatible (active `.jsonl` files continue to work). The fix is isolated to the cost calculation path and doesn't affect session discovery/listing functionality. - No files require special attention <sub>Last reviewed commit: cf74cd1</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs