BEFORE: /opt/aitbc/cli/ ├── aitbc_cli/ # Python package (box in a box) │ ├── commands/ │ ├── main.py │ └── ... ├── setup.py AFTER: /opt/aitbc/cli/ # Flat structure ├── commands/ # Direct access ├── main.py # Direct access ├── auth/ ├── config/ ├── core/ ├── models/ ├── utils/ ├── plugins.py └── setup.py CHANGES MADE: - Moved all files from aitbc_cli/ to cli/ root - Fixed all relative imports (from . to absolute imports) - Updated setup.py entry point: aitbc_cli.main → main - Added CLI directory to Python path in entry script - Simplified deployment.py to remove dependency on deleted core.deployment - Fixed import paths in all command files - Recreated virtual environment with new structure BENEFITS: - Eliminated 'box in a box' nesting - Simpler directory structure - Direct access to all modules - Cleaner imports - Easier maintenance and development - CLI works with both 'python main.py' and 'aitbc' commands
102 lines
4.2 KiB
Python
Executable File
102 lines
4.2 KiB
Python
Executable File
"""
|
|
Multi-chain configuration management for AITBC CLI
|
|
"""
|
|
|
|
from pathlib import Path
|
|
from typing import Dict, Any, Optional
|
|
import yaml
|
|
from pydantic import BaseModel, Field
|
|
|
|
class NodeConfig(BaseModel):
|
|
"""Configuration for a specific node"""
|
|
id: str = Field(..., description="Node identifier")
|
|
endpoint: str = Field(..., description="Node endpoint URL")
|
|
timeout: int = Field(default=30, description="Request timeout in seconds")
|
|
retry_count: int = Field(default=3, description="Number of retry attempts")
|
|
max_connections: int = Field(default=10, description="Maximum concurrent connections")
|
|
|
|
class ChainConfig(BaseModel):
|
|
"""Default chain configuration"""
|
|
default_gas_limit: int = Field(default=10000000, description="Default gas limit")
|
|
default_gas_price: int = Field(default=20000000000, description="Default gas price in wei")
|
|
max_block_size: int = Field(default=1048576, description="Maximum block size in bytes")
|
|
backup_path: Path = Field(default=Path("./backups"), description="Backup directory path")
|
|
max_concurrent_chains: int = Field(default=100, description="Maximum concurrent chains per node")
|
|
|
|
class MultiChainConfig(BaseModel):
|
|
"""Multi-chain configuration"""
|
|
nodes: Dict[str, NodeConfig] = Field(default_factory=dict, description="Node configurations")
|
|
chains: ChainConfig = Field(default_factory=ChainConfig, description="Chain configuration")
|
|
logging_level: str = Field(default="INFO", description="Logging level")
|
|
enable_caching: bool = Field(default=True, description="Enable response caching")
|
|
cache_ttl: int = Field(default=300, description="Cache TTL in seconds")
|
|
|
|
def load_multichain_config(config_path: Optional[str] = None) -> MultiChainConfig:
|
|
"""Load multi-chain configuration from file"""
|
|
if config_path is None:
|
|
config_path = Path.home() / ".aitbc" / "multichain_config.yaml"
|
|
|
|
config_file = Path(config_path)
|
|
|
|
if not config_file.exists():
|
|
# Create default configuration
|
|
default_config = MultiChainConfig()
|
|
save_multichain_config(default_config, config_path)
|
|
return default_config
|
|
|
|
try:
|
|
with open(config_file, 'r') as f:
|
|
config_data = yaml.safe_load(f)
|
|
|
|
return MultiChainConfig(**config_data)
|
|
except Exception as e:
|
|
raise ValueError(f"Failed to load configuration from {config_path}: {e}")
|
|
|
|
def save_multichain_config(config: MultiChainConfig, config_path: Optional[str] = None) -> None:
|
|
"""Save multi-chain configuration to file"""
|
|
if config_path is None:
|
|
config_path = Path.home() / ".aitbc" / "multichain_config.yaml"
|
|
|
|
config_file = Path(config_path)
|
|
config_file.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
try:
|
|
# Convert Path objects to strings for YAML serialization
|
|
config_dict = config.dict()
|
|
if 'chains' in config_dict and 'backup_path' in config_dict['chains']:
|
|
config_dict['chains']['backup_path'] = str(config_dict['chains']['backup_path'])
|
|
|
|
with open(config_file, 'w') as f:
|
|
yaml.dump(config_dict, f, default_flow_style=False, indent=2)
|
|
except Exception as e:
|
|
raise ValueError(f"Failed to save configuration to {config_path}: {e}")
|
|
|
|
def get_default_node_config() -> NodeConfig:
|
|
"""Get default node configuration for local development"""
|
|
return NodeConfig(
|
|
id="default-node",
|
|
endpoint="http://localhost:8545",
|
|
timeout=30,
|
|
retry_count=3,
|
|
max_connections=10
|
|
)
|
|
|
|
def add_node_config(config: MultiChainConfig, node_config: NodeConfig) -> MultiChainConfig:
|
|
"""Add a node configuration"""
|
|
config.nodes[node_config.id] = node_config
|
|
return config
|
|
|
|
def remove_node_config(config: MultiChainConfig, node_id: str) -> MultiChainConfig:
|
|
"""Remove a node configuration"""
|
|
if node_id in config.nodes:
|
|
del config.nodes[node_id]
|
|
return config
|
|
|
|
def get_node_config(config: MultiChainConfig, node_id: str) -> Optional[NodeConfig]:
|
|
"""Get a specific node configuration"""
|
|
return config.nodes.get(node_id)
|
|
|
|
def list_node_configs(config: MultiChainConfig) -> Dict[str, NodeConfig]:
|
|
"""List all node configurations"""
|
|
return config.nodes.copy()
|