MASFactory Visualizer runtime bridge. - Connects to the VS Code extension host via WebSocket (MASFACTORY_VISUALIZER_PORT). - Run mode: sends heartbeats; detailed data only after SUBSCRIBE. - Debug mode: sends full graph immediately and streams events.
| 66 | |
| 67 | |
| 68 | class VisualizerRuntime: |
| 69 | """ |
| 70 | MASFactory Visualizer runtime bridge. |
| 71 | |
| 72 | - Connects to the VS Code extension host via WebSocket (MASFACTORY_VISUALIZER_PORT). |
| 73 | - Run mode: sends heartbeats; detailed data only after SUBSCRIBE. |
| 74 | - Debug mode: sends full graph immediately and streams events. |
| 75 | """ |
| 76 | |
| 77 | def __init__(self, host: str, port: int, mode: str): |
| 78 | """Create a VisualizerRuntime bridge. |
| 79 | |
| 80 | Args: |
| 81 | host: Visualizer WebSocket server host. |
| 82 | port: Visualizer WebSocket server port. |
| 83 | mode: Runtime mode (`run` or `debug`). |
| 84 | """ |
| 85 | self._host = host |
| 86 | self._port = port |
| 87 | self._mode = (mode or "run").lower() |
| 88 | self._pid = os.getpid() |
| 89 | |
| 90 | self._lock = threading.RLock() |
| 91 | self._thread: threading.Thread | None = None |
| 92 | self._stop = threading.Event() |
| 93 | |
| 94 | self._connected = False |
| 95 | self._subscribed = False |
| 96 | |
| 97 | self._graph_name: str | None = None |
| 98 | self._graph_payload: dict[str, object] | None = None |
| 99 | self._graph_version = 0 |
| 100 | self._last_sent_graph_version = -1 |
| 101 | self._root_entry_obj: object | None = None |
| 102 | self._root_exit_obj: object | None = None |
| 103 | |
| 104 | self._outq: "queue.Queue[dict[str, object]]" = queue.Queue(maxsize=5000) |
| 105 | self._history_events: list[dict[str, object]] = [] |
| 106 | self._history_dropped = 0 |
| 107 | self._history_truncated_fields = 0 |
| 108 | |
| 109 | # Tune: keep a bounded history so late subscribers can reconstruct execution state. |
| 110 | self._history_max_events = 1200 |
| 111 | self._history_max_str = 5000 |
| 112 | |
| 113 | # Human-in-the-loop interaction (request/response) |
| 114 | self._pending_interactions: dict[str, _PendingInteraction] = {} |
| 115 | |
| 116 | @property |
| 117 | def mode(self) -> str: |
| 118 | return self._mode |
| 119 | |
| 120 | def is_debug(self) -> bool: |
| 121 | return self._mode == "debug" |
| 122 | |
| 123 | def is_streaming(self) -> bool: |
| 124 | # Debug is active-mode by definition. |
| 125 | if self.is_debug(): |
no outgoing calls
no test coverage detected