Skip to content

Commit 28a115f

Browse files
dicksontsairushilpatel0
authored andcommitted
Fix examples
Signed-off-by: Rushil Patel <[email protected]>
1 parent 7a24087 commit 28a115f

File tree

3 files changed

+103
-115
lines changed

3 files changed

+103
-115
lines changed

examples/streaming_mode.py

Lines changed: 37 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
AssistantMessage,
1414
ClaudeCodeOptions,
1515
ClaudeSDKClient,
16+
CLIConnectionError,
1617
ResultMessage,
1718
TextBlock,
1819
)
@@ -27,18 +28,13 @@ async def example_basic_streaming():
2728
await client.send_message("What is 2+2?")
2829

2930
# Receive complete response using the helper method
30-
messages, result = await client.receive_response()
31-
32-
# Extract text from assistant's response
33-
for msg in messages:
31+
async for msg in client.receive_response():
3432
if isinstance(msg, AssistantMessage):
3533
for block in msg.content:
3634
if isinstance(block, TextBlock):
3735
print(f"Claude: {block.text}")
38-
39-
# Print cost if available
40-
if result and result.total_cost_usd:
41-
print(f"Cost: ${result.total_cost_usd:.4f}")
36+
elif isinstance(msg, ResultMessage) and msg.total_cost_usd:
37+
print(f"Cost: ${msg.total_cost_usd:.4f}")
4238

4339
print("Session ended\n")
4440

@@ -52,32 +48,22 @@ async def example_multi_turn_conversation():
5248
print("User: What's the capital of France?")
5349
await client.send_message("What's the capital of France?")
5450

55-
messages, _ = await client.receive_response()
56-
5751
# Extract and print response
58-
for msg in messages:
59-
if isinstance(msg, AssistantMessage):
60-
for block in msg.content:
61-
if isinstance(block, TextBlock):
62-
print(f"Claude: {block.text}")
52+
async for msg in client.receive_response():
53+
content_blocks = getattr(msg, 'content', [])
54+
for block in content_blocks:
55+
if isinstance(block, TextBlock):
56+
print(f"{block.text}")
6357

6458
# Second turn - follow-up
6559
print("\nUser: What's the population of that city?")
6660
await client.send_message("What's the population of that city?")
6761

68-
messages, _ = await client.receive_response()
69-
70-
for msg in messages:
71-
if isinstance(msg, AssistantMessage):
72-
for block in msg.content:
73-
if isinstance(block, TextBlock):
74-
print(f"Claude: {block.text}")
75-
76-
for msg in messages:
77-
if isinstance(msg, AssistantMessage):
78-
for block in msg.content:
79-
if isinstance(block, TextBlock):
80-
print(f"Claude: {block.text}")
62+
async for msg in client.receive_response():
63+
content_blocks = getattr(msg, 'content', [])
64+
for block in content_blocks:
65+
if isinstance(block, TextBlock):
66+
print(f"{block.text}")
8167

8268
print("\nConversation ended\n")
8369

@@ -102,7 +88,7 @@ async def receive_messages():
10288
questions = [
10389
"What is 2 + 2?",
10490
"What is the square root of 144?",
105-
"What is 15% of 80?",
91+
"What is 10% of 80?",
10692
]
10793

10894
for question in questions:
@@ -168,9 +154,7 @@ async def consume_messages():
168154
await client.send_message("Never mind, just tell me a quick joke")
169155

170156
# Get the joke
171-
messages, result = await client.receive_response()
172-
173-
for msg in messages:
157+
async for msg in client.receive_response():
174158
if isinstance(msg, AssistantMessage):
175159
for block in msg.content:
176160
if isinstance(block, TextBlock):
@@ -233,10 +217,8 @@ async def example_with_options():
233217
"Create a simple hello.txt file with a greeting message"
234218
)
235219

236-
messages, result = await client.receive_response()
237-
238220
tool_uses = []
239-
for msg in messages:
221+
async for msg in client.receive_response():
240222
if isinstance(msg, AssistantMessage):
241223
for block in msg.content:
242224
if isinstance(block, TextBlock):
@@ -257,48 +239,34 @@ async def example_error_handling():
257239
client = ClaudeSDKClient()
258240

259241
try:
260-
# Connect with custom stream
261-
async def message_stream():
262-
yield {
263-
"type": "user",
264-
"message": {"role": "user", "content": "Hello"},
265-
"parent_tool_use_id": None,
266-
"session_id": "error-demo",
267-
}
268-
269-
await client.connect(message_stream())
242+
await client.connect()
270243

271-
# Create a background task to consume messages (required for interrupt to work)
272-
consume_task = None
244+
# Send a message that will take time to process
245+
await client.send_message("Run a bash sleep command for 60 seconds")
273246

274-
async def consume_messages():
275-
"""Background message consumer."""
276-
async for msg in client.receive_messages():
277-
if isinstance(msg, AssistantMessage):
278-
print("Received response from Claude")
279-
280-
# Receive messages with timeout
247+
# Try to receive response with a short timeout
281248
try:
282-
# Start consuming messages in background
283-
consume_task = asyncio.create_task(consume_messages())
284-
285-
# Wait for response with timeout
286-
await asyncio.wait_for(consume_task, timeout=30.0)
249+
messages = []
250+
async with asyncio.timeout(10.0):
251+
async for msg in client.receive_response():
252+
messages.append(msg)
253+
if isinstance(msg, AssistantMessage):
254+
for block in msg.content:
255+
if isinstance(block, TextBlock):
256+
print(f"Claude: {block.text[:50]}...")
257+
elif isinstance(msg, ResultMessage):
258+
print("Received complete response")
259+
break
287260

288261
except asyncio.TimeoutError:
289-
print("Response timeout - sending interrupt")
290-
# Note: interrupt requires active message consumption
291-
# Since we're already consuming in the background task, interrupt will work
292-
await client.interrupt()
262+
print("\nResponse timeout after 10 seconds - demonstrating graceful handling")
263+
print(f"Received {len(messages)} messages before timeout")
293264

294-
# Cancel the consume task
295-
if consume_task:
296-
consume_task.cancel()
297-
with contextlib.suppress(asyncio.CancelledError):
298-
await consume_task
265+
except CLIConnectionError as e:
266+
print(f"Connection error: {e}")
299267

300268
except Exception as e:
301-
print(f"Error: {e}")
269+
print(f"Unexpected error: {e}")
302270

303271
finally:
304272
# Always disconnect

examples/streaming_mode_ipython.py

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,18 @@
1010
# BASIC STREAMING
1111
# ============================================================================
1212

13-
from claude_code_sdk import ClaudeSDKClient, AssistantMessage, TextBlock
13+
from claude_code_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage
1414

1515
async with ClaudeSDKClient() as client:
1616
await client.send_message("What is 2+2?")
17-
messages, result = await client.receive_response()
1817

19-
for msg in messages:
18+
async for msg in client.receive_response():
2019
if isinstance(msg, AssistantMessage):
2120
for block in msg.content:
2221
if isinstance(block, TextBlock):
2322
print(f"Claude: {block.text}")
23+
elif isinstance(msg, ResultMessage) and msg.total_cost_usd:
24+
print(f"Cost: ${msg.total_cost_usd:.4f}")
2425

2526

2627
# ============================================================================
@@ -31,18 +32,17 @@
3132
from claude_code_sdk import ClaudeSDKClient, AssistantMessage, TextBlock
3233

3334
async with ClaudeSDKClient() as client:
34-
async def receive_response():
35-
messages, _ = await client.receive_response()
36-
for msg in messages:
35+
async def send_and_receive(prompt):
36+
await client.send_message(prompt)
37+
async for msg in client.receive_response():
3738
if isinstance(msg, AssistantMessage):
3839
for block in msg.content:
3940
if isinstance(block, TextBlock):
4041
print(f"Claude: {block.text}")
4142

42-
await client.send_message("Tell me a short joke")
43-
await receive_response()
44-
await client.send_message("Now tell me a fun fact")
45-
await receive_response()
43+
await send_and_receive("Tell me a short joke")
44+
print("\n---\n")
45+
await send_and_receive("Now tell me a fun fact")
4646

4747

4848
# ============================================================================
@@ -58,8 +58,7 @@ async def receive_response():
5858

5959
# Helper to get response
6060
async def get_response():
61-
messages, result = await client.receive_response()
62-
for msg in messages:
61+
async for msg in client.receive_response():
6362
if isinstance(msg, AssistantMessage):
6463
for block in msg.content:
6564
if isinstance(block, TextBlock):
@@ -123,9 +122,8 @@ async def consume_messages():
123122
# Send a new message after interrupt
124123
print("\n--- After interrupt, sending new message ---\n")
125124
await client.send_message("Just say 'Hello! I was interrupted.'")
126-
messages, result = await client.receive_response()
127125

128-
for msg in messages:
126+
async for msg in client.receive_response():
129127
if isinstance(msg, AssistantMessage):
130128
for block in msg.content:
131129
if isinstance(block, TextBlock):
@@ -142,12 +140,41 @@ async def consume_messages():
142140
async with ClaudeSDKClient() as client:
143141
await client.send_message("Run a bash sleep command for 60 seconds")
144142

145-
# Timeout after 30 seconds
146-
messages, result = await asyncio.wait_for(
147-
client.receive_response(), timeout=20.0
148-
)
143+
# Timeout after 20 seconds
144+
messages = []
145+
async with asyncio.timeout(20.0):
146+
async for msg in client.receive_response():
147+
messages.append(msg)
148+
if isinstance(msg, AssistantMessage):
149+
for block in msg.content:
150+
if isinstance(block, TextBlock):
151+
print(f"Claude: {block.text}")
149152

150153
except asyncio.TimeoutError:
151-
print("Request timed out")
154+
print("Request timed out after 20 seconds")
152155
except Exception as e:
153-
print(f"Error: {e}")
156+
print(f"Error: {e}")
157+
158+
159+
# ============================================================================
160+
# COLLECTING ALL MESSAGES INTO A LIST
161+
# ============================================================================
162+
163+
from claude_code_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage
164+
165+
async with ClaudeSDKClient() as client:
166+
await client.send_message("What are the primary colors?")
167+
168+
# Collect all messages into a list
169+
messages = [msg async for msg in client.receive_response()]
170+
171+
# Process them afterwards
172+
for msg in messages:
173+
if isinstance(msg, AssistantMessage):
174+
for block in msg.content:
175+
if isinstance(block, TextBlock):
176+
print(f"Claude: {block.text}")
177+
elif isinstance(msg, ResultMessage):
178+
print(f"Total messages: {len(messages)}")
179+
if msg.total_cost_usd:
180+
print(f"Cost: ${msg.total_cost_usd:.4f}")

src/claude_code_sdk/client.py

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -146,50 +146,43 @@ async def interrupt(self) -> None:
146146
raise CLIConnectionError("Not connected. Call connect() first.")
147147
await self._transport.interrupt()
148148

149-
async def receive_response(self) -> tuple[list[Message], ResultMessage | None]:
149+
async def receive_response(self) -> AsyncIterator[Message]:
150150
"""
151-
Receive a complete response from Claude, collecting all messages until ResultMessage.
151+
Receive messages from Claude until a ResultMessage is received.
152152
153-
Compared to receive_messages(), this is a convenience method that
154-
handles the common pattern of receiving messages until Claude completes
155-
its response. It collects all messages and returns them along with the
156-
final ResultMessage.
153+
This is an async iterator that yields all messages including the final ResultMessage.
154+
It's a convenience method over receive_messages() that automatically stops iteration
155+
after receiving a ResultMessage.
157156
158-
Returns:
159-
tuple: A tuple of (messages, result) where:
160-
- messages: List of all messages received (UserMessage, AssistantMessage, SystemMessage)
161-
- result: The final ResultMessage if received, None if stream ended without result
157+
Yields:
158+
Message: Each message received (UserMessage, AssistantMessage, SystemMessage, ResultMessage)
162159
163160
Example:
164161
```python
165162
async with ClaudeSDKClient() as client:
166-
# First turn
163+
# Send message and process response
167164
await client.send_message("What's the capital of France?")
168-
messages, result = await client.receive_response()
169165
170-
# Extract assistant's response
171-
for msg in messages:
166+
async for msg in client.receive_response():
172167
if isinstance(msg, AssistantMessage):
173168
for block in msg.content:
174169
if isinstance(block, TextBlock):
175170
print(f"Claude: {block.text}")
171+
elif isinstance(msg, ResultMessage):
172+
print(f"Cost: ${msg.total_cost_usd:.4f}")
173+
```
176174
177-
# Second turn
178-
await client.send_message("What's the population?")
179-
messages, result = await client.receive_response()
180-
# ... process response
175+
Note:
176+
The iterator will automatically stop after yielding a ResultMessage.
177+
If you need to collect all messages into a list, use:
178+
```python
179+
messages = [msg async for msg in client.receive_response()]
181180
```
182181
"""
183-
from .types import ResultMessage
184-
185-
messages = []
186182
async for message in self.receive_messages():
187-
messages.append(message)
183+
yield message
188184
if isinstance(message, ResultMessage):
189-
return messages, message
190-
191-
# Stream ended without ResultMessage
192-
return messages, None
185+
return
193186

194187
async def disconnect(self) -> None:
195188
"""Disconnect from Claude."""

0 commit comments

Comments
 (0)