fix: resolve CI failures across all workflows
All checks were successful
API Endpoint Tests / test-api-endpoints (push) Successful in 39s
Integration Tests / test-service-integration (push) Successful in 44s
Package Tests / test-python-packages (map[name:aitbc-core path:packages/py/aitbc-core]) (push) Successful in 16s
Package Tests / test-python-packages (map[name:aitbc-agent-sdk path:packages/py/aitbc-agent-sdk]) (push) Successful in 30s
Package Tests / test-python-packages (map[name:aitbc-crypto path:packages/py/aitbc-crypto]) (push) Successful in 20s
Package Tests / test-python-packages (map[name:aitbc-sdk path:packages/py/aitbc-sdk]) (push) Successful in 20s
Package Tests / test-javascript-packages (map[name:aitbc-sdk-js path:packages/js/aitbc-sdk]) (push) Successful in 17s
Package Tests / test-javascript-packages (map[name:aitbc-token path:packages/solidity/aitbc-token]) (push) Successful in 1m17s
Python Tests / test-python (push) Successful in 1m7s
Smart Contract Tests / test-solidity (map[name:aitbc-token path:packages/solidity/aitbc-token]) (push) Successful in 30s
Security Scanning / security-scan (push) Successful in 1m5s
Smart Contract Tests / test-solidity (map[name:zk-circuits path:apps/zk-circuits]) (push) Successful in 49s
Smart Contract Tests / lint-solidity (push) Successful in 54s

aitbc-agent-sdk (package-tests.yml):
- Add AITBCAgent convenience class matching test expectations
- Fix test_agent_sdk.py: was importing nonexistent AITBCAgent, now tests
  the real API (Agent.create, AgentCapabilities, to_dict) plus AITBCAgent
- Fix 3 remaining mypy errors: supported_models Optional coercion (line 64),
  missing return types on _submit_to_marketplace/_update_marketplace_offer
- Run black on all 5 src files — zero mypy errors, zero black warnings
- All 6 tests pass

python-tests.yml:
- Add pynacl to pip install (aitbc-crypto and aitbc-sdk import nacl)
- Add pynacl>=1.5.0 to root requirements.txt

Service readiness (api-endpoint-tests.yml, integration-tests.yml):
- Replace curl -sf with curl http_code check — -sf fails on 404 responses
  but port 8006 (blockchain RPC) returns 404 on / while being healthy
- Blockchain RPC uses REST /rpc/* endpoints, not JSON-RPC POST to /
  Fix test_api_endpoints.py to test /health, /rpc/head, /rpc/info, /rpc/supply
- Remove dead test_rpc() function, add blockchain RPC to perf tests
- All 4 services now pass: coordinator, exchange, wallet, blockchain_rpc
- Integration-tests: check is-active before systemctl start to avoid
  spurious warnings for already-running services

Hardhat compile (smart-contract-tests.yml, package-tests.yml):
- Relax engines field from >=24.14.0 to >=18.0.0 (CI has v24.13.0)
- Remove 2>/dev/null from hardhat compile/test so errors are visible
- Remove 2>/dev/null from npm run build/test in package-tests JS section
This commit is contained in:
aitbc1
2026-03-29 13:20:58 +02:00
parent af34f6ae81
commit 8b8d639bf7
15 changed files with 432 additions and 307 deletions

View File

@@ -16,123 +16,123 @@ from cryptography.hazmat.primitives.asymmetric import padding
logger = logging.getLogger(__name__)
@dataclass
class AgentCapabilities:
"""Agent capability specification"""
compute_type: str # "inference", "training", "processing"
gpu_memory: Optional[int] = None
supported_models: Optional[List[str]] = None
performance_score: float = 0.0
max_concurrent_jobs: int = 1
specialization: Optional[str] = None
def __post_init__(self) -> None:
if self.supported_models is None:
self.supported_models = []
@dataclass
class AgentIdentity:
"""Agent identity and cryptographic keys"""
id: str
name: str
address: str
public_key: str
private_key: str
def sign_message(self, message: Dict[str, Any]) -> str:
"""Sign a message with agent's private key"""
message_str = json.dumps(message, sort_keys=True)
private_key = serialization.load_pem_private_key(
self.private_key.encode(),
password=None
self.private_key.encode(), password=None
)
if not isinstance(private_key, rsa.RSAPrivateKey):
raise TypeError("Only RSA private keys are supported")
signature = private_key.sign(
message_str.encode(),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
hashes.SHA256(),
)
return signature.hex()
def verify_signature(self, message: Dict[str, Any], signature: str) -> bool:
"""Verify a message signature"""
message_str = json.dumps(message, sort_keys=True)
public_key = serialization.load_pem_public_key(
self.public_key.encode()
)
public_key = serialization.load_pem_public_key(self.public_key.encode())
if not isinstance(public_key, rsa.RSAPublicKey):
raise TypeError("Only RSA public keys are supported")
try:
public_key.verify(
bytes.fromhex(signature),
message_str.encode(),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
salt_length=padding.PSS.MAX_LENGTH,
),
hashes.SHA256()
hashes.SHA256(),
)
return True
except Exception:
return False
class Agent:
"""Core AITBC Agent class"""
def __init__(self, identity: AgentIdentity, capabilities: AgentCapabilities):
self.identity = identity
self.capabilities = capabilities
self.registered = False
self.reputation_score = 0.0
self.earnings = 0.0
@classmethod
def create(cls, name: str, agent_type: str, capabilities: Dict[str, Any]) -> 'Agent':
def create(
cls, name: str, agent_type: str, capabilities: Dict[str, Any]
) -> "Agent":
"""Create a new agent with generated identity"""
# Generate cryptographic keys
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()
private_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
encryption_algorithm=serialization.NoEncryption(),
)
public_pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
format=serialization.PublicFormat.SubjectPublicKeyInfo,
)
# Generate agent identity
agent_id = f"agent_{uuid.uuid4().hex[:8]}"
address = f"0x{uuid.uuid4().hex[:40]}"
identity = AgentIdentity(
id=agent_id,
name=name,
address=address,
public_key=public_pem.decode(),
private_key=private_pem.decode()
private_key=private_pem.decode(),
)
# Create capabilities object
agent_capabilities = AgentCapabilities(**capabilities)
return cls(identity, agent_capabilities)
async def register(self) -> bool:
"""Register the agent on the AITBC network"""
try:
@@ -147,27 +147,27 @@ class Agent:
"supported_models": self.capabilities.supported_models,
"performance_score": self.capabilities.performance_score,
"max_concurrent_jobs": self.capabilities.max_concurrent_jobs,
"specialization": self.capabilities.specialization
"specialization": self.capabilities.specialization,
},
"timestamp": datetime.utcnow().isoformat()
"timestamp": datetime.utcnow().isoformat(),
}
# Sign registration data
signature = self.identity.sign_message(registration_data)
registration_data["signature"] = signature
# TODO: Submit to AITBC network registration endpoint
# For now, simulate successful registration
await asyncio.sleep(1) # Simulate network call
self.registered = True
logger.info(f"Agent {self.identity.id} registered successfully")
return True
except Exception as e:
logger.error(f"Registration failed: {e}")
return False
async def get_reputation(self) -> Dict[str, float]:
"""Get agent reputation metrics"""
# TODO: Fetch from reputation system
@@ -175,14 +175,14 @@ class Agent:
"overall_score": self.reputation_score,
"job_success_rate": 0.95,
"avg_response_time": 30.5,
"client_satisfaction": 4.7
"client_satisfaction": 4.7,
}
async def update_reputation(self, new_score: float) -> None:
"""Update agent reputation score"""
self.reputation_score = new_score
logger.info(f"Reputation updated to {new_score}")
async def get_earnings(self, period: str = "30d") -> Dict[str, Any]:
"""Get agent earnings information"""
# TODO: Fetch from blockchain/payment system
@@ -190,38 +190,42 @@ class Agent:
"total": self.earnings,
"daily_average": self.earnings / 30,
"period": period,
"currency": "AITBC"
"currency": "AITBC",
}
async def send_message(self, recipient_id: str, message_type: str, payload: Dict[str, Any]) -> bool:
async def send_message(
self, recipient_id: str, message_type: str, payload: Dict[str, Any]
) -> bool:
"""Send a message to another agent"""
message = {
"from": self.identity.id,
"to": recipient_id,
"type": message_type,
"payload": payload,
"timestamp": datetime.utcnow().isoformat()
"timestamp": datetime.utcnow().isoformat(),
}
# Sign message
signature = self.identity.sign_message(message)
message["signature"] = signature
# TODO: Send through AITBC agent messaging protocol
logger.info(f"Message sent to {recipient_id}: {message_type}")
return True
async def receive_message(self, message: Dict[str, Any]) -> bool:
"""Process a received message from another agent"""
# Verify signature
if "signature" not in message:
return False
# TODO: Verify sender's signature
# For now, just process the message
logger.info(f"Received message from {message.get('from')}: {message.get('type')}")
logger.info(
f"Received message from {message.get('from')}: {message.get('type')}"
)
return True
def to_dict(self) -> Dict[str, Any]:
"""Convert agent to dictionary representation"""
return {
@@ -234,9 +238,48 @@ class Agent:
"supported_models": self.capabilities.supported_models,
"performance_score": self.capabilities.performance_score,
"max_concurrent_jobs": self.capabilities.max_concurrent_jobs,
"specialization": self.capabilities.specialization
"specialization": self.capabilities.specialization,
},
"reputation_score": self.reputation_score,
"registered": self.registered,
"earnings": self.earnings
"earnings": self.earnings,
}
class AITBCAgent:
"""High-level convenience wrapper for creating AITBC agents.
Provides a simple keyword-argument constructor suitable for quick
prototyping and testing without manually building AgentIdentity /
AgentCapabilities objects.
"""
def __init__(
self,
agent_id: str = "",
compute_type: str = "general",
capabilities: Optional[List[str]] = None,
**kwargs: Any,
) -> None:
self.agent_id = agent_id
self.compute_type = compute_type
self.capabilities: List[str] = capabilities or []
self.status = "initialized"
self._extra = kwargs
# Build a backing Agent for crypto / network operations
self._agent = Agent.create(
name=agent_id,
agent_type=compute_type,
capabilities={"compute_type": compute_type},
)
# Delegate common Agent methods
async def register(self) -> bool:
return await self._agent.register()
def to_dict(self) -> Dict[str, Any]:
d = self._agent.to_dict()
d["agent_id"] = self.agent_id
d["status"] = self.status
return d