From 19ffb8822d8fc130054af463d9a271c235b00b80 Mon Sep 17 00:00:00 2001 From: Xnbi Date: Fri, 24 Apr 2026 05:12:19 +0800 Subject: [PATCH] fix(gateway): default Slack tool_progress to off Slack Bolt posts are not editable like CLI spinners; medium-tier new still emitted a permanent line per tool start (issue #14663). - Built-in slack default: off; other tier-2 platforms unchanged. - Adjust /verbose isolation test for off to new cycle. - Migration tests: read/write config.yaml as UTF-8 (Windows locale). --- gateway/display_config.py | 4 +++- tests/gateway/test_display_config.py | 18 ++++++++++++------ tests/gateway/test_verbose_command.py | 6 +++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/gateway/display_config.py b/gateway/display_config.py index 9375266ca..b2f1ab3b1 100644 --- a/gateway/display_config.py +++ b/gateway/display_config.py @@ -75,7 +75,9 @@ _PLATFORM_DEFAULTS: dict[str, dict[str, Any]] = { "discord": _TIER_HIGH, # Tier 2 — edit support, often customer/workspace channels - "slack": _TIER_MEDIUM, + # Slack: tool_progress off by default — Bolt posts cannot be edited like CLI; + # "new"/"all" spam permanent lines in channels (hermes-agent#14663). + "slack": {**_TIER_MEDIUM, "tool_progress": "off"}, "mattermost": _TIER_MEDIUM, "matrix": _TIER_MEDIUM, "feishu": _TIER_MEDIUM, diff --git a/tests/gateway/test_display_config.py b/tests/gateway/test_display_config.py index c9ad51280..d8c0cae0d 100644 --- a/tests/gateway/test_display_config.py +++ b/tests/gateway/test_display_config.py @@ -186,12 +186,18 @@ class TestPlatformDefaults: assert resolve_display_setting({}, plat, "tool_progress") == "all", plat def test_medium_tier_platforms(self): - """Slack, Mattermost, Matrix default to 'new' tool progress.""" + """Mattermost, Matrix, Feishu, WhatsApp default to 'new' tool progress.""" from gateway.display_config import resolve_display_setting - for plat in ("slack", "mattermost", "matrix", "feishu", "whatsapp"): + for plat in ("mattermost", "matrix", "feishu", "whatsapp"): assert resolve_display_setting({}, plat, "tool_progress") == "new", plat + def test_slack_defaults_tool_progress_off(self): + """Slack defaults to quiet tool progress (permanent chat noise otherwise).""" + from gateway.display_config import resolve_display_setting + + assert resolve_display_setting({}, "slack", "tool_progress") == "off" + def test_low_tier_platforms(self): """Signal, BlueBubbles, etc. default to 'off' tool progress.""" from gateway.display_config import resolve_display_setting @@ -276,7 +282,7 @@ class TestConfigMigration: }, }, } - config_path.write_text(yaml.dump(config)) + config_path.write_text(yaml.dump(config), encoding="utf-8") monkeypatch.setenv("HERMES_HOME", str(tmp_path)) # Re-import to pick up the new HERMES_HOME @@ -286,7 +292,7 @@ class TestConfigMigration: result = cfg_mod.migrate_config(interactive=False, quiet=True) # Re-read config - updated = yaml.safe_load(config_path.read_text()) + updated = yaml.safe_load(config_path.read_text(encoding="utf-8")) platforms = updated.get("display", {}).get("platforms", {}) assert platforms.get("signal", {}).get("tool_progress") == "off" assert platforms.get("telegram", {}).get("tool_progress") == "all" @@ -303,7 +309,7 @@ class TestConfigMigration: "platforms": {"telegram": {"tool_progress": "verbose"}}, }, } - config_path.write_text(yaml.dump(config)) + config_path.write_text(yaml.dump(config), encoding="utf-8") monkeypatch.setenv("HERMES_HOME", str(tmp_path)) import importlib @@ -311,7 +317,7 @@ class TestConfigMigration: importlib.reload(cfg_mod) cfg_mod.migrate_config(interactive=False, quiet=True) - updated = yaml.safe_load(config_path.read_text()) + updated = yaml.safe_load(config_path.read_text(encoding="utf-8")) # Existing "verbose" should NOT be overwritten by legacy "off" assert updated["display"]["platforms"]["telegram"]["tool_progress"] == "verbose" diff --git a/tests/gateway/test_verbose_command.py b/tests/gateway/test_verbose_command.py index c34167b2e..c3743e591 100644 --- a/tests/gateway/test_verbose_command.py +++ b/tests/gateway/test_verbose_command.py @@ -134,7 +134,7 @@ class TestVerboseCommand: """Cycling /verbose on Telegram doesn't change Slack's setting. Without a global tool_progress, each platform uses its built-in - default: Telegram = 'all' (high tier), Slack = 'new' (medium tier). + default: Telegram = 'all' (high tier), Slack = 'off' (quiet Slack default). """ hermes_home = tmp_path / "hermes" hermes_home.mkdir() @@ -161,8 +161,8 @@ class TestVerboseCommand: platforms = saved["display"]["platforms"] # Telegram: all -> verbose (high tier default = all) assert platforms["telegram"]["tool_progress"] == "verbose" - # Slack: new -> all (medium tier default = new, cycle to all) - assert platforms["slack"]["tool_progress"] == "all" + # Slack: off -> new (first /verbose cycle from quiet default) + assert platforms["slack"]["tool_progress"] == "new" @pytest.mark.asyncio async def test_no_config_file_returns_disabled(self, tmp_path, monkeypatch):