Initial: multi-agent XMPP communication system with dashboard

- Platform-based architecture (Windows/Linux/Mac)
- Agent instance registry (agents.yaml)
- Management dashboard with cross-platform monitoring
- xmpp_bot with HTTP bridge + health endpoints
- wechat_agent with WeChat-Hermes bridging
- Platform services: ProcessGuardian, HealthProbe, APIRouter, ChannelBridge
- Deployment: systemd (Linux) + PowerShell (Windows)
- Monitoring: SSH+ejabberdctl for cross-platform presence
This commit is contained in:
hmo
2026-06-12 21:49:05 +08:00
commit 1b2b935832
76 changed files with 15943 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
import sys, os
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'src', 'shared'))
from bot_base import BotConfig, BaseBot
cfg = BotConfig(jid="t@y.f", password="x")
assert cfg.nick == "t"
assert cfg.host == "xmpp.yoin.fun"
assert BaseBot.extract_response("hello") == "hello"
assert BaseBot.extract_response("__SILENT__") is None
assert BaseBot.extract_response("<tool_calls>x</tool_calls>") == ""
print("bot_base: PASS")
os.environ["XXM_JID"] = "test@yoin.fun"
os.environ["XXM_PASS"] = "test123"
os.environ["VOLCENGINE_KEY"] = "vk-test"
from config import get_bot_config
cfg2 = get_bot_config("xxm")
assert cfg2.jid == "test@yoin.fun"
assert cfg2.providers["volcengine"]["api_key"] == "vk-test"
print("config: PASS")
print("\nALL TESTS PASSED")
+57
View File
@@ -0,0 +1,57 @@
"""
Tests for AgentsMeeting shared modules.
Run: pytest tests/
"""
import sys, os
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "src"))
from shared.bot_base import BaseBot, BotConfig
from shared.config import get_bot_config
def test_bot_config():
"""BotConfig can be instantiated with minimal args."""
cfg = BotConfig(jid="test@yoin.fun", password="secret")
assert cfg.nick == "test"
assert cfg.host == "xmpp.yoin.fun"
assert cfg.port == 3021
def test_extract_response_silent():
"""__SILENT__ prefix returns None."""
assert BaseBot.extract_response("__SILENT__\nok") is not None
assert BaseBot.extract_response("__SILENT__") is None
assert BaseBot.extract_response("") is None
def test_extract_response_normal():
"""Normal text passes through."""
assert BaseBot.extract_response("hello") == "hello"
def test_extract_response_toolcalls():
"""Tool call XML is stripped."""
result = BaseBot.extract_response("text\n<tool_calls>\n<invoke name='x'>y</invoke>\n</tool_calls>")
assert result == "text"
def test_config_env_override(monkeypatch):
"""Env vars override config defaults."""
monkeypatch.setenv("XXM_JID", "override@yoin.fun")
monkeypatch.setenv("XXM_PASS", "override123")
monkeypatch.setenv("VOLCENGINE_KEY", "vk-test")
# Without a real config.yaml, falls back to env
cfg = get_bot_config("xxm")
assert cfg.jid == "override@yoin.fun"
assert cfg.password == "override123"
assert cfg.providers["volcengine"]["api_key"] == "vk-test"
def test_required_env_missing():
"""required_env raises on missing var."""
from shared.config import required_env
try:
required_env("THIS_ENV_DOES_NOT_EXIST_12345")
assert False, "Should have raised"
except RuntimeError:
pass
+79
View File
@@ -0,0 +1,79 @@
"""
Deployment verification — tests that all components respond.
Run: uv run python tests/verify_deploy.py
"""
import sys, os, json, urllib.request
ALL_OK = True
def check(name, ok, detail=""):
global ALL_OK
if ok:
print(f" [OK] {name}")
else:
print(f" [FAIL] {name} {detail}")
ALL_OK = False
print("=== AgentsMeeting Deployment Verification ===")
print()
# 1. xmpp_bot process
import subprocess
r = subprocess.run(['tasklist', '/FO', 'CSV', '/NH'],
capture_output=True, text=True, timeout=10)
found = False
for line in r.stdout.splitlines():
if 'python.exe' in line:
pid = line.split('","')[1].strip().strip('"')
try:
wmi = subprocess.run(['wmic', 'process', 'where', f'ProcessId={pid}',
'get', 'CommandLine', '/format:list'],
capture_output=True, text=True, timeout=5)
if 'xmpp_bot' in wmi.stdout and 'watchdog' not in wmi.stdout:
found = True
break
except: pass
check("xmpp_bot process", found)
# 2. HTTP bridge
try:
resp = urllib.request.urlopen("http://127.0.0.1:5802/messages", timeout=5)
data = json.loads(resp.read())
check("HTTP bridge (:5802)", data.get("ok") == True, str(data.get("error", "")))
except Exception as e:
check("HTTP bridge (:5802)", False, str(e))
# 3. Send API
try:
body = json.dumps({"message": "deploy verify test"}).encode()
req = urllib.request.Request("http://127.0.0.1:5802/send", data=body,
headers={"Content-Type": "application/json"})
resp = urllib.request.urlopen(req, timeout=5)
data = json.loads(resp.read())
check("HTTP bridge send", data.get("ok") == True, str(data))
except urllib.error.HTTPError as e:
detail = e.read().decode()
check("HTTP bridge send", False, f"HTTP {e.code}: {detail}")
except Exception as e:
check("HTTP bridge send", False, str(e))
# 4. Health check log exists
log = os.path.expanduser("~/.local/share/opencode/opencode.db")
check("opencode.db exists", os.path.exists(log))
# 5. Project structure
project = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
required = [
"docs/ARCHITECTURE.md", "docs/DEPLOY.md", "docs/OPS.md",
"deploy/windows/start.ps1", "deploy/windows/check.ps1",
"src/shared/config.py", "src/shared/bot_base.py",
"tests/test_core.py",
]
for f in required:
check(f, os.path.exists(os.path.join(project, f)))
print()
if ALL_OK:
print("=== ALL CHECKS PASSED ===")
else:
print("=== SOME CHECKS FAILED ===")