An aborted model call reports its input usage (#180)
A model call cut short by a Stop or interrupt, or failed after the provider started answering, now carries the usage the provider reported before the cut on its result. Before this release it carried none, so the input tokens the provider billed for it were never booked. This is a minor release of @helix-agents/llm-vercel and a patch release of @helix-agents/core (documentation only). Nothing is removed or renamed.
What changes
- The result of such a call (the partial text of a call stopped mid-stream, or an error result), the
afterLLMCallhook'susageand the usage store'stokensentry now carry the call's input side:promptTokens, the total input: uncached + read from cache + written to cache, the same value a completed call reports;cachedTokensandcacheWriteTokens, when the provider reported them.
- It is a lower bound. The provider reports the output count only at the end of the stream, so the output generated before the cut is not known.
completionTokensandtotalTokensare absent (not 0). A provisional output count sent at the start is not used. - No
step_endusage is written for the cut call.
Which calls
| Model | A call cut short reports |
|---|---|
@helix-agents/llm-vercel with an @ai-sdk/anthropic model object | its input and cache tokens |
The same, through an Anthropic-format proxy (for example LiteLLM's /v1/messages) | its input and cache tokens |
An OpenAI-compatible route (/chat/completions): usage arrives only in the last chunk | nothing |
| A gateway model id string, or a V2 model object | nothing |
What to check
- Cost and budgets: compute them from the per-kind fields (
prompt,completion,cached,cacheWrite), never fromtotal. After an interrupted call, a session'stokens.totalsums only the calls that reported a total, so it is less thanprompt + completion. - Code that read a cut call's missing usage as "nothing was billed": its result now carries usage. Book it. A stopped call's partial
textresult carries input-only usage, with no marker that it is partial; readcompletionTokensbeing absent as "output not reported". - A custom adapter wrapper: keep forwarding the result's
usageunchanged.
See the usage guide, Calls cut short.