Major WHOOSH system refactoring and feature enhancements

- Migrated from HIVE branding to WHOOSH across all components
- Enhanced backend API with new services: AI models, BZZZ integration, templates, members
- Added comprehensive testing suite with security, performance, and integration tests
- Improved frontend with new components for project setup, AI models, and team management
- Updated MCP server implementation with WHOOSH-specific tools and resources
- Enhanced deployment configurations with production-ready Docker setups
- Added comprehensive documentation and setup guides
- Implemented age encryption service and UCXL integration

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-08-27 08:34:48 +10:00
parent 0e9844ef13
commit 268214d971
399 changed files with 57390 additions and 2045 deletions

View File

@@ -0,0 +1,266 @@
#!/usr/bin/env python3
"""
BZZZ Integration API for WHOOSH
API endpoints for team collaboration, decision publishing, and consensus mechanisms
"""
from fastapi import APIRouter, HTTPException, Depends, Query
from typing import Dict, List, Optional, Any
from pydantic import BaseModel, Field
from datetime import datetime
from ..services.bzzz_integration_service import bzzz_service, AgentRole
from ..core.auth_deps import get_current_user
from ..models.user import User
router = APIRouter(prefix="/api/bzzz", tags=["BZZZ Integration"])
# Pydantic models for API requests/responses
class DecisionRequest(BaseModel):
title: str = Field(..., description="Decision title")
description: str = Field(..., description="Detailed decision description")
context: Dict[str, Any] = Field(default_factory=dict, description="Decision context data")
ucxl_address: Optional[str] = Field(None, description="Related UCXL address")
class DecisionResponse(BaseModel):
decision_id: str
title: str
description: str
author_role: str
timestamp: datetime
ucxl_address: Optional[str] = None
class TaskAssignmentRequest(BaseModel):
task_description: str = Field(..., description="Task description")
required_capabilities: List[str] = Field(..., description="Required capabilities")
priority: str = Field("medium", description="Task priority (low, medium, high, urgent)")
class TaskAssignmentResponse(BaseModel):
decision_id: Optional[str]
assigned_to: str
assignment_score: float
alternatives: List[Dict[str, Any]]
class TeamMemberInfo(BaseModel):
agent_id: str
role: str
endpoint: str
capabilities: List[str]
status: str
class TeamStatusResponse(BaseModel):
total_members: int
online_members: int
offline_members: int
role_distribution: Dict[str, int]
active_decisions: int
recent_decisions: List[Dict[str, Any]]
network_health: float
class ConsensusResponse(BaseModel):
decision_id: str
total_votes: int
approvals: int
approval_rate: float
consensus_reached: bool
details: Dict[str, Any]
@router.get("/status", response_model=TeamStatusResponse)
async def get_team_status(
current_user: User = Depends(get_current_user)
) -> TeamStatusResponse:
"""Get current BZZZ team status and network health"""
try:
status = await bzzz_service.get_team_status()
return TeamStatusResponse(**status)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to get team status: {str(e)}")
@router.get("/members", response_model=List[TeamMemberInfo])
async def get_team_members(
current_user: User = Depends(get_current_user)
) -> List[TeamMemberInfo]:
"""Get list of active team members in BZZZ network"""
try:
members = []
for member in bzzz_service.team_members.values():
members.append(TeamMemberInfo(
agent_id=member.agent_id,
role=member.role.value,
endpoint=member.endpoint,
capabilities=member.capabilities,
status=member.status
))
return members
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to get team members: {str(e)}")
@router.post("/decisions", response_model=Dict[str, str])
async def publish_decision(
decision: DecisionRequest,
current_user: User = Depends(get_current_user)
) -> Dict[str, str]:
"""
Publish a decision to the BZZZ network for team consensus
"""
try:
decision_id = await bzzz_service.publish_decision(
title=decision.title,
description=decision.description,
context=decision.context,
ucxl_address=decision.ucxl_address
)
if decision_id:
return {"decision_id": decision_id, "status": "published"}
else:
raise HTTPException(status_code=500, detail="Failed to publish decision")
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to publish decision: {str(e)}")
@router.get("/decisions", response_model=List[DecisionResponse])
async def get_recent_decisions(
limit: int = Query(10, ge=1, le=100),
current_user: User = Depends(get_current_user)
) -> List[DecisionResponse]:
"""Get recent decisions from BZZZ network"""
try:
decisions = sorted(
bzzz_service.active_decisions.values(),
key=lambda d: d.timestamp,
reverse=True
)[:limit]
return [
DecisionResponse(
decision_id=decision.id,
title=decision.title,
description=decision.description,
author_role=decision.author_role,
timestamp=decision.timestamp,
ucxl_address=decision.ucxl_address
)
for decision in decisions
]
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to get decisions: {str(e)}")
@router.get("/decisions/{decision_id}/consensus", response_model=Optional[ConsensusResponse])
async def get_decision_consensus(
decision_id: str,
current_user: User = Depends(get_current_user)
) -> Optional[ConsensusResponse]:
"""Get consensus status for a specific decision"""
try:
consensus = await bzzz_service.get_team_consensus(decision_id)
if consensus:
return ConsensusResponse(**consensus)
else:
raise HTTPException(status_code=404, detail="Decision not found or no consensus data available")
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to get consensus: {str(e)}")
@router.post("/tasks/assign", response_model=TaskAssignmentResponse)
async def coordinate_task_assignment(
task: TaskAssignmentRequest,
current_user: User = Depends(get_current_user)
) -> TaskAssignmentResponse:
"""
Coordinate task assignment across team members based on capabilities and availability
"""
try:
assignment = await bzzz_service.coordinate_task_assignment(
task_description=task.task_description,
required_capabilities=task.required_capabilities,
priority=task.priority
)
if assignment:
return TaskAssignmentResponse(**assignment)
else:
raise HTTPException(status_code=404, detail="No suitable team members found for task")
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to coordinate task assignment: {str(e)}")
@router.post("/network/discover")
async def rediscover_network(
current_user: User = Depends(get_current_user)
) -> Dict[str, Any]:
"""Manually trigger team member discovery"""
try:
await bzzz_service._discover_team_members()
return {
"status": "success",
"members_discovered": len(bzzz_service.team_members),
"timestamp": datetime.utcnow().isoformat()
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to rediscover network: {str(e)}")
@router.get("/roles", response_model=List[str])
async def get_available_roles() -> List[str]:
"""Get list of available agent roles in BZZZ system"""
return [role.value for role in AgentRole]
@router.get("/capabilities/{agent_id}", response_model=Dict[str, Any])
async def get_agent_capabilities(
agent_id: str,
current_user: User = Depends(get_current_user)
) -> Dict[str, Any]:
"""Get detailed capabilities of a specific team member"""
try:
if agent_id not in bzzz_service.team_members:
raise HTTPException(status_code=404, detail=f"Agent {agent_id} not found")
member = bzzz_service.team_members[agent_id]
return {
"agent_id": member.agent_id,
"role": member.role.value,
"capabilities": member.capabilities,
"status": member.status,
"endpoint": member.endpoint,
"last_seen": datetime.utcnow().isoformat() # Placeholder
}
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to get agent capabilities: {str(e)}")
@router.get("/health")
async def bzzz_health_check() -> Dict[str, Any]:
"""BZZZ integration health check endpoint"""
try:
total_members = len(bzzz_service.team_members)
online_members = sum(1 for m in bzzz_service.team_members.values() if m.status == "online")
health_status = "healthy" if online_members >= total_members * 0.5 else "degraded"
if online_members == 0:
health_status = "offline"
return {
"status": health_status,
"bzzz_endpoints": len(bzzz_service.bzzz_endpoints),
"team_members": total_members,
"online_members": online_members,
"active_decisions": len(bzzz_service.active_decisions),
"timestamp": datetime.utcnow().isoformat()
}
except Exception as e:
return {
"status": "error",
"error": str(e),
"timestamp": datetime.utcnow().isoformat()
}
# Note: Exception handlers are registered at the app level, not router level