#22895·desktop

OpenRouter costs in the cline visual studio code extension always show as 0 after a recent cline desktop update

Author: DeanBeanBEER-WARECreated Sep 17, 2026Updated Sep 17, 2026
Labelsneeds-triage

The problem

Since a recent extension update, OpenRouter costs always show as 0 in the task header and task history, regardless of the model. This worked before.

Both cost sources appear to be available: OpenRouter reports per-request billing through usage.cost (see its “Usage Accounting” docs), and the bundled models.dev catalog includes non-zero pricing. For example, I verified that anthropic/claude-sonnet-5 has input/output/cache-read/cache-write prices of 2 / 10 / 0.2 / 2.5 per million tokens.

Suspected regression: PR #14012

PR #14012, “fix(llms): report zero cost for Cline Pass and free models,” merged on 2026-09-10 to address CLINE-3225, “Show ClinePass cost as 0.” It added an includedClineUsage guard in normalizeUsage() that forces totalCost to 0 when any of these conditions hold:

The provider is cline-pass.

The provider is cline and the model matches the cline-pass/, cline-free/, or :free checks. The resolved catalog pricing has input and output set to 0, with cacheRead and cacheWrite also 0 or missing. The last condition isn’t restricted to Cline providers. It applies to OpenRouter too, and takes precedence over explicit upstream costs and the pricing fallback.

That matters because zero pricing in the catalog doesn’t necessarily mean free usage. In catalog-live.ts, toModelInfo() defaults missing prices to 0, for example with input: model.cost?.input ?? 0. The bundled catalog contains many all-zero entries, including anthropic/claude-sonnet-4-6.

So, for an affected entry, this guard can discard a non-zero cost reported by OpenRouter simply because the catalog represents unknown pricing as zero.

The timing fits: releases built after September 10 ship this guard. It doesn’t explain every case, though. For a model with non-zero resolved pricing, such as anthropic/claude-sonnet-5, the guard shouldn’t trigger. If that model also shows 0, a second breakpoint worth checking is whether OpenRouter’s usage.cost survives the AI SDK usage layer and reaches usage.raw.

Where the cost flows

The display layer appears to be handling the values it receives correctly:

In sdk/packages/llms/src/providers/ai-sdk.ts, normalizeUsage() derives totalCost from explicit response fields (usage.raw.cost, market_cost, upstream_inference_cost, or providerMetadata.gateway.cost), or falls back to calculateUsageCostFromPricing(). The fallback uses context.model.metadata?.pricing, passed at the emitAiSdkEvents() call site around line 2372.

In apps/vscode/src/sdk/message-translator.ts, normalizeUsageEvent() uses usageEvent.cost ?? usageEvent.totalCost ?? 0 around line 109.

apps/vscode/src/shared/getApiMetrics.ts accumulates usage for the header, and updateTaskUsage() in apps/vscode/src/sdk/sdk-task-history.ts persists per-task totals.

Once a zero reaches the usage events, the header, per-request row, and history all correctly display 0. That points upstream of the display layer.

Suggested fixes and diagnostics

The zero-pricing check should either be restricted to cline / cline-pass, or replaced with positive evidence that usage is included, such as an explicit route prefix. For non-Cline providers, a zero-pricing heuristic shouldn’t override an explicit provider-reported cost such as usage.cost or upstream_inference_cost.

It would also help to distinguish unknown pricing from zero pricing in the catalog rather than defaulting both to 0.

To narrow this down, capture the raw OpenRouter SSE final chunk, which, according to its docs, always contains usage.cost, alongside the resolved catalog pricing for the same request.

The extension also logs this on every turn from updateTaskUsage() in sdk-task-history.ts:

[SdkController] Task usage: tokensIn=..., tokensOut=..., cost=...

If that log shows cost=0 while the raw response contains a non-zero usage.cost, tracing the value into normalizeUsage() should distinguish a guard override from the raw cost not reaching the normalizer.

Release version

0.0.30

Operating system

macOS 26.6.2

Steps to reproduce the behavior

  1. Install the latest version of cline desktop and the cline VSC extension
  2. Configure an open-router API-Key and choose anthropic/claude-sonnet-5
  3. Run a query inside the extension while cline desktop is open
  4. Cost should always show 0

Log files

No response

Screenshots

No response

Additional context

No response