fix(gateway): coerce tool_progress_command as a real boolean

This commit is contained in:
johnncenae 2026-04-27 14:58:56 +03:00 committed by Teknium
parent a94841eaa0
commit bb706c3f38
4 changed files with 45 additions and 3 deletions

View file

@ -8351,7 +8351,10 @@ class GatewayRunner:
# --- check config gate ------------------------------------------------
try:
user_config = _load_gateway_config()
gate_enabled = cfg_get(user_config, "display", "tool_progress_command", default=False)
gate_enabled = is_truthy_value(
cfg_get(user_config, "display", "tool_progress_command"),
default=False,
)
except Exception:
gate_enabled = False
@ -11302,7 +11305,10 @@ class GatewayRunner:
tool_progress_hint_gateway,
)
_cfg = _load_gateway_config()
gate_on = bool(cfg_get(_cfg, "display", "tool_progress_command", default=False))
gate_on = is_truthy_value(
cfg_get(_cfg, "display", "tool_progress_command"),
default=False,
)
if gate_on and not is_seen(_cfg, TOOL_PROGRESS_FLAG):
long_tool_hint_fired[0] = True
progress_queue.put(tool_progress_hint_gateway())

View file

@ -19,6 +19,8 @@ from collections.abc import Callable, Mapping
from dataclasses import dataclass
from typing import Any
from utils import is_truthy_value
# prompt_toolkit is an optional CLI dependency — only needed for
# SlashCommandCompleter and SlashCommandAutoSuggest. Gateway and test
# environments that lack it must still be able to import this module
@ -371,7 +373,7 @@ def _resolve_config_gates() -> set[str]:
else:
val = None
break
if val:
if is_truthy_value(val, default=False):
result.add(cmd.name)
return result

View file

@ -85,6 +85,25 @@ class TestVerboseCommand:
saved = yaml.safe_load(config_path.read_text(encoding="utf-8"))
assert saved["display"]["platforms"]["telegram"]["tool_progress"] == "verbose"
@pytest.mark.asyncio
async def test_quoted_false_keeps_command_disabled(self, tmp_path, monkeypatch):
"""Quoted false must not enable the /verbose gateway command."""
hermes_home = tmp_path / "hermes"
hermes_home.mkdir()
config_path = hermes_home / "config.yaml"
config_path.write_text(
'display:\n tool_progress_command: "false"\n tool_progress: all\n',
encoding="utf-8",
)
monkeypatch.setattr(gateway_run, "_hermes_home", hermes_home)
runner = _make_runner()
result = await runner._handle_verbose_command(_make_event())
assert "not enabled" in result.lower()
assert "tool_progress_command" in result
@pytest.mark.asyncio
async def test_cycles_through_all_modes(self, tmp_path, monkeypatch):
"""Calling /verbose repeatedly cycles through all four modes."""

View file

@ -405,6 +405,21 @@ class TestGatewayConfigGate:
joined = "\n".join(lines)
assert "`/verbose" in joined
def test_config_gate_quoted_false_stays_disabled_everywhere(self, tmp_path, monkeypatch):
"""Quoted false must not enable config-gated gateway commands."""
config_file = tmp_path / "config.yaml"
config_file.write_text('display:\n tool_progress_command: "false"\n')
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
lines = gateway_help_lines()
joined = "\n".join(lines)
names = {name for name, _ in telegram_bot_commands()}
mapping = slack_subcommand_map()
assert "`/verbose" not in joined
assert "verbose" not in names
assert "verbose" not in mapping
def test_config_gate_excluded_from_telegram_when_off(self, tmp_path, monkeypatch):
config_file = tmp_path / "config.yaml"
config_file.write_text("display:\n tool_progress_command: false\n")