From ba362f2735a4346f7ddc7020b3aa669d70f28e11 Mon Sep 17 00:00:00 2001 From: TA Date: Thu, 19 Feb 2026 19:39:21 +0700 Subject: [PATCH 1/2] fix: handle rate_limit_event message type Add RateLimitEvent dataclass and parser support for rate_limit_event messages from Claude Code CLI. This prevents MessageParseError from crashing the receive_messages() generator when rate limit events occur. The fix adds: 1. RateLimitEvent type to types.py 2. Handler for 'rate_limit_event' case in message_parser.py Fixes #583 --- src/claude_agent_sdk/_internal/message_parser.py | 16 ++++++++++++++++ src/claude_agent_sdk/types.py | 14 +++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/claude_agent_sdk/_internal/message_parser.py b/src/claude_agent_sdk/_internal/message_parser.py index f91081c3..f659d32e 100644 --- a/src/claude_agent_sdk/_internal/message_parser.py +++ b/src/claude_agent_sdk/_internal/message_parser.py @@ -8,6 +8,7 @@ AssistantMessage, ContentBlock, Message, + RateLimitEvent, ResultMessage, StreamEvent, SystemMessage, @@ -176,5 +177,20 @@ def parse_message(data: dict[str, Any]) -> Message: f"Missing required field in stream_event message: {e}", data ) from e + case "rate_limit_event": + try: + return RateLimitEvent( + type=data["type"], + session_id=data["session_id"], + limit_type=data.get("limit_type"), + limit=data.get("limit"), + remaining=data.get("remaining"), + reset_at=data.get("reset_at"), + ) + except KeyError as e: + raise MessageParseError( + f"Missing required field in rate_limit_event message: {e}", data + ) from e + case _: raise MessageParseError(f"Unknown message type: {message_type}", data) diff --git a/src/claude_agent_sdk/types.py b/src/claude_agent_sdk/types.py index 3ea89d5a..474217f5 100644 --- a/src/claude_agent_sdk/types.py +++ b/src/claude_agent_sdk/types.py @@ -693,7 +693,19 @@ class StreamEvent: parent_tool_use_id: str | None = None -Message = UserMessage | AssistantMessage | SystemMessage | ResultMessage | StreamEvent +@dataclass +class RateLimitEvent: + """Rate limit event from Claude Code CLI.""" + + type: str + session_id: str + limit_type: str | None = None + limit: int | None = None + remaining: int | None = None + reset_at: str | None = None + + +Message = UserMessage | AssistantMessage | SystemMessage | ResultMessage | StreamEvent | RateLimitEvent class ThinkingConfigAdaptive(TypedDict): From d784f3901cbfa56fff63183c2f8faad07d7927ce Mon Sep 17 00:00:00 2001 From: TA Date: Thu, 19 Feb 2026 19:40:46 +0700 Subject: [PATCH 2/2] fix: pass through unknown MCP content block types The MCP tool result handler in query.py only handled 'text' and 'image' content blocks, silently dropping other block types like 'search_result'. This fix adds a fallback that uses model_dump() to pass through unknown block types, enabling RAG applications to use search_result blocks for structured citations. Fixes #574 --- src/claude_agent_sdk/_internal/query.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/claude_agent_sdk/_internal/query.py b/src/claude_agent_sdk/_internal/query.py index 8f278428..e76e246f 100644 --- a/src/claude_agent_sdk/_internal/query.py +++ b/src/claude_agent_sdk/_internal/query.py @@ -495,6 +495,10 @@ async def _handle_sdk_mcp_request( "mimeType": item.mimeType, } ) + elif hasattr(item, "model_dump"): + # Pass through other block types (e.g., search_result) + # so they reach the Anthropic API intact + content.append(item.model_dump()) response_data = {"content": content} if hasattr(result.root, "is_error") and result.root.is_error: