Skip to content

fix: preserve wire fields in parse_message via data field#1061

Open
itxaiohanglover wants to merge 1 commit into
anthropics:mainfrom
itxaiohanglover:fix/parse-message-preserve-wire-fields
Open

fix: preserve wire fields in parse_message via data field#1061
itxaiohanglover wants to merge 1 commit into
anthropics:mainfrom
itxaiohanglover:fix/parse-message-preserve-wire-fields

Conversation

@itxaiohanglover

Copy link
Copy Markdown

Summary

parse_message() silently drops newer CLI wire fields like ttft_ms, terminal_reason, fast_mode_state, stop_details, diagnostics, context_management, caller, and request_id. Unlike SystemMessage (which keeps the raw frame as .data), AssistantMessage and ResultMessage don't retain the original frame, so SDK consumers cannot access these fields at all without bypassing the SDK and re-parsing the wire themselves.

This implements option 2 from the issue: add a data: dict[str, Any] | None = None field to both AssistantMessage and ResultMessage (matching the SystemMessage.data pattern), then pass data=data in the parser. This is a forward-compatible escape hatch so new CLI fields are reachable before they're explicitly modeled.

Changes

  • types.py: Added data: dict[str, Any] | None = None field to AssistantMessage and ResultMessage dataclasses (defaults to None for manually constructed messages, so existing code is unaffected).
  • message_parser.py: Pass data=data (the raw message dict) when constructing AssistantMessage and ResultMessage.
  • test_message_parser.py: Added 5 tests verifying that unmodeled wire fields survive parsing on both message types, that data defaults to None for manual construction, and that per-content-block caller is reachable via data.

Fixes #1026

Test plan

  • ruff check passes
  • ruff format --check passes
  • mypy src/ passes (strict mode, 0 issues)
  • pytest tests/ -v — 755 passed, 5 skipped
  • New tests verify ttft_ms, terminal_reason, fast_mode_state, stop_details, diagnostics, context_management, caller, and request_id are all reachable via .data
  • data field defaults to None — backward compatible with existing AssistantMessage(...) / ResultMessage(...) construction

Add `data: dict[str, Any] | None = None` to AssistantMessage and
ResultMessage, mirroring the existing SystemMessage.data pattern. The
parser now passes the raw frame dict as `data=data`, so newer CLI wire
fields (ttft_ms, terminal_reason, fast_mode_state, stop_details,
diagnostics, context_management, caller, request_id) are reachable
before they are explicitly modeled.

Fixes anthropics#1026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

parse_message silently drops newer CLI wire fields (ttft_ms, terminal_reason, stop_details, …) with no escape hatch

1 participant