@@ -554,9 +554,37 @@ def test_browser_routing_config_from_env_defaults(monkeypatch: pytest.MonkeyPatc
554554 "process" ,
555555 "fs" ,
556556 "logs/stream" ,
557+ "repl" ,
558+ "webmcp" ,
557559 )
558560
559561
562+ def test_default_routing_sends_repl_and_webmcp_to_vm_but_not_replays (monkeypatch : pytest .MonkeyPatch ) -> None :
563+ from kernel ._models import FinalRequestOptions
564+ from kernel .lib .browser_routing .routing import (
565+ BrowserRoute ,
566+ BrowserRouteCache ,
567+ rewrite_direct_vm_options ,
568+ )
569+
570+ monkeypatch .delenv ("KERNEL_BROWSER_ROUTING_SUBRESOURCES" , raising = False )
571+ cache = BrowserRouteCache ()
572+ cache .set (BrowserRoute (session_id = "sess-1" , base_url = "http://browser-session.test/browser/kernel" , jwt = "token-abc" ))
573+ config = browser_routing_config_from_env ()
574+
575+ for path in ("repl" , "webmcp/tools" , "webmcp/invoke" , "webmcp/custom-tools/ct_1" ):
576+ routed = rewrite_direct_vm_options (
577+ FinalRequestOptions (method = "post" , url = f"/browsers/sess-1/{ path } " ), cache = cache , config = config
578+ )
579+ assert str (routed .url ).startswith (f"http://browser-session.test/browser/kernel/{ path } " )
580+
581+ for path in ("replays" , "replays/rec-1" ):
582+ unrouted = rewrite_direct_vm_options (
583+ FinalRequestOptions (method = "get" , url = f"/browsers/sess-1/{ path } " ), cache = cache , config = config
584+ )
585+ assert unrouted .url == f"/browsers/sess-1/{ path } "
586+
587+
560588def test_direct_vm_routing_allowlist_segment_boundary () -> None :
561589 # Pins the fix: telemetry/stream (live SSE) routes to the VM; telemetry/events
562590 # (historical, served by the control plane from S2) does NOT; and a
0 commit comments