Skip to content

v0.117.0

Choose a tag to compare

@github-actions github-actions released this 05 Sep 21:21
· 64 commits to main since this release

v0.117.0 — Anthropic reports its reasoning tokens

Anthropic puts reasoning at usage.output_tokens_details.thinking_tokens, and
every Anthropic mapping in this package ignored it, so $usage->thoughtTokens
was null on every Anthropic call. Reported by the Moic Suite team (#33),
measured against the live API rather than inferred.

That matters more than a missing field usually would. Adaptive thinking makes
the model decide WHETHER to reason per request, so with the field unset
"reasoning is off", "the model judged this easy" and "it reasoned hard" are
indistinguishable — and the last one is the expensive case.

Wired at all five construction sites rather than the one the issue named: Text,
Structured, both streaming paths (message_start carries the first usage block,
message_delta the final output count) and batch results. The streaming delta
carries the earlier value forward rather than dropping it, for the same reason
it already carries the prompt and cache counts.

Anthropic was the only provider missing this. OpenAI, Gemini, OpenRouter,
DeepSeek, Vertex and Requesty all set it.

WORTH READING BEFORE YOU PRICE ANYTHING: thinking tokens are a BREAKDOWN of
completionTokens, not an addition to them — 1240 of reasoning inside 2820 of
output, not beside them. Code that prices completion + thought double-counts
the expensive half, and that arithmetic was silently correct while the field was
always null. It stops being correct with this release. The property's docblock
now says which it is, because the field is still null on providers that do not
report it and a null reads as "no thinking" rather than "not measured".

Verified against the live API before tagging, not just under test: a real
Anthropic call through a consuming application recorded 230 reasoning tokens
inside 597 output, where the 279 Anthropic calls before it had all recorded
null. That exercise immediately found the double-count above in the consumer,
which is the argument for doing it.

Also in this release: the release workflow reads its notes from the tag
annotation via the GitHub API. Three earlier mechanisms each published something
plausible instead — --generate-notes substituted commit subjects,
--notes-from-tag and git tag -l %(contents) both substituted the last commit
message, because actions/checkout creates a lightweight tag. Every one of them
succeeded loudly and published the wrong text. This is the first release to run
the corrected path.