fix: resolve missing module imports for coordinator-api and blockchain-rpc

Coordinator API (port 8011):
- Install aitbc-agent-core package from local source
- Fix agent_core_adapters import path in agent_integration_factory.py
- Wrap hermes_enhanced router imports in try/except in routers/__init__.py

Blockchain RPC (port 8006):
- Rename models.py to base_models.py to allow models/ package
- Create models/__init__.py re-exporting from base_models
- Create models/dispute.py with all dispute Pydantic models
- Fix disputes.py import path for dispute_resolution_service
- Update database.py and sync.py to import from base_models
- Wrap disputes, contracts, islands, bridge, staking imports in try/except in router.py
- Add None checks in endpoint handlers for unavailable modules
This commit is contained in:
aitbc
2026-05-25 17:22:38 +02:00
parent 214c1b65ec
commit e28a192a76
9 changed files with 243 additions and 78 deletions

View File

@@ -12,7 +12,7 @@ from sqlalchemy import event
from .config import settings
# Import all models to ensure they are registered with SQLModel.metadata
from .models import Block, Transaction, Account, Receipt, Escrow # noqa: F401
from .base_models import Block, Transaction, Account, Receipt, Escrow # noqa: F401
# Database encryption key (in production, this should come from HSM or secure key storage)
_DB_ENCRYPTION_KEY = os.environ.get("AITBC_DB_KEY", "default_encryption_key_change_in_production")

View File

@@ -0,0 +1,4 @@
"""Blockchain chain models package."""
# Re-export all models from base_models.py (the original models.py renamed)
# This package also contains sub-modules like dispute.py
from ..base_models import * # noqa: F403, E402

View File

@@ -0,0 +1,89 @@
"""Dispute-related Pydantic models for RPC endpoints."""
from typing import Any, Dict, List, Optional
from pydantic import BaseModel, Field
from datetime import datetime
class FileDisputeRequest(BaseModel):
agreement_id: int
respondent: str
dispute_type: str
reason: str
evidence_hash: str
class FileDisputeResponse(BaseModel):
dispute_id: int
status: str
timestamp: str
class SubmitEvidenceRequest(BaseModel):
dispute_id: int
evidence_hash: str
evidence_type: str
description: str
class SubmitEvidenceResponse(BaseModel):
evidence_id: int
status: str
class VerifyEvidenceRequest(BaseModel):
dispute_id: int
evidence_id: int
verified: bool
class VerifyEvidenceResponse(BaseModel):
status: str
class SubmitArbitrationVoteRequest(BaseModel):
dispute_id: int
vote: str # "plaintiff" or "defendant"
reasoning: str
class SubmitArbitrationVoteResponse(BaseModel):
status: str
vote_id: int
class AuthorizeArbitratorRequest(BaseModel):
arbitrator_address: str
authorized: bool
class AuthorizeArbitratorResponse(BaseModel):
status: str
class GetDisputeResponse(BaseModel):
dispute_id: int
agreement_id: int
plaintiff: str
respondent: str
dispute_type: str
reason: str
status: str
created_at: str
evidence: List[Dict[str, Any]] = []
votes: List[Dict[str, Any]] = []
class GetEvidenceResponse(BaseModel):
evidence_id: int
dispute_id: int
evidence_hash: str
evidence_type: str
description: str
submitted_by: str
verified: bool
created_at: str
class GetArbitrationVotesResponse(BaseModel):
dispute_id: int
votes: List[Dict[str, Any]] = []

View File

@@ -12,7 +12,7 @@ from .auth import get_authenticated_address
_logger = get_logger(__name__)
# Import dispute resolution service and models
from ..services.dispute_resolution import dispute_resolution_service
from ..rpc.dispute_resolution_service import dispute_resolution_service
from ..models.dispute import (
FileDisputeRequest,
FileDisputeResponse,

View File

@@ -31,6 +31,8 @@ from .utils import (
from aitbc.rate_limiting import rate_limit
_logger = get_logger(__name__)
# Import domain modules
from .blocks import (
get_genesis_allocations,
@@ -55,6 +57,7 @@ from .accounts import (
get_balance_breakdown,
reconcile_balance,
)
try:
from .disputes import (
file_dispute,
submit_evidence,
@@ -69,6 +72,9 @@ from .disputes import (
get_dispute_evidence,
get_arbitration_votes,
)
except ImportError:
_logger.warning("Disputes module not available")
try:
from ..models.dispute import (
FileDisputeRequest,
FileDisputeResponse,
@@ -84,6 +90,9 @@ from ..models.dispute import (
GetEvidenceResponse,
GetArbitrationVotesResponse,
)
except ImportError:
_logger.warning("Dispute models not available")
try:
from .contracts import (
deploy_messaging_contract,
list_contracts,
@@ -100,6 +109,8 @@ from .contracts import (
get_agent_reputation,
moderate_message,
)
except ImportError:
_logger.warning("Contracts module not available")
from .sync import (
export_chain,
import_chain,
@@ -110,6 +121,7 @@ from .gossip import (
GetLogsRequest,
GetLogsResponse,
)
try:
from .islands import (
join_island,
leave_island,
@@ -123,19 +135,43 @@ from .islands import (
BridgeRequestRequest,
BridgeRequestResponse,
)
except ImportError:
_logger.warning("Islands module not available")
join_island = None
leave_island = None
list_islands = None
get_island = None
request_bridge = None
JoinIslandRequest = None
JoinIslandResponse = None
LeaveIslandRequest = None
LeaveIslandResponse = None
BridgeRequestRequest = None
BridgeRequestResponse = None
try:
from .bridge import (
bridge_lock,
bridge_confirm,
get_bridge_transfer,
list_pending_transfers,
)
except ImportError:
_logger.warning("Bridge module not available")
bridge_lock = None
bridge_confirm = None
get_bridge_transfer = None
list_pending_transfers = None
try:
from .staking import (
stake_tokens,
unstake_tokens,
get_staking_info,
)
_logger = get_logger(__name__)
except ImportError:
_logger.warning("Staking module not available")
stake_tokens = None
unstake_tokens = None
get_staking_info = None
# Security scheme for authentication
security = HTTPBearer(auto_error=False)
@@ -588,12 +624,16 @@ async def get_logs_route(
@router.post("/islands/join", summary="Join an island")
async def join_island_route(request: JoinIslandRequest) -> JoinIslandResponse:
"""Join an island for edge compute operations"""
if join_island is None:
raise HTTPException(status_code=501, detail="Islands module not available")
return await join_island(request)
@router.post("/islands/leave", summary="Leave an island")
async def leave_island_route(request: LeaveIslandRequest) -> LeaveIslandResponse:
"""Leave an island"""
if leave_island is None:
raise HTTPException(status_code=501, detail="Islands module not available")
return await leave_island(request)
@@ -601,6 +641,8 @@ async def leave_island_route(request: LeaveIslandRequest) -> LeaveIslandResponse
@rate_limit(rate=100, per=60)
async def list_islands_route() -> Dict[str, Any]:
"""List all islands that the node is a member of"""
if list_islands is None:
raise HTTPException(status_code=501, detail="Islands module not available")
return await list_islands()
@@ -608,12 +650,16 @@ async def list_islands_route() -> Dict[str, Any]:
@rate_limit(rate=100, per=60)
async def get_island_route(island_id: str) -> Dict[str, Any]:
"""Get details about a specific island"""
if get_island is None:
raise HTTPException(status_code=501, detail="Islands module not available")
return await get_island(island_id)
@router.post("/islands/bridge", summary="Request a bridge to another island")
async def request_bridge_route(request: BridgeRequestRequest) -> BridgeRequestResponse:
"""Request a bridge to another island for cross-island communication"""
if request_bridge is None:
raise HTTPException(status_code=501, detail="Islands module not available")
return await request_bridge(request)
@@ -628,6 +674,8 @@ async def bridge_lock_route(
lock_data: dict
) -> Dict[str, Any]:
"""Initiate a cross-chain bridge transfer by locking funds"""
if bridge_lock is None:
raise HTTPException(status_code=501, detail="Bridge module not available")
return await bridge_lock(request, lock_data)
@@ -638,6 +686,8 @@ async def bridge_confirm_route(
confirm_data: dict
) -> Dict[str, Any]:
"""Confirm a cross-chain bridge transfer and release funds"""
if bridge_confirm is None:
raise HTTPException(status_code=501, detail="Bridge module not available")
return await bridge_confirm(request, confirm_data)
@@ -648,6 +698,8 @@ async def get_bridge_transfer_route(
transfer_id: str
) -> Dict[str, Any]:
"""Get the status of a cross-chain transfer"""
if get_bridge_transfer is None:
raise HTTPException(status_code=501, detail="Bridge module not available")
return await get_bridge_transfer(request, transfer_id)
@@ -658,6 +710,8 @@ async def list_pending_transfers_route(
chain_id: str = None
) -> List[Dict[str, Any]]:
"""List all pending cross-chain transfers"""
if list_pending_transfers is None:
raise HTTPException(status_code=501, detail="Bridge module not available")
return await list_pending_transfers(request, chain_id)
@@ -672,6 +726,8 @@ async def stake_tokens_route(
stake_data: dict
) -> Dict[str, Any]:
"""Stake tokens for consensus participation"""
if stake_tokens is None:
raise HTTPException(status_code=501, detail="Staking module not available")
return await stake_tokens(request, stake_data)
@@ -682,6 +738,8 @@ async def unstake_tokens_route(
unstake_data: dict
) -> Dict[str, Any]:
"""Unstake tokens after lock period expires"""
if unstake_tokens is None:
raise HTTPException(status_code=501, detail="Staking module not available")
return await unstake_tokens(request, unstake_data)
@@ -693,4 +751,6 @@ async def get_staking_info_route(
chain_id: str = None
) -> Dict[str, Any]:
"""Get staking information for an address"""
if get_staking_info is None:
raise HTTPException(status_code=501, detail="Staking module not available")
return await get_staking_info(request, address, chain_id)

View File

@@ -16,7 +16,7 @@ from sqlmodel import Session, select
from .config import settings
from .metrics import metrics_registry
from .models import Block, Transaction as ChainTransaction, Account
from .base_models import Block, Transaction as ChainTransaction, Account
from .logger import get_logger
from .state.merkle_patricia_trie import StateManager
from .state.state_transition import get_state_transition

View File

@@ -80,9 +80,21 @@ except ImportError:
logger.warning("Trading router not available")
# Hermes routers moved to contexts/hermes
try:
from ..contexts.hermes.routers.hermes_enhanced import router as hermes_enhanced
except ImportError:
hermes_enhanced = None # type: ignore[assignment]
logger.warning("Hermes enhanced router not available")
try:
from ..contexts.hermes.routers.hermes_enhanced_simple import router as hermes_enhanced_simple
except ImportError:
hermes_enhanced_simple = None # type: ignore[assignment]
logger.warning("Hermes enhanced simple router not available")
try:
from ..contexts.hermes.routers.hermes_enhanced_health import router as hermes_enhanced_health
except ImportError:
hermes_enhanced_health = None # type: ignore[assignment]
logger.warning("Hermes enhanced health router not available")
from .hermes import router as hermes
# Security router moved to contexts/security

View File

@@ -6,7 +6,7 @@ This enables gradual migration from duplicated code to shared implementation.
from sqlmodel import Session
from aitbc_agent_core import AgentIntegrationService
from .adapters.agent_core_adapters import (
from ..adapters.agent_core_adapters import (
AgentSecurityManagerAdapter,
AgentAuditorAdapter,
AgentOrchestratorAdapter,