Repository navigation
feat: add typed RateLimitEvent message - #648
Merged
Merged
Conversation
The CLI emits `rate_limit_event` when rate limit status changes for claude.ai subscription users. After #598 stopped the parser from crashing on unknown types, these events were silently dropped (returning None). Users need to see these events to warn before hitting limits or back off gracefully when rejected. This adds: - RateLimitEvent dataclass with rate_limit_info, uuid, session_id - RateLimitInfo dataclass with status, resets_at, rate_limit_type, utilization, overage_status, overage_resets_at, overage_disabled_reason - RateLimitStatus and RateLimitType literal types - Parser case for rate_limit_event message type - Exports for all the above plus StreamEvent (was missing from __init__) Field names follow Python conventions (snake_case); camelCase CLI fields are mapped in the parser. The .raw field preserves unmodeled fields for forward compatibility. E2E verified against real CLI output: status: allowed_warning, resets_at: 1773273600, rate_limit_type: seven_day, utilization: 0.62 Fixes #583, #599, #601, #603
qing-ant
force-pushed
the
fix/rate-limit-and-allowed-tools
branch
from
March 7, 2026 02:33
caebb82 to
bdc6270
Compare
qing-ant
enabled auto-merge (squash)
March 12, 2026 05:53
dicksontsai
approved these changes
Mar 12, 2026
This was referenced Mar 24, 2026
qing-ant
added a commit
that referenced
this pull request
Aug 11, 2026
…1196) ## Summary TypeScript-parity gap. In streaming-input mode one connection carries many user turns, and a `/clear` (or any other flow that discards the transcript mid-session) resets the conversation and zeroes the running totals reported on subsequent result messages. The CLI announces this with a top-level frame: ```json {"type": "conversation_reset", "new_conversation_id": "<uuid>", "uuid": "<uuid>", "session_id": "<outgoing session id>"} ``` The TypeScript SDK surfaces it as `SDKConversationResetMessage`. The Python parser only recognized its known message types and dropped this one through the forward-compat fallthrough in `message_parser.py`, so Python apps never saw resets — including ones they didn't initiate — and had no signal to snapshot totals before they zero. - `types.py`: new `ConversationResetMessage` dataclass (`new_conversation_id`, `uuid`, `session_id`), added to the `Message` union next to the other top-level non-system frames (`RateLimitEvent`, `StreamEvent`). - `message_parser.py`: parse `type == "conversation_reset"`; missing required field → `MessageParseError`, same as siblings. - `__init__.py`: export. **Compatibility note:** like `RateLimitEvent` (#648), this widens the public `Message` union. Code that exhaustively matches on `Message` with `assert_never` will get a new type-check error, and code that raises on unrecognized message classes will now see a frame that was previously dropped silently. ## Test plan - `tests/test_message_parser.py`: parse happy path + missing-field error. - `e2e-tests/test_conversation_reset.py` (runs in CI against the real CLI): open a `ClaudeSDKClient`, run one turn, send `/clear`, assert a `ConversationResetMessage` arrives before the `/clear` turn's result, stamped with the outgoing `session_id`, and that the following result carries a new `session_id`. Passed locally against CLI 2.1.227. - `ruff check`, `ruff format --check`, `mypy src/`, full `pytest tests/` green locally.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds typed parsing for
rate_limit_eventmessages emitted by the CLI when rate limit status changes for claude.ai subscription users. After #598 stopped the parser from crashing on unknown types, these events were silently dropped — users couldn't warn before hitting limits or back off gracefully when rejected.What's added
RateLimitEventdataclass withrate_limit_info,uuid,session_idRateLimitInfodataclass withstatus,resets_at,rate_limit_type,utilization,overage_status,overage_resets_at,overage_disabled_reason,rawRateLimitStatus("allowed" | "allowed_warning" | "rejected") andRateLimitTypeliteral typesrate_limit_eventmessage typeStreamEvent(was inMessageunion but missing from__init__.py)Field names follow Python conventions (snake_case); camelCase CLI fields are mapped in the parser. The
rawfield preserves the original dict including any unmodeled fields for forward compatibility.E2E verification
Captured a real event from the CLI:
Usage
Fixes #583, #599, #601, #603