Files
val-blog/ai-agent-living/bridge/bridge_server.py
T

202 lines
7.0 KiB
Python

#!/usr/bin/env python3
"""
AgentLiving Bridge Server
连接 Godot 前端和 OpenClaw 后端
"""
import asyncio
import websockets
import json
import sys
from datetime import datetime
# 简单的状态存储
agent_states = {
"val": {
"location": "客厅",
"energy": 80,
"mood": "开心",
"activity": "idle",
"position": [400, 300]
}
}
class AgentLivingBridge:
def __init__(self):
self.clients = set()
async def register(self, websocket):
self.clients.add(websocket)
print(f"Client connected. Total: {len(self.clients)}")
async def unregister(self, websocket):
self.clients.discard(websocket)
print(f"Client disconnected. Total: {len(self.clients)}")
async def handle_client(self, websocket, path):
await self.register(websocket)
try:
async for message in websocket:
await self.process_message(websocket, message)
except websockets.exceptions.ConnectionClosed:
pass
finally:
await self.unregister(websocket)
async def process_message(self, websocket, message):
try:
data = json.loads(message)
msg_type = data.get("type", "")
print(f"[{datetime.now().isoformat()}] Received: {msg_type}")
if msg_type == "hello":
# 新客户端连接
await websocket.send(json.dumps({
"type": "state_sync",
"state": agent_states["val"]
}))
elif msg_type == "user_command":
# 处理用户指令
command = data.get("command", "")
print(f"User command: {command}")
# 解析指令并生成动作序列
actions = self._parse_command(command)
await websocket.send(json.dumps({
"type": "action_sequence",
"actions": actions
}))
elif msg_type == "furniture_clicked":
# 处理家具点击
furniture = data.get("furniture", "")
print(f"Furniture clicked: {furniture}")
# 生成走过去+交互的动作序列
actions = [
{"cmd": "show_thought", "text": f"要去{furniture}那边...", "duration": 1.0},
{"cmd": "walk_to", "pos": data.get("position", [0, 0])},
{"cmd": "play_anim", "anim": "interact"},
{"cmd": "show_thought", "text": f"正在使用{furniture}", "duration": 2.0}
]
await websocket.send(json.dumps({
"type": "action_sequence",
"actions": actions
}))
elif msg_type == "room_changed":
# 更新房间状态
room = data.get("room", "")
agent_states["val"]["location"] = room
print(f"Val moved to: {room}")
elif msg_type == "request_state_sync":
# 请求状态同步
await websocket.send(json.dumps({
"type": "state_sync",
"state": agent_states["val"]
}))
elif msg_type == "heartbeat_ack":
# 心跳响应,忽略
pass
else:
print(f"Unknown message type: {msg_type}")
except json.JSONDecodeError:
print(f"Invalid JSON: {message}")
except Exception as e:
print(f"Error processing message: {e}")
await websocket.send(json.dumps({
"type": "error",
"error": str(e)
}))
def _parse_command(self, command: str) -> list:
"""解析用户指令为动作序列"""
command = command.lower()
actions = []
# 简单指令映射
if "沙发" in command or "坐" in command:
actions = [
{"cmd": "show_thought", "text": "去沙发上休息...", "duration": 1.0},
{"cmd": "walk_to", "pos": [280, 200]},
{"cmd": "play_anim", "anim": "interact"},
{"cmd": "show_thought", "text": "真舒服~", "duration": 2.0}
]
elif "冰箱" in command or "水" in command or "喝" in command:
actions = [
{"cmd": "show_thought", "text": "去倒杯水...", "duration": 1.0},
{"cmd": "walk_to", "pos": [280, 440]},
{"cmd": "play_anim", "anim": "interact"},
{"cmd": "show_thought", "text": "解渴了~", "duration": 2.0}
]
elif "床" in command or "睡" in command or "休息" in command:
actions = [
{"cmd": "show_thought", "text": "去睡一会儿...", "duration": 1.0},
{"cmd": "walk_to", "pos": [760, 200]},
{"cmd": "play_anim", "anim": "interact"},
{"cmd": "show_thought", "text": "Zzz...", "duration": 3.0}
]
elif "书桌" in command or "工作" in command or "学习" in command:
actions = [
{"cmd": "show_thought", "text": "去工作...", "duration": 1.0},
{"cmd": "walk_to", "pos": [840, 200]},
{"cmd": "play_anim", "anim": "think"},
{"cmd": "show_thought", "text": "正在思考...", "duration": 3.0}
]
elif "客厅" in command:
actions = [
{"cmd": "show_thought", "text": "去客厅...", "duration": 1.0},
{"cmd": "walk_to", "pos": [320, 240]}
]
elif "厨房" in command:
actions = [
{"cmd": "show_thought", "text": "去厨房...", "duration": 1.0},
{"cmd": "walk_to", "pos": [320, 480]}
]
elif "卧室" in command:
actions = [
{"cmd": "show_thought", "text": "去卧室...", "duration": 1.0},
{"cmd": "walk_to", "pos": [800, 240]}
]
else:
# 默认:显示思考
actions = [
{"cmd": "show_thought", "text": f"收到指令:{command}", "duration": 2.0},
{"cmd": "play_anim", "anim": "think"}
]
return actions
async def main():
bridge = AgentLivingBridge()
host = "localhost"
port = 8765
print(f"Starting AgentLiving Bridge Server on ws://{host}:{port}")
print("Press Ctrl+C to stop")
async with websockets.serve(
bridge.handle_client,
host,
port,
ping_interval=20,
ping_timeout=10
):
await asyncio.Future() # 永久运行
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
print("\nShutting down...")
sys.exit(0)