ws_smoke.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import argparse
  2. import asyncio
  3. import json
  4. from copy import deepcopy
  5. from typing import Any
  6. from agent_lab.application.contracts import DEFAULT_EXTRA_BODY
  7. DEFAULT_URL = "ws://127.0.0.1:8000/ws/debug"
  8. DEFAULT_MESSAGE = "Debug this agent handoff path."
  9. DEFAULT_MODEL = ""
  10. def build_payload(
  11. message: str,
  12. model: str,
  13. handoff_note_enabled: bool,
  14. ) -> dict[str, Any]:
  15. return {
  16. "user_message": message,
  17. "system_prompts": [
  18. "You are a chat agent running inside Agent Lab. "
  19. "Stream a concise answer and call handoff_note when an event handoff helps."
  20. ],
  21. "pre_messages": [],
  22. "chat_agent": {
  23. "model": model,
  24. "temperature": 0.2,
  25. "max_tokens": 1024,
  26. "system_prompt": "",
  27. "extra_body": deepcopy(DEFAULT_EXTRA_BODY),
  28. },
  29. "event_agent": {
  30. "model": model,
  31. "temperature": 0.2,
  32. "max_tokens": 1024,
  33. "system_prompt": "",
  34. "extra_body": deepcopy(DEFAULT_EXTRA_BODY),
  35. "enabled_tools": ["handoff_note"] if handoff_note_enabled else [],
  36. "max_event_loops": 1,
  37. },
  38. }
  39. def build_parser() -> argparse.ArgumentParser:
  40. parser = argparse.ArgumentParser(
  41. description="Send one Agent Lab WebSocket debug request and print streamed JSON."
  42. )
  43. parser.add_argument("--url", default=DEFAULT_URL, help=f"WebSocket URL. Default: {DEFAULT_URL}")
  44. parser.add_argument("--message", default=DEFAULT_MESSAGE, help="User message to send.")
  45. parser.add_argument(
  46. "--model",
  47. default=DEFAULT_MODEL,
  48. help="Chat model name. Defaults to the backend configured model.",
  49. )
  50. tool_group = parser.add_mutually_exclusive_group()
  51. tool_group.add_argument(
  52. "--enable-handoff-note",
  53. dest="handoff_note_enabled",
  54. action="store_true",
  55. default=True,
  56. help="Enable the handoff_note tool. This is the default.",
  57. )
  58. tool_group.add_argument(
  59. "--disable-handoff-note",
  60. dest="handoff_note_enabled",
  61. action="store_false",
  62. help="Disable the handoff_note tool.",
  63. )
  64. return parser
  65. async def run_smoke(url: str, payload: dict[str, Any]) -> None:
  66. import websockets
  67. async with websockets.connect(url) as websocket:
  68. await websocket.send(_compact_json(payload))
  69. async for raw_message in websocket:
  70. try:
  71. message = json.loads(raw_message)
  72. except json.JSONDecodeError:
  73. print(raw_message, flush=True)
  74. continue
  75. print(_compact_json(message), flush=True)
  76. if message.get("type") in {"done", "error"}:
  77. break
  78. def _compact_json(value: Any) -> str:
  79. return json.dumps(value, ensure_ascii=False, separators=(",", ":"))
  80. def main() -> int:
  81. args = build_parser().parse_args()
  82. payload = build_payload(
  83. message=args.message,
  84. model=args.model,
  85. handoff_note_enabled=args.handoff_note_enabled,
  86. )
  87. asyncio.run(run_smoke(args.url, payload))
  88. return 0
  89. if __name__ == "__main__":
  90. raise SystemExit(main())