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>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import asyncio
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
@@ -24,6 +25,10 @@ from nanobot.channels.matrix import (
|
||||
_ROOM_SEND_UNSET = object()
|
||||
|
||||
|
||||
def test_default_e2ee_matches_platform_support() -> None:
|
||||
assert MatrixConfig().e2ee_enabled is (sys.platform != "win32")
|
||||
|
||||
|
||||
class _DummyTask:
|
||||
def __init__(self) -> None:
|
||||
self.cancelled = False
|
||||
@@ -293,7 +298,7 @@ async def test_start_skips_load_store_when_device_id_missing(
|
||||
"nanobot.channels.matrix.asyncio.create_task", _fake_create_task
|
||||
)
|
||||
|
||||
channel = MatrixChannel(_make_config(device_id=""), MessageBus())
|
||||
channel = MatrixChannel(_make_config(device_id="", e2ee_enabled=True), MessageBus())
|
||||
await channel.start()
|
||||
|
||||
assert len(clients) == 1
|
||||
@@ -320,7 +325,7 @@ async def test_register_event_callbacks_uses_media_base_filter() -> None:
|
||||
|
||||
|
||||
def test_register_to_device_callbacks_when_sas_verification_enabled() -> None:
|
||||
channel = MatrixChannel(_make_config(sas_verification=True), MessageBus())
|
||||
channel = MatrixChannel(_make_config(e2ee_enabled=True, sas_verification=True), MessageBus())
|
||||
client = _FakeAsyncClient("", "", "", None)
|
||||
channel.client = client
|
||||
|
||||
@@ -348,7 +353,11 @@ def test_register_to_device_callbacks_skips_when_e2ee_disabled() -> None:
|
||||
async def test_sas_verification_start_accepts_allowed_sender(monkeypatch) -> None:
|
||||
_patch_key_verification_events(monkeypatch)
|
||||
channel = MatrixChannel(
|
||||
_make_config(allow_from=["@alice:matrix.org"], sas_verification=True),
|
||||
_make_config(
|
||||
allow_from=["@alice:matrix.org"],
|
||||
e2ee_enabled=True,
|
||||
sas_verification=True,
|
||||
),
|
||||
MessageBus(),
|
||||
)
|
||||
client = _FakeAsyncClient("", "", "", None)
|
||||
@@ -367,7 +376,11 @@ async def test_sas_verification_start_accepts_allowed_sender(monkeypatch) -> Non
|
||||
async def test_sas_verification_ignores_denied_sender(monkeypatch) -> None:
|
||||
_patch_key_verification_events(monkeypatch)
|
||||
channel = MatrixChannel(
|
||||
_make_config(allow_from=["@alice:matrix.org"], sas_verification=True),
|
||||
_make_config(
|
||||
allow_from=["@alice:matrix.org"],
|
||||
e2ee_enabled=True,
|
||||
sas_verification=True,
|
||||
),
|
||||
MessageBus(),
|
||||
)
|
||||
client = _FakeAsyncClient("", "", "", None)
|
||||
@@ -403,7 +416,11 @@ async def test_sas_verification_ignores_when_disabled(monkeypatch) -> None:
|
||||
async def test_sas_verification_key_confirms_allowed_sender(monkeypatch) -> None:
|
||||
_patch_key_verification_events(monkeypatch)
|
||||
channel = MatrixChannel(
|
||||
_make_config(allow_from=["@alice:matrix.org"], sas_verification=True),
|
||||
_make_config(
|
||||
allow_from=["@alice:matrix.org"],
|
||||
e2ee_enabled=True,
|
||||
sas_verification=True,
|
||||
),
|
||||
MessageBus(),
|
||||
)
|
||||
client = _FakeAsyncClient("", "", "", None)
|
||||
@@ -1203,7 +1220,7 @@ async def test_on_media_message_handles_decrypt_error(monkeypatch, tmp_path) ->
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_clears_typing_after_send() -> None:
|
||||
channel = MatrixChannel(_make_config(), MessageBus())
|
||||
channel = MatrixChannel(_make_config(e2ee_enabled=True), MessageBus())
|
||||
client = _FakeAsyncClient("", "", "", None)
|
||||
channel.client = client
|
||||
|
||||
|
||||
Reference in New Issue
Block a user