From db5378c7e8895fc88e077af68f0e46383f1493ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E7=99=BD?= Date: Sat, 14 Mar 2026 06:12:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=81=8A=E5=A4=A9?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 OpenClaw Gateway 连接器 (api/openclaw_connector.py) - 新增聊天 WebSocket 路由 (api/chat.py) - 新增聊天界面模板 (templates/chat/index.html) - 新增聊天样式 (static/css/chat.css) - 修改 app.py 支持 SocketIO - 登录后默认跳转到聊天界面 作者:小白 🐶 --- api/chat.py | 155 ++++++++++++++ api/openclaw_connector.py | 167 ++++++++++++++++ app.py | 29 ++- static/css/chat.css | 389 ++++++++++++++++++++++++++++++++++++ static/openclaw_report.docx | Bin 0 -> 40641 bytes templates/chat/index.html | 321 +++++++++++++++++++++++++++++ 6 files changed, 1058 insertions(+), 3 deletions(-) create mode 100644 api/chat.py create mode 100644 api/openclaw_connector.py create mode 100644 static/css/chat.css create mode 100644 static/openclaw_report.docx create mode 100644 templates/chat/index.html diff --git a/api/chat.py b/api/chat.py new file mode 100644 index 0000000..d13aa23 --- /dev/null +++ b/api/chat.py @@ -0,0 +1,155 @@ +#!/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") diff --git a/api/openclaw_connector.py b/api/openclaw_connector.py new file mode 100644 index 0000000..0fd6fcb --- /dev/null +++ b/api/openclaw_connector.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +OpenClaw Gateway 连接器 +用于连接多个 OpenClaw 实例并转发消息 +作者:小白 🐶 +""" + +import websocket +import json +import threading +import time +from typing import Dict, Optional, Callable, Any + + +class OpenClawConnector: + """OpenClaw Gateway 连接器""" + + def __init__(self, gateway_url: str, token: str, name: str = "default"): + self.gateway_url = gateway_url + self.token = token + self.name = name + self.ws: Optional[websocket.WebSocketApp] = None + self.connected = False + self.message_callback: Optional[Callable[[str, dict], None]] = None + self._reconnect_delay = 1 + self._max_reconnect_delay = 30 + self._should_reconnect = True + + def connect(self): + """连接到 OpenClaw Gateway""" + if not self.gateway_url or not self.token: + print(f"[Connector:{self.name}] Missing gateway_url or token") + return + + url = f"{self.gateway_url}?token={self.token}" + print(f"[Connector:{self.name}] Connecting to {self.gateway_url}...") + + try: + self.ws = websocket.WebSocketApp( + url, + on_open=self._on_open, + on_message=self._on_message, + on_error=self._on_error, + on_close=self._on_close + ) + + # 启动后台线程 + thread = threading.Thread(target=self._run_forever, daemon=True) + thread.start() + except Exception as e: + print(f"[Connector:{self.name}] Connection error: {e}") + + def _run_forever(self): + """后台运行 WebSocket""" + while self._should_reconnect: + try: + self.ws.run_forever() + except Exception as e: + print(f"[Connector:{self.name}] WebSocket error: {e}") + + # 重连逻辑 + if self._should_reconnect: + print(f"[Connector:{self.name}] Reconnecting in {self._reconnect_delay}s...") + time.sleep(self._reconnect_delay) + self._reconnect_delay = min(self._reconnect_delay * 2, self._max_reconnect_delay) + + def _on_open(self, ws): + self.connected = True + self._reconnect_delay = 1 + print(f"[Connector:{self.name}] ✅ Connected") + + def _on_message(self, ws, message): + """收到 Gateway 消息""" + try: + data = json.loads(message) + print(f"[Connector:{self.name}] Received: {data.get('method', 'unknown')}") + if self.message_callback: + self.message_callback(self.name, data) + except json.JSONDecodeError: + print(f"[Connector:{self.name}] Invalid JSON: {message[:100]}") + + def _on_error(self, ws, error): + print(f"[Connector:{self.name}] Error: {error}") + + def _on_close(self, ws, close_status_code, close_msg): + self.connected = False + print(f"[Connector:{self.name}] Disconnected: {close_status_code} {close_msg}") + + def send_message(self, message: str, session_key: str = None) -> bool: + """发送消息到 Gateway""" + if not self.connected or not self.ws: + print(f"[Connector:{self.name}] Not connected") + return False + + payload = { + "method": "agent.turn", + "id": str(int(time.time() * 1000)), + "params": { + "message": message, + "sessionKey": session_key or f"webchat:{self.name}", + "deliver": False # 不直接发送,等待响应 + } + } + + try: + self.ws.send(json.dumps(payload)) + print(f"[Connector:{self.name}] Sent message: {message[:50]}...") + return True + except Exception as e: + print(f"[Connector:{self.name}] Send error: {e}") + return False + + def disconnect(self): + """断开连接""" + self._should_reconnect = False + if self.ws: + self.ws.close() + + +class MultiGatewayManager: + """多 Gateway 连接管理器""" + + def __init__(self): + self.gateways: Dict[str, OpenClawConnector] = {} + self._lock = threading.Lock() + + def add_gateway(self, name: str, url: str, token: str) -> OpenClawConnector: + """添加 Gateway 连接""" + with self._lock: + if name in self.gateways: + self.gateways[name].disconnect() + + connector = OpenClawConnector(url, token, name) + self.gateways[name] = connector + return connector + + def connect_all(self): + """连接所有 Gateway""" + for connector in self.gateways.values(): + connector.connect() + + def get_gateway(self, name: str) -> Optional[OpenClawConnector]: + return self.gateways.get(name) + + def list_gateways(self) -> list: + return list(self.gateways.keys()) + + def get_status(self) -> Dict[str, Any]: + """获取所有 Gateway 状态""" + return { + name: { + "connected": connector.connected, + "url": connector.gateway_url + } + for name, connector in self.gateways.items() + } + + def disconnect_all(self): + """断开所有连接""" + for connector in self.gateways.values(): + connector.disconnect() + self.gateways.clear() + + +# 全局单例 +gateway_manager = MultiGatewayManager() diff --git a/app.py b/app.py index aa05c0d..4bae17e 100644 --- a/app.py +++ b/app.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- """ OpenClaw Mission Control - Flask 版本 -支持登录、注册、控制中心功能 +支持登录、注册、控制中心、聊天功能 作者:小白 🐶 """ from flask import Flask, render_template, redirect, url_for, request, flash, make_response from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user from flask_sqlalchemy import SQLAlchemy +from flask_socketio import SocketIO from werkzeug.security import generate_password_hash, check_password_hash import os @@ -18,6 +19,9 @@ app.config['SECRET_KEY'] = 'xiaobai-secret-key-2026' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +# 初始化 SocketIO +socketio = SocketIO(app, cors_allowed_origins="*", async_mode='threading') + # 禁用缓存 - 解决浏览器缓存问题 @app.after_request def add_no_cache_headers(response): @@ -40,6 +44,9 @@ login_manager.login_view = 'login' from api import api app.register_blueprint(api) +# 注册聊天 Socket Handlers +from api.chat import register_socket_handlers, init_gateways + # 用户模型 class User(UserMixin, db.Model): @@ -63,10 +70,17 @@ def load_user(user_id): @app.route('/') def index(): if current_user.is_authenticated: - return redirect(url_for('dashboard')) + return redirect(url_for('chat')) return render_template('index.html') +# 路由 - 聊天界面 +@app.route('/chat') +@login_required +def chat(): + return render_template('chat/index.html', username=current_user.username) + + # 路由 - 控制中心仪表盘 @app.route('/dashboard') @login_required @@ -166,4 +180,13 @@ with app.app_context(): if __name__ == '__main__': - app.run(host='0.0.0.0', port=5000, debug=False) + # 注册 Socket.IO 事件处理器 + register_socket_handlers(socketio) + + # 初始化 Gateway 连接 + init_gateways() + + # 启动应用(使用 SocketIO) + print("🚀 启动 OpenClaw Mission Control...") + print("📍 访问地址: http://0.0.0.0:5000") + socketio.run(app, host='0.0.0.0', port=5000, debug=False, allow_unsafe_werkzeug=True) diff --git a/static/css/chat.css b/static/css/chat.css new file mode 100644 index 0000000..9202573 --- /dev/null +++ b/static/css/chat.css @@ -0,0 +1,389 @@ +/* 聊天界面样式 + * 作者:小白 🐶 + */ + +/* 基础样式重置 */ +.chat-body { + margin: 0; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; +} + +/* 主容器 */ +.chat-container { + max-width: 900px; + margin: 0 auto; + height: 100vh; + display: flex; + flex-direction: column; + background: #fff; + box-shadow: 0 0 40px rgba(0, 0, 0, 0.1); +} + +/* 顶部导航栏 */ +.chat-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 12px 20px; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); +} + +.header-left { + display: flex; + align-items: center; + gap: 15px; +} + +.logo { + font-size: 20px; + font-weight: 600; +} + +.gateway-selector { + padding: 6px 12px; + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 6px; + background: rgba(255, 255, 255, 0.1); + color: white; + font-size: 14px; + cursor: pointer; +} + +.gateway-selector option { + background: #333; + color: white; +} + +.header-right { + display: flex; + align-items: center; + gap: 15px; +} + +.status-badge { + padding: 4px 10px; + border-radius: 12px; + font-size: 12px; + font-weight: 500; +} + +.status-badge.connecting { + background: #ffc107; + color: #333; +} + +.status-badge.connected { + background: #28a745; + color: white; +} + +.status-badge.disconnected { + background: #dc3545; + color: white; +} + +.user-info { + font-size: 14px; + opacity: 0.9; +} + +.logout-btn { + color: white; + text-decoration: none; + font-size: 14px; + opacity: 0.8; + transition: opacity 0.2s; +} + +.logout-btn:hover { + opacity: 1; +} + +/* 消息列表区域 */ +.message-list { + flex: 1; + overflow-y: auto; + padding: 20px; + background: #f5f7fb; +} + +/* 欢迎消息 */ +.welcome-message { + display: flex; + align-items: center; + gap: 15px; + padding: 30px; + background: white; + border-radius: 12px; + margin-bottom: 20px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.welcome-avatar { + font-size: 48px; +} + +.welcome-text h3 { + margin: 0 0 8px 0; + color: #333; +} + +.welcome-text p { + margin: 0; + color: #666; +} + +/* 消息气泡 */ +.message { + display: flex; + gap: 10px; + margin-bottom: 16px; + animation: fadeIn 0.3s ease; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.message.user { + flex-direction: row-reverse; +} + +.message-avatar { + width: 36px; + height: 36px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + background: #e9ecef; + flex-shrink: 0; +} + +.message.user .message-avatar { + background: #667eea; +} + +.message-content { + max-width: 70%; + min-width: 100px; +} + +.message-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 4px; + gap: 10px; +} + +.message-sender { + font-size: 12px; + color: #666; + font-weight: 500; +} + +.message-time { + font-size: 11px; + color: #999; +} + +.message-text { + padding: 12px 16px; + border-radius: 16px; + background: white; + color: #333; + line-height: 1.5; + word-wrap: break-word; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.message.user .message-text { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border-bottom-right-radius: 4px; +} + +.message.agent .message-text { + border-bottom-left-radius: 4px; +} + +.message.system .message-text { + background: #fff3cd; + color: #856404; + border-radius: 8px; +} + +/* 代码块样式 */ +.message-text pre { + background: #1e1e1e; + color: #d4d4d4; + padding: 12px; + border-radius: 8px; + overflow-x: auto; + margin: 8px 0; +} + +.message-text code { + background: #f0f0f0; + padding: 2px 6px; + border-radius: 4px; + font-family: 'Consolas', 'Monaco', monospace; + font-size: 13px; +} + +.message-text pre code { + background: transparent; + padding: 0; +} + +/* 输入区域 */ +.chat-input-area { + padding: 15px 20px; + background: white; + border-top: 1px solid #e9ecef; +} + +.input-wrapper { + display: flex; + gap: 10px; + align-items: flex-end; +} + +#message-input { + flex: 1; + padding: 12px 16px; + border: 2px solid #e9ecef; + border-radius: 12px; + font-size: 15px; + resize: none; + outline: none; + transition: border-color 0.2s; + font-family: inherit; + max-height: 150px; + line-height: 1.5; +} + +#message-input:focus { + border-color: #667eea; +} + +#send-btn { + padding: 12px 24px; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border: none; + border-radius: 12px; + font-size: 15px; + font-weight: 500; + cursor: pointer; + transition: opacity 0.2s, transform 0.1s; +} + +#send-btn:hover:not(:disabled) { + opacity: 0.9; +} + +#send-btn:active:not(:disabled) { + transform: scale(0.98); +} + +#send-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.input-hint { + margin-top: 8px; + height: 20px; +} + +/* 打字指示器 */ +.typing-indicator { + display: inline-flex; + align-items: center; + gap: 4px; + color: #666; + font-size: 13px; +} + +.typing-indicator .dot { + width: 6px; + height: 6px; + background: #667eea; + border-radius: 50%; + animation: bounce 1.4s infinite ease-in-out; +} + +.typing-indicator .dot:nth-child(1) { animation-delay: 0s; } +.typing-indicator .dot:nth-child(2) { animation-delay: 0.2s; } +.typing-indicator .dot:nth-child(3) { animation-delay: 0.4s; } + +@keyframes bounce { + 0%, 80%, 100% { + transform: scale(0.8); + opacity: 0.5; + } + 40% { + transform: scale(1); + opacity: 1; + } +} + +/* 滚动条样式 */ +.message-list::-webkit-scrollbar { + width: 6px; +} + +.message-list::-webkit-scrollbar-track { + background: transparent; +} + +.message-list::-webkit-scrollbar-thumb { + background: #ccc; + border-radius: 3px; +} + +.message-list::-webkit-scrollbar-thumb:hover { + background: #aaa; +} + +/* 响应式设计 */ +@media (max-width: 768px) { + .chat-container { + height: 100vh; + } + + .chat-header { + padding: 10px 15px; + } + + .logo { + font-size: 18px; + } + + .message-content { + max-width: 85%; + } + + .chat-input-area { + padding: 10px 15px; + } + + #send-btn { + padding: 12px 16px; + } +} diff --git a/static/openclaw_report.docx b/static/openclaw_report.docx new file mode 100644 index 0000000000000000000000000000000000000000..5ec37cf8be2f8225865f8c1791b95de8491c746b GIT binary patch literal 40641 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 + + + + + 小白聊天 - OpenClaw + + + +
+ +
+
+ + +
+
+ 连接中... + + 退出 +
+
+ + +
+
+
🐶
+
+

你好,{{ username }}!

+

我是小白,你的 AI 助手。有什么可以帮你的吗?

+
+
+
+ + +
+
+ + +
+
+ +
+
+
+ + + + +