Conversation
…ssage Add missing fields that the CLI emits but the SDK was discarding: AssistantMessage: - message_id: Anthropic API message ID (from message.id) - stop_reason: per-turn stop reason (from message.stop_reason) - session_id: session identifier - uuid: SDK message UUID for transcript correlation ResultMessage: - model_usage: per-model usage breakdown with cost, token counts, and context window info (from modelUsage) - permission_denials: list of denied permission requests - uuid: SDK message UUID for transcript correlation All new fields are optional with None defaults for backward compatibility. Fixes #562
There was a problem hiding this comment.
LGTM — straightforward additive change preserving optional CLI fields with full test coverage.
Extended reasoning...
Overview
This PR adds 7 optional fields across two dataclasses (AssistantMessage and ResultMessage) in types.py, extracts them via .get() in message_parser.py, and adds 4 test cases in test_message_parser.py. All new fields default to None for backward compatibility.
Security risks
None. The changes only preserve data that the CLI already emits — no new inputs are processed, no auth/permissions logic is touched, and no external APIs are called.
Level of scrutiny
Low scrutiny is appropriate. This is a mechanical, additive change that follows the exact same pattern already used throughout the parser (e.g., usage=data["message"].get("usage") was already present). The dataclass fields are all optional with None defaults, so there is zero risk of breaking existing consumers.
Other factors
The 4 new tests comprehensively cover both the "all fields present" and "all fields absent" scenarios for both message types. The PR description includes E2E verification against a live CLI. The change is small (7 new lines in types, 7 in parser, ~90 in tests) and self-contained.
E2E Test Results for PR #718Test: Live AssistantMessage Fields (Previously Dropped)
ResultMessage Fields (Previously Dropped)
Test SummaryAll previously-dropped fields are now correctly preserved and populated by the CLI. The |
Summary
The message parser was discarding several fields that the CLI emits in its JSON output. SDK consumers had no way to access important data like per-model usage breakdown (
modelUsage), message IDs, UUIDs, and permission denials.Changes
AssistantMessage — 4 fields added
message.idmessage_idmessage.stop_reasonstop_reasonend_turn,tool_use, etc.)session_idsession_iduuiduuidResultMessage — 3 fields added
modelUsagemodel_usagepermission_denialspermission_denialsuuiduuidAll new fields are optional with
Nonedefaults for backward compatibility.E2E Verification
Verified with a live SDK instance (v0.1.50, CLI 2.1.83):
Tests
4 new test cases:
test_parse_assistant_message_with_all_fields— verifies all new fields are parsedtest_parse_assistant_message_optional_fields_absent— verifies defaults to Nonetest_parse_result_message_with_model_usage— verifies modelUsage, permission_denials, uuidtest_parse_result_message_optional_fields_absent— verifies defaults to NoneAll 292 tests pass. Lint clean (ruff), type check clean (mypy).
Fixes #562