119 lines
4.0 KiB
Python
119 lines
4.0 KiB
Python
|
|
from rest_framework import serializers, status, views
|
|||
|
|
from rest_framework.response import Response
|
|||
|
|
from rest_framework.decorators import api_view
|
|||
|
|
from .models import Instance, MeetingInstanceMap
|
|||
|
|
from .webhook import register_instance, join_meeting
|
|||
|
|
import logging
|
|||
|
|
|
|||
|
|
logger = logging.getLogger(__name__)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class InstanceRegisterSerializer(serializers.Serializer):
|
|||
|
|
instance_id = serializers.CharField(max_length=100)
|
|||
|
|
instance_name = serializers.CharField(max_length=200)
|
|||
|
|
agent_ids = serializers.ListField(child=serializers.CharField())
|
|||
|
|
webhook_url = serializers.URLField()
|
|||
|
|
|
|||
|
|
|
|||
|
|
class InstanceRegisterView(views.APIView):
|
|||
|
|
"""
|
|||
|
|
实例注册接口
|
|||
|
|
|
|||
|
|
POST /api/v1/instances/register/
|
|||
|
|
{
|
|||
|
|
"instance_id": "phospher-openclaw",
|
|||
|
|
"instance_name": "飞行侠的 OpenClaw",
|
|||
|
|
"agent_ids": ["flying_hero", "lobster_monitor"],
|
|||
|
|
"webhook_url": "http://192.168.1.100:8888/meeting-notify"
|
|||
|
|
}
|
|||
|
|
"""
|
|||
|
|
def post(self, request):
|
|||
|
|
serializer = InstanceRegisterSerializer(data=request.data)
|
|||
|
|
if not serializer.is_valid():
|
|||
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
instance = register_instance(
|
|||
|
|
instance_id=serializer.validated_data['instance_id'],
|
|||
|
|
instance_name=serializer.validated_data['instance_name'],
|
|||
|
|
agent_ids=serializer.validated_data['agent_ids'],
|
|||
|
|
webhook_url=serializer.validated_data['webhook_url']
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
return Response({
|
|||
|
|
'status': 'success',
|
|||
|
|
'instance_id': str(instance.id),
|
|||
|
|
'message': f'实例 {instance.instance_name} 注册成功'
|
|||
|
|
})
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"注册失败:{e}")
|
|||
|
|
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class MeetingJoinSerializer(serializers.Serializer):
|
|||
|
|
instance_id = serializers.CharField(max_length=100)
|
|||
|
|
meeting_id = serializers.UUIDField()
|
|||
|
|
agent_ids = serializers.ListField(child=serializers.CharField())
|
|||
|
|
|
|||
|
|
|
|||
|
|
class MeetingJoinView(views.APIView):
|
|||
|
|
"""
|
|||
|
|
实例加入会议
|
|||
|
|
|
|||
|
|
POST /api/v1/instances/join-meeting/
|
|||
|
|
{
|
|||
|
|
"instance_id": "phospher-openclaw",
|
|||
|
|
"meeting_id": "xxx-xxx-xxx",
|
|||
|
|
"agent_ids": ["flying_hero"]
|
|||
|
|
}
|
|||
|
|
"""
|
|||
|
|
def post(self, request):
|
|||
|
|
serializer = MeetingJoinSerializer(data=request.data)
|
|||
|
|
if not serializer.is_valid():
|
|||
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
join_meeting(
|
|||
|
|
instance_id=serializer.validated_data['instance_id'],
|
|||
|
|
meeting_id=serializer.validated_data['meeting_id'],
|
|||
|
|
agent_ids=serializer.validated_data['agent_ids']
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
return Response({'status': 'success', 'message': '已加入会议'})
|
|||
|
|
except Instance.DoesNotExist:
|
|||
|
|
return Response({'error': '实例不存在'}, status=status.HTTP_404_NOT_FOUND)
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"加入会议失败:{e}")
|
|||
|
|
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class InstanceListView(views.APIView):
|
|||
|
|
"""
|
|||
|
|
获取实例列表
|
|||
|
|
|
|||
|
|
GET /api/v1/instances/
|
|||
|
|
"""
|
|||
|
|
def get(self, request):
|
|||
|
|
instances = Instance.objects.filter(is_active=True)
|
|||
|
|
data = [{
|
|||
|
|
'id': str(i.id),
|
|||
|
|
'instance_id': i.instance_id,
|
|||
|
|
'instance_name': i.instance_name,
|
|||
|
|
'agent_ids': i.agent_ids,
|
|||
|
|
'webhook_url': i.webhook_url,
|
|||
|
|
'last_heartbeat': i.last_heartbeat.isoformat() if i.last_heartbeat else None
|
|||
|
|
} for i in instances]
|
|||
|
|
|
|||
|
|
return Response(data)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class WebhookNotifyView(views.APIView):
|
|||
|
|
"""
|
|||
|
|
Webhook 通知接收(测试用)
|
|||
|
|
|
|||
|
|
POST /api/v1/instances/webhook-test/
|
|||
|
|
"""
|
|||
|
|
def post(self, request):
|
|||
|
|
logger.info(f"📬 收到 Webhook 通知:{request.data}")
|
|||
|
|
return Response({'status': 'received'})
|