Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/browser/components/RightSidebar/CostsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
name: "Cache Create",
tokens: displayUsage.cacheCreate.tokens,
cost: displayUsage.cacheCreate.cost_usd,
color: TOKEN_COMPONENT_COLORS.cached,
color: TOKEN_COMPONENT_COLORS.cacheCreate,
show: displayUsage.cacheCreate.tokens > 0,
},
{
Expand Down Expand Up @@ -312,7 +312,7 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
className="h-full transition-[width] duration-300"
style={{
width: `${cacheCreateCostPercentage}%`,
background: TOKEN_COMPONENT_COLORS.cached,
background: TOKEN_COMPONENT_COLORS.cacheCreate,
}}
/>
)}
Expand Down
54 changes: 54 additions & 0 deletions src/browser/stories/App.rightsidebar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,60 @@ export const CostsTab: AppStory = {
},
};

/**
* Costs tab showing cache create vs cache read differentiation.
* Cache create (orange) is typically more expensive than cache read (grey).
* This story uses realistic Anthropic-style usage where most input is cached.
*/
export const CostsTabWithCacheCreate: AppStory = {
render: () => (
<AppWithMocks
setup={() => {
localStorage.setItem(RIGHT_SIDEBAR_TAB_KEY, JSON.stringify("costs"));
localStorage.setItem(RIGHT_SIDEBAR_COSTS_WIDTH_KEY, "350");

return setupSimpleChatStory({
workspaceId: "ws-cache-create",
workspaceName: "feature/caching",
projectName: "my-app",
messages: [
createUserMessage("msg-1", "Refactor the auth module", { historySequence: 1 }),
createAssistantMessage("msg-2", "I'll refactor the authentication module.", {
historySequence: 2,
}),
],
sessionUsage: {
byModel: {
"anthropic:claude-sonnet-4-20250514": {
// Realistic Anthropic usage: heavy caching, cache create is expensive
input: { tokens: 2000, cost_usd: 0.006 },
cached: { tokens: 45000, cost_usd: 0.0045 }, // Cache read: cheap
cacheCreate: { tokens: 30000, cost_usd: 0.1125 }, // Cache create: expensive!
output: { tokens: 3000, cost_usd: 0.045 },
reasoning: { tokens: 0, cost_usd: 0 },
model: "anthropic:claude-sonnet-4-20250514",
},
},
version: 1,
},
});
}}
/>
),
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);

// Wait for costs to render - cache create should be dominant cost
await waitFor(
() => {
canvas.getByText("Cache Create");
canvas.getByText("Cache Read");
},
{ timeout: 5000 }
);
},
};

/**
* Review tab selected - click switches from Costs to Review tab
* Verifies per-tab width persistence: starts at Costs width (350px), switches to Review width (700px)
Expand Down
4 changes: 4 additions & 0 deletions src/browser/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
--color-token-input: hsl(120 40% 35%);
--color-token-output: hsl(207 100% 40%);
--color-token-cached: hsl(0 0% 50%);
--color-token-cache-create: hsl(30 90% 50%);

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

--surface-plan-gradient: linear-gradient(
135deg,
Expand Down Expand Up @@ -622,6 +624,7 @@
--color-token-input: #859900;
--color-token-output: #268bd2;
--color-token-cached: #839496;
--color-token-cache-create: #cb4b16;

--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%);
--surface-plan-border: color-mix(in srgb, var(--color-plan-mode), transparent 78%);
Expand Down Expand Up @@ -836,6 +839,7 @@
--color-token-input: #859900;
--color-token-output: #268bd2;
--color-token-cached: #586e75;
--color-token-cache-create: #cb4b16;

--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%);
--surface-plan-border: color-mix(in srgb, var(--color-plan-mode), transparent 70%);
Expand Down
3 changes: 2 additions & 1 deletion src/common/utils/tokens/tokenMeterUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { supports1MContext } from "../ai/models";

export const TOKEN_COMPONENT_COLORS = {
cached: "var(--color-token-cached)",
cacheCreate: "var(--color-token-cache-create)",
input: "var(--color-token-input)",
output: "var(--color-token-output)",
thinking: "var(--color-thinking-mode)",
Expand Down Expand Up @@ -35,7 +36,7 @@ const SEGMENT_DEFS: SegmentDef[] = [
{
type: "cacheCreate",
key: "cacheCreate",
color: TOKEN_COMPONENT_COLORS.cached,
color: TOKEN_COMPONENT_COLORS.cacheCreate,
label: "Cache Create",
},
{ type: "input", key: "input", color: TOKEN_COMPONENT_COLORS.input, label: "Input" },
Expand Down