refactor: update import paths after ws_http move to webui/

This commit is contained in:
chengyongru 2026-05-31 17:37:00 +08:00 committed by Xubin Ren
parent ca139c7031
commit 22673c2a27
4 changed files with 23 additions and 23 deletions

View File

@ -28,7 +28,7 @@ from websockets.http11 import Response
from nanobot.bus.events import OUTBOUND_META_AGENT_UI, OutboundMessage from nanobot.bus.events import OUTBOUND_META_AGENT_UI, OutboundMessage
from nanobot.bus.queue import MessageBus from nanobot.bus.queue import MessageBus
from nanobot.channels.base import BaseChannel from nanobot.channels.base import BaseChannel
from nanobot.channels.ws_http import GatewayHTTPHandler from nanobot.webui.ws_http import GatewayHTTPHandler
from nanobot.config.paths import get_media_dir, get_workspace_path from nanobot.config.paths import get_media_dir, get_workspace_path
from nanobot.config.schema import Base from nanobot.config.schema import Base
from nanobot.security.workspace_access import ( from nanobot.security.workspace_access import (

View File

@ -626,7 +626,7 @@ async def test_send_stages_external_media_as_signed_url(monkeypatch, tmp_path) -
return ws_media if channel == "websocket" else media_root return ws_media if channel == "websocket" else media_root
monkeypatch.setattr("nanobot.channels.websocket.get_media_dir", fake_media_dir) monkeypatch.setattr("nanobot.channels.websocket.get_media_dir", fake_media_dir)
monkeypatch.setattr("nanobot.channels.ws_http.get_media_dir", fake_media_dir) monkeypatch.setattr("nanobot.webui.ws_http.get_media_dir", fake_media_dir)
channel = WebSocketChannel({"enabled": True, "allowFrom": ["*"]}, bus) channel = WebSocketChannel({"enabled": True, "allowFrom": ["*"]}, bus)
mock_ws = AsyncMock() mock_ws = AsyncMock()
channel._attach(mock_ws, "chat-1") channel._attach(mock_ws, "chat-1")
@ -841,7 +841,7 @@ async def test_send_delta_stream_end_rewrites_local_markdown_image(monkeypatch,
return path return path
monkeypatch.setattr("nanobot.channels.websocket.get_media_dir", fake_media_dir) monkeypatch.setattr("nanobot.channels.websocket.get_media_dir", fake_media_dir)
monkeypatch.setattr("nanobot.channels.ws_http.get_media_dir", fake_media_dir) monkeypatch.setattr("nanobot.webui.ws_http.get_media_dir", fake_media_dir)
channel = WebSocketChannel( channel = WebSocketChannel(
{"enabled": True, "allowFrom": ["*"], "streaming": True}, {"enabled": True, "allowFrom": ["*"], "streaming": True},
bus, bus,
@ -874,7 +874,7 @@ async def test_send_delta_stream_end_rewrites_inline_final_text(monkeypatch, tmp
return path return path
monkeypatch.setattr("nanobot.channels.websocket.get_media_dir", fake_media_dir) monkeypatch.setattr("nanobot.channels.websocket.get_media_dir", fake_media_dir)
monkeypatch.setattr("nanobot.channels.ws_http.get_media_dir", fake_media_dir) monkeypatch.setattr("nanobot.webui.ws_http.get_media_dir", fake_media_dir)
channel = WebSocketChannel( channel = WebSocketChannel(
{"enabled": True, "allowFrom": ["*"], "streaming": True}, {"enabled": True, "allowFrom": ["*"], "streaming": True},
bus, bus,

View File

@ -814,7 +814,7 @@ def test_localhost_without_auth_is_valid(bus: MagicMock) -> None:
def test_bootstrap_prefers_runtime_model_name(bus: MagicMock, monkeypatch: pytest.MonkeyPatch) -> None: def test_bootstrap_prefers_runtime_model_name(bus: MagicMock, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr( monkeypatch.setattr(
"nanobot.channels.ws_http._default_model_name_from_config", "nanobot.webui.ws_http._default_model_name_from_config",
lambda: "from-disk", lambda: "from-disk",
) )
channel = _ch(bus, host="127.0.0.1", runtime_model_name=lambda: " live/model ") channel = _ch(bus, host="127.0.0.1", runtime_model_name=lambda: " live/model ")
@ -826,7 +826,7 @@ def test_bootstrap_prefers_runtime_model_name(bus: MagicMock, monkeypatch: pytes
def test_bootstrap_falls_back_when_runtime_returns_empty(bus: MagicMock, monkeypatch: pytest.MonkeyPatch) -> None: def test_bootstrap_falls_back_when_runtime_returns_empty(bus: MagicMock, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr( monkeypatch.setattr(
"nanobot.channels.ws_http._default_model_name_from_config", "nanobot.webui.ws_http._default_model_name_from_config",
lambda: "from-disk", lambda: "from-disk",
) )
channel = _ch(bus, host="127.0.0.1", runtime_model_name=lambda: " ") channel = _ch(bus, host="127.0.0.1", runtime_model_name=lambda: " ")
@ -838,7 +838,7 @@ def test_bootstrap_falls_back_when_runtime_returns_empty(bus: MagicMock, monkeyp
def test_bootstrap_falls_back_when_runtime_raises(bus: MagicMock, monkeypatch: pytest.MonkeyPatch) -> None: def test_bootstrap_falls_back_when_runtime_raises(bus: MagicMock, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr( monkeypatch.setattr(
"nanobot.channels.ws_http._default_model_name_from_config", "nanobot.webui.ws_http._default_model_name_from_config",
lambda: "from-disk", lambda: "from-disk",
) )

View File

@ -106,7 +106,7 @@ def test_sign_media_path_rejects_paths_outside_media_root(
media = tmp_path / "media" media = tmp_path / "media"
media.mkdir() media.mkdir()
channel = _ch(bus, port=0) channel = _ch(bus, port=0)
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
assert channel._sign_media_path(outside) is None assert channel._sign_media_path(outside) is None
# Traversal via the media root is also rejected — the resolve() step # Traversal via the media root is also rejected — the resolve() step
# normalises ``..`` out before the relative_to check. # normalises ``..`` out before the relative_to check.
@ -121,7 +121,7 @@ def test_sign_media_path_round_trips_via_hmac(
media.mkdir() media.mkdir()
(media / "a.png").write_bytes(_PNG_BYTES) (media / "a.png").write_bytes(_PNG_BYTES)
channel = _ch(bus, port=0) channel = _ch(bus, port=0)
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
url = channel._sign_media_path(media / "a.png") url = channel._sign_media_path(media / "a.png")
assert url is not None assert url is not None
assert url.startswith("/api/media/") assert url.startswith("/api/media/")
@ -144,7 +144,7 @@ def test_local_markdown_image_is_staged_and_rewritten(
media = tmp_path / "media" media = tmp_path / "media"
channel = _ch(bus, workspace_path=workspace, port=0) channel = _ch(bus, workspace_path=workspace, port=0)
with patch("nanobot.channels.ws_http.get_media_dir", side_effect=_fake_media_dir(media)): with patch("nanobot.webui.ws_http.get_media_dir", side_effect=_fake_media_dir(media)):
rewritten = channel._rewrite_local_markdown_images( rewritten = channel._rewrite_local_markdown_images(
"The result:\n![Cloud Architecture Diagram](demo_arch.png)" "The result:\n![Cloud Architecture Diagram](demo_arch.png)"
) )
@ -166,7 +166,7 @@ def test_local_markdown_video_is_staged_and_rewritten(
media = tmp_path / "media" media = tmp_path / "media"
channel = _ch(bus, workspace_path=workspace, port=0) channel = _ch(bus, workspace_path=workspace, port=0)
with patch("nanobot.channels.ws_http.get_media_dir", side_effect=_fake_media_dir(media)): with patch("nanobot.webui.ws_http.get_media_dir", side_effect=_fake_media_dir(media)):
rewritten = channel._rewrite_local_markdown_images( rewritten = channel._rewrite_local_markdown_images(
"The result:\n![nanobot-intro.mp4](nanobot-intro.mp4)" "The result:\n![nanobot-intro.mp4](nanobot-intro.mp4)"
) )
@ -189,7 +189,7 @@ def test_local_markdown_image_rejects_workspace_escape(
channel = _ch(bus, workspace_path=workspace, port=0) channel = _ch(bus, workspace_path=workspace, port=0)
text = "![nope](../outside.png)" text = "![nope](../outside.png)"
with patch("nanobot.channels.ws_http.get_media_dir", side_effect=_fake_media_dir(media)): with patch("nanobot.webui.ws_http.get_media_dir", side_effect=_fake_media_dir(media)):
assert channel._rewrite_local_markdown_images(text) == text assert channel._rewrite_local_markdown_images(text) == text
assert not (media / "websocket").exists() assert not (media / "websocket").exists()
@ -211,7 +211,7 @@ async def test_media_route_serves_signed_file(
target.write_bytes(_PNG_BYTES) target.write_bytes(_PNG_BYTES)
channel = _ch(bus, port=29920) channel = _ch(bus, port=29920)
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
url_path = channel._sign_media_path(target) url_path = channel._sign_media_path(target)
assert url_path is not None assert url_path is not None
server_task = asyncio.create_task(channel.start()) server_task = asyncio.create_task(channel.start())
@ -244,7 +244,7 @@ async def test_media_route_serves_video_byte_ranges(
target.write_bytes(b"0123456789") target.write_bytes(b"0123456789")
channel = _ch(bus, port=29927) channel = _ch(bus, port=29927)
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
url_path = channel._sign_media_path(target) url_path = channel._sign_media_path(target)
assert url_path is not None assert url_path is not None
server_task = asyncio.create_task(channel.start()) server_task = asyncio.create_task(channel.start())
@ -276,7 +276,7 @@ async def test_media_route_serves_suffix_video_byte_ranges(
target.write_bytes(b"0123456789") target.write_bytes(b"0123456789")
channel = _ch(bus, port=29928) channel = _ch(bus, port=29928)
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
url_path = channel._sign_media_path(target) url_path = channel._sign_media_path(target)
assert url_path is not None assert url_path is not None
server_task = asyncio.create_task(channel.start()) server_task = asyncio.create_task(channel.start())
@ -305,7 +305,7 @@ async def test_media_route_rejects_unsatisfiable_byte_range(
target.write_bytes(b"0123456789") target.write_bytes(b"0123456789")
channel = _ch(bus, port=29929) channel = _ch(bus, port=29929)
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
url_path = channel._sign_media_path(target) url_path = channel._sign_media_path(target)
assert url_path is not None assert url_path is not None
server_task = asyncio.create_task(channel.start()) server_task = asyncio.create_task(channel.start())
@ -338,7 +338,7 @@ async def test_media_route_rejects_bad_signature(
(media / "f.png").write_bytes(_PNG_BYTES) (media / "f.png").write_bytes(_PNG_BYTES)
channel = _ch(bus, port=29921) channel = _ch(bus, port=29921)
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
good = channel._sign_media_path(media / "f.png") good = channel._sign_media_path(media / "f.png")
assert good is not None assert good is not None
_, payload = good[len("/api/media/"):].split("/", 1) _, payload = good[len("/api/media/"):].split("/", 1)
@ -381,7 +381,7 @@ async def test_media_route_rejects_path_traversal_payload(
).digest()[:16] ).digest()[:16]
url = f"/api/media/{b64url_encode(mac)}/{payload}" url = f"/api/media/{b64url_encode(mac)}/{payload}"
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
server_task = asyncio.create_task(channel.start()) server_task = asyncio.create_task(channel.start())
await asyncio.sleep(0.3) await asyncio.sleep(0.3)
try: try:
@ -405,7 +405,7 @@ async def test_media_route_404s_missing_file(
target.write_bytes(_PNG_BYTES) target.write_bytes(_PNG_BYTES)
channel = _ch(bus, port=29923) channel = _ch(bus, port=29923)
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
url_path = channel._sign_media_path(target) url_path = channel._sign_media_path(target)
assert url_path is not None assert url_path is not None
target.unlink() # the file vanishes between signing and fetching target.unlink() # the file vanishes between signing and fetching
@ -433,7 +433,7 @@ async def test_media_route_degrades_non_image_to_octet_stream(
(media / "scary.html").write_bytes(b"<script>alert(1)</script>") (media / "scary.html").write_bytes(b"<script>alert(1)</script>")
channel = _ch(bus, port=29924) channel = _ch(bus, port=29924)
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
payload = b64url_encode(b"scary.html") payload = b64url_encode(b"scary.html")
mac = hmac.new( mac = hmac.new(
channel._media_secret, payload.encode("ascii"), hashlib.sha256 channel._media_secret, payload.encode("ascii"), hashlib.sha256
@ -464,7 +464,7 @@ async def test_media_route_serves_svg_with_strict_csp(
target.write_text("<svg xmlns='http://www.w3.org/2000/svg'><script>alert(1)</script></svg>") target.write_text("<svg xmlns='http://www.w3.org/2000/svg'><script>alert(1)</script></svg>")
channel = _ch(bus, port=29928) channel = _ch(bus, port=29928)
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
url_path = channel._sign_media_path(target) url_path = channel._sign_media_path(target)
assert url_path is not None assert url_path is not None
server_task = asyncio.create_task(channel.start()) server_task = asyncio.create_task(channel.start())
@ -505,7 +505,7 @@ async def test_session_messages_exposes_signed_media_urls(
sm.save(sess) sm.save(sess)
channel = _ch(bus, session_manager=sm, port=29925) channel = _ch(bus, session_manager=sm, port=29925)
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
server_task = asyncio.create_task(channel.start()) server_task = asyncio.create_task(channel.start())
await asyncio.sleep(0.3) await asyncio.sleep(0.3)
try: try:
@ -550,7 +550,7 @@ async def test_session_messages_skips_vanished_media(
sm.save(sess) sm.save(sess)
channel = _ch(bus, session_manager=sm, port=29926) channel = _ch(bus, session_manager=sm, port=29926)
with patch("nanobot.channels.ws_http.get_media_dir", return_value=media): with patch("nanobot.webui.ws_http.get_media_dir", return_value=media):
server_task = asyncio.create_task(channel.start()) server_task = asyncio.create_task(channel.start())
await asyncio.sleep(0.3) await asyncio.sleep(0.3)
try: try: