diff --git a/dimos/teleop/phone/phone_teleop_module.py b/dimos/teleop/phone/phone_teleop_module.py index 74cf25dc15..30af4092c4 100644 --- a/dimos/teleop/phone/phone_teleop_module.py +++ b/dimos/teleop/phone/phone_teleop_module.py @@ -85,7 +85,7 @@ def __init__(self, **kwargs: Any) -> None: self._stop_event = threading.Event() # Embedded web server — RobotWebInterface provides FastAPI app + run()/shutdown() - self._web_server = RobotWebInterface(port=self.config.server_port) + self._web_server = self._create_web_server() self._web_server_thread: threading.Thread | None = None # Fingerprint-based message dispatch table @@ -96,6 +96,12 @@ def __init__(self, **kwargs: Any) -> None: self._setup_routes() + def _create_web_server(self) -> RobotWebInterface: + return RobotWebInterface( + host=self.config.g.listen_host, + port=self.config.server_port, + ) + def _setup_routes(self) -> None: """Register teleop routes on the embedded web server.""" diff --git a/dimos/teleop/phone/test_phone_teleop_module.py b/dimos/teleop/phone/test_phone_teleop_module.py new file mode 100644 index 0000000000..31c24fe56f --- /dev/null +++ b/dimos/teleop/phone/test_phone_teleop_module.py @@ -0,0 +1,39 @@ +# Copyright 2025-2026 Dimensional Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Any + +from dimos.core.global_config import GlobalConfig +from dimos.teleop.phone import phone_teleop_module +from dimos.teleop.phone.phone_teleop_module import PhoneTeleopConfig, PhoneTeleopModule + + +def test_phone_teleop_web_server_uses_module_global_config_listen_host(monkeypatch) -> None: + captured: dict[str, Any] = {} + + class FakeRobotWebInterface: + def __init__(self, **kwargs: Any) -> None: + captured.update(kwargs) + + monkeypatch.setattr(phone_teleop_module, "RobotWebInterface", FakeRobotWebInterface) + + module = PhoneTeleopModule.__new__(PhoneTeleopModule) + module.config = PhoneTeleopConfig( + server_port=8444, + g=GlobalConfig(listen_host="0.0.0.0"), + ) + + module._create_web_server() + + assert captured == {"host": "0.0.0.0", "port": 8444} diff --git a/dimos/web/robot_web_interface.py b/dimos/web/robot_web_interface.py index 043aea71ec..ee67b4ca90 100644 --- a/dimos/web/robot_web_interface.py +++ b/dimos/web/robot_web_interface.py @@ -23,10 +23,19 @@ class RobotWebInterface(FastAPIServer): """Wrapper class for the dimos-interface FastAPI server.""" - def __init__(self, port: int = 5555, text_streams=None, audio_subject=None, **streams) -> None: # type: ignore[no-untyped-def] + def __init__( # type: ignore[no-untyped-def] + self, + port: int = 5555, + text_streams=None, + audio_subject=None, + *, + host: str | None = None, + **streams, + ) -> None: super().__init__( dev_name="Robot Web Interface", edge_type="Bidirectional", + host=host, port=port, text_streams=text_streams, audio_subject=audio_subject, diff --git a/dimos/web/templates/rerun_dashboard.html b/dimos/web/templates/rerun_dashboard.html index f0792079e3..b63ccbc6e8 100644 --- a/dimos/web/templates/rerun_dashboard.html +++ b/dimos/web/templates/rerun_dashboard.html @@ -29,15 +29,46 @@