Skip to content

Commit a30adbc

Browse files
🤖 feat: differentiate cache create vs cache read colors in costs tab (#1199)
## Summary Adds a distinct orange/amber color for **Cache Create** tokens in the costs tab, differentiating them from **Cache Read** (grey). For Anthropic models, cache create is significantly more expensive than cache read (~3.75x input cost vs 0.1x input cost). Having distinct colors makes it easy to see at a glance where costs are coming from. ## Changes - Add `--color-token-cache-create` CSS variable to all 4 themes (dark, light, solarized-dark, solarized-light) - Add `cacheCreate` key to `TOKEN_COMPONENT_COLORS` - Update `CostsTab.tsx` to use new color in both: - The token component table color indicators - The cost percentage bar visualization - Update `tokenMeterUtils.ts` `SEGMENT_DEFS` to use new color for context usage bar - Add `CostsTabWithCacheCreate` story showing the visual difference ## Color choices | Theme | Cache Create | Cache Read | |-------|-------------|------------| | Dark | `hsl(30 90% 50%)` (amber) | `hsl(0 0% 50%)` (grey) | | Light | `hsl(30 85% 45%)` (darker amber) | `hsl(210 16% 50%)` (grey) | | Solarized | `#cb4b16` (solarized orange) | `#839496` / `#586e75` (grey) | --- _Generated with `mux` • Model: `anthropic:claude-opus-4-5` • Thinking: `high`_
1 parent 49bc8af commit a30adbc

File tree

4 files changed

+62
-3
lines changed

4 files changed

+62
-3
lines changed

‎src/browser/components/RightSidebar/CostsTab.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
236236
name: "Cache Create",
237237
tokens: displayUsage.cacheCreate.tokens,
238238
cost: displayUsage.cacheCreate.cost_usd,
239-
color: TOKEN_COMPONENT_COLORS.cached,
239+
color: TOKEN_COMPONENT_COLORS.cacheCreate,
240240
show: displayUsage.cacheCreate.tokens > 0,
241241
},
242242
{
@@ -312,7 +312,7 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
312312
className="h-full transition-[width] duration-300"
313313
style={{
314314
width: `${cacheCreateCostPercentage}%`,
315-
background: TOKEN_COMPONENT_COLORS.cached,
315+
background: TOKEN_COMPONENT_COLORS.cacheCreate,
316316
}}
317317
/>
318318
)}

‎src/browser/stories/App.rightsidebar.stories.tsx‎

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,60 @@ export const CostsTab: AppStory = {
101101
},
102102
};
103103

104+
/**
105+
* Costs tab showing cache create vs cache read differentiation.
106+
* Cache create (orange) is typically more expensive than cache read (grey).
107+
* This story uses realistic Anthropic-style usage where most input is cached.
108+
*/
109+
export const CostsTabWithCacheCreate: AppStory = {
110+
render: () => (
111+
<AppWithMocks
112+
setup={() => {
113+
localStorage.setItem(RIGHT_SIDEBAR_TAB_KEY, JSON.stringify("costs"));
114+
localStorage.setItem(RIGHT_SIDEBAR_COSTS_WIDTH_KEY, "350");
115+
116+
return setupSimpleChatStory({
117+
workspaceId: "ws-cache-create",
118+
workspaceName: "feature/caching",
119+
projectName: "my-app",
120+
messages: [
121+
createUserMessage("msg-1", "Refactor the auth module", { historySequence: 1 }),
122+
createAssistantMessage("msg-2", "I'll refactor the authentication module.", {
123+
historySequence: 2,
124+
}),
125+
],
126+
sessionUsage: {
127+
byModel: {
128+
"anthropic:claude-sonnet-4-20250514": {
129+
// Realistic Anthropic usage: heavy caching, cache create is expensive
130+
input: { tokens: 2000, cost_usd: 0.006 },
131+
cached: { tokens: 45000, cost_usd: 0.0045 }, // Cache read: cheap
132+
cacheCreate: { tokens: 30000, cost_usd: 0.1125 }, // Cache create: expensive!
133+
output: { tokens: 3000, cost_usd: 0.045 },
134+
reasoning: { tokens: 0, cost_usd: 0 },
135+
model: "anthropic:claude-sonnet-4-20250514",
136+
},
137+
},
138+
version: 1,
139+
},
140+
});
141+
}}
142+
/>
143+
),
144+
play: async ({ canvasElement }) => {
145+
const canvas = within(canvasElement);
146+
147+
// Wait for costs to render - cache create should be dominant cost
148+
await waitFor(
149+
() => {
150+
canvas.getByText("Cache Create");
151+
canvas.getByText("Cache Read");
152+
},
153+
{ timeout: 5000 }
154+
);
155+
},
156+
};
157+
104158
/**
105159
* Review tab selected - click switches from Costs to Review tab
106160
* Verifies per-tab width persistence: starts at Costs width (350px), switches to Review width (700px)

‎src/browser/styles/globals.css‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@
131131
--color-token-input: hsl(120 40% 35%);
132132
--color-token-output: hsl(207 100% 40%);
133133
--color-token-cached: hsl(0 0% 50%);
134+
--color-token-cache-create: hsl(30 90% 50%);
134135

135136
/* Plan surfaces */
136137
--surface-plan-gradient: linear-gradient(
@@ -383,6 +384,7 @@
383384
--color-token-input: hsl(125 45% 36%);
384385
--color-token-output: hsl(207 90% 40%);
385386
--color-token-cached: hsl(210 16% 50%);
387+
--color-token-cache-create: hsl(30 85% 45%);
386388

387389
--surface-plan-gradient: linear-gradient(
388390
135deg,
@@ -622,6 +624,7 @@
622624
--color-token-input: #859900;
623625
--color-token-output: #268bd2;
624626
--color-token-cached: #839496;
627+
--color-token-cache-create: #cb4b16;
625628

626629
--surface-plan-gradient: linear-gradient(135deg, color-mix(in srgb, var(--color-plan-mode), transparent 94%) 0%, color-mix(in srgb, var(--color-plan-mode), transparent 97%) 100%);
627630
--surface-plan-border: color-mix(in srgb, var(--color-plan-mode), transparent 78%);
@@ -836,6 +839,7 @@
836839
--color-token-input: #859900;
837840
--color-token-output: #268bd2;
838841
--color-token-cached: #586e75;
842+
--color-token-cache-create: #cb4b16;
839843

840844
--surface-plan-gradient: linear-gradient(135deg, color-mix(in srgb, var(--color-plan-mode), transparent 92%) 0%, color-mix(in srgb, var(--color-plan-mode), transparent 95%) 100%);
841845
--surface-plan-border: color-mix(in srgb, var(--color-plan-mode), transparent 70%);

‎src/common/utils/tokens/tokenMeterUtils.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { supports1MContext } from "../ai/models";
44

55
export const TOKEN_COMPONENT_COLORS = {
66
cached: "var(--color-token-cached)",
7+
cacheCreate: "var(--color-token-cache-create)",
78
input: "var(--color-token-input)",
89
output: "var(--color-token-output)",
910
thinking: "var(--color-thinking-mode)",
@@ -35,7 +36,7 @@ const SEGMENT_DEFS: SegmentDef[] = [
3536
{
3637
type: "cacheCreate",
3738
key: "cacheCreate",
38-
color: TOKEN_COMPONENT_COLORS.cached,
39+
color: TOKEN_COMPONENT_COLORS.cacheCreate,
3940
label: "Cache Create",
4041
},
4142
{ type: "input", key: "input", color: TOKEN_COMPONENT_COLORS.input, label: "Input" },

0 commit comments

Comments
 (0)