fix(cli): allow empty strings and falsy values in config set

`hermes config set KEY ""` and `hermes config set KEY 0` were rejected
because the guard used `not value` which is truthy for empty strings,
zero, and False. Changed to `value is None` so only truly missing
arguments are rejected.

Closes #4277

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dakota Secula-Rosell 2026-03-31 13:32:54 -04:00 committed by Teknium
parent 49d7210fed
commit c1606aed69
2 changed files with 42 additions and 2 deletions

View file

@ -2040,7 +2040,7 @@ def config_command(args):
elif subcmd == "set": elif subcmd == "set":
key = getattr(args, 'key', None) key = getattr(args, 'key', None)
value = getattr(args, 'value', None) value = getattr(args, 'value', None)
if not key or not value: if not key or value is None:
print("Usage: hermes config set <key> <value>") print("Usage: hermes config set <key> <value>")
print() print()
print("Examples:") print("Examples:")

View file

@ -1,12 +1,13 @@
"""Tests for set_config_value — verifying secrets route to .env and config to config.yaml.""" """Tests for set_config_value — verifying secrets route to .env and config to config.yaml."""
import argparse
import os import os
from pathlib import Path from pathlib import Path
from unittest.mock import patch, call from unittest.mock import patch, call
import pytest import pytest
from hermes_cli.config import set_config_value from hermes_cli.config import set_config_value, config_command
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
@ -125,3 +126,42 @@ class TestConfigYamlRouting:
"TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACE=true" in env_content "TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACE=true" in env_content
or "TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACE=True" in env_content or "TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACE=True" in env_content
) )
# ---------------------------------------------------------------------------
# Empty / falsy values — regression tests for #4277
# ---------------------------------------------------------------------------
class TestFalsyValues:
"""config set should accept empty strings and falsy values like '0'."""
def test_empty_string_routes_to_env(self, _isolated_hermes_home):
"""Blanking an API key should write an empty value to .env."""
set_config_value("OPENROUTER_API_KEY", "")
env_content = _read_env(_isolated_hermes_home)
assert "OPENROUTER_API_KEY=" in env_content
def test_empty_string_routes_to_config(self, _isolated_hermes_home):
"""Blanking a config key should write an empty string to config.yaml."""
set_config_value("model", "")
config = _read_config(_isolated_hermes_home)
assert "model: ''" in config or "model: \"\"" in config
def test_zero_routes_to_config(self, _isolated_hermes_home):
"""Setting a config key to '0' should write 0 to config.yaml."""
set_config_value("verbose", "0")
config = _read_config(_isolated_hermes_home)
assert "verbose: 0" in config
def test_config_command_rejects_missing_value(self):
"""config set with no value arg (None) should still exit."""
args = argparse.Namespace(config_command="set", key="model", value=None)
with pytest.raises(SystemExit):
config_command(args)
def test_config_command_accepts_empty_string(self, _isolated_hermes_home):
"""config set KEY '' should not exit — it should set the value."""
args = argparse.Namespace(config_command="set", key="model", value="")
config_command(args)
config = _read_config(_isolated_hermes_home)
assert "model" in config