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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user