nanobot/nanobot/webui/nanobot_features_api.py
chengyongru 5283ceae85
Add optional Nanobot plugin controls (#4396)
* feat: add optional nanobot features

* test: update azure install hint expectation

* fix: validate optional feature extras

maintainer edit: verify requested dependency extras before treating optional features as installed, propagate restart state from feature enablement, and align docs with the new plugins enable command.

* fix: bound optional feature installs

maintainer edit: make optional feature installs time out as a normal install failure instead of leaving the WebUI or CLI action waiting indefinitely.

* feat: slim optional channel dependencies

* fix: log optional install commands

* fix(webui): gate remote feature installs

* docs: clarify webhook plugin example

* fix(webui): harden optional feature installs

* fix: install optional deps without package fallback

* fix(cli): refine plugin feature controls

* fix(webui): count enabled nanobot features

* fix(webui): allow slow feature install routes

* fix(webui): allow disabling websocket channel

* fix(plugins): simplify optional feature controls

* fix(webui): polish apps catalog states

* fix(webui): confirm nanobot support installs

* fix(webui): polish nanobot install dialog

* fix(webui): suppress empty websocket handshakes

* fix(webui): clarify apps plugin summary

* fix(webui): localize workspace access copy

* fix(plugins): polish optional feature controls (#4691)

---------

Co-authored-by: Xubin Ren <52506698+Re-bin@users.noreply.github.com>
2026-07-03 18:17:52 +08:00

41 lines
1.2 KiB
Python

"""Nanobot optional feature helpers for WebUI Settings."""
from __future__ import annotations
from typing import Any
from nanobot.optional_features import (
OptionalFeatureError,
disable_optional_feature,
enable_optional_feature,
optional_features_payload,
)
from nanobot.webui.http_utils import query_first
QueryParams = dict[str, list[str]]
def nanobot_features_payload() -> dict[str, Any]:
return optional_features_payload()
def nanobot_features_action(
action: str,
query: QueryParams,
*,
allow_install: bool = True,
) -> dict[str, Any]:
name = (query_first(query, "name") or "").strip()
if not name:
raise OptionalFeatureError("missing feature name")
if action == "enable":
return enable_optional_feature(name, allow_install=allow_install)
if action == "disable":
if name == "websocket":
raise OptionalFeatureError(
"The WebUI websocket channel cannot be disabled from WebUI. "
"Use `nanobot plugins disable websocket` from a terminal if you need to disable it.",
status=400,
)
return disable_optional_feature(name)
raise OptionalFeatureError(f"unknown feature action '{action}'", status=404)