verify_pipe.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. """
  2. verify_pipe.py — 真实联调自检(接真小智AI)
  3. 替代旧的 mock-W 版本:mcp_pipe 改成 in-process 后,没有跨进程桥接可测了。
  4. 现在直接 spawn mcp_pipe.py 进程(不传 audio_server 脚本,因为它被 import 了),
  5. 让它连真实 xiaozhi.me,等握手完成 + tools/list round-trip + ping 一次。
  6. """
  7. from __future__ import annotations
  8. import os
  9. import subprocess
  10. import sys
  11. import time
  12. HERE = os.path.dirname(os.path.abspath(__file__))
  13. PY = os.path.join(HERE, ".venv", "Scripts", "python.exe")
  14. env_path = os.path.join(HERE, ".env")
  15. def main() -> int:
  16. if not os.path.exists(env_path):
  17. print("FAIL: .env 不存在")
  18. return 1
  19. if not os.path.exists(PY):
  20. print(f"FAIL: 找不到 {PY}")
  21. return 1
  22. # 加载 .env
  23. with open(env_path, encoding="utf-8") as f:
  24. for line in f:
  25. line = line.strip()
  26. if not line or line.startswith("#") or "=" not in line:
  27. continue
  28. k, v = line.split("=", 1)
  29. os.environ.setdefault(k.strip(), v.strip().strip("'\""))
  30. if "MCP_ENDPOINT" not in os.environ or "your_token_here" in os.environ.get("MCP_ENDPOINT", ""):
  31. print("FAIL: .env 里 MCP_ENDPOINT 没填")
  32. return 1
  33. print(f"[verify_pipe] launching mcp_pipe.py (real xiaozhi.me) ...")
  34. proc = subprocess.Popen(
  35. [PY, "mcp_pipe.py"],
  36. cwd=HERE,
  37. stdout=subprocess.PIPE,
  38. stderr=subprocess.STDOUT,
  39. env=os.environ,
  40. bufsize=0,
  41. )
  42. deadline = time.time() + 70 # xiaozhi 30s 后才发 ping,留足余量
  43. saw_init = False
  44. saw_tools_list = False
  45. saw_ping = False
  46. try:
  47. while time.time() < deadline:
  48. line = proc.stdout.readline()
  49. if not line:
  50. break
  51. text = line.decode("utf-8", errors="replace").rstrip()
  52. if not text:
  53. continue
  54. print(text)
  55. if "response for initialize" in text:
  56. saw_init = True
  57. elif "response for tools/list" in text:
  58. saw_tools_list = True
  59. elif "response for ping" in text:
  60. saw_ping = True
  61. break # 一个 ping 就够了
  62. finally:
  63. proc.terminate()
  64. try:
  65. proc.wait(timeout=3)
  66. except subprocess.TimeoutExpired:
  67. proc.kill()
  68. if saw_init and saw_tools_list and saw_ping:
  69. print("\n[verify_pipe] PASS: initialize + tools/list + ping all round-tripped")
  70. return 0
  71. print(f"\n[verify_pipe] FAIL: init={saw_init} tools_list={saw_tools_list} ping={saw_ping}")
  72. return 1
  73. if __name__ == "__main__":
  74. sys.exit(main())