File size: 3,088 Bytes
7f611c5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | """
Live run monitor for SkyDiscover solution discovery.
Provides a real-time WebSocket-powered dashboard that shows programs
appearing on a scatter plot as they're evaluated, with lineage arrows,
stats, and code inspection.
"""
import logging
import os
import time
from typing import Optional, Tuple
from skydiscover.extras.monitor.callback import create_external_callback, create_monitor_callback
from skydiscover.extras.monitor.server import MonitorServer
__all__ = [
"MonitorServer",
"create_monitor_callback",
"create_external_callback",
"start_monitor",
"stop_monitor",
]
logger = logging.getLogger(__name__)
def start_monitor(
config, output_dir: str
) -> Tuple[Optional[MonitorServer], Optional[object], Optional[object]]:
"""Start the live monitor server. Returns (server, callback, feedback_reader)."""
monitor_server = None
monitor_callback = None
feedback_reader = None
if not config.monitor.enabled:
return monitor_server, monitor_callback, feedback_reader
try:
monitor_server = MonitorServer(
host=config.monitor.host,
port=config.monitor.port,
max_solution_length=config.monitor.max_solution_length,
)
monitor_server.start()
monitor_callback = create_external_callback(monitor_server, time.time())
if config.monitor.summary_model:
monitor_server.configure_summary(
model=config.monitor.summary_model,
api_key=config.monitor.summary_api_key or "",
api_base=config.monitor.summary_api_base,
top_k=config.monitor.summary_top_k,
interval=config.monitor.summary_interval,
)
try:
from skydiscover.context_builder.human_feedback import HumanFeedbackReader
feedback_path = getattr(config, "human_feedback_file", None) or os.path.join(
output_dir, "human_feedback.md"
)
feedback_mode = getattr(config, "human_feedback_mode", "append")
feedback_reader = HumanFeedbackReader(feedback_path, mode=feedback_mode)
monitor_server.set_feedback_reader(feedback_reader)
logger.info("Human feedback enabled — file: %s", feedback_path)
except Exception as exc:
logger.warning("Failed to set up human feedback: %s", exc)
url = f"http://localhost:{monitor_server.port}/"
print(f"\n Live monitor: {url}\n", flush=True)
logger.info("Live monitor: %s", url)
except Exception as exc:
logger.warning("Failed to start monitor: %s", exc)
return monitor_server, monitor_callback, feedback_reader
def stop_monitor(monitor_server: Optional[MonitorServer]) -> None:
"""Gracefully shut down the monitor server."""
if monitor_server is None:
return
try:
monitor_server.push_event({"type": "discovery_complete"})
time.sleep(0.5)
monitor_server.stop()
except Exception:
logger.debug("Failed to stop monitor server", exc_info=True)
|