mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-05-22 17:42:24 +00:00
fix(channels): address progress override review
This commit is contained in:
parent
0b111a0e0c
commit
a0443e8f9e
@ -7,6 +7,7 @@ from pathlib import Path
|
|||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
from pydantic.alias_generators import to_camel
|
||||||
|
|
||||||
from nanobot.bus.events import OutboundMessage
|
from nanobot.bus.events import OutboundMessage
|
||||||
from nanobot.bus.queue import MessageBus
|
from nanobot.bus.queue import MessageBus
|
||||||
@ -28,21 +29,8 @@ def _default_webui_dist() -> Path | None:
|
|||||||
return candidate if candidate.is_dir() else None
|
return candidate if candidate.is_dir() else None
|
||||||
|
|
||||||
|
|
||||||
def _snake_to_camel(value: str) -> str:
|
|
||||||
head, *tail = value.split("_")
|
|
||||||
return head + "".join(part.capitalize() for part in tail)
|
|
||||||
|
|
||||||
|
|
||||||
def _coerce_optional_bool(value: Any) -> bool | None:
|
def _coerce_optional_bool(value: Any) -> bool | None:
|
||||||
if isinstance(value, bool):
|
return value if isinstance(value, bool) else None
|
||||||
return value
|
|
||||||
if isinstance(value, str):
|
|
||||||
normalized = value.strip().lower()
|
|
||||||
if normalized in {"true", "1", "yes", "on"}:
|
|
||||||
return True
|
|
||||||
if normalized in {"false", "0", "no", "off"}:
|
|
||||||
return False
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
# Retry delays for message sending (exponential backoff: 1s, 2s, 4s)
|
# Retry delays for message sending (exponential backoff: 1s, 2s, 4s)
|
||||||
@ -161,7 +149,7 @@ class ChannelManager:
|
|||||||
if section is None:
|
if section is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
camel_key = _snake_to_camel(key)
|
camel_key = to_camel(key)
|
||||||
if isinstance(section, dict):
|
if isinstance(section, dict):
|
||||||
value = section.get(key, section.get(camel_key))
|
value = section.get(key, section.get(camel_key))
|
||||||
return _coerce_optional_bool(value)
|
return _coerce_optional_bool(value)
|
||||||
|
|||||||
@ -325,6 +325,32 @@ class TestProgressFiltering:
|
|||||||
assert manager._should_send_progress("other", tool_hint=False) is True
|
assert manager._should_send_progress("other", tool_hint=False) is True
|
||||||
assert manager._should_send_progress("other", tool_hint=True) is False
|
assert manager._should_send_progress("other", tool_hint=True) is False
|
||||||
|
|
||||||
|
def test_progress_visibility_uses_snake_case_channel_overrides(self, manager):
|
||||||
|
manager.config.channels = ChannelsConfig.model_validate({
|
||||||
|
"sendProgress": True,
|
||||||
|
"sendToolHints": False,
|
||||||
|
"mock": {
|
||||||
|
"send_progress": False,
|
||||||
|
"send_tool_hints": True,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
assert manager._should_send_progress("mock", tool_hint=False) is False
|
||||||
|
assert manager._should_send_progress("mock", tool_hint=True) is True
|
||||||
|
|
||||||
|
def test_progress_visibility_ignores_non_bool_channel_overrides(self, manager):
|
||||||
|
manager.config.channels = ChannelsConfig.model_validate({
|
||||||
|
"sendProgress": True,
|
||||||
|
"sendToolHints": False,
|
||||||
|
"mock": {
|
||||||
|
"sendProgress": "false",
|
||||||
|
"sendToolHints": "true",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
assert manager._should_send_progress("mock", tool_hint=False) is True
|
||||||
|
assert manager._should_send_progress("mock", tool_hint=True) is False
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_channel_override_can_drop_progress_message(self, manager, bus):
|
async def test_channel_override_can_drop_progress_message(self, manager, bus):
|
||||||
manager.config.channels = ChannelsConfig.model_validate({
|
manager.config.channels = ChannelsConfig.model_validate({
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user