@@ -337,6 +337,8 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
337
337
component = AnthropicChatGenerator (api_key = Secret .from_token ("test-api-key" ))
338
338
component_info = ComponentInfo .from_component (component )
339
339
340
+ raw_chunks = []
341
+
340
342
# Test message_start chunk
341
343
message_start_chunk = RawMessageStartEvent (
342
344
message = Message (
@@ -358,6 +360,7 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
358
360
),
359
361
type = "message_start" ,
360
362
)
363
+ raw_chunks .append (message_start_chunk )
361
364
streaming_chunk = component ._convert_anthropic_chunk_to_streaming_chunk (
362
365
message_start_chunk , component_info = component_info , tool_call_index = 0
363
366
)
@@ -373,6 +376,7 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
373
376
text_block_start_chunk = RawContentBlockStartEvent (
374
377
content_block = TextBlock (citations = None , text = "" , type = "text" ), index = 0 , type = "content_block_start"
375
378
)
379
+ raw_chunks .append (text_block_start_chunk )
376
380
streaming_chunk = component ._convert_anthropic_chunk_to_streaming_chunk (
377
381
text_block_start_chunk , component_info = component_info , tool_call_index = 0
378
382
)
@@ -390,6 +394,7 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
390
394
index = 0 ,
391
395
type = "content_block_delta" ,
392
396
)
397
+ raw_chunks .append (text_delta_chunk )
393
398
streaming_chunk = component ._convert_anthropic_chunk_to_streaming_chunk (
394
399
text_delta_chunk , component_info = component_info , tool_call_index = 0
395
400
)
@@ -414,6 +419,7 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
414
419
index = 1 ,
415
420
type = "content_block_start" ,
416
421
)
422
+ raw_chunks .append (tool_block_start_chunk )
417
423
streaming_chunk = component ._convert_anthropic_chunk_to_streaming_chunk (
418
424
tool_block_start_chunk , component_info = component_info , tool_call_index = 0
419
425
)
@@ -431,6 +437,7 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
431
437
empty_json_delta_chunk = RawContentBlockDeltaEvent (
432
438
delta = InputJSONDelta (partial_json = "" , type = "input_json_delta" ), index = 1 , type = "content_block_delta"
433
439
)
440
+ raw_chunks .append (empty_json_delta_chunk )
434
441
streaming_chunk = component ._convert_anthropic_chunk_to_streaming_chunk (
435
442
empty_json_delta_chunk , component_info = component_info , tool_call_index = 0
436
443
)
@@ -450,6 +457,7 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
450
457
index = 1 ,
451
458
type = "content_block_delta" ,
452
459
)
460
+ raw_chunks .append (json_delta_chunk )
453
461
streaming_chunk = component ._convert_anthropic_chunk_to_streaming_chunk (
454
462
json_delta_chunk , component_info = component_info , tool_call_index = 0
455
463
)
@@ -473,6 +481,7 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
473
481
server_tool_use = None ,
474
482
),
475
483
)
484
+ raw_chunks .append (message_delta_chunk )
476
485
streaming_chunk = component ._convert_anthropic_chunk_to_streaming_chunk (
477
486
message_delta_chunk , component_info = component_info , tool_call_index = 0
478
487
)
@@ -496,6 +505,7 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
496
505
index = 2 ,
497
506
type = "content_block_start" ,
498
507
)
508
+ raw_chunks .append (tool_block_start_chunk )
499
509
streaming_chunk = component ._convert_anthropic_chunk_to_streaming_chunk (
500
510
tool_block_start_chunk , component_info = component_info , tool_call_index = 1
501
511
)
@@ -513,6 +523,7 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
513
523
empty_json_delta_chunk = RawContentBlockDeltaEvent (
514
524
delta = InputJSONDelta (partial_json = "" , type = "input_json_delta" ), index = 1 , type = "content_block_delta"
515
525
)
526
+ raw_chunks .append (empty_json_delta_chunk )
516
527
streaming_chunk = component ._convert_anthropic_chunk_to_streaming_chunk (
517
528
empty_json_delta_chunk , component_info = component_info , tool_call_index = 1
518
529
)
@@ -532,6 +543,7 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
532
543
index = 2 ,
533
544
type = "content_block_delta" ,
534
545
)
546
+ raw_chunks .append (json_delta_chunk )
535
547
streaming_chunk = component ._convert_anthropic_chunk_to_streaming_chunk (
536
548
json_delta_chunk , component_info = component_info , tool_call_index = 1
537
549
)
@@ -555,6 +567,7 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
555
567
server_tool_use = None ,
556
568
),
557
569
)
570
+ raw_chunks .append (message_delta_chunk )
558
571
streaming_chunk = component ._convert_anthropic_chunk_to_streaming_chunk (
559
572
message_delta_chunk , component_info = component_info , tool_call_index = 0
560
573
)
@@ -574,6 +587,16 @@ def test_convert_anthropic_completion_chunks_with_multiple_tool_calls_to_streami
574
587
# message_stop_chunk = RawMessageStopEvent(type="message_stop")
575
588
# but we don't stream it
576
589
590
+ generator = AnthropicChatGenerator (Secret .from_token ("test-api-key" ))
591
+ message = generator ._process_response (raw_chunks )
592
+ assert message ["replies" ][0 ].meta ["usage" ] == {
593
+ "cache_creation_input_tokens" : None ,
594
+ "cache_read_input_tokens" : None ,
595
+ "input_tokens" : 393 ,
596
+ "output_tokens" : 77 ,
597
+ "server_tool_use" : None ,
598
+ }
599
+
577
600
def test_convert_streaming_chunks_to_chat_message_with_multiple_tool_calls (self ):
578
601
"""
579
602
Test converting streaming chunks to a chat message with tool calls
@@ -703,7 +726,7 @@ def test_convert_streaming_chunks_to_chat_message_with_multiple_tool_calls(self)
703
726
meta = {
704
727
"type" : "message_delta" ,
705
728
"delta" : {"stop_reason" : "tool_calls" , "stop_sequence" : None },
706
- "usage" : {"completion_tokens " : 40 },
729
+ "usage" : {"output_tokens " : 40 },
707
730
},
708
731
component_info = ComponentInfo .from_component (self ),
709
732
finish_reason = "tool_calls" ,
@@ -728,7 +751,7 @@ def test_convert_streaming_chunks_to_chat_message_with_multiple_tool_calls(self)
728
751
# Verify meta information
729
752
assert message ._meta ["index" ] == 0
730
753
assert message ._meta ["finish_reason" ] == "tool_calls"
731
- assert message ._meta ["usage" ] == {"completion_tokens " : 40 }
754
+ assert message ._meta ["usage" ] == {"output_tokens " : 40 }
732
755
733
756
def test_convert_streaming_chunks_to_chat_message_tool_call_with_empty_arguments (self ):
734
757
"""
@@ -815,7 +838,7 @@ def test_convert_streaming_chunks_to_chat_message_tool_call_with_empty_arguments
815
838
meta = {
816
839
"type" : "message_delta" ,
817
840
"delta" : {"stop_reason" : "tool_calls" , "stop_sequence" : None },
818
- "usage" : {"completion_tokens " : 40 },
841
+ "usage" : {"output_tokens " : 40 },
819
842
},
820
843
component_info = ComponentInfo .from_component (self ),
821
844
index = 1 ,
@@ -838,7 +861,7 @@ def test_convert_streaming_chunks_to_chat_message_tool_call_with_empty_arguments
838
861
# Verify meta information
839
862
assert message ._meta ["index" ] == 0
840
863
assert message ._meta ["finish_reason" ] == "tool_calls"
841
- assert message ._meta ["usage" ] == {"completion_tokens " : 40 }
864
+ assert message ._meta ["usage" ] == {"output_tokens " : 40 }
842
865
843
866
def test_serde_in_pipeline (self ):
844
867
tool = Tool (name = "name" , description = "description" , parameters = {"x" : {"type" : "string" }}, function = print )
@@ -971,9 +994,10 @@ def __call__(self, chunk: StreamingChunk) -> None:
971
994
972
995
assert "claude-sonnet-4-20250514" in message .meta ["model" ]
973
996
assert message .meta ["finish_reason" ] == "stop"
974
-
975
997
assert callback .counter > 1
976
998
assert "Paris" in callback .responses
999
+ assert "input_tokens" in message .meta ["usage" ]
1000
+ assert "output_tokens" in message .meta ["usage" ]
977
1001
978
1002
def test_convert_message_to_anthropic_format (self ):
979
1003
"""
@@ -1171,6 +1195,7 @@ def test_live_run_with_tools(self, tools):
1171
1195
assert tool_call .tool_name == "weather"
1172
1196
assert tool_call .arguments == {"city" : "Paris" }
1173
1197
assert message .meta ["finish_reason" ] == "tool_calls"
1198
+ assert "completion_tokens" in message .meta ["usage" ]
1174
1199
1175
1200
new_messages = [
1176
1201
* initial_messages ,
@@ -1268,6 +1293,8 @@ def test_live_run_with_tools_streaming(self, tools):
1268
1293
assert tool_call .tool_name == "weather"
1269
1294
assert tool_call .arguments == {"city" : "Paris" }
1270
1295
assert message .meta ["finish_reason" ] == "tool_calls"
1296
+ assert "output_tokens" in message .meta ["usage" ]
1297
+ assert "input_tokens" in message .meta ["usage" ]
1271
1298
1272
1299
new_messages = [
1273
1300
* initial_messages ,
@@ -1673,6 +1700,7 @@ async def test_run_async_with_params(self, chat_messages, mock_anthropic_complet
1673
1700
assert "Hello! I'm Claude." in response ["replies" ][0 ].text
1674
1701
assert response ["replies" ][0 ].meta ["model" ] == "claude-sonnet-4-20250514"
1675
1702
assert response ["replies" ][0 ].meta ["finish_reason" ] == "stop"
1703
+ assert "completion_tokens" in response ["replies" ][0 ].meta ["usage" ]
1676
1704
1677
1705
@pytest .mark .asyncio
1678
1706
@pytest .mark .skipif (
@@ -1691,6 +1719,7 @@ async def test_live_run_async(self):
1691
1719
assert "Paris" in message .text
1692
1720
assert "claude-sonnet-4-20250514" in message .meta ["model" ]
1693
1721
assert message .meta ["finish_reason" ] == "stop"
1722
+ assert "completion_tokens" in message .meta ["usage" ]
1694
1723
1695
1724
@pytest .mark .asyncio
1696
1725
@pytest .mark .skipif (
@@ -1726,6 +1755,8 @@ async def callback(chunk: StreamingChunk) -> None:
1726
1755
assert "paris" in message .text .lower ()
1727
1756
assert "claude-sonnet-4-20250514" in message .meta ["model" ]
1728
1757
assert message .meta ["finish_reason" ] == "stop"
1758
+ assert "input_tokens" in message .meta ["usage" ]
1759
+ assert "output_tokens" in message .meta ["usage" ]
1729
1760
1730
1761
# Verify streaming behavior
1731
1762
assert counter > 1 # Should have received multiple chunks
@@ -1767,3 +1798,4 @@ async def test_live_run_async_with_tools(self, tools):
1767
1798
assert not final_message .tool_calls
1768
1799
assert len (final_message .text ) > 0
1769
1800
assert "paris" in final_message .text .lower ()
1801
+ assert "completion_tokens" in final_message .meta ["usage" ]
0 commit comments