feat: add QR login and browser-backed web tools
This commit is contained in:
@@ -31,6 +31,7 @@ class AccountConfig:
|
||||
no_updates: bool = False
|
||||
takeout: bool = False
|
||||
hide_password: bool = False
|
||||
use_qr: bool = False
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
@@ -69,6 +70,8 @@ class AiConfig:
|
||||
max_tool_rounds: int = 16
|
||||
brave_api_key: str | None = None
|
||||
brave_timeout_seconds: float = 10.0
|
||||
web_page_timeout_seconds: float = 45.0
|
||||
web_page_max_chars: int = 60_000
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
@@ -93,6 +96,20 @@ def _parse_int(value: Any, *, field_name: str) -> int:
|
||||
raise ValueError(f"{field_name} must be an integer") from exc
|
||||
|
||||
|
||||
def _parse_bool(value: Any, *, field_name: str) -> bool:
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
if isinstance(value, str):
|
||||
normalized = value.strip().lower()
|
||||
if normalized in {"1", "true", "yes", "on"}:
|
||||
return True
|
||||
if normalized in {"0", "false", "no", "off"}:
|
||||
return False
|
||||
if isinstance(value, int):
|
||||
return bool(value)
|
||||
raise ValueError(f"{field_name} must be a boolean")
|
||||
|
||||
|
||||
def _parse_float(value: Any, *, field_name: str) -> float:
|
||||
try:
|
||||
return float(value)
|
||||
@@ -206,6 +223,14 @@ def _parse_ai_config(raw: Any) -> AiConfig:
|
||||
raw_config.get("brave_timeout_seconds", 10),
|
||||
field_name="ai.brave_timeout_seconds",
|
||||
)
|
||||
web_page_timeout_seconds = _parse_float(
|
||||
raw_config.get("web_page_timeout_seconds", 45),
|
||||
field_name="ai.web_page_timeout_seconds",
|
||||
)
|
||||
web_page_max_chars = _parse_int(
|
||||
raw_config.get("web_page_max_chars", 60_000),
|
||||
field_name="ai.web_page_max_chars",
|
||||
)
|
||||
|
||||
raw_brave_key = raw_config.get("brave_api_key")
|
||||
brave_api_key = str(raw_brave_key).strip() if raw_brave_key is not None else None
|
||||
@@ -234,6 +259,16 @@ def _parse_ai_config(raw: Any) -> AiConfig:
|
||||
os.environ["BRAVE_SEARCH_TIMEOUT_SECONDS"],
|
||||
field_name="BRAVE_SEARCH_TIMEOUT_SECONDS",
|
||||
)
|
||||
if os.environ.get("AI_WEB_PAGE_TIMEOUT_SECONDS") is not None:
|
||||
web_page_timeout_seconds = _parse_float(
|
||||
os.environ["AI_WEB_PAGE_TIMEOUT_SECONDS"],
|
||||
field_name="AI_WEB_PAGE_TIMEOUT_SECONDS",
|
||||
)
|
||||
if os.environ.get("AI_WEB_PAGE_MAX_CHARS") is not None:
|
||||
web_page_max_chars = _parse_int(
|
||||
os.environ["AI_WEB_PAGE_MAX_CHARS"],
|
||||
field_name="AI_WEB_PAGE_MAX_CHARS",
|
||||
)
|
||||
|
||||
if max_context_messages < 0:
|
||||
raise ValueError("ai.max_context_messages must not be negative")
|
||||
@@ -243,6 +278,10 @@ def _parse_ai_config(raw: Any) -> AiConfig:
|
||||
raise ValueError("ai.max_tool_rounds must be greater than zero")
|
||||
if brave_timeout_seconds <= 0:
|
||||
raise ValueError("ai.brave_timeout_seconds must be greater than zero")
|
||||
if web_page_timeout_seconds <= 0:
|
||||
raise ValueError("ai.web_page_timeout_seconds must be greater than zero")
|
||||
if web_page_max_chars < 1:
|
||||
raise ValueError("ai.web_page_max_chars must be greater than zero")
|
||||
|
||||
return AiConfig(
|
||||
glm=glm,
|
||||
@@ -252,6 +291,8 @@ def _parse_ai_config(raw: Any) -> AiConfig:
|
||||
max_tool_rounds=max_tool_rounds,
|
||||
brave_api_key=brave_api_key,
|
||||
brave_timeout_seconds=brave_timeout_seconds,
|
||||
web_page_timeout_seconds=web_page_timeout_seconds,
|
||||
web_page_max_chars=web_page_max_chars,
|
||||
)
|
||||
|
||||
|
||||
@@ -314,6 +355,10 @@ def _parse_accounts(raw_accounts: Any, *, default_api_id: int | None, default_ap
|
||||
no_updates=bool(raw_account.get("no_updates", False)),
|
||||
takeout=bool(raw_account.get("takeout", False)),
|
||||
hide_password=bool(raw_account.get("hide_password", False)),
|
||||
use_qr=_parse_bool(
|
||||
raw_account.get("use_qr", False),
|
||||
field_name=f"accounts[{index}].use_qr",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user