@@ -173,6 +173,12 @@ class SessionStats:
173173 output_tokens : int = 0
174174 """Cumulative output tokens across all LLM requests."""
175175
176+ cache_read_tokens : int = 0
177+ """Cumulative prompt tokens served from provider caches."""
178+
179+ cache_write_tokens : int = 0
180+ """Cumulative prompt tokens written to provider caches."""
181+
176182 total_cost_usd : float = 0.0
177183 """Cumulative estimated USD cost across priceable LLM requests."""
178184
@@ -202,6 +208,8 @@ def record_request(
202208 * ,
203209 cost_usd : float | None = None ,
204210 kind : UsageKind = "assistant" ,
211+ cache_read_tokens : int = 0 ,
212+ cache_write_tokens : int = 0 ,
205213 ) -> None :
206214 """Accumulate usage for one completed LLM request.
207215
@@ -223,10 +231,14 @@ def record_request(
223231
224232 Missing estimates leave monetary totals unchanged.
225233 kind: Request class used for `/cost` type breakdowns.
234+ cache_read_tokens: Input tokens served from provider caches.
235+ cache_write_tokens: Input tokens written to provider caches.
226236 """
227237 self .request_count += 1
228238 self .input_tokens += input_toks
229239 self .output_tokens += output_toks
240+ self .cache_read_tokens += cache_read_tokens
241+ self .cache_write_tokens += cache_write_tokens
230242 if cost_usd is not None :
231243 self .total_cost_usd += cost_usd
232244 self .priced_request_count += 1
@@ -276,6 +288,8 @@ def retract_request(self, recorded: RecordedRequest) -> None:
276288 self .request_count -= 1
277289 self .input_tokens -= input_toks
278290 self .output_tokens -= output_toks
291+ self .cache_read_tokens -= recorded .cache_read_tokens
292+ self .cache_write_tokens -= recorded .cache_write_tokens
279293 if cost_usd is not None :
280294 self .total_cost_usd -= cost_usd
281295 self .priced_request_count -= 1
@@ -318,6 +332,8 @@ def merge(self, other: SessionStats) -> None:
318332 self .request_count += other .request_count
319333 self .input_tokens += other .input_tokens
320334 self .output_tokens += other .output_tokens
335+ self .cache_read_tokens += other .cache_read_tokens
336+ self .cache_write_tokens += other .cache_write_tokens
321337 self .total_cost_usd += other .total_cost_usd
322338 self .priced_request_count += other .priced_request_count
323339 self .wall_time_seconds += other .wall_time_seconds
@@ -364,6 +380,12 @@ class RecordedRequest:
364380 output_tokens : int
365381 """Running output tokens recorded so far for the request."""
366382
383+ cache_read_tokens : int
384+ """Running cache-read tokens recorded so far for the request."""
385+
386+ cache_write_tokens : int
387+ """Running cache-write tokens recorded so far for the request."""
388+
367389 cost_usd : float | None
368390 """Estimate for the whole request so far, or `None` when unpriceable."""
369391
@@ -654,13 +676,17 @@ def _move_request_to_named_model(
654676 provider ,
655677 cost_usd = cost_usd ,
656678 kind = previous .kind ,
679+ cache_read_tokens = previous .cache_read_tokens ,
680+ cache_write_tokens = previous .cache_write_tokens ,
657681 )
658682 recorded_requests [request_id ] = RecordedRequest (
659683 model_name = model_name ,
660684 provider = provider ,
661685 kind = previous .kind ,
662686 input_tokens = previous .input_tokens ,
663687 output_tokens = previous .output_tokens ,
688+ cache_read_tokens = previous .cache_read_tokens ,
689+ cache_write_tokens = previous .cache_write_tokens ,
664690 cost_usd = cost_usd ,
665691 usage_metadata = previous .usage_metadata ,
666692 finalized = previous .finalized ,
@@ -782,7 +808,7 @@ def record_message_usage(
782808 )
783809 return None
784810
785- from deepagents_code .cost_tracking import estimate_cost
811+ from deepagents_code .cost_tracking import cache_token_counts , estimate_cost
786812
787813 model_name , provider = _resolve_usage_model (
788814 message ,
@@ -816,6 +842,8 @@ def record_message_usage(
816842 # when the fallback is unpriceable, leave a priceable request showing no
817843 # cost at all.
818844 cost_usd = estimate_cost (accumulated_usage , model_name , provider )
845+ cache_reads , cache_writes = cache_token_counts (accumulated_usage )
846+ cache_write_tokens = sum (cache_writes )
819847
820848 stats .record_request (
821849 model_name ,
@@ -824,6 +852,8 @@ def record_message_usage(
824852 provider ,
825853 cost_usd = cost_usd ,
826854 kind = kind ,
855+ cache_read_tokens = cache_reads ,
856+ cache_write_tokens = cache_write_tokens ,
827857 )
828858 if request_id is not None :
829859 recorded_requests [request_id ] = RecordedRequest (
@@ -832,6 +862,8 @@ def record_message_usage(
832862 kind = kind ,
833863 input_tokens = input_count ,
834864 output_tokens = output_count ,
865+ cache_read_tokens = cache_reads ,
866+ cache_write_tokens = cache_write_tokens ,
835867 cost_usd = cost_usd ,
836868 usage_metadata = accumulated_usage ,
837869 finalized = not is_chunk ,
0 commit comments