mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
Merge 1f844b9189 into 4fade39c90
This commit is contained in:
commit
05d0b06dad
3 changed files with 136 additions and 3 deletions
|
|
@ -941,6 +941,9 @@ def _apply_env_overrides(config: GatewayConfig) -> None:
|
|||
"account": signal_account,
|
||||
"ignore_stories": os.getenv("SIGNAL_IGNORE_STORIES", "true").lower() in ("true", "1", "yes"),
|
||||
})
|
||||
signal_notify_self = os.getenv("SIGNAL_NOTIFY_SELF", "").lower()
|
||||
if signal_notify_self in ("true", "1", "yes"):
|
||||
config.platforms[Platform.SIGNAL].extra["notify_self"] = True
|
||||
signal_home = os.getenv("SIGNAL_HOME_CHANNEL")
|
||||
if signal_home and Platform.SIGNAL in config.platforms:
|
||||
config.platforms[Platform.SIGNAL].home_channel = HomeChannel(
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@ class SignalAdapter(BasePlatformAdapter):
|
|||
self.http_url = extra.get("http_url", "http://127.0.0.1:8080").rstrip("/")
|
||||
self.account = extra.get("account", "")
|
||||
self.ignore_stories = extra.get("ignore_stories", True)
|
||||
self.notify_self = extra.get("notify_self", False)
|
||||
|
||||
# Parse allowlists — group policy is derived from presence of group allowlist
|
||||
group_allowed_str = os.getenv("SIGNAL_GROUP_ALLOWED_USERS", "")
|
||||
|
|
@ -729,7 +730,12 @@ class SignalAdapter(BasePlatformAdapter):
|
|||
if chat_id.startswith("group:"):
|
||||
params["groupId"] = chat_id[6:]
|
||||
else:
|
||||
params["recipient"] = [await self._resolve_recipient(chat_id)]
|
||||
recipient = await self._resolve_recipient(chat_id)
|
||||
params["recipient"] = [recipient]
|
||||
if self.notify_self and (
|
||||
recipient == self._account_normalized or chat_id == self._account_normalized
|
||||
):
|
||||
params["notifySelf"] = True
|
||||
|
||||
result = await self._rpc("send", params)
|
||||
|
||||
|
|
@ -841,7 +847,12 @@ class SignalAdapter(BasePlatformAdapter):
|
|||
if chat_id.startswith("group:"):
|
||||
params["groupId"] = chat_id[6:]
|
||||
else:
|
||||
params["recipient"] = [await self._resolve_recipient(chat_id)]
|
||||
recipient = await self._resolve_recipient(chat_id)
|
||||
params["recipient"] = [recipient]
|
||||
if self.notify_self and (
|
||||
recipient == self._account_normalized or chat_id == self._account_normalized
|
||||
):
|
||||
params["notifySelf"] = True
|
||||
|
||||
result = await self._rpc("send", params)
|
||||
if result is not None:
|
||||
|
|
@ -880,7 +891,12 @@ class SignalAdapter(BasePlatformAdapter):
|
|||
if chat_id.startswith("group:"):
|
||||
params["groupId"] = chat_id[6:]
|
||||
else:
|
||||
params["recipient"] = [await self._resolve_recipient(chat_id)]
|
||||
recipient = await self._resolve_recipient(chat_id)
|
||||
params["recipient"] = [recipient]
|
||||
if self.notify_self and (
|
||||
recipient == self._account_normalized or chat_id == self._account_normalized
|
||||
):
|
||||
params["notifySelf"] = True
|
||||
|
||||
result = await self._rpc("send", params)
|
||||
if result is not None:
|
||||
|
|
|
|||
|
|
@ -57,6 +57,30 @@ class TestSignalConfigLoading:
|
|||
assert sc.extra["http_url"] == "http://localhost:9090"
|
||||
assert sc.extra["account"] == "+15551234567"
|
||||
|
||||
def test_apply_env_overrides_signal_notify_self(self, monkeypatch):
|
||||
monkeypatch.setenv("SIGNAL_HTTP_URL", "http://localhost:9090")
|
||||
monkeypatch.setenv("SIGNAL_ACCOUNT", "+15551234567")
|
||||
monkeypatch.setenv("SIGNAL_NOTIFY_SELF", "true")
|
||||
|
||||
from gateway.config import GatewayConfig, _apply_env_overrides
|
||||
config = GatewayConfig()
|
||||
_apply_env_overrides(config)
|
||||
|
||||
sc = config.platforms[Platform.SIGNAL]
|
||||
assert sc.extra.get("notify_self") is True
|
||||
|
||||
def test_apply_env_overrides_signal_notify_self_disabled(self, monkeypatch):
|
||||
monkeypatch.setenv("SIGNAL_HTTP_URL", "http://localhost:9090")
|
||||
monkeypatch.setenv("SIGNAL_ACCOUNT", "+15551234567")
|
||||
monkeypatch.setenv("SIGNAL_NOTIFY_SELF", "false")
|
||||
|
||||
from gateway.config import GatewayConfig, _apply_env_overrides
|
||||
config = GatewayConfig()
|
||||
_apply_env_overrides(config)
|
||||
|
||||
sc = config.platforms[Platform.SIGNAL]
|
||||
assert "notify_self" not in sc.extra
|
||||
|
||||
def test_signal_not_loaded_without_both_vars(self, monkeypatch):
|
||||
monkeypatch.setenv("SIGNAL_HTTP_URL", "http://localhost:9090")
|
||||
# No SIGNAL_ACCOUNT
|
||||
|
|
@ -997,3 +1021,93 @@ class TestSignalTypingBackoff:
|
|||
|
||||
assert "+155****4567" not in adapter._typing_failures
|
||||
assert "+155****4567" not in adapter._typing_skip_until
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# notifySelf toggle for Note-to-Self bubble-side fix
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestSignalNotifySelf:
|
||||
"""Verify that notify_self=True adds notifySelf param for self-messages
|
||||
in text, image, and attachment sends, while leaving other chats untouched."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_to_self_adds_notifySelf_when_enabled(self, monkeypatch):
|
||||
adapter = _make_signal_adapter(monkeypatch, notify_self=True)
|
||||
mock_rpc, captured = _stub_rpc({"timestamp": 1234567890})
|
||||
adapter._rpc = mock_rpc
|
||||
adapter._stop_typing_indicator = AsyncMock()
|
||||
|
||||
result = await adapter.send(chat_id="+15551234567", content="hello self")
|
||||
assert result.success is True
|
||||
send_call = [c for c in captured if c["method"] == "send"][0]
|
||||
assert send_call["params"].get("notifySelf") is True
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_to_self_omits_notifySelf_when_disabled(self, monkeypatch):
|
||||
adapter = _make_signal_adapter(monkeypatch, notify_self=False)
|
||||
mock_rpc, captured = _stub_rpc({"timestamp": 1234567890})
|
||||
adapter._rpc = mock_rpc
|
||||
adapter._stop_typing_indicator = AsyncMock()
|
||||
|
||||
result = await adapter.send(chat_id="+15551234567", content="hello self")
|
||||
assert result.success is True
|
||||
send_call = [c for c in captured if c["method"] == "send"][0]
|
||||
assert "notifySelf" not in send_call["params"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_to_other_omits_notifySelf_even_when_enabled(self, monkeypatch):
|
||||
adapter = _make_signal_adapter(monkeypatch, notify_self=True)
|
||||
mock_rpc, captured = _stub_rpc({"timestamp": 1234567890})
|
||||
adapter._rpc = mock_rpc
|
||||
adapter._stop_typing_indicator = AsyncMock()
|
||||
|
||||
result = await adapter.send(chat_id="+15559999999", content="hello other")
|
||||
assert result.success is True
|
||||
send_call = [c for c in captured if c["method"] == "send"][0]
|
||||
assert "notifySelf" not in send_call["params"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_image_file_to_self_adds_notifySelf(self, monkeypatch, tmp_path):
|
||||
adapter = _make_signal_adapter(monkeypatch, notify_self=True)
|
||||
mock_rpc, captured = _stub_rpc({"timestamp": 1234567890})
|
||||
adapter._rpc = mock_rpc
|
||||
adapter._stop_typing_indicator = AsyncMock()
|
||||
|
||||
img_path = tmp_path / "chart.png"
|
||||
img_path.write_bytes(b"\x89PNG" + b"\x00" * 100)
|
||||
|
||||
result = await adapter.send_image_file(chat_id="+15551234567", image_path=str(img_path))
|
||||
assert result.success is True
|
||||
send_call = [c for c in captured if c["method"] == "send"][0]
|
||||
assert send_call["params"].get("notifySelf") is True
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_voice_to_self_adds_notifySelf(self, monkeypatch, tmp_path):
|
||||
adapter = _make_signal_adapter(monkeypatch, notify_self=True)
|
||||
mock_rpc, captured = _stub_rpc({"timestamp": 1234567890})
|
||||
adapter._rpc = mock_rpc
|
||||
adapter._stop_typing_indicator = AsyncMock()
|
||||
|
||||
audio_path = tmp_path / "note.ogg"
|
||||
audio_path.write_bytes(b"OggS" + b"\x00" * 100)
|
||||
|
||||
result = await adapter.send_voice(chat_id="+15551234567", audio_path=str(audio_path))
|
||||
assert result.success is True
|
||||
send_call = [c for c in captured if c["method"] == "send"][0]
|
||||
assert send_call["params"].get("notifySelf") is True
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_group_send_omits_notifySelf(self, monkeypatch, tmp_path):
|
||||
adapter = _make_signal_adapter(monkeypatch, notify_self=True)
|
||||
mock_rpc, captured = _stub_rpc({"timestamp": 1234567890})
|
||||
adapter._rpc = mock_rpc
|
||||
adapter._stop_typing_indicator = AsyncMock()
|
||||
|
||||
img_path = tmp_path / "chart.png"
|
||||
img_path.write_bytes(b"\x89PNG" + b"\x00" * 100)
|
||||
|
||||
result = await adapter.send_image_file(chat_id="group:abc123==", image_path=str(img_path))
|
||||
assert result.success is True
|
||||
send_call = [c for c in captured if c["method"] == "send"][0]
|
||||
assert "notifySelf" not in send_call["params"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue