#!/usr/bin/env python3 """ BZZZ SDK Python Async Client Example ==================================== Demonstrates asynchronous operations with the BZZZ SDK Python bindings. Shows decision publishing, event streaming, and collaborative workflows. """ import asyncio import json import logging import sys from datetime import datetime, timedelta from typing import Dict, List, Any, Optional # BZZZ SDK imports (would be installed via pip install bzzz-sdk) try: from bzzz_sdk import BzzzClient, DecisionType, EventType from bzzz_sdk.decisions import CodeDecision, ArchitecturalDecision, TestResults from bzzz_sdk.crypto import AgeKeyPair from bzzz_sdk.exceptions import BzzzError, PermissionError, NetworkError except ImportError: print("⚠️ BZZZ SDK not installed. Run: pip install bzzz-sdk") print(" This example shows the expected API structure") sys.exit(1) # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) class BzzzAsyncExample: """Comprehensive async example using BZZZ SDK""" def __init__(self, endpoint: str = "http://localhost:8080"): self.endpoint = endpoint self.client: Optional[BzzzClient] = None self.event_count = 0 self.decision_count = 0 async def initialize(self, role: str = "backend_developer"): """Initialize the BZZZ client connection""" try: self.client = BzzzClient( endpoint=self.endpoint, role=role, timeout=30.0, max_retries=3 ) # Test connection status = await self.client.get_status() logger.info(f"✅ Connected as {status.agent_id} ({status.role})") logger.info(f" Node ID: {status.node_id}") logger.info(f" Authority: {status.authority_level}") logger.info(f" Can decrypt: {status.can_decrypt}") return True except NetworkError as e: logger.error(f"❌ Network error connecting to BZZZ: {e}") return False except BzzzError as e: logger.error(f"❌ BZZZ error during initialization: {e}") return False async def example_basic_operations(self): """Example 1: Basic client operations""" logger.info("📋 Example 1: Basic Operations") try: # Get status status = await self.client.get_status() logger.info(f" Status: {status.role} with {status.active_tasks} active tasks") # Get peers peers = await self.client.get_peers() logger.info(f" Connected peers: {len(peers)}") for peer in peers[:3]: # Show first 3 logger.info(f" - {peer.agent_id} ({peer.role})") # Get capabilities capabilities = await self.client.get_capabilities() logger.info(f" Capabilities: {capabilities.capabilities}") logger.info(f" Models: {capabilities.models}") except BzzzError as e: logger.error(f" ❌ Basic operations failed: {e}") async def example_decision_publishing(self): """Example 2: Publishing different types of decisions""" logger.info("📝 Example 2: Decision Publishing") try: # Publish code decision code_decision = await self.client.decisions.publish_code( task="implement_async_client", decision="Implemented Python async client with comprehensive examples", files_modified=[ "examples/sdk/python/async_client.py", "bzzz_sdk/client.py", "tests/test_async_client.py" ], lines_changed=250, test_results=TestResults( passed=15, failed=0, skipped=1, coverage=94.5, failed_tests=[] ), dependencies=[ "asyncio", "aiohttp", "websockets" ], language="python" ) logger.info(f" ✅ Code decision published: {code_decision.address}") # Publish architectural decision arch_decision = await self.client.decisions.publish_architectural( task="design_async_architecture", decision="Adopt asyncio-based architecture for better concurrency", rationale="Async operations improve performance for I/O-bound tasks", alternatives=[ "Threading-based approach", "Synchronous with process pools", "Hybrid sync/async model" ], implications=[ "Requires Python 3.7+", "All network operations become async", "Better resource utilization", "More complex error handling" ], next_steps=[ "Update all SDK methods to async", "Add async connection pooling", "Implement proper timeout handling", "Add async example documentation" ] ) logger.info(f" ✅ Architectural decision published: {arch_decision.address}") except PermissionError as e: logger.error(f" ❌ Permission denied publishing decision: {e}") except BzzzError as e: logger.error(f" ❌ Decision publishing failed: {e}") async def example_event_streaming(self, duration: int = 30): """Example 3: Real-time event streaming""" logger.info(f"🎧 Example 3: Event Streaming ({duration}s)") try: # Subscribe to all events event_stream = self.client.subscribe_events() # Subscribe to specific role decisions decision_stream = self.client.decisions.stream_decisions( role="backend_developer", content_type="decision" ) # Process events for specified duration end_time = datetime.now() + timedelta(seconds=duration) while datetime.now() < end_time: try: # Wait for events with timeout event = await asyncio.wait_for(event_stream.get_event(), timeout=1.0) await self.handle_event(event) except asyncio.TimeoutError: # Check for decisions try: decision = await asyncio.wait_for(decision_stream.get_decision(), timeout=0.1) await self.handle_decision(decision) except asyncio.TimeoutError: continue logger.info(f" 📊 Processed {self.event_count} events, {self.decision_count} decisions") except BzzzError as e: logger.error(f" ❌ Event streaming failed: {e}") async def handle_event(self, event): """Handle incoming system events""" self.event_count += 1 event_handlers = { EventType.DECISION_PUBLISHED: self.handle_decision_published, EventType.ADMIN_CHANGED: self.handle_admin_changed, EventType.PEER_CONNECTED: self.handle_peer_connected, EventType.PEER_DISCONNECTED: self.handle_peer_disconnected } handler = event_handlers.get(event.type, self.handle_unknown_event) await handler(event) async def handle_decision_published(self, event): """Handle decision published events""" logger.info(f" 📝 Decision published: {event.data.get('address', 'unknown')}") logger.info(f" Creator: {event.data.get('creator_role', 'unknown')}") async def handle_admin_changed(self, event): """Handle admin change events""" old_admin = event.data.get('old_admin', 'unknown') new_admin = event.data.get('new_admin', 'unknown') reason = event.data.get('election_reason', 'unknown') logger.info(f" 👑 Admin changed: {old_admin} -> {new_admin} ({reason})") async def handle_peer_connected(self, event): """Handle peer connection events""" agent_id = event.data.get('agent_id', 'unknown') role = event.data.get('role', 'unknown') logger.info(f" 🌐 Peer connected: {agent_id} ({role})") async def handle_peer_disconnected(self, event): """Handle peer disconnection events""" agent_id = event.data.get('agent_id', 'unknown') logger.info(f" 🔌 Peer disconnected: {agent_id}") async def handle_unknown_event(self, event): """Handle unknown event types""" logger.info(f" ❓ Unknown event: {event.type}") async def handle_decision(self, decision): """Handle incoming decisions""" self.decision_count += 1 logger.info(f" 📋 Decision: {decision.task} - Success: {decision.success}") async def example_crypto_operations(self): """Example 4: Cryptographic operations""" logger.info("🔐 Example 4: Crypto Operations") try: # Generate Age key pair key_pair = await self.client.crypto.generate_keys() logger.info(f" 🔑 Generated Age key pair") logger.info(f" Public: {key_pair.public_key[:20]}...") logger.info(f" Private: {key_pair.private_key[:25]}...") # Test encryption test_content = "Sensitive Python development data" # Encrypt for current role encrypted = await self.client.crypto.encrypt_for_role( content=test_content.encode(), role="backend_developer" ) logger.info(f" 🔒 Encrypted {len(test_content)} bytes -> {len(encrypted)} bytes") # Decrypt content decrypted = await self.client.crypto.decrypt_with_role(encrypted) decrypted_text = decrypted.decode() if decrypted_text == test_content: logger.info(f" ✅ Decryption successful: {decrypted_text}") else: logger.error(f" ❌ Decryption mismatch") # Check permissions permissions = await self.client.crypto.get_permissions() logger.info(f" 🛡️ Role permissions:") logger.info(f" Current role: {permissions.current_role}") logger.info(f" Can decrypt: {permissions.can_decrypt}") logger.info(f" Authority: {permissions.authority_level}") except BzzzError as e: logger.error(f" ❌ Crypto operations failed: {e}") async def example_query_operations(self): """Example 5: Querying and data retrieval""" logger.info("📊 Example 5: Query Operations") try: # Query recent decisions recent_decisions = await self.client.decisions.query_recent( role="backend_developer", project="bzzz_sdk", since=datetime.now() - timedelta(hours=24), limit=10 ) logger.info(f" 📋 Found {len(recent_decisions)} recent decisions") for i, decision in enumerate(recent_decisions[:3]): logger.info(f" {i+1}. {decision.task} - {decision.timestamp}") logger.info(f" Success: {decision.success}") # Get specific decision content if recent_decisions: first_decision = recent_decisions[0] content = await self.client.decisions.get_content(first_decision.address) logger.info(f" 📄 Decision content preview:") logger.info(f" Address: {content.address}") logger.info(f" Decision: {content.decision[:100]}...") logger.info(f" Files modified: {len(content.files_modified or [])}") except PermissionError as e: logger.error(f" ❌ Permission denied querying decisions: {e}") except BzzzError as e: logger.error(f" ❌ Query operations failed: {e}") async def example_collaborative_workflow(self): """Example 6: Collaborative workflow simulation""" logger.info("🤝 Example 6: Collaborative Workflow") try: # Simulate a collaborative code review workflow logger.info(" Starting collaborative code review...") # Step 1: Announce code change await self.client.decisions.publish_code( task="refactor_authentication", decision="Refactored authentication module for better security", files_modified=[ "auth/jwt_handler.py", "auth/middleware.py", "tests/test_auth.py" ], lines_changed=180, test_results=TestResults( passed=12, failed=0, coverage=88.0 ), language="python" ) logger.info(" ✅ Step 1: Code change announced") # Step 2: Request reviews (simulate) await asyncio.sleep(1) # Simulate processing time logger.info(" 📋 Step 2: Review requests sent to:") logger.info(" - Senior Software Architect") logger.info(" - Security Expert") logger.info(" - QA Engineer") # Step 3: Simulate review responses await asyncio.sleep(2) reviews_completed = 0 # Simulate architect review await self.client.decisions.publish_architectural( task="review_auth_refactor", decision="Architecture review approved with minor suggestions", rationale="Refactoring improves separation of concerns", next_steps=["Add input validation documentation"] ) reviews_completed += 1 logger.info(f" ✅ Step 3.{reviews_completed}: Architect review completed") # Step 4: Aggregate and finalize await asyncio.sleep(1) logger.info(" 📊 Step 4: All reviews completed") logger.info(" Status: APPROVED with minor changes") logger.info(" Next steps: Address documentation suggestions") except BzzzError as e: logger.error(f" ❌ Collaborative workflow failed: {e}") async def run_all_examples(self): """Run all examples in sequence""" logger.info("🚀 Starting BZZZ SDK Python Async Examples") logger.info("=" * 60) examples = [ self.example_basic_operations, self.example_decision_publishing, self.example_crypto_operations, self.example_query_operations, self.example_collaborative_workflow, # Note: event_streaming runs last as it takes time ] for example in examples: try: await example() await asyncio.sleep(0.5) # Brief pause between examples except Exception as e: logger.error(f"❌ Example {example.__name__} failed: {e}") # Run event streaming for a shorter duration await self.example_event_streaming(duration=10) logger.info("=" * 60) logger.info("✅ All BZZZ SDK Python examples completed") async def cleanup(self): """Clean up resources""" if self.client: await self.client.close() logger.info("🧹 Client connection closed") async def main(): """Main entry point""" example = BzzzAsyncExample() try: # Initialize connection if not await example.initialize("backend_developer"): logger.error("Failed to initialize BZZZ client") return 1 # Run all examples await example.run_all_examples() except KeyboardInterrupt: logger.info("\n🛑 Examples interrupted by user") except Exception as e: logger.error(f"❌ Unexpected error: {e}") return 1 finally: await example.cleanup() return 0 if __name__ == "__main__": # Run the async example exit_code = asyncio.run(main()) sys.exit(exit_code)