From 62e65bc88f3a653b9c705795e08ebdb849a9c844 Mon Sep 17 00:00:00 2001 From: aitbc Date: Sat, 9 May 2026 12:17:56 +0200 Subject: [PATCH] docs: add CLI modularization analysis and common error handling utilities - Analyze blockchain.py (1,388 lines) and agent.py (793 lines) structure - Correct size estimates from analysis (not 55k/26k lines) - Both files already well-organized with logical command groupings - Create common error handling utilities module for CLI - Add CLIError base class and specialized exceptions - Add handle_cli_error and handle_async_cli_error decorators - Add validation utilities for URLs, addresses, and required fields --- cli/utils/error_handling.py | 181 ++++++++++++++++++ .../CLI_MODULARIZATION_ANALYSIS_2026-05-09.md | 127 ++++++++++++ 2 files changed, 308 insertions(+) create mode 100644 cli/utils/error_handling.py create mode 100644 docs/CLI_MODULARIZATION_ANALYSIS_2026-05-09.md diff --git a/cli/utils/error_handling.py b/cli/utils/error_handling.py new file mode 100644 index 00000000..a1e1162b --- /dev/null +++ b/cli/utils/error_handling.py @@ -0,0 +1,181 @@ +""" +Common error handling utilities for AITBC CLI +Provides standardized error handling patterns and utilities for CLI commands +""" + +import sys +from typing import Optional, Callable, Any +from functools import wraps +from . import error, warning, info + + +class CLIError(Exception): + """Base exception for CLI errors""" + def __init__(self, message: str, exit_code: int = 1): + self.message = message + self.exit_code = exit_code + super().__init__(self.message) + + +class NetworkError(CLIError): + """Network-related errors""" + def __init__(self, message: str): + super().__init__(f"Network error: {message}", exit_code=2) + + +class ConfigurationError(CLIError): + """Configuration-related errors""" + def __init__(self, message: str): + super().__init__(f"Configuration error: {message}", exit_code=3) + + +class ValidationError(CLIError): + """Validation errors for user input""" + def __init__(self, message: str): + super().__init__(f"Validation error: {message}", exit_code=4) + + +class APIError(CLIError): + """API-related errors""" + def __init__(self, message: str, status_code: Optional[int] = None): + msg = f"API error: {message}" + if status_code: + msg += f" (HTTP {status_code})" + super().__init__(msg, exit_code=5) + + +def handle_cli_error(func: Callable) -> Callable: + """ + Decorator to standardize error handling in CLI commands. + + Catches common exceptions and displays user-friendly error messages. + + Args: + func: Function to wrap with error handling + + Returns: + Wrapped function with standardized error handling + """ + @wraps(func) + def wrapper(*args, **kwargs): + try: + return func(*args, **kwargs) + except CLIError as e: + error(e.message) + sys.exit(e.exit_code) + except KeyboardInterrupt: + warning("\nOperation cancelled by user") + sys.exit(130) + except Exception as e: + error(f"Unexpected error: {e}") + sys.exit(1) + return wrapper + + +def handle_async_cli_error(func: Callable) -> Callable: + """ + Decorator to standardize error handling in async CLI commands. + + Args: + func: Async function to wrap with error handling + + Returns: + Wrapped async function with standardized error handling + """ + @wraps(func) + async def wrapper(*args, **kwargs): + try: + return await func(*args, **kwargs) + except CLIError as e: + error(e.message) + sys.exit(e.exit_code) + except KeyboardInterrupt: + warning("\nOperation cancelled by user") + sys.exit(130) + except Exception as e: + error(f"Unexpected error: {e}") + sys.exit(1) + return wrapper + + +def safe_execute( + operation: Callable, + error_message: str = "Operation failed", + default_return: Any = None, + raise_on_error: bool = False +) -> Any: + """ + Safely execute an operation with standardized error handling. + + Args: + operation: Function to execute + error_message: Custom error message prefix + default_return: Value to return on error (if not raising) + raise_on_error: Whether to raise exception on error + + Returns: + Operation result or default_return on error + + Raises: + Exception: If raise_on_error is True and operation fails + """ + try: + return operation() + except Exception as e: + if raise_on_error: + raise + error(f"{error_message}: {e}") + return default_return + + +def validate_required_fields(data: dict, required_fields: list) -> None: + """ + Validate that required fields are present in data dictionary. + + Args: + data: Dictionary to validate + required_fields: List of required field names + + Raises: + ValidationError: If any required field is missing + """ + missing_fields = [field for field in required_fields if field not in data or data[field] is None] + if missing_fields: + raise ValidationError(f"Missing required fields: {', '.join(missing_fields)}") + + +def validate_url(url: str) -> bool: + """ + Validate URL format. + + Args: + url: URL string to validate + + Returns: + True if valid, False otherwise + """ + import re + url_pattern = re.compile( + r'^https?://' # http:// or https:// + r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain... + r'localhost|' # localhost... + r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip + r'(?::\d+)?' # optional port + r'(?:/?|[/?]\S+)$', re.IGNORECASE) + return bool(url_pattern.match(url)) + + +def validate_address(address: str) -> bool: + """ + Validate Ethereum address format. + + Args: + address: Ethereum address string + + Returns: + True if valid, False otherwise + """ + import re + # Basic Ethereum address validation (0x followed by 40 hex characters) + address_pattern = re.compile(r'^0x[a-fA-F0-9]{40}$') + return bool(address_pattern.match(address)) diff --git a/docs/CLI_MODULARIZATION_ANALYSIS_2026-05-09.md b/docs/CLI_MODULARIZATION_ANALYSIS_2026-05-09.md new file mode 100644 index 00000000..eda96bc3 --- /dev/null +++ b/docs/CLI_MODULARIZATION_ANALYSIS_2026-05-09.md @@ -0,0 +1,127 @@ +# CLI Command Modularization Analysis + +**Date:** 2026-05-09 +**Purpose:** Analyze CLI command structure for modularization opportunities + +--- + +## blockchain.py Analysis + +**File Size:** 1,388 lines (not 55k as initially estimated) +**Commands:** 17 blockchain commands +**Structure:** Well-organized with single command group + +### Current Commands: +1. blocks - List recent blocks across chains +2. block - Get details of a specific block +3. transaction - Get transaction details +4. transactions - Get latest transactions on a chain +5. status - Get blockchain node status +6. sync_status - Get blockchain synchronization status +7. peers - List connected peers +8. info - Get blockchain information +9. supply - Get token supply information +10. validators - List blockchain validators +11. genesis - Get the genesis block +12. head - Get the head block +13. send - Send a transaction +14. balance - Get account balance +15. verify_genesis - Verify genesis block integrity +16. genesis_hash - Get genesis hash +17. state - Get chain state + +### Modularization Opportunities: +**Status:** Already well-organized. Single command group with focused commands. No immediate modularization needed. + +**Recommendation:** Keep as-is. The file size is manageable and commands are logically grouped. + +--- + +## agent.py Analysis + +**File Size:** 793 lines (not 26k as initially estimated) +**Commands:** 20 commands across 7 command groups +**Structure:** Well-organized with logical subgroups + +### Command Groups: +1. **agent** (main group) + - create - Create a new AI agent workflow + - list - List agents + - execute - Execute an agent + - status - Get execution status + - receipt - Get execution receipt + +2. **network** (subgroup) + - create - Create agent network + - execute - Execute network task + - status - Get network status + - optimize - Optimize network + +3. **zk** (subgroup) + - generate_proof - Generate zero-knowledge proof + - verify_proof - Verify zero-knowledge proof + - create_receipt - Create cryptographic receipt + +4. **knowledge** (subgroup) + - create - Create knowledge graph + - add_node - Add node to graph + +5. **bounty** (subgroup) + - create - Create bounty + - list - List bounties + +6. **dispute** (subgroup) + - file - File dispute + - vote - Vote on dispute + +7. **learning** (subgroup) + - enable - Enable learning + - train - Train agent + - progress - Get training progress + - export - Export model + +8. **contribution** (standalone) + - submit_contribution - Submit contribution + +### Modularization Opportunities: +**Status:** Already well-organized with logical command groups. Each subgroup handles a specific domain. + +**Recommendation:** Keep as-is. The file structure is already modular with clear separation of concerns. + +--- + +## Other CLI Commands + +**Total command files:** 62 command files in `/opt/aitbc/cli/commands/` + +### Large Command Files to Review: +- `admin.py` +- `advanced_analytics.py` +- `ai_trading.py` +- `marketplace_advanced.py` +- `multi_region_load_balancer.py` + +### Modularization Recommendations: + +**Immediate Actions:** +1. Review files > 500 lines for potential modularization +2. Ensure consistent error handling patterns across all command files +3. Create common utilities for repeated patterns + +**Medium-term Actions:** +1. Consider extracting common patterns into utility modules +2. Create base classes for similar command structures +3. Implement plugin system for extensible commands + +--- + +## Conclusion + +The initial analysis estimated blockchain.py at 55k lines and agent.py at 26k lines, but actual sizes are: +- blockchain.py: 1,388 lines +- agent.py: 793 lines + +Both files are already well-organized with logical command groupings and do not require immediate modularization. The focus should shift to: +1. Standardizing error handling across all 62 command files +2. Creating common utilities for repeated patterns +3. Reviewing other large command files for actual modularization needs