refactor(webui): improve visual consistency (#5249)

This commit is contained in:
chengyongru
2026-08-05 13:24:45 +08:00
committed by GitHub
parent a54d5d14cb
commit 9098ffd38f
33 changed files with 578 additions and 646 deletions
@@ -2545,6 +2545,7 @@ async def test_settings_api_returns_safe_subset_and_updates_whitelist(
)
config.tools.web.search.provider = "brave"
config.tools.web.search.api_key = "brave-secret"
expected_timezone = config.agents.defaults.timezone
save_config(config, config_path)
monkeypatch.setattr("nanobot.config.loader._current_config_path", config_path)
monkeypatch.setattr(
@@ -2585,7 +2586,7 @@ async def test_settings_api_returns_safe_subset_and_updates_whitelist(
assert body["agent"]["provider"] == "openai"
assert body["agent"]["model_preset"] == "default"
assert body["agent"]["max_tokens"] == 8192
assert body["agent"]["timezone"] == "UTC"
assert body["agent"]["timezone"] == expected_timezone
assert "bot_name" not in body["agent"]
assert "bot_icon" not in body["agent"]
assert body["agent"]["tool_hint_max_length"] == 40
+20 -2
View File
@@ -2,11 +2,12 @@
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING, Any, ClassVar, Literal
from typing import TYPE_CHECKING, Any, ClassVar, Literal, cast
from pydantic import AliasChoices, ConfigDict, Field, field_validator, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
from nanobot.config.timezone import detect_system_timezone
from nanobot.config_base import Base
from nanobot.cron.types import CronSchedule
@@ -140,7 +141,8 @@ class AgentDefaults(Base):
serialization_alias="toolHintMaxLength",
) # Max characters for tool hint display (e.g. "$ cd …/project && npm test")
reasoning_effort: str | None = None # low / medium / high / xhigh / max / adaptive / none — LLM thinking effort; None preserves the provider default
timezone: str = "UTC" # IANA timezone, e.g. "Asia/Shanghai", "America/New_York"
timezone: str = "UTC" # Effective IANA timezone, e.g. "Asia/Shanghai"
timezone_mode: Literal["auto", "manual"] = "auto"
bot_name: str = "nanobot" # Display name shown in CLI prompts (e.g. "{name} is thinking...")
bot_icon: str = "🐈" # Short icon (emoji or text) shown next to the bot name in CLI; "" to omit
unified_session: bool = False # Share one session across all channels (single-user multi-device)
@@ -164,6 +166,22 @@ class AgentDefaults(Base):
) # Consolidation target ratio (0.5 = 50% of budget retained after compression)
dream: DreamConfig = Field(default_factory=DreamConfig)
@model_validator(mode="before")
@classmethod
def resolve_timezone(cls, value: object) -> object:
"""Detect new defaults server-side while preserving configured timezones."""
if not isinstance(value, dict):
return value
data = dict(cast(dict[str, object], value))
timezone_mode = data.get("timezoneMode", data.get("timezone_mode"))
if timezone_mode is None:
timezone_mode = "manual" if "timezone" in data else "auto"
data["timezoneMode"] = timezone_mode
if timezone_mode == "auto":
data["timezone"] = detect_system_timezone()
return data
@field_validator("timezone")
@classmethod
def validate_timezone(cls, value: str) -> str:
+19
View File
@@ -0,0 +1,19 @@
"""Backend timezone detection for automatic agent defaults."""
from zoneinfo import ZoneInfo
from tzlocal import get_localzone_name
_UTC_ALIASES = frozenset(
{"Etc/GMT", "Etc/UTC", "GMT", "GMT0", "Greenwich", "UCT", "Universal", "Zulu"}
)
def detect_system_timezone() -> str:
"""Return the host's IANA timezone, falling back safely to UTC."""
try:
timezone = get_localzone_name()
ZoneInfo(timezone)
except Exception:
return "UTC"
return "UTC" if timezone in _UTC_ALIASES else timezone
+4 -2
View File
@@ -1399,10 +1399,12 @@ def update_agent_settings(query: QueryParams) -> dict[str, Any]:
ZoneInfo(timezone)
except Exception:
raise WebUISettingsError("invalid timezone") from None
if defaults.timezone != timezone:
timezone_changed = defaults.timezone != timezone
if timezone_changed or defaults.timezone_mode != "manual":
defaults.timezone = timezone
defaults.timezone_mode = "manual"
changed = True
restart_required = True
restart_required = timezone_changed
tool_hint_max_length = _query_first_alias(
query,