Skip to content

cost: read qwen's usage log - #420

Merged
ralyodio merged 1 commit into
mainfrom
cost-qwen-reader
Aug 17, 2026
Merged

cost: read qwen's usage log#420
ralyodio merged 1 commit into
mainfrom
cost-qwen-reader

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Follow-on to #418. /usage covers whatever /agents launched — but only for engines with a reader, and qwen was listed as one that keeps no readable record. That has stopped being true, so a qwen session showed up nowhere in the report.

qwen writes:

  • ~/.qwen/usage/token-usage-YYYY-MM.jsonl — one record per request: timestamp, sessionId, model, and the token counts
  • ~/.qwen/projects/<slug>/chats/<session>.runtime.json — a tiny file carrying work_dir, which is the only exact directory on disk (the project slug is lossy, like Claude's)

So the reader groups requests by session, and attributes each session to the directory qwen was started in — subagent requests carry the session that spawned them, so they land on the right run.

The arithmetic

Both traps were checked against qwen-code's own response conversion, not guessed:

  • cachedTokens is part of inputTokens, so fresh input is the difference — counting both would bill the cache twice at the full input rate.
  • thoughtsTokens is already inside outputTokens on the OpenAI-compatible path (authType: "openai", where outputTokens is completion_tokens and that contains reasoning_tokens), so adding it would double-count thinking. The native path reports Gemini's candidatesTokenCount, which excludes thoughts — that is the one case where they are added back.

No Alibaba rates are shipped; that stays deliberate. qwen runs report tokens with no cost, and the report already prints how to price them in ~/.moshcode/pricing.json.

Verification

Against this machine's real log: 314,485 in / 54,574 out / 8.34M cached across 3 sessions, matching a raw sum of the file, with the two known directories attributed correctly.

Five new tests cover the session sum, cache netting, both thinking paths, the cwd filter, the window, and a session with no runtime file. Full suite: 1980 passing, 0 failing.

Still uncosted: gemini, kimi, deepseek, openagents — none are installed here, so there was nothing to verify a reader against.

🤖 Generated with Claude Code

qwen was listed as an engine that keeps no readable record, and that has
stopped being true: it appends one record per request to
~/.qwen/usage/token-usage-YYYY-MM.jsonl, and writes the directory it was
started in to ~/.qwen/projects/<slug>/chats/<session>.runtime.json. So a
qwen session launched through /agents showed up nowhere in /usage.

Two pieces of its arithmetic are easy to get wrong, and both are checked
against qwen-code's own conversion rather than guessed:

- `cachedTokens` is part of `inputTokens`, so fresh input is the
  difference — the same trap codex's cumulative counts have.
- `thoughtsTokens` is already inside `outputTokens` on the
  OpenAI-compatible path (`completion_tokens` contains `reasoning_tokens`),
  so adding it would double-count the thinking. Only the native path,
  which reports Gemini's `candidatesTokenCount`, has to add it back.

No Alibaba rates are shipped — that stays deliberate — so qwen runs report
tokens and no cost, and the report already says how to price them.

Verified against this machine's real log: 314,485 in / 54,574 out /
8.34M cached across 3 sessions, matching a raw sum of the file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

3 finding(s) in the 3 file(s) this pull request changes.

MEDIUM: 3

Severity Rule Location
MEDIUM sql-string-concatenation src/cli-schema.mjs:161
MEDIUM sql-string-concatenation src/cli-schema.mjs:460
MEDIUM sql-string-concatenation src/cli-schema.mjs:586
52 pre-existing finding(s) elsewhere in the repository — **HIGH/CRITICAL**: 5 | **MEDIUM**: 41 | **LOW**: 6

Not introduced by this pull request. The full set is in the Security tab.

Severity Rule Location
HIGH js-ssrf-outbound-request apps/pwa/public/sw.js:45
HIGH tls-verification-disabled apps/pwa/src/lib/moshpit-gateway.mjs:299
HIGH sh-remote-script-execution install.sh:79
HIGH sh-remote-script-execution install.sh:83
HIGH tls-verification-disabled src/dns.mjs:741
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:68
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:82
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:108
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:295
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:299
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:344
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:568
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:749
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:751
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:810
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:856
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:926
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:1029
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:1052
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:1074

…and 32 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit e8bbb91 into main Aug 17, 2026
4 checks passed
@ralyodio
ralyodio deleted the cost-qwen-reader branch August 17, 2026 03:14
@ralyodio ralyodio mentioned this pull request Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant