Skip to content

feat: add custom repr to message and content block types#727

Open
javierdejesusda wants to merge 2 commits intoanthropics:mainfrom
javierdejesusda:feat/message-type-repr
Open

feat: add custom repr to message and content block types#727
javierdejesusda wants to merge 2 commits intoanthropics:mainfrom
javierdejesusda:feat/message-type-repr

Conversation

@javierdejesusda
Copy link
Copy Markdown

Summary

  • Add concise, readable __repr__ methods to 14 dataclass types so
    print(message) produces useful output without helper functions
  • Add _truncate private helper (80-char limit with ... suffix)
  • 28 new tests covering all types + edge cases (quotes, newlines, backslashes)

Closes #78

Context

Issue #78 (filed by @blois) noted that the auto-generated dataclass repr
is too verbose for practical debugging. Example helpers like
display_message() in examples/streaming_mode.py exist solely because
the default output is unreadable.

Note: PR #326 by @martinritchie addressed the same issue but has been
pending review since Nov 2025. This PR takes a more focused approach
(repr only, no __str__, no version bump, no example changes) and uses
!r formatting for proper escaping of special characters.

Changes

src/claude_agent_sdk/types.py (+106 lines):

  • _truncate(text, max_length=80) helper before content block section
  • @dataclass(repr=False) + custom __repr__ on 14 types:
    • Content blocks: TextBlock, ThinkingBlock, ToolUseBlock, ToolResultBlock
    • Messages: UserMessage, AssistantMessage, SystemMessage, ResultMessage
    • System subtypes: TaskStartedMessage, TaskProgressMessage, TaskNotificationMessage
    • Events: StreamEvent, RateLimitEvent, RateLimitInfo

tests/test_types.py (+237 lines):

  • TestTruncateHelper (5 tests)
  • TestContentBlockRepr (10 tests incl. quotes/newlines/backslash edge cases)
  • TestMessageRepr (4 tests)
  • TestSystemMessageRepr (4 tests)
  • TestResultAndEventRepr (5 tests)

Before / After

# Before (auto-generated, unreadable):
AssistantMessage(content=[TextBlock(text='Hello! I am Claude...a very long message'), ToolUseBlock(id='toolu_01X3mRqK5nKYrvSxnFEqqP1a', name='Read', input={'file_path': '/home/user/project/src/main.py', 'limit': 200, 'offset': 0})], model='claude-opus-4-6', parent_tool_use_id=None, error=None, usage={'input_tokens': 12345, 'output_tokens': 6789})

# After (concise, readable):
AssistantMessage(model='claude-opus-4-6', content=[TextBlock(text='Hello! I am Claude...a very long message'), ToolUseBlock(id='toolu_01X3mRqK5nKYrvSxnFEqqP1a', name='Read')])

Test plan

  • python -m pytest tests/ — 355/355 pass
  • python -m ruff check src/ tests/ — clean
  • python -m ruff format src/ tests/ — clean
  • python -m mypy src/ — only pre-existing errors in __init__.py
  • Edge cases: quotes, newlines, backslashes properly escaped via !r
  • No breaking changes — repr format is not a stable API

Add concise __repr__ methods to 14 dataclass types so print(message)
produces readable output without helper functions. Uses !r formatting
for proper escaping and _truncate helper for 80-char limit.
@javierdejesusda javierdejesusda force-pushed the feat/message-type-repr branch from fd694f9 to 802f338 Compare March 24, 2026 20:37
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.

Support reprs for message types

1 participant