diff --git a/CHANGELOG.md b/CHANGELOG.md index 915c566..d45d22d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ - **`build_companion_prompt()` 未标记已注入**:读取 uninjected ruminations 后调用 `mark_injected(ids)`,避免重复注入 - **`scheduler/tasks.py` 导入路径错误**:`from .engine.context_injection` → `from ..engine.context_injection` +- **SAN 白名单私聊 scope**:SAN 群分析会跳过 `private_` scope,避免将私聊 ID 当作群号解析 #### Changed diff --git a/cognition/san.py b/cognition/san.py index 4b5bbc8..46fbc8f 100644 --- a/cognition/san.py +++ b/cognition/san.py @@ -194,8 +194,9 @@ async def _get_listened_groups(self): # 方式1: 白名单配置 whitelist = self.plugin.cfg.target_scopes if whitelist: - logger.debug(f"[SAN] 使用白名单群列表: {whitelist}") - return whitelist + groups = [g for g in whitelist if not str(g).startswith("private_")] + logger.debug(f"[SAN] 使用白名单群列表 (已过滤私聊): {groups}") + return groups # 方式2: eavesdropping get_active_scopes() eavesdropping = getattr(self.plugin, "eavesdropping", None) if eavesdropping and hasattr(eavesdropping, "get_active_scopes"): @@ -249,6 +250,9 @@ async def _analyze_group(self, group_id: str) -> dict | None: async def _fetch_group_messages(self, group_id: str) -> list: """通过 NapCat API 获取群消息""" + if not group_id or str(group_id).startswith("private_"): + logger.debug(f"[SAN] 忽略私聊会话消息获取: {group_id}") + return [] try: platform_insts = self.plugin.context.platform_manager.platform_insts if not platform_insts: diff --git a/tests/test_san.py b/tests/test_san.py index 62ad5f2..9d6f9c6 100644 --- a/tests/test_san.py +++ b/tests/test_san.py @@ -11,6 +11,29 @@ class SANSystemTests(IsolatedAsyncioTestCase): + async def test_get_listened_groups_filters_private_scopes_from_whitelist(self): + plugin = SimpleNamespace( + cfg=SimpleNamespace(target_scopes=["7001", "private_1001", "7002"]), + ) + san = SANSystem(plugin) + + groups = await san._get_listened_groups() + + self.assertEqual(groups, ["7001", "7002"]) + + async def test_fetch_group_messages_ignores_private_scope_without_bot_call(self): + bot = SimpleNamespace(call_action=AsyncMock()) + plugin = SimpleNamespace( + cfg=SimpleNamespace(san_msg_count_per_group=50), + context=SimpleNamespace(platform_manager=SimpleNamespace(platform_insts=[SimpleNamespace(get_client=lambda: bot)])), + ) + san = SANSystem(plugin) + + messages = await san._fetch_group_messages("private_1001") + + self.assertEqual(messages, []) + bot.call_action.assert_not_called() + async def test_llm_analyze_uses_group_umo_for_provider_lookup(self): provider = SimpleNamespace( text_chat=AsyncMock(