Skip to content

feat(usage): show the cached subset beside every token total - #4421

Merged
lidge-jun merged 1 commit into
devfrom
codex/260912-cached-token-companion
Sep 12, 2026
Merged

feat(usage): show the cached subset beside every token total#4421
lidge-jun merged 1 commit into
devfrom
codex/260912-cached-token-companion

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Sep 12, 2026

Copy link
Copy Markdown
Owner

Summary

A cached request's total is mostly cache. A 58,000-token prompt that is 57,000 cache read and 1,000 fresh was printed as a bare 5.8만 everywhere except the logs table row, so it read as a different, smaller request than the row directly beside it.

formatTokensWithCache renders the total with its cached companion — 5.8만 c5.7만, 58K c57K — reusing the marker the logs.tokens.cacheRead label already documents as "cache read (c)", so no new i18n key is required. A provider that reports no cache is untouched. A turn served entirely from cache still shows the marker, because that is the row most worth seeing and suppressing it would blank exactly the case this exists for.

No backend change was needed. /api/logs forwards the whole usage object and /api/usage already emits cache on summary, models and providers. The loss was entirely client-side: the row types dropped the fields and the aggregators summed only totals. This widens UsageModel, UsageProvider, UsageSummary30d, the CLI's CostRow, and summarizeFilteredLogs to keep what was already arriving.

Surfaces converted: the Logs conversation-totals banner, the Usage per-model and per-provider token columns, the dashboard 30-day tile, and the CLI ocx usage provider/model/account rows. The log detail panel is deliberately left alone — it already has separate cache read and cache write cells, so stacking the companion on its total would duplicate them.

Usage page rendering token totals with their cached companion

Captured from a build of this branch served by a throwaway proxy on its own port and its own OPENCODEX_HOME, seeded with synthetic usage rows, so the running service was untouched. Anthropic Claude shows 41.7만 c33.1만, Devin CLI 10만 c9.7만, and xAI Grok — which reported no cache — stays a bare 9.9만.

Verification

  • bun test tests/gui/gui-format-tokens-cache.test.ts tests/cli/cli-usage-report.test.ts tests/test-layout.test.ts tests/test-layout-tooling.test.ts — green. The new test file is registered in scripts/test-layout/layout.json and tests/fixtures/test-layout-expected.json.
  • bun x tsc --noEmit — clean.
  • bun run lint:gui — clean.
  • Live render verified on the throwaway instance above, in both the Korean myriad scale and the Western thousands scale.
  • Full bun run test: NOT RUN locally by request; remote CI on this head is the evidence.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Summary by CodeRabbit

  • New Features

    • Token usage displays now show cache-read amounts alongside total tokens across usage reports, dashboards, logs, and usage tables.
    • Cached totals are formatted using localized number styles and remain visible when the entire request was served from cache.
    • CLI reports identify cached token amounts in provider, account, and model rows.
  • Tests

    • Added coverage for cached-token formatting and CLI usage report output.

A cached request's total is mostly cache. A 58,000-token prompt that is
57,000 cache read and 1,000 fresh was printed as a bare 58,000 on every
surface except the logs table row, so it read as a different, smaller
request than the row directly beside it.

formatTokensWithCache renders the total with its cached companion —
5.8만 c5.7만, 58K c57K — reusing the marker the logs.tokens.cacheRead
label already documents as "cache read (c)", so no new i18n key is needed.
A provider that reports no cache is untouched, and a turn served entirely
from cache still shows the marker, since that is the row worth seeing.

No backend change: /api/logs forwards the whole usage object and /api/usage
already emits cache on summary, models and providers. The loss was purely
client-side, in the row types and the aggregators, so the fix widens
UsageModel, UsageProvider, UsageSummary30d, the CLI CostRow, and
summarizeFilteredLogs to keep the fields that were already arriving.

The log detail panel is deliberately left alone: it already has separate
cache read and cache write cells, and stacking the companion onto its
total would duplicate them.
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 12, 2026 15:02
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 12, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-12T15:06:16.560364Z 635725a PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the enhancement New feature or request label Sep 12, 2026
@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 00fd3c1c-ff49-4efc-b668-5499fe37d497

📥 Commits

Reviewing files that changed from the base of the PR and between f5b2a0d and 635725a.

⛔ Files ignored due to path filters (1)
  • devlog/_plan/260912_devin_hardening/cached-token-companion.jpg is excluded by !**/*.jpg
📒 Files selected for processing (10)
  • gui/src/format-tokens.ts
  • gui/src/pages/Logs.tsx
  • gui/src/pages/Usage.tsx
  • gui/src/pages/dashboard-overview-head.tsx
  • gui/src/pages/dashboard-shared.ts
  • scripts/test-layout/layout.json
  • src/cli/usage-report.ts
  • tests/cli/cli-usage-report.test.ts
  • tests/fixtures/test-layout-expected.json
  • tests/gui/gui-format-tokens-cache.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

The change adds cache-aware token formatting to GUI logs, usage tables, dashboards, and CLI usage reports. It adds optional cache token fields to usage models and validates cached and uncached display cases.

Changes

Cache-aware token reporting

Layer / File(s) Summary
GUI cache-aware token reporting
gui/src/format-tokens.ts, gui/src/pages/Logs.tsx, gui/src/pages/Usage.tsx, gui/src/pages/dashboard-overview-head.tsx, gui/src/pages/dashboard-shared.ts, tests/gui/*, scripts/test-layout/layout.json, tests/fixtures/test-layout-expected.json
The GUI adds formatTokensWithCache, collects cache-read totals from logs, extends usage summary types, and displays cache-read counts in logs, usage tables, and the dashboard. Tests cover locales, invalid cache values, and fully cached totals.
CLI cache-aware token reporting
src/cli/usage-report.ts, tests/cli/cli-usage-report.test.ts
The CLI adds optional cache token fields and renders cache-read counts in provider, account, and model token columns. Tests cover cached and uncached rows.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Suggested reviewers: invalid-email-address

Sequence Diagram(s)

sequenceDiagram
  participant Logs
  participant summarizeFilteredLogs
  participant cacheSplit
  participant formatTokensWithCache
  participant ConversationTotals
  Logs->>summarizeFilteredLogs: summarize filtered entries
  summarizeFilteredLogs->>cacheSplit: read cache-read tokens
  cacheSplit-->>summarizeFilteredLogs: cachedInputTokens
  ConversationTotals->>formatTokensWithCache: format total and cachedInputTokens
  formatTokensWithCache-->>ConversationTotals: cache-aware token text
Loading

Merge Risk: ⚪ Minimal · up to 63572

Cache-aware token displays preserve the required data flow and formatting behavior across the reviewed GUI and CLI paths.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 8 files. (2 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: displaying the cached token subset beside token totals across GUI, dashboard, logs, and CLI usage views.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 8 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/260912-cached-token-companion

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 58 / 80

이 PR은 사용량 화면에서 토큰 숫자만 덩그러니 보이던 자리를, 캐시로 읽힌 부분까지 같이 보여 주게 고칩니다. 지금 dev HEAD(f5b2a0d00, #4417 데브로그 마감)에는 캐시 텔레메트리와 캐시 레인 증거가 이미 들어와 있습니다. /api/usage의 모델·프로바이더 행과 /api/logs 사용량 객체에는 cachedInputTokens / cacheReadInputTokens가 이미 실려 나옵니다. 그런데 GUI의 UsageModel·UsageProvider·대시보드 30일 요약 타입과 CLI CostRow가 그 필드를 타입에서 버려 두고, 화면은 formatTokens(total)만 호출해서 로그 표의 c … 줄과 숫자가 다르게 읽혔습니다. 예를 들어 총 58,000인데 캐시 읽기 57,000인 요청이 로그 행에서는 캐시가 보이는데, 배너·Usage 표·대시보드·ocx usage에서는 그냥 5.8만 / 58K처럼 보여 “다른 작은 요청”처럼 느껴지던 문제였습니다.

고치는 방식은 백엔드를 건드리지 않습니다. gui/src/format-tokens.tsformatTokensWithCache(total, cached, locale)를 추가해 5.8만 c5.7만, 58K c57K처럼 붙이고, c 표시는 이미 i18n logs.tokens.cacheRead(예: 영어 cache read (c), 한국어 캐시 히트 (c))가 쓰던 표기와 맞춥니다. 캐시가 없거나 0·NaN·음수면 예전처럼 총량만 냅니다. 캐시가 총량과 같아도 마커를 숨기지 않습니다. 전부 캐시인 줄이야말로 보고 싶은 경우이기 때문입니다. 연결 표면은 Logs 대화 합계 배너(summarizeFilteredLogscacheSplit(...).read를 합산), Usage 모델/프로바이더 표, 대시보드 30일 타일(dashboard-shared.tsUsageSummary30d), CLI src/cli/usage-report.ts의 provider/model/account 행입니다. 로그 상세 패널은 이미 캐시 읽기/쓰기 칸이 따로 있어서 의도적으로 손대지 않았습니다. 테스트는 tests/gui/gui-format-tokens-cache.test.ts와 CLI usage-report 확장, layout fixture 등록까지 들어가 있고, PR 본문 기준 로컬 타깃 테스트·tsc·lint:gui는 통과했다고 적혀 있습니다. 원격 CI는 이 글을 쓰는 순간 일부 job이 아직 pending입니다.

types.ts/config.ts 대규모 분리 캠페인과 겹치지 않는 클라이언트 표시 수정이라 닫고 리베이스하라는 대상은 아닙니다. 중복 PR도 아닙니다. Devin ACP 제거(#4415) 이후 캐시·사용량 가시성을 다듬는 작은 후속 작업으로 읽힙니다.

gui/src/pages/Logs.tsx - formatTokensformatTokensWithCache를 같은 모듈에서 import 두 줄로 나눠 가져옵니다. 한 줄로 합치는 편이 읽기 쉽습니다.

gui/src/pages/Usage.tsx (daybar / heatmap) - PR 제목·본문은 “토큰 총량 옆마다”라고 말하지만, 같은 Usage 페이지의 daybar 카운트·툴팁과 heatmap 툴팁은 여전히 formatTokens(total)만 씁니다. 표만 고치고 차트 쪽은 그대로라 “모든 총량” 약속과 어긋납니다.

gui/src/components/provider-workspace (ProviderUsage / ProviderOverview) - 프로바이더 워크스페이스 토큰 숫자도 아직 캐시 동반 표시가 없습니다. 이번 diff 범위 밖이지만, 운영자가 Usage 표와 PWS를 같이 보면 다시 숫자가 다르게 읽힐 수 있습니다.

gui formatTokensWithCache vs CLI countWithCache - GUI는 58K c57K, CLI는 58,000 (cached 57,000)입니다. CLI가 요약 줄의 cached N 말투를 맞춘 선택은 이해되지만, 같은 저장소를 보는 사람이 GUI/CLI를 오가면 표기 체계가 둘로 갈라집니다.

formatTokensWithCache / countWithCache - cached > total인 깨진 텔레메트리에도 그대로 붙입니다. 드물지만 운영 화면에 58K c90K처럼 불가능한 조합이 나갈 수 있습니다. 클램프하거나 경고 표기를 둘지 정하면 좋습니다.

devlog/_plan/.../cached-token-companion.jpg - 계획 폴더에 스크린샷을 넣는 증거용으로 보이며 용량도 작습니다. 다만 제품 경로가 아니라 plan 자산이라, 머지 후 plan 정리 때 남길지 _fin으로 옮길지만 정하면 됩니다.

메인테이너의 판단이 필요한 지점

  • Usage 상단 카드는 총량 카드와 캐시 카드가 이미 나란히 있어서 동반 표기를 안 붙인 것이 맞는지, 아니면 총량 카드에도 c…를 붙일지
  • daybar·heatmap·프로바이더 워크스페이스까지 “모든 토큰 총량”에 넣을지, 이번 PR은 표/배너/CLI만으로 끝낼지
  • GUI의 c 접두와 CLI의 (cached N)을 장기적으로 하나로 맞출지, 표면별 관례로 둘지
  • CI 전체(test shards / gates 등 pending job) 그린을 머지 게이트로 볼지

너의 추천
우선순위는 중간입니다. 백엔드 계약은 이미 맞춰져 있고 손실이 클라이언트 타입·표시에만 있던 문제를 정확히 짚었으며, 테스트와 라이브 렌더 설명이 있습니다. Logs.tsx import만 한 줄로 정리하고, daybar/heatmap은 “이번 범위 밖”을 PR에 한 줄 명시하거나 후속 이슈로 남겨 둔 뒤, CI가 전부 초록이면 dev에 머지하는 쪽을 추천합니다. types/config 분리로 무효화될 PR이 아니므로 닫지 마세요.

이 댓글은 grok-bot이 작성했습니다

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 635725a9cf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread gui/src/format-tokens.ts
export function formatTokensWithCache(total: number, cached: number | undefined, locale: string): string {
const base = formatTokens(total, locale);
if (cached === undefined || !Number.isFinite(cached) || cached <= 0) return base;
return `${base} c${formatTokens(cached, locale)}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Document the new cache-companion notation

When cached usage is present, the dashboard and Usage tables now display compact values such as 58K c57K, but docs-site/src/content/docs/guides/web-dashboard.md still describes only a token total and the CLI observability reference does not explain that c is a non-additive cache-read subset. Users encountering the notation outside the Logs detail view therefore have no documented way to interpret it; update the English documentation and keep the translated pages consistent.

AGENTS.md reference: AGENTS.md:L380-L381

Useful? React with 👍 / 👎.

@lidge-jun
lidge-jun merged commit 7b3c4e9 into dev Sep 12, 2026
31 checks passed
@lidge-jun
lidge-jun deleted the codex/260912-cached-token-companion branch September 12, 2026 15:15
lidge-jun added a commit that referenced this pull request Sep 12, 2026
…esent

Evidence for the revert: the logs table layout is exactly what it was before #4421, and the Devin CLI rows now carry their cached line because #4419 reads the usage field that actually holds it.
lidge-jun added a commit that referenced this pull request Sep 12, 2026
…#4424)

* Revert "feat(usage): show the cached subset beside every token total"

This reverts 7b3c4e9.

The reported defect was Devin-only and had nothing to do with the display
layer. The logs table has always rendered a total with its cached value;
Devin rows showed a bare total because the cloud-direct adapter decoded
GetChatMessageResponse field 28 (response_dimension_groups, the rows the
IDE draws) instead of field 7 (ModelUsageStats), so cache read and cache
write never reached the log row in the first place. #4419 fixes that at
the source, which is the whole fix.

Changing the Usage page, the dashboard tile and the CLI tables rewrote
surfaces that were already correct for every other provider, so the revert
restores them.

* docs(devlog): capture the restored logs rendering with Devin cache present

Evidence for the revert: the logs table layout is exactly what it was before #4421, and the Devin CLI rows now carry their cached line because #4419 reads the usage field that actually holds it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant