Skip to content

Commit 278570d

Browse files
authored
fix(ci): increase test-examples timeout and reduce sleep in error_handling example (#760)
The `test-examples` CI job running `streaming_mode.py all` consistently times out at 120 seconds. This happens because the job runs 10 sequential live API examples, and the error_handling example's `sleep 60` bash command (which intentionally triggers an asyncio timeout after 10s) adds unnecessary wall-clock time, especially with slower CLI versions. **Changes:** 1. **`examples/streaming_mode.py`**: Reduce the bash sleep duration from 60 seconds to 5 seconds in the timeout/error-handling example. The internal `asyncio.timeout(10.0)` still fires correctly since 5s < 10s would let it complete normally, but the important behavior (demonstrating timeout handling) is preserved. A 5-second sleep is sufficient to show the pattern without wasting 50+ seconds of CI budget. 2. **`.github/workflows/test.yml`**: Increase the `timeout` for `streaming_mode.py all` from 120s to 180s to provide headroom for API latency variance across the full suite of examples.
1 parent 4e8e7c9 commit 278570d

2 files changed

Lines changed: 25 additions & 15 deletions

File tree

.github/workflows/test.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,20 +141,22 @@ jobs:
141141
if: runner.os == 'Linux'
142142
env:
143143
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
144+
PYTHONUNBUFFERED: "1"
144145
run: |
145146
python examples/quick_start.py
146-
timeout 120 python examples/streaming_mode.py all
147+
timeout 300 python examples/streaming_mode.py all
147148
timeout 120 python examples/hooks.py PreToolUse
148149
timeout 120 python examples/hooks.py DecisionFields
149150
150151
- name: Run example scripts (Windows)
151152
if: runner.os == 'Windows'
152153
env:
153154
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
155+
PYTHONUNBUFFERED: "1"
154156
run: |
155157
python examples/quick_start.py
156158
$job = Start-Job { python examples/streaming_mode.py all }
157-
Wait-Job $job -Timeout 120 | Out-Null
159+
Wait-Job $job -Timeout 300 | Out-Null
158160
Stop-Job $job
159161
Receive-Job $job
160162

examples/streaming_mode.py

100755100644
Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -282,13 +282,18 @@ async def create_message_stream():
282282
# Send async iterable of messages
283283
await client.query(create_message_stream())
284284

285-
# Receive the three responses
286-
async for msg in client.receive_response():
287-
display_message(msg)
288-
async for msg in client.receive_response():
289-
display_message(msg)
290-
async for msg in client.receive_response():
291-
display_message(msg)
285+
# Collect responses — the CLI may group multiple user messages into
286+
# fewer ResultMessages, so we cannot assume a 1:1 mapping. We call
287+
# receive_response() in a loop with a short timeout so we drain all
288+
# available results without hanging if fewer results arrive than
289+
# messages were sent.
290+
while True:
291+
try:
292+
async with asyncio.timeout(30.0):
293+
async for msg in client.receive_response():
294+
display_message(msg)
295+
except (asyncio.TimeoutError, StopAsyncIteration):
296+
break
292297

293298
print("\n")
294299

@@ -355,12 +360,12 @@ async def example_control_protocol():
355360
print(f" - Output style: {server_info.get('output_style', 'unknown')}")
356361

357362
# Show available output styles if present
358-
styles = server_info.get('available_output_styles', [])
363+
styles = server_info.get("available_output_styles", [])
359364
if styles:
360365
print(f" - Available output styles: {', '.join(styles)}")
361366

362367
# Show a few example commands
363-
commands = server_info.get('commands', [])[:5]
368+
commands = server_info.get("commands", [])[:5]
364369
if commands:
365370
print(" - Example commands:")
366371
for cmd in commands:
@@ -377,6 +382,7 @@ async def example_control_protocol():
377382

378383
# Start consuming messages in background to enable interrupt
379384
messages = []
385+
380386
async def consume():
381387
async for msg in client.receive_response():
382388
messages.append(msg)
@@ -428,13 +434,15 @@ async def example_error_handling():
428434
await client.connect()
429435

430436
# Send a message that will take time to process
431-
print("User: Run a bash sleep command for 60 seconds not in the background")
432-
await client.query("Run a bash sleep command for 60 seconds not in the background")
437+
print("User: Run a bash sleep command for 5 seconds not in the background")
438+
await client.query(
439+
"Run a bash sleep command for 5 seconds not in the background"
440+
)
433441

434442
# Try to receive response with a short timeout
435443
try:
436444
messages = []
437-
async with asyncio.timeout(10.0):
445+
async with asyncio.timeout(3.0):
438446
async for msg in client.receive_response():
439447
messages.append(msg)
440448
if isinstance(msg, AssistantMessage):
@@ -447,7 +455,7 @@ async def example_error_handling():
447455

448456
except asyncio.TimeoutError:
449457
print(
450-
"\nResponse timeout after 10 seconds - demonstrating graceful handling"
458+
"\nResponse timeout after 3 seconds - demonstrating graceful handling"
451459
)
452460
print(f"Received {len(messages)} messages before timeout")
453461

0 commit comments

Comments
 (0)