From 2ba0b9a9bbf009c6398eb00f35303dc56a9c169e Mon Sep 17 00:00:00 2001 From: Theo Jiang Date: Wed, 27 May 2026 18:20:09 +0800 Subject: [PATCH] fix: pass viewer websocket URL for native teleop --- dimos/visualization/rerun/bridge.py | 9 +++++++- .../rerun/test_viewer_integration.py | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/dimos/visualization/rerun/bridge.py b/dimos/visualization/rerun/bridge.py index 2f5fb1efa9..e8abae8f77 100644 --- a/dimos/visualization/rerun/bridge.py +++ b/dimos/visualization/rerun/bridge.py @@ -107,6 +107,10 @@ RerunData: TypeAlias = "Archetype | RerunMulti" +def _dimos_viewer_extra_args(server_uri: str, ws_url: str) -> list[str]: + return ["--connect", server_uri, f"--ws-url={ws_url}"] + + def is_rerun_multi(data: Any) -> TypeGuard[RerunMulti]: """Check if data is a list of (entity_path, archetype) tuples.""" return ( @@ -342,12 +346,15 @@ def start(self) -> None: try: import rerun_bindings + ws_url = f"ws://{self.host}:{self.config.g.rerun_websocket_server_port}/ws" + # Use --connect so the viewer connects to the bridge's gRPC # server rather than starting its own (which would conflict). + # Use --ws-url so keyboard teleop events flow back to Dimos. rerun_bindings.spawn( executable_name="dimos-viewer", memory_limit=self.config.memory_limit, - extra_args=["--connect", server_uri], + extra_args=_dimos_viewer_extra_args(server_uri, ws_url), ) spawned = True except ImportError: diff --git a/dimos/visualization/rerun/test_viewer_integration.py b/dimos/visualization/rerun/test_viewer_integration.py index a8eb0602c3..bb7ac051dd 100644 --- a/dimos/visualization/rerun/test_viewer_integration.py +++ b/dimos/visualization/rerun/test_viewer_integration.py @@ -116,3 +116,24 @@ def test_bridge_has_fallback(self): "bridge.py start() has no fallback for missing dimos-viewer. " "Users without dimos-viewer will crash." ) + + def test_viewer_extra_args_include_grpc_and_websocket_urls(self): + """Native dimos-viewer launch must include the teleop WebSocket URL.""" + from dimos.visualization.rerun.bridge import _dimos_viewer_extra_args + + server_uri = "rerun+http://127.0.0.1:9877/proxy" + ws_url = "ws://127.0.0.1:3030/ws" + + assert _dimos_viewer_extra_args(server_uri, ws_url) == [ + "--connect", + server_uri, + f"--ws-url={ws_url}", + ] + + def test_bridge_uses_viewer_extra_args_helper(self): + """Guard against regressing to gRPC-only native viewer launch.""" + from dimos.visualization.rerun.bridge import RerunBridgeModule + + src = inspect.getsource(RerunBridgeModule.start) + assert "_dimos_viewer_extra_args" in src + assert "rerun_websocket_server_port" in src