Implement 36 missing CLI subcommands for scenarios 04-47

Phase 1: Simple GET Commands (system, resource, edge, config)
- system: restart, status, config
- resource: status, deallocate
- edge: status, balance, transfer
- config: import (already existed)

Phase 2: Exchange & Market Commands
- exchange: order, orders, book, history
- marketplace: bid, bids, ask, asks

Phase 3: AI & GPU Commands
- agent (AI): job, jobs, submit, cancel
- gpu: register, update

Phase 4: Wallet, Hermes, Operations
- wallet: export, import
- hermes: send, receive, peers
- operations: vote, proposal, delegate

Phase 5: Simulate Commands
- simulate: run, status, result

All commands follow common pattern using AITBCHTTPClient for backend API interaction.
This commit is contained in:
aitbc
2026-05-26 22:03:58 +02:00
parent ac59e3ee0a
commit 51209844c9
11 changed files with 865 additions and 10 deletions

View File

@@ -5,6 +5,13 @@ System commands for AITBC CLI
import click
import os
import subprocess
from pathlib import Path
from ..utils import output, error, success
from ..config import get_config
from aitbc import get_logger, AITBCHTTPClient, NetworkError
logger = get_logger(__name__)
@click.group()
def system():
@@ -50,5 +57,80 @@ def check(service):
else:
click.echo(f"{svc}: {service_file}")
@system.command()
@click.option('--service', required=True, help='Service to restart (e.g., blockchain-node, wallet)')
@click.pass_context
def restart(ctx, service: str):
"""Restart a systemd service"""
service_name = f"aitbc-{service}" if not service.startswith("aitbc-") else service
try:
success(f"Restarting service: {service_name}")
result = subprocess.run(
["sudo", "systemctl", "restart", service_name],
capture_output=True,
text=True,
timeout=30
)
if result.returncode == 0:
success(f"Service {service_name} restarted successfully")
output({"service": service_name, "status": "restarted"}, ctx.obj.get("output_format", "table"))
else:
error(f"Failed to restart service: {result.stderr}")
except subprocess.TimeoutExpired:
error(f"Timeout restarting service {service_name}")
except Exception as e:
error(f"Error restarting service: {e}")
@system.command()
@click.pass_context
def status(ctx):
"""Get system status from coordinator-api"""
config = get_config()
try:
http_client = AITBCHTTPClient(base_url=config.coordinator_url, timeout=10)
status_data = http_client.get("/api/v1/status")
success("System Status:")
output(status_data, ctx.obj.get("output_format", "table"))
except NetworkError as e:
error(f"Network error: {e}")
except Exception as e:
error(f"Error fetching status: {e}")
@system.command()
@click.option('--show-secrets', is_flag=True, help='Show sensitive values like API keys')
@click.pass_context
def config(ctx, show_secrets: bool):
"""Display system configuration from /etc/aitbc/blockchain.env"""
config_path = Path("/etc/aitbc/blockchain.env")
if not config_path.exists():
error(f"Configuration file not found: {config_path}")
return
try:
with open(config_path, 'r') as f:
config_lines = f.readlines()
config_data = {}
for line in config_lines:
line = line.strip()
if line and not line.startswith('#') and '=' in line:
key, value = line.split('=', 1)
# Hide secrets unless explicitly requested
if not show_secrets and any(secret in key.lower() for secret in ['key', 'secret', 'password', 'token']):
value = '***HIDDEN***'
config_data[key.strip()] = value.strip()
success("System Configuration:")
output(config_data, ctx.obj.get("output_format", "table"))
except Exception as e:
error(f"Error reading configuration: {e}")
if __name__ == '__main__':
system()