feat(coordinator-api): integrate dynamic pricing engine with GPU marketplace and add agent identity router

- Add DynamicPricingEngine and MarketDataCollector dependencies to GPU marketplace endpoints
- Implement dynamic pricing calculation for GPU registration with market_balance strategy
- Calculate real-time dynamic prices at booking time with confidence scores and pricing factors
- Enhance /marketplace/pricing/{model} endpoint with comprehensive dynamic pricing analysis
  - Add static vs dynamic price
This commit is contained in:
oib
2026-02-28 22:57:10 +01:00
parent 85ae21a568
commit 0e6c9eda72
83 changed files with 30189 additions and 134 deletions

View File

@@ -0,0 +1,478 @@
"""
Cross-Chain Reputation Aggregator
Aggregates reputation data from multiple blockchains and normalizes scores
"""
import asyncio
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any, Set
from uuid import uuid4
import json
from aitbc.logging import get_logger
from sqlmodel import Session, select, update, delete, func
from sqlalchemy.exc import SQLAlchemyError
from ..domain.reputation import AgentReputation, ReputationEvent
from ..domain.cross_chain_reputation import (
CrossChainReputationAggregation, CrossChainReputationEvent,
CrossChainReputationConfig, ReputationMetrics
)
logger = get_logger(__name__)
class CrossChainReputationAggregator:
"""Aggregates reputation data from multiple blockchains"""
def __init__(self, session: Session, blockchain_clients: Optional[Dict[int, Any]] = None):
self.session = session
self.blockchain_clients = blockchain_clients or {}
async def collect_chain_reputation_data(self, chain_id: int) -> List[Dict[str, Any]]:
"""Collect reputation data from a specific blockchain"""
try:
# Get all reputations for the chain
stmt = select(AgentReputation).where(
AgentReputation.chain_id == chain_id if hasattr(AgentReputation, 'chain_id') else True
)
# Handle case where reputation doesn't have chain_id
if not hasattr(AgentReputation, 'chain_id'):
# For now, return all reputations (assume they're on the primary chain)
stmt = select(AgentReputation)
reputations = self.session.exec(stmt).all()
chain_data = []
for reputation in reputations:
chain_data.append({
'agent_id': reputation.agent_id,
'trust_score': reputation.trust_score,
'reputation_level': reputation.reputation_level,
'total_transactions': getattr(reputation, 'transaction_count', 0),
'success_rate': getattr(reputation, 'success_rate', 0.0),
'dispute_count': getattr(reputation, 'dispute_count', 0),
'last_updated': reputation.updated_at,
'chain_id': getattr(reputation, 'chain_id', chain_id)
})
return chain_data
except Exception as e:
logger.error(f"Error collecting reputation data for chain {chain_id}: {e}")
return []
async def normalize_reputation_scores(self, scores: Dict[int, float]) -> float:
"""Normalize reputation scores across chains"""
try:
if not scores:
return 0.0
# Get chain configurations
chain_configs = {}
for chain_id in scores.keys():
config = await self._get_chain_config(chain_id)
chain_configs[chain_id] = config
# Apply chain-specific normalization
normalized_scores = {}
total_weight = 0.0
weighted_sum = 0.0
for chain_id, score in scores.items():
config = chain_configs.get(chain_id)
if config and config.is_active:
# Apply chain weight
weight = config.chain_weight
normalized_score = score * weight
normalized_scores[chain_id] = normalized_score
total_weight += weight
weighted_sum += normalized_score
# Calculate final normalized score
if total_weight > 0:
final_score = weighted_sum / total_weight
else:
# If no valid configurations, use simple average
final_score = sum(scores.values()) / len(scores)
return max(0.0, min(1.0, final_score))
except Exception as e:
logger.error(f"Error normalizing reputation scores: {e}")
return 0.0
async def apply_chain_weighting(self, scores: Dict[int, float]) -> Dict[int, float]:
"""Apply chain-specific weighting to reputation scores"""
try:
weighted_scores = {}
for chain_id, score in scores.items():
config = await self._get_chain_config(chain_id)
if config and config.is_active:
weight = config.chain_weight
weighted_scores[chain_id] = score * weight
else:
# Default weight if no config
weighted_scores[chain_id] = score
return weighted_scores
except Exception as e:
logger.error(f"Error applying chain weighting: {e}")
return scores
async def detect_reputation_anomalies(self, agent_id: str) -> List[Dict[str, Any]]:
"""Detect reputation anomalies across chains"""
try:
anomalies = []
# Get cross-chain aggregation
stmt = select(CrossChainReputationAggregation).where(
CrossChainReputationAggregation.agent_id == agent_id
)
aggregation = self.session.exec(stmt).first()
if not aggregation:
return anomalies
# Check for consistency anomalies
if aggregation.consistency_score < 0.7:
anomalies.append({
'agent_id': agent_id,
'anomaly_type': 'low_consistency',
'detected_at': datetime.utcnow(),
'description': f"Low consistency score: {aggregation.consistency_score:.2f}",
'severity': 'high' if aggregation.consistency_score < 0.5 else 'medium',
'consistency_score': aggregation.consistency_score,
'score_variance': aggregation.score_variance,
'score_range': aggregation.score_range
})
# Check for score variance anomalies
if aggregation.score_variance > 0.25:
anomalies.append({
'agent_id': agent_id,
'anomaly_type': 'high_variance',
'detected_at': datetime.utcnow(),
'description': f"High score variance: {aggregation.score_variance:.2f}",
'severity': 'high' if aggregation.score_variance > 0.5 else 'medium',
'score_variance': aggregation.score_variance,
'score_range': aggregation.score_range,
'chain_scores': aggregation.chain_scores
})
# Check for missing chain data
expected_chains = await self._get_active_chain_ids()
missing_chains = set(expected_chains) - set(aggregation.active_chains)
if missing_chains:
anomalies.append({
'agent_id': agent_id,
'anomaly_type': 'missing_chain_data',
'detected_at': datetime.utcnow(),
'description': f"Missing data for chains: {list(missing_chains)}",
'severity': 'medium',
'missing_chains': list(missing_chains),
'active_chains': aggregation.active_chains
})
return anomalies
except Exception as e:
logger.error(f"Error detecting reputation anomalies for agent {agent_id}: {e}")
return []
async def batch_update_reputations(self, updates: List[Dict[str, Any]]) -> Dict[str, bool]:
"""Batch update reputation scores for multiple agents"""
try:
results = {}
for update in updates:
agent_id = update['agent_id']
chain_id = update.get('chain_id', 1)
new_score = update['score']
try:
# Get existing reputation
stmt = select(AgentReputation).where(
AgentReputation.agent_id == agent_id,
AgentReputation.chain_id == chain_id if hasattr(AgentReputation, 'chain_id') else True
)
if not hasattr(AgentReputation, 'chain_id'):
stmt = select(AgentReputation).where(AgentReputation.agent_id == agent_id)
reputation = self.session.exec(stmt).first()
if reputation:
# Update reputation
reputation.trust_score = new_score * 1000 # Convert to 0-1000 scale
reputation.reputation_level = self._determine_reputation_level(new_score)
reputation.updated_at = datetime.utcnow()
# Create event record
event = ReputationEvent(
agent_id=agent_id,
event_type='batch_update',
impact_score=new_score - (reputation.trust_score / 1000.0),
trust_score_before=reputation.trust_score,
trust_score_after=reputation.trust_score,
event_data=update,
occurred_at=datetime.utcnow()
)
self.session.add(event)
results[agent_id] = True
else:
# Create new reputation
reputation = AgentReputation(
agent_id=agent_id,
trust_score=new_score * 1000,
reputation_level=self._determine_reputation_level(new_score),
created_at=datetime.utcnow(),
updated_at=datetime.utcnow()
)
self.session.add(reputation)
results[agent_id] = True
except Exception as e:
logger.error(f"Error updating reputation for agent {agent_id}: {e}")
results[agent_id] = False
self.session.commit()
# Update cross-chain aggregations
for agent_id in updates:
if results.get(agent_id):
await self._update_cross_chain_aggregation(agent_id)
return results
except Exception as e:
logger.error(f"Error in batch reputation update: {e}")
return {update['agent_id']: False for update in updates}
async def get_chain_statistics(self, chain_id: int) -> Dict[str, Any]:
"""Get reputation statistics for a specific chain"""
try:
# Get all reputations for the chain
stmt = select(AgentReputation).where(
AgentReputation.chain_id == chain_id if hasattr(AgentReputation, 'chain_id') else True
)
if not hasattr(AgentReputation, 'chain_id'):
# For now, get all reputations
stmt = select(AgentReputation)
reputations = self.session.exec(stmt).all()
if not reputations:
return {
'chain_id': chain_id,
'total_agents': 0,
'average_reputation': 0.0,
'reputation_distribution': {},
'total_transactions': 0,
'success_rate': 0.0
}
# Calculate statistics
total_agents = len(reputations)
total_reputation = sum(rep.trust_score for rep in reputations)
average_reputation = total_reputation / total_agents / 1000.0 # Convert to 0-1 scale
# Reputation distribution
distribution = {}
for reputation in reputations:
level = reputation.reputation_level.value
distribution[level] = distribution.get(level, 0) + 1
# Transaction statistics
total_transactions = sum(getattr(rep, 'transaction_count', 0) for rep in reputations)
successful_transactions = sum(
getattr(rep, 'transaction_count', 0) * getattr(rep, 'success_rate', 0) / 100.0
for rep in reputations
)
success_rate = successful_transactions / max(total_transactions, 1)
return {
'chain_id': chain_id,
'total_agents': total_agents,
'average_reputation': average_reputation,
'reputation_distribution': distribution,
'total_transactions': total_transactions,
'success_rate': success_rate,
'last_updated': datetime.utcnow()
}
except Exception as e:
logger.error(f"Error getting chain statistics for chain {chain_id}: {e}")
return {
'chain_id': chain_id,
'error': str(e),
'total_agents': 0,
'average_reputation': 0.0
}
async def sync_cross_chain_reputations(self, agent_ids: List[str]) -> Dict[str, bool]:
"""Synchronize reputation data across chains for multiple agents"""
try:
results = {}
for agent_id in agent_ids:
try:
# Re-aggregate cross-chain reputation
await self._update_cross_chain_aggregation(agent_id)
results[agent_id] = True
except Exception as e:
logger.error(f"Error syncing cross-chain reputation for agent {agent_id}: {e}")
results[agent_id] = False
return results
except Exception as e:
logger.error(f"Error in cross-chain reputation sync: {e}")
return {agent_id: False for agent_id in agent_ids}
async def _get_chain_config(self, chain_id: int) -> Optional[CrossChainReputationConfig]:
"""Get configuration for a specific chain"""
stmt = select(CrossChainReputationConfig).where(
CrossChainReputationConfig.chain_id == chain_id,
CrossChainReputationConfig.is_active == True
)
config = self.session.exec(stmt).first()
if not config:
# Create default config
config = CrossChainReputationConfig(
chain_id=chain_id,
chain_weight=1.0,
base_reputation_bonus=0.0,
transaction_success_weight=0.1,
transaction_failure_weight=-0.2,
dispute_penalty_weight=-0.3,
minimum_transactions_for_score=5,
reputation_decay_rate=0.01,
anomaly_detection_threshold=0.3
)
self.session.add(config)
self.session.commit()
return config
async def _get_active_chain_ids(self) -> List[int]:
"""Get list of active chain IDs"""
try:
stmt = select(CrossChainReputationConfig.chain_id).where(
CrossChainReputationConfig.is_active == True
)
configs = self.session.exec(stmt).all()
return [config.chain_id for config in configs]
except Exception as e:
logger.error(f"Error getting active chain IDs: {e}")
return [1] # Default to Ethereum mainnet
async def _update_cross_chain_aggregation(self, agent_id: str) -> None:
"""Update cross-chain aggregation for an agent"""
try:
# Get all reputations for the agent
stmt = select(AgentReputation).where(AgentReputation.agent_id == agent_id)
reputations = self.session.exec(stmt).all()
if not reputations:
return
# Extract chain scores
chain_scores = {}
for reputation in reputations:
chain_id = getattr(reputation, 'chain_id', 1)
chain_scores[chain_id] = reputation.trust_score / 1000.0 # Convert to 0-1 scale
# Apply weighting
weighted_scores = await self.apply_chain_weighting(chain_scores)
# Calculate aggregation metrics
if chain_scores:
avg_score = sum(chain_scores.values()) / len(chain_scores)
variance = sum((score - avg_score) ** 2 for score in chain_scores.values()) / len(chain_scores)
score_range = max(chain_scores.values()) - min(chain_scores.values())
consistency_score = max(0.0, 1.0 - (variance / 0.25))
else:
avg_score = 0.0
variance = 0.0
score_range = 0.0
consistency_score = 1.0
# Update or create aggregation
stmt = select(CrossChainReputationAggregation).where(
CrossChainReputationAggregation.agent_id == agent_id
)
aggregation = self.session.exec(stmt).first()
if aggregation:
aggregation.aggregated_score = avg_score
aggregation.chain_scores = chain_scores
aggregation.active_chains = list(chain_scores.keys())
aggregation.score_variance = variance
aggregation.score_range = score_range
aggregation.consistency_score = consistency_score
aggregation.last_updated = datetime.utcnow()
else:
aggregation = CrossChainReputationAggregation(
agent_id=agent_id,
aggregated_score=avg_score,
chain_scores=chain_scores,
active_chains=list(chain_scores.keys()),
score_variance=variance,
score_range=score_range,
consistency_score=consistency_score,
verification_status="pending",
created_at=datetime.utcnow(),
last_updated=datetime.utcnow()
)
self.session.add(aggregation)
self.session.commit()
except Exception as e:
logger.error(f"Error updating cross-chain aggregation for agent {agent_id}: {e}")
def _determine_reputation_level(self, score: float) -> str:
"""Determine reputation level based on score"""
# Map to existing reputation levels
if score >= 0.9:
return "master"
elif score >= 0.8:
return "expert"
elif score >= 0.6:
return "advanced"
elif score >= 0.4:
return "intermediate"
elif score >= 0.2:
return "beginner"
else:
return "beginner"

View File

@@ -0,0 +1,476 @@
"""
Cross-Chain Reputation Engine
Core reputation calculation and aggregation engine for multi-chain agent reputation
"""
import asyncio
import math
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any, Tuple
from uuid import uuid4
import json
from aitbc.logging import get_logger
from sqlmodel import Session, select, update, delete, func
from sqlalchemy.exc import SQLAlchemyError
from ..domain.reputation import AgentReputation, ReputationEvent, ReputationLevel
from ..domain.cross_chain_reputation import (
CrossChainReputationAggregation, CrossChainReputationEvent,
CrossChainReputationConfig, ReputationMetrics
)
logger = get_logger(__name__)
class CrossChainReputationEngine:
"""Core reputation calculation and aggregation engine"""
def __init__(self, session: Session):
self.session = session
async def calculate_reputation_score(
self,
agent_id: str,
chain_id: int,
transaction_data: Optional[Dict[str, Any]] = None
) -> float:
"""Calculate reputation score for an agent on a specific chain"""
try:
# Get existing reputation
stmt = select(AgentReputation).where(
AgentReputation.agent_id == agent_id,
AgentReputation.chain_id == chain_id if hasattr(AgentReputation, 'chain_id') else True
)
# Handle case where existing reputation doesn't have chain_id
if not hasattr(AgentReputation, 'chain_id'):
stmt = select(AgentReputation).where(AgentReputation.agent_id == agent_id)
reputation = self.session.exec(stmt).first()
if reputation:
# Update existing reputation based on transaction data
score = await self._update_reputation_from_transaction(reputation, transaction_data)
else:
# Create new reputation with base score
config = await self._get_chain_config(chain_id)
base_score = config.base_reputation_bonus if config else 0.0
score = max(0.0, min(1.0, base_score))
# Create new reputation record
new_reputation = AgentReputation(
agent_id=agent_id,
trust_score=score * 1000, # Convert to 0-1000 scale
reputation_level=self._determine_reputation_level(score),
created_at=datetime.utcnow(),
updated_at=datetime.utcnow()
)
self.session.add(new_reputation)
self.session.commit()
return score
except Exception as e:
logger.error(f"Error calculating reputation for agent {agent_id} on chain {chain_id}: {e}")
return 0.0
async def aggregate_cross_chain_reputation(self, agent_id: str) -> Dict[int, float]:
"""Aggregate reputation scores across all chains for an agent"""
try:
# Get all reputation records for the agent
stmt = select(AgentReputation).where(AgentReputation.agent_id == agent_id)
reputations = self.session.exec(stmt).all()
if not reputations:
return {}
# Get chain configurations
chain_configs = {}
for reputation in reputations:
chain_id = getattr(reputation, 'chain_id', 1) # Default to chain 1 if not set
config = await self._get_chain_config(chain_id)
chain_configs[chain_id] = config
# Calculate weighted scores
chain_scores = {}
total_weight = 0.0
weighted_sum = 0.0
for reputation in reputations:
chain_id = getattr(reputation, 'chain_id', 1)
config = chain_configs.get(chain_id)
if config and config.is_active:
# Convert trust score to 0-1 scale
score = min(1.0, reputation.trust_score / 1000.0)
weight = config.chain_weight
chain_scores[chain_id] = score
total_weight += weight
weighted_sum += score * weight
# Normalize scores
if total_weight > 0:
normalized_scores = {
chain_id: score * (total_weight / len(chain_scores))
for chain_id, score in chain_scores.items()
}
else:
normalized_scores = chain_scores
# Store aggregation
await self._store_cross_chain_aggregation(agent_id, chain_scores, normalized_scores)
return chain_scores
except Exception as e:
logger.error(f"Error aggregating cross-chain reputation for agent {agent_id}: {e}")
return {}
async def update_reputation_from_event(self, event_data: Dict[str, Any]) -> bool:
"""Update reputation from a reputation-affecting event"""
try:
agent_id = event_data['agent_id']
chain_id = event_data.get('chain_id', 1)
event_type = event_data['event_type']
impact_score = event_data['impact_score']
# Get existing reputation
stmt = select(AgentReputation).where(
AgentReputation.agent_id == agent_id,
AgentReputation.chain_id == chain_id if hasattr(AgentReputation, 'chain_id') else True
)
if not hasattr(AgentReputation, 'chain_id'):
stmt = select(AgentReputation).where(AgentReputation.agent_id == agent_id)
reputation = self.session.exec(stmt).first()
if not reputation:
# Create new reputation record
config = await self._get_chain_config(chain_id)
base_score = config.base_reputation_bonus if config else 0.0
reputation = AgentReputation(
agent_id=agent_id,
trust_score=max(0, min(1000, (base_score + impact_score) * 1000)),
reputation_level=self._determine_reputation_level(base_score + impact_score),
created_at=datetime.utcnow(),
updated_at=datetime.utcnow()
)
self.session.add(reputation)
else:
# Update existing reputation
old_score = reputation.trust_score / 1000.0
new_score = max(0.0, min(1.0, old_score + impact_score))
reputation.trust_score = new_score * 1000
reputation.reputation_level = self._determine_reputation_level(new_score)
reputation.updated_at = datetime.utcnow()
# Create reputation event record
event = ReputationEvent(
agent_id=agent_id,
event_type=event_type,
impact_score=impact_score,
trust_score_before=reputation.trust_score - (impact_score * 1000),
trust_score_after=reputation.trust_score,
event_data=event_data,
occurred_at=datetime.utcnow()
)
self.session.add(event)
self.session.commit()
# Update cross-chain aggregation
await self.aggregate_cross_chain_reputation(agent_id)
logger.info(f"Updated reputation for agent {agent_id} from {event_type} event")
return True
except Exception as e:
logger.error(f"Error updating reputation from event: {e}")
return False
async def get_reputation_trend(self, agent_id: str, days: int = 30) -> List[float]:
"""Get reputation trend for an agent over specified days"""
try:
# Get reputation events for the period
cutoff_date = datetime.utcnow() - timedelta(days=days)
stmt = select(ReputationEvent).where(
ReputationEvent.agent_id == agent_id,
ReputationEvent.occurred_at >= cutoff_date
).order_by(ReputationEvent.occurred_at)
events = self.session.exec(stmt).all()
# Extract scores from events
scores = []
for event in events:
if event.trust_score_after is not None:
scores.append(event.trust_score_after / 1000.0) # Convert to 0-1 scale
return scores
except Exception as e:
logger.error(f"Error getting reputation trend for agent {agent_id}: {e}")
return []
async def detect_reputation_anomalies(self, agent_id: str) -> List[Dict[str, Any]]:
"""Detect reputation anomalies for an agent"""
try:
anomalies = []
# Get recent reputation events
stmt = select(ReputationEvent).where(
ReputationEvent.agent_id == agent_id
).order_by(ReputationEvent.occurred_at.desc()).limit(10)
events = self.session.exec(stmt).all()
if len(events) < 2:
return anomalies
# Check for sudden score changes
for i in range(len(events) - 1):
current_event = events[i]
previous_event = events[i + 1]
if current_event.trust_score_after and previous_event.trust_score_after:
score_change = abs(current_event.trust_score_after - previous_event.trust_score_after) / 1000.0
if score_change > 0.3: # 30% change threshold
anomalies.append({
'agent_id': agent_id,
'chain_id': getattr(current_event, 'chain_id', 1),
'anomaly_type': 'sudden_score_change',
'detected_at': current_event.occurred_at,
'description': f"Sudden reputation change of {score_change:.2f}",
'severity': 'high' if score_change > 0.5 else 'medium',
'previous_score': previous_event.trust_score_after / 1000.0,
'current_score': current_event.trust_score_after / 1000.0,
'score_change': score_change,
'confidence': min(1.0, score_change / 0.3)
})
return anomalies
except Exception as e:
logger.error(f"Error detecting reputation anomalies for agent {agent_id}: {e}")
return []
async def _update_reputation_from_transaction(
self,
reputation: AgentReputation,
transaction_data: Optional[Dict[str, Any]]
) -> float:
"""Update reputation based on transaction data"""
if not transaction_data:
return reputation.trust_score / 1000.0
# Extract transaction metrics
success = transaction_data.get('success', True)
gas_efficiency = transaction_data.get('gas_efficiency', 0.5)
response_time = transaction_data.get('response_time', 1.0)
# Calculate impact based on transaction outcome
config = await self._get_chain_config(getattr(reputation, 'chain_id', 1))
if success:
impact = config.transaction_success_weight if config else 0.1
impact *= gas_efficiency # Bonus for gas efficiency
impact *= (2.0 - min(response_time, 2.0)) # Bonus for fast response
else:
impact = config.transaction_failure_weight if config else -0.2
# Update reputation
old_score = reputation.trust_score / 1000.0
new_score = max(0.0, min(1.0, old_score + impact))
reputation.trust_score = new_score * 1000
reputation.reputation_level = self._determine_reputation_level(new_score)
reputation.updated_at = datetime.utcnow()
# Update transaction metrics if available
if 'transaction_count' in transaction_data:
reputation.transaction_count = transaction_data['transaction_count']
self.session.commit()
return new_score
async def _get_chain_config(self, chain_id: int) -> Optional[CrossChainReputationConfig]:
"""Get configuration for a specific chain"""
stmt = select(CrossChainReputationConfig).where(
CrossChainReputationConfig.chain_id == chain_id,
CrossChainReputationConfig.is_active == True
)
config = self.session.exec(stmt).first()
if not config:
# Create default config
config = CrossChainReputationConfig(
chain_id=chain_id,
chain_weight=1.0,
base_reputation_bonus=0.0,
transaction_success_weight=0.1,
transaction_failure_weight=-0.2,
dispute_penalty_weight=-0.3,
minimum_transactions_for_score=5,
reputation_decay_rate=0.01,
anomaly_detection_threshold=0.3
)
self.session.add(config)
self.session.commit()
return config
async def _store_cross_chain_aggregation(
self,
agent_id: str,
chain_scores: Dict[int, float],
normalized_scores: Dict[int, float]
) -> None:
"""Store cross-chain reputation aggregation"""
try:
# Calculate aggregation metrics
if chain_scores:
avg_score = sum(chain_scores.values()) / len(chain_scores)
variance = sum((score - avg_score) ** 2 for score in chain_scores.values()) / len(chain_scores)
score_range = max(chain_scores.values()) - min(chain_scores.values())
consistency_score = max(0.0, 1.0 - (variance / 0.25)) # Normalize variance
else:
avg_score = 0.0
variance = 0.0
score_range = 0.0
consistency_score = 1.0
# Check if aggregation already exists
stmt = select(CrossChainReputationAggregation).where(
CrossChainReputationAggregation.agent_id == agent_id
)
aggregation = self.session.exec(stmt).first()
if aggregation:
# Update existing aggregation
aggregation.aggregated_score = avg_score
aggregation.chain_scores = chain_scores
aggregation.active_chains = list(chain_scores.keys())
aggregation.score_variance = variance
aggregation.score_range = score_range
aggregation.consistency_score = consistency_score
aggregation.last_updated = datetime.utcnow()
else:
# Create new aggregation
aggregation = CrossChainReputationAggregation(
agent_id=agent_id,
aggregated_score=avg_score,
chain_scores=chain_scores,
active_chains=list(chain_scores.keys()),
score_variance=variance,
score_range=score_range,
consistency_score=consistency_score,
verification_status="pending",
created_at=datetime.utcnow(),
last_updated=datetime.utcnow()
)
self.session.add(aggregation)
self.session.commit()
except Exception as e:
logger.error(f"Error storing cross-chain aggregation for agent {agent_id}: {e}")
def _determine_reputation_level(self, score: float) -> ReputationLevel:
"""Determine reputation level based on score"""
if score >= 0.9:
return ReputationLevel.MASTER
elif score >= 0.8:
return ReputationLevel.EXPERT
elif score >= 0.6:
return ReputationLevel.ADVANCED
elif score >= 0.4:
return ReputationLevel.INTERMEDIATE
elif score >= 0.2:
return ReputationLevel.BEGINNER
else:
return ReputationLevel.BEGINNER # Map to existing levels
async def get_agent_reputation_summary(self, agent_id: str) -> Dict[str, Any]:
"""Get comprehensive reputation summary for an agent"""
try:
# Get basic reputation
stmt = select(AgentReputation).where(AgentReputation.agent_id == agent_id)
reputation = self.session.exec(stmt).first()
if not reputation:
return {
'agent_id': agent_id,
'trust_score': 0.0,
'reputation_level': ReputationLevel.BEGINNER,
'total_transactions': 0,
'success_rate': 0.0,
'cross_chain': {
'aggregated_score': 0.0,
'chain_count': 0,
'active_chains': [],
'consistency_score': 1.0
}
}
# Get cross-chain aggregation
stmt = select(CrossChainReputationAggregation).where(
CrossChainReputationAggregation.agent_id == agent_id
)
aggregation = self.session.exec(stmt).first()
# Get reputation trend
trend = await self.get_reputation_trend(agent_id, 30)
# Get anomalies
anomalies = await self.detect_reputation_anomalies(agent_id)
return {
'agent_id': agent_id,
'trust_score': reputation.trust_score,
'reputation_level': reputation.reputation_level,
'performance_rating': getattr(reputation, 'performance_rating', 3.0),
'reliability_score': getattr(reputation, 'reliability_score', 50.0),
'total_transactions': getattr(reputation, 'transaction_count', 0),
'success_rate': getattr(reputation, 'success_rate', 0.0),
'dispute_count': getattr(reputation, 'dispute_count', 0),
'last_activity': getattr(reputation, 'last_activity', datetime.utcnow()),
'cross_chain': {
'aggregated_score': aggregation.aggregated_score if aggregation else 0.0,
'chain_count': aggregation.chain_count if aggregation else 0,
'active_chains': aggregation.active_chains if aggregation else [],
'consistency_score': aggregation.consistency_score if aggregation else 1.0,
'chain_scores': aggregation.chain_scores if aggregation else {}
},
'trend': trend,
'anomalies': anomalies,
'created_at': reputation.created_at,
'updated_at': reputation.updated_at
}
except Exception as e:
logger.error(f"Error getting reputation summary for agent {agent_id}: {e}")
return {'agent_id': agent_id, 'error': str(e)}