92 """Fold a lane's ``usage`` block into :class:`UsageStats`.
94 Handles the dialect variants named in the module docstring; unknown
95 extra keys are ignored, so a lane that grows a field does not break
98 func =
"normalise_usage"
103 prompt =
_as_int(block.get(
"prompt_tokens"))
104 completion =
_as_int(block.get(
"completion_tokens"))
105 reported_total =
_as_int(block.get(
"total_tokens"))
106 total = reported_total
or (prompt + completion)
108 completion_details =
_as_dict(block.get(
"completion_tokens_details"))
109 prompt_details =
_as_dict(block.get(
"prompt_tokens_details"))
111 reasoning =
_as_int(completion_details.get(
"reasoning_tokens"))
112 cached =
_as_int(prompt_details.get(
"cached_tokens"))
113 hit = min(cached, prompt)
if prompt
else cached
114 miss = max(0, prompt - hit)
116 _dbg(
"OC_CHAT.CLIENT", func,
117 f
"prompt={prompt} completion={completion} total={total} "
118 f
"reasoning={reasoning} cache_hit={hit}", 4)
120 prompt_tokens=prompt,
121 completion_tokens=completion,
125 cache_hit_tokens=hit
if cached
else 0,
126 cache_miss_tokens=miss
if cached
else 0,
127 reasoning_tokens=reasoning,