| 26 | |
| 27 | |
| 28 | class Logger: |
| 29 | # Match scripts/dashboard.py palette |
| 30 | _PAL_ACCENT = "#8bb5ff" |
| 31 | _PAL_GREEN = "#8fd19e" |
| 32 | _PAL_YELLOW = "#e3c07b" |
| 33 | _PAL_RED = "#f28b82" |
| 34 | _PAL_ORANGE = "#ffb072" |
| 35 | _PAL_PURPLE = "#c9a0ff" |
| 36 | _PAL_CYAN = "#7bd9ff" |
| 37 | |
| 38 | def __init__( |
| 39 | self, |
| 40 | mcp_client: MCPClient, |
| 41 | log_file: str, |
| 42 | to_stdout: bool = True, |
| 43 | *, |
| 44 | host_log_path: Path | None = None, |
| 45 | event_log_path: str | None = None, |
| 46 | host_event_log_path: Path | None = None, |
| 47 | deduplicate: bool = False, |
| 48 | append_mode: bool = False, |
| 49 | ): |
| 50 | """ |
| 51 | Initialize the logger. |
| 52 | |
| 53 | Args: |
| 54 | log_file (str): Path to the log file. |
| 55 | to_stdout (bool): If True, also print to stdout. |
| 56 | host_log_path (Path | None): Optional local path to write logs outside MCP. |
| 57 | event_log_path (str | None): Optional log path for structured events. |
| 58 | host_event_log_path (Path | None): Optional local path for structured events. |
| 59 | deduplicate (bool): If True, skip consecutive duplicate messages. |
| 60 | append_mode (bool): If True, append to existing log files instead of |
| 61 | overwriting them. Useful when re-creating the logger during resume |
| 62 | to preserve previously logged events. |
| 63 | """ |
| 64 | self.mcp_client = mcp_client |
| 65 | self.log_path = log_file # path under MCP fs_write |
| 66 | self.to_stdout = to_stdout |
| 67 | self.host_log_path = Path(host_log_path) if host_log_path else None |
| 68 | self.event_log_path = event_log_path or self.log_path |
| 69 | self.host_event_log_path = ( |
| 70 | Path(host_event_log_path) if host_event_log_path else self.host_log_path |
| 71 | ) |
| 72 | self.deduplicate = deduplicate |
| 73 | self.mcp_available = True |
| 74 | self._last_message = None |
| 75 | |
| 76 | # Thread lock for thread-safe logging in parallel execution |
| 77 | self._lock = threading.Lock() |
| 78 | |
| 79 | # Pretty console rendering (optional) |
| 80 | self.pretty = ( |
| 81 | self._env_bool("CS_PRETTY", default=True) |
| 82 | and self.to_stdout |
| 83 | and Console is not None |
| 84 | ) |
| 85 | self._console = ( |
no outgoing calls
no test coverage detected