From 584b54d1f3bff8d3c3c89b6657939b8872c4c09a Mon Sep 17 00:00:00 2001 From: Drac Pet Date: Fri, 21 Aug 2026 10:39:44 +0200 Subject: [PATCH] fix: include input_tokens in message_delta events for Anthropic compatibility --- skillclaw/protocols/anthropic_messages.py | 2 +- tests/test_anthropic_messages.py | 24 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/skillclaw/protocols/anthropic_messages.py b/skillclaw/protocols/anthropic_messages.py index 1cede6b..0aa4f94 100644 --- a/skillclaw/protocols/anthropic_messages.py +++ b/skillclaw/protocols/anthropic_messages.py @@ -537,7 +537,7 @@ def sse(event: str, data: dict[str, Any]) -> str: { "type": "message_delta", "delta": {"stop_reason": stop_reason, "stop_sequence": None}, - "usage": {"output_tokens": anthropic_usage.get("output_tokens", 0)}, + "usage": {**anthropic_usage}, }, ) yield sse("message_stop", {"type": "message_stop"}) diff --git a/tests/test_anthropic_messages.py b/tests/test_anthropic_messages.py index d68a3cb..3d5c0d7 100644 --- a/tests/test_anthropic_messages.py +++ b/tests/test_anthropic_messages.py @@ -518,6 +518,30 @@ def test_streaming_openai_tool_calls_use_tool_use_stop_reason_even_if_finish_rea ) +def test_streaming_final_message_delta_usage_includes_input_and_output_tokens(): + import asyncio + import json + + result = { + "response": { + "id": "chatcmpl_1", + "choices": [ + { + "finish_reason": "stop", + "message": {"role": "assistant", "content": "ok"}, + } + ], + "usage": {"prompt_tokens": 10, "completion_tokens": 2}, + } + } + + events = asyncio.run(_collect_stream_events(result, "claude-code-test")) + parsed = [(name, json.loads(data)) for name, data in events] + + message_delta = next(payload for name, payload in parsed if name == "message_delta") + assert message_delta["usage"] == {"input_tokens": 10, "output_tokens": 2} + + def test_anthropic_system_blocks_preserve_text_and_cache_control(): body = { "model": "claude-code-test",