feat(webui): add model settings runtime refresh

This commit is contained in:
Xubin Ren
2026-04-25 18:05:06 +00:00
parent a58d9fd357
commit b440e76d2f
14 changed files with 793 additions and 172 deletions
+68
View File
@@ -26,6 +26,8 @@ from nanobot.channels.websocket import (
_parse_query,
_parse_request_path,
)
from nanobot.config.loader import load_config, save_config
from nanobot.config.schema import Config
# -- Shared helpers (aligned with test_websocket_integration.py) ---------------
@@ -439,6 +441,72 @@ async def test_http_route_issues_token_then_websocket_requires_it(bus: MagicMock
await server_task
@pytest.mark.asyncio
async def test_settings_api_returns_safe_subset_and_updates_whitelist(
bus: MagicMock,
monkeypatch,
tmp_path,
) -> None:
port = 29891
config_path = tmp_path / "config.json"
config = Config()
config.agents.defaults.model = "openai/gpt-4o"
config.providers.openai.api_key = "secret-key"
save_config(config, config_path)
monkeypatch.setattr("nanobot.config.loader._current_config_path", config_path)
channel = _ch(bus, port=port)
channel._api_tokens["tok"] = time.monotonic() + 300
server_task = asyncio.create_task(channel.start())
await asyncio.sleep(0.3)
try:
settings = await _http_get(
f"http://127.0.0.1:{port}/api/settings",
headers={"Authorization": "Bearer tok"},
)
assert settings.status_code == 200
body = settings.json()
assert body["agent"]["model"] == "openai/gpt-4o"
assert body["agent"]["provider"] == "openai"
assert {"name": "auto", "label": "Auto"} in body["providers"]
assert body["agent"]["has_api_key"] is True
assert "secret-key" not in settings.text
updated = await _http_get(
"http://127.0.0.1:"
f"{port}/api/settings/update?model=openrouter/test"
"&provider=openrouter",
headers={"Authorization": "Bearer tok"},
)
assert updated.status_code == 200
assert updated.json()["requires_restart"] is True
saved = load_config(config_path)
assert saved.agents.defaults.model == "openrouter/test"
assert saved.agents.defaults.provider == "openrouter"
finally:
await channel.stop()
await server_task
def test_settings_payload_normalizes_camel_case_provider(
bus: MagicMock,
monkeypatch,
tmp_path,
) -> None:
config_path = tmp_path / "config.json"
config = Config()
config.agents.defaults.provider = "minimaxAnthropic"
save_config(config, config_path)
monkeypatch.setattr("nanobot.config.loader._current_config_path", config_path)
body = _ch(bus)._settings_payload()
assert body["agent"]["provider"] == "minimax_anthropic"
@pytest.mark.asyncio
async def test_end_to_end_server_pushes_streaming_deltas_to_client(bus: MagicMock) -> None:
port = 29880