mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 06:51:16 +08:00
fix(openclaw-migration): case-preserving brand rewrite + one-time ~/.openclaw residue banner (#16327)
Two related fixes for OpenClaw-residue problems after an OpenClaw→Hermes migration (especially migrations done via OpenClaw's own tool, which doesn't archive the source directory). 1. optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py: rebrand_text() was rewriting ~/.openclaw/config.yaml → ~/.Hermes/config.yaml (capital H — a directory that doesn't exist). Now case-preserving: "OpenClaw" → "Hermes" (prose), but "openclaw" → "hermes" (so filesystem paths land on the real Hermes home). Regex logic unchanged — replacement function now checks if the matched text was all-lowercase and emits the replacement in the matching case. 2. agent/onboarding.py + cli.py: one-time startup banner the first time Hermes launches and finds ~/.openclaw/. Tells the user to run `hermes claw cleanup` to archive it, gated on the existing onboarding seen-flag framework (onboarding.seen.openclaw_residue_cleanup in config.yaml). Fires once per install; re-running requires wiping that flag or running cleanup directly. Tests: - 4 new TestDetectOpenclawResidue tests (present / absent / file-instead- of-dir / default-home smoke) - 2 TestOpenclawResidueHint tests (content check) - 2 TestOpenclawResidueSeenFlag tests (flag isolation + round-trip) - test_rebrand_text_preserves_filesystem_path_casing regression test with 4 scenarios including the exact ~/.openclaw/config.yaml case - Existing test_rebrand_text_* tests updated to the new case-preserving contract (lowercase input → lowercase output) Co-authored-by: teknium1 <teknium@noreply.github.com>
This commit is contained in:
@@ -7,11 +7,14 @@ import pytest
|
||||
|
||||
from agent.onboarding import (
|
||||
BUSY_INPUT_FLAG,
|
||||
OPENCLAW_RESIDUE_FLAG,
|
||||
TOOL_PROGRESS_FLAG,
|
||||
busy_input_hint_cli,
|
||||
busy_input_hint_gateway,
|
||||
detect_openclaw_residue,
|
||||
is_seen,
|
||||
mark_seen,
|
||||
openclaw_residue_hint_cli,
|
||||
tool_progress_hint_cli,
|
||||
tool_progress_hint_gateway,
|
||||
)
|
||||
@@ -176,3 +179,50 @@ class TestRoundTrip:
|
||||
|
||||
assert is_seen(loaded, BUSY_INPUT_FLAG) is True
|
||||
assert is_seen(loaded, TOOL_PROGRESS_FLAG) is True
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# OpenClaw residue banner
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestDetectOpenclawResidue:
|
||||
def test_returns_true_when_openclaw_dir_present(self, tmp_path):
|
||||
(tmp_path / ".openclaw").mkdir()
|
||||
assert detect_openclaw_residue(home=tmp_path) is True
|
||||
|
||||
def test_returns_false_when_absent(self, tmp_path):
|
||||
assert detect_openclaw_residue(home=tmp_path) is False
|
||||
|
||||
def test_returns_false_when_path_is_a_file(self, tmp_path):
|
||||
# A stray file named ``.openclaw`` is NOT a workspace — skip the banner.
|
||||
(tmp_path / ".openclaw").write_text("oops")
|
||||
assert detect_openclaw_residue(home=tmp_path) is False
|
||||
|
||||
def test_default_home_does_not_crash(self):
|
||||
# Smoke: real $HOME lookup must not raise regardless of state.
|
||||
assert isinstance(detect_openclaw_residue(), bool)
|
||||
|
||||
|
||||
class TestOpenclawResidueHint:
|
||||
def test_hint_mentions_cleanup_command(self):
|
||||
msg = openclaw_residue_hint_cli()
|
||||
assert "hermes claw cleanup" in msg
|
||||
assert "~/.openclaw" in msg
|
||||
|
||||
def test_hint_not_empty(self):
|
||||
assert openclaw_residue_hint_cli().strip()
|
||||
|
||||
|
||||
class TestOpenclawResidueSeenFlag:
|
||||
def test_flag_independent_of_other_flags(self, tmp_path):
|
||||
cfg_path = tmp_path / "config.yaml"
|
||||
mark_seen(cfg_path, BUSY_INPUT_FLAG)
|
||||
loaded = yaml.safe_load(cfg_path.read_text())
|
||||
assert is_seen(loaded, OPENCLAW_RESIDUE_FLAG) is False
|
||||
|
||||
def test_flag_round_trips(self, tmp_path):
|
||||
cfg_path = tmp_path / "config.yaml"
|
||||
assert mark_seen(cfg_path, OPENCLAW_RESIDUE_FLAG) is True
|
||||
loaded = yaml.safe_load(cfg_path.read_text())
|
||||
assert is_seen(loaded, OPENCLAW_RESIDUE_FLAG) is True
|
||||
|
||||
Reference in New Issue
Block a user