diff --git a/CHANGELOG.md b/CHANGELOG.md index 0884b617..da2f032d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ Status of the `main` branch. Changes prior to the next official version change w and `workspace/configuration` pulls. Enables Yarn PnP setups with `typescript.tsdk` pointing at the Yarn-generated SDK. +* Dashboard: + - Fix: Host validation required a local host regardless of the listen address (regression introduced in v1.5.2), + preventing remote connections + # v1.5.3 (2026-05-26) # v1.5.2 (2026-05-26) @@ -17,6 +21,9 @@ Status of the `main` branch. Changes prior to the next official version change w - Add `serena-agent` CLI command so that `uvx serena-agent` can be used as entrypoint. - Fortls and pyright are now installed on the fly instead of being bundled in the serena-agent package. +* Dashboard: + - Add host validation + * Hooks: - Extend list of extensions that are considered code files (affects the reminder hook counter). diff --git a/src/serena/agent.py b/src/serena/agent.py index c8e0d1e5..ce4c1191 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -664,8 +664,12 @@ class SerenaAgent: # may access various parts of the agent if self.serena_config.web_dashboard: self._dashboard_thread, port = SerenaDashboardAPI( - get_memory_log_handler(), tool_names, agent=self, tool_usage_stats=self._tool_usage_stats - ).run_in_thread(host=self.serena_config.web_dashboard_listen_address) + get_memory_log_handler(), + tool_names, + agent=self, + tool_usage_stats=self._tool_usage_stats, + host=self.serena_config.web_dashboard_listen_address, + ).run_in_thread() self._dashboard_manager = DashboardManager( port, self.serena_config.web_dashboard_listen_address, diff --git a/src/serena/dashboard.py b/src/serena/dashboard.py index 914b28e5..f7c5c3cc 100644 --- a/src/serena/dashboard.py +++ b/src/serena/dashboard.py @@ -197,14 +197,16 @@ class SerenaDashboardAPI: tool_names: list[str], agent: "SerenaAgent", tool_usage_stats: ToolUsageStats | None = None, + host: str = "127.0.0.1", ) -> None: self._memory_log_handler = memory_log_handler self._tool_names = tool_names self._agent = agent + self._host = host self._app = Flask(__name__) - - self._app.config["TRUSTED_HOSTS"] = ["127.0.0.1", "localhost"] - + local_hosts = ["127.0.0.1", "localhost"] + if self._host in local_hosts: + self._app.config["TRUSTED_HOSTS"] = local_hosts self._tool_usage_stats = tool_usage_stats self._loaded_news: dict[str, str] = {} self._news_ready = threading.Event() @@ -770,7 +772,7 @@ class SerenaDashboardAPI: raise RuntimeError(f"No free ports found starting from {start_port}") - def run(self, host: str, port: int) -> int: + def run(self, port: int) -> int: """ Runs the dashboard on the given host and port and returns the port number. """ @@ -778,13 +780,13 @@ class SerenaDashboardAPI: from flask import cli cli.show_server_banner = lambda *args, **kwargs: None - self._app.run(host=host, port=port, debug=False, use_reloader=False, threaded=True) + self._app.run(host=self._host, port=port, debug=False, use_reloader=False, threaded=True) return port - def run_in_thread(self, host: str) -> tuple[threading.Thread, int]: - port = self._find_first_free_port(self.BASE_PORT, host) - log.info("Starting dashboard (listen_address=%s, port=%d)", host, port) - thread = threading.Thread(target=lambda: self.run(host=host, port=port), daemon=True) + def run_in_thread(self) -> tuple[threading.Thread, int]: + port = self._find_first_free_port(self.BASE_PORT, self._host) + log.info("Starting dashboard (listen_address=%s, port=%d)", self._host, port) + thread = threading.Thread(target=lambda: self.run(port=port), daemon=True) thread.start() return thread, port