Add comprehensive documentation for Claude Agent SDK including usage patterns, test examples, and development guide. Includes: - CLAUDE.md with project structure and quick reference - SDK test examples for query, client, and hooks - Shared test utilities for auth and tmpdir management - Detailed SDK overview and capabilities documentation
117 lines
3.6 KiB
Python
117 lines
3.6 KiB
Python
"""Example: ClaudeSDKClient — Write file + resume session.
|
|
|
|
Demonstrates:
|
|
- ClaudeSDKClient (stateful, interactive mode)
|
|
- Creating a file via Write tool
|
|
- Capturing session_id from SystemMessage
|
|
- Resuming a session with options.resume
|
|
- receive_response() for streaming messages
|
|
- Manual tmpdir management
|
|
|
|
Usage:
|
|
cd docs/claude
|
|
../../.venv/Scripts/python test_client_write_resume.py
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from pathlib import Path
|
|
|
|
from _sdk_test_common import auth_env, make_tmpdir, remove_tmpdir, setup_auth
|
|
|
|
|
|
async def drain(client):
|
|
"""Collect text from receive_response(), return (session_id, joined_text)."""
|
|
from claude_agent_sdk import AssistantMessage, ResultMessage, SystemMessage, TextBlock
|
|
|
|
texts: list[str] = []
|
|
session_id = None
|
|
async for msg in client.receive_response():
|
|
if isinstance(msg, SystemMessage) and msg.subtype == "init":
|
|
session_id = msg.data.get("session_id")
|
|
elif isinstance(msg, AssistantMessage):
|
|
for block in msg.content:
|
|
if isinstance(block, TextBlock):
|
|
texts.append(block.text)
|
|
elif isinstance(msg, ResultMessage):
|
|
session_id = session_id or msg.session_id
|
|
if msg.result:
|
|
texts.append(msg.result)
|
|
return session_id, "\n".join(texts)
|
|
|
|
|
|
async def main() -> int:
|
|
ok, msg = setup_auth()
|
|
print(msg)
|
|
if not ok:
|
|
return 1
|
|
|
|
from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient
|
|
|
|
tmpdir = make_tmpdir("write-resume-")
|
|
try:
|
|
target = tmpdir / "session_test.txt"
|
|
|
|
# --- Turn 1: create file ---
|
|
print("--- Turn 1: Write ---")
|
|
async with ClaudeSDKClient(
|
|
ClaudeAgentOptions(
|
|
cwd=str(tmpdir),
|
|
allowed_tools=["Write", "Read"],
|
|
permission_mode="acceptEdits",
|
|
max_turns=3,
|
|
env=auth_env(),
|
|
)
|
|
) as client:
|
|
await client.query(
|
|
f"Use the Write tool to create session_test.txt "
|
|
f"in {tmpdir} with exactly the content 'Session 1'."
|
|
)
|
|
session_id, response = await drain(client)
|
|
print(f" Response: {response[:200]}")
|
|
|
|
if not target.exists():
|
|
print("FAIL: file not created")
|
|
return 2
|
|
|
|
print(f" File content: {target.read_text(encoding='utf-8')!r}")
|
|
print(f" Session ID: {session_id}")
|
|
|
|
if not session_id:
|
|
print("FAIL: no session_id captured")
|
|
return 3
|
|
|
|
# --- Turn 2: resume and verify context ---
|
|
print("\n--- Turn 2: Resume ---")
|
|
async with ClaudeSDKClient(
|
|
ClaudeAgentOptions(
|
|
cwd=str(tmpdir),
|
|
resume=session_id,
|
|
allowed_tools=["Read"],
|
|
permission_mode="acceptEdits",
|
|
max_turns=2,
|
|
env=auth_env(),
|
|
)
|
|
) as resumed:
|
|
await resumed.query(
|
|
"Without modifying files, tell me the exact filename and content you created."
|
|
)
|
|
_, resume_response = await drain(resumed)
|
|
print(f" Response: {resume_response[:300]}")
|
|
|
|
content_ok = target.read_text(encoding="utf-8").strip() == "Session 1"
|
|
resume_ok = "session_test.txt" in resume_response and "Session 1" in resume_response
|
|
|
|
if content_ok and resume_ok:
|
|
print("\nPASS")
|
|
return 0
|
|
print(f"\nFAIL: content_ok={content_ok} resume_ok={resume_ok}")
|
|
return 4
|
|
finally:
|
|
remove_tmpdir(tmpdir)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(asyncio.run(main()))
|