156 lines
4.8 KiB
Python
156 lines
4.8 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
# -*- coding: utf-8 -*-
|
|||
|
|
"""
|
|||
|
|
聊天 WebSocket 路由
|
|||
|
|
处理前端与 OpenClaw Gateway 之间的消息转发
|
|||
|
|
作者:小白 🐶
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
from flask import request, session
|
|||
|
|
from flask_login import current_user
|
|||
|
|
from flask_socketio import emit, join_room, leave_room
|
|||
|
|
import json
|
|||
|
|
import time
|
|||
|
|
|
|||
|
|
from .openclaw_connector import gateway_manager
|
|||
|
|
|
|||
|
|
# Gateway 配置(从环境变量或配置文件读取)
|
|||
|
|
GATEWAYS = {
|
|||
|
|
"local": {
|
|||
|
|
"url": "ws://127.0.0.1:18888",
|
|||
|
|
"token": "ae4d5989ba173a01cc721200614a8a8a8226724b46d5af13a65089aa628c32b9"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
def init_gateways():
|
|||
|
|
"""初始化 Gateway 连接"""
|
|||
|
|
for name, config in GATEWAYS.items():
|
|||
|
|
connector = gateway_manager.add_gateway(
|
|||
|
|
name,
|
|||
|
|
config["url"],
|
|||
|
|
config["token"]
|
|||
|
|
)
|
|||
|
|
# 设置消息回调
|
|||
|
|
connector.message_callback = handle_gateway_response
|
|||
|
|
gateway_manager.connect_all()
|
|||
|
|
print(f"[Chat] Initialized {len(GATEWAYS)} gateway(s)")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def handle_gateway_response(gateway_name: str, data: dict):
|
|||
|
|
"""处理 Gateway 响应并转发给前端"""
|
|||
|
|
from app import socketio
|
|||
|
|
|
|||
|
|
# 获取用户房间
|
|||
|
|
user_id = data.get("params", {}).get("userId", "anonymous")
|
|||
|
|
room = f"user_{user_id}"
|
|||
|
|
|
|||
|
|
# 转发给前端
|
|||
|
|
socketio.emit('agent_response', {
|
|||
|
|
'gateway': gateway_name,
|
|||
|
|
'data': data,
|
|||
|
|
'timestamp': int(time.time() * 1000)
|
|||
|
|
}, room=room, namespace='/chat')
|
|||
|
|
|
|||
|
|
print(f"[Chat] Forwarded response to {room}")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def register_socket_handlers(socketio):
|
|||
|
|
"""注册 Socket.IO 事件处理器"""
|
|||
|
|
|
|||
|
|
@socketio.on('connect', namespace='/chat')
|
|||
|
|
def handle_connect():
|
|||
|
|
"""用户连接"""
|
|||
|
|
if not current_user.is_authenticated:
|
|||
|
|
print("[Chat] Unauthorized connection attempt")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
user_id = current_user.id
|
|||
|
|
room = f"user_{user_id}"
|
|||
|
|
join_room(room)
|
|||
|
|
|
|||
|
|
# 返回 Gateway 列表和状态
|
|||
|
|
emit('connected', {
|
|||
|
|
'gateways': gateway_manager.list_gateways(),
|
|||
|
|
'status': gateway_manager.get_status(),
|
|||
|
|
'userId': user_id
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
print(f"[Chat] User {current_user.username} connected, room: {room}")
|
|||
|
|
|
|||
|
|
|
|||
|
|
@socketio.on('disconnect', namespace='/chat')
|
|||
|
|
def handle_disconnect():
|
|||
|
|
"""用户断开连接"""
|
|||
|
|
if current_user.is_authenticated:
|
|||
|
|
room = f"user_{current_user.id}"
|
|||
|
|
leave_room(room)
|
|||
|
|
print(f"[Chat] User {current_user.username} disconnected")
|
|||
|
|
|
|||
|
|
|
|||
|
|
@socketio.on('send_message', namespace='/chat')
|
|||
|
|
def handle_message(data):
|
|||
|
|
"""处理用户消息"""
|
|||
|
|
if not current_user.is_authenticated:
|
|||
|
|
emit('error', {'message': '未授权'})
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
gateway_name = data.get('gateway', 'local')
|
|||
|
|
message = data.get('message', '').strip()
|
|||
|
|
|
|||
|
|
if not message:
|
|||
|
|
emit('error', {'message': '消息不能为空'})
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
connector = gateway_manager.get_gateway(gateway_name)
|
|||
|
|
|
|||
|
|
if connector and connector.connected:
|
|||
|
|
# 构造会话 key
|
|||
|
|
session_key = f"webchat:user_{current_user.id}"
|
|||
|
|
|
|||
|
|
# 发送到 Gateway
|
|||
|
|
success = connector.send_message(message, session_key)
|
|||
|
|
|
|||
|
|
if success:
|
|||
|
|
# 确认收到
|
|||
|
|
emit('message_sent', {
|
|||
|
|
'gateway': gateway_name,
|
|||
|
|
'message': message,
|
|||
|
|
'timestamp': int(time.time() * 1000)
|
|||
|
|
})
|
|||
|
|
print(f"[Chat] User {current_user.username} sent message to {gateway_name}")
|
|||
|
|
else:
|
|||
|
|
emit('error', {'message': f'发送失败:Gateway {gateway_name} 连接异常'})
|
|||
|
|
else:
|
|||
|
|
emit('error', {'message': f'Gateway {gateway_name} 未连接'})
|
|||
|
|
|
|||
|
|
|
|||
|
|
@socketio.on('switch_gateway', namespace='/chat')
|
|||
|
|
def handle_switch(data):
|
|||
|
|
"""切换 Gateway"""
|
|||
|
|
if not current_user.is_authenticated:
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
gateway_name = data.get('gateway')
|
|||
|
|
connector = gateway_manager.get_gateway(gateway_name)
|
|||
|
|
|
|||
|
|
if connector:
|
|||
|
|
emit('gateway_changed', {
|
|||
|
|
'gateway': gateway_name,
|
|||
|
|
'connected': connector.connected,
|
|||
|
|
'status': gateway_manager.get_status()
|
|||
|
|
})
|
|||
|
|
print(f"[Chat] User {current_user.username} switched to {gateway_name}")
|
|||
|
|
else:
|
|||
|
|
emit('error', {'message': f'Gateway {gateway_name} 不存在'})
|
|||
|
|
|
|||
|
|
|
|||
|
|
@socketio.on('get_status', namespace='/chat')
|
|||
|
|
def handle_get_status():
|
|||
|
|
"""获取 Gateway 状态"""
|
|||
|
|
emit('status_update', {
|
|||
|
|
'status': gateway_manager.get_status()
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
print("[Chat] Socket handlers registered")
|