Files
werkrevisor/docs/prs/2026-10-06-PR#24-billed-provider-calls.md
claude-code d7e9afa737
werkator build succeeded after 00:09
werkator/server build succeeded after 00:27
werkrevisor 0.18.3: billed OpenRouter calls fill the time before the statistics service (#24)
Co-authored-by: claude-code <claude-code@javagil.de>
2026-10-06 12:16:33 +02:00

5.2 KiB

PR#24: the dashboard counts the billed OpenRouter calls from before the service

WARNING: This document describes only the change applied in this PR. It may already be outdated once the next PR is merged. Historic PR documentation is not maintained along with new PRs; treat it as a snapshot.

The Problem

The statistics service of werkrevisor 0.18.0 stores the usage record of each run since 2026-10-06T09:13:41Z. The reviews and trial runs before that cost about 10 USD at OpenRouter, but the dashboard does not show them. So the costs of the first days and the token ratio of models such as GPT-6 Astra and DeepSeek V4 Pro are missing.

OpenRouter exports each call as one CSV row, with an id, the time in UTC, the model, the billed amount and the tokens. Such a row has no pull request: the review that caused it cannot be found again.

Non-Goals

  • No pull requests, reviews or verdicts for billed calls: the CSV does not tell them.
  • No calls from the time that the service already records: they would count twice.
  • No regular comparison with the bill; this import fills the time before the service once.

The Scenarios

Feature: billed calls fill the time before the service

Scenario#24.01: a billed call counts in the costs and tokens, not in the reviews

So that the dashboard shows what werkrevisor cost since its first run.

  • Given OpenRouter billed a call of Claude Sonnet 5.5 for 0.07 USD, with 31000 input and 850 output tokens, before the first usage record
  • When the operator imports the call
    • and someone opens the dashboard with a read token
  • Then the card of its period shows "Billed earlier: 1 call = 0.0700 USD" below the total
    • and the table per model holds its tokens in the line of Claude Sonnet 5.5
    • and the numbers of reviews and pull requests do not change
Verified by

Scenario#24.02: a call from the time of the service is not imported

So that no call counts twice.

  • Given the first usage record is from 2026-10-06T09:13:41Z
    • and a run writes its usage record at its end
  • When the operator imports a call from <time>
  • Then the call <result>
time result
2026-10-06T08:21:43Z, an earlier run counts
2026-10-06T09:13:33Z, the run of the first usage record does not count
2026-10-06T09:22:29Z, a later run does not count
Verified by

Scenario#24.03: an import repeated with the same file changes nothing

So that the operator can repeat an import after an error.

  • Given the operator imported a CSV file
  • When the operator imports the same file again
  • Then each call counts once
Verified by

Scenario#24.04: the import uses the model names of the usage records

So that a model has one line in the table per model.

  • Given the CSV names the model anthropic/claude-sonnet-5.5-20260928
  • When the operator imports the CSV
  • Then the table per model shows the call in the line anthropic/claude-sonnet-5.5, together with the reviews of this model
Verified by

The Solution

  • POST /api/billed-calls stores billed calls with a source token in the table billed_call, keyed by the provider's id; it skips calls from 10 minutes before the first usage record on, since that record is written at the end of its run, and answers how many it stored, found again or skipped; without a usage record it stores nothing, since the cut-off is then unknown.
  • Each sum holds billedCostUsd and billedCalls; costUsd and the token counts include them, the cost per pull request does not, since a billed call has no pull request.
  • The Web Component lists the billed part with "=" below the total, if a period has one; the table per model includes billed calls, the tables per repository and per verdict do not.
  • tools/import-openrouter-activity <csv> reads the activity export of OpenRouter, removes the date suffix of the model, and sends the calls in parts of 500; a cancelled call counts with the amount that OpenRouter billed for it.
  • werkrevisor 0.18.3.

Measurement

On 2026-10-06, the service ran locally with a copy of the live database and imported the OpenRouter export of 65 calls. It stored 61 calls for 9.76 USD and skipped 4 calls from the first run with a usage record on; a second import stored none. Each card showed "Billed earlier: 61 calls = 9.76 USD" in one line; the table per model showed 4 models, with 24 : 1 for GPT-6 Astra and 88 : 1 for Claude Sonnet 5.5.

Prerequisite PRs

  • PR#23: input and output tokens per model.