feat(coding-agent): add prompt cache miss tracking (#6427)

Detect prompt cache misses per turn by comparing each assistant message's
cache reads against the previous request's prompt tokens (core/cache-stats.ts).
Significant misses emit a warning-colored transcript notice at the turn they
occur, noting idle gaps past the cache TTL and model switches when relevant.

/session gained cache statistics: a compact token/cache breakdown with hit
rate, a $-prefixed cost section with per-model cost breakdown, and the
cumulative cost re-billed due to cache misses.
This commit is contained in:
Armin Ronacher
2026-07-09 14:12:57 +02:00
committed by GitHub
parent 57d96d72ed
commit 3f9aa5d10b
11 changed files with 471 additions and 36 deletions
@@ -20,7 +20,7 @@ function sanitizeStatusText(text: string): string {
/**
* Format token counts for compact footer display.
*/
function formatTokens(count: number): string {
export function formatTokens(count: number): string {
if (count < 1000) return count.toString();
if (count < 10000) return `${(count / 1000).toFixed(1)}k`;
if (count < 1000000) return `${Math.round(count / 1000)}k`;
@@ -137,7 +137,6 @@ export class FooterComponent implements Component {
if ((totalCacheRead > 0 || totalCacheWrite > 0) && latestCacheHitRate !== undefined) {
statsParts.push(`CH${latestCacheHitRate.toFixed(1)}%`);
}
// Show cost with "(sub)" indicator if using OAuth subscription
const usingSubscription = state.model ? this.session.modelRegistry.isUsingOAuth(state.model) : false;
if (totalCost || usingSubscription) {
@@ -65,6 +65,7 @@ export interface SettingsConfig {
terminalTheme: TerminalTheme;
availableThemes: string[];
hideThinkingBlock: boolean;
showCacheMissNotices: boolean;
collapseChangelog: boolean;
enableInstallTelemetry: boolean;
doubleEscapeAction: "fork" | "tree" | "none";
@@ -95,6 +96,7 @@ export interface SettingsCallbacks {
onThemeChange: (theme: string) => void;
onThemePreview?: (theme: string) => void;
onHideThinkingBlockChange: (hidden: boolean) => void;
onShowCacheMissNoticesChange: (shown: boolean) => void;
onCollapseChangelogChange: (collapsed: boolean) => void;
onEnableInstallTelemetryChange: (enabled: boolean) => void;
onDoubleEscapeActionChange: (action: "fork" | "tree" | "none") => void;
@@ -521,6 +523,13 @@ export class SettingsSelectorComponent extends Container {
currentValue: config.hideThinkingBlock ? "true" : "false",
values: ["true", "false"],
},
{
id: "cache-miss-notices",
label: "Cache miss notices",
description: "Show transcript notices for significant prompt-cache misses",
currentValue: config.showCacheMissNotices ? "true" : "false",
values: ["true", "false"],
},
{
id: "collapse-changelog",
label: "Collapse changelog",
@@ -764,6 +773,9 @@ export class SettingsSelectorComponent extends Container {
case "hide-thinking":
callbacks.onHideThinkingBlockChange(newValue === "true");
break;
case "cache-miss-notices":
callbacks.onShowCacheMissNoticesChange(newValue === "true");
break;
case "collapse-changelog":
callbacks.onCollapseChangelogChange(newValue === "true");
break;