mirror of
https://github.com/anthropics/claude-code-sdk-python.git
synced 2025-12-23 09:19:52 +00:00
## Summary - Add `Dockerfile.test`: Python 3.12 image with Claude Code CLI installed - Add `scripts/test-docker.sh`: Local script to run tests in Docker - Add `test-e2e-docker` job to CI workflow that runs the full e2e suite in a container - Add `.dockerignore` to speed up Docker builds ## Context This helps catch Docker-specific issues like #406 where filesystem-based agents loaded via `setting_sources=["project"]` may silently fail in Docker environments. ## Local Usage ```bash # Run unit tests in Docker (no API key needed) ./scripts/test-docker.sh unit # Run e2e tests in Docker ANTHROPIC_API_KEY=sk-... ./scripts/test-docker.sh e2e # Run all tests ANTHROPIC_API_KEY=sk-... ./scripts/test-docker.sh all ``` ## Test plan - [x] Unit tests pass in Docker locally (129 passed) - [ ] CI job runs successfully 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>
107 lines
3.4 KiB
Python
107 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Example of loading filesystem-based agents via setting_sources.
|
|
|
|
This example demonstrates how to load agents defined in .claude/agents/ files
|
|
using the setting_sources option. This is different from inline AgentDefinition
|
|
objects - these agents are loaded from markdown files on disk.
|
|
|
|
This example tests the scenario from issue #406 where filesystem-based agents
|
|
loaded via setting_sources=["project"] may silently fail in certain environments.
|
|
|
|
Usage:
|
|
./examples/filesystem_agents.py
|
|
"""
|
|
|
|
import asyncio
|
|
from pathlib import Path
|
|
|
|
from claude_agent_sdk import (
|
|
AssistantMessage,
|
|
ClaudeAgentOptions,
|
|
ClaudeSDKClient,
|
|
ResultMessage,
|
|
SystemMessage,
|
|
TextBlock,
|
|
)
|
|
|
|
|
|
def extract_agents(msg: SystemMessage) -> list[str]:
|
|
"""Extract agent names from system message init data."""
|
|
if msg.subtype == "init":
|
|
agents = msg.data.get("agents", [])
|
|
# Agents can be either strings or dicts with a 'name' field
|
|
result = []
|
|
for a in agents:
|
|
if isinstance(a, str):
|
|
result.append(a)
|
|
elif isinstance(a, dict):
|
|
result.append(a.get("name", ""))
|
|
return result
|
|
return []
|
|
|
|
|
|
async def main():
|
|
"""Test loading filesystem-based agents."""
|
|
print("=== Filesystem Agents Example ===")
|
|
print("Testing: setting_sources=['project'] with .claude/agents/test-agent.md")
|
|
print()
|
|
|
|
# Use the SDK repo directory which has .claude/agents/test-agent.md
|
|
sdk_dir = Path(__file__).parent.parent
|
|
|
|
options = ClaudeAgentOptions(
|
|
setting_sources=["project"],
|
|
cwd=sdk_dir,
|
|
)
|
|
|
|
message_types: list[str] = []
|
|
agents_found: list[str] = []
|
|
|
|
async with ClaudeSDKClient(options=options) as client:
|
|
await client.query("Say hello in exactly 3 words")
|
|
|
|
async for msg in client.receive_response():
|
|
message_types.append(type(msg).__name__)
|
|
|
|
if isinstance(msg, SystemMessage) and msg.subtype == "init":
|
|
agents_found = extract_agents(msg)
|
|
print(f"Init message received. Agents loaded: {agents_found}")
|
|
|
|
elif isinstance(msg, AssistantMessage):
|
|
for block in msg.content:
|
|
if isinstance(block, TextBlock):
|
|
print(f"Assistant: {block.text}")
|
|
|
|
elif isinstance(msg, ResultMessage):
|
|
print(
|
|
f"Result: subtype={msg.subtype}, cost=${msg.total_cost_usd or 0:.4f}"
|
|
)
|
|
|
|
print()
|
|
print("=== Summary ===")
|
|
print(f"Message types received: {message_types}")
|
|
print(f"Total messages: {len(message_types)}")
|
|
|
|
# Validate the results
|
|
has_init = "SystemMessage" in message_types
|
|
has_assistant = "AssistantMessage" in message_types
|
|
has_result = "ResultMessage" in message_types
|
|
has_test_agent = "test-agent" in agents_found
|
|
|
|
print()
|
|
if has_init and has_assistant and has_result:
|
|
print("SUCCESS: Received full response (init, assistant, result)")
|
|
else:
|
|
print("FAILURE: Did not receive full response")
|
|
print(f" - Init: {has_init}")
|
|
print(f" - Assistant: {has_assistant}")
|
|
print(f" - Result: {has_result}")
|
|
|
|
if has_test_agent:
|
|
print("SUCCESS: test-agent was loaded from filesystem")
|
|
else:
|
|
print("WARNING: test-agent was NOT loaded (may not exist in .claude/agents/)")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|