docs: merge EasyTier into AgentsMeeting + cleanup hosts approach

This commit is contained in:
hmo
2026-06-23 03:53:04 +08:00
parent 5a5cc1b45d
commit 4cf125231e
2 changed files with 368 additions and 2 deletions
+102 -2
View File
@@ -205,6 +205,70 @@ def _call_hermes_api(content: str, session_id: str | None = None) -> str:
return ""
# ═══════════════════════════════════════════════════════════════
# EasyTier control (Windows)
# ═══════════════════════════════════════════════════════════════
_EASYTIER_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
"tools", "easytier")
_EASYTIER_CORE = os.path.join(_EASYTIER_DIR, "easytier-core.exe")
_EASYTIER_PID_FILE = os.path.join(_EASYTIER_DIR, "easytier.pid")
_EASYTIER_NET = "--network-name mynet --network-secret ce75d0a5"
_EASYTIER_RELAY = "--peers tcp://47.115.32.206:11010"
_EASYTIER_IP = "--ipv4 10.144.144.3"
def _start_easytier():
"""Start EasyTier on Windows."""
import subprocess as _sp
if not os.path.exists(_EASYTIER_CORE):
log(f"EasyTier binary not found: {_EASYTIER_CORE}")
return
# Check if already running
if os.path.exists(_EASYTIER_PID_FILE):
try:
with open(_EASYTIER_PID_FILE) as f:
old_pid = int(f.read().strip())
_sp.run(["taskkill", "/f", "/pid", str(old_pid)], capture_output=True, timeout=5)
log(f"Killed old EasyTier (PID {old_pid})")
except Exception:
pass
# Start
cmd = f'start /b "" "{_EASYTIER_CORE}" {_EASYTIER_NET} {_EASYTIER_RELAY} {_EASYTIER_IP} --disable-encryption'
try:
_sp.run(cmd, shell=True, timeout=5)
log("EasyTier start command issued")
except Exception as e:
log(f"EasyTier start error: {e}")
def _stop_easytier():
"""Stop EasyTier on Windows."""
import subprocess as _sp
try:
_sp.run(["taskkill", "/f", "/im", "easytier-core.exe"], capture_output=True, timeout=5)
log("EasyTier stopped (taskkill)")
except Exception as e:
log(f"EasyTier stop error: {e}")
# Clean up PID file
try:
if os.path.exists(_EASYTIER_PID_FILE):
os.remove(_EASYTIER_PID_FILE)
except Exception:
pass
def _check_easytier() -> bool:
"""Check if EasyTier is running on Windows."""
import subprocess as _sp
try:
r = _sp.run(["tasklist", "/fi", "imagename eq easytier-core.exe"],
capture_output=True, text=True, timeout=5)
return "easytier-core.exe" in r.stdout
except Exception:
return False
# ═══════════════════════════════════════════════════════════════
# Message Dedup
# ═══════════════════════════════════════════════════════════════
@@ -606,17 +670,36 @@ class _BridgeHandler(http.server.BaseHTTPRequestHandler):
try:
length = int(self.headers.get('Content-Length', 0))
body = json.loads(self.rfile.read(length))
path = urllib.parse.urlparse(self.path).path.rstrip('/')
# /easytier endpoint — execute EasyTier action locally (no XMPP DM)
if path == "/easytier":
action = body.get("action", "")
if action == "start":
_start_easytier()
self._reply(200, {"ok": True, "message": "EasyTier started"})
elif action == "stop":
_stop_easytier()
self._reply(200, {"ok": True, "message": "EasyTier stopped"})
elif action == "status":
running = _check_easytier()
self._reply(200, {"ok": True, "running": running})
else:
self._reply(400, {"ok": False, "error": "action must be start|stop|status"})
return
to = body.get('to', cfg["muc_rooms"][0])
msg = body.get('message', '') or body.get('body', '')
msg_type = body.get('type', 'groupchat')
if not msg:
self._reply(400, {"ok": False, "error": "empty message"})
return
safe = _escape(msg.strip())
bot = _xmpp_ref
if bot:
bot.send_message(mto=to, mbody=msg.strip(), mtype='groupchat')
bot.send_message(mto=to, mbody=msg.strip(), mtype=msg_type)
_record_group_msg(cfg["nick"], msg)
log(f"[http] → [{to.split('@')[0]}]: {msg[:80]}")
log(f"[http] → [{to.split('@')[0]}]: {msg[:80]} (type={msg_type})")
self._reply(200, {"ok": True})
except Exception as e:
self._reply(500, {"ok": False, "error": str(e)})
@@ -751,6 +834,23 @@ def _handle_private_message(msg):
target_sid = _KANBAN_SESSION_ID if is_kanban else cfg["session_id"]
if is_kanban:
log(f"📋 看板通知(#{_CALL_SEQ}): {body[:80]}")
# ── EasyTier toggle ──
if body.startswith('[EasyTier]'):
action = body.replace('[EasyTier]', '').strip().lower()
log(f"🔌 EasyTier command: {action}")
if action == 'start':
_start_easytier()
reply_text = "[EasyTier] started on Windows"
elif action == 'stop':
_stop_easytier()
reply_text = "[EasyTier] stopped on Windows"
else:
reply_text = f"[EasyTier] unknown action: {action}"
bot = _xmpp_ref
if bot:
bot.send_message(mto=sender, mbody=reply_text, mtype='chat')
log(f"-> {sender}: {reply_text}")
return
raw = _call_llm(body, sender, is_group=False, session_id=target_sid)
if raw:
reply = _extract_response(raw)