Phase 6.4 - Modular Architecture: - Add lewooogo-brain adapters for LLM providers - Add lewooogo-data dual memory (Redis + PostgreSQL) - Implement consensus engine for multi-agent decisions - Add incident memory service for historical context Phase 9 - Agent Teams (Claude Agent SDK): - Add base agent class with Claude Sonnet 4 integration - Implement action planner, blast radius, and security agents - Add agent API endpoints and proposal workflow - Integrate ADR-009 OpenClaw Agent Teams architecture DevOps & CI/CD: - Add GitHub Actions CI/CD workflows (ci.yaml, cd.yaml) - Add pre-commit hooks and secrets baseline - Add docker-compose for local development - Update Kubernetes network policies Frontend Improvements: - Add auto-healing error boundary component - Update i18n messages for agent features - Enhance dual-state incident card with execution feedback Documentation: - Add 7 ADRs covering MCP, design system, architecture decisions - Update ARCHITECTURE_MEMORY.md with modular design - Add GLOBAL_RULES.md and SOUL.md for project identity Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
282 lines
8.2 KiB
Python
282 lines
8.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Phase 9 Agent SDK POC Verification Script
|
|
==========================================
|
|
|
|
驗證 claude-agent-sdk 是否能在 AWOOOI 專案中正常運作。
|
|
|
|
Usage:
|
|
python scripts/test_agent_sdk.py
|
|
|
|
Environment Variables:
|
|
ANTHROPIC_API_KEY - 如果設置,將測試基本 API 調用
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
from typing import Any
|
|
|
|
|
|
def test_import() -> bool:
|
|
"""Test basic import of claude-agent-sdk."""
|
|
print("=" * 60)
|
|
print("Phase 9 Agent SDK POC Verification")
|
|
print("=" * 60)
|
|
print()
|
|
|
|
try:
|
|
import claude_agent_sdk
|
|
|
|
version = getattr(claude_agent_sdk, "__version__", "N/A")
|
|
print(f"[PASS] claude_agent_sdk imported successfully")
|
|
print(f" Version: {version}")
|
|
return True
|
|
except ImportError as e:
|
|
print(f"[FAIL] Failed to import claude_agent_sdk: {e}")
|
|
return False
|
|
|
|
|
|
def test_core_exports() -> bool:
|
|
"""Test that core exports are available."""
|
|
print()
|
|
print("-" * 60)
|
|
print("Testing core exports...")
|
|
print("-" * 60)
|
|
|
|
required_exports = [
|
|
"query",
|
|
"ClaudeAgentOptions",
|
|
"ClaudeSDKClient",
|
|
"Message",
|
|
"UserMessage",
|
|
"AssistantMessage",
|
|
"SystemMessage",
|
|
]
|
|
|
|
all_passed = True
|
|
for export in required_exports:
|
|
try:
|
|
from claude_agent_sdk import query # noqa: F401
|
|
|
|
module = __import__("claude_agent_sdk", fromlist=[export])
|
|
getattr(module, export)
|
|
print(f" [PASS] {export}")
|
|
except (ImportError, AttributeError) as e:
|
|
print(f" [FAIL] {export}: {e}")
|
|
all_passed = False
|
|
|
|
return all_passed
|
|
|
|
|
|
def test_types() -> bool:
|
|
"""Test type definitions are available."""
|
|
print()
|
|
print("-" * 60)
|
|
print("Testing type definitions...")
|
|
print("-" * 60)
|
|
|
|
try:
|
|
from claude_agent_sdk import (
|
|
AssistantMessage,
|
|
ClaudeAgentOptions,
|
|
Message,
|
|
PermissionMode,
|
|
StreamEvent,
|
|
TextBlock,
|
|
ThinkingConfig,
|
|
ToolUseBlock,
|
|
UserMessage,
|
|
)
|
|
|
|
print(f" [PASS] ClaudeAgentOptions: {ClaudeAgentOptions}")
|
|
print(f" [PASS] Message: {Message}")
|
|
print(f" [PASS] UserMessage: {UserMessage}")
|
|
print(f" [PASS] AssistantMessage: {AssistantMessage}")
|
|
print(f" [PASS] TextBlock: {TextBlock}")
|
|
print(f" [PASS] ToolUseBlock: {ToolUseBlock}")
|
|
print(f" [PASS] StreamEvent: {StreamEvent}")
|
|
print(f" [PASS] ThinkingConfig: {ThinkingConfig}")
|
|
print(f" [PASS] PermissionMode: {PermissionMode}")
|
|
return True
|
|
except ImportError as e:
|
|
print(f" [FAIL] Type import failed: {e}")
|
|
return False
|
|
|
|
|
|
def test_mcp_integration() -> bool:
|
|
"""Test MCP server configuration types."""
|
|
print()
|
|
print("-" * 60)
|
|
print("Testing MCP integration types...")
|
|
print("-" * 60)
|
|
|
|
try:
|
|
from claude_agent_sdk import (
|
|
McpServerConfig,
|
|
McpServerInfo,
|
|
McpServerStatus,
|
|
McpStatusResponse,
|
|
McpToolInfo,
|
|
)
|
|
|
|
print(f" [PASS] McpServerConfig: {McpServerConfig}")
|
|
print(f" [PASS] McpServerInfo: {McpServerInfo}")
|
|
print(f" [PASS] McpServerStatus: {McpServerStatus}")
|
|
print(f" [PASS] McpStatusResponse: {McpStatusResponse}")
|
|
print(f" [PASS] McpToolInfo: {McpToolInfo}")
|
|
return True
|
|
except ImportError as e:
|
|
print(f" [FAIL] MCP type import failed: {e}")
|
|
return False
|
|
|
|
|
|
def test_hook_types() -> bool:
|
|
"""Test hook-related types for agent customization."""
|
|
print()
|
|
print("-" * 60)
|
|
print("Testing hook types...")
|
|
print("-" * 60)
|
|
|
|
try:
|
|
from claude_agent_sdk import (
|
|
HookCallback,
|
|
HookContext,
|
|
HookInput,
|
|
PermissionRequestHookInput,
|
|
PostToolUseHookInput,
|
|
PreToolUseHookInput,
|
|
StopHookInput,
|
|
)
|
|
|
|
print(f" [PASS] HookCallback: {HookCallback}")
|
|
print(f" [PASS] HookContext: {HookContext}")
|
|
print(f" [PASS] HookInput: {HookInput}")
|
|
print(f" [PASS] PreToolUseHookInput: {PreToolUseHookInput}")
|
|
print(f" [PASS] PostToolUseHookInput: {PostToolUseHookInput}")
|
|
print(f" [PASS] PermissionRequestHookInput: {PermissionRequestHookInput}")
|
|
print(f" [PASS] StopHookInput: {StopHookInput}")
|
|
return True
|
|
except ImportError as e:
|
|
print(f" [FAIL] Hook type import failed: {e}")
|
|
return False
|
|
|
|
|
|
def test_session_management() -> bool:
|
|
"""Test session management functions."""
|
|
print()
|
|
print("-" * 60)
|
|
print("Testing session management functions...")
|
|
print("-" * 60)
|
|
|
|
try:
|
|
from claude_agent_sdk import (
|
|
get_session_info,
|
|
get_session_messages,
|
|
list_sessions,
|
|
rename_session,
|
|
tag_session,
|
|
)
|
|
|
|
print(f" [PASS] list_sessions: {list_sessions}")
|
|
print(f" [PASS] get_session_info: {get_session_info}")
|
|
print(f" [PASS] get_session_messages: {get_session_messages}")
|
|
print(f" [PASS] rename_session: {rename_session}")
|
|
print(f" [PASS] tag_session: {tag_session}")
|
|
return True
|
|
except ImportError as e:
|
|
print(f" [FAIL] Session management import failed: {e}")
|
|
return False
|
|
|
|
|
|
def test_api_key_available() -> bool:
|
|
"""Check if ANTHROPIC_API_KEY is available."""
|
|
print()
|
|
print("-" * 60)
|
|
print("Checking environment variables...")
|
|
print("-" * 60)
|
|
|
|
api_key = os.environ.get("ANTHROPIC_API_KEY")
|
|
if api_key:
|
|
# Don't print the actual key
|
|
masked = api_key[:8] + "..." + api_key[-4:] if len(api_key) > 12 else "***"
|
|
print(f" [INFO] ANTHROPIC_API_KEY is set (masked: {masked})")
|
|
return True
|
|
else:
|
|
print(" [INFO] ANTHROPIC_API_KEY not set - skipping API call test")
|
|
return False
|
|
|
|
|
|
def list_required_env_vars() -> None:
|
|
"""List all required environment variables for full functionality."""
|
|
print()
|
|
print("=" * 60)
|
|
print("Required Environment Variables for Full Functionality")
|
|
print("=" * 60)
|
|
print()
|
|
|
|
env_vars = [
|
|
("ANTHROPIC_API_KEY", "Required for API calls", True),
|
|
("CLAUDE_API_KEY", "Alternative API key (optional)", False),
|
|
("CLAUDE_CONFIG_DIR", "Custom config directory (optional)", False),
|
|
]
|
|
|
|
print("| Variable | Description | Required |")
|
|
print("|-------------------|----------------------------------|----------|")
|
|
for var, desc, required in env_vars:
|
|
status = "Yes" if required else "No"
|
|
is_set = "[SET]" if os.environ.get(var) else "[NOT SET]"
|
|
print(f"| {var:<17} | {desc:<32} | {status:<8} | {is_set}")
|
|
print()
|
|
|
|
|
|
def main() -> int:
|
|
"""Run all tests and return exit code."""
|
|
results: dict[str, bool] = {}
|
|
|
|
# Run tests
|
|
results["import"] = test_import()
|
|
results["core_exports"] = test_core_exports()
|
|
results["types"] = test_types()
|
|
results["mcp_integration"] = test_mcp_integration()
|
|
results["hooks"] = test_hook_types()
|
|
results["session_management"] = test_session_management()
|
|
|
|
# Check API key
|
|
has_api_key = test_api_key_available()
|
|
|
|
# List required env vars
|
|
list_required_env_vars()
|
|
|
|
# Summary
|
|
print("=" * 60)
|
|
print("Summary")
|
|
print("=" * 60)
|
|
print()
|
|
|
|
passed = sum(1 for v in results.values() if v)
|
|
total = len(results)
|
|
|
|
for test_name, passed_test in results.items():
|
|
status = "[PASS]" if passed_test else "[FAIL]"
|
|
print(f" {status} {test_name}")
|
|
|
|
print()
|
|
print(f"Results: {passed}/{total} tests passed")
|
|
print()
|
|
|
|
if passed == total:
|
|
print("[SUCCESS] claude-agent-sdk is ready for Phase 9 integration!")
|
|
print()
|
|
print("Next steps:")
|
|
print(" 1. Add 'claude-agent-sdk>=0.1.50' to apps/api/pyproject.toml")
|
|
print(" 2. Set ANTHROPIC_API_KEY in environment")
|
|
print(" 3. Create agent definitions in apps/api/src/agents/")
|
|
return 0
|
|
else:
|
|
print("[WARNING] Some tests failed. Please review the output above.")
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|