mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-24 05:41:40 +00:00
feat(discord): default history backfill on, expand to per-user + threads
Follow-up to snav's PR #25463 contribution: flip default to on, broaden scope so backfill fires whenever require_mention gates the bot (not just shared-session channels). Why: - The mention-gate creates a session-transcript gap regardless of whether the channel is shared or per-user. In per-user sessions, Alice's session is still missing other participants' messages and her own pre-mention messages — backfill fills both gaps. - Threads naturally scope to thread-only history because discord.py's channel.history() on a thread returns only that thread's messages. - DMs still skip — every DM triggers the bot, so the session transcript is already complete. Changes: - hermes_cli/config.py: discord.history_backfill default → true - gateway/platforms/discord.py: drop the _is_shared gate, keep _is_dm skip and _needed_mention gate; env var DISCORD_HISTORY_BACKFILL default → 'true' - cli-config.yaml.example + website docs: update defaults and prose; add the DISCORD_HISTORY_BACKFILL / _LIMIT env var rows that were documented in the PR description but missing from the env-var table - tests/gateway/test_discord_free_response.py: - flip test_discord_per_user_channel_does_not_backfill → test_discord_per_user_channel_backfills_too (new behavior) - add test_discord_dm_does_not_backfill (DM skip is invariant) - give FakeThread a no-op history() so existing thread tests don't hit a fake discord.Forbidden when backfill now fires on threads too Tests: 160/160 in target files; 400/400 across all tests/gateway/ -k discord.
This commit is contained in:
parent
e84fe483bc
commit
4abfb6bc24
5 changed files with 80 additions and 20 deletions
|
|
@ -87,6 +87,12 @@ class FakeThread:
|
|||
self.guild = getattr(parent, "guild", None) or SimpleNamespace(name=guild_name)
|
||||
self.topic = None
|
||||
|
||||
def history(self, *, limit, before, after=None, oldest_first=None):
|
||||
async def _iter():
|
||||
return
|
||||
yield
|
||||
return _iter()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def adapter(monkeypatch):
|
||||
|
|
@ -820,7 +826,9 @@ async def test_discord_shared_channel_backfill_prepends_context(adapter, monkeyp
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_discord_per_user_channel_does_not_backfill(adapter, monkeypatch):
|
||||
async def test_discord_per_user_channel_backfills_too(adapter, monkeypatch):
|
||||
"""Per-user sessions also benefit from backfill: Alice's session is missing
|
||||
other-channel-participants' context and her own pre-mention messages."""
|
||||
monkeypatch.setenv("DISCORD_REQUIRE_MENTION", "true")
|
||||
monkeypatch.delenv("DISCORD_FREE_RESPONSE_CHANNELS", raising=False)
|
||||
monkeypatch.setenv("DISCORD_AUTO_THREAD", "false")
|
||||
|
|
@ -837,9 +845,42 @@ async def test_discord_per_user_channel_does_not_backfill(adapter, monkeypatch):
|
|||
|
||||
await adapter._handle_message(message)
|
||||
|
||||
adapter._fetch_channel_context.assert_not_awaited()
|
||||
adapter._fetch_channel_context.assert_awaited_once()
|
||||
event = adapter.handle_message.await_args.args[0]
|
||||
assert event.text == "hello with mention"
|
||||
assert event.channel_context is None
|
||||
assert event.channel_context == "[Recent channel messages]\n[Alice] context"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_discord_dm_does_not_backfill(adapter, monkeypatch):
|
||||
"""DMs skip backfill — every DM triggers the bot, so there's no mention gap."""
|
||||
monkeypatch.setenv("DISCORD_REQUIRE_MENTION", "true")
|
||||
adapter.config.extra["history_backfill"] = True
|
||||
adapter._fetch_channel_context = AsyncMock(return_value="[Recent channel messages]\n[Alice] context")
|
||||
|
||||
bot_user = adapter._client.user
|
||||
dm_channel = SimpleNamespace(
|
||||
id=999,
|
||||
name=None,
|
||||
guild=None,
|
||||
topic=None,
|
||||
)
|
||||
# Make isinstance(channel, discord.DMChannel) return True
|
||||
monkeypatch.setattr(
|
||||
discord_platform.discord, "DMChannel", type(dm_channel), raising=False,
|
||||
)
|
||||
|
||||
message = make_message(
|
||||
channel=dm_channel,
|
||||
content="hello in DM",
|
||||
mentions=[],
|
||||
)
|
||||
|
||||
await adapter._handle_message(message)
|
||||
|
||||
adapter._fetch_channel_context.assert_not_awaited()
|
||||
if adapter.handle_message.await_args is not None:
|
||||
event = adapter.handle_message.await_args.args[0]
|
||||
assert event.channel_context is None
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue