fix: make CLI robust to missing coordinator dependencies

- Replace hardcoded absolute paths with project-relative resolution
- Add AITBC_SERVICES_PATH environment variable override
- Wrap service imports in try/except with graceful degradation
- Add aiohttp to CLI requirements
- Create missing README.md for aitbc-agent-sdk to fix poetry build
- Make run_all_tests.sh portable with PROJECT_ROOT calculation
- Fix enterprise_integration.py path handling

CLI now loads successfully even when coordinator-api services
are not installed. Advanced commands fail with helpful hints
instead of crashing the entire CLI.
This commit is contained in:
aitbc1
2026-03-13 11:34:30 +00:00
parent 3a711d4e33
commit 1feeadf8d2
9 changed files with 280 additions and 55 deletions

View File

@@ -10,14 +10,50 @@ import json
from typing import Optional, List, Dict, Any
from datetime import datetime, timedelta
# Import advanced analytics
# Import advanced analytics with robust path resolution
import os
import sys
sys.path.append('/home/oib/windsurf/aitbc/apps/coordinator-api/src/app/services')
from advanced_analytics import (
start_analytics_monitoring, stop_analytics_monitoring, get_dashboard_data,
create_analytics_alert, get_analytics_summary, advanced_analytics,
MetricType, Timeframe
)
_services_path = os.environ.get('AITBC_SERVICES_PATH')
if _services_path:
if os.path.isdir(_services_path):
if _services_path not in sys.path:
sys.path.insert(0, _services_path)
else:
print(f"Warning: AITBC_SERVICES_PATH set but not a directory: {_services_path}", file=sys.stderr)
else:
_project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
_computed_services = os.path.join(_project_root, 'apps', 'coordinator-api', 'src', 'app', 'services')
if os.path.isdir(_computed_services) and _computed_services not in sys.path:
sys.path.insert(0, _computed_services)
else:
_fallback = '/home/oib/windsurf/aitbc/apps/coordinator-api/src/app/services'
if os.path.isdir(_fallback) and _fallback not in sys.path:
sys.path.insert(0, _fallback)
try:
from advanced_analytics import (
start_analytics_monitoring, stop_analytics_monitoring, get_dashboard_data,
create_analytics_alert, get_analytics_summary, advanced_analytics,
MetricType, Timeframe
)
_import_error = None
except ImportError as e:
_import_error = e
def _missing(*args, **kwargs):
raise ImportError(
f"Required service module 'advanced_analytics' could not be imported: {_import_error}. "
"Ensure coordinator-api dependencies are installed or set AITBC_SERVICES_PATH."
)
start_analytics_monitoring = stop_analytics_monitoring = get_dashboard_data = _missing
create_analytics_alert = get_analytics_summary = _missing
advanced_analytics = None
class MetricType:
pass
class Timeframe:
pass
@click.group()
def advanced_analytics_group():

View File

@@ -10,14 +10,52 @@ import json
from typing import Optional, List, Dict, Any
from datetime import datetime
# Import AI surveillance system
# Import AI surveillance system with robust path resolution
import os
import sys
sys.path.append('/home/oib/windsurf/aitbc/apps/coordinator-api/src/app/services')
from ai_surveillance import (
start_ai_surveillance, stop_ai_surveillance, get_surveillance_summary,
get_user_risk_profile, list_active_alerts, analyze_behavior_patterns,
ai_surveillance, SurveillanceType, RiskLevel, AlertPriority
)
_services_path = os.environ.get('AITBC_SERVICES_PATH')
if _services_path:
if os.path.isdir(_services_path):
if _services_path not in sys.path:
sys.path.insert(0, _services_path)
else:
print(f"Warning: AITBC_SERVICES_PATH set but not a directory: {_services_path}", file=sys.stderr)
else:
_project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
_computed_services = os.path.join(_project_root, 'apps', 'coordinator-api', 'src', 'app', 'services')
if os.path.isdir(_computed_services) and _computed_services not in sys.path:
sys.path.insert(0, _computed_services)
else:
_fallback = '/home/oib/windsurf/aitbc/apps/coordinator-api/src/app/services'
if os.path.isdir(_fallback) and _fallback not in sys.path:
sys.path.insert(0, _fallback)
try:
from ai_surveillance import (
start_ai_surveillance, stop_ai_surveillance, get_surveillance_summary,
get_user_risk_profile, list_active_alerts, analyze_behavior_patterns,
ai_surveillance, SurveillanceType, RiskLevel, AlertPriority
)
_import_error = None
except ImportError as e:
_import_error = e
def _missing(*args, **kwargs):
raise ImportError(
f"Required service module 'ai_surveillance' could not be imported: {_import_error}. "
"Ensure coordinator-api dependencies are installed or set AITBC_SERVICES_PATH."
)
start_ai_surveillance = stop_ai_surveillance = get_surveillance_summary = _missing
get_user_risk_profile = list_active_alerts = analyze_behavior_patterns = _missing
ai_surveillance = None
class SurveillanceType:
pass
class RiskLevel:
pass
class AlertPriority:
pass
@click.group()
def ai_surveillance_group():

View File

@@ -10,13 +10,46 @@ import json
from typing import Optional, List, Dict, Any
from datetime import datetime, timedelta
# Import AI trading engine
# Import AI trading engine with robust path resolution
import os
import sys
sys.path.append('/home/oib/windsurf/aitbc/apps/coordinator-api/src/app/services')
from ai_trading_engine import (
initialize_ai_engine, train_strategies, generate_trading_signals,
get_engine_status, ai_trading_engine, TradingStrategy
)
_services_path = os.environ.get('AITBC_SERVICES_PATH')
if _services_path:
if os.path.isdir(_services_path):
if _services_path not in sys.path:
sys.path.insert(0, _services_path)
else:
print(f"Warning: AITBC_SERVICES_PATH set but not a directory: {_services_path}", file=sys.stderr)
else:
_project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
_computed_services = os.path.join(_project_root, 'apps', 'coordinator-api', 'src', 'app', 'services')
if os.path.isdir(_computed_services) and _computed_services not in sys.path:
sys.path.insert(0, _computed_services)
else:
_fallback = '/home/oib/windsurf/aitbc/apps/coordinator-api/src/app/services'
if os.path.isdir(_fallback) and _fallback not in sys.path:
sys.path.insert(0, _fallback)
try:
from ai_trading_engine import (
initialize_ai_engine, train_strategies, generate_trading_signals,
get_engine_status, ai_trading_engine, TradingStrategy
)
_import_error = None
except ImportError as e:
_import_error = e
def _missing(*args, **kwargs):
raise ImportError(
f"Required service module 'ai_trading_engine' could not be imported: {_import_error}. "
"Ensure coordinator-api dependencies are installed or set AITBC_SERVICES_PATH."
)
initialize_ai_engine = train_strategies = generate_trading_signals = get_engine_status = _missing
ai_trading_engine = None
class TradingStrategy:
pass
@click.group()
def ai_trading():

View File

@@ -12,18 +12,40 @@ from datetime import datetime
# Import enterprise integration services using importlib to avoid naming conflicts
import importlib.util
import os
spec = importlib.util.spec_from_file_location("enterprise_integration_service", "/home/oib/windsurf/aitbc/apps/coordinator-api/src/app/services/enterprise_integration.py")
ei = importlib.util.module_from_spec(spec)
spec.loader.exec_module(ei)
_services_path = os.environ.get('AITBC_SERVICES_PATH')
if _services_path:
base_dir = _services_path
else:
_project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
base_dir = os.path.join(_project_root, 'apps', 'coordinator-api', 'src', 'app', 'services')
if not os.path.isdir(base_dir):
base_dir = '/home/oib/windsurf/aitbc/apps/coordinator-api/src/app/services'
create_tenant = ei.create_tenant
get_tenant_info = ei.get_tenant_info
generate_api_key = ei.generate_api_key
register_integration = ei.register_integration
get_system_status = ei.get_system_status
list_tenants = ei.list_tenants
list_integrations = ei.list_integrations
module_path = os.path.join(base_dir, 'enterprise_integration.py')
if os.path.isfile(module_path):
spec = importlib.util.spec_from_file_location("enterprise_integration_service", module_path)
ei = importlib.util.module_from_spec(spec)
spec.loader.exec_module(ei)
create_tenant = ei.create_tenant
get_tenant_info = ei.get_tenant_info
generate_api_key = ei.generate_api_key
register_integration = ei.register_integration
get_system_status = ei.get_system_status
list_tenants = ei.list_tenants
list_integrations = ei.list_integrations
EnterpriseAPIGateway = getattr(ei, 'EnterpriseAPIGateway', None)
else:
# Provide stubs if module not found
def _missing(*args, **kwargs):
raise ImportError(
f"Could not load enterprise_integration.py from {module_path}. "
"Ensure coordinator-api services are available or set AITBC_SERVICES_PATH."
)
create_tenant = get_tenant_info = generate_api_key = _missing
register_integration = get_system_status = list_tenants = list_integrations = _missing
EnterpriseAPIGateway = None
@click.group()
def enterprise_integration_group():

View File

@@ -10,13 +10,49 @@ import json
from typing import Optional, List, Dict, Any
from datetime import datetime, timedelta
# Import regulatory reporting system
# Import regulatory reporting system with robust path resolution
import os
import sys
sys.path.append('/home/oib/windsurf/aitbc/apps/coordinator-api/src/app/services')
from regulatory_reporting import (
generate_sar, generate_compliance_summary, list_reports,
regulatory_reporter, ReportType, ReportStatus, RegulatoryBody
)
_services_path = os.environ.get('AITBC_SERVICES_PATH')
if _services_path:
if os.path.isdir(_services_path):
if _services_path not in sys.path:
sys.path.insert(0, _services_path)
else:
print(f"Warning: AITBC_SERVICES_PATH set but not a directory: {_services_path}", file=sys.stderr)
else:
_project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
_computed_services = os.path.join(_project_root, 'apps', 'coordinator-api', 'src', 'app', 'services')
if os.path.isdir(_computed_services) and _computed_services not in sys.path:
sys.path.insert(0, _computed_services)
else:
_fallback = '/home/oib/windsurf/aitbc/apps/coordinator-api/src/app/services'
if os.path.isdir(_fallback) and _fallback not in sys.path:
sys.path.insert(0, _fallback)
try:
from regulatory_reporting import (
generate_sar, generate_compliance_summary, list_reports,
regulatory_reporter, ReportType, ReportStatus, RegulatoryBody
)
_import_error = None
except ImportError as e:
_import_error = e
def _missing(*args, **kwargs):
raise ImportError(
f"Required service module 'regulatory_reporting' could not be imported: {_import_error}. "
"Ensure coordinator-api dependencies are installed or set AITBC_SERVICES_PATH."
)
generate_sar = generate_compliance_summary = list_reports = regulatory_reporter = _missing
class ReportType:
pass
class ReportStatus:
pass
class RegulatoryBody:
pass
@click.group()
def regulatory():

View File

@@ -10,13 +10,49 @@ import json
from typing import Optional, List, Dict, Any
from datetime import datetime, timedelta
# Import surveillance system
# Import surveillance system with robust path resolution
import os
import sys
sys.path.append('/home/oib/windsurf/aitbc/apps/coordinator-api/src/app/services')
from trading_surveillance import (
start_surveillance, stop_surveillance, get_alerts,
get_surveillance_summary, AlertLevel
)
# Determine services path: use AITBC_SERVICES_PATH if set, else compute relative to repo layout
_services_path = os.environ.get('AITBC_SERVICES_PATH')
if _services_path:
if os.path.isdir(_services_path):
if _services_path not in sys.path:
sys.path.insert(0, _services_path)
else:
print(f"Warning: AITBC_SERVICES_PATH set but not a directory: {_services_path}", file=sys.stderr)
else:
# Compute project root relative to this file: cli/aitbc_cli/commands -> 3 levels up to project root
_project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
_computed_services = os.path.join(_project_root, 'apps', 'coordinator-api', 'src', 'app', 'services')
if os.path.isdir(_computed_services) and _computed_services not in sys.path:
sys.path.insert(0, _computed_services)
else:
# Fallback to known hardcoded path if it exists (for legacy deployments)
_fallback = '/home/oib/windsurf/aitbc/apps/coordinator-api/src/app/services'
if os.path.isdir(_fallback) and _fallback not in sys.path:
sys.path.insert(0, _fallback)
try:
from trading_surveillance import (
start_surveillance, stop_surveillance, get_alerts,
get_surveillance_summary, AlertLevel
)
_import_error = None
except ImportError as e:
_import_error = e
def _missing(*args, **kwargs):
raise ImportError(
f"Required service module 'trading_surveillance' could not be imported: {_import_error}. "
"Ensure coordinator-api dependencies are installed or set AITBC_SERVICES_PATH."
)
start_surveillance = stop_surveillance = get_alerts = get_surveillance_summary = _missing
class AlertLevel:
"""Stub for AlertLevel when import fails."""
pass
@click.group()
def surveillance():

View File

@@ -9,3 +9,4 @@ click-completion>=0.5.2
tabulate>=0.9.0
colorama>=0.4.4
python-dotenv>=0.19.0
aiohttp>=3.9.0

View File

@@ -0,0 +1,18 @@
# aitbc-agent-sdk
Agent SDK for AITBC (AI Agent Compute Network).
This package provides tools and abstractions for building AI agents that participate in the AITBC decentralized compute marketplace.
## Installation
```bash
pip install -e .[dev]
```
## Development
Run tests:
```bash
pytest
```

View File

@@ -6,6 +6,10 @@ echo "=========================================="
echo "Testing localhost, aitbc, and aitbc1 with all CLI features"
echo ""
# Resolve project root (directory containing this script)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR" && pwd)"
# Function to run a test scenario
run_scenario() {
local scenario_name=$1
@@ -90,14 +94,15 @@ check_prerequisites() {
echo ""
echo "📋 Checking user configurations..."
# Check miner1 and client1 configurations
if [ -f "/home/oib/windsurf/aitbc/home/miner1/miner_wallet.json" ]; then
# Check miner1 and client1 configurations (relative to project root)
local home_dir="$PROJECT_ROOT/home"
if [ -f "$home_dir/miner1/miner_wallet.json" ]; then
echo "✅ miner1 configuration found"
else
echo "❌ miner1 configuration missing"
fi
if [ -f "/home/oib/windsurf/aitbc/home/client1/client_wallet.json" ]; then
if [ -f "$home_dir/client1/client_wallet.json" ]; then
echo "✅ client1 configuration found"
else
echo "❌ client1 configuration missing"
@@ -196,10 +201,10 @@ main() {
# Run scenario tests
local scenarios=(
"Scenario A: Localhost GPU Miner → aitbc Marketplace:/home/oib/windsurf/aitbc/test_scenario_a.sh"
"Scenario B: Localhost GPU Client → aitbc1 Marketplace:/home/oib/windsurf/aitbc/test_scenario_b.sh"
"Scenario C: aitbc Container User Operations:/home/oib/windsurf/aitbc/test_scenario_c.sh"
"Scenario D: aitbc1 Container User Operations:/home/oib/windsurf/aitbc/test_scenario_d.sh"
"Scenario A: Localhost GPU Miner → aitbc Marketplace:$PROJECT_ROOT/test_scenario_a.sh"
"Scenario B: Localhost GPU Client → aitbc1 Marketplace:$PROJECT_ROOT/test_scenario_b.sh"
"Scenario C: aitbc Container User Operations:$PROJECT_ROOT/test_scenario_c.sh"
"Scenario D: aitbc1 Container User Operations:$PROJECT_ROOT/test_scenario_d.sh"
)
for scenario_info in "${scenarios[@]}"; do
@@ -215,7 +220,7 @@ main() {
echo ""
echo "🔧 Running Comprehensive Test Suite"
echo "=================================="
if python3 /home/oib/windsurf/aitbc/test_multi_site.py; then
if python3 "$PROJECT_ROOT/test_multi_site.py"; then
echo "✅ Comprehensive test suite passed"
passed_count=$((passed_count + 1))
else
@@ -236,19 +241,19 @@ case "${1:-all}" in
run_cli_tests
;;
"scenario-a")
run_scenario "Scenario A" "/home/oib/windsurf/aitbc/test_scenario_a.sh"
run_scenario "Scenario A" "$PROJECT_ROOT/test_scenario_a.sh"
;;
"scenario-b")
run_scenario "Scenario B" "/home/oib/windsurf/aitbc/test_scenario_b.sh"
run_scenario "Scenario B" "$PROJECT_ROOT/test_scenario_b.sh"
;;
"scenario-c")
run_scenario "Scenario C" "/home/oib/windsurf/aitbc/test_scenario_c.sh"
run_scenario "Scenario C" "$PROJECT_ROOT/test_scenario_c.sh"
;;
"scenario-d")
run_scenario "Scenario D" "/home/oib/windsurf/aitbc/test_scenario_d.sh"
run_scenario "Scenario D" "$PROJECT_ROOT/test_scenario_d.sh"
;;
"comprehensive")
python3 /home/oib/windsurf/aitbc/test_multi_site.py
python3 "$PROJECT_ROOT/test_multi_site.py"
;;
"all"|*)
main