Skip to content

Commit 1a9aa13

Browse files
authored
Use upstream_inference_cost for OpenRouter BYOK cost calculation and show cached token count (#5145)
Improve OpenRouter cache calculation and show cached tokens
1 parent c4594cc commit 1a9aa13

File tree

5 files changed

+23
-33
lines changed

5 files changed

+23
-33
lines changed

src/api/providers/openrouter.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,11 @@ interface CompletionUsage {
4848
}
4949
total_tokens?: number
5050
cost?: number
51-
is_byok?: boolean
51+
cost_details?: {
52+
upstream_inference_cost?: number
53+
}
5254
}
5355

54-
// with bring your own key, OpenRouter charges 5% of what it normally would: https://openrouter.ai/docs/use-cases/byok
55-
// so we multiply the cost reported by OpenRouter to get an estimate of what the request actually cost
56-
const BYOK_COST_MULTIPLIER = 20
57-
5856
export class OpenRouterHandler extends BaseProvider implements SingleCompletionHandler {
5957
protected options: ApiHandlerOptions
6058
private client: OpenAI
@@ -168,11 +166,9 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH
168166
type: "usage",
169167
inputTokens: lastUsage.prompt_tokens || 0,
170168
outputTokens: lastUsage.completion_tokens || 0,
171-
// Waiting on OpenRouter to figure out what this represents in the Gemini case
172-
// and how to best support it.
173-
// cacheReadTokens: lastUsage.prompt_tokens_details?.cached_tokens,
169+
cacheReadTokens: lastUsage.prompt_tokens_details?.cached_tokens,
174170
reasoningTokens: lastUsage.completion_tokens_details?.reasoning_tokens,
175-
totalCost: (lastUsage.is_byok ? BYOK_COST_MULTIPLIER : 1) * (lastUsage.cost || 0),
171+
totalCost: (lastUsage.cost_details?.upstream_inference_cost || 0) + (lastUsage.cost || 0),
176172
}
177173
}
178174
}

webview-ui/src/__tests__/ContextWindowProgress.spec.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ describe("ContextWindowProgress", () => {
5151
task: { ts: Date.now(), type: "say" as const, say: "text" as const, text: "Test task" },
5252
tokensIn: 100,
5353
tokensOut: 50,
54-
doesModelSupportPromptCache: true,
5554
totalCost: 0.001,
5655
contextTokens: 1000,
5756
onClose: vi.fn(),

webview-ui/src/components/chat/ChatView.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1371,7 +1371,6 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
13711371
task={task}
13721372
tokensIn={apiMetrics.totalTokensIn}
13731373
tokensOut={apiMetrics.totalTokensOut}
1374-
doesModelSupportPromptCache={model?.supportsPromptCache ?? false}
13751374
cacheWrites={apiMetrics.totalCacheWrites}
13761375
cacheReads={apiMetrics.totalCacheReads}
13771376
totalCost={apiMetrics.totalCost}

webview-ui/src/components/chat/TaskHeader.tsx

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ export interface TaskHeaderProps {
2525
task: ClineMessage
2626
tokensIn: number
2727
tokensOut: number
28-
doesModelSupportPromptCache: boolean
2928
cacheWrites?: number
3029
cacheReads?: number
3130
totalCost: number
@@ -39,7 +38,6 @@ const TaskHeader = ({
3938
task,
4039
tokensIn,
4140
tokensOut,
42-
doesModelSupportPromptCache,
4341
cacheWrites,
4442
cacheReads,
4543
totalCost,
@@ -186,25 +184,24 @@ const TaskHeader = ({
186184
{!totalCost && <TaskActions item={currentTaskItem} buttonsDisabled={buttonsDisabled} />}
187185
</div>
188186

189-
{doesModelSupportPromptCache &&
190-
((typeof cacheReads === "number" && cacheReads > 0) ||
191-
(typeof cacheWrites === "number" && cacheWrites > 0)) && (
192-
<div className="flex items-center gap-1 flex-wrap h-[20px]">
193-
<span className="font-bold">{t("chat:task.cache")}</span>
194-
{typeof cacheWrites === "number" && cacheWrites > 0 && (
195-
<span className="flex items-center gap-0.5">
196-
<CloudUpload size={16} />
197-
{formatLargeNumber(cacheWrites)}
198-
</span>
199-
)}
200-
{typeof cacheReads === "number" && cacheReads > 0 && (
201-
<span className="flex items-center gap-0.5">
202-
<CloudDownload size={16} />
203-
{formatLargeNumber(cacheReads)}
204-
</span>
205-
)}
206-
</div>
207-
)}
187+
{((typeof cacheReads === "number" && cacheReads > 0) ||
188+
(typeof cacheWrites === "number" && cacheWrites > 0)) && (
189+
<div className="flex items-center gap-1 flex-wrap h-[20px]">
190+
<span className="font-bold">{t("chat:task.cache")}</span>
191+
{typeof cacheWrites === "number" && cacheWrites > 0 && (
192+
<span className="flex items-center gap-0.5">
193+
<CloudUpload size={16} />
194+
{formatLargeNumber(cacheWrites)}
195+
</span>
196+
)}
197+
{typeof cacheReads === "number" && cacheReads > 0 && (
198+
<span className="flex items-center gap-0.5">
199+
<CloudDownload size={16} />
200+
{formatLargeNumber(cacheReads)}
201+
</span>
202+
)}
203+
</div>
204+
)}
208205

209206
{!!totalCost && (
210207
<div className="flex justify-between items-center h-[20px]">

webview-ui/src/components/chat/__tests__/TaskHeader.spec.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ describe("TaskHeader", () => {
4949
task: { type: "say", ts: Date.now(), text: "Test task", images: [] },
5050
tokensIn: 100,
5151
tokensOut: 50,
52-
doesModelSupportPromptCache: true,
5352
totalCost: 0.05,
5453
contextTokens: 200,
5554
buttonsDisabled: false,

0 commit comments

Comments
 (0)